Merge pull request #4263 from MaximilianKrambach/categoryView

rework category list and sorting
This commit is contained in:
Emanuel Schütze 2019-02-12 21:57:09 +01:00 committed by GitHub
commit 4f75639780
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 367 additions and 187 deletions

View File

@ -11,7 +11,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 { HttpService } from '../../core-services/http.service'; import { HttpService } from '../../core-services/http.service';
import { Identifiable } from 'app/shared/models/base/identifiable'; import { Identifiable } from 'app/shared/models/base/identifiable';
import { Motion } from 'app/shared/models/motions/motion';
import { ViewCategory } from 'app/site/motions/models/view-category'; import { ViewCategory } from 'app/site/motions/models/view-category';
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
@ -81,22 +80,6 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
await this.dataSend.deleteModel(category); await this.dataSend.deleteModel(category);
} }
/**
* Returns all motions belonging to a category
* @param category category
*/
public getMotionsOfCategory(category: Category): Motion[] {
const motList = this.DS.getAll(Motion);
const retList: Array<Motion> = [];
motList.forEach(motion => {
if (motion.category_id && motion.category_id === category.id) {
retList.push(motion);
}
});
// TODO: Sorting the return List?!
return retList;
}
/** /**
* Returns the category for the ID * Returns the category for the ID
* @param category_id category ID * @param category_id category ID

View File

@ -1,12 +1,15 @@
<div cdkDropList class="list" (cdkDropListDropped)="drop($event)"> <div cdkDropList class="os-card" (cdkDropListDropped)="drop($event)">
<div class= "box line" *ngIf="!array.length">
<span translate>No data</span>
</div>
<div class="box line" *ngFor="let item of array; let i = index" cdkDrag> <div class="box line" *ngFor="let item of array; let i = index" cdkDrag>
<div class="section-one" cdkDragHandle> <div class="section-one" cdkDragHandle>
<mat-icon>drag_indicator</mat-icon> <mat-icon>drag_indicator</mat-icon>
</div> </div>
<div class="section-two"> <div class="section-two">
<!-- {number}. {item.toString()} --> <!-- {number}. {item.getTitle()} -->
<span *ngIf="count">{{ i+1 }}.&nbsp;</span> <span *ngIf="count">{{ i + 1 }}.&nbsp;</span>
<span>{{ item }}</span> <span>{{ item.getTitle() }}</span>
</div> </div>
<div class="section-three"> <div class="section-three">
<!-- Extra controls slot using implicit template references --> <!-- Extra controls slot using implicit template references -->

View File

@ -1,9 +1,3 @@
.list {
width: 100%;
display: block;
overflow: hidden;
}
.box { .box {
width: 100%; width: 100%;
border-bottom: solid 1px #ccc; border-bottom: solid 1px #ccc;

View File

@ -5,7 +5,6 @@ import { TranslateService } from '@ngx-translate/core';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { Selectable } from '../selectable'; import { Selectable } from '../selectable';
import { EmptySelectable } from '../empty-selectable';
/** /**
* Reusable Sorting List * Reusable Sorting List
@ -133,8 +132,8 @@ export class SortingListComponent implements OnInit, OnDestroy {
if (this.array.length !== newValues.length || this.live) { if (this.array.length !== newValues.length || this.live) {
this.array = []; this.array = [];
this.array = newValues.map(val => val); this.array = newValues.map(val => val);
} else if (this.array.length === 0) { } else {
this.array.push(new EmptySelectable(this.translate)); this.array = this.array.map(arrayValue => newValues.find(val => val.id === arrayValue.id));
} }
} }

View File

@ -4,27 +4,28 @@
<h2 translate>Categories</h2> <h2 translate>Categories</h2>
</div> </div>
</os-head-bar> </os-head-bar>
<div class="custom-table-header"></div>
<!-- Creating a new category --> <div class="spacer-top-20"></div>
<mat-card *ngIf="categoryToCreate"> <mat-card class="os-card" *ngIf="categoryToCreate">
<mat-card-title translate>Create new category</mat-card-title> <mat-card-title translate>Create new category</mat-card-title>
<mat-card-content> <mat-card-content>
<form [formGroup]="createForm" (keydown)="keyDownFunction($event)"> <form
<p> class="full-width-form flex-spaced"
<!-- Prefix field --> id="createForm"
<mat-form-field> [formGroup]="createForm"
<input formControlName="prefix" matInput placeholder="{{'Prefix' | translate}}"> (keydown)="keyDownFunction($event)"
</mat-form-field> >
<!-- prefix input -->
<!-- Name field --> <mat-form-field class="short-input">
<mat-form-field> <input formControlName="prefix" matInput placeholder="{{ 'Prefix' | translate }}" />
<input formControlName="name" matInput placeholder="{{'Name' | translate}}" required> </mat-form-field>
<mat-hint *ngIf="!createForm.controls.name.valid"> <!-- name input -->
<span translate>Required</span> <mat-form-field class="long-input">
</mat-hint> <input formControlName="name" matInput placeholder="{{ 'Name' | translate }}" required />
</mat-form-field> <mat-hint *ngIf="!updateForm.controls.name.valid">
</p> <span translate>Required</span>
</mat-hint>
</mat-form-field>
</form> </form>
</mat-card-content> </mat-card-content>
@ -39,80 +40,94 @@
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>
<mat-accordion class="os-form-card"> <mat-card class="os-card">
<mat-expansion-panel *ngFor="let category of categories" (opened)="openId = category.id" (closed)="panelClosed(category)" <mat-accordion displayMode="flat">
[expanded]="openId === category.id" multiple="false"> <ng-container *ngFor="let category of categories">
<mat-expansion-panel
class="os-card-expandion-panel"
(opened)="setValues(category)"
[expanded]="editId === category.id"
(closed)="onCancelButton()"
>
<!-- Header shows Prefix and name -->
<mat-expansion-panel-header>
<mat-panel-title>
<div class="header-container">
<div class="header-name">
<div>
{{ category.prefixedName }}
</div>
</div>
<div class="header-size os-amount-chip">
{{ motionsInCategory(category).length }}
</div>
</div>
</mat-panel-title>
</mat-expansion-panel-header>
<!-- Header shows Prefix and name --> <!-- Edit form shows during the edit event -->
<mat-expansion-panel-header> <div class="full-width-form">
<mat-panel-title> <form
<div class="header-container"> class="full-width-form"
<div class="header-prefix"> id="updateForm"
<div *ngIf="editId !== category.id"> [formGroup]="updateForm"
{{ category.prefix }} *ngIf="editId === category.id"
(keydown)="keyDownFunction($event, category)"
>
<div class="flex-spaced">
<mat-form-field class="short-input">
<input formControlName="prefix" matInput placeholder="{{ 'Prefix' | translate }}" />
</mat-form-field>
<mat-form-field class="long-input">
<input
formControlName="name"
matInput
placeholder="{{ 'Name' | translate }}"
required
/>
<mat-hint *ngIf="!updateForm.controls.name.valid">
<span translate>Required</span>
</mat-hint>
</mat-form-field>
</div> </div>
<div *ngIf="editId === category.id"> <div class="inline-form-submit" *osPerms="'motions.can_manage'">
{{ updateForm.get('prefix').value }} <button
[disabled]="!updateForm.dirty"
mat-button
class="on-transition-fade"
(click)="onSaveButton(category)"
>
<span translate>Save</span>
</button>
<button
type="button"
mat-button
class="on-transition-fade"
[routerLink]="getSortUrl(category)"
>
<span translate>Sort motions</span>
</button>
<button
type="button"
mat-button
class="on-transition-fade"
(click)="onDeleteButton(category)"
>
<span translate>Delete</span>
</button>
</div> </div>
</div> </form>
<div class="header-name"> </div>
<div *ngIf="editId !== category.id"> <!-- Show and sort corresponding motions-->
{{ category.name }} <div *ngIf="motionsInCategory(category).length > 0">
</div> <span translate>Motions</span>:
<div *ngIf="editId === category.id"> <div>
{{ updateForm.get('name').value }} <ul *ngFor="let motion of motionsInCategory(category)">
</div> <li class="ellipsis-overflow">{{ motion.getListTitle() }}</li>
</div> </ul>
<div class="header-size os-amount-chip">
{{ motionsInCategory(category).length }}
</div> </div>
</div> </div>
</mat-panel-title> </mat-expansion-panel>
</mat-expansion-panel-header> </ng-container>
</mat-accordion>
<!-- Edit form shows during the edit event --> </mat-card>
<form id="updateForm" [formGroup]='updateForm' *ngIf="editId === category.id" (keydown)="keyDownFunction($event, category)">
<span translate>Edit category</span>:<br>
<mat-form-field>
<input formControlName="prefix" matInput placeholder="{{'Prefix' | translate}}">
</mat-form-field>
<mat-form-field>
<input formControlName="name" matInput placeholder="{{'Name' | translate}}" required>
<mat-hint *ngIf="!updateForm.controls.name.valid">
<span translate>Required</span>
</mat-hint>
</mat-form-field>
</form>
<!-- Show and sort corresponding motions-->
<div *ngIf="motionsInCategory(category).length > 0">
<span translate>Motions</span>:
<div *ngIf="editId !== category.id">
<ul *ngFor="let motion of motionsInCategory(category)">
<li>{{ motion }}</li>
</ul>
</div>
<div *ngIf="editId === category.id" class="half-width">
<os-sorting-list [input]="motionsInCategory(category)" #sorter></os-sorting-list>
</div>
</div>
<!-- Buttons to edit, delete, save ... -->
<mat-action-row>
<button mat-icon-button *ngIf="editId !== category.id" class='on-transition-fade' (click)=onEditButton(category)>
<mat-icon>edit</mat-icon>
</button>
<button mat-icon-button *ngIf="editId === category.id" class='on-transition-fade' (click)=onCancelButton()>
<mat-icon>close</mat-icon>
</button>
<button mat-icon-button *ngIf="editId === category.id" class='on-transition-fade' (click)=onSaveButton(category)>
<mat-icon>save</mat-icon>
</button>
<button mat-icon-button mat-button class='on-transition-fade' (click)=onDeleteButton(category)>
<mat-icon>delete</mat-icon>
</button>
</mat-action-row>
</mat-expansion-panel>
</mat-accordion>

View File

@ -1,33 +1,50 @@
.header-container { .header-container {
display: grid; display: grid;
grid-template-rows: auto; grid-template-rows: auto;
grid-template-columns: 33.333% 33.333% 33.333%; grid-template-columns: 75% 25%;
width: 100%; width: 100%;
> div { > div {
grid-row-start: 1; grid-row-start: 1;
grid-row-end: span 1; grid-row-end: span 1;
grid-column-end: span 3; grid-column-end: span 2;
}
.header-prefix {
grid-column-start: 1;
} }
.header-name { .header-name {
grid-column-start: 2; grid-column-start: 1;
color: lightslategray; color: lightslategray;
} }
.header-size { .header-size {
grid-column-start: 3; grid-column-start: 2;
} }
} }
#updateForm { mat-expansion-panel {
margin-bottom: 20px; max-width: 770px;
margin: auto;
} }
.half-width { .flex-spaced {
width: 50%; display: flex;
justify-content: space-between;
}
.full-width-form {
display: flex;
width: 100%;
align-content: space-between;
flex: 2;
}
.short-input {
width: 20%;
}
.long-input {
width: 75%;
}
.inline-form-submit {
justify-content: end;
display: block;
flex: 1;
} }

View File

@ -1,17 +1,17 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { BaseViewComponent } from '../../../base/base-view';
import { Category } from 'app/shared/models/motions/category'; import { Category } from 'app/shared/models/motions/category';
import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service'; import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service';
import { ViewCategory } from '../../models/view-category'; import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Motion } from 'app/shared/models/motions/motion';
import { SortingListComponent } from 'app/shared/components/sorting-list/sorting-list.component';
import { PromptService } from 'app/core/ui-services/prompt.service'; import { PromptService } from 'app/core/ui-services/prompt.service';
import { BaseViewComponent } from '../../../base/base-view'; import { ViewCategory } from '../../models/view-category';
import { MatSnackBar } from '@angular/material'; import { ViewMotion } from '../../models/view-motion';
/** /**
* List view for the categories. * List view for the categories.
@ -28,15 +28,10 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
public categoryToCreate: Category | null; public categoryToCreate: Category | null;
/** /**
* Determine which category to edit * Determine which category is opened
*/ */
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
*/ */
@ -52,12 +47,6 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
*/ */
public updateForm: FormGroup; public updateForm: FormGroup;
/**
* The MultiSelect Component
*/
@ViewChild('sorter')
public sortSelector: SortingListComponent;
/** /**
* The usual component constructor * The usual component constructor
* @param titleService * @param titleService
@ -72,6 +61,7 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
translate: TranslateService, translate: TranslateService,
matSnackBar: MatSnackBar, matSnackBar: MatSnackBar,
private repo: CategoryRepositoryService, private repo: CategoryRepositoryService,
private motionRepo: MotionRepositoryService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private promptService: PromptService private promptService: PromptService
) { ) {
@ -89,7 +79,8 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
} }
/** /**
* Event on key-down in form * Event on key-down in form. Submits the current form if the 'enter' button is pressed
*
* @param event * @param event
* @param viewCategory * @param viewCategory
*/ */
@ -154,47 +145,33 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
} }
/** /**
* Saves the category * Saves a category
* * TODO: Some feedback
* 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> {
// get the sorted motions. Save them before updating the category. if (this.updateForm.dirty && this.updateForm.valid) {
let sortedMotionIds;
if (this.sortSelector) {
sortedMotionIds = this.sortSelector.array.map(selectable => selectable.id);
this.repo.numberMotionsInCategory(viewCategory.category, sortedMotionIds);
}
if (this.updateForm.valid) {
const cat: Partial<Category> = { name: this.updateForm.get('name').value }; const cat: Partial<Category> = { name: this.updateForm.get('name').value };
if (this.updateForm.get('prefix').value) { if (this.updateForm.get('prefix').value) {
cat.prefix = this.updateForm.get('prefix').value; cat.prefix = this.updateForm.get('prefix').value;
} }
// wait for the category to update; then the (maybe) changed prefix can be applied to the motions
await this.repo.update(cat, viewCategory); await this.repo.update(cat, viewCategory);
this.onCancelButton(); this.updateForm.markAsPristine();
if (this.sortSelector) {
this.repo.numberMotionsInCategory(viewCategory.category, sortedMotionIds);
}
} }
} }
/** /**
* executed on cancel button * Trigger after cancelling an edit. The updateForm is reset to an original
* @param viewCategory * value, which might belong to a different category
*/ */
public onCancelButton(): void { public onCancelButton(): void {
this.editId = null; this.updateForm.markAsPristine();
} }
/** /**
* is executed, when the delete button is pressed * is executed, when the delete button is pressed
*
* @param viewCategory The category to delete * @param viewCategory The category to delete
*/ */
public async onDeleteButton(viewCategory: ViewCategory): Promise<void> { public async onDeleteButton(viewCategory: ViewCategory): Promise<void> {
@ -206,23 +183,36 @@ 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 * @returns all motions in the category
*/ */
public motionsInCategory(category: Category): Motion[] { public motionsInCategory(category: Category): ViewMotion[] {
const motions = this.repo.getMotionsOfCategory(category); return this.motionRepo
motions.sort((motion1, motion2) => (motion1 > motion2 ? 1 : -1)); .getViewModelList()
return motions; .filter(m => m.category_id === category.id)
.sort((motion1, motion2) => motion1.identifier.localeCompare(motion2.identifier));
} }
/** /**
* Is executed when a mat-extension-panel is closed * Fetch the correct URL for a detail sort view
* @param viewCategory the category in the panel *
* @param viewCategory
*/ */
public panelClosed(viewCategory: ViewCategory): void { public getSortUrl(viewCategory: ViewCategory): string {
this.openId = null; return `/motions/category/${viewCategory.id}`;
if (this.editId) { }
this.onSaveButton(viewCategory);
} /**
* Set/reset the initial values and the referenced category of the update form
*
* @param category
*/
public setValues(category: ViewCategory): void {
this.editId = category.id;
this.updateForm.setValue({
prefix: category.prefix,
name: category.name
});
} }
} }

View File

@ -0,0 +1,24 @@
<!-- TODO permission -->
<os-head-bar [nav]="false">
<!-- Title -->
<div class="title-slot"><h2 translate>Sort motions</h2></div>
</os-head-bar>
<mat-card class="os-form-card">
<h3>{{ categoryName }}</h3>
<br />
<span translate>
Drag and drop motions to reorder the category. Then click the button to renumber.
</span>
<br />
<button
mat-raised-button
color="primary"
(click)="onNumberMotions()"
class="spacer-top-10"
[disabled]="!motionsCount"
>
<span translate>Number motions</span>
</button>
<os-sorting-list [input]="motionObservable" #sorter></os-sorting-list>
</mat-card>

View File

@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CategorySortComponent } from './category-sort.component';
import { E2EImportsModule } from 'e2e-imports.module';
describe('CategorySortComponent', () => {
let component: CategorySortComponent;
let fixture: ComponentFixture<CategorySortComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [E2EImportsModule],
declarations: [CategorySortComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CategorySortComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,119 @@
import { ActivatedRoute } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { BaseViewComponent } from 'app/site/base/base-view';
import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service';
import { MatSnackBar } from '@angular/material';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { PromptService } from 'app/core/ui-services/prompt.service';
import { SortingListComponent } from 'app/shared/components/sorting-list/sorting-list.component';
import { ViewCategory } from '../../models/view-category';
import { ViewMotion } from '../../models/view-motion';
/**
* View for rearranging and renumbering the motions of a category. The {@link onNumberMotions}
* method sends a request to the server to re-number the given motions in the order
* as displayed in this view
*/
@Component({
selector: 'os-category-sort',
templateUrl: './category-sort.component.html',
styleUrls: ['./category-sort.component.scss']
})
export class CategorySortComponent extends BaseViewComponent implements OnInit {
/**
* The current category. Determined by the route
*/
public category: ViewCategory;
/**
* A behaviorSubject emitting the currently asigned motions on change
*/
public motionsSubject = new BehaviorSubject<ViewMotion[]>([]);
/**
* Counter indicating the amount of motions currently in the category
*/
public motionsCount = 0;
/**
* @returns an observable for the {@link motionsSubject}
*/
public get motionObservable(): Observable<ViewMotion[]> {
return this.motionsSubject.asObservable();
}
/**
* @returns the name and (if present) prefix of the category
*/
public get categoryName(): string {
if (!this.category) {
return '';
}
return this.category.prefix ? `${this.category.name} (${this.category.prefix})` : this.category.name;
}
/**
* The Sort Component
*/
@ViewChild('sorter')
public sortSelector: SortingListComponent;
/**
* Constructor. Calls parents
*
* @param title
* @param translate
* @param matSnackBar
* @param promptService
* @param repo
* @param route
* @param motionRepo
*/
public constructor(
title: Title,
translate: TranslateService,
matSnackBar: MatSnackBar,
private promptService: PromptService,
private repo: CategoryRepositoryService,
private route: ActivatedRoute,
private motionRepo: MotionRepositoryService
) {
super(title, translate, matSnackBar);
}
/**
* Subscribes to the category and motions of this category.
*/
public ngOnInit(): void {
const category_id: number = +this.route.snapshot.params.id;
this.repo.getViewModelObservable(category_id).subscribe(cat => {
this.category = cat;
});
this.motionRepo.getViewModelListObservable().subscribe(motions => {
const filtered = motions.filter(m => m.category_id === category_id);
this.motionsCount = filtered.length;
this.motionsSubject.next(filtered);
});
}
/**
* Triggers a (re-)numbering of the motions after a configmarion dialog
*
* @param category
*/
public async onNumberMotions(): Promise<void> {
if (this.sortSelector) {
const content = this.translate.instant('This will change the identifier for the motions of this category.');
if (await this.promptService.open('Are you sure?', content)) {
const sortedMotionIds = this.sortSelector.array.map(selectable => selectable.id);
await this.repo
.numberMotionsInCategory(this.category.category, sortedMotionIds)
.then(null, this.raiseError);
}
}
}
}

View File

@ -74,7 +74,7 @@
</div> </div>
<!-- submitters line --> <!-- submitters line -->
<div class="motion-list"> <div class="motion-list">
<span class="motion-list-from" *ngIf="motion.submitters.length"> <span class="motion-list-from ellipsis-overflow" *ngIf="motion.submitters.length">
<span translate>by</span> {{ motion.submitters }} <span translate>by</span> {{ motion.submitters }}
</span> </span>
</div> </div>

View File

@ -4,6 +4,7 @@ import { Routes, RouterModule } from '@angular/router';
import { AmendmentCreateWizardComponent } from './components/amendment-create-wizard/amendment-create-wizard.component'; import { AmendmentCreateWizardComponent } from './components/amendment-create-wizard/amendment-create-wizard.component';
import { CallListComponent } from './components/call-list/call-list.component'; import { CallListComponent } from './components/call-list/call-list.component';
import { CategoryListComponent } from './components/category-list/category-list.component'; import { CategoryListComponent } from './components/category-list/category-list.component';
import { CategorySortComponent } from './components/category-sort/category-sort.component';
import { MotionBlockListComponent } from './components/motion-block-list/motion-block-list.component'; import { MotionBlockListComponent } from './components/motion-block-list/motion-block-list.component';
import { MotionBlockDetailComponent } from './components/motion-block-detail/motion-block-detail.component'; import { MotionBlockDetailComponent } from './components/motion-block-detail/motion-block-detail.component';
import { MotionCommentSectionListComponent } from './components/motion-comment-section-list/motion-comment-section-list.component'; import { MotionCommentSectionListComponent } from './components/motion-comment-section-list/motion-comment-section-list.component';
@ -19,6 +20,7 @@ import { WorkflowDetailComponent } from './components/workflow-detail/workflow-d
const routes: Routes = [ const routes: Routes = [
{ path: '', component: MotionListComponent }, { path: '', component: MotionListComponent },
{ path: 'category', component: CategoryListComponent }, { path: 'category', component: CategoryListComponent },
{ path: 'category/:id', component: CategorySortComponent },
{ path: 'comment-section', component: MotionCommentSectionListComponent }, { path: 'comment-section', component: MotionCommentSectionListComponent },
{ path: 'statute-paragraphs', component: StatuteParagraphListComponent }, { path: 'statute-paragraphs', component: StatuteParagraphListComponent },
{ path: 'statute-paragraphs/import', component: StatuteImportListComponent }, { path: 'statute-paragraphs/import', component: StatuteImportListComponent },

View File

@ -25,6 +25,7 @@ import { MotionExportDialogComponent } from './components/motion-export-dialog/m
import { StatuteImportListComponent } from './components/statute-paragraph-list/statute-import-list/statute-import-list.component'; import { StatuteImportListComponent } from './components/statute-paragraph-list/statute-import-list/statute-import-list.component';
import { WorkflowListComponent } from './components/workflow-list/workflow-list.component'; import { WorkflowListComponent } from './components/workflow-list/workflow-list.component';
import { WorkflowDetailComponent } from './components/workflow-detail/workflow-detail.component'; import { WorkflowDetailComponent } from './components/workflow-detail/workflow-detail.component';
import { CategorySortComponent } from './components/category-sort/category-sort.component';
@NgModule({ @NgModule({
imports: [CommonModule, MotionsRoutingModule, SharedModule], imports: [CommonModule, MotionsRoutingModule, SharedModule],
@ -50,7 +51,8 @@ import { WorkflowDetailComponent } from './components/workflow-detail/workflow-d
MotionExportDialogComponent, MotionExportDialogComponent,
StatuteImportListComponent, StatuteImportListComponent,
WorkflowListComponent, WorkflowListComponent,
WorkflowDetailComponent WorkflowDetailComponent,
CategorySortComponent
], ],
entryComponents: [ entryComponents: [
MotionChangeRecommendationComponent, MotionChangeRecommendationComponent,

View File

@ -640,3 +640,9 @@ button.mat-menu-item.selected {
margin: 10px 0; margin: 10px 0;
} }
} }
.ellipsis-overflow {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}