Enhance subcategories

- show parents over children in motion list, motion detail and PDF
- indent children of categories in the filter list
This commit is contained in:
Sean Engelhardt 2019-07-16 10:48:48 +02:00
parent 1c3d60fe39
commit 530dcf490a
9 changed files with 54 additions and 39 deletions

View File

@ -36,6 +36,7 @@ export interface OsFilterOption {
label: string; label: string;
condition: OsFilterOptionCondition; condition: OsFilterOptionCondition;
isActive?: boolean; isActive?: boolean;
isChild?: boolean;
} }
/** /**
@ -46,6 +47,14 @@ export interface OsFilterIndicator {
option: OsFilterOption; option: OsFilterOption;
} }
/**
* Extends the BaseViewModel with a parent
* Required to represent parent-child relationships in the filter
*/
interface HierarchyModel extends BaseViewModel {
parent: BaseViewModel;
}
/** /**
* Define the type of a filter condition * Define the type of a filter condition
*/ */
@ -266,10 +275,11 @@ export abstract class BaseFilterListService<V extends BaseViewModel> {
filterProperties = viewModel filterProperties = viewModel
.filter(model => (excludeIds && excludeIds.length ? !excludeIds.includes(model.id) : true)) .filter(model => (excludeIds && excludeIds.length ? !excludeIds.includes(model.id) : true))
.map(model => { .map((model: HierarchyModel) => {
return { return {
condition: model.id, condition: model.id,
label: model.getTitle() label: model.getTitle(),
isChild: !!model.parent
}; };
}); });

View File

@ -37,5 +37,6 @@ os-icon-container {
margin: auto 5px; margin: auto 5px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: pre-line;
} }
} }

View File

@ -14,7 +14,7 @@
<div *ngFor="let option of filter.options"> <div *ngFor="let option of filter.options">
<div *ngIf="isFilter(option)"> <div *ngIf="isFilter(option)">
<mat-checkbox <mat-checkbox
class="filter-title" [ngClass]="option.isChild ? 'filter-child' : ''"
[checked]="option.isActive" [checked]="option.isActive"
(change)="service.toggleFilterOption(filter.property, option)" (change)="service.toggleFilterOption(filter.property, option)"
> >

View File

@ -28,6 +28,10 @@ mat-divider {
font-style: italic; font-style: italic;
} }
.filter-child {
margin-left: 20px;
}
// adds breaks to mat-checkboxes with long labels // adds breaks to mat-checkboxes with long labels
::ng-deep .mat-checkbox-layout { ::ng-deep .mat-checkbox-layout {
white-space: normal !important; white-space: normal !important;

View File

@ -64,6 +64,17 @@ export class ViewCategory extends BaseViewModel<Category> implements CategoryTit
return name; return name;
} }
/**
* Shows the (direct) parent above the current category
*/
public get nameWithParentAbove(): string {
if (this.parent) {
return `${this.parent.toString()}\n${this.toString()}`;
} else {
return this.toString();
}
}
public constructor(category: Category, parent?: ViewCategory) { public constructor(category: Category, parent?: ViewCategory) {
super(Category.COLLECTIONSTRING, category); super(Category.COLLECTIONSTRING, category);
this._parent = parent; this._parent = parent;

View File

@ -152,9 +152,7 @@
<!-- Sequential number --> <!-- Sequential number -->
<span class="main-nav-color title-font"> <span class="main-nav-color title-font">
<span *ngIf="showSequential"> <span *ngIf="showSequential"> <span translate>Sequential number</span>&nbsp;{{ motion.id }} </span>
<span translate>Sequential number</span>&nbsp;{{ motion.id }}
</span>
<span *ngIf="showSequential && motion.parent_id">&#xb7;&nbsp;</span> <span *ngIf="showSequential && motion.parent_id">&#xb7;&nbsp;</span>
<span *ngIf="motion.parent_id"> <span *ngIf="motion.parent_id">
<span> <span>
@ -345,10 +343,18 @@
<mat-basic-chip <mat-basic-chip
*ngIf="perms.isAllowed('change_metadata', motion)" *ngIf="perms.isAllowed('change_metadata', motion)"
[matMenuTriggerFor]="categoryMenu" [matMenuTriggerFor]="categoryMenu"
class="grey" class="grey multi-line-chip"
disableRipple disableRipple
> >
{{ motion.category ? motion.category.prefixedNameWithParents : '' }} <div *ngIf="motion.category">
<div *ngIf="motion.category.parent">
{{ motion.category.parent }}
</div>
<span *ngIf="motion.category.parent">{{ 'Subcategory' | translate }}:</span>
{{ motion.category }}
</div>
<span *ngIf="!motion.category">-</span>
</mat-basic-chip> </mat-basic-chip>
<mat-basic-chip <mat-basic-chip
*ngIf="!perms.isAllowed('change_metadata', motion) && motion.category" *ngIf="!perms.isAllowed('change_metadata', motion) && motion.category"

View File

@ -104,35 +104,6 @@
</span> </span>
</div> </div>
<!-- state column -->
<ng-container matColumnDef="state">
<mat-header-cell *matHeaderCellDef mat-sort-header>State</mat-header-cell>
<mat-cell (click)="openEditInfo(motion, $event)" *matCellDef="let motion">
<div class="fill">
<div class="innerTable state-column">
<div class="ellipsis-overflow" *ngIf="motion.category">
<os-icon-container icon="device_hub">
{{ motion.category.prefixedNameWithParents }}
</os-icon-container>
</div>
<div class="ellipsis-overflow spacer-top-5" *ngIf="motion.motion_block">
<os-icon-container icon="widgets">
{{ motion.motion_block.title }}
</os-icon-container>
</div>
<div class="ellipsis-overflow spacer-top-5" *ngIf="motion.tags && motion.tags.length">
<os-icon-container icon="local_offer">
<span *ngFor="let tag of motion.tags; let last = last">
{{ tag.getTitle() }}
<span *ngIf="!last">,&nbsp;</span>
</span>
</os-icon-container>
</div>
</div>
</div>
</mat-cell>
</ng-container>
<!-- Workflow state --> <!-- Workflow state -->
<div class="ellipsis-overflow white"> <div class="ellipsis-overflow white">
<mat-basic-chip *ngIf="motion.state" [ngClass]="motion.stateCssColor" [disabled]="true"> <mat-basic-chip *ngIf="motion.state" [ngClass]="motion.stateCssColor" [disabled]="true">
@ -163,7 +134,7 @@
<!-- Category --> <!-- Category -->
<div class="ellipsis-overflow" *ngIf="motion.category"> <div class="ellipsis-overflow" *ngIf="motion.category">
<os-icon-container icon="device_hub"> <os-icon-container icon="device_hub">
{{ motion.category.prefixedNameWithParents }} {{ motion.category.nameWithParentAbove }}
</os-icon-container> </os-icon-container>
</div> </div>

View File

@ -310,13 +310,21 @@ export class MotionPdfService {
// category // category
if (motion.category && (!infoToExport || infoToExport.includes('category'))) { if (motion.category && (!infoToExport || infoToExport.includes('category'))) {
let categoryText = '';
if (!!motion.category.parent) {
categoryText = `${motion.category.parent.toString()}\n${this.translate.instant(
'Subcategory'
)}: ${motion.category.toString()}`;
} else {
categoryText = motion.category.toString();
}
metaTableBody.push([ metaTableBody.push([
{ {
text: `${this.translate.instant('Category')}:`, text: `${this.translate.instant('Category')}:`,
style: 'boldText' style: 'boldText'
}, },
{ {
text: motion.category.prefixedNameWithParents text: categoryText
} }
]); ]);
} }

View File

@ -732,6 +732,10 @@ button.mat-menu-item.selected {
color: rgba(0, 0, 0, 0.87) !important; color: rgba(0, 0, 0, 0.87) !important;
} }
.multi-line-chip {
white-space: pre-line
}
/* TODO: move to site.component.scss-theme.scss (does not work currently) */ /* TODO: move to site.component.scss-theme.scss (does not work currently) */
/* make the .user-menu expansion panel look like the nav-toolbar above */ /* make the .user-menu expansion panel look like the nav-toolbar above */