Skip to content
Snippets Groups Projects
Commit f5a09b00 authored by jojohoch's avatar jojohoch
Browse files

Add ControlStates and Rules to control visibility of sections

- Basic implementation
parent a090be39
No related branches found
No related tags found
No related merge requests found
Showing
with 417 additions and 32 deletions
...@@ -66,3 +66,32 @@ blockquote p { ...@@ -66,3 +66,32 @@ blockquote p {
.cdk-drag-dragging { .cdk-drag-dragging {
cursor: grabbing; cursor: grabbing;
} }
.fx-row-start-stretch {
display: flex;
align-items: stretch;
flex-direction: row;
justify-content: flex-start;
}
.fx-row-end-stretch {
display: flex;
align-items: stretch;
flex-direction: row;
justify-content: flex-end;
}
.fx-colum-start-stretch {
display: flex;
align-items: stretch;
flex-direction: column;
justify-content: flex-start;
}
.fx-gap-10 {
gap: 10px;
}
.fx-gap-20 {
gap: 20px;
}
...@@ -3,13 +3,14 @@ import { UIElement } from 'common/models/elements/element'; ...@@ -3,13 +3,14 @@ import { UIElement } from 'common/models/elements/element';
import { ButtonComponent } from 'common/components/button/button.component'; import { ButtonComponent } from 'common/components/button/button.component';
import { ElementComponent } from 'common/directives/element-component.directive'; import { ElementComponent } from 'common/directives/element-component.directive';
import { BasicStyles, PositionProperties } from 'common/models/elements/property-group-interfaces'; import { BasicStyles, PositionProperties } from 'common/models/elements/property-group-interfaces';
import { StateVariable } from 'common/models/state-variable';
export interface ButtonEvent { export interface ButtonEvent {
action: ButtonAction; action: ButtonAction;
param: UnitNavParam | number | string; param: UnitNavParam | number | string | StateVariable
} }
export type ButtonAction = 'unitNav' | 'pageNav' | 'highlightText'; export type ButtonAction = 'unitNav' | 'pageNav' | 'highlightText' | 'stateVariableChange';
export type UnitNavParam = 'previous' | 'next' | 'first' | 'last' | 'end'; export type UnitNavParam = 'previous' | 'next' | 'first' | 'last' | 'end';
export class ButtonElement extends UIElement { export class ButtonElement extends UIElement {
...@@ -17,7 +18,7 @@ export class ButtonElement extends UIElement { ...@@ -17,7 +18,7 @@ export class ButtonElement extends UIElement {
imageSrc: string | null = null; imageSrc: string | null = null;
asLink: boolean = false; asLink: boolean = false;
action: null | ButtonAction = null; action: null | ButtonAction = null;
actionParam: null | UnitNavParam | number | string = null; actionParam: null | UnitNavParam | number | string | StateVariable = null;
position: PositionProperties | undefined; position: PositionProperties | undefined;
styling: BasicStyles & { styling: BasicStyles & {
borderRadius: number; borderRadius: number;
......
...@@ -10,6 +10,8 @@ import { ...@@ -10,6 +10,8 @@ import {
BasicStyles, ExtendedStyles, BasicStyles, ExtendedStyles,
DimensionProperties, PlayerProperties, PositionProperties DimensionProperties, PlayerProperties, PositionProperties
} from 'common/models/elements/property-group-interfaces'; } from 'common/models/elements/property-group-interfaces';
import { VisibilityRule } from 'common/models/visibility-rule';
import { StateVariable } from 'common/models/state-variable';
export type UIElementType = 'text' | 'button' | 'text-field' | 'text-field-simple' | 'text-area' | 'checkbox' export type UIElementType = 'text' | 'button' | 'text-field' | 'text-field-simple' | 'text-area' | 'checkbox'
| 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert-row' | 'radio-group-images' | 'hotspot-image' | 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert-row' | 'radio-group-images' | 'hotspot-image'
...@@ -31,8 +33,8 @@ export interface ValueChangeElement { ...@@ -31,8 +33,8 @@ export interface ValueChangeElement {
} }
export type UIElementValue = string | number | boolean | undefined | UIElementType | InputElementValue | export type UIElementValue = string | number | boolean | undefined | UIElementType | InputElementValue |
TextLabel | TextLabel[] | ClozeDocument | LikertRowElement[] | Hotspot[] | TextLabel | TextLabel[] | ClozeDocument | LikertRowElement[] | Hotspot[] | StateVariable |
PositionProperties | PlayerProperties | BasicStyles | Measurement | Measurement[]; PositionProperties | PlayerProperties | BasicStyles | Measurement | Measurement[] | VisibilityRule[];
export type InputAssistancePreset = null | 'french' | 'numbers' | 'numbersAndOperators' | 'numbersAndBasicOperators' export type InputAssistancePreset = null | 'french' | 'numbers' | 'numbersAndOperators' | 'numbersAndBasicOperators'
| 'comparisonOperators' | 'squareDashDot' | 'placeValue' | 'space' | 'comma' | 'custom'; | 'comparisonOperators' | 'squareDashDot' | 'placeValue' | 'space' | 'comma' | 'custom';
......
...@@ -10,6 +10,7 @@ import { TextElement } from 'common/models/elements/text/text'; ...@@ -10,6 +10,7 @@ import { TextElement } from 'common/models/elements/text/text';
import { ImageElement } from 'common/models/elements/media-elements/image'; import { ImageElement } from 'common/models/elements/media-elements/image';
import { ElementFactory } from 'common/util/element.factory'; import { ElementFactory } from 'common/util/element.factory';
import { AnswerScheme } from 'common/models/elements/answer-scheme-interfaces'; import { AnswerScheme } from 'common/models/elements/answer-scheme-interfaces';
import { VisibilityRule } from 'common/models/visibility-rule';
export class Section { export class Section {
[index: string]: unknown; [index: string]: unknown;
...@@ -23,6 +24,7 @@ export class Section { ...@@ -23,6 +24,7 @@ export class Section {
gridRowSizes: { value: number; unit: string }[] = [{ value: 1, unit: 'fr' }]; gridRowSizes: { value: number; unit: string }[] = [{ value: 1, unit: 'fr' }];
activeAfterID: string | null = null; activeAfterID: string | null = null;
activeAfterIdDelay: number = 0; activeAfterIdDelay: number = 0;
visibilityRules: VisibilityRule[] = [];
constructor(blueprint?: Record<string, any>) { constructor(blueprint?: Record<string, any>) {
const sanitizedBlueprint = Section.sanitizeBlueprint(blueprint); const sanitizedBlueprint = Section.sanitizeBlueprint(blueprint);
...@@ -35,6 +37,10 @@ export class Section { ...@@ -35,6 +37,10 @@ export class Section {
if (sanitizedBlueprint.gridRowSizes !== undefined) this.gridRowSizes = sanitizedBlueprint.gridRowSizes; if (sanitizedBlueprint.gridRowSizes !== undefined) this.gridRowSizes = sanitizedBlueprint.gridRowSizes;
if (sanitizedBlueprint.activeAfterID) this.activeAfterID = sanitizedBlueprint.activeAfterID; if (sanitizedBlueprint.activeAfterID) this.activeAfterID = sanitizedBlueprint.activeAfterID;
if (sanitizedBlueprint.activeAfterIdDelay) this.activeAfterIdDelay = sanitizedBlueprint.activeAfterIdDelay; if (sanitizedBlueprint.activeAfterIdDelay) this.activeAfterIdDelay = sanitizedBlueprint.activeAfterIdDelay;
if (sanitizedBlueprint.visibilityRules) {
this.visibilityRules = sanitizedBlueprint.visibilityRules
.map(rule => new VisibilityRule(rule.id, rule.operator, rule.value));
}
this.elements = this.elements =
sanitizedBlueprint.elements?.map(element => ElementFactory.createElement({ sanitizedBlueprint.elements?.map(element => ElementFactory.createElement({
...element, ...element,
......
export class StateVariable {
id: string;
value: string;
constructor(id: string, value: string) {
this.id = id;
this.value = value;
}
}
import packageJSON from '../../../package.json';
import { Page } from 'common/models/page'; import { Page } from 'common/models/page';
import { UIElement } from 'common/models/elements/element'; import { UIElement } from 'common/models/elements/element';
import { AnswerScheme } from 'common/models/elements/answer-scheme-interfaces'; import { AnswerScheme } from 'common/models/elements/answer-scheme-interfaces';
import { StateVariable } from 'common/models/state-variable';
import packageJSON from '../../../package.json';
export class Unit { export class Unit {
type = 'aspect-unit-definition'; type = 'aspect-unit-definition';
version: string; version: string;
stateVariables: StateVariable[] = [];
pages: Page[] = []; pages: Page[] = [];
constructor(unit?: Partial<Unit>) { constructor(unit?: Partial<Unit>) {
this.version = packageJSON.config.unit_definition_version; this.version = packageJSON.config.unit_definition_version;
this.stateVariables = unit?.stateVariables || [];
this.pages = unit?.pages?.map(page => new Page(page)) || [new Page()]; this.pages = unit?.pages?.map(page => new Page(page)) || [new Page()];
} }
......
export class VisibilityRule {
id: string;
operator: Operator;
value: string;
static operators = ['=', '!=', '<', '<=', '>', '>='];
constructor(id: string, operator: Operator, value: string) {
this.id = id;
this.operator = operator;
this.value = value;
}
}
export type Operator = typeof VisibilityRule.operators[number];
...@@ -27,6 +27,25 @@ import { ...@@ -27,6 +27,25 @@ import {
} from 'editor/src/app/components/properties-panel/model-properties-tab/input-groups/hotspot-field-set.component'; } from 'editor/src/app/components/properties-panel/model-properties-tab/input-groups/hotspot-field-set.component';
import { HotspotEditDialogComponent } from 'editor/src/app/components/dialogs/hotspot-edit-dialog.component'; import { HotspotEditDialogComponent } from 'editor/src/app/components/dialogs/hotspot-edit-dialog.component';
import { MathEditorModule } from 'common/math-editor.module'; import { MathEditorModule } from 'common/math-editor.module';
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
import {
StateVariablesDialogComponent
} from 'editor/src/app/components/dialogs/state-variables-dialog/state-variables-dialog.component';
import {
VisibilityRuleEditorComponent
} from 'editor/src/app/components/dialogs/visibility-rules-dialog/visibility-rule-editor.component';
import {
ShowStateVariablesButtonComponent
} from 'editor/src/app/components/new-ui-element-panel/state-variables-button/show-state-variables-button.component';
import {
StateVariableEditorComponent
} from 'editor/src/app/components/dialogs/state-variables-dialog/state-variable-editor.component';
import {
ButtonActionParamStateVariableComponent
} from 'editor/src/app/components/properties-panel/model-properties-tab/input-groups/button-properties/button-action-param-state-variable.component';
import {
VisibilityRulesDialogComponent
} from 'editor/src/app/components/dialogs/visibility-rules-dialog/visibility-rules-dialog.component';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { ToolbarComponent } from './components/toolbar/toolbar.component'; import { ToolbarComponent } from './components/toolbar/toolbar.component';
import { UiElementToolboxComponent } from import { UiElementToolboxComponent } from
...@@ -73,7 +92,7 @@ import { OptionsFieldSetComponent } from ...@@ -73,7 +92,7 @@ import { OptionsFieldSetComponent } from
import { TextPropertiesFieldSetComponent } from import { TextPropertiesFieldSetComponent } from
'./components/properties-panel/model-properties-tab/input-groups/text-properties-field-set.component'; './components/properties-panel/model-properties-tab/input-groups/text-properties-field-set.component';
import { ButtonPropertiesComponent, GetAnchorIdsPipe, ScrollPageIndexPipe } from import { ButtonPropertiesComponent, GetAnchorIdsPipe, ScrollPageIndexPipe } from
'./components/properties-panel/model-properties-tab/input-groups/button-properties.component'; './components/properties-panel/model-properties-tab/input-groups/button-properties/button-properties.component';
import { SliderPropertiesComponent } from import { SliderPropertiesComponent } from
'./components/properties-panel/model-properties-tab/input-groups/slider-properties.component'; './components/properties-panel/model-properties-tab/input-groups/slider-properties.component';
import { TextFieldElementPropertiesComponent } from import { TextFieldElementPropertiesComponent } from
...@@ -99,7 +118,9 @@ import { ...@@ -99,7 +118,9 @@ import {
import { GeogebraAppDefinitionDialogComponent } from './components/dialogs/geogebra-app-definition-dialog.component'; import { GeogebraAppDefinitionDialogComponent } from './components/dialogs/geogebra-app-definition-dialog.component';
import { SizeInputPanelComponent } from './components/util/size-input-panel.component'; import { SizeInputPanelComponent } from './components/util/size-input-panel.component';
import { ComboButtonComponent } from './components/util/combo-button.component'; import { ComboButtonComponent } from './components/util/combo-button.component';
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay'; import {
GetStateVariableIdsPipe
} from './components/properties-panel/model-properties-tab/input-groups/button-properties/get-state-variable-ids.pipe';
@NgModule({ @NgModule({
declarations: [ declarations: [
...@@ -158,7 +179,14 @@ import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay'; ...@@ -158,7 +179,14 @@ import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
GetAnchorIdsPipe, GetAnchorIdsPipe,
ScrollPageIndexPipe, ScrollPageIndexPipe,
SizeInputPanelComponent, SizeInputPanelComponent,
ComboButtonComponent ComboButtonComponent,
VisibilityRuleEditorComponent,
StateVariablesDialogComponent,
ShowStateVariablesButtonComponent,
StateVariableEditorComponent,
ButtonActionParamStateVariableComponent,
GetStateVariableIdsPipe,
VisibilityRulesDialogComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
......
import { import {
Component, OnDestroy, Input, Output, EventEmitter, Component, OnDestroy, Input, Output, EventEmitter, ViewChild, ElementRef
ViewChild, ElementRef
} from '@angular/core'; } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
...@@ -10,6 +9,7 @@ import { UIElement } from 'common/models/elements/element'; ...@@ -10,6 +9,7 @@ import { UIElement } from 'common/models/elements/element';
import { Section } from 'common/models/section'; import { Section } from 'common/models/section';
import { DropListElement } from 'common/models/elements/input-elements/drop-list'; import { DropListElement } from 'common/models/elements/input-elements/drop-list';
import { IDService } from 'editor/src/app/services/id.service'; import { IDService } from 'editor/src/app/services/id.service';
import { VisibilityRule } from 'common/models/visibility-rule';
import { UnitService } from '../../services/unit.service'; import { UnitService } from '../../services/unit.service';
import { DialogService } from '../../services/dialog.service'; import { DialogService } from '../../services/dialog.service';
import { SelectionService } from '../../services/selection.service'; import { SelectionService } from '../../services/selection.service';
...@@ -42,28 +42,59 @@ import { SelectionService } from '../../services/selection.service'; ...@@ -42,28 +42,59 @@ import { SelectionService } from '../../services/selection.service';
[value]="$any(section.backgroundColor)" [value]="$any(section.backgroundColor)"
(change)="updateModel('backgroundColor', $any($event.target).value)"> (change)="updateModel('backgroundColor', $any($event.target).value)">
<button mat-mini-fab [matMenuTriggerFor]="activeAfterIDMenu" <button mat-mini-fab
(click)="showVisibilityRulesDialog()"
[matTooltip]="'Sichtbarkeit'" [matTooltipPosition]="'left'"> [matTooltip]="'Sichtbarkeit'" [matTooltipPosition]="'left'">
<mat-icon>disabled_visible</mat-icon> <mat-icon>disabled_visible</mat-icon>
</button> </button>
<mat-menu #activeAfterIDMenu="matMenu" <!-- <mat-menu #activeAfterIDMenu="matMenu"-->
class="activeAfterID-menu" xPosition="before"> <!-- class="activeAfterID-menu" xPosition="before">-->
<mat-form-field appearance="outline">
<mat-label>{{'section-menu.activeAfterID' | translate }}</mat-label> <!-- <aspect-rules [elementIds]="elementIds"-->
<input matInput <!-- [rules]="section.rules"-->
[value]="$any(section.activeAfterID)" <!-- (click)="$event.stopPropagation()">-->
(click)="$any($event).stopPropagation()" <!-- </aspect-rules>-->
(change)="updateModel('activeAfterID', $any($event.target).value)">
</mat-form-field>
<mat-form-field appearance="outline"> <!-- <mat-form-field appearance="outline">-->
<mat-label>{{'section-menu.activeAfterIdDelay' | translate }}</mat-label> <!-- <mat-label>{{'section-menu.activeAfterID' | translate }}</mat-label>-->
<input matInput type="number" step="1000" min="0" <!-- <input matInput-->
[disabled]="!section.activeAfterID" <!-- [value]="$any(section.activeAfterID)"-->
[value]="$any(section.activeAfterIdDelay)" <!-- (click)="$any($event).stopPropagation()"-->
(click)="$any($event).stopPropagation()" <!-- (change)="updateModel('activeAfterID', $any($event.target).value)">-->
(change)="updateModel('activeAfterIdDelay', $any($event.target).value)"> <!-- </mat-form-field>-->
</mat-form-field> <!-- <mat-form-field appearance="outline">-->
</mat-menu> <!-- <mat-label>{{'section-menu.activeAfterIdDelay' | translate }}</mat-label>-->
<!-- <input matInput type="number" step="1000" min="0"-->
<!-- [disabled]="!section.activeAfterID"-->
<!-- [value]="$any(section.activeAfterIdDelay)"-->
<!-- (click)="$any($event).stopPropagation()"-->
<!-- (change)="updateModel('activeAfterIdDelay', $any($event.target).value)">-->
<!-- </mat-form-field>-->
<!-- <button mat-icon-button-->
<!-- matSuffix-->
<!-- color="primary"-->
<!-- (click)="addRule($event)">-->
<!-- <mat-icon>add</mat-icon>-->
<!-- </button>-->
<!-- <ng-container *ngFor="let rule of section.rules; let i = index">-->
<!-- <aspect-rule [elementIds]="elementIds"-->
<!-- [rule]="rule"-->
<!-- (ruleChange)="updateRule(i, $event)"-->
<!-- (click)="$event.stopPropagation()">-->
<!-- </aspect-rule>-->
<!-- <button mat-icon-button-->
<!-- matSuffix-->
<!-- color="primary"-->
<!-- (click)="deleteRule(i)">-->
<!-- <mat-icon>delete</mat-icon>-->
<!-- </button>-->
<!-- </ng-container>-->
<!-- </mat-menu>-->
<button mat-mini-fab [matMenuTriggerFor]="layoutMenu" <button mat-mini-fab [matMenuTriggerFor]="layoutMenu"
[matTooltip]="'Layout'" [matTooltipPosition]="'left'"> [matTooltip]="'Layout'" [matTooltipPosition]="'left'">
<mat-icon>space_dashboard</mat-icon> <mat-icon>space_dashboard</mat-icon>
...@@ -206,7 +237,9 @@ export class SectionMenuComponent implements OnDestroy { ...@@ -206,7 +237,9 @@ export class SectionMenuComponent implements OnDestroy {
private idService: IDService, private idService: IDService,
private clipboard: Clipboard) { } private clipboard: Clipboard) { }
updateModel(property: string, value: string | number | boolean | { value: number; unit: string }[]): void { updateModel(
property: string, value: string | number | boolean | VisibilityRule[] | { value: number; unit: string }[]
): void {
this.unitService.updateSectionProperty(this.section, property, value); this.unitService.updateSectionProperty(this.section, property, value);
} }
...@@ -285,4 +318,21 @@ export class SectionMenuComponent implements OnDestroy { ...@@ -285,4 +318,21 @@ export class SectionMenuComponent implements OnDestroy {
} }
}); });
} }
showVisibilityRulesDialog(): void {
this.dialogService.showVisibilityRulesDialog(this.section.visibilityRules, this.getControlIds(), this.section.activeAfterIdDelay)
.subscribe(rulesWithDelay => {
if (rulesWithDelay) {
this.updateModel('visibilityRules', rulesWithDelay.visibilityRules);
this.updateModel('activeAfterIdDelay', rulesWithDelay.activeAfterIdDelay);
}
});
}
private getControlIds(): string[] {
return this.unitService.unit.getAllElements()
.map(element => element.id)
.concat(this.unitService.unit.stateVariables
.map(element => element.id));
}
} }
<div class="fx-row-start-stretch fx-gap-10">
<mat-form-field>
<mat-label>Id</mat-label>
<input matInput
placeholder="Id"
[(ngModel)]="stateVariable.id"
(ngModelChange)="stateVariableChange.emit(stateVariable)">
</mat-form-field>
<mat-form-field>
<mat-label>Wert</mat-label>
<input matInput
placeholder="Initialwert"
[(ngModel)]="stateVariable.value"
(ngModelChange)="stateVariableChange.emit(stateVariable)">
</mat-form-field>
</div>
import {
Component, EventEmitter, Input, Output
} from '@angular/core';
import { StateVariable } from 'common/models/state-variable';
@Component({
selector: 'aspect-state-variable-editor',
templateUrl: './state-variable-editor.component.html'
})
export class StateVariableEditorComponent {
@Input() stateVariable: StateVariable = new StateVariable('', '');
@Output() stateVariableChange = new EventEmitter<StateVariable>();
}
<h1 mat-dialog-title>Player-Variablen bearbeiten</h1>
<div mat-dialog-content class="fx-colum-start-stretch fx-gap-20">
<div class="fx-row-end-stretch">
<button mat-icon-button
matSuffix
color="primary"
(click)="addStateVariable()">
<mat-icon>add</mat-icon>
</button>
</div>
<div *ngFor="let stateVariable of stateVariables; let i = index"
class="fx-row-start-stretch fx-gap-10">
<aspect-state-variable-editor
[(stateVariable)]="stateVariables[i]">
</aspect-state-variable-editor>
<button mat-icon-button
matSuffix
color="warn"
(click)="deleteStateVariable(i)">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
<div mat-dialog-actions>
<button mat-button
mat-dialog-close>
Abbrechen
</button>
<button mat-button
[mat-dialog-close]="stateVariables">
Speichern
</button>
</div>
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { StateVariable } from 'common/models/state-variable';
@Component({
templateUrl: './state-variables-dialog.component.html'
})
export class StateVariablesDialogComponent {
stateVariables: StateVariable[];
constructor(@Inject(MAT_DIALOG_DATA) private data: { stateVariables: StateVariable[] }) {
this.stateVariables = [...data.stateVariables];
}
addStateVariable() {
this.stateVariables.push(new StateVariable('NewState', '1'));
}
deleteStateVariable(index: number) {
this.stateVariables.splice(index, 1);
}
}
<div class="fx-row-start-stretch fx-gap-10">
<mat-form-field>
<mat-label>Id</mat-label>
<mat-select [(ngModel)]="visibilityRule.id"
(ngModelChange)="visibilityRuleChange.emit(visibilityRule)">
<mat-option *ngFor="let id of controlIds"
[value]="id">
{{id}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-label>Operator</mat-label>
<mat-select [(ngModel)]="visibilityRule.operator"
(ngModelChange)="visibilityRuleChange.emit(visibilityRule)">
<mat-option *ngFor="let operator of VisibilityRule.operators"
[value]="operator">
{{operator}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-label>Wert</mat-label>
<input matInput
placeholder="Wert"
[(ngModel)]="visibilityRule.value"
(ngModelChange)="visibilityRuleChange.emit(visibilityRule)">
</mat-form-field>
</div>
import {
Component, EventEmitter, Input, Output
} from '@angular/core';
import { VisibilityRule } from 'common/models/visibility-rule';
@Component({
selector: 'aspect-visibility-rule-editor',
templateUrl: './visibility-rule-editor.component.html'
})
export class VisibilityRuleEditorComponent {
@Input() controlIds!: string[];
@Input() visibilityRule!: VisibilityRule;
@Output() visibilityRuleChange = new EventEmitter<VisibilityRule>();
protected readonly VisibilityRule = VisibilityRule;
}
<h1 mat-dialog-title>Regeln zur Sichtbarkeit</h1>
<div mat-dialog-content class="fx-colum-start-stretch fx-gap-20">
<ng-container *ngIf="controlIds.length">
<div class="fx-row-end-stretch">
<button mat-icon-button
matSuffix
color="primary"
(click)="addVisibilityRule()">
<mat-icon>add</mat-icon>
</button>
</div>
<mat-form-field *ngIf="visibilityRules.length">
<mat-label>Verzögerung in ms</mat-label>
<input matInput
placeholder="Verzögerung in ms"
[(ngModel)]="activeAfterIdDelay">
</mat-form-field>
</ng-container>
<p *ngIf="!controlIds.length">Bitte zuerst Elemente oder Player-Variablen anlegen</p>
<div *ngFor="let rule of visibilityRules; let i = index"
class="fx-row-start-stretch fx-gap-10">
<aspect-visibility-rule-editor [controlIds]="controlIds"
[(visibilityRule)]="visibilityRules[i]">
</aspect-visibility-rule-editor>
<button mat-icon-button
matSuffix
color="warn"
(click)="deleteVisibilityRule(i)">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
<div mat-dialog-actions>
<button mat-button
mat-dialog-close>
Abbrechen
</button>
<button *ngIf="controlIds.length"
mat-button
[mat-dialog-close]="{visibilityRules:visibilityRules, activeAfterIdDelay}">
Speichern
</button>
</div>
import { Component, Inject } from '@angular/core';
import { VisibilityRule } from 'common/models/visibility-rule';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
@Component({
templateUrl: './visibility-rules-dialog.component.html'
})
export class VisibilityRulesDialogComponent {
visibilityRules!: VisibilityRule[];
controlIds!: string[];
activeAfterIdDelay!: number;
constructor(
@Inject(MAT_DIALOG_DATA) private data: {
visibilityRules: VisibilityRule[],
activeAfterIdDelay: number,
controlIds: string[],
}
) {
this.visibilityRules = [...data.visibilityRules];
this.activeAfterIdDelay = data.activeAfterIdDelay;
this.controlIds = data.controlIds;
}
addVisibilityRule(): void {
this.visibilityRules.push(new VisibilityRule('', '=', ''));
}
deleteVisibilityRule(index: number): void {
this.visibilityRules.splice(index, 1);
}
}
<button mat-flat-button
class="show-state-variables-button"
color="accent"
(click)="showStateVariablesDialog()">
<mat-icon>integration_instructions</mat-icon>
<span>State Variables</span>
</button>
.show-state-variables-button {
width: 100%;
}
import { Component } from '@angular/core';
import { DialogService } from 'editor/src/app/services/dialog.service';
import { UnitService } from 'editor/src/app/services/unit.service';
@Component({
selector: 'aspect-show-state-variables-button',
templateUrl: './show-state-variables-button.component.html',
styleUrls: ['./show-state-variables-button.component.scss']
})
export class ShowStateVariablesButtonComponent {
constructor(private dialogService: DialogService,
private unitService: UnitService) { }
showStateVariablesDialog() {
this.dialogService.showStateVariablesDialog(this.unitService.unit.stateVariables)
.subscribe(stateVariables => {
if (stateVariables) {
this.unitService.updateStateVariables(stateVariables);
}
});
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment