From eb78dc66ed6464e9c76bf8bf3805b0dba3166996 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 19 Mar 2020 17:21:11 +0100 Subject: [PATCH] Inline editor for references. --- .../Controllers/Schemas/Models/SchemaDto.cs | 7 + frontend/app/features/content/declarations.ts | 1 + frontend/app/features/content/module.ts | 2 + .../content/content-field.component.scss | 12 -- .../pages/content/content-page.component.html | 8 +- .../pages/content/content-page.component.ts | 4 - .../references/content-creator.component.html | 56 +++++++ .../references/content-creator.component.scss | 11 ++ .../references/content-creator.component.ts | 141 ++++++++++++++++++ .../content-selector.component.html | 12 +- .../references-editor.component.html | 25 +++- .../references-editor.component.scss | 6 +- .../references/references-editor.component.ts | 6 +- .../schema/fields/field-wizard.component.html | 10 +- .../app/shared/services/schemas.service.ts | 6 + 15 files changed, 264 insertions(+), 43 deletions(-) create mode 100644 frontend/app/features/content/shared/references/content-creator.component.html create mode 100644 frontend/app/features/content/shared/references/content-creator.component.scss create mode 100644 frontend/app/features/content/shared/references/content-creator.component.ts diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs index 3c9fd858a..bf8b9a43f 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs @@ -105,6 +105,13 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models AddGetLink("contents", controller.Url(x => nameof(x.GetContents), values)); } + if (controller.HasPermission(Permissions.AppContentsCreate, app, Name)) + { + AddPostLink("contents/create", controller.Url(x => nameof(x.PostContent), values)); + + AddPostLink("contents/create/publish", controller.Url(x => nameof(x.PostContent), values) + "?publish=true"); + } + if (controller.HasPermission(Permissions.AppSchemasPublish, app, Name)) { if (IsPublished) diff --git a/frontend/app/features/content/declarations.ts b/frontend/app/features/content/declarations.ts index ce183ac66..7164ff7d7 100644 --- a/frontend/app/features/content/declarations.ts +++ b/frontend/app/features/content/declarations.ts @@ -35,5 +35,6 @@ export * from './shared/list/content.component'; export * from './shared/references/content-selector-item.component'; export * from './shared/references/content-selector.component'; +export * from './shared/references/content-creator.component'; export * from './shared/references/reference-item.component'; export * from './shared/references/references-editor.component'; \ No newline at end of file diff --git a/frontend/app/features/content/module.ts b/frontend/app/features/content/module.ts index a85c1215c..cc2f1433f 100644 --- a/frontend/app/features/content/module.ts +++ b/frontend/app/features/content/module.ts @@ -25,6 +25,7 @@ import { AssetsEditorComponent, CommentsPageComponent, ContentComponent, + ContentCreatorComponent, ContentEventComponent, ContentFieldComponent, ContentHistoryPageComponent, @@ -118,6 +119,7 @@ const routes: Routes = [ AssetsEditorComponent, CommentsPageComponent, ContentComponent, + ContentCreatorComponent, ContentEventComponent, ContentFieldComponent, ContentHistoryPageComponent, diff --git a/frontend/app/features/content/pages/content/content-field.component.scss b/frontend/app/features/content/pages/content/content-field.component.scss index 338171a33..21271daf5 100644 --- a/frontend/app/features/content/pages/content/content-field.component.scss +++ b/frontend/app/features/content/pages/content/content-field.component.scss @@ -7,25 +7,13 @@ @include absolute(.25rem, 1.25rem); } -.row { - margin-left: -1.5rem; - margin-right: -1.5rem; -} - -.col-12 { - padding-left: 1.5rem; - padding-right: 1.5rem; -} - .col-6 { & { - padding-left: 1.5rem; padding-right: .5rem; } &.col-right { padding-left: .5rem; - padding-right: 1.5rem; } } diff --git a/frontend/app/features/content/pages/content/content-page.component.html b/frontend/app/features/content/pages/content/content-page.component.html index 1d3a6d27a..4e849dad0 100644 --- a/frontend/app/features/content/pages/content/content-page.component.html +++ b/frontend/app/features/content/pages/content/content-page.component.html @@ -82,14 +82,14 @@
+ [schema]="schema">
diff --git a/frontend/app/features/content/pages/content/content-page.component.ts b/frontend/app/features/content/pages/content/content-page.component.ts index 2f89c9400..39a027e62 100644 --- a/frontend/app/features/content/pages/content/content-page.component.ts +++ b/frontend/app/features/content/pages/content/content-page.component.ts @@ -150,10 +150,6 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD this.saveContent(true); } - public saveAsDraft() { - this.saveContent(false); - } - public save() { this.saveContent(false); } diff --git a/frontend/app/features/content/shared/references/content-creator.component.html b/frontend/app/features/content/shared/references/content-creator.component.html new file mode 100644 index 000000000..bf52a96b9 --- /dev/null +++ b/frontend/app/features/content/shared/references/content-creator.component.html @@ -0,0 +1,56 @@ + + +
+
+ +
+
+
+ + +
+
+
+ + +
+
+ +
+ + + + + +
+
+
+ + + +
+ + +
+
+
+
\ No newline at end of file diff --git a/frontend/app/features/content/shared/references/content-creator.component.scss b/frontend/app/features/content/shared/references/content-creator.component.scss new file mode 100644 index 000000000..085d0a35c --- /dev/null +++ b/frontend/app/features/content/shared/references/content-creator.component.scss @@ -0,0 +1,11 @@ +:host ::ng-deep { + .modal-tabs { + background: $color-white; + padding-left: 1.75rem; + padding-right: 1.75rem; + } + + .modal-content { + background: $color-background; + } +} \ No newline at end of file diff --git a/frontend/app/features/content/shared/references/content-creator.component.ts b/frontend/app/features/content/shared/references/content-creator.component.ts new file mode 100644 index 000000000..eee52effc --- /dev/null +++ b/frontend/app/features/content/shared/references/content-creator.component.ts @@ -0,0 +1,141 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + +import { + ApiUrlConfig, + AppLanguageDto, + AppsState, + AuthService, + ContentDto, + EditContentForm, + LanguageDto, + ManualContentsState, + ResourceOwner, + SchemaDetailsDto, + SchemaDto, + SchemasState, + Types +} from '@app/shared'; + +@Component({ + selector: 'sqx-content-creator', + styleUrls: ['./content-creator.component.scss'], + templateUrl: './content-creator.component.html', + providers: [ + ManualContentsState + ] +}) +export class ContentCreatorComponent extends ResourceOwner implements OnInit { + @Output() + public select = new EventEmitter>(); + + @Input() + public schemaIds: ReadonlyArray; + + @Input() + public language: LanguageDto; + + @Input() + public languages: ReadonlyArray; + + public schema: SchemaDetailsDto; + public schemas: ReadonlyArray = []; + + public contentFormContext: any; + public contentForm: EditContentForm; + + constructor(authService: AuthService, + public readonly appsState: AppsState, + public readonly apiUrl: ApiUrlConfig, + public readonly contentsState: ManualContentsState, + public readonly schemasState: SchemasState, + private readonly changeDetector: ChangeDetectorRef + ) { + super(); + + this.contentFormContext = { user: authService.user, apiUrl: apiUrl.buildUrl('api') }; + } + + public ngOnInit() { + this.schemas = this.schemasState.snapshot.schemas.filter(x => x.canContentsCreate); + + if (this.schemaIds && this.schemaIds.length > 0) { + this.schemas = this.schemas.filter(x => this.schemaIds.indexOf(x.id) >= 0); + } + + this.selectSchema(this.schemas[0]); + } + + public selectSchema(selected: string | SchemaDto) { + if (Types.is(selected, SchemaDto)) { + selected = selected.id; + } + + this.schemasState.loadSchema(selected, true) + .subscribe(schema => { + if (schema) { + this.schema = schema; + + this.contentsState.schema = schema; + this.contentForm = new EditContentForm(this.languages, this.schema); + + this.changeDetector.markForCheck(); + } + }); + } + + public saveAndPublish() { + this.saveContent(true); + } + + public save() { + this.saveContent(false); + } + + private saveContent(publish: boolean) { + const value = this.contentForm.submit(); + + if (value) { + if (!this.canCreate(publish)) { + return; + } + + this.contentsState.create(value, publish) + .subscribe(content => { + this.contentForm.submitCompleted({ noReset: true }); + + this.emitSelect(content); + }, error => { + this.contentForm.submitFailed(error); + }); + } else { + this.contentForm.submitFailed('Content element not valid, please check the field with the red bar on the left in all languages (if localizable).'); + } + } + + private canCreate(publish: boolean) { + if (publish) { + return this.schema.canContentsCreateAndPublish; + } else { + return this.schema.canContentsCreateAndPublish; + } + } + + public emitComplete() { + this.select.emit([]); + } + + public emitSelect(content: ContentDto) { + this.select.emit([content]); + } + + public selectLanguage(language: LanguageDto) { + this.language = language; + } +} \ No newline at end of file diff --git a/frontend/app/features/content/shared/references/content-selector.component.html b/frontend/app/features/content/shared/references/content-selector.component.html index ed50dd9f8..b295a97df 100644 --- a/frontend/app/features/content/shared/references/content-selector.component.html +++ b/frontend/app/features/content/shared/references/content-selector.component.html @@ -29,14 +29,10 @@ -
- -
- -
- - - +
+ +
diff --git a/frontend/app/features/content/shared/references/references-editor.component.html b/frontend/app/features/content/shared/references/references-editor.component.html index e9d8c63d1..2cf613450 100644 --- a/frontend/app/features/content/shared/references/references-editor.component.html +++ b/frontend/app/features/content/shared/references/references-editor.component.html @@ -4,8 +4,12 @@ [sqxResizeMaxWidth]="0">
-
- Click here to link content items. +
+ Add New + + · + + Select Existing
@@ -19,10 +23,10 @@ class="table-drag" cdkDrag cdkDragLockAxis="y" - [language]="language" [columns]="snapshot.columns" [isCompact]="snapshot.isCompact" [isDisabled]="snapshot.isDisabled" + [language]="language" (delete)="remove(content)"> @@ -30,13 +34,22 @@
- + + + + + + + [schemaIds]="schemaIds"> \ No newline at end of file diff --git a/frontend/app/features/content/shared/references/references-editor.component.scss b/frontend/app/features/content/shared/references/references-editor.component.scss index 3b3f653ef..93e444171 100644 --- a/frontend/app/features/content/shared/references/references-editor.component.scss +++ b/frontend/app/features/content/shared/references/references-editor.component.scss @@ -32,8 +32,10 @@ transition: border-color .4s ease; } - &:hover { - text-decoration: underline; + a { + &:hover { + text-decoration: underline; + } } } diff --git a/frontend/app/features/content/shared/references/references-editor.component.ts b/frontend/app/features/content/shared/references/references-editor.component.ts index ff6b7120b..88d4a918c 100644 --- a/frontend/app/features/content/shared/references/references-editor.component.ts +++ b/frontend/app/features/content/shared/references/references-editor.component.ts @@ -57,7 +57,8 @@ export class ReferencesEditorComponent extends StatefulControlComponentCancel
- - - + + +
- - + +
\ No newline at end of file diff --git a/frontend/app/shared/services/schemas.service.ts b/frontend/app/shared/services/schemas.service.ts index f441801ca..0c8815b15 100644 --- a/frontend/app/shared/services/schemas.service.ts +++ b/frontend/app/shared/services/schemas.service.ts @@ -55,6 +55,9 @@ export class SchemaDto { public readonly _links: ResourceLinks; public readonly canAddField: boolean; + public readonly canContentsRead: boolean; + public readonly canContentsCreate: boolean; + public readonly canContentsCreateAndPublish: boolean; public readonly canDelete: boolean; public readonly canOrderFields: boolean; public readonly canPublish: boolean; @@ -85,6 +88,9 @@ export class SchemaDto { this._links = links; this.canAddField = hasAnyLink(links, 'fields/add'); + this.canContentsRead = hasAnyLink(links, 'contents'); + this.canContentsCreate = hasAnyLink(links, 'contents/create'); + this.canContentsCreateAndPublish = hasAnyLink(links, 'contents/create/publish'); this.canDelete = hasAnyLink(links, 'delete'); this.canOrderFields = hasAnyLink(links, 'fields/order'); this.canPublish = hasAnyLink(links, 'publish');