Browse Source

Work to convert move error toast notifications to move to top-right of content. (#431)

release/3.x
Ben-Fletcher-UK 6 years ago
committed by Sebastian Stehle
parent
commit
1eab73f31c
  1. 24
      src/Squidex/app/features/content/pages/content/content-page.component.html
  2. 2
      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. 6
      src/Squidex/app/shared/state/contents.state.ts
  6. 41
      src/Squidex/app/theme/_forms.scss

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

@ -36,9 +36,9 @@
<div class="dropdown dropdown-options ml-1" *ngIf="content"> <div class="dropdown dropdown-options ml-1" *ngIf="content">
<sqx-preview-button [schema]="schema" [content]="content"></sqx-preview-button> <sqx-preview-button [schema]="schema" [content]="content"></sqx-preview-button>
<button type="button" class="btn btn-outline-secondary btn-status" (click)="dropdown.toggle()" [disabled]="schema.isSingleton && !content.isPending" <button type="button" class="btn btn-outline-secondary btn-status" (click)="dropdown.toggle()" [disabled]="schema.isSingleton && !content.isPending"
[class.active]="dropdown.isOpen | async" #buttonOptions> [class.active]="dropdown.isOpen | async" #buttonOptions>
<sqx-content-status <sqx-content-status
[status]="content.status" [status]="content.status"
[statusColor]="content.statusColor" [statusColor]="content.statusColor"
[scheduledTo]="content.scheduleJob?.status" [scheduledTo]="content.scheduleJob?.status"
@ -56,7 +56,7 @@
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" (click)="publishChanges()" *ngIf="content.canDraftPublish"> <a class="dropdown-item" (click)="publishChanges()" *ngIf="content.canDraftPublish">
Publish changes Publish changes
</a> </a>
@ -69,10 +69,10 @@
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item dropdown-item-delete" <a class="dropdown-item dropdown-item-delete"
[class.disabled]="!content.canDelete" [class.disabled]="!content.canDelete"
(sqxConfirmClick)="delete()" (sqxConfirmClick)="delete()"
confirmTitle="Delete content" confirmTitle="Delete content"
confirmText="Do you really want to delete the content?"> confirmText="Do you really want to delete the content?">
Delete Delete
</a> </a>
</ng-container> </ng-container>
@ -80,11 +80,11 @@
</ng-container> </ng-container>
</ng-container> </ng-container>
</div> </div>
<button type="button" class="btn btn-secondary ml-1" (click)="saveAsDraft()" *ngIf="content.canDraftPropose"> <button type="button" class="btn btn-secondary ml-1" (click)="saveAsDraft()" *ngIf="content.canDraftPropose">
Save as Draft Save as Draft
</button> </button>
<ng-container *ngIf="content.canUpdate"> <ng-container *ngIf="content.canUpdate">
<button type="submit" class="btn btn-primary ml-1" title="CTRL + S"> <button type="submit" class="btn btn-primary ml-1" title="CTRL + S">
Save Save
@ -93,6 +93,10 @@
<sqx-shortcut keys="ctrl+s" (trigger)="saveAndPublish()"></sqx-shortcut> <sqx-shortcut keys="ctrl+s" (trigger)="saveAndPublish()"></sqx-shortcut>
</ng-container> </ng-container>
</ng-template> </ng-template>
<div>
<sqx-form-error bubble="true" closeable="true" [error]="contentForm.error | async"></sqx-form-error>
</div>
</ng-container> </ng-container>
<ng-container content> <ng-container content>

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

@ -220,7 +220,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD
}); });
} }
} else { } 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).');
} }
} }

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

@ -11,7 +11,7 @@
</ng-container> </ng-container>
<ng-container content> <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"> <div class="form-group name-group">
<label for="schemaName">Name <small class="hint">(required)</small></label> <label for="schemaName">Name <small class="hint">(required)</small></label>

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

@ -5,17 +5,42 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * 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';
@Component({ @Component({
selector: 'sqx-form-error', selector: 'sqx-form-error',
template: ` template: `
<ng-container *ngIf="error"> <ng-container *ngIf="show">
<div class="form-alert form-alert-error" [innerHTML]="error"></div> <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"></div>
</div>
</div>
</ng-container>`, </ng-container>`,
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class FormErrorComponent { export class FormErrorComponent implements OnChanges {
@Input() @Input()
public error: string | null | undefined; public error: string | null | undefined;
@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;
}
} }

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

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

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

@ -67,7 +67,7 @@
// //
// Form alerts. // Form alerts.
// //
.form-alert { .form-alert {
& { & {
@include border-radius(4px); @include border-radius(4px);
@ -77,6 +77,13 @@
font-size: .9rem; font-size: .9rem;
font-weight: normal; font-weight: normal;
padding: .5rem; padding: .5rem;
padding-right: 1.5rem;
}
&-close {
@include absolute(0, 0, auto, auto);
padding: .5rem;
display: none;
} }
&-error { &-error {
@ -87,11 +94,43 @@
background: $color-theme-green-dark; background: $color-theme-green-dark;
} }
&.closeable {
position: relative;
.form-alert-close {
display: inline-block;
}
}
ul { ul {
margin: 0; margin: 0;
} }
} }
.form-bubble {
& {
position: relative;
}
.form-alert {
@include absolute(.25rem, 0, auto, auto);
min-width: 200px;
max-width: 400px;
z-index: 1000;
text-align: left;
&::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 // Control Dropdown item
// //

Loading…
Cancel
Save