Browse Source

Temp

pull/372/head
Sebastian Stehle 7 years ago
parent
commit
2a04e6cc3a
  1. 13
      src/Squidex/app-config/webpack.config.js
  2. 2
      src/Squidex/app/features/settings/declarations.ts
  3. 70
      src/Squidex/app/features/settings/module.ts
  4. 28
      src/Squidex/app/features/settings/pages/clients/client.component.html
  5. 31
      src/Squidex/app/features/settings/pages/clients/client.component.scss
  6. 46
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  7. 59
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.html
  8. 28
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.scss
  9. 62
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts
  10. 35
      src/Squidex/app/features/settings/pages/workflows/workflows-page.component.html
  11. 2
      src/Squidex/app/features/settings/pages/workflows/workflows-page.component.scss
  12. 48
      src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts
  13. 6
      src/Squidex/app/features/settings/settings-area.component.html
  14. 15
      src/Squidex/app/framework/angular/forms/autocomplete.component.ts
  15. 22
      src/Squidex/app/framework/angular/forms/color-picker.component.html
  16. 9
      src/Squidex/app/framework/angular/forms/color-picker.component.scss
  17. 3
      src/Squidex/app/framework/angular/forms/color-picker.component.ts
  18. 26
      src/Squidex/app/framework/angular/forms/dropdown.component.html
  19. 38
      src/Squidex/app/framework/angular/forms/dropdown.component.scss
  20. 130
      src/Squidex/app/framework/angular/forms/dropdown.component.ts
  21. 23
      src/Squidex/app/framework/angular/forms/editable-title.component.html
  22. 33
      src/Squidex/app/framework/angular/forms/editable-title.component.scss
  23. 72
      src/Squidex/app/framework/angular/forms/editable-title.component.ts
  24. 18
      src/Squidex/app/framework/angular/forms/tag-editor.component.ts
  25. 2
      src/Squidex/app/framework/declarations.ts
  26. 1
      src/Squidex/app/framework/internal.ts
  27. 6
      src/Squidex/app/framework/module.ts
  28. 15
      src/Squidex/app/framework/utils/keys.ts
  29. 1
      src/Squidex/app/shared/services/apps.service.ts
  30. 14
      src/Squidex/app/shared/services/workflows.service.ts
  31. 18
      src/Squidex/app/theme/icomoon/demo.html
  32. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.eot
  33. 1
      src/Squidex/app/theme/icomoon/fonts/icomoon.svg
  34. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.ttf
  35. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.woff
  36. 2
      src/Squidex/app/theme/icomoon/selection.json
  37. 13
      src/Squidex/app/theme/icomoon/style.css

13
src/Squidex/app-config/webpack.config.js

@ -31,7 +31,7 @@ const plugins = {
module.exports = function(env) { module.exports = function(env) {
const isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js'; const isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js';
const isProduction = env && env.production; const isProduction = env && env.production;
const isTesting = env && env.target === 'tests'; const isTests = env && env.target === 'tests';
const isCoverage = env && env.coverage; const isCoverage = env && env.coverage;
const isJit = env && env.jit; const isJit = env && env.jit;
@ -43,7 +43,7 @@ module.exports = function(env) {
* *
* See: https://webpack.js.org/configuration/devtool/ * See: https://webpack.js.org/configuration/devtool/
*/ */
devtool: isProduction ? undefined : (isTesting ? 'inline-source-map' : 'source-map'), devtool: isProduction ? false : (isTests ? 'inline-source-map' : 'source-map'),
/** /**
* Options affecting the resolving of modules. * Options affecting the resolving of modules.
@ -181,7 +181,9 @@ module.exports = function(env) {
} }
}; };
if (!isTesting) { console.log(JSON.stringify(config, null, 2));
if (!isTests) {
/** /**
* The entry point for the bundle. Our Angular app. * The entry point for the bundle. Our Angular app.
* *
@ -286,9 +288,8 @@ module.exports = function(env) {
config.module.rules.push({ config.module.rules.push({
test: /\.ts$/, test: /\.ts$/,
use: [{ use: [{
loader: 'awesome-typescript-loader' loader: 'awesome-typescript-loader', options: { useCache: true, useBabel: true }
}], }]
exclude: [/node_modules/]
}) })
} else { } else {
config.module.rules.push({ config.module.rules.push({

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

@ -18,5 +18,7 @@ export * from './pages/patterns/patterns-page.component';
export * from './pages/plans/plans-page.component'; export * from './pages/plans/plans-page.component';
export * from './pages/roles/role.component'; export * from './pages/roles/role.component';
export * from './pages/roles/roles-page.component'; export * from './pages/roles/roles-page.component';
export * from './pages/workflows/workflow-step.component';
export * from './pages/workflows/workflows-page.component';
export * from './settings-area.component'; export * from './settings-area.component';

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

@ -30,7 +30,9 @@ import {
PlansPageComponent, PlansPageComponent,
RoleComponent, RoleComponent,
RolesPageComponent, RolesPageComponent,
SettingsAreaComponent SettingsAreaComponent,
WorkflowsPageComponent,
WorkflowStepComponent
} from './declarations'; } from './declarations';
const routes: Routes = [ const routes: Routes = [
@ -59,117 +61,121 @@ const routes: Routes = [
] ]
}, },
{ {
path: 'plans', path: 'clients',
component: PlansPageComponent, component: ClientsPageComponent,
children: [ children: [
{ {
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.plan' channel: 'settings.clients'
}
},
{
path: 'help',
component: HelpComponent,
data: {
helpPage: '05-integrated/clients'
} }
} }
] ]
}, },
{ {
path: 'patterns', path: 'contributors',
component: PatternsPageComponent, component: ContributorsPageComponent,
children: [ children: [
{ {
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.patterns' channel: 'settings.contributors'
} }
}, },
{ {
path: 'help', path: 'help',
component: HelpComponent, component: HelpComponent,
data: { data: {
helpPage: '05-integrated/patterns' helpPage: '05-integrated/contributors'
} }
} }
] ]
}, },
{ {
path: 'clients', path: 'languages',
component: ClientsPageComponent, component: LanguagesPageComponent,
children: [ children: [
{ {
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.clients' channel: 'settings.languages'
} }
}, },
{ {
path: 'help', path: 'help',
component: HelpComponent, component: HelpComponent,
data: { data: {
helpPage: '05-integrated/clients' helpPage: '05-integrated/languages'
} }
} }
] ]
}, },
{ {
path: 'contributors', path: 'patterns',
component: ContributorsPageComponent, component: PatternsPageComponent,
children: [ children: [
{ {
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.contributors' channel: 'settings.patterns'
} }
}, },
{ {
path: 'help', path: 'help',
component: HelpComponent, component: HelpComponent,
data: { data: {
helpPage: '05-integrated/contributors' helpPage: '05-integrated/patterns'
} }
} }
] ]
}, },
{ {
path: 'roles', path: 'plans',
component: RolesPageComponent, component: PlansPageComponent,
children: [ children: [
{ {
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.roles' channel: 'settings.plan'
}
},
{
path: 'help',
component: HelpComponent,
data: {
helpPage: '05-integrated/roles'
} }
} }
] ]
}, },
{ {
path: 'languages', path: 'roles',
component: LanguagesPageComponent, component: RolesPageComponent,
children: [ children: [
{ {
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.languages' channel: 'settings.roles'
} }
}, },
{ {
path: 'help', path: 'help',
component: HelpComponent, component: HelpComponent,
data: { data: {
helpPage: '05-integrated/languages' helpPage: '05-integrated/roles'
} }
} }
] ]
},
{
path: 'workflows',
component: WorkflowsPageComponent
} }
] ]
} }
@ -196,7 +202,9 @@ const routes: Routes = [
PlansPageComponent, PlansPageComponent,
RoleComponent, RoleComponent,
RolesPageComponent, RolesPageComponent,
SettingsAreaComponent SettingsAreaComponent,
WorkflowsPageComponent,
WorkflowStepComponent
] ]
}) })
export class SqxFeatureSettingsModule { } export class SqxFeatureSettingsModule { }

28
src/Squidex/app/features/settings/pages/clients/client.component.html

@ -2,27 +2,13 @@
<div class="card-header"> <div class="card-header">
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col col-name"> <div class="col col-name">
<form *ngIf="isRenaming; else noRenaming" class="form-inline" [formGroup]="renameForm.form" (ngSubmit)="rename()"> <div class="row">
<div class="form-group mr-1"> <sqx-editable-title
<sqx-control-errors for="name"></sqx-control-errors> [name]="client.name"
(nameChanged)="rename($event)"
<input type="text" class="form-control client-name form-underlined" formControlName="name" maxlength="20" sqxFocusOnInit (keydown)="onKeyDown($event.keyCode)" /> [disabled]="!client.canUpdate">
</div> </sqx-editable-title>
</div>
<button type="submit" class="btn btn-primary" [disabled]="!renameForm.form.valid || !renameForm.form.dirty">Save</button>
<button type="button" class="btn btn-text-secondary btn-cancel" (click)="toggleRename()">
<i class="icon-close"></i>
</button>
</form>
<ng-template #noRenaming>
<h3 class="client-name" (dblclick)="toggleRename()">
{{client.name}}
</h3>
<i class="client-edit icon-pencil" *ngIf="client.canUpdate" (click)="toggleRename()"></i>
</ng-template>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<button type="button" class="btn btn-primary" (click)="connect()">Connect</button> <button type="button" class="btn btn-primary" (click)="connect()">Connect</button>

31
src/Squidex/app/features/settings/pages/clients/client.component.scss

@ -18,14 +18,6 @@ $color-editor: #eceeef;
} }
} }
.col-name {
&:hover {
.client-edit {
display: inline-block;
}
}
}
.client { .client {
&-info { &-info {
margin: 0; margin: 0;
@ -34,29 +26,6 @@ $color-editor: #eceeef;
&-delete { &-delete {
vertical-align: top; vertical-align: top;
} }
&-edit {
color: $color-border-dark;
display: none;
font-size: .9rem;
font-weight: normal;
padding: .6rem .25rem;
border: 0;
background: transparent;
vertical-align: baseline;
}
&-name {
padding: .375rem 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-size: 1.2rem;
font-weight: normal;
line-height: 1.5rem;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
display: inline-block;
margin: 0;
}
} }
.no-padding { .no-padding {

46
src/Squidex/app/features/settings/pages/clients/client.component.ts

@ -6,7 +6,6 @@
*/ */
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { import {
AccessTokenDto, AccessTokenDto,
@ -17,12 +16,9 @@ import {
ClientsState, ClientsState,
DialogModel, DialogModel,
DialogService, DialogService,
RenameClientForm,
RoleDto RoleDto
} from '@app/shared'; } from '@app/shared';
const ESCAPE_KEY = 27;
@Component({ @Component({
selector: 'sqx-client', selector: 'sqx-client',
styleUrls: ['./client.component.scss'], styleUrls: ['./client.component.scss'],
@ -35,13 +31,9 @@ export class ClientComponent implements OnChanges {
@Input() @Input()
public clientRoles: RoleDto[]; public clientRoles: RoleDto[];
public isRenaming = false;
public connectToken: AccessTokenDto; public connectToken: AccessTokenDto;
public connectDialog = new DialogModel(); public connectDialog = new DialogModel();
public renameForm = new RenameClientForm(this.formBuilder);
public connectHttpText: string; public connectHttpText: string;
public connectCLINixText: string; public connectCLINixText: string;
public connectCLIWinText: string; public connectCLIWinText: string;
@ -53,15 +45,12 @@ export class ClientComponent implements OnChanges {
private readonly apiUrl: ApiUrlConfig, private readonly apiUrl: ApiUrlConfig,
private readonly clientsService: ClientsService, private readonly clientsService: ClientsService,
private readonly clientsState: ClientsState, private readonly clientsState: ClientsState,
private readonly dialogs: DialogService, private readonly dialogs: DialogService
private readonly formBuilder: FormBuilder
) { ) {
} }
public ngOnChanges(changes: SimpleChanges) { public ngOnChanges(changes: SimpleChanges) {
if (changes['client']) { if (changes['client']) {
this.renameForm.load(this.client);
const app = this.appsState.appName; const app = this.appsState.appName;
this.connectHttpText = connectHttpText(this.apiUrl, app, this.client); this.connectHttpText = connectHttpText(this.apiUrl, app, this.client);
@ -80,31 +69,8 @@ export class ClientComponent implements OnChanges {
this.clientsState.update(this.client, { role }); this.clientsState.update(this.client, { role });
} }
public toggleRename() { public rename(name: string) {
if (!this.client.canUpdate) { this.clientsState.update(this.client, { name });
return;
}
this.isRenaming = !this.isRenaming;
}
public rename() {
if (!this.client.canUpdate) {
return;
}
const value = this.renameForm.submit();
if (value) {
this.clientsState.update(this.client, value)
.subscribe(() => {
this.renameForm.submitCompleted();
this.toggleRename();
}, error => {
this.renameForm.submitFailed(error);
});
}
} }
public connect() { public connect() {
@ -121,12 +87,6 @@ export class ClientComponent implements OnChanges {
public trackByRole(index: number, role: RoleDto) { public trackByRole(index: number, role: RoleDto) {
return role.name; return role.name;
} }
public onKeyDown(keyCode: number) {
if (keyCode === ESCAPE_KEY) {
this.toggleRename();
}
}
} }
function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {

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

@ -0,0 +1,59 @@
<div class="step">
<div class="row no-gutters">
<div class="col-auto color pr-2">
<sqx-color-picker mode="Circle"
[ngModel]="step.color"
(ngModelChange)="changeColor($event)">
</sqx-color-picker>
</div>
<div class="col">
<sqx-editable-title
[name]="step.name"
(nameChanged)="changeName($event)"
[disabled]="step.isLocked">
</sqx-editable-title>
</div>
<div class="col-auto">
<button type="button" class="btn btn-text-danger" (click)="remove.emit()" *ngIf="!step.isLocked">
<i class="icon-bin2"></i>
</button>
</div>
</div>
<div class="row transition no-gutters">
<div class="col-auto">
<i class="icon-arrow-right text-decent"></i>
</div>
<div class="col-3 pl-2">
<div class="color-circle" [style.background]="'red'"></div> In Progress
</div>
<div class="col pl-2">
<input class="form-control" placeholder="Expression" />
</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>
<div class="row transition no-gutters" *ngIf="openSteps.length > 0">
<div class="col-auto">
<i class="icon-arrow-right text-decent"></i>
</div>
<div class="col-3 pl-2">
<sqx-dropdown [items]="openSteps">
<ng-template let-target="$implicit">
<span class="autocomplete-user">
<div class="color-circle" [style.background]="target.color"></div> {{target.name}}
</span>
</ng-template>
</sqx-dropdown>
</div>
<div class="col pl-2">
<button class="btn btn-success">
Add Transition
</button>
</div>
</div>
</div>

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

@ -0,0 +1,28 @@
@import '_vars';
@import '_mixins';
.color {
line-height: 2.8rem;
}
.color-circle {
@include circle(12px);
border: 1px solid $color-border-dark;
background: $color-border;
display: inline-block;
}
.transition {
& {
padding-left: 1rem;
margin-top: .25rem;
margin-bottom: .5rem;
line-height: 2rem;
}
}
.step {
& {
margin-bottom: 1rem;
}
}

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

@ -0,0 +1,62 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import {
WorkflowDto,
WorkflowStep,
WorkflowStepValues,
WorkflowTransition,
WorkflowTransitionView
} from '@app/shared';
@Component({
selector: 'sqx-workflow-step',
styleUrls: ['./workflow-step.component.scss'],
templateUrl: './workflow-step.component.html'
})
export class WorkflowStepComponent implements OnChanges {
@Input()
public workflow: WorkflowDto;
@Input()
public step: WorkflowStep;
@Output()
public transitionRemove = new EventEmitter<WorkflowTransition>();
@Output()
public update = new EventEmitter<WorkflowStepValues>();
@Output()
public rename = new EventEmitter<string>();
@Output()
public remove = new EventEmitter();
public openSteps: WorkflowStep[];
public transitions: WorkflowTransitionView[];
public ngOnChanges(changes: SimpleChanges) {
if (changes['workflow'] || changes['step']) {
this.openSteps = this.workflow.getOpenSteps(this.step);
this.transitions = this.workflow.getTransitions(this.step);
}
}
public changeName(name: string) {
this.rename.emit(name);
}
public changeColor(color: string) {
this.update.emit({ color });
}
}

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

@ -0,0 +1,35 @@
<sqx-panel desiredWidth="50rem" isBlank="true" [isLazyLoaded]="false">
<ng-container title>
Workflows
</ng-container>
<ng-container menu>
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="Refresh roles (CTRL + SHIFT + R)">
<i class="icon-reset"></i> Refresh
</button>
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<ng-container>
<button type="button" class="btn btn-primary" (click)="save()" title="Save (CTRL + S)">
Save
</button>
<sqx-shortcut keys="ctrl+s" (trigger)="save()"></sqx-shortcut>
</ng-container>
</ng-container>
<ng-container content>
<sqx-workflow-step *ngFor="let step of workflow.steps"
[workflow]="workflow"
[step]="step"
(update)="updateStep(step, $event)"
(rename)="renameStep(step, $event)"
(remove)="removeStep(step)">
</sqx-workflow-step>
<button class="btn btn-success" (click)="addStep()">
Add Step
</button>
</ng-container>
</sqx-panel>

2
src/Squidex/app/features/settings/pages/workflows/workflows-page.component.scss

@ -0,0 +1,2 @@
@import '_vars';
@import '_mixins';

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

@ -0,0 +1,48 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component } from '@angular/core';
import {
WorkflowDto,
WorkflowStep,
WorkflowStepValues
} from '@app/shared';
@Component({
selector: 'sqx-workflows-page',
styleUrls: ['./workflows-page.component.scss'],
templateUrl: './workflows-page.component.html'
})
export class WorkflowsPageComponent {
public workflow = new WorkflowDto().setStep('Published', { color: 'green' });
public reload() {
return;
}
public save() {
return;
}
public addStep() {
this.workflow = this.workflow.setStep(`Step${this.workflow.steps.length + 1}`, {});
}
public updateStep(step: WorkflowStep, values: WorkflowStepValues) {
// this.workflow = this.workflow.setStep(step.name, values);
}
public renameStep(step: WorkflowStep, newName: string) {
// this.workflow = this.workflow.renameStep(step.name, newName);
}
public removeStep(step: WorkflowStep) {
// this.workflow = this.workflow.removeStep(step.name);
}
}

6
src/Squidex/app/features/settings/settings-area.component.html

@ -43,6 +43,12 @@
<i class="icon-angle-right"></i> <i class="icon-angle-right"></i>
</a> </a>
</li> </li>
<li class="nav-item" *ngIf="selectedApp.canReadWorkflows">
<a class="nav-link" routerLink="workflows" routerLinkActive="active">
Workflows
<i class="icon-angle-right"></i>
</a>
</li>
<li class="nav-item" *ngIf="selectedApp.canReadPlans"> <li class="nav-item" *ngIf="selectedApp.canReadPlans">
<a class="nav-link" routerLink="plans" routerLinkActive="active"> <a class="nav-link" routerLink="plans" routerLinkActive="active">
Subscription Subscription

15
src/Squidex/app/framework/angular/forms/autocomplete.component.ts

@ -10,17 +10,12 @@ import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { catchError, debounceTime, distinctUntilChanged, filter, map, switchMap, tap } from 'rxjs/operators'; import { catchError, debounceTime, distinctUntilChanged, filter, map, switchMap, tap } from 'rxjs/operators';
import { StatefulControlComponent } from '@app/framework/internal'; import { Keys, StatefulControlComponent } from '@app/framework/internal';
export interface AutocompleteSource { export interface AutocompleteSource {
find(query: string): Observable<any[]>; find(query: string): Observable<any[]>;
} }
const KEY_ENTER = 13;
const KEY_ESCAPE = 27;
const KEY_UP = 38;
const KEY_DOWN = 40;
const NO_EMIT = { emitEvent: false }; const NO_EMIT = { emitEvent: false };
export const SQX_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = { export const SQX_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = {
@ -95,17 +90,17 @@ export class AutocompleteComponent extends StatefulControlComponent<State, any[]
public onKeyDown(event: KeyboardEvent) { public onKeyDown(event: KeyboardEvent) {
switch (event.keyCode) { switch (event.keyCode) {
case KEY_UP: case Keys.UP:
this.up(); this.up();
return false; return false;
case KEY_DOWN: case Keys.DOWN:
this.down(); this.down();
return false; return false;
case KEY_ESCAPE: case Keys.ESCAPE:
this.resetForm(); this.resetForm();
this.reset(); this.reset();
return false; return false;
case KEY_ENTER: case Keys.ENTER:
if (this.snapshot.suggestedItems.length > 0 && this.selectItem()) { if (this.snapshot.suggestedItems.length > 0 && this.selectItem()) {
return false; return false;
} }

22
src/Squidex/app/framework/angular/forms/color-picker.component.html

@ -1,10 +1,18 @@
<input class="form-control" type="text" #input <span class="color-container" #input>
[style.background]="snapshot.value" <ng-container *ngIf="mode === 'Input'; else circle">
[style.color]="snapshot.foreground" <input class="form-control" type="text"
[placeholder]="placeholder" [style.background]="snapshot.value"
[ngModel]="snapshot.value" [style.color]="snapshot.foreground"
(ngModelChange)="writeValue($event)" [placeholder]="placeholder"
(focus)="modal.show()" (blur)="blur()" /> [ngModel]="snapshot.value"
(ngModelChange)="writeValue($event)"
(focus)="modal.show()" (blur)="blur()" />
</ng-container>
<ng-template #circle>
<div class="circle" [style.background]="snapshot.value" (click)="modal.show()"></div>
</ng-template>
</span>
<div *sqxModalView="modal" [sqxModalTarget]="input" position="bottom-left"> <div *sqxModalView="modal" [sqxModalTarget]="input" position="bottom-left">
<div [style.background]="snapshot.value" <div [style.background]="snapshot.value"

9
src/Squidex/app/framework/angular/forms/color-picker.component.scss

@ -16,3 +16,12 @@
} }
} }
} }
.color-container {
display: inline-block;
}
.circle {
@include circle(16px);
border: 1px solid $color-border-dark;
}

3
src/Squidex/app/framework/angular/forms/color-picker.component.ts

@ -35,6 +35,9 @@ export class ColorPickerComponent extends StatefulControlComponent<State, string
@Input() @Input()
public placeholder = ''; public placeholder = '';
@Input()
public mode: 'Input' | 'Circle' = 'Input';
public modal = new ModalModel(); public modal = new ModalModel();
constructor(changeDetector: ChangeDetectorRef) { constructor(changeDetector: ChangeDetectorRef) {

26
src/Squidex/app/framework/angular/forms/dropdown.component.html

@ -0,0 +1,26 @@
<span>
<div class="selection">
<input type="text" class="form-control" [disabled]="snapshot.isDisabled" (click)="open()" readonly (keydown)="onKeyDown($event)" #input
autocomplete="off"
autocorrect="off"
autocapitalize="off">
<div class="control-dropdown-item" *ngIf="snapshot.selectedItem">
<ng-container *ngIf="!selectionTemplate">{{snapshot.selectedItem}}</ng-container>
<ng-template *ngIf="selectionTemplate" [sqxTemplateWrapper]="selectionTemplate" [item]="snapshot.selectedItem"></ng-template>
</div>
<i class="icon-caret-down"></i>
</div>
<div class="items-container">
<div class="control-dropdown" #container *sqxModalView="dropdown" [sqxModalTarget]="input" position="bottomLeft">
<div *ngFor="let item of items; let i = index;" class="control-dropdown-item control-dropdown-item-selectable" [class.active]="i === snapshot.selectedIndex" (mousedown)="selectIndexAndClose(i)" [sqxScrollActive]="i === snapshot.selectedIndex" [container]="container">
<ng-container *ngIf="!itemTemplate">{{item}}</ng-container>
<ng-template *ngIf="itemTemplate" [sqxTemplateWrapper]="itemTemplate" [item]="item" [index]="i"></ng-template>
</div>
</div>
</div>
</span>

38
src/Squidex/app/framework/angular/forms/dropdown.component.scss

@ -0,0 +1,38 @@
@import '_mixins';
@import '_vars';
$color-input-disabled: #eef1f4;
.form-control {
& {
width: 100%;
}
&[readonly] {
background: $color-input-background;
}
&:disabled {
background: $color-input-disabled;
}
}
.selection {
& {
position: relative;
overflow: hidden;
}
.control-dropdown-item {
@include absolute(0, 1rem, 0, 0);
pointer-events: none;
}
.icon-caret-down {
@include absolute(30%, .4rem, auto, auto);
cursor: pointer;
font-size: .9rem;
font-weight: normal;
pointer-events: none;
}
}

130
src/Squidex/app/framework/angular/forms/dropdown.component.ts

@ -0,0 +1,130 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterContentInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, forwardRef, Input, QueryList, TemplateRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Keys, ModalModel, StatefulControlComponent } from '@app/framework/internal';
export const SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DropdownComponent), multi: true
};
interface State {
selectedItem: any;
selectedIndex: number;
}
@Component({
selector: 'sqx-dropdown',
styleUrls: ['./dropdown.component.scss'],
templateUrl: './dropdown.component.html',
providers: [SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DropdownComponent extends StatefulControlComponent<State, any[]> implements AfterContentInit, ControlValueAccessor {
@Input()
public items: any[] = [];
@ContentChildren(TemplateRef)
public templates: QueryList<any>;
public dropdown = new ModalModel();
public selectionTemplate: TemplateRef<any>;
public itemTemplate: TemplateRef<any>;
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {
selectedItem: undefined,
selectedIndex: -1
});
}
public ngAfterContentInit() {
if (this.templates.length === 1) {
this.itemTemplate = this.selectionTemplate = this.templates.first;
} else {
this.templates.forEach(template => {
if (template.name === 'selection') {
this.selectionTemplate = template;
} else {
this.itemTemplate = template;
}
});
}
}
public writeValue(obj: any) {
this.selectIndex(this.items && obj ? this.items.indexOf(obj) : 0);
}
public onKeyDown(event: KeyboardEvent) {
switch (event.keyCode) {
case Keys.UP:
this.up();
return false;
case Keys.DOWN:
this.down();
return false;
case Keys.ESCAPE:
case Keys.ENTER:
if (this.dropdown.isOpen) {
this.close();
return false;
}
}
return true;
}
public open() {
this.dropdown.show();
this.callTouched();
}
public selectIndexAndClose(selectedIndex: number) {
this.selectIndex(selectedIndex);
this.close();
}
private close() {
this.dropdown.hide();
}
public selectIndex(selectedIndex: number) {
if (selectedIndex < 0) {
selectedIndex = 0;
}
const items = this.items || [];
if (selectedIndex >= items.length) {
selectedIndex = items.length - 1;
}
const value = items[selectedIndex];
if (value !== this.snapshot.selectedItem) {
selectedIndex = selectedIndex;
this.next(s => ({ ...s, selectedIndex, selectedItem: value }));
}
}
private up() {
this.selectIndex(this.snapshot.selectedIndex - 1);
}
private down() {
this.selectIndex(this.snapshot.selectedIndex + 1);
}
}

23
src/Squidex/app/framework/angular/forms/editable-title.component.html

@ -0,0 +1,23 @@
<div class="title">
<form *ngIf="isRenaming; else noRenaming" class="form-inline" [formGroup]="renameForm" (ngSubmit)="rename()">
<div class="form-group mr-1">
<sqx-control-errors for="name"></sqx-control-errors>
<input type="text" class="form-control form-underlined" formControlName="name" maxlength="20" sqxFocusOnInit (keydown)="onKeyDown($event.keyCode)" />
</div>
<button type="submit" class="btn btn-primary" [disabled]="!renameForm.valid || !renameForm.dirty">Save</button>
<button type="button" class="btn btn-text-secondary btn-cancel" (click)="toggleRename()">
<i class="icon-close"></i>
</button>
</form>
<ng-template #noRenaming>
<h3 class="title-name" (dblclick)="toggleRename()">
{{name}}
</h3>
<i class="title-edit icon-pencil" *ngIf="!disabled" (click)="toggleRename()"></i>
</ng-template>
</div>

33
src/Squidex/app/framework/angular/forms/editable-title.component.scss

@ -0,0 +1,33 @@
@import '_vars';
@import '_mixins';
.title {
&-edit {
color: $color-border-dark;
display: none;
font-size: .9rem;
font-weight: normal;
padding: .6rem .25rem;
border: 0;
background: transparent;
vertical-align: baseline;
}
&-name {
padding: .375rem 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-size: 1.2rem;
font-weight: normal;
line-height: 1.5rem;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
display: inline-block;
margin: 0;
}
&:hover {
.title-edit {
display: inline-block;
}
}
}

72
src/Squidex/app/framework/angular/forms/editable-title.component.ts

@ -0,0 +1,72 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
const ESCAPE_KEY = 27;
@Component({
selector: 'sqx-editable-title',
styleUrls: ['./editable-title.component.scss'],
templateUrl: './editable-title.component.html'
})
export class EditableTitleComponent {
@Input()
public disabled = false;
@Input()
public name: string;
@Output()
public nameChanged = new EventEmitter<string>();
public isRenaming = false;
public renameForm = this.formBuilder.group({
name: ['',
[
Validators.required
]
]
});
constructor(
private readonly formBuilder: FormBuilder
) {
}
public onKeyDown(keyCode: number) {
if (keyCode === ESCAPE_KEY) {
this.toggleRename();
}
}
public toggleRename() {
if (this.disabled) {
return;
}
this.renameForm.setValue({ name: this.name });
this.isRenaming = !this.isRenaming;
}
public rename() {
if (this.disabled) {
return;
}
if (this.renameForm.valid) {
const value = this.renameForm.value;
this.nameChanged.emit(value.name);
this.toggleRename();
}
}
}

18
src/Squidex/app/framework/angular/forms/tag-editor.component.ts

@ -11,13 +11,7 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, E
import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms'; import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { distinctUntilChanged, map, tap } from 'rxjs/operators';
import { StatefulControlComponent, Types } from '@app/framework/internal'; import { Keys, StatefulControlComponent, Types } from '@app/framework/internal';
const KEY_COMMA = 188;
const KEY_DELETE = 8;
const KEY_ENTER = 13;
const KEY_UP = 38;
const KEY_DOWN = 40;
export interface Converter { export interface Converter {
convert(input: string): any; convert(input: string): any;
@ -265,11 +259,11 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
public onKeyDown(event: KeyboardEvent) { public onKeyDown(event: KeyboardEvent) {
const key = event.keyCode; const key = event.keyCode;
if (key === KEY_COMMA) { if (key === Keys.COMMA) {
if (this.selectValue(this.addInput.value)) { if (this.selectValue(this.addInput.value)) {
return false; return false;
} }
} else if (key === KEY_DELETE) { } else if (key === Keys.DELETE) {
const value = <string>this.addInput.value; const value = <string>this.addInput.value;
if (!value || value.length === 0) { if (!value || value.length === 0) {
@ -277,13 +271,13 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
return false; return false;
} }
} else if (key === KEY_UP) { } else if (key === Keys.UP) {
this.up(); this.up();
return false; return false;
} else if (key === KEY_DOWN) { } else if (key === Keys.DOWN) {
this.down(); this.down();
return false; return false;
} else if (key === KEY_ENTER) { } else if (key === Keys.ENTER) {
if (this.snapshot.suggestedIndex >= 0) { if (this.snapshot.suggestedIndex >= 0) {
if (this.selectValue(this.snapshot.suggestedItems[this.snapshot.suggestedIndex])) { if (this.selectValue(this.snapshot.suggestedItems[this.snapshot.suggestedIndex])) {
return false; return false;

2
src/Squidex/app/framework/declarations.ts

@ -13,6 +13,8 @@ export * from './angular/forms/confirm-click.directive';
export * from './angular/forms/control-errors.component'; export * from './angular/forms/control-errors.component';
export * from './angular/forms/copy.directive'; export * from './angular/forms/copy.directive';
export * from './angular/forms/date-time-editor.component'; export * from './angular/forms/date-time-editor.component';
export * from './angular/forms/dropdown.component';
export * from './angular/forms/editable-title.component';
export * from './angular/forms/file-drop.directive'; export * from './angular/forms/file-drop.directive';
export * from './angular/forms/focus-on-init.directive'; export * from './angular/forms/focus-on-init.directive';
export * from './angular/forms/form-alert.component'; export * from './angular/forms/form-alert.component';

1
src/Squidex/app/framework/internal.ts

@ -26,6 +26,7 @@ export * from './utils/error';
export * from './utils/hateos'; export * from './utils/hateos';
export * from './utils/interpolator'; export * from './utils/interpolator';
export * from './utils/immutable-array'; export * from './utils/immutable-array';
export * from './utils/keys';
export * from './utils/math-helper'; export * from './utils/math-helper';
export * from './utils/modal-positioner'; export * from './utils/modal-positioner';
export * from './utils/modal-view'; export * from './utils/modal-view';

6
src/Squidex/app/framework/module.ts

@ -32,7 +32,9 @@ import {
DialogRendererComponent, DialogRendererComponent,
DialogService, DialogService,
DisplayNamePipe, DisplayNamePipe,
DropdownComponent,
DurationPipe, DurationPipe,
EditableTitleComponent,
ExternalLinkDirective, ExternalLinkDirective,
FileDropDirective, FileDropDirective,
FileSizePipe, FileSizePipe,
@ -112,7 +114,9 @@ import {
DayPipe, DayPipe,
DialogRendererComponent, DialogRendererComponent,
DisplayNamePipe, DisplayNamePipe,
DropdownComponent,
DurationPipe, DurationPipe,
EditableTitleComponent,
ExternalLinkDirective, ExternalLinkDirective,
FileDropDirective, FileDropDirective,
FileSizePipe, FileSizePipe,
@ -177,7 +181,9 @@ import {
DayPipe, DayPipe,
DialogRendererComponent, DialogRendererComponent,
DisplayNamePipe, DisplayNamePipe,
DropdownComponent,
DurationPipe, DurationPipe,
EditableTitleComponent,
ExternalLinkDirective, ExternalLinkDirective,
FileDropDirective, FileDropDirective,
FileSizePipe, FileSizePipe,

15
src/Squidex/app/framework/utils/keys.ts

@ -0,0 +1,15 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
export module Keys {
export const COMMA = 188;
export const DELETE = 8;
export const ENTER = 13;
export const ESCAPE = 27;
export const DOWN = 40;
export const UP = 38;
}

1
src/Squidex/app/shared/services/apps.service.ts

@ -35,6 +35,7 @@ export class AppDto {
public readonly canReadRoles: boolean; public readonly canReadRoles: boolean;
public readonly canReadRules: boolean; public readonly canReadRules: boolean;
public readonly canReadSchemas: boolean; public readonly canReadSchemas: boolean;
public readonly canReadWorkflows: boolean = true;
public readonly canUploadAssets: boolean; public readonly canUploadAssets: boolean;
constructor(links: ResourceLinks, constructor(links: ResourceLinks,

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

@ -20,6 +20,18 @@ export class WorkflowDto extends Model<WorkflowDto> {
this._links = links; this._links = links;
} }
public getOpenSteps(step: WorkflowStep) {
return this.steps.filter(x => !this.transitions.find(y => y.from === step.name && y.to === x.name));
}
public getTransitions(step: WorkflowStep): WorkflowTransitionView[] {
return this.transitions.filter(x => x.from === step.name).map(x => ({ step: this.getStep(x.to), ...x }));
}
public getStep(name: string): WorkflowStep {
return this.steps.find(x => x.name === name)!;
}
public setStep(name: string, values: Partial<WorkflowStepValues>) { public setStep(name: string, values: Partial<WorkflowStepValues>) {
const steps = [...this.steps.filter(s => s.name !== name), { name, ...values }]; const steps = [...this.steps.filter(s => s.name !== name), { name, ...values }];
@ -97,3 +109,5 @@ export type WorkflowStep = { name: string } & WorkflowStepValues;
export type WorkflowTransitionValues = { expression?: string }; export type WorkflowTransitionValues = { expression?: string };
export type WorkflowTransition = { from: string; to: string } & WorkflowTransitionValues; export type WorkflowTransition = { from: string; to: string } & WorkflowTransitionValues;
export type WorkflowTransitionView = { step: WorkflowStep } & WorkflowTransition;

18
src/Squidex/app/theme/icomoon/demo.html

@ -9,7 +9,7 @@
<link rel="stylesheet" href="style.css"></head> <link rel="stylesheet" href="style.css"></head>
<body> <body>
<div class="bgc1 clearfix"> <div class="bgc1 clearfix">
<h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;121)</small></h1> <h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;122)</small></h1>
</div> </div>
<div class="clearfix mhl ptl"> <div class="clearfix mhl ptl">
<h1 class="mvm mtn fgc1">Grid Size: Unknown</h1> <h1 class="mvm mtn fgc1">Grid Size: Unknown</h1>
@ -1107,6 +1107,22 @@
</div> </div>
<div class="clearfix mhl ptl"> <div class="clearfix mhl ptl">
<h1 class="mvm mtn fgc1">Grid Size: 16</h1> <h1 class="mvm mtn fgc1">Grid Size: 16</h1>
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-arrow-right">
</span>
<span class="mls"> icon-arrow-right</span>
</div>
<fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="e976" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#xe976;" class="unitRight size1of2 talign-right" />
</fieldset>
<div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3"> <div class="glyph fs3">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-upload"> <span class="icon-upload">

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.eot

Binary file not shown.

1
src/Squidex/app/theme/icomoon/fonts/icomoon.svg

@ -125,6 +125,7 @@
<glyph unicode="&#xe973;" glyph-name="upload-3" d="M469.333 323.67v-281.003c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667v281.003l97.835-97.835c16.683-16.683 43.691-16.683 60.331 0s16.683 43.691 0 60.331l-170.667 170.667c-0.085 0.085-0.171 0.171-0.256 0.256-4.053 3.968-8.661 6.955-13.568 9.003-5.12 2.133-10.624 3.2-16.085 3.243-0.171 0-0.341 0-0.469 0-5.461-0.043-10.965-1.109-16.085-3.243-4.949-2.048-9.557-5.035-13.568-9.003-0.085-0.085-0.171-0.171-0.256-0.256l-170.667-170.667c-16.683-16.683-16.683-43.691 0-60.331s43.691-16.683 60.331 0zM890.411 116.566c30.379 16.555 56.149 38.443 76.672 63.915 21.333 26.411 36.949 56.619 46.379 88.576s12.629 65.835 9.003 99.584c-3.456 32.512-13.269 64.896-29.824 95.232-14.208 26.069-32.384 48.768-53.376 67.669-21.717 19.541-46.421 34.944-72.875 45.952-30.891 12.8-64.171 19.584-98.048 19.84h-22.528c-13.312 37.717-32.085 72.235-55.168 102.912-30.635 40.661-68.821 74.453-111.915 99.84s-91.179 42.411-141.568 49.536c-48.597 6.784-99.243 4.395-149.504-8.619s-95.744-35.413-134.912-64.939c-40.661-30.635-74.453-68.821-99.84-111.915s-42.411-91.179-49.493-141.568c-6.827-48.555-4.395-99.2 8.576-149.461 15.872-61.312 45.781-115.627 84.267-158.421 15.744-17.536 42.752-18.944 60.245-3.2s18.944 42.752 3.2 60.245c-29.355 32.64-52.693 74.667-65.109 122.752-10.155 39.253-11.989 78.592-6.699 116.224 5.504 39.125 18.773 76.501 38.571 110.123s46.080 63.317 77.653 87.083c30.379 22.869 65.664 40.32 104.917 50.475s78.592 11.989 116.224 6.699c39.125-5.504 76.544-18.731 110.123-38.528s63.317-46.080 87.083-77.653c22.869-30.379 40.32-65.664 50.475-104.917 4.907-18.56 21.547-32 41.301-32h53.461c22.869-0.171 45.269-4.736 65.92-13.312 17.707-7.339 34.133-17.621 48.512-30.592 13.909-12.501 25.984-27.605 35.541-45.099 11.093-20.352 17.579-41.899 19.883-63.488 2.389-22.443 0.256-45.013-6.016-66.432s-16.725-41.515-30.933-59.093c-13.611-16.896-30.763-31.445-51.115-42.581-20.693-11.264-28.331-37.205-17.024-57.899s37.205-28.331 57.899-17.024z" /> <glyph unicode="&#xe973;" glyph-name="upload-3" d="M469.333 323.67v-281.003c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667v281.003l97.835-97.835c16.683-16.683 43.691-16.683 60.331 0s16.683 43.691 0 60.331l-170.667 170.667c-0.085 0.085-0.171 0.171-0.256 0.256-4.053 3.968-8.661 6.955-13.568 9.003-5.12 2.133-10.624 3.2-16.085 3.243-0.171 0-0.341 0-0.469 0-5.461-0.043-10.965-1.109-16.085-3.243-4.949-2.048-9.557-5.035-13.568-9.003-0.085-0.085-0.171-0.171-0.256-0.256l-170.667-170.667c-16.683-16.683-16.683-43.691 0-60.331s43.691-16.683 60.331 0zM890.411 116.566c30.379 16.555 56.149 38.443 76.672 63.915 21.333 26.411 36.949 56.619 46.379 88.576s12.629 65.835 9.003 99.584c-3.456 32.512-13.269 64.896-29.824 95.232-14.208 26.069-32.384 48.768-53.376 67.669-21.717 19.541-46.421 34.944-72.875 45.952-30.891 12.8-64.171 19.584-98.048 19.84h-22.528c-13.312 37.717-32.085 72.235-55.168 102.912-30.635 40.661-68.821 74.453-111.915 99.84s-91.179 42.411-141.568 49.536c-48.597 6.784-99.243 4.395-149.504-8.619s-95.744-35.413-134.912-64.939c-40.661-30.635-74.453-68.821-99.84-111.915s-42.411-91.179-49.493-141.568c-6.827-48.555-4.395-99.2 8.576-149.461 15.872-61.312 45.781-115.627 84.267-158.421 15.744-17.536 42.752-18.944 60.245-3.2s18.944 42.752 3.2 60.245c-29.355 32.64-52.693 74.667-65.109 122.752-10.155 39.253-11.989 78.592-6.699 116.224 5.504 39.125 18.773 76.501 38.571 110.123s46.080 63.317 77.653 87.083c30.379 22.869 65.664 40.32 104.917 50.475s78.592 11.989 116.224 6.699c39.125-5.504 76.544-18.731 110.123-38.528s63.317-46.080 87.083-77.653c22.869-30.379 40.32-65.664 50.475-104.917 4.907-18.56 21.547-32 41.301-32h53.461c22.869-0.171 45.269-4.736 65.92-13.312 17.707-7.339 34.133-17.621 48.512-30.592 13.909-12.501 25.984-27.605 35.541-45.099 11.093-20.352 17.579-41.899 19.883-63.488 2.389-22.443 0.256-45.013-6.016-66.432s-16.725-41.515-30.933-59.093c-13.611-16.896-30.763-31.445-51.115-42.581-20.693-11.264-28.331-37.205-17.024-57.899s37.205-28.331 57.899-17.024z" />
<glyph unicode="&#xe974;" glyph-name="info-outline" d="M470 554.667v86h84v-86h-84zM512 84.667c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM470 212.667v256h84v-256h-84z" /> <glyph unicode="&#xe974;" glyph-name="info-outline" d="M470 554.667v86h84v-86h-84zM512 84.667c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM470 212.667v256h84v-256h-84z" />
<glyph unicode="&#xe975;" glyph-name="type-UI" d="M512 256h-341.333c-5.845 0-11.349 1.152-16.299 3.2-5.205 2.133-9.899 5.333-13.867 9.301s-7.125 8.661-9.301 13.867c-2.048 4.949-3.2 10.453-3.2 16.299v426.667c0 5.845 1.152 11.349 3.2 16.299 2.133 5.205 5.333 9.899 9.301 13.867s8.661 7.125 13.867 9.301c4.949 2.048 10.453 3.2 16.299 3.2h682.667c5.845 0 11.349-1.152 16.299-3.2 5.205-2.133 9.899-5.333 13.867-9.301s7.125-8.661 9.301-13.867c2.048-4.949 3.2-10.453 3.2-16.299v-426.667c0-5.845-1.152-11.349-3.2-16.299-2.133-5.205-5.333-9.899-9.301-13.867s-8.661-7.125-13.867-9.301c-4.949-2.048-10.453-3.2-16.299-3.2zM469.333 170.667v-85.333h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h341.333c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667h-128v85.333h298.667c17.28 0 33.835 3.456 48.981 9.728 15.701 6.485 29.781 16 41.557 27.776s21.291 25.856 27.776 41.557c6.229 15.104 9.685 31.659 9.685 48.939v426.667c0 17.28-3.456 33.835-9.728 48.981-6.485 15.701-16 29.781-27.776 41.557s-25.856 21.291-41.557 27.776c-15.104 6.229-31.659 9.685-48.939 9.685h-682.667c-17.28 0-33.835-3.456-48.981-9.728-15.659-6.485-29.739-16-41.515-27.776s-21.291-25.856-27.776-41.515c-6.272-15.147-9.728-31.701-9.728-48.981v-426.667c0-17.28 3.456-33.835 9.728-48.981 6.485-15.701 16-29.781 27.776-41.557s25.856-21.291 41.557-27.776c15.104-6.229 31.659-9.685 48.939-9.685z" /> <glyph unicode="&#xe975;" glyph-name="type-UI" d="M512 256h-341.333c-5.845 0-11.349 1.152-16.299 3.2-5.205 2.133-9.899 5.333-13.867 9.301s-7.125 8.661-9.301 13.867c-2.048 4.949-3.2 10.453-3.2 16.299v426.667c0 5.845 1.152 11.349 3.2 16.299 2.133 5.205 5.333 9.899 9.301 13.867s8.661 7.125 13.867 9.301c4.949 2.048 10.453 3.2 16.299 3.2h682.667c5.845 0 11.349-1.152 16.299-3.2 5.205-2.133 9.899-5.333 13.867-9.301s7.125-8.661 9.301-13.867c2.048-4.949 3.2-10.453 3.2-16.299v-426.667c0-5.845-1.152-11.349-3.2-16.299-2.133-5.205-5.333-9.899-9.301-13.867s-8.661-7.125-13.867-9.301c-4.949-2.048-10.453-3.2-16.299-3.2zM469.333 170.667v-85.333h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h341.333c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667h-128v85.333h298.667c17.28 0 33.835 3.456 48.981 9.728 15.701 6.485 29.781 16 41.557 27.776s21.291 25.856 27.776 41.557c6.229 15.104 9.685 31.659 9.685 48.939v426.667c0 17.28-3.456 33.835-9.728 48.981-6.485 15.701-16 29.781-27.776 41.557s-25.856 21.291-41.557 27.776c-15.104 6.229-31.659 9.685-48.939 9.685h-682.667c-17.28 0-33.835-3.456-48.981-9.728-15.659-6.485-29.739-16-41.515-27.776s-21.291-25.856-27.776-41.515c-6.272-15.147-9.728-31.701-9.728-48.981v-426.667c0-17.28 3.456-33.835 9.728-48.981 6.485-15.701 16-29.781 27.776-41.557s25.856-21.291 41.557-27.776c15.104-6.229 31.659-9.685 48.939-9.685z" />
<glyph unicode="&#xe976;" glyph-name="arrow-right" d="M621.254 82.746l320 320c24.994 24.992 24.994 65.516 0 90.51l-320 320c-24.994 24.992-65.516 24.992-90.51 0-24.994-24.994-24.994-65.516 0-90.51l210.746-210.746h-613.49c-35.346 0-64-28.654-64-64s28.654-64 64-64h613.49l-210.746-210.746c-12.496-12.496-18.744-28.876-18.744-45.254s6.248-32.758 18.744-45.254c24.994-24.994 65.516-24.994 90.51 0z" />
<glyph unicode="&#xe9ca;" glyph-name="earth" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512-0.002c-62.958 0-122.872 13.012-177.23 36.452l233.148 262.29c5.206 5.858 8.082 13.422 8.082 21.26v96c0 17.674-14.326 32-32 32-112.99 0-232.204 117.462-233.374 118.626-6 6.002-14.14 9.374-22.626 9.374h-128c-17.672 0-32-14.328-32-32v-192c0-12.122 6.848-23.202 17.69-28.622l110.31-55.156v-187.886c-116.052 80.956-192 215.432-192 367.664 0 68.714 15.49 133.806 43.138 192h116.862c8.488 0 16.626 3.372 22.628 9.372l128 128c6 6.002 9.372 14.14 9.372 22.628v77.412c40.562 12.074 83.518 18.588 128 18.588 70.406 0 137.004-16.26 196.282-45.2-4.144-3.502-8.176-7.164-12.046-11.036-36.266-36.264-56.236-84.478-56.236-135.764s19.97-99.5 56.236-135.764c36.434-36.432 85.218-56.264 135.634-56.26 3.166 0 6.342 0.080 9.518 0.236 13.814-51.802 38.752-186.656-8.404-372.334-0.444-1.744-0.696-3.488-0.842-5.224-81.324-83.080-194.7-134.656-320.142-134.656z" /> <glyph unicode="&#xe9ca;" glyph-name="earth" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512-0.002c-62.958 0-122.872 13.012-177.23 36.452l233.148 262.29c5.206 5.858 8.082 13.422 8.082 21.26v96c0 17.674-14.326 32-32 32-112.99 0-232.204 117.462-233.374 118.626-6 6.002-14.14 9.374-22.626 9.374h-128c-17.672 0-32-14.328-32-32v-192c0-12.122 6.848-23.202 17.69-28.622l110.31-55.156v-187.886c-116.052 80.956-192 215.432-192 367.664 0 68.714 15.49 133.806 43.138 192h116.862c8.488 0 16.626 3.372 22.628 9.372l128 128c6 6.002 9.372 14.14 9.372 22.628v77.412c40.562 12.074 83.518 18.588 128 18.588 70.406 0 137.004-16.26 196.282-45.2-4.144-3.502-8.176-7.164-12.046-11.036-36.266-36.264-56.236-84.478-56.236-135.764s19.97-99.5 56.236-135.764c36.434-36.432 85.218-56.264 135.634-56.26 3.166 0 6.342 0.080 9.518 0.236 13.814-51.802 38.752-186.656-8.404-372.334-0.444-1.744-0.696-3.488-0.842-5.224-81.324-83.080-194.7-134.656-320.142-134.656z" />
<glyph unicode="&#xf00a;" glyph-name="grid" d="M292.571 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857z" /> <glyph unicode="&#xf00a;" glyph-name="grid" d="M292.571 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857z" />
<glyph unicode="&#xf0c9;" glyph-name="list1" horiz-adv-x="878" d="M877.714 182.857v-73.143c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v73.143c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571zM877.714 475.428v-73.143c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v73.143c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571zM877.714 768v-73.143c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v73.143c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571z" /> <glyph unicode="&#xf0c9;" glyph-name="list1" horiz-adv-x="878" d="M877.714 182.857v-73.143c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v73.143c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571zM877.714 475.428v-73.143c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v73.143c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571zM877.714 768v-73.143c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v73.143c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571z" />

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.ttf

Binary file not shown.

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.woff

Binary file not shown.

2
src/Squidex/app/theme/icomoon/selection.json

File diff suppressed because one or more lines are too long

13
src/Squidex/app/theme/icomoon/style.css

@ -1,10 +1,10 @@
@font-face { @font-face {
font-family: 'icomoon'; font-family: 'icomoon';
src: url('fonts/icomoon.eot?wt9idh'); src: url('fonts/icomoon.eot?h3wogz');
src: url('fonts/icomoon.eot?wt9idh#iefix') format('embedded-opentype'), src: url('fonts/icomoon.eot?h3wogz#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?wt9idh') format('truetype'), url('fonts/icomoon.ttf?h3wogz') format('truetype'),
url('fonts/icomoon.woff?wt9idh') format('woff'), url('fonts/icomoon.woff?h3wogz') format('woff'),
url('fonts/icomoon.svg?wt9idh#icomoon') format('svg'); url('fonts/icomoon.svg?h3wogz#icomoon') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -228,6 +228,9 @@
.icon-download:before { .icon-download:before {
content: "\e93e"; content: "\e93e";
} }
.icon-arrow-right:before {
content: "\e976";
}
.icon-upload:before { .icon-upload:before {
content: "\e970"; content: "\e970";
} }

Loading…
Cancel
Save