|
-
+
|
diff --git a/src/Squidex/app/features/content/shared/references-editor.component.html b/src/Squidex/app/features/content/shared/references-editor.component.html
index 488e1166a..49a8ae83e 100644
--- a/src/Squidex/app/features/content/shared/references-editor.component.html
+++ b/src/Squidex/app/features/content/shared/references-editor.component.html
@@ -7,14 +7,20 @@
0"
- [sqxSortModel]="snapshot.contentItems"
- (sqxSort)="sort($event)">
+ cdkDropList
+ [cdkDropListData]="snapshot.contentItems"
+ [cdkDropListDisabled]="snapshot.isDisabled"
+ (cdkDropListDropped)="sort($event)">
+
diff --git a/src/Squidex/app/features/content/shared/references-editor.component.ts b/src/Squidex/app/features/content/shared/references-editor.component.ts
index 016e42187..9c4751d28 100644
--- a/src/Squidex/app/features/content/shared/references-editor.component.ts
+++ b/src/Squidex/app/features/content/shared/references-editor.component.ts
@@ -5,6 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
+import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -14,6 +15,7 @@ import {
ContentDto,
ContentsService,
DialogModel,
+ sorted,
StatefulControlComponent,
Types
} from '@app/shared';
@@ -113,9 +115,9 @@ export class ReferencesEditorComponent extends StatefulControlComponent) {
- if (contents) {
- this.setContentItems(contents);
+ public sort(event: CdkDragDrop>) {
+ if (event) {
+ this.setContentItems(sorted(event));
this.updateValue();
}
diff --git a/src/Squidex/app/features/schemas/module.ts b/src/Squidex/app/features/schemas/module.ts
index 3ce75e43f..00ab8cf1d 100644
--- a/src/Squidex/app/features/schemas/module.ts
+++ b/src/Squidex/app/features/schemas/module.ts
@@ -7,7 +7,6 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
-import { DndModule } from 'ng2-dnd';
import {
HelpComponent,
@@ -75,7 +74,6 @@ const routes: Routes = [
imports: [
SqxFrameworkModule,
SqxSharedModule,
- DndModule,
RouterModule.forChild(routes)
],
providers: [
diff --git a/src/Squidex/app/features/schemas/pages/schema/field.component.html b/src/Squidex/app/features/schemas/pages/schema/field.component.html
index 921d3d8bc..a81597fbe 100644
--- a/src/Squidex/app/features/schemas/pages/schema/field.component.html
+++ b/src/Squidex/app/features/schemas/pages/schema/field.component.html
@@ -1,6 +1,8 @@
-
-
+
+
+
+
@@ -95,13 +97,20 @@
-
+ cdkDropList
+ [cdkDropListDisabled]="!isEditable"
+ [cdkDropListData]="nested"
+ (cdkDropListDropped)="sortFields($event)">
+
+
-
+
+
+
diff --git a/src/Squidex/app/features/schemas/pages/schema/field.component.scss b/src/Squidex/app/features/schemas/pages/schema/field.component.scss
index c4c5a1937..db5afbc88 100644
--- a/src/Squidex/app/features/schemas/pages/schema/field.component.scss
+++ b/src/Squidex/app/features/schemas/pages/schema/field.component.scss
@@ -22,8 +22,9 @@ $padding: 1rem;
padding-left: 3rem;
}
-.drag-handle {
+.drag-container {
@include absolute(1.75rem, auto, auto, .75rem);
+ line-height: 1px;
}
.col {
@@ -37,6 +38,10 @@ $padding: 1rem;
}
}
+.field {
+ position: relative;
+}
+
.nested-fields {
padding: $padding;
padding-left: 2 * $padding;
diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
index d3bebe6cc..898631fda 100644
--- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
+++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
@@ -76,11 +76,17 @@
-
-
+ cdkDropList
+ [cdkDropListDisabled]="!schema.canOrderFields"
+ [cdkDropListData]="schema.fields"
+ (cdkDropListDropped)="sortFields($event)">
+
+
+
+
diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
index c44d5b9cb..ab7a9ac61 100644
--- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
+++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
@@ -7,6 +7,7 @@
// tslint:disable:no-shadowed-variable
+import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
@@ -20,7 +21,8 @@ import {
PatternsState,
ResourceOwner,
SchemaDetailsDto,
- SchemasState
+ SchemasState,
+ sorted
} from '@app/shared';
import {
@@ -79,8 +81,8 @@ export class SchemaPageComponent extends ResourceOwner implements OnInit {
this.schemasState.unpublish(this.schema).subscribe();
}
- public sortFields(fields: ReadonlyArray ) {
- this.schemasState.orderFields(this.schema, fields).subscribe();
+ public sortFields(event: CdkDragDrop>) {
+ this.schemasState.orderFields(this.schema, sorted(event)).subscribe();
}
public trackByField(index: number, field: FieldDto) {
diff --git a/src/Squidex/app/features/settings/pages/languages/language.component.html b/src/Squidex/app/features/settings/pages/languages/language.component.html
index 45c4610a1..5ec63b9fa 100644
--- a/src/Squidex/app/features/settings/pages/languages/language.component.html
+++ b/src/Squidex/app/features/settings/pages/languages/language.component.html
@@ -39,14 +39,18 @@
- 0">
-
+
-
+
{{language.englishName}}
diff --git a/src/Squidex/app/features/settings/pages/languages/language.component.ts b/src/Squidex/app/features/settings/pages/languages/language.component.ts
index 323d82673..ff421fa98 100644
--- a/src/Squidex/app/features/settings/pages/languages/language.component.ts
+++ b/src/Squidex/app/features/settings/pages/languages/language.component.ts
@@ -5,6 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
+import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { Component, Input, OnChanges } from '@angular/core';
import { FormBuilder } from '@angular/forms';
@@ -12,7 +13,8 @@ import {
AppLanguageDto,
EditLanguageForm,
fadeAnimation,
- LanguagesState
+ LanguagesState,
+ sorted
} from '@app/shared';
@Component({
@@ -63,6 +65,10 @@ export class LanguageComponent implements OnChanges {
this.languagesState.remove(this.language);
}
+ public sort(event: CdkDragDrop >) {
+ this.fallbackLanguages = sorted(event);
+ }
+
public save() {
if (!this.isEditable) {
return;
diff --git a/src/Squidex/app/framework/angular/drag-helper.ts b/src/Squidex/app/framework/angular/drag-helper.ts
new file mode 100644
index 000000000..8e49daec3
--- /dev/null
+++ b/src/Squidex/app/framework/angular/drag-helper.ts
@@ -0,0 +1,16 @@
+/*
+ * Squidex Headless CMS
+ *
+ * @license
+ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
+ */
+
+import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
+
+export function sorted(event: CdkDragDrop>): ReadonlyArray {
+ const items = event.container.data;
+
+ moveItemInArray(items, event.previousIndex, event.currentIndex);
+
+ return items;
+}
\ No newline at end of file
diff --git a/src/Squidex/app/framework/internal.ts b/src/Squidex/app/framework/internal.ts
index 4cd0cb44b..f811e808a 100644
--- a/src/Squidex/app/framework/internal.ts
+++ b/src/Squidex/app/framework/internal.ts
@@ -5,6 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
+export * from './angular/drag-helper';
export * from './angular/routers/router-utils';
export * from './angular/animations';
diff --git a/src/Squidex/app/shared/components/geolocation-editor.component.ts b/src/Squidex/app/shared/components/geolocation-editor.component.ts
index dbac71d27..2ce7e0ca1 100644
--- a/src/Squidex/app/shared/components/geolocation-editor.component.ts
+++ b/src/Squidex/app/shared/components/geolocation-editor.component.ts
@@ -335,11 +335,11 @@ export class GeolocationEditorComponent extends StatefulControlComponent 0" dnd-droppable class="droppable category" [allowDrop]="allowDrop" (onDropSuccess)="changeCategory($event.dragData)">
-
+ 0" class="droppable category"
+ cdkDropList
+ cdkDropListSortingDisabled
+ [cdkDropListData]="schemaCategory.name"
+ (cdkDropListDropped)="changeCategory($event)">
-
diff --git a/src/Squidex/app/shared/components/schema-category.component.scss b/src/Squidex/app/shared/components/schema-category.component.scss
index 0db9907fc..c12c16860 100644
--- a/src/Squidex/app/shared/components/schema-category.component.scss
+++ b/src/Squidex/app/shared/components/schema-category.component.scss
@@ -21,17 +21,12 @@ h3 {
margin-bottom: 1rem;
}
-.dnd-drag-start {
- border: 0;
-}
-
.droppable {
& {
position: relative;
}
- &.dnd-drag-over,
- &.dnd-drag-enter {
+ &.cdk-drop-list-dragging {
& {
border: 0;
}
@@ -43,9 +38,9 @@ h3 {
.drop-indicator {
@include absolute($drag-margin, $drag-margin, $drag-margin, $drag-margin);
+ display: none;
border: 2px dashed $color-dark-black;
background: none;
- display: none;
pointer-events: none;
}
}
@@ -57,6 +52,47 @@ h3 {
.nav-link {
padding-top: .75rem;
padding-bottom: .75rem;
+ border: 0;
+}
+
+.nav-item {
+ & {
+ border-bottom: 1px solid $color-dark2-separator;
+ }
+
+ &:last-child {
+ border: 0;
+ }
+
+ &.active {
+ background: $color-dark2-active-background;
+ }
+
+ &.cdk-drag {
+ padding-left: 2rem;
+ padding-right: 0;
+ position: relative;
+ }
+
+ .drag-handle {
+ @include absolute(1rem, auto, auto, 1rem);
+ }
+}
+
+.cdk-drag-preview {
+ background: $color-dark2-background !important;
+
+ a {
+ color: $color-dark1-foreground !important;
+ }
+}
+
+.cdk-drag-placeholder {
+ display: none;
+}
+
+.cdk-drag-animating {
+ @include transition(none);
}
.schema {
diff --git a/src/Squidex/app/shared/components/schema-category.component.ts b/src/Squidex/app/shared/components/schema-category.component.ts
index abfca51d7..5dbc5f61b 100644
--- a/src/Squidex/app/shared/components/schema-category.component.ts
+++ b/src/Squidex/app/shared/components/schema-category.component.ts
@@ -5,18 +5,16 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
+import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import {
fadeAnimation,
- isSameCategory,
LocalStoreService,
SchemaCategory,
- SchemaDetailsDto,
SchemaDto,
SchemasState,
- StatefulComponent,
- Types
+ StatefulComponent
} from '@app/shared/internal';
interface State {
@@ -47,10 +45,6 @@ export class SchemaCategoryComponent extends StatefulComponent implements
@Input()
public forContent: boolean;
- public allowDrop = (schema: any) => {
- return (Types.is(schema, SchemaDto) || Types.is(schema, SchemaDetailsDto)) && !isSameCategory(this.schemaCategory.name, schema);
- }
-
constructor(changeDetector: ChangeDetectorRef,
private readonly localStore: LocalStoreService,
private readonly schemasState: SchemasState
@@ -98,8 +92,10 @@ export class SchemaCategoryComponent extends StatefulComponent implements
}
}
- public changeCategory(schema: SchemaDto) {
- this.schemasState.changeCategory(schema, this.schemaCategory.name);
+ public changeCategory(drag: CdkDragDrop) {
+ if (drag.previousContainer !== drag.container) {
+ this.schemasState.changeCategory(drag.item.data, this.schemaCategory.name);
+ }
}
public emitRemove() {
diff --git a/src/Squidex/app/shared/module.ts b/src/Squidex/app/shared/module.ts
index fc0dcfaec..1a13fbf4c 100644
--- a/src/Squidex/app/shared/module.ts
+++ b/src/Squidex/app/shared/module.ts
@@ -5,10 +5,10 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
+import { DragDropModule } from '@angular/cdk/drag-drop';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
-import { DndModule } from 'ng2-dnd';
import { SqxFrameworkModule } from '@app/framework';
@@ -109,7 +109,7 @@ import { SchemaTagConverter } from './state/schema-tag-converter';
@NgModule({
imports: [
- DndModule,
+ DragDropModule,
RouterModule,
SqxFrameworkModule
],
@@ -162,6 +162,7 @@ import { SchemaTagConverter } from './state/schema-tag-converter';
AssetUploaderComponent,
CommentComponent,
CommentsComponent,
+ DragDropModule,
FileIconPipe,
GeolocationEditorComponent,
HelpComponent,
diff --git a/src/Squidex/app/theme/_common.scss b/src/Squidex/app/theme/_common.scss
index 3a47bf2f4..00546abb0 100644
--- a/src/Squidex/app/theme/_common.scss
+++ b/src/Squidex/app/theme/_common.scss
@@ -47,6 +47,38 @@ body {
}
}
+.cdk-drag-preview {
+ @include opacity(.7);
+
+ &.table-drag {
+ background: $color-dark-foreground;
+ border: 2px dashed darken($color-border, 5%);
+ display: table;
+
+ * {
+ display: none;
+ }
+ }
+}
+
+.cdk-drag-placeholder {
+ @include opacity(0);
+}
+
+.cdk-drag-animating {
+ @include transition(transform 250ms cubic-bezier(0, 0, .2, 1));
+}
+
+.cdk-drop-list-dragging {
+ * {
+ @include transition(transform 250ms cubic-bezier(0, 0, .2, 1));
+ }
+
+ .cdk-drag-placeholder {
+ @include transition(none);
+ }
+}
+
.icon-bold {
font-weight: bold;
}
diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json
index dc7e8df97..d8e399e6a 100644
--- a/src/Squidex/package-lock.json
+++ b/src/Squidex/package-lock.json
@@ -4,6 +4,71 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+ "@angular-devkit/build-optimizer": {
+ "version": "0.803.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.8.tgz",
+ "integrity": "sha512-UiMxl1wI3acqIoRkC0WA0qpab+ni6SlCaB4UIwfD1H/FdzU80P04AIUuJS7StxjbwVkVtA05kcfgmqzP8yBMVg==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "1.2.3",
+ "source-map": "0.7.3",
+ "tslib": "1.10.0",
+ "typescript": "3.5.3",
+ "webpack-sources": "1.4.3"
+ },
+ "dependencies": {
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "webpack-sources": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+ "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
"@angular-devkit/core": {
"version": "8.3.8",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.8.tgz",
@@ -84,6 +149,15 @@
"tslib": "^1.9.0"
}
},
+ "@angular/cdk": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.2.3.tgz",
+ "integrity": "sha512-ZwO5Sn720RA2YvBqud0JAHkZXjmjxM0yNzCO8RVtRE9i8Gl26Wk0j0nQeJkVm4zwv2QO8MwbKUKGTMt8evsokA==",
+ "requires": {
+ "parse5": "^5.0.0",
+ "tslib": "^1.7.1"
+ }
+ },
"@angular/common": {
"version": "8.2.9",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-8.2.9.tgz",
@@ -9329,11 +9403,6 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
- "ng2-dnd": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/ng2-dnd/-/ng2-dnd-5.0.2.tgz",
- "integrity": "sha512-5mWWBePwvEPsNd/HkdbD543Q9mPyJofL6zkNydl8/Ah3qrrvZT2DaEPbknY08OgkXpI2qUGksc01OzzVlRQ9dQ=="
- },
"ngx-color-picker": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-8.2.0.tgz",
@@ -10068,6 +10137,12 @@
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true
},
+ "parse5": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+ "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+ "optional": true
+ },
"parseqs": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
diff --git a/src/Squidex/package.json b/src/Squidex/package.json
index c725d3a64..19d42b21e 100644
--- a/src/Squidex/package.json
+++ b/src/Squidex/package.json
@@ -16,6 +16,7 @@
},
"dependencies": {
"@angular/animations": "8.2.9",
+ "@angular/cdk": "^8.2.3",
"@angular/common": "8.2.9",
"@angular/core": "8.2.9",
"@angular/forms": "8.2.9",
@@ -31,10 +32,9 @@
"graphiql": "0.13.2",
"graphql": "14.4.2",
"marked": "0.7.0",
- "mersenne-twister": "^1.1.0",
+ "mersenne-twister": "1.1.0",
"moment": "2.24.0",
"mousetrap": "1.6.3",
- "ng2-dnd": "5.0.2",
"ngx-color-picker": "8.2.0",
"oidc-client": "1.9.1",
"pikaday": "1.8.0",
@@ -43,18 +43,19 @@
"react-dom": "16.10.2",
"rxjs": "6.5.3",
"slugify": "1.3.5",
- "sortablejs": "1.10.1",
+ "sortablejs": "^1.10.1",
"tslib": "1.10.0",
"zone.js": "0.10.2"
},
"devDependencies": {
+ "@angular-devkit/build-optimizer": "0.803.8",
"@angular/compiler": "8.2.9",
"@angular/compiler-cli": "8.2.9",
"@ngtools/webpack": "8.3.8",
"@types/core-js": "2.5.2",
"@types/jasmine": "3.4.2",
"@types/marked": "0.6.5",
- "@types/mersenne-twister": "^1.1.2",
+ "@types/mersenne-twister": "1.1.2",
"@types/mousetrap": "1.6",
"@types/node": "12.7.11",
"@types/react": "16.9.5",
|