Browse Source

Test

pull/379/head
Sebastian Stehle 7 years ago
parent
commit
2b030de8e0
  1. 1
      src/Squidex/app/features/settings/declarations.ts
  2. 4
      src/Squidex/app/features/settings/module.ts
  3. 49
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html
  4. 23
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss
  5. 20
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts
  6. 52
      src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.html
  7. 6
      src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.scss
  8. 84
      src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.ts
  9. 4
      src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html
  10. 26
      src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts
  11. 8
      src/Squidex/app/framework/angular/forms/focus-on-init.directive.ts
  12. 36
      src/Squidex/app/shared/services/workflows.service.ts

1
src/Squidex/app/features/settings/declarations.ts

@ -19,6 +19,7 @@ export * from './pages/plans/plans-page.component';
export * from './pages/roles/role.component';
export * from './pages/roles/roles-page.component';
export * from './pages/workflows/workflow-step.component';
export * from './pages/workflows/workflow-transition.component';
export * from './pages/workflows/workflows-page.component';
export * from './settings-area.component';

4
src/Squidex/app/features/settings/module.ts

@ -32,7 +32,8 @@ import {
RolesPageComponent,
SettingsAreaComponent,
WorkflowsPageComponent,
WorkflowStepComponent
WorkflowStepComponent,
WorkflowTransitionComponent
} from './declarations';
const routes: Routes = [
@ -204,6 +205,7 @@ const routes: Routes = [
RolesPageComponent,
SettingsAreaComponent,
WorkflowsPageComponent,
WorkflowTransitionComponent,
WorkflowStepComponent
]
})

49
src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html

@ -25,37 +25,13 @@
</div>
</div>
<div class="row transition no-gutters" *ngFor="let transition of transitions">
<div class="col-auto">
<i class="icon-arrow-right text-decent"></i>
</div>
<div class="col col-step">
<div class="transition-to">
<div class="color-circle" [style.background]="transition.step.color"></div> {{transition.to}}
</div>
</div>
<div class="col-auto col-label">
<span class="text-decent">when</span>
</div>
<div class="col">
<button class="btn btn-block btn-outline-secondary dashed">
Add Expression
</button>
</div>
<div class="col-auto col-label">
<span class="text-decent">for</span>
</div>
<div class="col">
<button class="btn btn-block btn-outline-secondary dashed">
Add Role
</button>
</div>
<div class="col-auto pl-2">
<button type="button" class="btn btn-text-danger" (click)="transitionRemove.emit(transition)">
<i class="icon-bin2"></i>
</button>
</div>
</div>
<div class="step-inner">
<sqx-workflow-transition *ngFor="let transition of transitions; trackBy: trackByTransition"
[transition]="transition"
[roles]="roles"
(remove)="transitionRemove.emit(transition)"
(update)="changeTransition(transition, $event)">
</sqx-workflow-transition>
<div class="row transition no-gutters" *ngIf="openSteps.length > 0">
<div class="col-auto">
@ -74,4 +50,15 @@
</button>
</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="preventUpdates_{{step.name}}"
[ngModel]="step.noUpdate"
(ngModelChange)="changeNoUpdate($event)" />
<label class="form-check-label" for="preventUpdates_{{step.name}}">
Prevent updates
</label>
</div>
</div>
</div>

23
src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss

@ -1,6 +1,7 @@
@import '_vars';
@import '_mixins';
:host ::ng-deep {
.color {
line-height: 2.8rem;
}
@ -12,13 +13,18 @@
display: inline-block;
}
.dashed {
border-style: dashed;
.col-label {
padding: 0 .5rem;
}
.col-step {
min-width: 10rem;
max-width: 10rem;
padding-left: .5rem;
}
.transition {
& {
padding-left: 1rem;
margin-top: .25rem;
margin-bottom: .5rem;
line-height: 2.2rem;
@ -30,19 +36,14 @@
line-height: 1.2rem;
}
}
}
.step {
& {
margin-bottom: 1rem;
}
}
.col-label {
padding: 0 .5rem;
&-inner {
padding-left: 1rem;
}
.col-step {
min-width: 10rem;
max-width: 10rem;
padding-left: .5rem;
}

20
src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts

@ -8,10 +8,12 @@
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import {
RoleDto,
WorkflowDto,
WorkflowStep,
WorkflowStepValues,
WorkflowTransition,
WorkflowTransitionValues,
WorkflowTransitionView
} from '@app/shared';
@ -27,12 +29,18 @@ export class WorkflowStepComponent implements OnChanges {
@Input()
public step: WorkflowStep;
@Input()
public roles: RoleDto[];
@Output()
public transitionAdd = new EventEmitter<WorkflowStep>();
@Output()
public transitionRemove = new EventEmitter<WorkflowTransition>();
@Output()
public transitionUpdate = new EventEmitter<{ transition: WorkflowTransition, values: WorkflowTransitionValues }>();
@Output()
public update = new EventEmitter<WorkflowStepValues>();
@ -58,6 +66,10 @@ export class WorkflowStepComponent implements OnChanges {
}
}
public changeTransition(transition: WorkflowTransition, values: WorkflowTransitionValues) {
this.transitionUpdate.emit({ transition, values });
}
public changeName(name: string) {
this.rename.emit(name);
}
@ -65,5 +77,13 @@ export class WorkflowStepComponent implements OnChanges {
public changeColor(color: string) {
this.update.emit({ color });
}
public changeNoUpdate(noUpdate: boolean) {
this.update.emit({ noUpdate });
}
public trackByTransition(index: number, transition: WorkflowTransition) {
return transition.to;
}
}

52
src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.html

@ -0,0 +1,52 @@
<div class="row transition no-gutters">
<div class="col-auto">
<i class="icon-arrow-right text-decent"></i>
</div>
<div class="col col-step">
<div class="transition-to">
<div class="color-circle" [style.background]="transition.step.color"></div> {{transition.to}}
</div>
</div>
<div class="col-auto col-label">
<span class="text-decent">when</span>
</div>
<div class="col">
<ng-container *ngIf="elementsActive['expression']; else noExpression">
<input class="form-control" sqxFocusOnInit (focus)="focusElement('expression')" (blur)="blurElement('expression')" spellcheck="false"
[ngModelOptions]="onBlur"
[ngModel]="transition.expression"
(ngModelChange)="changeExpression($event)" />
</ng-container>
<ng-template #noExpression>
<button class="btn btn-block btn-outline-secondary dashed" (click)="showElement('expression')">
Add Expression
</button>
</ng-template>
</div>
<div class="col-auto col-label">
<span class="text-decent">for</span>
</div>
<div class="col">
<ng-container *ngIf="elementsActive['role']; else noRole">
<select class="form-control" sqxFocusOnInit (focus)="focusElement('role')" (blur)="blurElement('role')"
[ngModelOptions]="onBlur"
[ngModel]="transition.role"
(ngModelChange)="changeRole($event)">
<option *ngFor="let role of roles; trackBy: trackByRole" [ngValue]="role.name">{{role.name}}</option>
<option [ngValue]="null">- All Roles -</option>
</select>
</ng-container>
<ng-template #noRole>
<button class="btn btn-block btn-outline-secondary dashed" (click)="showElement('role')">
Add Role
</button>
</ng-template>
</div>
<div class="col-auto pl-2">
<button type="button" class="btn btn-text-danger" (click)="remove.emit()">
<i class="icon-bin2"></i>
</button>
</div>
</div>

6
src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.scss

@ -0,0 +1,6 @@
@import '_vars';
@import '_mixins';
.dashed {
border-style: dashed;
}

84
src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.ts

@ -0,0 +1,84 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import {
RoleDto,
WorkflowTransitionValues,
WorkflowTransitionView
} from '@app/shared';
@Component({
selector: 'sqx-workflow-transition',
styleUrls: ['./workflow-transition.component.scss'],
templateUrl: './workflow-transition.component.html'
})
export class WorkflowTransitionComponent implements OnChanges {
@Input()
public transition: WorkflowTransitionView;
@Input()
public roles: RoleDto[];
@Output()
public update = new EventEmitter<WorkflowTransitionValues>();
@Output()
public remove = new EventEmitter();
public elementsActive: { [name: string]: boolean } = {};
public elementsFocused: { [name: string]: boolean } = {};
public elementsValid: { [name: string]: boolean } = {};
public onBlur = { updateOn: 'blur' };
public ngOnChanges(changes: SimpleChanges) {
if (changes['transition']) {
if (this.transition.expression) {
this.elementsValid['expression'] = true;
this.elementsActive['expression'] = true;
}
if (this.transition.role) {
this.elementsValid['role'] = true;
this.elementsActive['role'] = true;
}
}
}
public changeExpression(expression: string) {
this.update.emit({ expression });
}
public changeRole(role: string) {
this.update.emit({ role });
}
public showElement(name: string) {
this.elementsActive[name] = true;
}
public focusElement(name: string) {
this.elementsFocused[name] = true;
}
public blurElement(name: string) {
this.elementsFocused[name] = false;
setTimeout(() => {
if (!this.elementsFocused[name] && !this.elementsValid[name]) {
this.elementsActive[name] = false;
}
}, 2000);
}
public trackByRole(index: number, role: RoleDto) {
return role.name;
}
}

4
src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html

@ -20,15 +20,19 @@
</ng-container>
<ng-container content>
<ng-container *ngIf="rolesState.roles | async; let roles">
<sqx-workflow-step *ngFor="let step of workflow.steps; trackBy: trackByStep"
[workflow]="workflow"
[step]="step"
[roles]="roles"
(rename)="renameStep(step, $event)"
(remove)="removeStep(step)"
(transitionAdd)="addTransiton(step, $event)"
(transitionRemove)="removeTransition(step, $event)"
(transitionUpdate)="updateTransition($event)"
(update)="updateStep(step, $event)">
</sqx-workflow-step>
</ng-container>
<button class="btn btn-success" (click)="addStep()">
Add Step

26
src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts

@ -9,10 +9,12 @@ import { Component, OnInit } from '@angular/core';
import {
MathHelper,
RolesState,
WorkflowDto,
WorkflowStep,
WorkflowStepValues,
WorkflowTransition
WorkflowTransition,
WorkflowTransitionValues
} from '@app/shared';
@Component({
@ -25,8 +27,24 @@ export class WorkflowsPageComponent implements OnInit {
public workflow: WorkflowDto;
constructor(
public readonly rolesState: RolesState
) {
}
public ngOnInit() {
this.workflow = new WorkflowDto().setStep('Published', { color: 'green', isLocked: true });
this.rolesState.load();
this.workflow =
new WorkflowDto()
.setStep('Archived', { color: '#eb3142', noUpdate: true })
.setStep('Draft', { color: '#8091a5' })
.setStep('Published', { color: '#4bb958', isLocked: true })
.setTransition('Archived', 'Draft')
.setTransition('Draft', 'Archived')
.setTransition('Draft', 'Published')
.setTransition('Published', 'Draft')
.setTransition('Published', 'Archived');
}
public reload() {
@ -51,6 +69,10 @@ export class WorkflowsPageComponent implements OnInit {
this.workflow = this.workflow.removeTransition(from.name, transition.to);
}
public updateTransition(update: { transition: WorkflowTransition, values: WorkflowTransitionValues }) {
this.workflow = this.workflow.setTransition(update.transition.from, update.transition.to, update.values);
}
public updateStep(step: WorkflowStep, values: WorkflowStepValues) {
this.workflow = this.workflow.setStep(step.name, values);
}

8
src/Squidex/app/framework/angular/forms/focus-on-init.directive.ts

@ -17,7 +17,7 @@ export class FocusOnInitDirective implements AfterViewInit {
public select: boolean;
constructor(
private readonly element: ElementRef
private readonly element: ElementRef<HTMLElement>
) {
}
@ -28,8 +28,10 @@ export class FocusOnInitDirective implements AfterViewInit {
}
if (this.select) {
if (Types.isFunction(this.element.nativeElement.select)) {
this.element.nativeElement.select();
const input: HTMLInputElement = <any>this.element.nativeElement;
if (Types.isFunction(input.select)) {
input.select();
}
}
}, 100);

36
src/Squidex/app/shared/services/workflows.service.ts

@ -26,6 +26,8 @@ export class WorkflowDto extends Model<WorkflowDto> {
public onCloned() {
this.steps.sort((a, b) => compareStringsAsc(a.name, b.name));
this.transitions.sort((a, b) => compareStringsAsc(a.to, b.to));
}
public getOpenSteps(step: WorkflowStep) {
@ -41,7 +43,19 @@ export class WorkflowDto extends Model<WorkflowDto> {
}
public setStep(name: string, values: Partial<WorkflowStepValues>) {
const steps = [...this.steps.filter(s => s.name !== name), { name, ...values }];
const found = this.getStep(name);
if (found) {
const { name: _, ...existing } = found;
if (found.isLocked) {
return this;
}
values = { ...values, ...existing };
}
const steps = [...this.steps.filter(s => s !== found), { name, ...values }];
return this.with({ steps });
}
@ -93,29 +107,37 @@ export class WorkflowDto extends Model<WorkflowDto> {
return this.with({ transitions });
}
public setTransition(from: string, to: string, values: Partial<WorkflowTransitionValues>) {
const stepFrom = this.steps.find(s => s.name === from);
public setTransition(from: string, to: string, values?: Partial<WorkflowTransitionValues>) {
const stepFrom = this.getStep(from);
if (!stepFrom) {
return this;
}
const stepTo = this.steps.find(s => s.name === to);
const stepTo = this.getStep(to);
if (!stepTo) {
return this;
}
const transitions = [...this.transitions.filter(t => t.from !== from || t.to !== to), { from, to, ...values }];
const found = this.transitions.find(x => x.from === from && x.to === to);
if (found) {
const { from: _, to: __, ...existing } = found;
values = { ...values, ...existing };
}
const transitions = [...this.transitions.filter(t => t !== found), { from, to, ...values }];
return this.with({ transitions });
}
}
export type WorkflowStepValues = { color?: string; isLocked?: boolean; };
export type WorkflowStepValues = { color?: string; isLocked?: boolean; noUpdate?: boolean; };
export type WorkflowStep = { name: string } & WorkflowStepValues;
export type WorkflowTransitionValues = { expression?: string };
export type WorkflowTransitionValues = { expression?: string; role?: string; };
export type WorkflowTransition = { from: string; to: string } & WorkflowTransitionValues;
export type WorkflowTransitionView = { step: WorkflowStep } & WorkflowTransition;
Loading…
Cancel
Save