Browse Source

Merge branch 'master' of github.com:Squidex/squidex

# Conflicts:
#	src/Squidex/app/framework/angular/forms/form-error.component.ts
release/3.x
Sebastian 6 years ago
parent
commit
07f44f6014
  1. 2
      src/Squidex/app/features/content/pages/content/content-page.component.html
  2. 29
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  3. 2
      src/Squidex/app/features/schemas/pages/schemas/schema-form.component.html
  4. 33
      src/Squidex/app/framework/angular/forms/form-error.component.ts
  5. 3
      src/Squidex/app/framework/angular/modals/dialog-renderer.component.html
  6. 6
      src/Squidex/app/shared/state/contents.state.ts
  7. 42
      src/Squidex/app/theme/_forms.scss
  8. 85
      tests/Squidex.Domain.Apps.Core.Tests/Operations/EventSynchronization/SchemaSynchronizerTests.cs

2
src/Squidex/app/features/content/pages/content/content-page.component.html

@ -93,6 +93,8 @@
<sqx-shortcut keys="ctrl+s" (trigger)="saveAndPublish()"></sqx-shortcut>
</ng-container>
</ng-template>
<sqx-form-error bubble="true" closeable="true" [error]="contentForm.error | async"></sqx-form-error>
</ng-container>
<ng-container content>

29
src/Squidex/app/features/content/pages/content/content-page.component.ts

@ -156,12 +156,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD
}
public canDeactivate(): Observable<boolean> {
const observable =
this.contentForm.hasChanged() ?
this.dialogs.confirm('Unsaved changes', 'You have unsaved changes, do you want to close the current content view and discard your changes?') :
of(true);
return observable.pipe(
return this.checkPendingChanges('close current content view').pipe(
tap(confirmed => {
if (confirmed) {
this.autoSaveService.remove(this.autoSaveKey);
@ -225,7 +220,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD
});
}
} else {
this.dialogs.notifyError('Content element not valid, please check the field with the red bar on the left in all languages (if localizable).');
this.contentForm.submitFailed('Content element not valid, please check the field with the red bar on the left in all languages (if localizable).');
}
}
@ -253,17 +248,29 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD
}
public publishChanges() {
this.dueTimeSelector.selectDueTime('Publish').pipe(
switchMap(d => this.contentsState.publishDraft(this.content, d)), onErrorResumeNext())
this.checkPendingChanges('publish your changes').pipe(
filter(x => !!x),
switchMap(_ => this.dueTimeSelector.selectDueTime(status)),
switchMap(d => this.contentsState.publishDraft(this.content, d)),
onErrorResumeNext())
.subscribe();
}
public changeStatus(status: string) {
this.dueTimeSelector.selectDueTime(status).pipe(
switchMap(d => this.contentsState.changeStatus(this.content, status, d)), onErrorResumeNext())
this.checkPendingChanges('change the status').pipe(
filter(x => !!x),
switchMap(_ => this.dueTimeSelector.selectDueTime(status)),
switchMap(d => this.contentsState.changeStatus(this.content, status, d)),
onErrorResumeNext())
.subscribe();
}
private checkPendingChanges(action: string) {
return this.contentForm.hasChanged() ?
this.dialogs.confirm('Unsaved changes', `You have unsaved changes. When you ${action} you will loose them.<br />Do you want to continue anyway?`) :
of(true);
}
public showLatest() {
this.loadVersion(null, false);
}

2
src/Squidex/app/features/schemas/pages/schemas/schema-form.component.html

@ -11,7 +11,7 @@
</ng-container>
<ng-container content>
<sqx-form-error [error]="createForm.error | async"></sqx-form-error>
<sqx-form-error closeable="true" [error]="createForm.error | async"></sqx-form-error>
<div class="form-group name-group">
<label for="schemaName">Name <small class="hint">(required)</small></label>

33
src/Squidex/app/framework/angular/forms/form-error.component.ts

@ -5,19 +5,44 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { ErrorDto } from '@app/framework/internal';
@Component({
selector: 'sqx-form-error',
template: `
<ng-container *ngIf="error">
<div class="form-alert form-alert-error" [innerHTML]="error?.displayMessage"></div>
<ng-container *ngIf="show">
<div [class.form-bubble]="bubble">
<div class="form-alert form-alert-error" [class.closeable]="closeable">
<a class="form-alert-close" (click)="close()">
<i class="icon-close"></i>
</a>
<div [innerHTML]="error?.displayMessage"></div>
</div>
</div>
</ng-container>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormErrorComponent {
export class FormErrorComponent implements OnChanges {
@Input()
public error?: ErrorDto | null;
@Input()
public bubble = false;
@Input()
public closeable = false;
public show: boolean;
public ngOnChanges(changes: SimpleChanges) {
if (changes['error']) {
this.show = !!this.error;
}
}
public close() {
this.show = false;
}
}

3
src/Squidex/app/framework/angular/modals/dialog-renderer.component.html

@ -1,6 +1,5 @@
<ng-content></ng-content>
<ng-container *sqxModal="dialogView">
<sqx-modal-dialog showClose="false" (close)="cancel()">
<ng-container title>
@ -8,7 +7,7 @@
</ng-container>
<ng-container content>
{{snapshot.dialogRequest?.text}}
<span [innerHTML]="snapshot.dialogRequest?.text"></span>
</ng-container>
<ng-container footer>

6
src/Squidex/app/shared/state/contents.state.ts

@ -197,7 +197,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
return { ...s, contents, contentsPager };
});
}),
shareSubscribed(this.dialogs));
shareSubscribed(this.dialogs, {silent: true}));
}
public changeManyStatus(contents: ReadonlyArray<ContentDto>, status: string, dueTime: string | null): Observable<any> {
@ -263,7 +263,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
this.replaceContent(updated, content.version);
}),
shareSubscribed(this.dialogs));
shareSubscribed(this.dialogs, { silent: true }));
}
public proposeDraft(content: ContentDto, request: any): Observable<ContentDto> {
@ -273,7 +273,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
this.replaceContent(updated, content.version);
}),
shareSubscribed(this.dialogs));
shareSubscribed(this.dialogs, { silent: true }));
}
public discardDraft(content: ContentDto): Observable<ContentDto> {

42
src/Squidex/app/theme/_forms.scss

@ -77,6 +77,13 @@
font-size: .9rem;
font-weight: normal;
padding: .5rem;
padding-right: 1.5rem;
}
&-close {
@include absolute(0, 0, auto, auto);
padding: .5rem;
display: none;
}
&-error {
@ -87,11 +94,46 @@
background: $color-theme-green-dark;
}
&.closeable {
position: relative;
.form-alert-close {
display: inline-block;
}
}
ul {
margin: 0;
}
}
.form-bubble {
& {
position: relative;
}
.form-alert {
@include absolute(.25rem, 0, auto, auto);
padding: 1rem;
min-width: 200px;
max-width: 400px;
font-size: 1rem;
font-weight: normal;
text-align: left;
z-index: 1000;
&::after {
@include absolute(-.75rem, .625rem, auto, auto);
content: '';
height: 0;
border-style: solid;
border-width: .4rem;
border-color: transparent transparent $color-theme-error;
width: 0;
}
}
}
//
// Control Dropdown item
//

85
tests/Squidex.Domain.Apps.Core.Tests/Operations/EventSynchronization/SchemaSynchronizerTests.cs

@ -1,4 +1,5 @@
// ==========================================================================

// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -33,8 +34,11 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
[Fact]
public void Should_create_events_if_schema_deleted()
{
var sourceSchema = new Schema("source");
var targetSchema = (Schema)null;
var sourceSchema =
new Schema("source");
var targetSchema =
(Schema)null;
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -46,8 +50,12 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
[Fact]
public void Should_create_events_if_category_changed()
{
var sourceSchema = new Schema("source");
var targetSchema = new Schema("target").ChangeCategory("Category");
var sourceSchema =
new Schema("source");
var targetSchema =
new Schema("target")
.ChangeCategory("Category");
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -64,8 +72,11 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
Create = "<create-script>"
};
var sourceSchema = new Schema("source");
var targetSchema = new Schema("target").ConfigureScripts(scripts);
var sourceSchema =
new Schema("source");
var targetSchema =
new Schema("target").ConfigureScripts(scripts);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -82,8 +93,12 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
["web"] = "Url"
};
var sourceSchema = new Schema("source");
var targetSchema = new Schema("target").ConfigurePreviewUrls(previewUrls);
var sourceSchema =
new Schema("source");
var targetSchema =
new Schema("target")
.ConfigurePreviewUrls(previewUrls);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -95,8 +110,12 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
[Fact]
public void Should_create_events_if_schema_published()
{
var sourceSchema = new Schema("source");
var targetSchema = new Schema("target").Publish();
var sourceSchema =
new Schema("source");
var targetSchema =
new Schema("target")
.Publish();
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -108,8 +127,12 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
[Fact]
public void Should_create_events_if_schema_unpublished()
{
var sourceSchema = new Schema("source").Publish();
var targetSchema = new Schema("target");
var sourceSchema =
new Schema("source")
.Publish();
var targetSchema =
new Schema("target");
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -207,7 +230,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f
.AddString(nestedId.Id, nestedId.Name)).LockField(nestedId.Id, arrayId.Id);
.AddString(nestedId.Id, nestedId.Name))
.LockField(nestedId.Id, arrayId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -225,7 +249,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).LockField(stringId.Id);
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant)
.LockField(stringId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -245,7 +270,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f
.AddString(nestedId.Id, nestedId.Name)).HideField(nestedId.Id, arrayId.Id);
.AddString(nestedId.Id, nestedId.Name))
.HideField(nestedId.Id, arrayId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -263,7 +289,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).HideField(stringId.Id);
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant)
.HideField(stringId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -278,7 +305,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var sourceSchema =
new Schema("source")
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f
.AddString(nestedId.Id, nestedId.Name)).HideField(nestedId.Id, arrayId.Id);
.AddString(nestedId.Id, nestedId.Name))
.HideField(nestedId.Id, arrayId.Id);
var targetSchema =
new Schema("target")
@ -297,7 +325,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
{
var sourceSchema =
new Schema("source")
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).HideField(stringId.Id);
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant)
.HideField(stringId.Id);
var targetSchema =
new Schema("target")
@ -321,7 +350,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f
.AddString(nestedId.Id, nestedId.Name)).DisableField(nestedId.Id, arrayId.Id);
.AddString(nestedId.Id, nestedId.Name))
.DisableField(nestedId.Id, arrayId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -339,7 +369,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).DisableField(stringId.Id);
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant)
.DisableField(stringId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -354,7 +385,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var sourceSchema =
new Schema("source")
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f
.AddString(nestedId.Id, nestedId.Name)).DisableField(nestedId.Id, arrayId.Id);
.AddString(nestedId.Id, nestedId.Name))
.DisableField(nestedId.Id, arrayId.Id);
var targetSchema =
new Schema("target")
@ -373,7 +405,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
{
var sourceSchema =
new Schema("source")
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).DisableField(stringId.Id);
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant)
.DisableField(stringId.Id);
var targetSchema =
new Schema("target")
@ -394,7 +427,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).HideField(stringId.Id);
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant)
.HideField(stringId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);
@ -457,7 +491,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization
var targetSchema =
new Schema("target")
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f
.AddString(nestedId.Id, nestedId.Name)).HideField(nestedId.Id, arrayId.Id);
.AddString(nestedId.Id, nestedId.Name))
.HideField(nestedId.Id, arrayId.Id);
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator);

Loading…
Cancel
Save