Browse Source

Bugfixes and confirmations for all delete buttons.

pull/100/head
Sebastian Stehle 9 years ago
parent
commit
be8711c7a3
  1. 2
      src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts
  2. 22
      src/Squidex/app/features/content/pages/content/content-page.component.html
  3. 33
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  4. 2
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  5. 5
      src/Squidex/app/features/content/shared/content-item.component.html
  6. 34
      src/Squidex/app/features/schemas/pages/schema/field.component.html
  7. 32
      src/Squidex/app/features/schemas/pages/schema/field.component.ts
  8. 8
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
  9. 5
      src/Squidex/app/features/settings/pages/clients/client.component.html
  10. 5
      src/Squidex/app/features/settings/pages/languages/language.component.html
  11. 5
      src/Squidex/app/features/webhooks/pages/webhooks-page.component.html
  12. 51
      src/Squidex/app/framework/angular/confirm-click.directive.ts
  13. 2
      src/Squidex/app/framework/angular/date-time-editor.component.ts
  14. 2
      src/Squidex/app/framework/angular/dialog-renderer.component.html
  15. 12
      src/Squidex/app/framework/angular/dialog-renderer.component.scss
  16. 16
      src/Squidex/app/framework/angular/dialog-renderer.component.ts
  17. 2
      src/Squidex/app/framework/angular/parent-link.directive.ts
  18. 2
      src/Squidex/app/framework/angular/shortcut.component.ts
  19. 2
      src/Squidex/app/framework/angular/template-wrapper.directive.ts
  20. 4
      src/Squidex/app/framework/services/dialog.service.ts
  21. 2
      src/Squidex/app/shared/components/component-base.ts
  22. 2
      src/Squidex/app/shell/pages/app/left-menu.component.ts
  23. 2
      src/Squidex/app/shell/pages/internal/apps-menu.component.ts
  24. 2
      src/Squidex/app/shell/pages/internal/internal-area.component.ts
  25. 2
      src/Squidex/app/shell/pages/internal/profile-menu.component.ts
  26. 4
      src/Squidex/app/theme/_bootstrap-vars.scss

2
src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts

@ -26,7 +26,7 @@ import {
fadeAnimation
]
})
export class EventConsumersPageComponent extends ComponentBase implements OnInit, OnDestroy {
export class EventConsumersPageComponent extends ComponentBase implements OnDestroy, OnInit {
private subscription: Subscription;
public eventConsumerErrorDialog = new ModalView();

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

@ -54,24 +54,4 @@
</sqx-panel>
</form>
<router-outlet></router-outlet>
<div class="modal" *sqxModalView="cancelDialog;onRoot:true" [@fade]>
<div class="modal-backdrop"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Unsaved changes</h4>
</div>
<div class="modal-body">
You have unsaved changes, do you want to close the current content view?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="confirmLeave()">Yes</button>
<button type="button" class="btn btn-secondary" (click)="cancelLeave()">No</button>
</div>
</div>
</div>
</div>
<router-outlet></router-outlet>

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

@ -8,7 +8,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subject, Subscription } from 'rxjs';
import { Observable, Subscription } from 'rxjs';
import {
ContentCreated,
@ -26,8 +26,6 @@ import {
ContentDto,
ContentsService,
DialogService,
fadeAnimation,
ModalView,
MessageBus,
SchemaDetailsDto,
Version
@ -36,20 +34,15 @@ import {
@Component({
selector: 'sqx-content-page',
styleUrls: ['./content-page.component.scss'],
templateUrl: './content-page.component.html',
animations: [
fadeAnimation
]
templateUrl: './content-page.component.html'
})
export class ContentPageComponent extends AppComponentBase implements CanComponentDeactivate, OnDestroy, OnInit {
private contentDeletedSubscription: Subscription;
private version = new Version('');
private cancelPromise: Subject<boolean> | null = null;
private content: ContentDto;
public schema: SchemaDetailsDto;
public cancelDialog = new ModalView();
public contentFormSubmitted = false;
public contentForm: FormGroup;
public contentData: any = null;
@ -100,27 +93,7 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
if (!this.contentForm.dirty || this.isNewMode) {
return Observable.of(true);
} else {
this.cancelDialog.show();
return this.cancelPromise = new Subject<boolean>();
}
}
public confirmLeave() {
this.cancelDialog.hide();
if (this.cancelPromise) {
this.cancelPromise.next(true);
this.cancelPromise = null;
}
}
public cancelLeave() {
this.cancelDialog.hide();
if (this.cancelPromise) {
this.cancelPromise.next(false);
this.cancelPromise = null;
return this.dialogs.confirmUnsavedChanges();
}
}

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

@ -68,7 +68,7 @@
<tbody *ngIf="!isReadOnly">
<ng-template ngFor let-content [ngForOf]="contentItems")>
<tr [sqxContent]="content" (click)="cacheContent(content)" [routerLink]="[content.id]" routerLinkActive="active"
<tr [sqxContent]="content" [routerLink]="[content.id]" routerLinkActive="active"
[languageCode]="languageSelected.iso2Code"
[schemaFields]="contentFields"
[schema]="schema"

5
src/Squidex/app/features/content/shared/content-item.component.html

@ -23,7 +23,10 @@
<a class="dropdown-item" (click)="unpublishing.emit(); $event.stopPropagation()" *ngIf="content.isPublished">
Unpublish
</a>
<a class="dropdown-item dropdown-item-delete" (click)="deleting.emit(); $event.stopPropagation()">
<a class="dropdown-item dropdown-item-delete"
(sqxConfirmClick)="deleting.emit()"
confirmTitle="Delete content"
confirmText="Do you really want to delete the content?">
Delete
</a>
</div>

34
src/Squidex/app/features/schemas/pages/schema/field.component.html

@ -27,9 +27,6 @@
<i class="icon-dots"></i>
</button>
<div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [sqxModalTarget]="optionsButton" position="right" [@fade]>
<a class="dropdown-item" (click)="askLock()" *ngIf="!field.isLocked">
Lock
</a>
<a class="dropdown-item" (click)="enabling.emit()" *ngIf="field.isDisabled" [class.disabled]="field.isLocked">
Enable
</a>
@ -41,8 +38,17 @@
</a>
<a class="dropdown-item" (click)="showing.emit()" *ngIf="field.isHidden" [class.disabled]="field.isLocked">
Show
</a>
<a class="dropdown-item" *ngIf="!field.isLocked"
(sqxConfirmClick)="locking.emit()"
confirmTitle="Lock field"
confirmText="Do you really want to lock the field? Lock fields cannot be deleted or changed.">
Lock
</a>
<a class="dropdown-item dropdown-item-delete" (click)="deleting.emit()" [class.disabled]="field.isLocked">
<a class="dropdown-item dropdown-item-delete" (sqxConfirmClick)="deleting.emit()" [class.disabled]="field.isLocked"
(sqxConfirmClick)="deleting.emit()"
confirmTitle="Delete field"
confirmText="Do you really want to delete the field?">
Delete
</a>
</div>
@ -186,24 +192,4 @@
</div>
</form>
</div>
</div>
<div class="modal" *sqxModalView="lockDialog;onRoot:true" [@fade]>
<div class="modal-backdrop"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Lock Field</h4>
</div>
<div class="modal-body">
Do you really want to lock the field? Lock fields cannot be changed and deleted.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="confirmLock()">Yes</button>
<button type="button" class="btn btn-secondary" (click)="cancelLock()">No</button>
</div>
</div>
</div>
</div>

32
src/Squidex/app/features/schemas/pages/schema/field.component.ts

@ -32,28 +32,27 @@ export class FieldComponent implements OnInit {
public schemas: SchemaDto[];
@Output()
public locking = new EventEmitter<FieldDto>();
public locking = new EventEmitter();
@Output()
public hiding = new EventEmitter<FieldDto>();
public hiding = new EventEmitter();
@Output()
public showing = new EventEmitter<FieldDto>();
public showing = new EventEmitter();
@Output()
public saving= new EventEmitter<FieldDto>();
public saving= new EventEmitter();
@Output()
public enabling = new EventEmitter<FieldDto>();
public enabling = new EventEmitter();
@Output()
public disabling = new EventEmitter<FieldDto>();
public disabling = new EventEmitter();
@Output()
public deleting = new EventEmitter<FieldDto>();
public deleting = new EventEmitter();
public dropdown = new ModalView(false, true);
public lockDialog = new ModalView(false, true);
public isEditing = false;
public selectedTab = 0;
@ -118,23 +117,6 @@ export class FieldComponent implements OnInit {
}
}
public confirmLock() {
this.lockDialog.hide();
this.emitLocking(this.field);
}
public cancelLock() {
this.lockDialog.hide();
}
public askLock() {
this.lockDialog.show();
}
private emitLocking(field: FieldDto) {
this.locking.emit(field);
}
private emitSaving(field: FieldDto) {
this.saving.emit(field);
}

8
src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts

@ -47,8 +47,6 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
public schema: SchemaDetailsDto;
public schemas: SchemaDto[];
public confirmDeleteDialog = new ModalView();
public exportSchemaDialog = new ModalView();
public editOptionsDropdown = new ModalView();
@ -202,10 +200,8 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
.switchMap(app => this.schemasService.deleteSchema(app, this.schema.name, this.schema.version)).retry(2)
.subscribe(() => {
this.emitSchemaDeleted(this.schema);
this.hideDeleteDialog();
this.back();
}, error => {
this.hideDeleteDialog();
this.notifyError(error);
});
}
@ -300,10 +296,6 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.messageBus.emit(new SchemaUpdated(schema));
}
private hideDeleteDialog() {
this.confirmDeleteDialog.hide();
}
private notify() {
this.messageBus.emit(new HistoryChannelUpdated());
}

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

@ -39,7 +39,10 @@
<div class="client-expires">Access tokens expire after 30 days</div>
</td>
<td class="client-delete">
<button type="button" class="btn btn-link btn-danger" (click)="revoking.emit()">
<button type="button" class="btn btn-link btn-danger"
(sqxConfirmClick)="revoking.emit()"
confirmTitle="Revoke client"
confirmText="Do you really want to revoke the client?">
<i class="icon-bin2"></i>
</button>
</td>

5
src/Squidex/app/features/settings/pages/languages/language.component.html

@ -13,7 +13,10 @@
<i class="icon-settings2"></i>
</button>
<button type="button" class="btn btn-link btn-danger" (click)="removing.emit(language)" [class.invisible]="language.isMaster">
<button type="button" class="btn btn-link btn-danger" [class.invisible]="language.isMaster"
(sqxConfirmClick)="removing.emit(language)"
confirmTitle="Remove language"
confirmText="Do you really want to remove the language?">
<i class="icon-bin2"></i>
</button>
</div>

5
src/Squidex/app/features/webhooks/pages/webhooks-page.component.html

@ -42,7 +42,10 @@
</h3>
</td>
<td class="client-delete">
<button type="button" class="btn btn-link btn-danger" (click)="deleteWebhook(w)">
<button type="button" class="btn btn-link btn-danger"
(sqxConfirmClick)="deleteWebhook(w)"
confirmTitle="Delete webhook"
confirmText="Do you really want to delete the webhook?">
<i class="icon-bin2"></i>
</button>
</td>

51
src/Squidex/app/framework/angular/confirm-click.directive.ts

@ -5,14 +5,37 @@
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core';
import { Directive, EventEmitter, HostListener, Input, OnDestroy, Output } from '@angular/core';
import { DialogService } from './../services/dialog.service';
class DelayEventEmitter<T> extends EventEmitter<T> {
private delayedNexts: any[] = [];
public delayEmit() {
for (let callback of this.delayedNexts) {
callback();
}
}
public clear() {
this.delayedNexts = null;
}
public subscribe(generatorOrNext?: any, error?: any, complete?: any): any {
this.delayedNexts.push(generatorOrNext);
return super.subscribe(generatorOrNext, error, complete);
}
}
@Directive({
selector: '[sqxConfirmClick]'
})
export class ConfirmClickDirective {
export class ConfirmClickDirective implements OnDestroy {
private isOpen = false;
private isDestroyed = false;
@Input()
public confirmTitle: string;
@ -20,13 +43,21 @@ export class ConfirmClickDirective {
public confirmText: string;
@Output('sqxConfirmClick')
public click = new EventEmitter();
public clickConfirmed = new DelayEventEmitter();
constructor(
private readonly dialogService: DialogService
) {
}
public ngOnDestroy() {
this.isDestroyed = true;
if (!this.isOpen) {
this.clickConfirmed.clear();
}
}
@HostListener('click', ['$event'])
public onClick(event: Event) {
if (this.confirmTitle &&
@ -34,17 +65,27 @@ export class ConfirmClickDirective {
this.confirmText &&
this.confirmText.length > 0) {
this.isOpen = true;
let subscription =
this.dialogService.confirm(this.confirmTitle, this.confirmText)
.subscribe(result => {
this.isOpen = false;
if (result) {
this.click.emit();
if (result) {
this.clickConfirmed.delayEmit();
}
}
subscription.unsubscribe();
if (this.isDestroyed) {
this.clickConfirmed.clear();
}
});
} else {
this.click.emit();
this.clickConfirmed.emit();
}
event.stopPropagation();

2
src/Squidex/app/framework/angular/date-time-editor.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { AfterViewInit, Component, forwardRef, ElementRef, Input, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, Component, forwardRef, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subscription } from 'rxjs';
import * as moment from 'moment';

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

@ -1,4 +1,4 @@
<div class="modal" *sqxModalView="dialogView;onRoot:true" [@fade]>
<div class="modal" *sqxModalView="dialogView;onRoot:true">
<div class="modal-backdrop"></div>
<div class="modal-dialog">
<div class="modal-content">

12
src/Squidex/app/framework/angular/dialog-renderer.component.scss

@ -10,19 +10,19 @@
z-index: 100000;
}
&-righttop {
&-topright {
@include fixed(0, 0, auto, auto);
}
&-rightbottom {
@include fixed(auto, 0, 0, auto);
&-topleft {
@include fixed(0, auto, auto, 0);
}
&-lefttop {
@include fixed(0, auto, auto, 0);
&-bottomright {
@include fixed(auto, 0, 0, auto);
}
&-leftbottom {
&-bottomleft {
@include fixed(auto, auto, 0, 0);
}
}

16
src/Squidex/app/framework/angular/dialog-renderer.component.ts

@ -8,8 +8,6 @@
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { fadeAnimation } from './animations';
import {
DialogRequest,
DialogService,
@ -21,12 +19,10 @@ import { ModalView } from './../utils/modal-view';
@Component({
selector: 'sqx-dialog-renderer',
styleUrls: ['./dialog-renderer.component.scss'],
templateUrl: './dialog-renderer.component.html',
animations: [
fadeAnimation
]
templateUrl: './dialog-renderer.component.html'
})
export class DialogRendererComponent implements OnDestroy, OnInit {
private dialogSubscription: Subscription;
private dialogsSubscription: Subscription;
private notificationsSubscription: Subscription;
@ -45,10 +41,18 @@ export class DialogRendererComponent implements OnDestroy, OnInit {
public ngOnDestroy() {
this.notificationsSubscription.unsubscribe();
this.dialogSubscription.unsubscribe();
this.dialogsSubscription.unsubscribe();
}
public ngOnInit() {
this.dialogSubscription =
this.dialogView.isOpen.subscribe(isOpen => {
if (!isOpen) {
this.cancel();
}
});
this.notificationsSubscription =
this.dialogService.notifications.subscribe(notification => {
this.notifications.push(notification);

2
src/Squidex/app/framework/angular/parent-link.directive.ts

@ -12,7 +12,7 @@ import { Subscription } from 'rxjs';
@Directive({
selector: '[sqxParentLink]'
})
export class ParentLinkDirective implements OnInit, OnDestroy {
export class ParentLinkDirective implements OnDestroy, OnInit {
private urlSubscription: Subscription;
private url: string;

2
src/Squidex/app/framework/angular/shortcut.component.ts

@ -13,7 +13,7 @@ import { ShortcutService } from './../services/shortcut.service';
selector: 'sqx-shortcut',
template: ''
})
export class ShortcutComponent implements OnInit, OnDestroy {
export class ShortcutComponent implements OnDestroy, OnInit {
@Input()
public keys: string;

2
src/Squidex/app/framework/angular/template-wrapper.directive.ts

@ -10,7 +10,7 @@ import { Directive, EmbeddedViewRef, Input, OnChanges, OnDestroy, OnInit, Simple
@Directive({
selector: '[sqxTemplateWrapper]'
})
export class TemplateWrapperDirective implements OnInit, OnDestroy, OnChanges {
export class TemplateWrapperDirective implements OnDestroy, OnInit, OnChanges {
@Input()
public item: any;

4
src/Squidex/app/framework/services/dialog.service.ts

@ -65,6 +65,10 @@ export class DialogService {
this.notificationsStream$.next(notification);
}
public confirmUnsavedChanges(): Observable<boolean> {
return this.confirm('Unsaved changes', 'You have unsaved changes, do you want to close the current content view?');
}
public confirm(title: string, text: string): Observable<boolean> {
const request = new DialogRequest(title, text);

2
src/Squidex/app/shared/components/component-base.ts

@ -13,7 +13,7 @@ import {
export abstract class ComponentBase {
constructor(
private readonly dialogs: DialogService
public readonly dialogs: DialogService
) {
}

2
src/Squidex/app/shell/pages/app/left-menu.component.ts

@ -15,7 +15,7 @@ import { AppsStoreService } from 'shared';
styleUrls: ['./left-menu.component.scss'],
templateUrl: './left-menu.component.html'
})
export class LeftMenuComponent implements OnInit, OnDestroy {
export class LeftMenuComponent implements OnDestroy, OnInit {
private appSubscription: Subscription;
public permission: string | null = null;

2
src/Squidex/app/shell/pages/internal/apps-menu.component.ts

@ -25,7 +25,7 @@ const FALLBACK_NAME = 'Apps Overview';
fadeAnimation
]
})
export class AppsMenuComponent implements OnInit, OnDestroy {
export class AppsMenuComponent implements OnDestroy, OnInit {
private appsSubscription: Subscription;
private appSubscription: Subscription;

2
src/Squidex/app/shell/pages/internal/internal-area.component.ts

@ -16,7 +16,7 @@ import { DialogService, Notification } from 'shared';
styleUrls: ['./internal-area.component.scss'],
templateUrl: './internal-area.component.html'
})
export class InternalAreaComponent implements OnInit, OnDestroy {
export class InternalAreaComponent implements OnDestroy, OnInit {
private queryParamsSubscription: Subscription;
public notifications: Notification[] = [];

2
src/Squidex/app/shell/pages/internal/profile-menu.component.ts

@ -23,7 +23,7 @@ import {
fadeAnimation
]
})
export class ProfileMenuComponent implements OnInit, OnDestroy {
export class ProfileMenuComponent implements OnDestroy, OnInit {
private authenticationSubscription: Subscription;
public modalMenu = new ModalView(false, true);

4
src/Squidex/app/theme/_bootstrap-vars.scss

@ -16,15 +16,19 @@ $brand-danger: $color-theme-error;
$brand-warning: $color-theme-orange;
$alert-success-bg: $color-theme-green;
$alert-success-border: $color-theme-green;
$alert-success-text: #fff;
$alert-info-bg: $color-theme-blue;
$alert-info-border: $color-theme-blue;
$alert-info-text: #fff;
$alert-warning-bg: $color-theme-orange;
$alert-warning-border: $color-theme-orange;
$alert-warning-text: #fff;
$alert-danger-bg: $color-theme-error;
$alert-danger-border: $color-theme-error;
$alert-danger-text: #fff;
$btn-secondary-bg: $color-theme-secondary;

Loading…
Cancel
Save