diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js
index 6b9fcb4d0..b072231ea 100644
--- a/src/Squidex/app-config/webpack.config.js
+++ b/src/Squidex/app-config/webpack.config.js
@@ -1,5 +1,5 @@
const webpack = require('webpack'),
- path = require('path');
+ path = require('path');
const appRoot = path.resolve(__dirname, '..');
@@ -28,12 +28,12 @@ const plugins = {
TsLintPlugin: require('tslint-webpack-plugin')
};
-module.exports = function(env) {
+module.exports = function (env) {
const isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js';
const isProduction = env && env.production;
const isTests = env && env.target === 'tests';
const isCoverage = env && env.coverage;
- const isJit = env && env.jit;
+ const isAot = isProduction;
const config = {
mode: isProduction ? 'production' : 'development',
@@ -56,7 +56,7 @@ module.exports = function(env) {
*
* See: https://webpack.js.org/configuration/resolve/#resolve-extensions
*/
- extensions: ['.js', '.mjs', '.ts', '.css', '.scss'],
+ extensions: ['.ts', '.js', '.mjs', '.css', '.scss'],
modules: [
root('app'),
root('app', 'theme'),
@@ -103,7 +103,7 @@ module.exports = function(env) {
use: [{
loader: 'file-loader?name=[name].[hash].[ext]',
options: {
- outputPath: 'assets',
+ outputPath: 'assets',
/*
* Use custom public path as ./ is not supported by fonts.
*/
@@ -122,9 +122,9 @@ module.exports = function(env) {
test: /\.css$/,
use: [
plugins.MiniCssExtractPlugin.loader,
- {
- loader: 'css-loader'
- }]
+ {
+ loader: 'css-loader'
+ }]
}, {
test: /\.scss$/,
use: [{
@@ -172,7 +172,7 @@ module.exports = function(env) {
failOnError: true
}),
],
-
+
devServer: {
headers: {
'Access-Control-Allow-Origin': '*'
@@ -181,8 +181,6 @@ module.exports = function(env) {
}
};
- console.log(JSON.stringify(config, null, 2));
-
if (!isTests) {
/**
* The entry point for the bundle. Our Angular app.
@@ -202,16 +200,16 @@ module.exports = function(env) {
* See: https://webpack.js.org/configuration/output/#output-path
*/
path: root('wwwroot/build/'),
-
+
publicPath: './build/',
-
+
/**
* Specifies the name of each output file on disk.
*
* See: https://webpack.js.org/configuration/output/#output-filename
*/
filename: '[name].js',
-
+
/**
* The filename of non-entry chunks as relative path inside the output.path directory.
*
@@ -222,7 +220,7 @@ module.exports = function(env) {
} else {
config.output = {
filename: '[name].js',
-
+
/**
* Set the public path, because we are running the website from another port (5000).
*/
@@ -258,6 +256,15 @@ module.exports = function(env) {
waitForLinting: isProduction
})
);
+
+ config.plugins.push(
+ new plugins.NgToolsWebpack.AngularCompilerPlugin({
+ entryModule: 'app/app.module#AppModule',
+ sourceMap: !isProduction,
+ skipSourceGeneration: !isAot,
+ tsConfigPath: './tsconfig.json'
+ })
+ );
}
if (isProduction) {
@@ -280,18 +287,12 @@ module.exports = function(env) {
};
config.performance = {
- hints: false
+ hints: false
};
}
- if (!isCoverage) {
- config.module.rules.push({
- test: /\.ts$/,
- use: [{
- loader: 'awesome-typescript-loader', options: { useCache: true, useBabel: true }
- }]
- })
- } else {
+ if (isCoverage) {
+ // Do not instrument tests.
config.module.rules.push({
test: /\.ts$/,
use: [{
@@ -300,7 +301,7 @@ module.exports = function(env) {
include: [/\.(e2e|spec)\.ts$/],
});
- // Use instrument loader for all normal builds.
+ // Use instrument loader for all normal files.
config.module.rules.push({
test: /\.ts$/,
use: [{
@@ -310,6 +311,13 @@ module.exports = function(env) {
}],
exclude: [/\.(e2e|spec)\.ts$/]
});
+ } else {
+ config.module.rules.push({
+ test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
+ use: [{
+ loader: plugins.NgToolsWebpack.NgToolsLoader
+ }]
+ })
}
if (isProduction) {
@@ -322,11 +330,11 @@ module.exports = function(env) {
*/
use: [
plugins.MiniCssExtractPlugin.loader,
- {
- loader: 'css-loader'
- }, {
- loader: 'sass-loader'
- }],
+ {
+ loader: 'css-loader'
+ }, {
+ loader: 'sass-loader'
+ }],
/*
* Do not include component styles.
*/
@@ -349,23 +357,5 @@ module.exports = function(env) {
});
}
- if (!isJit) {
- config.module.rules.push({
- test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
- use: [{
- loader: '@ngtools/webpack'
- }]
- });
-
- config.plugins.push(
- new plugins.NgToolsWebpack.AngularCompilerPlugin({
- entryModule: 'app/app.module#AppModule',
- sourceMap: !isProduction,
- skipSourceGeneration: false,
- tsConfigPath: './tsconfig.json'
- })
- );
- }
-
return config;
};
\ No newline at end of file
diff --git a/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html b/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html
index 3a6b20f9f..70f05540d 100644
--- a/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html
+++ b/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html
@@ -2,8 +2,10 @@
+ (ngModelChange)="changeColor($event)"
+ [disabled]="step.isLocked">
@@ -20,18 +22,22 @@
-
+
-
+
-
@@ -42,17 +48,15 @@
-
+
-
- {{target.name}}
-
+ {{target.name}}
-
- Add Transition
+
+
diff --git a/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss b/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss
index 415e44a21..a51dd500f 100644
--- a/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss
+++ b/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss
@@ -12,6 +12,10 @@
display: inline-block;
}
+.dashed {
+ border-style: dashed;
+}
+
.transition {
& {
padding-left: 1rem;
@@ -19,6 +23,13 @@
margin-bottom: .5rem;
line-height: 2rem;
}
+
+ &-to {
+ padding: .5rem .75rem;
+ background: transparent;
+ border: 1px solid transparent;
+ line-height: 1.2rem;
+ }
}
.step {
diff --git a/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts b/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts
index 4da32e3c5..afbb45169 100644
--- a/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts
+++ b/src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts
@@ -27,6 +27,9 @@ export class WorkflowStepComponent implements OnChanges {
@Input()
public step: WorkflowStep;
+ @Output()
+ public transitionAdd = new EventEmitter();
+
@Output()
public transitionRemove = new EventEmitter();
@@ -39,13 +42,17 @@ export class WorkflowStepComponent implements OnChanges {
@Output()
public remove = new EventEmitter();
+ public onBlur = { updateOn: 'blur' };
+
public openSteps: WorkflowStep[];
+ public openStep: WorkflowStep;
public transitions: WorkflowTransitionView[];
public ngOnChanges(changes: SimpleChanges) {
- if (changes['workflow'] || changes['step']) {
+ if (changes['workflow'] || changes['step'] || false) {
this.openSteps = this.workflow.getOpenSteps(this.step);
+ this.openStep = this.openSteps[0];
this.transitions = this.workflow.getTransitions(this.step);
}
diff --git a/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html b/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html
index 31430d112..c5782052b 100644
--- a/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html
+++ b/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html
@@ -20,12 +20,14 @@
-
+ (remove)="removeStep(step)"
+ (transitionAdd)="addTransiton(step, $event)"
+ (transitionRemove)="removeTransition(step, $event)"
+ (update)="updateStep(step, $event)">
diff --git a/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts b/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts
index 897d5c6f0..272a2852b 100644
--- a/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts
+++ b/src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts
@@ -5,12 +5,13 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import {
WorkflowDto,
WorkflowStep,
- WorkflowStepValues
+ WorkflowStepValues,
+ WorkflowTransition
} from '@app/shared';
@Component({
@@ -18,8 +19,12 @@ import {
styleUrls: ['./workflows-page.component.scss'],
templateUrl: './workflows-page.component.html'
})
-export class WorkflowsPageComponent {
- public workflow = new WorkflowDto().setStep('Published', { color: 'green' });
+export class WorkflowsPageComponent implements OnInit {
+ public workflow: WorkflowDto;
+
+ public ngOnInit() {
+ this.workflow = new WorkflowDto().setStep('Published', { color: 'green', isLocked: true });
+ }
public reload() {
return;
@@ -33,16 +38,28 @@ export class WorkflowsPageComponent {
this.workflow = this.workflow.setStep(`Step${this.workflow.steps.length + 1}`, {});
}
+ public addTransiton(from: WorkflowStep, to: WorkflowStep) {
+ this.workflow = this.workflow.setTransition(from.name, to.name, {});
+ }
+
+ public removeTransition(from: WorkflowStep, transition: WorkflowTransition) {
+ this.workflow = this.workflow.removeTransition(from.name, transition.to);
+ }
+
public updateStep(step: WorkflowStep, values: WorkflowStepValues) {
- // this.workflow = this.workflow.setStep(step.name, values);
+ this.workflow = this.workflow.setStep(step.name, values);
}
public renameStep(step: WorkflowStep, newName: string) {
- // this.workflow = this.workflow.renameStep(step.name, newName);
+ this.workflow = this.workflow.renameStep(step.name, newName);
}
public removeStep(step: WorkflowStep) {
- // this.workflow = this.workflow.removeStep(step.name);
+ this.workflow = this.workflow.removeStep(step.name);
+ }
+
+ public trackByStep(index: number, step: WorkflowStep) {
+ return step.name;
}
}
diff --git a/src/Squidex/app/framework/angular/forms/color-picker.component.html b/src/Squidex/app/framework/angular/forms/color-picker.component.html
index bb94aa157..54db50895 100644
--- a/src/Squidex/app/framework/angular/forms/color-picker.component.html
+++ b/src/Squidex/app/framework/angular/forms/color-picker.component.html
@@ -5,21 +5,23 @@
[style.color]="snapshot.foreground"
[placeholder]="placeholder"
[ngModel]="snapshot.value"
- (ngModelChange)="writeValue($event)"
- (focus)="modal.show()" (blur)="blur()" />
+ (ngModelChange)="updateValue($event)"
+ (focus)="focus()" (blur)="blur()" />
-
+
-
-
+
+ (colorPickerChange)="updateValue($event)">
\ No newline at end of file
diff --git a/src/Squidex/app/framework/angular/forms/color-picker.component.ts b/src/Squidex/app/framework/angular/forms/color-picker.component.ts
index 18d55706f..8b6dc1172 100644
--- a/src/Squidex/app/framework/angular/forms/color-picker.component.ts
+++ b/src/Squidex/app/framework/angular/forms/color-picker.component.ts
@@ -32,31 +32,76 @@ interface State {
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ColorPickerComponent extends StatefulControlComponent
{
+ private wasOpen = false;
+
@Input()
public placeholder = '';
@Input()
public mode: 'Input' | 'Circle' = 'Input';
+ @Input()
+ public set disabled(value: boolean) {
+ super.setDisabledState(value);
+ }
+
public modal = new ModalModel();
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, { foreground: 'black' });
+
+ this.modal.isOpen.subscribe(open => {
+ if (open) {
+ this.wasOpen = true;
+ } else {
+ if (this.wasOpen) {
+ this.callTouched();
+ }
+
+ this.wasOpen = false;
+ }
+ });
}
public writeValue(obj: any) {
- let foreground = 'black';
+ const previousColor = this.snapshot.value;
+
+ if (previousColor !== obj) {
+ let foreground = 'black';
- if (MathHelper.toLuminance(MathHelper.parseColor(obj)!) < .5) {
- foreground = 'white';
+ if (MathHelper.toLuminance(MathHelper.parseColor(obj)!) < .5) {
+ foreground = 'white';
+ }
+
+ this.next(s => ({ ...s, value: obj, foreground }));
}
+ }
- this.next(s => ({ ...s, value: obj, foreground }));
+ public focus() {
+ if (this.snapshot.isDisabled) {
+ return;
+ }
- this.callChange(obj);
+ this.modal.show();
}
public blur() {
+ if (this.snapshot.isDisabled) {
+ return;
+ }
+
this.callTouched();
}
+
+ public updateValue(value: string) {
+ if (this.snapshot.isDisabled) {
+ return;
+ }
+
+ if (this.snapshot.value !== value) {
+ this.callChange(value);
+
+ this.writeValue(value);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Squidex/app/framework/angular/forms/dropdown.component.html b/src/Squidex/app/framework/angular/forms/dropdown.component.html
index 14acdfbba..b73df3c90 100644
--- a/src/Squidex/app/framework/angular/forms/dropdown.component.html
+++ b/src/Squidex/app/framework/angular/forms/dropdown.component.html
@@ -6,20 +6,20 @@
autocapitalize="off">
- {{snapshot.selectedItem}}
+ {{snapshot.selectedItem}}
-
+
-
+
- {{item}}
+ {{item}}
-
+
diff --git a/src/Squidex/app/framework/angular/forms/dropdown.component.scss b/src/Squidex/app/framework/angular/forms/dropdown.component.scss
index 2b7ec23c4..a601a86ba 100644
--- a/src/Squidex/app/framework/angular/forms/dropdown.component.scss
+++ b/src/Squidex/app/framework/angular/forms/dropdown.component.scss
@@ -26,13 +26,18 @@ $color-input-disabled: #eef1f4;
.control-dropdown-item {
@include absolute(0, 1rem, 0, 0);
pointer-events: none;
+ position: absolute;
+ line-height: 1.2rem;
}
.icon-caret-down {
@include absolute(30%, .4rem, auto, auto);
- cursor: pointer;
font-size: .9rem;
font-weight: normal;
pointer-events: none;
}
+
+ .form-control {
+ cursor: default;
+ }
}
\ No newline at end of file
diff --git a/src/Squidex/app/framework/angular/forms/dropdown.component.ts b/src/Squidex/app/framework/angular/forms/dropdown.component.ts
index bdc7414d6..ea366b827 100644
--- a/src/Squidex/app/framework/angular/forms/dropdown.component.ts
+++ b/src/Squidex/app/framework/angular/forms/dropdown.component.ts
@@ -35,9 +35,8 @@ export class DropdownComponent extends StatefulControlComponent
im
public dropdown = new ModalModel();
- public selectionTemplate: TemplateRef;
-
- public itemTemplate: TemplateRef;
+ public templateSelection: TemplateRef;
+ public templateItem: TemplateRef;
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {
@@ -48,16 +47,20 @@ export class DropdownComponent extends StatefulControlComponent im
public ngAfterContentInit() {
if (this.templates.length === 1) {
- this.itemTemplate = this.selectionTemplate = this.templates.first;
+ this.templateItem = this.templateSelection = this.templates.first;
} else {
this.templates.forEach(template => {
if (template.name === 'selection') {
- this.selectionTemplate = template;
+ this.templateSelection = template;
} else {
- this.itemTemplate = template;
+ this.templateItem = template;
}
});
}
+
+ if (this.templateItem) {
+ this.detectChanges();
+ }
}
public writeValue(obj: any) {
diff --git a/src/Squidex/app/framework/angular/panel.component.ts b/src/Squidex/app/framework/angular/panel.component.ts
index 46f5cd838..7abdf2a00 100644
--- a/src/Squidex/app/framework/angular/panel.component.ts
+++ b/src/Squidex/app/framework/angular/panel.component.ts
@@ -89,17 +89,25 @@ export class PanelComponent implements AfterViewInit, OnDestroy, OnInit {
if (this.styleWidth !== size) {
this.styleWidth = size;
- this.renderer.setStyle(this.panel.nativeElement, 'width', size);
- this.renderer.setStyle(this.panel.nativeElement, 'minWidth', this.minWidth);
- this.renderWidth = this.panel.nativeElement.offsetWidth;
+ const element = this.panel ? this.panel.nativeElement : undefined;
+
+ if (element) {
+ this.renderer.setStyle(element, 'width', size);
+ this.renderer.setStyle(element, 'minWidth', this.minWidth);
+ this.renderWidth = element.offsetWidth;
+ }
}
}
public arrange(left: any, layer: any) {
- this.renderer.setStyle(this.panel.nativeElement, 'top', '0px');
- this.renderer.setStyle(this.panel.nativeElement, 'left', left);
- this.renderer.setStyle(this.panel.nativeElement, 'bottom', '0px');
- this.renderer.setStyle(this.panel.nativeElement, 'position', 'absolute');
- this.renderer.setStyle(this.panel.nativeElement, 'z-index', layer);
+ const element = this.panel ? this.panel.nativeElement : undefined;
+
+ if (element) {
+ this.renderer.setStyle(element, 'top', '0px');
+ this.renderer.setStyle(element, 'left', left);
+ this.renderer.setStyle(element, 'bottom', '0px');
+ this.renderer.setStyle(element, 'position', 'absolute');
+ this.renderer.setStyle(element, 'z-index', layer);
+ }
}
}
\ No newline at end of file
diff --git a/src/Squidex/app/shared/services/workflows.service.ts b/src/Squidex/app/shared/services/workflows.service.ts
index 51ec23970..f5a98ba83 100644
--- a/src/Squidex/app/shared/services/workflows.service.ts
+++ b/src/Squidex/app/shared/services/workflows.service.ts
@@ -5,7 +5,11 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
-import { Model, ResourceLinks } from '@app/framework';
+import {
+ compareStringsAsc,
+ Model,
+ ResourceLinks
+} from '@app/framework';
export class WorkflowDto extends Model {
public readonly _links: ResourceLinks;
@@ -20,8 +24,12 @@ export class WorkflowDto extends Model {
this._links = links;
}
+ public onCloned() {
+ this.steps.sort((a, b) => compareStringsAsc(a.name, b.name));
+ }
+
public getOpenSteps(step: WorkflowStep) {
- return this.steps.filter(x => !this.transitions.find(y => y.from === step.name && y.to === x.name));
+ return this.steps.filter(x => x.name !== step.name && !this.transitions.find(y => y.from === step.name && y.to === x.name));
}
public getTransitions(step: WorkflowStep): WorkflowTransitionView[] {