This commit is contained in:
Joshua Sangmeister 2019-08-06 09:26:11 +02:00
parent 1bd93f0e98
commit 30c93f3990
11 changed files with 119 additions and 127 deletions

View File

@ -30,3 +30,4 @@ Authors of OpenSlides in chronological order of first contribution:
Jochen Saalfeld <jochen.saalfeld@intevation.de> Jochen Saalfeld <jochen.saalfeld@intevation.de>
Fadi Abbud <fmfn13@hotmail.com> Fadi Abbud <fmfn13@hotmail.com>
Gabriel Meyer <meyergabriel@live.de> Gabriel Meyer <meyergabriel@live.de>
Joshua Sangmeister <joshua.sangmeister@gmail.com>

View File

@ -1,9 +1,11 @@
<ng-container *osPerms="'agenda.can_manage'"> <ng-container *osPerms="'agenda.can_manage'">
<ng-container *ngIf="showForm"> <ng-container *ngIf="showForm">
<div [formGroup]="form"> <div [formGroup]="form">
<mat-checkbox formControlName="agenda_create"> <p>
<span translate>Add to agenda</span> <mat-checkbox formControlName="agenda_create">
</mat-checkbox> <span translate>Add to agenda</span>
</mat-checkbox>
</p>
</div> </div>
<ng-container *ngIf="!!checkbox.value"> <ng-container *ngIf="!!checkbox.value">

View File

@ -41,16 +41,14 @@
<span>{{ "New motion block" | translate }}</span> <span>{{ "New motion block" | translate }}</span>
</h1> </h1>
<form [formGroup]="createBlockForm" (keydown)="onKeyDown($event)"> <form [formGroup]="createBlockForm" (keydown)="onKeyDown($event)">
<div class="os-form-card-mobile" mat-dialog-content> <div mat-dialog-content>
<!-- Title --> <!-- Title -->
<p> <mat-form-field>
<mat-form-field> <input formControlName="title" matInput placeholder="{{ 'Title' | translate }}" required />
<input formControlName="title" matInput placeholder="{{ 'Title' | translate }}" required /> <mat-error *ngIf="createBlockForm.get('title').hasError('required')" translate>
<mat-error *ngIf="createBlockForm.get('title').hasError('required')" translate> A title is required
A title is required </mat-error>
</mat-error> </mat-form-field>
</mat-form-field>
</p>
<!-- Internal --> <!-- Internal -->
<p> <p>
@ -61,9 +59,9 @@
</div> </div>
</form> </form>
<div mat-dialog-actions> <div mat-dialog-actions>
<button mat-button [disabled]="!createBlockForm.valid" (click)="onSaveNewButton()"> <button mat-button [disabled]="!createBlockForm.valid" [mat-dialog-close]="true">
<span translate>Save</span> <span translate>Save</span>
</button> </button>
<button mat-button (click)="onCancel()"><span translate>Cancel</span></button> <button mat-button [mat-dialog-close]="false"><span translate>Cancel</span></button>
</div> </div>
</ng-template> </ng-template>

View File

@ -8,6 +8,12 @@
} }
} }
.mat-form-field { .mat-dialog-container {
width: 50%; .mat-dialog-title {
margin: 0;
}
.mat-form-field {
width: 100%;
}
} }

View File

@ -1,6 +1,6 @@
import { Component, OnInit, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material'; import { MatDialog } from '@angular/material';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -17,6 +17,7 @@ import { ViewItem } from 'app/site/agenda/models/view-item';
import { BaseListViewComponent } from 'app/site/base/base-list-view'; import { BaseListViewComponent } from 'app/site/base/base-list-view';
import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block'; import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block';
import { MotionBlockSortService } from 'app/site/motions/services/motion-block-sort.service'; import { MotionBlockSortService } from 'app/site/motions/services/motion-block-sort.service';
import { infoDialogSettings } from 'app/shared/utils/dialog-settings';
/** /**
* Table for the motion blocks * Table for the motion blocks
@ -31,8 +32,6 @@ export class MotionBlockListComponent extends BaseListViewComponent<ViewMotionBl
@ViewChild('newMotionBlockDialog', { static: true }) @ViewChild('newMotionBlockDialog', { static: true })
private newMotionBlockDialog: TemplateRef<string>; private newMotionBlockDialog: TemplateRef<string>;
private dialogRef: MatDialogRef<string, any>;
/** /**
* Holds the create form * Holds the create form
*/ */
@ -136,13 +135,9 @@ export class MotionBlockListComponent extends BaseListViewComponent<ViewMotionBl
/** /**
* Helper function reset the form and set the default values as well as closing the modal dialog * Helper function reset the form and set the default values as well as closing the modal dialog
*/ */
public resetForm(): void { private resetForm(): void {
this.createBlockForm.reset(); this.createBlockForm.reset();
this.createBlockForm.get('agenda_type').setValue(this.defaultVisibility); this.createBlockForm.get('agenda_type').setValue(this.defaultVisibility);
if (this.dialogRef) {
this.dialogRef.close();
}
this.dialogRef = null;
} }
/** /**
@ -151,19 +146,18 @@ export class MotionBlockListComponent extends BaseListViewComponent<ViewMotionBl
*/ */
public onPlusButton(): void { public onPlusButton(): void {
this.resetForm(); this.resetForm();
this.dialogRef = this.dialog.open(this.newMotionBlockDialog, { const dialogRef = this.dialog.open(this.newMotionBlockDialog, infoDialogSettings);
width: '400px', dialogRef.afterClosed().subscribe((res) => {
maxWidth: '90vw', if (res) {
maxHeight: '90vh', this.save();
disableClose: true }
}); })
} }
/** /**
* Click handler for the save button.
* Sends the block to create to the repository and resets the form. * Sends the block to create to the repository and resets the form.
*/ */
public async onSaveNewButton(): Promise<void> { private save(): void {
if (this.createBlockForm.valid) { if (this.createBlockForm.valid) {
const block = this.createBlockForm.value; const block = this.createBlockForm.value;
if (!block.agenda_parent_id) { if (!block.agenda_parent_id) {
@ -171,14 +165,12 @@ export class MotionBlockListComponent extends BaseListViewComponent<ViewMotionBl
} }
try { try {
await this.repo.create(block); this.repo.create(block);
this.resetForm(); this.resetForm();
} catch (e) { } catch (e) {
this.raiseError(e); this.raiseError(e);
} }
} }
// set a form control as "touched" to trigger potential error messages
this.createBlockForm.get('title').markAsTouched();
} }
/** /**
@ -189,17 +181,12 @@ export class MotionBlockListComponent extends BaseListViewComponent<ViewMotionBl
*/ */
public onKeyDown(event: KeyboardEvent): void { public onKeyDown(event: KeyboardEvent): void {
if (event.key === 'Enter' && event.shiftKey) { if (event.key === 'Enter' && event.shiftKey) {
this.onSaveNewButton(); this.save();
this.dialog.closeAll();
} }
if (event.key === 'Escape') { if (event.key === 'Escape') {
this.onCancel(); this.resetForm();
this.dialog.closeAll();
} }
} }
/**
* Cancels the current form action
*/
public onCancel(): void {
this.resetForm();
}
} }

View File

@ -112,10 +112,10 @@
</form> </form>
</div> </div>
<div mat-dialog-actions> <div mat-dialog-actions>
<button [disabled]="commentFieldForm.invalid" mat-button (click)="save()"> <button [disabled]="commentFieldForm.invalid" mat-button [mat-dialog-close]="true">
<span translate>Save</span> <span translate>Save</span>
</button> </button>
<button mat-button (click)="cancel()"> <button mat-button [mat-dialog-close]="false">
<span translate>Cancel</span> <span translate>Cancel</span>
</button> </button>
</div> </div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material'; import { MatDialog } from '@angular/material';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -14,6 +14,7 @@ import { MotionCommentSection } from 'app/shared/models/motions/motion-comment-s
import { BaseViewComponent } from 'app/site/base/base-view'; import { BaseViewComponent } from 'app/site/base/base-view';
import { ViewMotionCommentSection } from 'app/site/motions/models/view-motion-comment-section'; import { ViewMotionCommentSection } from 'app/site/motions/models/view-motion-comment-section';
import { ViewGroup } from 'app/site/users/models/view-group'; import { ViewGroup } from 'app/site/users/models/view-group';
import { infoDialogSettings } from 'app/shared/utils/dialog-settings';
/** /**
* List view for the comment sections. * List view for the comment sections.
@ -29,8 +30,6 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme
public currentComment: ViewMotionCommentSection | null; public currentComment: ViewMotionCommentSection | null;
public dialogRef: MatDialogRef<string, any>;
/** /**
* Source of the Data * Source of the Data
*/ */
@ -93,54 +92,47 @@ export class MotionCommentSectionListComponent extends BaseViewComponent impleme
public onKeyDown(event: KeyboardEvent, viewSection?: ViewMotionCommentSection): void { public onKeyDown(event: KeyboardEvent, viewSection?: ViewMotionCommentSection): void {
if (event.key === 'Enter' && event.shiftKey) { if (event.key === 'Enter' && event.shiftKey) {
this.save(); this.save();
this.dialog.closeAll();
} }
if (event.key === 'Escape') { if (event.key === 'Escape') {
this.cancel(); this.dialog.closeAll();
} }
} }
/** /**
* Opens the create dialog. * Opens the create dialog.
*/ */
public openDialog(c?: ViewMotionCommentSection): void { public openDialog(commentSection?: ViewMotionCommentSection): void {
this.currentComment = c; this.currentComment = commentSection;
this.commentFieldForm.reset({ this.commentFieldForm.reset({
name: c ? c.name : '', name: commentSection ? commentSection.name : '',
read_groups_id: c ? c.read_groups_id : [], read_groups_id: commentSection ? commentSection.read_groups_id : [],
write_groups_id: c ? c.write_groups_id : [] write_groups_id: commentSection ? commentSection.write_groups_id : []
}); });
this.dialogRef = this.dialog.open(this.motionCommentDialog, { const dialogRef = this.dialog.open(this.motionCommentDialog, infoDialogSettings);
width: '500px', dialogRef.afterClosed().subscribe((res) => {
maxWidth: '90vw', if (res) {
maxHeight: '90vh', this.save();
disableClose: true }
}); });
} }
/** /**
* saves the current data, either updating an existing comment or creating a new one. * saves the current data, either updating an existing comment or creating a new one.
*/ */
public save(): void { private save(): void {
if (this.commentFieldForm.valid) { if (this.commentFieldForm.valid) {
// eiher update or create // eiher update or create
if (this.currentComment) { if (this.currentComment) {
this.repo this.repo.update(this.commentFieldForm.value as Partial<MotionCommentSection>, this.currentComment).catch(this.raiseError);
.update(this.commentFieldForm.value as Partial<MotionCommentSection>, this.currentComment)
.then(() => this.dialogRef.close(), this.raiseError);
} else { } else {
const c = new MotionCommentSection(this.commentFieldForm.value); const c = new MotionCommentSection(this.commentFieldForm.value);
this.repo.create(c).then(() => this.dialogRef.close(), this.raiseError); this.repo.create(c).catch(this.raiseError);
} }
this.commentFieldForm.reset();
} }
} }
/**
* close the dialog
*/
public cancel(): void {
this.dialogRef.close();
}
/** /**
* is executed, when the delete button is pressed * is executed, when the delete button is pressed
* @param viewSection The section to delete * @param viewSection The section to delete

View File

@ -64,7 +64,7 @@
<!-- Template for statute paragraph dialog --> <!-- Template for statute paragraph dialog -->
<ng-template #statuteParagraphDialog> <ng-template #statuteParagraphDialog>
<h1 mat-dialog-title> <h1 mat-dialog-title>
<span>{{ (currentStatuteParagraph ? "Edit statute paragraph" : "New statute paragraph") | translate }}</span> <span>{{ ((currentStatuteParagraph ? "Edit" : "New") + "statute paragraph") | translate }}</span>
</h1> </h1>
<div class="os-form-card-mobile" mat-dialog-content> <div class="os-form-card-mobile" mat-dialog-content>
<form [formGroup]="statuteParagraphForm" (keydown)="onKeyDown($event)"> <form [formGroup]="statuteParagraphForm" (keydown)="onKeyDown($event)">
@ -84,10 +84,10 @@
</form> </form>
</div> </div>
<div mat-dialog-actions> <div mat-dialog-actions>
<button mat-button (click)="save()" [disabled]="!statuteParagraphForm.valid"> <button mat-button [mat-dialog-close]="true" [disabled]="!statuteParagraphForm.valid">
<span translate>Save</span> <span translate>Save</span>
</button> </button>
<button mat-button (click)="cancel()"> <button mat-button [mat-dialog-close]="false">
<span translate>Cancel</span> <span translate>Cancel</span>
</button> </button>
</div> </div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material'; import { MatDialog } from '@angular/material';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -12,6 +12,7 @@ import { StatuteParagraph } from 'app/shared/models/motions/statute-paragraph';
import { BaseViewComponent } from 'app/site/base/base-view'; import { BaseViewComponent } from 'app/site/base/base-view';
import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph'; import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph';
import { StatuteCsvExportService } from 'app/site/motions/services/statute-csv-export.service'; import { StatuteCsvExportService } from 'app/site/motions/services/statute-csv-export.service';
import { largeDialogSettings } from 'app/shared/utils/dialog-settings';
/** /**
* List view for the statute paragraphs. * List view for the statute paragraphs.
@ -25,8 +26,6 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements
@ViewChild('statuteParagraphDialog', { static: true }) @ViewChild('statuteParagraphDialog', { static: true })
private statuteParagraphDialog: TemplateRef<string>; private statuteParagraphDialog: TemplateRef<string>;
private dialogRef: MatDialogRef<string, any>;
private currentStatuteParagraph: ViewStatuteParagraph | null; private currentStatuteParagraph: ViewStatuteParagraph | null;
/** /**
@ -86,37 +85,36 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements
/** /**
* Open the modal dialog * Open the modal dialog
*/ */
public openDialog(p?: ViewStatuteParagraph): void { public openDialog(paragraph?: ViewStatuteParagraph): void {
this.currentStatuteParagraph = p; this.currentStatuteParagraph = paragraph;
this.statuteParagraphForm.reset(); this.statuteParagraphForm.reset();
if (p) { if (paragraph) {
this.statuteParagraphForm.setValue({ this.statuteParagraphForm.setValue({
title: p.title, title: paragraph.title,
text: p.text text: paragraph.text
}); });
} }
this.dialogRef = this.dialog.open(this.statuteParagraphDialog, { const dialogRef = this.dialog.open(this.statuteParagraphDialog, largeDialogSettings);
width: '1000px', dialogRef.afterClosed().subscribe((res) => {
maxWidth: '95vw', if (res) {
maxHeight: '90vh', this.save();
disableClose: true }
}); });
} }
/** /**
* creates a new statute paragraph or updates the current one * creates a new statute paragraph or updates the current one
*/ */
public save(): void { private save(): void {
if (this.statuteParagraphForm.valid) { if (this.statuteParagraphForm.valid) {
// eiher update or create // eiher update or create
if (this.currentStatuteParagraph) { if (this.currentStatuteParagraph) {
this.repo this.repo.update(this.statuteParagraphForm.value as Partial<StatuteParagraph>, this.currentStatuteParagraph).catch(this.raiseError);
.update(this.statuteParagraphForm.value as Partial<StatuteParagraph>, this.currentStatuteParagraph)
.then(() => this.dialogRef.close(), this.raiseError);
} else { } else {
const p = new StatuteParagraph(this.statuteParagraphForm.value); const p = new StatuteParagraph(this.statuteParagraphForm.value);
this.repo.create(p).then(() => this.dialogRef.close(), this.raiseError); this.repo.create(p).catch(this.raiseError);
} }
this.statuteParagraphForm.reset();
} }
} }
@ -148,19 +146,13 @@ export class StatuteParagraphListComponent extends BaseViewComponent implements
public onKeyDown(event: KeyboardEvent): void { public onKeyDown(event: KeyboardEvent): void {
if (event.key === 'Enter' && event.shiftKey) { if (event.key === 'Enter' && event.shiftKey) {
this.save(); this.save();
this.dialog.closeAll();
} }
if (event.key === 'Escape') { if (event.key === 'Escape') {
this.cancel(); this.dialog.closeAll();
} }
} }
/**
* Closes the dialog
*/
public cancel(): void {
this.dialogRef.close();
}
/** /**
* Triggers a csv export of the statute paragraphs * Triggers a csv export of the statute paragraphs
*/ */

View File

@ -39,20 +39,20 @@
<h1 mat-dialog-title> <h1 mat-dialog-title>
<span>{{ (currentTag ? 'Edit tag' : 'New tag') | translate }}</span> <span>{{ (currentTag ? 'Edit tag' : 'New tag') | translate }}</span>
</h1> </h1>
<form [formGroup]="tagForm" (ngSubmit)="onSubmit()"> <div class="os-form-card-mobile" mat-dialog-content>
<div class="os-form-card-mobile" mat-dialog-content> <form [formGroup]="tagForm" (keydown)="onKeyDown($event)">
<mat-form-field> <mat-form-field>
<input required type="text" matInput formControlName="name" placeholder="{{ 'Name' | translate }}"> <input required type="text" matInput formControlName="name" placeholder="{{ 'Name' | translate }}">
</mat-form-field> </mat-form-field>
</div> </form>
</div>
<div mat-dialog-actions> <div mat-dialog-actions>
<button type="submit" mat-button color="primary"> <button type="submit" mat-button [mat-dialog-close]="true" color="primary">
<span translate>Save</span> <span translate>Save</span>
</button> </button>
<button type="button" mat-button [mat-dialog-close]="null"> <button type="button" mat-button [mat-dialog-close]="false">
<span translate>Cancel</span> <span translate>Cancel</span>
</button> </button>
</div> </div>
</form>
</ng-template> </ng-template>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material'; import { MatDialog } from '@angular/material';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -12,6 +12,7 @@ import { PromptService } from 'app/core/ui-services/prompt.service';
import { Tag } from 'app/shared/models/core/tag'; import { Tag } from 'app/shared/models/core/tag';
import { BaseListViewComponent } from 'app/site/base/base-list-view'; import { BaseListViewComponent } from 'app/site/base/base-list-view';
import { ViewTag } from '../../models/view-tag'; import { ViewTag } from '../../models/view-tag';
import { infoDialogSettings } from 'app/shared/utils/dialog-settings';
/** /**
* Listview for the complete list of available Tags * Listview for the complete list of available Tags
@ -33,8 +34,6 @@ export class TagListComponent extends BaseListViewComponent<ViewTag> implements
name: ['', [Validators.required]] name: ['', [Validators.required]]
}); });
private dialogRef: MatDialogRef<string, any>;
/** /**
* Holds the tag that's currently being edited, or null. * Holds the tag that's currently being edited, or null.
*/ */
@ -94,28 +93,27 @@ export class TagListComponent extends BaseListViewComponent<ViewTag> implements
this.currentTag = tag; this.currentTag = tag;
this.tagForm.reset(); this.tagForm.reset();
this.tagForm.get('name').setValue(this.currentTag ? this.currentTag.name : ''); this.tagForm.get('name').setValue(this.currentTag ? this.currentTag.name : '');
this.dialogRef = this.dialog.open(this.tagDialog, { const dialogRef = this.dialog.open(this.tagDialog, infoDialogSettings);
width: '400px', dialogRef.afterClosed().subscribe((res) => {
maxWidth: '90vw', if (res) {
maxHeight: '90vh', this.save();
disableClose: true }
}); })
} }
/** /**
* Submit the form and create or update a tag. * Submit the form and create or update a tag.
*/ */
public onSubmit(): void { private save(): void {
if (!this.tagForm.value || !this.tagForm.valid) { if (!this.tagForm.value || !this.tagForm.valid) {
return; return;
} }
if (this.currentTag) { if (this.currentTag) {
this.repo this.repo.update(new Tag(this.tagForm.value), this.currentTag).catch(this.raiseError);
.update(new Tag(this.tagForm.value), this.currentTag)
.then(() => this.dialogRef.close(), this.raiseError);
} else { } else {
this.repo.create(this.tagForm.value).then(() => this.dialogRef.close(), this.raiseError); this.repo.create(this.tagForm.value).catch(this.raiseError);
} }
this.tagForm.reset(); // reset here so pressing shift+enter wont save when dialog isnt open
} }
/** /**
@ -128,4 +126,20 @@ export class TagListComponent extends BaseListViewComponent<ViewTag> implements
this.repo.delete(tag).catch(this.raiseError); this.repo.delete(tag).catch(this.raiseError);
} }
} }
/**
* clicking Shift and Enter will save automatically
* clicking Escape will cancel the process
*
* @param event has the code
*/
public onKeyDown(event: KeyboardEvent): void {
if (event.key === 'Enter' && event.shiftKey) {
this.save();
this.dialog.closeAll();
}
if (event.key === 'Escape') {
this.dialog.closeAll();
}
}
} }