From cb1247ba333c33c8711eab254232e12c149c2af2 Mon Sep 17 00:00:00 2001 From: Stefanie S Date: Fri, 12 Jun 2020 22:01:46 +0200 Subject: [PATCH] feat(#22): show error message and prevent creation on faulty file names --- src/app/app.module.ts | 2 - .../tagDialog/tagDialog.component.html | 2 +- .../createNewItemDialog.component.html | 28 ++++++++------ .../createNewItemDialog.component.scss | 7 +++- .../createNewItemDialog.component.ts | 25 ++++++++++--- .../checkForNameSafety.directive.spec.ts | 17 --------- .../checkForNameSafety.directive.ts | 37 ------------------- src/app/directives/nameSafetyValidator.ts | 21 +++++++++++ src/assets/i18n/de.json | 4 +- src/assets/i18n/en.json | 4 +- 10 files changed, 70 insertions(+), 77 deletions(-) delete mode 100644 src/app/directives/checkForNameSafety.directive.spec.ts delete mode 100644 src/app/directives/checkForNameSafety.directive.ts create mode 100644 src/app/directives/nameSafetyValidator.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0ad494ab..2c2137da 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -23,7 +23,6 @@ import { CreateNewLabelComponent } from './components/_labels/createNewLabel/cre import { LabelTreeComponent } from './components/_labels/labelTree/labelTree.component'; import { DocumentTreeComponent } from './components/_documents/documentTree/documentTree.component'; import { UpsertNoteComponent } from './components/_notes/upsertNote/upsertNote.component'; -import { CheckForNameSafetyDirective } from './directives/checkForNameSafety.directive'; import { TagDialogComponent } from './components/_snapshots/tagDialog/tagDialog.component'; import { LastModifiedComponent } from './components/lastModified/lastModified.component'; import { CreateNewItemDialogComponent } from './components/createNewItemDialog/createNewItemDialog.component'; @@ -111,7 +110,6 @@ const matModules = [ TagDialogComponent, LastModifiedComponent, UpsertNoteComponent, - CheckForNameSafetyDirective, DocumentTreeComponent, LabelTreeComponent, CreateNewLabelComponent, diff --git a/src/app/components/_snapshots/tagDialog/tagDialog.component.html b/src/app/components/_snapshots/tagDialog/tagDialog.component.html index ac17bb2b..27200ab1 100644 --- a/src/app/components/_snapshots/tagDialog/tagDialog.component.html +++ b/src/app/components/_snapshots/tagDialog/tagDialog.component.html @@ -12,7 +12,7 @@

{{ t('title') }}

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

{{ t('input') }} - + BOOOOH! diff --git a/src/app/components/createNewItemDialog/createNewItemDialog.component.html b/src/app/components/createNewItemDialog/createNewItemDialog.component.html index b70b7395..d6cf452a 100644 --- a/src/app/components/createNewItemDialog/createNewItemDialog.component.html +++ b/src/app/components/createNewItemDialog/createNewItemDialog.component.html @@ -8,15 +8,21 @@

{{ t('title') }}

-
-

{{ t('message') }}

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

{{ t('message') }}

+ + {{ t('input') }} + + + {{ '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 c9ae728b..8d89d8e2 100644 --- a/src/app/components/createNewItemDialog/createNewItemDialog.component.scss +++ b/src/app/components/createNewItemDialog/createNewItemDialog.component.scss @@ -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/. @@ -12,3 +12,8 @@ input { .message { padding: 1em 0; } + +mat-error { + margin-top: -1.8em; + font-size: 10px; +} diff --git a/src/app/components/createNewItemDialog/createNewItemDialog.component.ts b/src/app/components/createNewItemDialog/createNewItemDialog.component.ts index ab7e3e4e..77418b4c 100644 --- a/src/app/components/createNewItemDialog/createNewItemDialog.component.ts +++ b/src/app/components/createNewItemDialog/createNewItemDialog.component.ts @@ -1,19 +1,30 @@ // 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/. import { Component, OnInit, Inject } from '@angular/core'; 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'; @Component({ selector: 'wy-createNewFileDialog', templateUrl: './createNewItemDialog.component.html', styleUrls: ['./createNewItemDialog.component.scss'], + animations: [slideInDownOnEnterAnimation()], }) export class CreateNewItemDialogComponent implements OnInit { typeOfDialog = ''; + form; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + private formBuilder: FormBuilder + ) {} ngOnInit() { switch (this.data.typeOfDialog) { @@ -30,15 +41,17 @@ export class CreateNewItemDialogComponent implements OnInit { this.typeOfDialog = 'createUnkownDialog'; break; } - } - constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data) {} + this.form = this.formBuilder.group({ + name: new FormControl('', [NameSafetyValidator()]), + }); + } cancel(): void { - this.dialogRef.close(); + this.dialogRef.close(null); } - submit() { - this.dialogRef.close(this.data.filename); + submit(values) { + this.dialogRef.close(values.name); } } diff --git a/src/app/directives/checkForNameSafety.directive.spec.ts b/src/app/directives/checkForNameSafety.directive.spec.ts deleted file mode 100644 index 7e36df31..00000000 --- a/src/app/directives/checkForNameSafety.directive.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -// 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/. - -/* tslint:disable:no-unused-variable */ - -import { TestBed, async } from '@angular/core/testing'; -import { CheckForNameSafetyDirective } from './checkForNameSafety.directive'; - -describe('Directive: CheckForNameSafety', () => { - it('should create an instance', () => { - const directive = new CheckForNameSafetyDirective(); - expect(directive).toBeTruthy(); - }); -}); diff --git a/src/app/directives/checkForNameSafety.directive.ts b/src/app/directives/checkForNameSafety.directive.ts deleted file mode 100644 index 6352ad03..00000000 --- a/src/app/directives/checkForNameSafety.directive.ts +++ /dev/null @@ -1,37 +0,0 @@ -// 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/. - -import { Directive, Input } from '@angular/core'; -import { NG_VALIDATORS, Validator, AbstractControl, ValidatorFn } from '@angular/forms'; - -@Directive({ - selector: '[wyCheckForNameSafety]', - providers: [{ provide: NG_VALIDATORS, useExisting: CheckForNameSafetyDirective, multi: true }], -}) -export class CheckForNameSafetyDirective implements Validator { - // FIXME: I AM BROKEN - - @Input('wyCheckForNameSafety') typeOfName: 'tag' | 'explorer'; - - private forbiddenCharatersRe = { - explorer: /([/\\<>\*\?:\'"])*/, - tag: /([\s\.~\^:\?\*\[@\\])*/, - }; - - constructor() {} - - validate(control: AbstractControl): { [key: string]: any } | null { - const regex = this.forbiddenCharatersRe[this.typeOfName]; - return regex ? this.nameValidator(regex)(control) : null; - } - - nameValidator(regex): ValidatorFn { - return (control: AbstractControl): { [key: string]: any } | null => { - const forbidden = regex.test(control.value); - return forbidden ? { forbiddenName: { value: control.value } } : null; - }; - } -} diff --git a/src/app/directives/nameSafetyValidator.ts b/src/app/directives/nameSafetyValidator.ts new file mode 100644 index 00000000..55f358a3 --- /dev/null +++ b/src/app/directives/nameSafetyValidator.ts @@ -0,0 +1,21 @@ +// 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/. + +import { AbstractControl, ValidatorFn } from '@angular/forms'; + +export function NameSafetyValidator(typeToCheck = 'explorer') { + const nameValidator = (control: AbstractControl): { [key: string]: boolean } | null => { + const forbidden = regex.test(control.value); + return forbidden ? { forbiddenName: true } : null; + }; + + const forbiddenCharatersRe = { + explorer: /([/\\<>\*\?:\'"])+/, + tag: /([\s\.~\^:\?\*\[@\\])+/, + }; + const regex = forbiddenCharatersRe[typeToCheck]; + return regex ? nameValidator : null; +} diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 9272c03e..7801fb41 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -97,7 +97,9 @@ "lastSnapshotted": "Letzte Sicherung vom" }, "createDirOrFile": { - "alreadyInUse": "Dieser Name ist bereits vergeben. Bitte wähle einen anderen." + "alreadyInUse": "Dieser Name ist bereits vergeben. Bitte wähle einen anderen.", + "forbiddenName": "Folgende Zeichen dürfen nicht verwendet werden: < > : / \\ * ? \" | ", + "required": "Bitte gib einen Namen ein." }, "createFileDialog": { "title": "Neues Dokument erstellen", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index c38b8fb4..8ed0a2ff 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -97,7 +97,9 @@ "lastSnapshotted": "Last snapshotted on" }, "createDirOrFile": { - "alreadyInUse": "This name is already in use. Please choose a different one." + "alreadyInUse": "This name is already in use. Please choose a different one.", + "forbiddenName": "The following characters cannot be used: < > : / \\ * ? \" | ", + "required": "Please input a name" }, "createFileDialog": { "title": "Create new document",