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

[editor] Extract actions from ButtonPropertiesComponent

to make them available for new trigger element
parent 00fa000b
No related branches found
No related tags found
No related merge requests found
...@@ -50,6 +50,9 @@ import { MatBadgeModule } from '@angular/material/badge'; ...@@ -50,6 +50,9 @@ import { MatBadgeModule } from '@angular/material/badge';
import { import {
TooltipPropertiesDialogComponent TooltipPropertiesDialogComponent
} from 'editor/src/app/components/dialogs/tooltip-properties-dialog.component'; } from 'editor/src/app/components/dialogs/tooltip-properties-dialog.component';
import {
ActionPropertiesComponent, GetAnchorIdsPipe, GetStateVariableIdsPipe, ScrollPageIndexPipe
} from 'editor/src/app/components/properties-panel/model-properties-tab/input-groups/action-properties.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
...@@ -98,8 +101,8 @@ import { OptionsFieldSetComponent } from ...@@ -98,8 +101,8 @@ import { OptionsFieldSetComponent } from
'./components/properties-panel/model-properties-tab/input-groups/options-field-set.component'; './components/properties-panel/model-properties-tab/input-groups/options-field-set.component';
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 } from
'./components/properties-panel/model-properties-tab/input-groups/button-properties/button-properties.component'; './components/properties-panel/model-properties-tab/input-groups/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
...@@ -126,9 +129,6 @@ import { GeogebraAppDefinitionDialogComponent } from './components/dialogs/geoge ...@@ -126,9 +129,6 @@ import { GeogebraAppDefinitionDialogComponent } from './components/dialogs/geoge
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 { DeleteReferenceDialogComponent } from './components/dialogs/delete-reference-dialog.component'; import { DeleteReferenceDialogComponent } from './components/dialogs/delete-reference-dialog.component';
import {
GetStateVariableIdsPipe
} from './components/properties-panel/model-properties-tab/input-groups/button-properties/get-state-variable-ids.pipe';
import { SanitizationDialogComponent } from './components/dialogs/sanitization-dialog.component'; import { SanitizationDialogComponent } from './components/dialogs/sanitization-dialog.component';
import { CheckboxNodeviewComponent } from './text-editor/angular-node-views/checkbox-nodeview.component'; import { CheckboxNodeviewComponent } from './text-editor/angular-node-views/checkbox-nodeview.component';
import { import {
...@@ -172,6 +172,7 @@ import { ...@@ -172,6 +172,7 @@ import {
OptionsFieldSetComponent, OptionsFieldSetComponent,
TextPropertiesFieldSetComponent, TextPropertiesFieldSetComponent,
ButtonPropertiesComponent, ButtonPropertiesComponent,
ActionPropertiesComponent,
SliderPropertiesComponent, SliderPropertiesComponent,
TextFieldElementPropertiesComponent, TextFieldElementPropertiesComponent,
ScaleAndZoomPropertiesComponent, ScaleAndZoomPropertiesComponent,
......
// eslint-disable-next-line max-classes-per-file
import {
Component, EventEmitter, Input, Output, Pipe, PipeTransform
} from '@angular/core';
import { UIElement } from 'common/models/elements/element';
import { StateVariable } from 'common/models/state-variable';
import { TextComponent } from 'common/components/text/text.component';
import { UnitService } from 'editor/src/app/services/unit.service';
import { SelectionService } from 'editor/src/app/services/selection.service';
import { Page } from 'common/models/page';
@Component({
selector: 'aspect-action-properties',
template: `
<fieldset>
<legend>{{'propertiesPanel.action' | translate}}</legend>
<div class="fx-column-start-stretch">
<mat-form-field *ngIf="combinedProperties.action !== undefined" appearance="fill">
<mat-label>{{'propertiesPanel.action' | translate }}</mat-label>
<mat-select [value]="combinedProperties.action"
(selectionChange)="updateModel.emit({ property: 'action', value: $event.value })">
<mat-option [value]="null">
{{ 'propertiesPanel.none' | translate }}
</mat-option>
<mat-option *ngFor="let option of ['unitNav', 'pageNav', 'highlightText', 'stateVariableChange']"
[value]="option">
{{ 'propertiesPanel.' + option | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<ng-container *ngIf="combinedProperties.action === 'stateVariableChange'">
<aspect-action-param-state-variable
*ngIf="unitService.unit.stateVariables.length"
[stateVariableIds]="unitService.unit.stateVariables | getStateVariableIds"
[stateVariable]="combinedProperties.actionParam ?
$any(combinedProperties.actionParam) :
{ id: unitService.unit.stateVariables[0].id, value: '' }"
(stateVariableChange)="updateModel.emit({ property: 'actionParam', value: $event })">
</aspect-action-param-state-variable>
<p *ngIf="!unitService.unit.stateVariables.length">{{'propertiesPanel.addStateVariables' | translate}}</p>
</ng-container>
<mat-form-field *ngIf="combinedProperties.action !== 'stateVariableChange'"
appearance="fill">
<mat-label>{{'propertiesPanel.actionParam' | translate }}</mat-label>
<mat-select [disabled]="combinedProperties.action === null"
[value]="combinedProperties.actionParam"
[matTooltipDisabled]="combinedProperties.action !== 'pageNav'"
[matTooltip]="'propertiesPanel.pageNavSelectionHint' | translate"
(selectionChange)="updateModel.emit({ property: 'actionParam', value: $event.value })">
<ng-container *ngIf="combinedProperties.action === 'pageNav'">
<ng-container *ngFor="let page of (unitService.unit.pages | scrollPages); index as i">
<mat-option *ngIf="(unitService.unit.pages | scrollPageIndex: selectionService.selectedPageIndex) !== i"
[value]="i">
{{'page' | translate}} {{i + 1}}
</mat-option>
</ng-container>
</ng-container>
<ng-container *ngIf="combinedProperties.action === 'unitNav'">
<mat-option *ngFor="let option of [undefined, 'previous', 'next', 'first', 'last', 'end']"
[value]="option">
{{ 'propertiesPanel.' + option | translate }}
</mat-option>
</ng-container>
<ng-container *ngIf="combinedProperties.action === 'highlightText'">
<mat-option *ngFor="let option of (textComponents | getAnchorIds) "
[value]="option">
{{ option }}
</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
</div>
</fieldset>
`,
styles: [`
.fx-column-start-stretch {
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;}
`]
})
export class ActionPropertiesComponent {
@Input() combinedProperties!: UIElement;
@Output() updateModel =
new EventEmitter<{
property: string; value: string | number | boolean | StateVariable | null, isInputValid?: boolean | null
}>();
textComponents: { [id: string]: TextComponent } = {};
constructor(public unitService: UnitService, public selectionService: SelectionService) {
this.textComponents = TextComponent.textComponents;
}
}
@Pipe({
name: 'getStateVariableIds'
})
export class GetStateVariableIdsPipe implements PipeTransform {
transform(stateVariables: StateVariable[]): string[] {
return stateVariables.map(stateVariable => stateVariable.id);
}
}
@Pipe({
name: 'getAnchorIds'
})
export class GetAnchorIdsPipe implements PipeTransform {
// There can be multiple elements with the same data-anchor-id,
// since a selected range can include multiple HTMLElements.
// The first element is filtered out for display in the properties panel.
transform(textComponents: { [id: string]: TextComponent }): string[] {
return Object.values(textComponents)
.map(textComponent => Array
.from(textComponent.textContainerRef.nativeElement.querySelectorAll('aspect-anchor'))
.map(anchor => (anchor as Element).getAttribute('data-anchor-id'))
.filter((anchorId, index, anchorIds) => anchorIds
.indexOf(anchorId) === index) as string[]
)
.flat();
}
}
@Pipe({
name: 'scrollPageIndex'
})
export class ScrollPageIndexPipe implements PipeTransform {
transform(pages: Page[], index: number): number | null {
if (pages.find((page: Page): boolean => page.alwaysVisible)) {
return index - 1;
}
return index;
}
}
// eslint-disable-next-line max-classes-per-file
import { import {
Component, EventEmitter, Input, Output, Pipe, PipeTransform Component, EventEmitter, Input, Output
} from '@angular/core'; } from '@angular/core';
import { FileService } from 'common/services/file.service'; import { FileService } from 'common/services/file.service';
import { UIElement } from 'common/models/elements/element'; import { UIElement } from 'common/models/elements/element';
import { TextComponent } from 'common/components/text/text.component';
import { Page } from 'common/models/page';
import { StateVariable } from 'common/models/state-variable'; import { StateVariable } from 'common/models/state-variable';
import { UnitService } from '../../../../../services/unit.service';
import { SelectionService } from '../../../../../services/selection.service';
@Component({ @Component({
selector: 'aspect-button-properties', selector: 'aspect-button-properties',
...@@ -89,73 +84,10 @@ import { SelectionService } from '../../../../../services/selection.service'; ...@@ -89,73 +84,10 @@ import { SelectionService } from '../../../../../services/selection.service';
</mat-form-field> </mat-form-field>
</div> </div>
</fieldset> </fieldset>
<aspect-action-properties
<fieldset> [combinedProperties]="combinedProperties"
<legend>{{'propertiesPanel.action' | translate}}</legend> (updateModel)="updateModel.emit($event)">
<div class="fx-column-start-stretch"> </aspect-action-properties>
<mat-form-field *ngIf="combinedProperties.action !== undefined" appearance="fill">
<mat-label>{{'propertiesPanel.action' | translate }}</mat-label>
<mat-select [value]="combinedProperties.action"
(selectionChange)="updateModel.emit({ property: 'action', value: $event.value })">
<mat-option [value]="null">
{{ 'propertiesPanel.none' | translate }}
</mat-option>
<mat-option *ngFor="let option of ['unitNav', 'pageNav', 'highlightText', 'stateVariableChange']"
[value]="option">
{{ 'propertiesPanel.' + option | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<ng-container *ngIf="combinedProperties.action === 'stateVariableChange'">
<aspect-action-param-state-variable
*ngIf="unitService.unit.stateVariables.length"
[stateVariableIds]="unitService.unit.stateVariables | getStateVariableIds"
[stateVariable]="combinedProperties.actionParam ?
$any(combinedProperties.actionParam) :
{ id: unitService.unit.stateVariables[0].id, value: '' }"
(stateVariableChange)="updateModel.emit({ property: 'actionParam', value: $event })">
</aspect-action-param-state-variable>
<p *ngIf="!unitService.unit.stateVariables.length">{{'propertiesPanel.addStateVariables' | translate}}</p>
</ng-container>
<mat-form-field *ngIf="combinedProperties.action !== 'stateVariableChange'"
appearance="fill">
<mat-label>{{'propertiesPanel.actionParam' | translate }}</mat-label>
<mat-select [disabled]="combinedProperties.action === null"
[value]="combinedProperties.actionParam"
[matTooltipDisabled]="combinedProperties.action !== 'pageNav'"
[matTooltip]="'propertiesPanel.pageNavSelectionHint' | translate"
(selectionChange)="updateModel.emit({ property: 'actionParam', value: $event.value })">
<ng-container *ngIf="combinedProperties.action === 'pageNav'">
<ng-container *ngFor="let page of (unitService.unit.pages | scrollPages); index as i">
<mat-option *ngIf="(unitService.unit.pages | scrollPageIndex: selectionService.selectedPageIndex) !== i"
[value]="i">
{{'page' | translate}} {{i + 1}}
</mat-option>
</ng-container>
</ng-container>
<ng-container *ngIf="combinedProperties.action === 'unitNav'">
<mat-option *ngFor="let option of [undefined, 'previous', 'next', 'first', 'last', 'end']"
[value]="option">
{{ 'propertiesPanel.' + option | translate }}
</mat-option>
</ng-container>
<ng-container *ngIf="combinedProperties.action === 'highlightText'">
<mat-option *ngFor="let option of (textComponents | getAnchorIds) "
[value]="option">
{{ option }}
</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
</div>
</fieldset>
</ng-container> </ng-container>
`, `,
styles: [` styles: [`
...@@ -196,14 +128,8 @@ export class ButtonPropertiesComponent { ...@@ -196,14 +128,8 @@ export class ButtonPropertiesComponent {
property: string; value: string | number | boolean | StateVariable | null, isInputValid?: boolean | null property: string; value: string | number | boolean | StateVariable | null, isInputValid?: boolean | null
}>(); }>();
hoveringImage = false;
textComponents: { [id: string]: TextComponent } = {};
checked = false; checked = false;
constructor(public unitService: UnitService, public selectionService: SelectionService) {
this.textComponents = TextComponent.textComponents;
}
async loadImage(): Promise<void> { async loadImage(): Promise<void> {
this.updateModel.emit({ property: 'imageSrc', value: await FileService.loadImage() }); this.updateModel.emit({ property: 'imageSrc', value: await FileService.loadImage() });
} }
...@@ -212,31 +138,3 @@ export class ButtonPropertiesComponent { ...@@ -212,31 +138,3 @@ export class ButtonPropertiesComponent {
this.updateModel.emit({ property: 'imageSrc', value: null }); this.updateModel.emit({ property: 'imageSrc', value: null });
} }
} }
@Pipe({
name: 'getAnchorIds'
})
export class GetAnchorIdsPipe implements PipeTransform {
// There can be multiple elements with the same data-anchor-id,
// since a selected range can include multiple HTMLElements.
// The first element is filtered out for display in the properties panel.
transform(textComponents: { [id: string]: TextComponent }): string[] {
return Object.values(textComponents)
.map(textComponent => Array.from(textComponent.textContainerRef.nativeElement.querySelectorAll('aspect-anchor'))
.map(anchor => (anchor as Element).getAttribute('data-anchor-id'))
.filter((anchorId, index, anchorIds) => anchorIds.indexOf(anchorId) === index) as string[]
).flat();
}
}
@Pipe({
name: 'scrollPageIndex'
})
export class ScrollPageIndexPipe implements PipeTransform {
transform(pages: Page[], index: number): number | null {
if (pages.find((page: Page): boolean => page.alwaysVisible)) {
return index - 1;
}
return index;
}
}
import { Pipe, PipeTransform } from '@angular/core';
import { StateVariable } from 'common/models/state-variable';
@Pipe({
name: 'getStateVariableIds'
})
export class GetStateVariableIdsPipe implements PipeTransform {
transform(stateVariables: StateVariable[]): string[] {
return stateVariables.map(stateVariable => stateVariable.id);
}
}
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