From f63443afa76f7176ddb08f20907fd577713bcd86 Mon Sep 17 00:00:00 2001 From: rhenck <richard.henck@iqb.hu-berlin.de> Date: Wed, 1 Jun 2022 22:51:45 +0200 Subject: [PATCH] Fix simple drop list properties panel Now properly finds all normal and simple drop lists. This is achieved by a new method of unit all it's sub-components, which returns all contained elements with and optional type filter. Also improve (still not very pretty) styling of the drop list props panel. #260 #259 --- .../elements/compound-elements/cloze/cloze.ts | 2 +- projects/common/models/page.ts | 5 ++ projects/common/models/section.ts | 10 ++- projects/common/models/unit.ts | 9 ++- .../common/services/sanitization.service.ts | 6 +- .../section-insert-dialog.component.ts | 2 +- .../drop-list-properties.component.ts | 64 ++++++++++--------- .../editor/src/app/services/unit.service.ts | 12 ++-- 8 files changed, 62 insertions(+), 48 deletions(-) diff --git a/projects/common/models/elements/compound-elements/cloze/cloze.ts b/projects/common/models/elements/compound-elements/cloze/cloze.ts index 4d13bf342..a90b6dc5b 100644 --- a/projects/common/models/elements/compound-elements/cloze/cloze.ts +++ b/projects/common/models/elements/compound-elements/cloze/cloze.ts @@ -102,7 +102,7 @@ export class ClozeElement extends CompoundElement implements PositionedUIElement } getChildElements(): UIElement[] { - return ClozeElement.getDocumentChildElements(this.documnent); + return ClozeElement.getDocumentChildElements(this.document); } static getDocumentChildElements(document: ClozeDocument): UIElement[] { diff --git a/projects/common/models/page.ts b/projects/common/models/page.ts index 54e905ca7..2119d3492 100644 --- a/projects/common/models/page.ts +++ b/projects/common/models/page.ts @@ -1,5 +1,6 @@ import { Section } from 'common/models/section'; import { IDManager } from 'common/util/id-manager'; +import { UIElement } from 'common/models/elements/element'; export class Page { [index: string]: any; @@ -22,4 +23,8 @@ export class Page { if (page?.alwaysVisibleAspectRatio) this.alwaysVisibleAspectRatio = page.alwaysVisibleAspectRatio; this.sections = page?.sections.map(section => new Section(section, idManager)) || [new Section()]; } + + getAllElements(elementType?: string): UIElement[] { + return this.sections.map(section => section.getAllElements(elementType)).flat(); + } } diff --git a/projects/common/models/section.ts b/projects/common/models/section.ts index 2f543d89e..eca8a7555 100644 --- a/projects/common/models/section.ts +++ b/projects/common/models/section.ts @@ -88,7 +88,13 @@ export class Section { } /* Includes children of children, i.e. compound children. */ - getAllChildElements(): UIElement[] { - return this.elements.map(element => [element, ...element.getChildElements()]).flat(); + getAllElements(elementType?: string): UIElement[] { + let allElements: UIElement[] = + this.elements.map(element => [element, ...element.getChildElements()]) + .flat(); + if (elementType) { + allElements = allElements.filter(element => element.type === elementType); + } + return allElements; } } diff --git a/projects/common/models/unit.ts b/projects/common/models/unit.ts index 9aa6c8e00..f23bcd99d 100644 --- a/projects/common/models/unit.ts +++ b/projects/common/models/unit.ts @@ -1,14 +1,19 @@ import packageJSON from '../../../package.json'; import { Page } from 'common/models/page'; import { IDManager } from 'common/util/id-manager'; +import { UIElement } from 'common/models/elements/element'; export class Unit { type = 'aspect-unit-definition'; version: string; pages: Page[] = []; - constructor(unit?: Unit, idManager?: IDManager) { + constructor(unit?: Partial<Unit>, idManager?: IDManager) { this.version = packageJSON.config.unit_definition_version; - this.pages = unit?.pages.map(page => new Page(page, idManager)) || [new Page()]; + this.pages = unit?.pages?.map(page => new Page(page, idManager)) || [new Page()]; + } + + getAllElements(elementType?: string): UIElement[] { + return this.pages.map(page => page.getAllElements(elementType)).flat(); } } diff --git a/projects/common/services/sanitization.service.ts b/projects/common/services/sanitization.service.ts index 3bc7b1680..fc622e7a8 100644 --- a/projects/common/services/sanitization.service.ts +++ b/projects/common/services/sanitization.service.ts @@ -45,10 +45,10 @@ export class SanitizationService { return SanitizationService.isVersionOlderThanCurrent(SanitizationService.unitDefinitionVersion); } - sanitizeUnitDefinition(unitDefinition: Unit): Unit { + sanitizeUnitDefinition(unitDefinition: Unit): Partial<Unit> { return { ...unitDefinition, - pages: unitDefinition.pages.map((page: Page) => this.sanitizePage(page)) + pages: unitDefinition.pages.map((page: Page) => this.sanitizePage(page)) as Page[] }; } @@ -71,7 +71,7 @@ export class SanitizationService { return version[2] < SanitizationService.expectedUnitVersion[2]; } - private sanitizePage(page: Page): Page { + private sanitizePage(page: Page): Partial<Page> { return { ...page, sections: page.sections.map((section: Section) => this.sanitizeSection(section)) diff --git a/projects/editor/src/app/components/dialogs/section-insert-dialog.component.ts b/projects/editor/src/app/components/dialogs/section-insert-dialog.component.ts index 89384e45c..3fb0c7cda 100644 --- a/projects/editor/src/app/components/dialogs/section-insert-dialog.component.ts +++ b/projects/editor/src/app/components/dialogs/section-insert-dialog.component.ts @@ -58,7 +58,7 @@ export class SectionInsertDialogComponent { try { this.newSection = new Section(JSON.parse(pastedText)); - if (this.findElementsWithDuplicateID(this.newSection.getAllChildElements()).length > 0) { + if (this.findElementsWithDuplicateID(this.newSection.getAllElements()).length > 0) { this.operationStatusText = this.translateService.instant('Doppelte IDs festgestellt. Weiter mit neu generierten IDs?'); this.operationStatus = 'yellow'; diff --git a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts index 73589c077..83360045f 100644 --- a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts +++ b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts @@ -15,49 +15,47 @@ import { IDManager } from 'common/util/id-manager'; selector: 'aspect-drop-list-properties', template: ` <fieldset *ngIf="combinedProperties.type === 'drop-list' || - combinedProperties.type === 'drop-list-sorting'"> + combinedProperties.type === 'drop-list-simple'"> <legend>Ablegeliste</legend> - <mat-form-field disabled="true" *ngIf="combinedProperties.type === 'drop-list' || - combinedProperties.type === 'drop-list-sorting'"> - <ng-container> - <mat-label>{{'preset' | translate }}</mat-label> - <div class="drop-list" cdkDropList [cdkDropListData]="combinedProperties.value" - (cdkDropListDropped)="moveListValue($any($event))"> - <div *ngFor="let value of $any(combinedProperties.value); let i = index" cdkDrag - class="list-items" fxLayout="row" fxLayoutAlign="end center"> - <div fxFlex="70" class="draggable-element-label"> - {{value.stringValue}} ({{value.id}}) - </div> - <img [src]="value.imgSrcValue" - [style.object-fit]="'scale-down'" - [style.height.px]="40"> - <button mat-icon-button color="primary" - (click)="editDropListOption(i)"> - <mat-icon>build</mat-icon> - </button> - <button mat-icon-button color="primary" - (click)="removeListValue('value', i)"> - <mat-icon>clear</mat-icon> - </button> + <div class="value-list-container"> + <mat-label>{{'preset' | translate }}</mat-label> + <div class="drop-list" cdkDropList [cdkDropListData]="combinedProperties.value" + (cdkDropListDropped)="moveListValue($any($event))"> + <div *ngFor="let value of $any(combinedProperties.value); let i = index" cdkDrag + class="list-items" fxLayout="row" fxLayoutAlign="end center"> + <div fxFlex="70" class="draggable-element-label"> + {{value.stringValue}} ({{value.id}}) </div> + <img [src]="value.imgSrcValue" + [style.object-fit]="'scale-down'" + [style.height.px]="40"> + <button mat-icon-button color="primary" + (click)="editDropListOption(i)"> + <mat-icon>build</mat-icon> + </button> + <button mat-icon-button color="primary" + (click)="removeListValue('value', i)"> + <mat-icon>clear</mat-icon> + </button> </div> - </ng-container> - <div fxLayout="row" fxLayoutAlign="center center"> - <textarea matInput type="text" #newValue rows="2" + </div> + <div fxLayout="row" fxLayoutAlign="center center" class="text-area-container"> + <textarea matInput type="text" + #newValue rows="2" (keyup.enter)="addDropListOption(newValue.value); newValue.select()"></textarea> <button mat-icon-button (click)="addDropListOption(newValue.value); newValue.select()"> <mat-icon>add</mat-icon> </button> </div> - </mat-form-field> + </div> - <mat-form-field appearance="fill" *ngIf="combinedProperties.connectedTo !== null"> + <mat-form-field appearance="fill" *ngIf="combinedProperties.connectedTo !== null" + (click)="generateValidDropLists()"> <mat-label>{{'propertiesPanel.connectedDropLists' | translate }}</mat-label> <mat-select multiple [ngModel]="combinedProperties.connectedTo" - (ngModelChange)="toggleConnectedDropList($event)" - (click)="generateValidDropLists()"> + (ngModelChange)="toggleConnectedDropList($event)"> <mat-select-trigger> {{'propertiesPanel.connectedDropLists' | translate }} ({{combinedProperties.connectedTo.length}}) </mat-select-trigger> @@ -109,7 +107,11 @@ import { IDManager } from 'common/util/id-manager'; styles: [ 'mat-form-field {width: 100%;}', '.draggable-element-label {overflow-wrap: anywhere;}', - 'mat-select {height: 100%;}' + 'mat-select {height: 100%;}', + '.text-area-container {background-color: lightgray; margin-bottom: 15px;}', + '.value-list-container {background-color: rgba(0,0,0,.04);}', + '.text-area-container button {border: 1px solid gray;}', + '.value-list-container mat-label {font-size: large;}' ] }) export class DropListPropertiesComponent { diff --git a/projects/editor/src/app/services/unit.service.ts b/projects/editor/src/app/services/unit.service.ts index d73d4e57a..b61d0d22c 100644 --- a/projects/editor/src/app/services/unit.service.ts +++ b/projects/editor/src/app/services/unit.service.ts @@ -404,14 +404,10 @@ export class UnitService { /* Used by props panel to show available dropLists to connect */ getDropListElementIDs(): string[] { - return this.unit.pages - .map(page => page.sections - .map(section => section.elements - .reduce((accumulator: any[], currentValue: any) => ( - currentValue.type === 'drop-list' ? accumulator.concat(currentValue.id) : accumulator), []) - .flat() - ) - .flat()).flat(); + const allDropLists = [ + ...this.unit.getAllElements('drop-list'), + ...this.unit.getAllElements('drop-list-simple')]; + return allDropLists.map(dropList => dropList.id); } replaceSection(pageIndex: number, sectionIndex: number, newSection: Section): void { -- GitLab