diff --git a/AUTHORS b/AUTHORS index e438973a9..6147d3e87 100644 --- a/AUTHORS +++ b/AUTHORS @@ -30,3 +30,4 @@ Authors of OpenSlides in chronological order of first contribution: Jochen Saalfeld Fadi Abbud Gabriel Meyer + Joshua Sangmeister diff --git a/client/package.json b/client/package.json index 65a66e9c9..81a104ac2 100644 --- a/client/package.json +++ b/client/package.json @@ -24,7 +24,8 @@ "po2json-tempfix": "./node_modules/.bin/po2json -f mf src/assets/i18n/de.po /dev/stdout | sed -f sed_replacements > src/assets/i18n/de.json && ./node_modules/.bin/po2json -f mf src/assets/i18n/cs.po /dev/stdout | sed -f sed_replacements > src/assets/i18n/cs.json", "prettify-check": "prettier --config ./.prettierrc --list-different \"src/{app,environments}/**/*{.ts,.js,.json,.css,.scss}\"", "prettify-write": "prettier --config ./.prettierrc --write \"src/{app,environments}/**/*{.ts,.js,.json,.css,.scss}\"", - "cleanup": "npm run lint-write; npm run prettify-write" + "cleanup": "npm run lint-write; npm run prettify-write", + "cleanup-win": "npm run lint-write & npm run prettify-write" }, "dependencies": { "@angular/animations": "^8.0.3", @@ -90,7 +91,7 @@ "karma-jasmine-html-reporter": "^1.4.0", "npm-license-crawler": "^0.2.1", "npm-run-all": "^4.1.5", - "prettier": "^1.18.0", + "prettier": "^1.18.2", "protractor": "^5.4.2", "resize-observer-polyfill": "^1.5.1", "source-map-explorer": "^2.0.1", diff --git a/client/src/app/shared/components/agenda-content-object-form/agenda-content-object-form.component.html b/client/src/app/shared/components/agenda-content-object-form/agenda-content-object-form.component.html index 3cd2a2f02..bd59f1a30 100644 --- a/client/src/app/shared/components/agenda-content-object-form/agenda-content-object-form.component.html +++ b/client/src/app/shared/components/agenda-content-object-form/agenda-content-object-form.component.html @@ -1,9 +1,11 @@
- - Add to agenda - +

+ + Add to agenda + +

diff --git a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html index be4934842..1b9dddd0c 100644 --- a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html +++ b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html @@ -3,39 +3,6 @@

Motion blocks

- - - New motion block - -
- -

- - - - A title is required - - -

- - -

- Internal -

- - -
-
- - - - - - -
- + + + +

+ New motion block +

+
+
+ + + + + A title is required + + + + +

+ Internal +

+ + +
+
+
+ + +
+
diff --git a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.scss b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.scss index 7a60d3212..83f48c826 100644 --- a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.scss +++ b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.scss @@ -8,6 +8,12 @@ } } -.mat-form-field { - width: 50%; +.mat-dialog-container { + .mat-dialog-title { + margin: 0; + } + + .mat-form-field { + width: 100%; + } } diff --git a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts index 2d33f766a..f8a6d48e7 100644 --- a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts +++ b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, OnInit, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatDialog } from '@angular/material'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Title } from '@angular/platform-browser'; @@ -12,6 +13,7 @@ import { StorageService } from 'app/core/core-services/storage.service'; import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service'; import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service'; import { MotionBlock } from 'app/shared/models/motions/motion-block'; +import { infoDialogSettings } from 'app/shared/utils/dialog-settings'; import { ViewItem } from 'app/site/agenda/models/view-item'; import { BaseListViewComponent } from 'app/site/base/base-list-view'; import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block'; @@ -27,16 +29,14 @@ import { MotionBlockSortService } from 'app/site/motions/services/motion-block-s encapsulation: ViewEncapsulation.None }) export class MotionBlockListComponent extends BaseListViewComponent implements OnInit { + @ViewChild('newMotionBlockDialog', { static: true }) + private newMotionBlockDialog: TemplateRef; + /** * Holds the create form */ public createBlockForm: FormGroup; - /** - * Flag, if the creation panel is open - */ - public isCreatingNewBlock = false; - /** * Holds the agenda items to select the parent item */ @@ -95,6 +95,7 @@ export class MotionBlockListComponent extends BaseListViewComponent { + if (res) { + this.save(); + } + }); } /** - * Click handler for the save button. * Sends the block to create to the repository and resets the form. */ - public async onSaveNewButton(): Promise { + private save(): void { if (this.createBlockForm.valid) { const block = this.createBlockForm.value; if (!block.agenda_parent_id) { delete block.agenda_parent_id; } - - try { - await this.repo.create(block); - this.resetForm(); - this.isCreatingNewBlock = false; - } catch (e) { - this.raiseError(e); - } + this.repo.create(block).catch(this.raiseError); + this.resetForm(); } - // set a form control as "touched" to trigger potential error messages - this.createBlockForm.get('title').markAsTouched(); } /** @@ -175,17 +171,12 @@ export class MotionBlockListComponent extends BaseListViewComponent +

Comment fields

@@ -13,53 +13,9 @@
- - New comment field - -
-

- - - - Required - - -

-

- -

-

- -

-
-
- - - - -
@@ -87,59 +43,22 @@
-
- Edit comment field: -

- - - - Required - - -

-

- -

-

- -

-
- -

Name

-
{{ section.name }}
-

Groups with read permissions

-
    -
  • {{ group.getTitle() }}
  • -
-
No groups selected
-

Groups with write permissions

-
    -
  • {{ group.getTitle() }}
  • -
-
No groups selected
-
+

Name

+
{{ section.name }}
+

Groups with read permissions

+
    +
  • {{ group.getTitle() }}
  • +
+
No groups selected
+

Groups with write permissions

+
    +
  • {{ group.getTitle() }}
  • +
+
No groups selected
- - - @@ -153,3 +72,49 @@ Sort + + + +

+ Edit comment field + New comment field +

+
+
+

+ + + + Required + + +

+

+ +

+

+ +

+
+
+
+ + +
+
diff --git a/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.ts b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.ts index 9be7b7a3c..410569703 100644 --- a/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.ts +++ b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatDialog } from '@angular/material'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Title } from '@angular/platform-browser'; @@ -10,6 +11,7 @@ import { MotionCommentSectionRepositoryService } from 'app/core/repositories/mot import { GroupRepositoryService } from 'app/core/repositories/users/group-repository.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { MotionCommentSection } from 'app/shared/models/motions/motion-comment-section'; +import { infoDialogSettings } from 'app/shared/utils/dialog-settings'; import { BaseViewComponent } from 'app/site/base/base-view'; import { ViewMotionCommentSection } from 'app/site/motions/models/view-motion-comment-section'; import { ViewGroup } from 'app/site/users/models/view-group'; @@ -23,7 +25,10 @@ import { ViewGroup } from 'app/site/users/models/view-group'; styleUrls: ['./motion-comment-section-list.component.scss'] }) export class MotionCommentSectionListComponent extends BaseViewComponent implements OnInit { - public commentSectionToCreate: MotionCommentSection | null; + @ViewChild('motionCommentDialog', { static: true }) + private motionCommentDialog: TemplateRef; + + public currentComment: ViewMotionCommentSection | null; /** * Source of the Data @@ -31,14 +36,9 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme public commentSections: ViewMotionCommentSection[] = []; /** - * The current focussed formgroup + * formgroup for editing and creating of comments */ - public updateForm: FormGroup; - - public createForm: FormGroup; - - public openId: number | null; - public editId: number | null; + public commentFieldForm: FormGroup; public groups: BehaviorSubject; @@ -59,6 +59,7 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme private repo: MotionCommentSectionRepositoryService, private formBuilder: FormBuilder, private promptService: PromptService, + private dialog: MatDialog, private groupRepo: GroupRepositoryService ) { super(titleService, translate, matSnackBar); @@ -68,8 +69,7 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme read_groups_id: [[]], write_groups_id: [[]] }; - this.createForm = this.formBuilder.group(form); - this.updateForm = this.formBuilder.group(form); + this.commentFieldForm = this.formBuilder.group(form); } /** @@ -82,78 +82,54 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme } /** - * Event on Key Down in update or create form. + * Event on Key Down in form. * * @param event the keyboard event * @param the current view in scope */ - public keyDownFunction(event: KeyboardEvent, viewSection?: ViewMotionCommentSection): void { + public onKeyDown(event: KeyboardEvent, viewSection?: ViewMotionCommentSection): void { if (event.key === 'Enter' && event.shiftKey) { - if (viewSection) { - this.onSaveButton(viewSection); - } else { - this.create(); - } + this.save(); + this.dialog.closeAll(); } if (event.key === 'Escape') { - if (viewSection) { - this.editId = null; - } else { - this.commentSectionToCreate = null; + this.dialog.closeAll(); + } + } + + /** + * Opens the create dialog. + */ + public openDialog(commentSection?: ViewMotionCommentSection): void { + this.currentComment = commentSection; + this.commentFieldForm.reset({ + name: commentSection ? commentSection.name : '', + read_groups_id: commentSection ? commentSection.read_groups_id : [], + write_groups_id: commentSection ? commentSection.write_groups_id : [] + }); + const dialogRef = this.dialog.open(this.motionCommentDialog, infoDialogSettings); + dialogRef.afterClosed().subscribe(res => { + if (res) { + this.save(); } - } - } - - /** - * Opens the create form. - */ - public onPlusButton(): void { - if (!this.commentSectionToCreate) { - this.commentSectionToCreate = new MotionCommentSection(); - this.createForm.setValue({ - name: '', - read_groups_id: [], - write_groups_id: [] - }); - } - } - - /** - * Creates the comment section from the create form. - */ - public create(): void { - if (this.createForm.valid) { - this.commentSectionToCreate.patchValues(this.createForm.value as MotionCommentSection); - this.repo - .create(this.commentSectionToCreate) - .then(() => (this.commentSectionToCreate = null), this.raiseError); - } - } - - /** - * Executed on edit button - * @param viewSection - */ - public onEditButton(viewSection: ViewMotionCommentSection): void { - this.editId = viewSection.id; - - this.updateForm.setValue({ - name: viewSection.name, - read_groups_id: viewSection.read_groups_id, - write_groups_id: viewSection.write_groups_id }); } /** - * Saves the comment section - * - * @param viewSection The section to save + * saves the current data, either updating an existing comment or creating a new one. */ - public onSaveButton(viewSection: ViewMotionCommentSection): void { - if (this.updateForm.valid) { - this.repo.update(this.updateForm.value as Partial, viewSection).then(() => { - this.openId = this.editId = null; - }, this.raiseError); + private save(): void { + if (this.commentFieldForm.valid) { + // eiher update or create + if (this.currentComment) { + this.repo + .update(this.commentFieldForm.value as Partial, this.currentComment) + .catch(this.raiseError); + } else { + const comment = new MotionCommentSection(this.commentFieldForm.value); + this.repo.create(comment).catch(this.raiseError); + } + this.commentFieldForm.reset(); } } @@ -165,18 +141,7 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme const title = this.translate.instant('Are you sure you want to delete this comment field?'); const content = viewSection.name; if (await this.promptService.open(title, content)) { - this.repo.delete(viewSection).then(() => (this.openId = this.editId = null), this.raiseError); - } - } - - /** - * Is executed when a mat-extension-panel is closed - * @param viewSection the section in the panel - */ - public panelClosed(viewSection: ViewMotionCommentSection): void { - this.openId = null; - if (this.editId) { - this.onSaveButton(viewSection); + this.repo.delete(viewSection).catch(this.raiseError); } } } diff --git a/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.html b/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.html index bdbbcf1e1..14fa29e07 100644 --- a/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.html +++ b/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.html @@ -1,4 +1,4 @@ - +

Statute

@@ -12,42 +12,10 @@
- - New statute paragraph - -
-

- - - - Required - - -

- - -

Statute paragraph

- -
-
-
- - - - -
- - + @@ -55,51 +23,17 @@ {{ statuteParagraph.title }} -
- Edit statute paragraph: -

- - - - Required - - -

- - -

Statute paragraph

- -
-
- - - {{ statuteParagraph.title }} - -
-
-
-
+ + {{ statuteParagraph.title }} + +
+
+
- - - - @@ -123,3 +57,36 @@ Import ... + + + +

+ Edit statute paragraph + New statute paragraph +

+
+
+

+ + + + Required + + +

+ + +

Statute paragraph

+ +
+
+
+
+ + +
+
diff --git a/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.ts b/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.ts index 8463f4d40..f9af28da3 100644 --- a/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.ts +++ b/client/src/app/site/motions/modules/statute-paragraph/components/statute-paragraph-list/statute-paragraph-list.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatDialog } from '@angular/material'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Title } from '@angular/platform-browser'; @@ -8,6 +9,7 @@ import { TranslateService } from '@ngx-translate/core'; import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions/statute-paragraph-repository.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { StatuteParagraph } from 'app/shared/models/motions/statute-paragraph'; +import { largeDialogSettings } from 'app/shared/utils/dialog-settings'; import { BaseViewComponent } from 'app/site/base/base-view'; import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph'; import { StatuteCsvExportService } from 'app/site/motions/services/statute-csv-export.service'; @@ -21,7 +23,10 @@ import { StatuteCsvExportService } from 'app/site/motions/services/statute-csv-e styleUrls: ['./statute-paragraph-list.component.scss'] }) export class StatuteParagraphListComponent extends BaseViewComponent implements OnInit { - public statuteParagraphToCreate: StatuteParagraph | null; + @ViewChild('statuteParagraphDialog', { static: true }) + private statuteParagraphDialog: TemplateRef; + + private currentStatuteParagraph: ViewStatuteParagraph | null; /** * Source of the Data @@ -29,14 +34,9 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements public statuteParagraphs: ViewStatuteParagraph[] = []; /** - * The current focussed formgroup + * Formgroup for creating and updating of statute paragraphs */ - public updateForm: FormGroup; - - public createForm: FormGroup; - - public openId: number | null; - public editId: number | null; + public statuteParagraphForm: FormGroup; /** * The usual component constructor. Initializes the forms @@ -56,6 +56,7 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements private repo: StatuteParagraphRepositoryService, private formBuilder: FormBuilder, private promptService: PromptService, + private dialog: MatDialog, private csvExportService: StatuteCsvExportService ) { super(titleService, translate, matSnackBar); @@ -64,8 +65,7 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements title: ['', Validators.required], text: ['', Validators.required] }; - this.createForm = this.formBuilder.group(form); - this.updateForm = this.formBuilder.group(form); + this.statuteParagraphForm = this.formBuilder.group(form); } /** @@ -81,53 +81,40 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements } /** - * Add a new Section. + * Open the modal dialog */ - public onPlusButton(): void { - if (!this.statuteParagraphToCreate) { - this.createForm.reset(); - this.createForm.setValue({ - title: '', - text: '' + public openDialog(paragraph?: ViewStatuteParagraph): void { + this.currentStatuteParagraph = paragraph; + this.statuteParagraphForm.reset(); + if (paragraph) { + this.statuteParagraphForm.setValue({ + title: paragraph.title, + text: paragraph.text }); - this.statuteParagraphToCreate = new StatuteParagraph(); } - } - - /** - * Handler when clicking on create to create a new statute paragraph - */ - public create(): void { - if (this.createForm.valid) { - this.statuteParagraphToCreate.patchValues(this.createForm.value as StatuteParagraph); - this.repo.create(this.statuteParagraphToCreate).then(() => { - this.statuteParagraphToCreate = null; - }, this.raiseError); - } - } - - /** - * Executed on edit button - * @param viewStatuteParagraph - */ - public onEditButton(viewStatuteParagraph: ViewStatuteParagraph): void { - this.editId = viewStatuteParagraph.id; - - this.updateForm.setValue({ - title: viewStatuteParagraph.title, - text: viewStatuteParagraph.text + const dialogRef = this.dialog.open(this.statuteParagraphDialog, largeDialogSettings); + dialogRef.afterClosed().subscribe(res => { + if (res) { + this.save(); + } }); } /** - * Saves the statute paragraph - * @param viewStatuteParagraph The statute paragraph to save + * creates a new statute paragraph or updates the current one */ - public onSaveButton(viewStatuteParagraph: ViewStatuteParagraph): void { - if (this.updateForm.valid) { - this.repo.update(this.updateForm.value as Partial, viewStatuteParagraph).then(() => { - this.openId = this.editId = null; - }, this.raiseError); + private save(): void { + if (this.statuteParagraphForm.valid) { + // eiher update or create + if (this.currentStatuteParagraph) { + this.repo + .update(this.statuteParagraphForm.value as Partial, this.currentStatuteParagraph) + .catch(this.raiseError); + } else { + const paragraph = new StatuteParagraph(this.statuteParagraphForm.value); + this.repo.create(paragraph).catch(this.raiseError); + } + this.statuteParagraphForm.reset(); } } @@ -139,18 +126,7 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements const title = this.translate.instant('Are you sure you want to delete this statute paragraph?'); const content = viewStatuteParagraph.title; if (await this.promptService.open(title, content)) { - this.repo.delete(viewStatuteParagraph).then(() => (this.openId = this.editId = null), this.raiseError); - } - } - - /** - * Is executed when a mat-extension-panel is closed - * @param viewStatuteParagraph the statute paragraph in the panel - */ - public panelClosed(viewStatuteParagraph: ViewStatuteParagraph): void { - this.openId = null; - if (this.editId) { - this.onSaveButton(viewStatuteParagraph); + this.repo.delete(viewStatuteParagraph).catch(this.raiseError); } } @@ -167,45 +143,16 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements * * @param event has the code */ - public onKeyDownCreate(event: KeyboardEvent): void { + public onKeyDown(event: KeyboardEvent): void { if (event.key === 'Enter' && event.shiftKey) { - this.create(); + this.save(); + this.dialog.closeAll(); } if (event.key === 'Escape') { - this.onCancelCreate(); + this.dialog.closeAll(); } } - /** - * Cancels the current form action - */ - public onCancelCreate(): void { - this.statuteParagraphToCreate = null; - } - - /** - * clicking Shift and Enter will save automatically - * clicking Escape will cancel the process - * - * @param event has the code - */ - public onKeyDownUpdate(event: KeyboardEvent): void { - if (event.key === 'Enter' && event.shiftKey) { - const myParagraph = this.statuteParagraphs.find(x => x.id === this.editId); - this.onSaveButton(myParagraph); - } - if (event.key === 'Escape') { - this.onCancelUpdate(); - } - } - - /** - * Cancels the current form action - */ - public onCancelUpdate(): void { - this.editId = null; - } - /** * Triggers a csv export of the statute paragraphs */ diff --git a/client/src/app/site/tags/components/tag-list/tag-list.component.html b/client/src/app/site/tags/components/tag-list/tag-list.component.html index 8154989d7..740d706ed 100644 --- a/client/src/app/site/tags/components/tag-list/tag-list.component.html +++ b/client/src/app/site/tags/components/tag-list/tag-list.component.html @@ -1,37 +1,10 @@ - -
-

Tags

-
- - - Required - -
-
- - -
- -
+

Tags

-
+
{{ name }}
+ +
+ +
+ +
+ +
+ + + +

+ Edit tag + New tag +

+
+
+ + + +
+
+ +
+ + +
+
diff --git a/client/src/app/site/tags/components/tag-list/tag-list.component.ts b/client/src/app/site/tags/components/tag-list/tag-list.component.ts index ae424b516..38da6f29a 100644 --- a/client/src/app/site/tags/components/tag-list/tag-list.component.ts +++ b/client/src/app/site/tags/components/tag-list/tag-list.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; -import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatDialog } from '@angular/material'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Title } from '@angular/platform-browser'; @@ -9,11 +10,12 @@ import { PblColumnDefinition } from '@pebula/ngrid'; import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service'; import { PromptService } from 'app/core/ui-services/prompt.service'; import { Tag } from 'app/shared/models/core/tag'; +import { infoDialogSettings } from 'app/shared/utils/dialog-settings'; import { BaseListViewComponent } from 'app/site/base/base-list-view'; import { ViewTag } from '../../models/view-tag'; /** - * Listview for the complete lsit of available Tags + * Listview for the complete list of available Tags * ### Usage: * ```html * @@ -25,12 +27,17 @@ import { ViewTag } from '../../models/view-tag'; styleUrls: ['./tag-list.component.scss'] }) export class TagListComponent extends BaseListViewComponent implements OnInit { - public editTag = false; - public newTag = false; - public selectedTag: ViewTag; + @ViewChild('tagDialog', { static: true }) + private tagDialog: TemplateRef; - @ViewChild('tagForm', { static: true }) - public tagForm: FormGroup; + private tagForm: FormGroup = this.formBuilder.group({ + name: ['', [Validators.required]] + }); + + /** + * Holds the tag that's currently being edited, or null. + */ + public currentTag: ViewTag; /** * Define the columns to show @@ -39,6 +46,14 @@ export class TagListComponent extends BaseListViewComponent implements { prop: 'name', width: 'auto' + }, + { + prop: 'edit', + width: this.singleButtonWidth + }, + { + prop: 'delete', + width: this.singleButtonWidth } ]; @@ -55,7 +70,9 @@ export class TagListComponent extends BaseListViewComponent implements matSnackBar: MatSnackBar, public repo: TagRepositoryService, protected translate: TranslateService, // protected required for ng-translate-extract - private promptService: PromptService + private promptService: PromptService, + private dialog: MatDialog, + private formBuilder: FormBuilder ) { super(titleService, translate, matSnackBar); } @@ -66,93 +83,63 @@ export class TagListComponent extends BaseListViewComponent implements */ public ngOnInit(): void { super.setTitle('Tags'); - this.tagForm = new FormGroup({ name: new FormControl('', Validators.required) }); } /** - * Sends a new or updates tag to the dataStore + * sets the given tag as the current and opens the tag dialog. + * @param tag the current tag, or null if a new tag is to be created */ - public saveTag(): void { - if (this.editTag && this.newTag) { - this.submitNewTag(); - } else if (this.editTag && !this.newTag) { - this.submitEditedTag(); - } - } - - /** - * Saves a newly created tag. - */ - public submitNewTag(): void { - if (!this.tagForm.value || !this.tagForm.valid) { - return; - } - this.repo.create(this.tagForm.value).then(() => { - this.tagForm.reset(); - this.cancelEditing(); - }, this.raiseError); - } - - /** - * Saves an edited tag. - */ - public submitEditedTag(): void { - if (!this.tagForm.value || !this.tagForm.valid) { - return; - } - const updateData = new Tag({ name: this.tagForm.value.name }); - - this.repo.update(updateData, this.selectedTag).then(() => this.cancelEditing(), this.raiseError); - } - - /** - * Deletes the selected Tag after a successful confirmation. - */ - public async deleteSelectedTag(): Promise { - const title = this.translate.instant('Are you sure you want to delete this tag?'); - const content = this.selectedTag.name; - if (await this.promptService.open(title, content)) { - this.repo.delete(this.selectedTag).then(() => this.cancelEditing(), this.raiseError); - } - } - - /** - * Cancels the editing - */ - public cancelEditing(): void { - this.newTag = false; - this.editTag = false; + public openTagDialog(tag?: ViewTag): void { + this.currentTag = tag; this.tagForm.reset(); + this.tagForm.get('name').setValue(this.currentTag ? this.currentTag.name : ''); + const dialogRef = this.dialog.open(this.tagDialog, infoDialogSettings); + dialogRef.afterClosed().subscribe(res => { + if (res) { + this.save(); + } + }); } /** - * Handler for a click on a row in the table - * @param viewTag + * Submit the form and create or update a tag. */ - public selectTag(viewTag: ViewTag): void { - this.selectedTag = viewTag; - this.setEditMode(true, false); - this.tagForm.setValue({ name: this.selectedTag.name }); + private save(): void { + if (!this.tagForm.value || !this.tagForm.valid) { + return; + } + if (this.currentTag) { + this.repo.update(new Tag(this.tagForm.value), this.currentTag).catch(this.raiseError); + } else { + this.repo.create(this.tagForm.value).catch(this.raiseError); + } + this.tagForm.reset(); // reset here so pressing shift+enter wont save when dialog isnt open } - public setEditMode(mode: boolean, newTag: boolean = true): void { - this.editTag = mode; - this.newTag = newTag; - if (!mode) { - this.cancelEditing(); + /** + * Deletes the given Tag after a successful confirmation. + */ + public async onDeleteButton(tag: ViewTag): Promise { + const title = this.translate.instant('Are you sure you want to delete this tag?'); + const content = tag.name; + if (await this.promptService.open(title, content)) { + this.repo.delete(tag).catch(this.raiseError); } } /** - * Handles keyboard events. On enter, the editing is canceled. - * @param event + * clicking Shift and Enter will save automatically + * clicking Escape will cancel the process + * + * @param event has the code */ - public keyDownFunction(event: KeyboardEvent): void { + public onKeyDown(event: KeyboardEvent): void { if (event.key === 'Enter' && event.shiftKey) { - this.submitNewTag(); + this.save(); + this.dialog.closeAll(); } if (event.key === 'Escape') { - this.cancelEditing(); + this.dialog.closeAll(); } } }