Merge pull request #3970 from FinnStutzenstein/refineCategories
refine category editing and motion numbering. Fixes the current behav…
This commit is contained in:
commit
11a5335777
@ -39,7 +39,8 @@
|
|||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<mat-accordion class="os-card">
|
<mat-accordion class="os-card">
|
||||||
<mat-expansion-panel *ngFor="let category of this.categories" multiple="false">
|
<mat-expansion-panel *ngFor="let category of categories" (opened)="openId = category.id" (closed)="panelClosed(category)"
|
||||||
|
[expanded]="openId === category.id" multiple="false">
|
||||||
|
|
||||||
<!-- Header shows Prefix and name -->
|
<!-- Header shows Prefix and name -->
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
@ -50,7 +51,7 @@
|
|||||||
{{ category.prefix }}
|
{{ category.prefix }}
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="editId === category.id">
|
<div *ngIf="editId === category.id">
|
||||||
{{ this.updateForm.get('prefix').value }}
|
{{ updateForm.get('prefix').value }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-name">
|
<div class="header-name">
|
||||||
@ -58,7 +59,7 @@
|
|||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="editId === category.id">
|
<div *ngIf="editId === category.id">
|
||||||
{{ this.updateForm.get('name').value }}
|
{{ updateForm.get('name').value }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-size">
|
<div class="header-size">
|
||||||
@ -69,17 +70,17 @@
|
|||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
<!-- Edit form shows during the edit event -->
|
<!-- Edit form shows during the edit event -->
|
||||||
<form [formGroup]='this.updateForm' *ngIf="editId === category.id" (keydown)="keyDownFunction($event, category)">
|
<form id="updateForm" [formGroup]='updateForm' *ngIf="editId === category.id" (keydown)="keyDownFunction($event, category)">
|
||||||
<span translate>Edit category details:</span><br>
|
<span translate>Edit category details</span>:<br>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input formControlName="prefix" matInput placeholder="{{'Prefix' | translate}}">
|
<input formControlName="prefix" matInput placeholder="{{'Prefix' | translate}}" required>
|
||||||
<mat-hint>
|
<mat-hint *ngIf="!updateForm.controls.prefix.valid">
|
||||||
<span translate>Required</span>
|
<span translate>Required</span>
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input formControlName="name" matInput placeholder="{{'Name' | translate}}">
|
<input formControlName="name" matInput placeholder="{{'Name' | translate}}" required>
|
||||||
<mat-hint>
|
<mat-hint *ngIf="!updateForm.controls.name.valid">
|
||||||
<span translate>Required</span>
|
<span translate>Required</span>
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@ -87,10 +88,10 @@
|
|||||||
|
|
||||||
<!-- Show and sort corresponding motions-->
|
<!-- Show and sort corresponding motions-->
|
||||||
<div *ngIf="motionsInCategory(category).length > 0">
|
<div *ngIf="motionsInCategory(category).length > 0">
|
||||||
<span translate>Motions:</span>
|
<span translate>Motions</span>:
|
||||||
<div *ngIf="editId !== category.id">
|
<div *ngIf="editId !== category.id">
|
||||||
<ul *ngFor="let motion of motionsInCategory(category)">
|
<ul *ngFor="let motion of motionsInCategory(category)">
|
||||||
<li>{{motion}}</li>
|
<li>{{ motion }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="editId === category.id">
|
<div *ngIf="editId === category.id">
|
||||||
|
@ -40,3 +40,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#updateForm {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
@ -32,10 +32,15 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public editId: number | null;
|
public editId: number | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine which category is opened.
|
||||||
|
*/
|
||||||
|
public openId: number | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Source of the data
|
* Source of the data
|
||||||
*/
|
*/
|
||||||
public categories: Array<ViewCategory>;
|
public categories: ViewCategory[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For new categories
|
* For new categories
|
||||||
@ -146,31 +151,36 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the category
|
* Saves the category
|
||||||
|
*
|
||||||
|
* TODO: Do not number the motions. This needs to be a separate button (maybe with propting for confirmation), because
|
||||||
|
* not every body uses this and this would destroy their own order in motion identifiers.
|
||||||
|
* See issue #3969
|
||||||
|
*
|
||||||
* @param viewCategory
|
* @param viewCategory
|
||||||
*/
|
*/
|
||||||
public async onSaveButton(viewCategory: ViewCategory): Promise<void> {
|
public async onSaveButton(viewCategory: ViewCategory): Promise<void> {
|
||||||
if (this.updateForm.valid) {
|
// get the sorted motions. Save them before updating the category.
|
||||||
// TODO: Check the motion sorting code below. If it is removed, change to .then() syntax.
|
let sortedMotionIds;
|
||||||
try {
|
if (this.sortSelector) {
|
||||||
await this.repo.update(this.updateForm.value as Partial<Category>, viewCategory);
|
sortedMotionIds = this.sortSelector.array.map(selectable => selectable.id);
|
||||||
} catch (e) {
|
this.repo.numberMotionsInCategory(viewCategory.category, sortedMotionIds);
|
||||||
this.raiseError(e);
|
|
||||||
}
|
|
||||||
this.onCancelButton();
|
|
||||||
this.sortDataSource();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the sorted motions
|
if (this.updateForm.valid) {
|
||||||
if (this.sortSelector) {
|
// wait for the category to update; then the (maybe) changed prefix can be applied to the motions
|
||||||
const manuallySortedMotions = this.sortSelector.array as Motion[];
|
await this.repo.update(this.updateForm.value as Partial<Category>, viewCategory);
|
||||||
await this.repo.updateCategoryNumbering(viewCategory.category, manuallySortedMotions);
|
this.onCancelButton();
|
||||||
|
|
||||||
|
if (this.sortSelector) {
|
||||||
|
this.repo.numberMotionsInCategory(viewCategory.category, sortedMotionIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sorts the categories by prefix
|
* sorts the categories by prefix
|
||||||
*/
|
*/
|
||||||
protected sortDataSource(): void {
|
private sortDataSource(): void {
|
||||||
this.categories.sort((viewCategory1, viewCategory2) => (viewCategory1 > viewCategory2 ? 1 : -1));
|
this.categories.sort((viewCategory1, viewCategory2) => (viewCategory1 > viewCategory2 ? 1 : -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,10 +206,22 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* Returns the motions corresponding to a category
|
* Returns the motions corresponding to a category
|
||||||
* @param category target
|
* @param category target
|
||||||
|
* @returns all motions in the category
|
||||||
*/
|
*/
|
||||||
public motionsInCategory(category: Category): Array<Motion> {
|
public motionsInCategory(category: Category): Motion[] {
|
||||||
const motList = this.repo.getMotionsOfCategory(category);
|
const motions = this.repo.getMotionsOfCategory(category);
|
||||||
motList.sort((motion1, motion2) => (motion1 > motion2 ? 1 : -1));
|
motions.sort((motion1, motion2) => (motion1 > motion2 ? 1 : -1));
|
||||||
return motList;
|
return motions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is executed when a mat-extension-panel is closed
|
||||||
|
* @param viewCategory the category in the panel
|
||||||
|
*/
|
||||||
|
public panelClosed(viewCategory: ViewCategory): void {
|
||||||
|
this.openId = null;
|
||||||
|
if (this.editId) {
|
||||||
|
this.onSaveButton(viewCategory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,16 +323,9 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
* shows a "are you sure" dialog
|
* shows a "are you sure" dialog
|
||||||
*/
|
*/
|
||||||
public async deleteMotionButton(): Promise<void> {
|
public async deleteMotionButton(): Promise<void> {
|
||||||
await this.repo.delete(this.motion).then();
|
this.repo.delete(this.motion).then(() => {
|
||||||
this.router.navigate(['./motions/']);
|
this.router.navigate(['./motions/']);
|
||||||
|
}, this.raiseError);
|
||||||
// This should happen during auto update
|
|
||||||
// const motList = this.categoryRepo.getMotionsOfCategory(this.motion.category);
|
|
||||||
// const index = motList.indexOf(this.motion.motion, 0);
|
|
||||||
// if (index > -1) {
|
|
||||||
// motList.splice(index, 1);
|
|
||||||
// }
|
|
||||||
// this.categoryRepo.updateCategoryNumbering(this.motion.category, motList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
import { Motion } from '../../../shared/models/motions/motion';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* wrapper class for the HTTP Call
|
|
||||||
*/
|
|
||||||
export class CategoryNumbering {
|
|
||||||
private motions: number[];
|
|
||||||
|
|
||||||
public constructor() {}
|
|
||||||
|
|
||||||
public setMotions(motionList: Motion[]): void {
|
|
||||||
const motion_id_list: number[] = [];
|
|
||||||
motionList.forEach(motion => {
|
|
||||||
motion_id_list.push(motion.id);
|
|
||||||
});
|
|
||||||
this.motions = motion_id_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMotions(): number[] {
|
|
||||||
return this.motions;
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ import { DataSendService } from '../../../core/services/data-send.service';
|
|||||||
import { DataStoreService } from '../../../core/services/data-store.service';
|
import { DataStoreService } from '../../../core/services/data-store.service';
|
||||||
import { BaseRepository } from '../../base/base-repository';
|
import { BaseRepository } from '../../base/base-repository';
|
||||||
import { Motion } from '../../../shared/models/motions/motion';
|
import { Motion } from '../../../shared/models/motions/motion';
|
||||||
import { CategoryNumbering } from '../models/category-numbering';
|
|
||||||
import { HttpService } from '../../../core/services/http.service';
|
import { HttpService } from '../../../core/services/http.service';
|
||||||
import { Identifiable } from '../../../shared/models/base/identifiable';
|
import { Identifiable } from '../../../shared/models/base/identifiable';
|
||||||
import { CollectionStringModelMapperService } from '../../../core/services/collectionStringModelMapper.service';
|
import { CollectionStringModelMapperService } from '../../../core/services/collectionStringModelMapper.service';
|
||||||
@ -28,7 +27,9 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
* Creates a CategoryRepository
|
* Creates a CategoryRepository
|
||||||
* Converts existing and incoming category to ViewCategories
|
* Converts existing and incoming category to ViewCategories
|
||||||
* Handles CRUD using an observer to the DataStore
|
* Handles CRUD using an observer to the DataStore
|
||||||
* @param DataSend
|
* @param DS
|
||||||
|
* @param dataSend
|
||||||
|
* @param httpService
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
protected DS: DataStoreService,
|
protected DS: DataStoreService,
|
||||||
@ -64,10 +65,10 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all Motions belonging to a category
|
* Returns all motions belonging to a category
|
||||||
* @param category category
|
* @param category category
|
||||||
*/
|
*/
|
||||||
public getMotionsOfCategory(category: Category): Array<Motion> {
|
public getMotionsOfCategory(category: Category): Motion[] {
|
||||||
const motList = this.DS.getAll(Motion);
|
const motList = this.DS.getAll(Motion);
|
||||||
const retList: Array<Motion> = [];
|
const retList: Array<Motion> = [];
|
||||||
motList.forEach(motion => {
|
motList.forEach(motion => {
|
||||||
@ -89,23 +90,12 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a Categories numbering
|
* Updates a categories numbering.
|
||||||
* @param category the category it should be updated in
|
* @param category the category it should be updated in
|
||||||
* @param motionList the list of motions on this category
|
* @param motionList the list of motions on this category
|
||||||
*/
|
*/
|
||||||
public async updateCategoryNumbering(category: Category, motionList: Motion[]): Promise<void> {
|
public async numberMotionsInCategory(category: Category, motionIds: number[]): Promise<void> {
|
||||||
const categoryNumbering = new CategoryNumbering();
|
|
||||||
categoryNumbering.setMotions(motionList);
|
|
||||||
await this.sentCategoryNumbering(category, categoryNumbering);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save category in the server
|
|
||||||
*
|
|
||||||
* @return Observable from
|
|
||||||
*/
|
|
||||||
protected async sentCategoryNumbering(category: Category, categoryNumbering: CategoryNumbering): Promise<void> {
|
|
||||||
const collectionString = 'rest/motions/category/' + category.id + '/numbering/';
|
const collectionString = 'rest/motions/category/' + category.id + '/numbering/';
|
||||||
await this.httpService.post(collectionString, categoryNumbering);
|
await this.httpService.post(collectionString, { motions: motionIds });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user