diff --git a/src/app/components/_documents/createNewDirOrFile/createNewDirOrFile.component.ts b/src/app/components/_documents/createNewDirOrFile/createNewDirOrFile.component.ts index 2ca61670..3e3f38bf 100644 --- a/src/app/components/_documents/createNewDirOrFile/createNewDirOrFile.component.ts +++ b/src/app/components/_documents/createNewDirOrFile/createNewDirOrFile.component.ts @@ -1,5 +1,5 @@ // Copyright (c) 2020 s-blu -// +// // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -47,6 +47,7 @@ export class CreateNewDirOrFileComponent implements OnInit, OnDestroy { createNewItem() { const dialogRef = this.dialog.open(CreateNewItemDialogComponent, { data: { dirPath: this.path, typeOfDialog: this.type }, + minWidth: 500, }); zip(dialogRef.afterClosed(), this.directoryStore.tree$) .pipe( @@ -61,7 +62,6 @@ export class CreateNewDirOrFileComponent implements OnInit, OnDestroy { return this.stripFileEndingPipe.transform(file.name).toLowerCase() === name.toLowerCase(); }); if (!existing) createObservable = this.documentService.createDocument(this.path, name); - } else if (this.type === 'dir') { const existing = containingDir.dirs.find(dir => dir.name.toLowerCase() === name.toLowerCase()); if (!existing) createObservable = this.directoryService.createDirectory(this.path, name); diff --git a/src/app/components/_snapshots/tagDialog/tagDialog.component.html b/src/app/components/_snapshots/tagDialog/tagDialog.component.html index 27200ab1..83a7c909 100644 --- a/src/app/components/_snapshots/tagDialog/tagDialog.component.html +++ b/src/app/components/_snapshots/tagDialog/tagDialog.component.html @@ -8,16 +8,24 @@

{{ t('title') }}

-
-

{{ t('message', { date: data.lastSnapshotDate }) }}

- - {{ t('input') }} - - BOOOOH! - -
-
- - -
+
+
+

{{ t('message', { date: data.lastSnapshotDate }) }}

+ + {{ t('input') }} + + {{ t('forbiddenName') }} + +
+
+ + +
+
diff --git a/src/app/components/_snapshots/tagDialog/tagDialog.component.scss b/src/app/components/_snapshots/tagDialog/tagDialog.component.scss index dca964d5..ded40317 100644 --- a/src/app/components/_snapshots/tagDialog/tagDialog.component.scss +++ b/src/app/components/_snapshots/tagDialog/tagDialog.component.scss @@ -1,6 +1,10 @@ // Copyright (c) 2020 s-blu -// +// // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +.mat-form-field, +input { + width: 100%; +} diff --git a/src/app/components/_snapshots/tagDialog/tagDialog.component.ts b/src/app/components/_snapshots/tagDialog/tagDialog.component.ts index 1882506c..671e7722 100644 --- a/src/app/components/_snapshots/tagDialog/tagDialog.component.ts +++ b/src/app/components/_snapshots/tagDialog/tagDialog.component.ts @@ -1,3 +1,4 @@ +import { OnChangeErrorMatcher } from './../../../utils/form.utils'; // Copyright (c) 2020 s-blu // // This Source Code Form is subject to the terms of the Mozilla Public @@ -6,6 +7,8 @@ import { Component, OnInit, Inject } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { FormBuilder, FormControl } from '@angular/forms'; +import { NameSafetyValidator } from 'src/app/directives/nameSafetyValidator'; @Component({ selector: 'wy-tagDialog', @@ -13,17 +16,24 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; styleUrls: ['./tagDialog.component.scss'], }) export class TagDialogComponent implements OnInit { - constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data) {} - ngOnInit() {} + form; + matcher = new OnChangeErrorMatcher(); + + constructor(private formBuilder: FormBuilder, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data) {} - isTagNameValid() { - console.log('isTagNameValid', this.data.tagName); - if (!this.data.tagName || this.data.tagName === '') return true; - return this.data.tagName.match(/(0-9A-Za-z:\/)/); + ngOnInit() { + this.form = this.formBuilder.group({ + name: new FormControl('', [NameSafetyValidator('tag')]), + }); } cancel(): void { this.dialogRef.close(); } + + submit(values) { + if (this.form.invalid) return; + this.dialogRef.close(values.name); + } } diff --git a/src/app/components/createNewItemDialog/createNewItemDialog.component.html b/src/app/components/createNewItemDialog/createNewItemDialog.component.html index d6cf452a..cbc89e38 100644 --- a/src/app/components/createNewItemDialog/createNewItemDialog.component.html +++ b/src/app/components/createNewItemDialog/createNewItemDialog.component.html @@ -13,12 +13,12 @@

{{ t('title') }}

{{ t('message') }}

{{ t('input') }} - + + {{ 'createDirOrFile.forbiddenName' | transloco }} + + {{ 'createDirOrFile.required' | transloco }} - {{ 'createDirOrFile.forbiddenName' | transloco }} - - {{ 'createDirOrFile.required' | transloco }}
diff --git a/src/app/components/createNewItemDialog/createNewItemDialog.component.scss b/src/app/components/createNewItemDialog/createNewItemDialog.component.scss index 8d89d8e2..def340cf 100644 --- a/src/app/components/createNewItemDialog/createNewItemDialog.component.scss +++ b/src/app/components/createNewItemDialog/createNewItemDialog.component.scss @@ -11,9 +11,4 @@ input { .message { padding: 1em 0; -} - -mat-error { - margin-top: -1.8em; - font-size: 10px; -} +} \ No newline at end of file diff --git a/src/app/components/createNewItemDialog/createNewItemDialog.component.ts b/src/app/components/createNewItemDialog/createNewItemDialog.component.ts index 77418b4c..f7e717d3 100644 --- a/src/app/components/createNewItemDialog/createNewItemDialog.component.ts +++ b/src/app/components/createNewItemDialog/createNewItemDialog.component.ts @@ -9,6 +9,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { FormControl, FormBuilder } from '@angular/forms'; import { NameSafetyValidator } from 'src/app/directives/nameSafetyValidator'; import { slideInDownAnimation, slideInDownOnEnterAnimation } from 'angular-animations'; +import { OnChangeErrorMatcher } from 'src/app/utils/form.utils'; @Component({ selector: 'wy-createNewFileDialog', @@ -19,6 +20,7 @@ import { slideInDownAnimation, slideInDownOnEnterAnimation } from 'angular-anima export class CreateNewItemDialogComponent implements OnInit { typeOfDialog = ''; form; + matcher = new OnChangeErrorMatcher(); constructor( public dialogRef: MatDialogRef, @@ -52,6 +54,7 @@ export class CreateNewItemDialogComponent implements OnInit { } submit(values) { + if (this.form.invalid) return; this.dialogRef.close(values.name); } } diff --git a/src/app/directives/nameSafetyValidator.ts b/src/app/directives/nameSafetyValidator.ts index 55f358a3..7b348146 100644 --- a/src/app/directives/nameSafetyValidator.ts +++ b/src/app/directives/nameSafetyValidator.ts @@ -7,7 +7,7 @@ import { AbstractControl, ValidatorFn } from '@angular/forms'; export function NameSafetyValidator(typeToCheck = 'explorer') { - const nameValidator = (control: AbstractControl): { [key: string]: boolean } | null => { + const nameValidator: ValidatorFn = (control: AbstractControl): { [key: string]: boolean } | null => { const forbidden = regex.test(control.value); return forbidden ? { forbiddenName: true } : null; }; diff --git a/src/app/utils/form.utils.ts b/src/app/utils/form.utils.ts new file mode 100644 index 00000000..58bc1504 --- /dev/null +++ b/src/app/utils/form.utils.ts @@ -0,0 +1,10 @@ +import { ErrorStateMatcher } from '@angular/material/core'; +import { FormControl, FormGroupDirective, NgForm } from '@angular/forms'; + +// From https://material.angular.io/components/input/overview#changing-when-error-messages-are-shown +export class OnChangeErrorMatcher implements ErrorStateMatcher { + isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const isSubmitted = form && form.submitted; + return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted)); + } +} \ No newline at end of file diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 7801fb41..1d7806a4 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -204,10 +204,11 @@ }, "tagDialog": { "title": "Einen Tag erstellen", - "message": "Erstelle einen Tag, um deine letzte Sicherung von {{date}} zu markieren und jederzeit wiederzufinden. Bitte keine Leerzeichen verwenden.", + "message": "Erstelle einen Tag, um deine letzte Sicherung von {{date}} zu markieren und jederzeit wiederzufinden.", "input": "Tagname", "cancel": "Abbrechen", - "create": "Erstellen" + "create": "Erstellen", + "forbiddenName": "Folgende Zeichen dürfen nicht verwendet werden: Leerzeichen ~.^:?*[]@\\" }, "git": { "message": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 8ed0a2ff..2f2d2c9d 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -207,7 +207,8 @@ "message": "Create a tag to mark your latest snapshot from {{date}}", "input": "name of tag", "cancel": "Cancel", - "create": "Create" + "create": "Create", + "forbiddenName": "The following characters cannot be used: Spaces ~.^:?*[]@\\" }, "git": { "message": {