Browse Source

Modal handling improved.

pull/95/head
Sebastian Stehle 9 years ago
parent
commit
e41dd12187
  1. 53
      src/Squidex/app/features/administration/pages/users/user-page.component.ts
  2. 52
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  3. 62
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  4. 2
      src/Squidex/app/features/schemas/pages/schema/field.component.html
  5. 6
      src/Squidex/app/features/schemas/pages/schema/field.component.scss
  6. 30
      src/Squidex/app/features/schemas/pages/schema/field.component.ts
  7. 42
      src/Squidex/app/features/schemas/pages/schema/schema-edit-form.component.ts
  8. 2
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
  9. 48
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
  10. 27
      src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts
  11. 2
      src/Squidex/app/features/settings/pages/clients/clients-page.component.html
  12. 6
      src/Squidex/app/features/settings/pages/clients/clients-page.component.ts
  13. 14
      src/Squidex/app/features/settings/pages/languages/language.component.ts
  14. 2
      src/Squidex/app/features/settings/pages/plans/plans-page.component.ts
  15. 2
      src/Squidex/app/features/webhooks/pages/webhooks-page.component.html
  16. 37
      src/Squidex/app/features/webhooks/pages/webhooks-page.component.ts
  17. 90
      src/Squidex/app/framework/angular/modal-view.directive.ts
  18. 4
      src/Squidex/app/framework/utils/modal-view.ts
  19. 32
      src/Squidex/app/shared/components/app-form.component.ts
  20. 4
      src/Squidex/app/shared/components/asset.component.html
  21. 57
      src/Squidex/app/shared/components/asset.component.ts

53
src/Squidex/app/features/administration/pages/users/user-page.component.ts

@ -56,7 +56,7 @@ export class UserPageComponent extends ComponentBase implements OnInit {
.subscribe((user: UserDto) => {
this.user = user;
this.populateForm();
this.setupAndPopulateForm();
});
}
@ -68,18 +68,6 @@ export class UserPageComponent extends ComponentBase implements OnInit {
const requestDto = this.userForm.value;
const enable = (message?: string) => {
this.userForm.enable();
this.userForm.controls['password'].reset();
this.userForm.controls['passwordConfirm'].reset();
this.userFormSubmitted = false;
this.userFormError = message;
};
const back = () => {
this.router.navigate(['../'], { relativeTo: this.route, replaceUrl: true });
};
if (this.isNewMode) {
this.userManagementService.postUser(requestDto)
.subscribe(created => {
@ -90,12 +78,12 @@ export class UserPageComponent extends ComponentBase implements OnInit {
requestDto.displayName,
created.pictureUrl!,
false);
this.messageBus.publish(new UserCreated(this.user));
this.sendUserCreated(this.user);
this.notifyInfo('User created successfully.');
back();
this.back();
}, error => {
enable(error.displayMessage);
this.resetUserForm(error.displayMessage);
});
} else {
this.userManagementService.putUser(this.userId, requestDto)
@ -105,24 +93,33 @@ export class UserPageComponent extends ComponentBase implements OnInit {
requestDto.email,
requestDto.displayMessage);
this.messageBus.publish(new UserUpdated(this.user));
this.sendUserUpdated(this.user);
this.notifyInfo('User saved successfully.');
enable();
this.resetUserForm();
}, error => {
enable(error.displayMessage);
this.resetUserForm(error.displayMessage);
});
}
}
}
private populateForm() {
private back() {
this.router.navigate(['../'], { relativeTo: this.route, replaceUrl: true });
}
private sendUserCreated(user: UserDto) {
this.messageBus.publish(new UserCreated(user));
}
private sendUserUpdated(user: UserDto) {
this.messageBus.publish(new UserUpdated(user));
}
private setupAndPopulateForm() {
const input = this.user || {};
this.isNewMode = !this.user;
this.userId = input['id'];
this.userFormError = '';
this.userFormSubmitted = false;
this.userForm =
this.formBuilder.group({
email: [input['email'],
@ -147,6 +144,16 @@ export class UserPageComponent extends ComponentBase implements OnInit {
});
this.isCurrentUser = this.userId === this.currentUserId;
this.resetUserForm();
}
private resetUserForm(message: string = '') {
this.userForm.enable();
this.userForm.controls['password'].reset();
this.userForm.controls['passwordConfirm'].reset();
this.userFormSubmitted = false;
this.userFormError = message;
}
}

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

@ -86,13 +86,13 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
}
});
this.setupForm(routeData['schema']);
this.setupContentForm(routeData['schema']);
this.route.data.map(p => p['content'])
.subscribe((content: ContentDto) => {
this.content = content;
this.populateForm();
this.populateContentForm();
});
}
@ -136,27 +136,22 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
this.contentFormSubmitted = true;
if (this.contentForm.valid) {
this.disable();
this.disableContentForm();
const requestDto = this.contentForm.value;
const back = () => {
this.router.navigate(['../'], { relativeTo: this.route, replaceUrl: true });
};
if (this.isNewMode) {
this.appNameOnce()
.switchMap(app => this.contentsService.postContent(app, this.schema.name, requestDto, publish, this.version))
.subscribe(dto => {
this.content = dto;
this.messageBus.publish(new ContentCreated(dto));
this.sendContentCreated(this.content);
this.notifyInfo('Content created successfully.');
back();
this.back();
}, error => {
this.notifyError(error);
this.enable();
this.enableContentForm();
});
} else {
this.appNameOnce()
@ -164,13 +159,12 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
.subscribe(() => {
this.content = this.content.update(requestDto, this.authService.user.token);
this.messageBus.publish(new ContentUpdated(this.content));
this.sendContentUpdated(this.content);
this.notifyInfo('Content saved successfully.');
this.enable();
this.enableContentForm();
}, error => {
this.notifyError(error);
this.enable();
this.enableContentForm();
});
}
} else {
@ -178,21 +172,31 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
}
}
private enable() {
this.contentForm.markAsPristine();
private sendContentCreated(content: ContentDto) {
this.messageBus.publish(new ContentCreated(content));
}
for (const field of this.schema.fields.filter(f => !f.isDisabled)) {
this.contentForm.controls[field.name].enable();
}
private sendContentUpdated(content: ContentDto) {
this.messageBus.publish(new ContentUpdated(content));
}
private disable() {
private back() {
this.router.navigate(['../'], { relativeTo: this.route, replaceUrl: true });
}
private disableContentForm() {
this.contentForm.disable();
}
private enableContentForm() {
this.contentForm.markAsPristine();
for (const field of this.schema.fields.filter(f => !f.isDisabled)) {
this.contentForm.controls[field.name].disable();
this.contentForm.controls[field.name].enable();
}
}
private setupForm(schema: SchemaDetailsDto) {
private setupContentForm(schema: SchemaDetailsDto) {
this.schema = schema;
const controls: { [key: string]: AbstractControl } = {};
@ -214,7 +218,7 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
this.contentForm = new FormGroup(controls);
}
private populateForm() {
private populateContentForm() {
this.contentForm.markAsPristine();
if (!this.content) {

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

@ -98,7 +98,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
.subscribe(schema => {
this.schema = schema;
this.reset();
this.resetContents();
this.load();
});
@ -112,15 +112,6 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.load();
}
private reset() {
this.contentItems = ImmutableArray.empty<ContentDto>();
this.contentsQuery = '';
this.contentsFilter.setValue('');
this.contentsPager = new Pager(0);
this.loadFields();
}
public publishContent(content: ContentDto) {
this.appNameOnce()
.switchMap(app => this.contentsService.publishContent(app, this.schema.name, content.id, content.version))
@ -148,30 +139,12 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.contentItems = this.contentItems.removeAll(x => x.id === content.id);
this.contentsPager = this.contentsPager.decrementCount();
this.messageBus.publish(new ContentDeleted(content));
this.sendContentDeleted(content);
}, error => {
this.notifyError(error);
});
}
public selectLanguage(language: AppLanguageDto) {
this.languageSelected = language;
}
private loadFields() {
this.contentFields = this.schema.fields.filter(x => x.properties.isListField);
if (this.contentFields.length === 0 && this.schema.fields.length > 0) {
this.contentFields = [this.schema.fields[0]];
}
if (this.contentFields.length > 0) {
this.columnWidth = 100 / this.contentFields.length;
} else {
this.columnWidth = 100;
}
}
public load(showInfo = false) {
this.appNameOnce()
.switchMap(app => this.contentsService.getContents(app, this.schema.name, this.contentsPager.pageSize, this.contentsPager.skip, this.contentsQuery))
@ -187,6 +160,10 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
});
}
public selectLanguage(language: AppLanguageDto) {
this.languageSelected = language;
}
public dropData(content: ContentDto) {
return { content, schemaId: this.schema.id };
}
@ -202,5 +179,32 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.load();
}
private resetContents() {
this.contentItems = ImmutableArray.empty<ContentDto>();
this.contentsQuery = '';
this.contentsFilter.setValue('');
this.contentsPager = new Pager(0);
this.loadFields();
}
private loadFields() {
this.contentFields = this.schema.fields.filter(x => x.properties.isListField);
if (this.contentFields.length === 0 && this.schema.fields.length > 0) {
this.contentFields = [this.schema.fields[0]];
}
if (this.contentFields.length > 0) {
this.columnWidth = 100 / this.contentFields.length;
} else {
this.columnWidth = 100;
}
}
private sendContentDeleted(content: ContentDto) {
this.messageBus.publish(new ContentDeleted(content));
}
}

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

@ -6,7 +6,7 @@
<i class="field-icon icon-type-{{field.properties.fieldType}}"></i>
<span [class.field-hidden]="field.isHidden" [attr.title]="field.isHidden ? 'Hidden Field' : 'Visible Field'">{{displayName}}</span>
<span class="field-hints">{{field.properties.hints}}</span>
<span class="field-partitioning" *ngIf="field.partitioning === 'language'">localizable</span>
</span>
</div>
<div class="col col-3">

6
src/Squidex/app/features/schemas/pages/schema/field.component.scss

@ -24,6 +24,12 @@ $field-header: #e7ebef;
color: $color-subtext;
}
&-partitioning {
color: $color-subtext;
font-weight: normal;
font-size: .85rem;
}
.tag {
@include opacity(.9);
min-width: 4rem;

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

@ -79,7 +79,19 @@ export class FieldComponent implements OnInit {
}
public ngOnInit() {
this.resetForm();
this.resetEditForm();
}
public toggleEditing() {
this.isEditing = !this.isEditing;
}
public selectTab(tab: number) {
this.selectedTab = tab;
}
public cancel() {
this.resetEditForm();
}
public save() {
@ -97,23 +109,15 @@ export class FieldComponent implements OnInit {
this.field.partitioning,
properties);
this.saving.emit(field);
this.sendSaving(field);
}
}
public cancel() {
this.resetForm();
}
public toggleEditing() {
this.isEditing = !this.isEditing;
}
public selectTab(tab: number) {
this.selectedTab = tab;
private sendSaving(field: FieldDto) {
this.saving.emit(field);
}
private resetForm() {
private resetEditForm() {
this.editFormSubmitted = false;
this.editForm.reset(this.field.properties);

42
src/Squidex/app/features/schemas/pages/schema/schema-edit-form.component.ts

@ -9,7 +9,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import {
Notification,
ComponentBase,
NotificationService,
SchemaPropertiesDto,
SchemasService,
@ -21,7 +21,7 @@ import {
styleUrls: ['./schema-edit-form.component.scss'],
templateUrl: './schema-edit-form.component.html'
})
export class SchemaEditFormComponent implements OnInit {
export class SchemaEditFormComponent extends ComponentBase implements OnInit {
@Output()
public saved = new EventEmitter<SchemaPropertiesDto>();
@ -53,11 +53,11 @@ export class SchemaEditFormComponent implements OnInit {
]]
});
constructor(
constructor(notifications: NotificationService,
private readonly schemas: SchemasService,
private readonly formBuilder: FormBuilder,
private readonly notifications: NotificationService
private readonly formBuilder: FormBuilder
) {
super(notifications);
}
public ngOnInit() {
@ -65,8 +65,8 @@ export class SchemaEditFormComponent implements OnInit {
}
public cancel() {
this.reset();
this.cancelled.emit();
this.sendCancelled();
this.resetEditForm();
}
public saveSchema() {
@ -75,25 +75,33 @@ export class SchemaEditFormComponent implements OnInit {
if (this.editForm.valid) {
this.editForm.disable();
const enable = () => {
this.editForm.enable();
this.editFormSubmitted = false;
};
const requestDto = this.editForm.value;
this.schemas.putSchema(this.appName, this.name, requestDto, this.version)
.subscribe(dto => {
this.reset();
this.saved.emit(new SchemaPropertiesDto(requestDto.label, requestDto.hints));
this.sendSaved(requestDto);
this.resetEditForm();
}, error => {
enable();
this.notifications.notify(Notification.error(error.displayMessage));
this.notifyError(error);
this.enableEditForm();
});
}
}
private reset() {
private sendCancelled() {
this.cancelled.emit();
}
private sendSaved(requestDto: any) {
this.saved.emit(new SchemaPropertiesDto(requestDto.label, requestDto.hints));
}
private enableEditForm() {
this.editForm.enable();
this.editFormSubmitted = false;
}
private resetEditForm() {
this.editFormSubmitted = false;
this.editForm.reset();
this.editForm.enable();

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

@ -69,7 +69,7 @@
</div>
<button type="submit" class="btn btn-success" [disabled]="!hasName">Add Field</button>
<button type="reset" class="btn btn-link" (click)="resetFieldForm()" [disabled]="addFieldFormSubmitted">Cancel</button>
<button type="button" class="btn btn-link" (click)="cancelAddField()">Cancel</button>
</div>
<div>

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

@ -201,13 +201,12 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.deleteSchema(app, this.schema.name, this.schema.version)).retry(2)
.subscribe(() => {
this.messageBus.publish(new SchemaDeleted(this.schema));
this.router.navigate(['../'], { relativeTo: this.route });
this.sendSchemaDeleted(this.schema);
this.hideDeleteDialog();
this.back();
}, error => {
this.hideDeleteDialog();
this.notifyError(error);
}, () => {
this.confirmDeleteDialog.hide();
});
}
@ -222,27 +221,20 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
const requestDto = new AddFieldDto(this.addFieldForm.controls['name'].value, partitioning, properties);
const reset = () => {
this.addFieldForm.reset({ type: 'String' });
this.addFieldForm.enable();
this.addFieldFormSubmitted = false;
};
this.appNameOnce()
.switchMap(app => this.schemasService.postField(app, this.schema.name, requestDto, this.schema.version))
.subscribe(dto => {
this.updateSchema(this.schema.addField(dto, this.authService.user.token));
reset();
this.resetFieldForm();
}, error => {
this.notifyError(error);
reset();
this.resetFieldForm();
});
}
}
public resetFieldForm() {
this.addFieldForm.reset({ type: 'String' });
this.addFieldFormSubmitted = false;
public cancelAddField() {
this.resetFieldForm();
}
public onSchemaSaved(properties: SchemaPropertiesDto) {
@ -251,9 +243,16 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.editSchemaDialog.hide();
}
private resetFieldForm() {
this.addFieldForm.enable();
this.addFieldForm.reset({ type: 'String' });
this.addFieldFormSubmitted = false;
}
private updateSchema(schema: SchemaDetailsDto) {
this.schema = schema;
this.sendSchemaUpdated(schema);
this.notify();
this.export();
}
@ -289,9 +288,24 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.schemaExport = result;
}
private hideDeleteDialog() {
this.confirmDeleteDialog.hide();
}
private back() {
this.router.navigate(['../'], { relativeTo: this.route });
}
private sendSchemaDeleted(schema: SchemaDto) {
this.messageBus.publish(new SchemaDeleted(schema));
}
private sendSchemaUpdated(schema: SchemaDto) {
this.messageBus.publish(new SchemaUpdated(schema));
}
private notify() {
this.messageBus.publish(new HistoryChannelUpdated());
this.messageBus.publish(new SchemaUpdated(this.schema));
}
}

27
src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts

@ -72,8 +72,8 @@ export class SchemaFormComponent {
}
public cancel() {
this.resetForm();
this.cancelled.emit();
this.sendCancelled();
this.resetCreateForm();
}
public createSchema() {
@ -91,19 +91,30 @@ export class SchemaFormComponent {
this.schemas.postSchema(this.appName, requestDto, me, undefined, schemaVersion)
.subscribe(dto => {
this.resetForm();
this.created.emit(dto);
this.sendCreated(dto);
this.resetCreateForm();
}, error => {
this.createForm.enable();
this.createFormError = error.displayMessage;
this.enableCreateForm(error.displayMessage);
});
}
}
private resetForm() {
private sendCancelled() {
this.cancelled.emit();
}
private sendCreated(schema: SchemaDto) {
this.created.emit(schema);
}
private enableCreateForm(message: string) {
this.createForm.enable();
this.createFormError = message;
}
private resetCreateForm() {
this.createFormError = '';
this.createForm.reset();
this.createFormSubmitted = false;
}
}

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

@ -33,7 +33,7 @@
</div>
<button type="submit" class="btn btn-success" [disabled]="!hasName">Add Client</button>
<button type="reset" class="btn btn-link" (click)="resetClientForm()">Cancel</button>
<button type="reset" class="btn btn-link" (click)="cancelAttachClient()">Cancel</button>
</form>
</div>
</div>

6
src/Squidex/app/features/settings/pages/clients/clients-page.component.ts

@ -123,7 +123,11 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit {
}
}
public resetClientForm() {
public cancelAttachClient() {
this.resetClientForm();
}
private resetClientForm() {
this.addClientFormSubmitted = false;
this.addClientForm.enable();
this.addClientForm.reset();

14
src/Squidex/app/features/settings/pages/languages/language.component.ts

@ -72,7 +72,7 @@ export class LanguageComponent implements OnInit, OnChanges, OnDestroy {
this.editForm.controls['isOptional'].setValue(false);
});
this.resetForm();
this.resetEditForm();
}
public ngOnDestroy() {
@ -80,11 +80,11 @@ export class LanguageComponent implements OnInit, OnChanges, OnDestroy {
}
public ngOnChanges() {
this.resetForm();
this.resetEditForm();
}
public cancel() {
this.resetForm();
this.resetEditForm();
}
public toggleEditing() {
@ -119,11 +119,15 @@ export class LanguageComponent implements OnInit, OnChanges, OnDestroy {
this.editForm.controls['isOptional'].value,
this.fallbackLanguages.map(l => l.iso2Code));
this.saving.emit(newLanguage);
this.sendSaving(newLanguage);
}
}
private resetForm() {
private sendSaving(language: AppLanguageDto) {
this.saving.emit(language);
}
private resetEditForm() {
this.editFormSubmitted = false;
this.editForm.reset(this.language);

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

@ -74,9 +74,9 @@ export class PlansPageComponent extends AppComponentBase implements OnInit {
this.plans.hasPortal,
this.plans.hasConfigured,
this.plans.plans);
this.isDisabled = false;
}, error => {
this.notifyError(error);
}, () => {
this.isDisabled = false;
});
}

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

@ -126,7 +126,7 @@
<button type="submit" class="btn btn-success" [disabled]="!hasUrl">Add Webhook</button>
<button type="reset" class="btn btn-link" (click)="resetWebhookForm()" [disabled]="addWebhookFormSubmitted">Cancel</button>
<button type="reset" class="btn btn-link" (click)="cancelAddWebhook()" [disabled]="addWebhookFormSubmitted">Cancel</button>
</form>
</div>
</div>

37
src/Squidex/app/features/webhooks/pages/webhooks-page.component.ts

@ -87,10 +87,14 @@ export class WebhooksPageComponent extends AppComponentBase implements OnInit {
});
}
public resetWebhookForm() {
this.addWebhookFormSubmitted = false;
this.addWebhookForm.enable();
this.addWebhookForm.reset();
public deleteWebhook(webhook: WebhookWithSchema) {
this.appNameOnce()
.switchMap(app => this.webhooksService.deleteWebhook(app, webhook.schema.name, webhook.webhook.id, this.version))
.subscribe(dto => {
this.webhooks = this.webhooks.remove(webhook);
}, error => {
this.notifyError(error);
});
}
public addWebhook() {
@ -108,25 +112,30 @@ export class WebhooksPageComponent extends AppComponentBase implements OnInit {
.switchMap(app => this.webhooksService.postWebhook(app, schema.name, requestDto, this.version))
.subscribe(dto => {
this.webhooks = this.webhooks.push({ webhook: dto, schema: schema, showDetails: false });
this.resetWebhookForm();
}, error => {
this.notifyError(error);
}, () => {
this.resetWebhookForm();
this.enableWebhookForm();
});
}
}
public cancelAddWebhook() {
this.resetWebhookForm();
}
public toggleDetails(webhook: WebhookWithSchema) {
this.webhooks = this.webhooks.replace(webhook, { webhook: webhook.webhook, schema: webhook.schema, showDetails: !webhook.showDetails });
}
public deleteWebhook(webhook: WebhookWithSchema) {
this.appNameOnce()
.switchMap(app => this.webhooksService.deleteWebhook(app, webhook.schema.name, webhook.webhook.id, this.version))
.subscribe(dto => {
this.webhooks = this.webhooks.remove(webhook);
}, error => {
this.notifyError(error);
});
private enableWebhookForm() {
this.addWebhookForm.enable();
}
private resetWebhookForm() {
this.addWebhookFormSubmitted = false;
this.addWebhookForm.enable();
this.addWebhookForm.reset();
}
}

90
src/Squidex/app/framework/angular/modal-view.directive.ts

@ -5,7 +5,7 @@
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Directive, EmbeddedViewRef, Input, OnChanges, OnDestroy, OnInit, Renderer, TemplateRef, ViewContainerRef } from '@angular/core';
import { Directive, EmbeddedViewRef, Input, OnChanges, OnDestroy, Renderer, SimpleChanges, TemplateRef, ViewContainerRef } from '@angular/core';
import { Subscription } from 'rxjs';
import { ModalView } from './../utils/modal-view';
@ -15,9 +15,8 @@ import { RootViewService } from './../services/root-view.service';
@Directive({
selector: '[sqxModalView]'
})
export class ModalViewDirective implements OnChanges, OnInit, OnDestroy {
export class ModalViewDirective implements OnChanges, OnDestroy {
private subscription: Subscription | null;
private isEnabled = true;
private clickHandler: Function | null;
private renderedView: EmbeddedViewRef<any> | null = null;
@ -35,39 +34,15 @@ export class ModalViewDirective implements OnChanges, OnInit, OnDestroy {
) {
}
public ngOnInit() {
this.clickHandler =
this.renderer.listenGlobal('document', 'click', (event: MouseEvent) => {
if (!event.target || this.renderedView === null) {
return;
}
if (this.renderedView.rootNodes.length === 0) {
return;
}
if (this.isEnabled) {
if (this.modalView.closeAlways) {
this.modalView.hide();
} else {
const clickedInside = this.renderedView.rootNodes[0].contains(event.target);
if (!clickedInside && this.modalView) {
this.modalView.hide();
}
}
}
});
public ngOnDestroy() {
this.stopListening();
}
public ngOnDestroy() {
if (this.clickHandler) {
this.clickHandler();
this.clickHandler = null;
public ngOnChanges(changes: SimpleChanges) {
if (!changes['modalView']) {
return;
}
}
public ngOnChanges() {
if (this.subscription) {
this.subscription.unsubscribe();
this.subscription = null;
@ -75,19 +50,22 @@ export class ModalViewDirective implements OnChanges, OnInit, OnDestroy {
if (this.modalView) {
this.subscription = this.modalView.isOpen.subscribe(isOpen => {
if (this.isEnabled) {
if (isOpen === (this.renderedView !== null)) {
return;
}
if (isOpen) {
if (isOpen && !this.renderedView) {
if (this.placeOnRoot) {
this.renderedView = this.rootContainer.createEmbeddedView(this.templateRef);
} else {
this.renderedView = this.viewContainer.createEmbeddedView(this.templateRef);
}
this.renderer.setElementStyle(this.renderedView.rootNodes[0], 'display', 'block');
} else {
setTimeout(() => {
this.startListening();
});
} else if (!isOpen && this.renderedView) {
this.renderedView = null;
if (this.placeOnRoot) {
@ -95,19 +73,45 @@ export class ModalViewDirective implements OnChanges, OnInit, OnDestroy {
} else {
this.viewContainer.clear();
}
}
this.updateEnabled();
}
this.stopListening();
}
});
}
}
private updateEnabled() {
this.isEnabled = false;
private startListening() {
this.clickHandler =
this.renderer.listenGlobal('document', 'click', (event: MouseEvent) => {
if (!event.target || this.renderedView === null) {
return;
}
if (this.renderedView.rootNodes.length === 0) {
return;
}
if (this.modalView.closeAlways) {
this.modalView.hide();
} else {
const rootNode = this.renderedView.rootNodes[0];
const rootBounds = rootNode.getBoundingClientRect();
if (rootBounds.width > 0 && rootBounds.height > 0) {
const clickedInside = rootNode.contains(event.target);
setTimeout(() => {
this.isEnabled = true;
}, 500);
if (!clickedInside && this.modalView) {
this.modalView.hide();
}
}
}
});
}
private stopListening() {
if (this.clickHandler) {
this.clickHandler();
this.clickHandler = null;
}
}
}

4
src/Squidex/app/framework/utils/modal-view.ts

@ -9,18 +9,16 @@ import { BehaviorSubject, Observable } from 'rxjs';
export class ModalView {
private readonly isOpen$: BehaviorSubject<boolean>;
private readonly isOpenChanges$: Observable<boolean>;
private static openView: ModalView | null = null;
public get isOpen(): Observable<boolean> {
return this.isOpenChanges$;
return this.isOpen$;
}
constructor(isOpen = false,
public readonly closeAlways: boolean = false
) {
this.isOpen$ = new BehaviorSubject(isOpen);
this.isOpenChanges$ = this.isOpen$.distinctUntilChanged();
}
public show() {

32
src/Squidex/app/shared/components/app-form.component.ts

@ -54,8 +54,8 @@ export class AppFormComponent {
}
public cancel() {
this.reset();
this.cancelled.emit();
this.sendCancelled();
this.resetCreateForm();
}
public createApp() {
@ -66,23 +66,31 @@ export class AppFormComponent {
const request = new CreateAppDto(this.createForm.controls['name'].value);
const enable = (message?: string) => {
this.createForm.enable();
this.createFormSubmitted = false;
this.createFormError = message;
};
this.appsStore.createApp(request)
.subscribe(dto => {
this.reset();
this.created.emit(dto);
this.resetCreateForm();
this.sendCreated(dto);
}, error => {
enable(error.displayMessage);
this.enableCreateForm(error.displayMessage);
});
}
}
private reset() {
private sendCancelled() {
this.cancelled.emit();
}
private sendCreated(app: AppDto) {
this.created.emit(app);
}
private enableCreateForm(message: string) {
this.createForm.enable();
this.createFormSubmitted = false;
this.createFormError = message;
}
private resetCreateForm() {
this.createFormError = '';
this.createForm.enable();
this.createFormSubmitted = false;

4
src/Squidex/app/shared/components/asset.component.html

@ -68,7 +68,7 @@
<div class="modal-header">
<h4 class="modal-title">Rename asset</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="resetRename()">
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="cancelRenameAsset()">
<span aria-hidden="true">&times;</span>
</button>
</div>
@ -84,7 +84,7 @@
</div>
<div class="form-group clearfix">
<button type="reset" class="float-left btn btn-secondary" (click)="resetRename()">Cancel</button>
<button type="reset" class="float-left btn btn-secondary" (click)="cancelRenameAsset()">Cancel</button>
<button type="submit" class="float-right btn btn-success">Rename</button>
</div>
</form>

57
src/Squidex/app/shared/components/asset.component.ts

@ -91,19 +91,15 @@ export class AssetComponent extends AppComponentBase implements OnInit {
const initFile = this.initFile;
if (initFile) {
const me = `subject:${this.authService.user!.id}`;
this.appNameOnce()
.switchMap(app => this.assetsService.uploadFile(app, initFile, me))
.switchMap(app => this.assetsService.uploadFile(app, initFile, this.authService.user.token))
.subscribe(dto => {
if (dto instanceof AssetDto) {
this.loaded.emit(dto);
this.sendLoaded(dto);
} else {
this.progress = dto;
}
}, error => {
this.failed.emit();
this.notifyError(error);
});
} else {
@ -113,20 +109,17 @@ export class AssetComponent extends AppComponentBase implements OnInit {
public updateFile(files: FileList) {
if (files.length === 1) {
const me = `subject:${this.authService.user!.id}`;
this.appNameOnce()
.switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0], this.version))
.subscribe(dto => {
if (dto instanceof AssetReplacedDto) {
this.updateAsset(this.asset.update(dto, me), true);
this.updateAsset(this.asset.update(dto, this.authService.user.token), true);
} else {
this.progress = dto;
this.setProgress(dto);
}
}, error => {
this.notifyError(error);
}, () => {
this.progress = 0;
this.setProgress();
this.sendFailed(error);
});
}
}
@ -139,21 +132,43 @@ export class AssetComponent extends AppComponentBase implements OnInit {
const requestDto = new UpdateAssetDto(this.renameForm.controls['name'].value);
const me = `subject:${this.authService.user!.id}`;
this.appNameOnce()
.switchMap(app => this.assetsService.putAsset(app, this.asset.id, requestDto, this.version))
.subscribe(() => {
this.updateAsset(this.asset.rename(requestDto.fileName, me), true);
this.updateAsset(this.asset.rename(requestDto.fileName, this.authService.user.token), true);
this.resetRenameForm();
}, error => {
this.notifyError(error);
}, () => {
this.resetRename();
this.enableRenameForm();
});
}
}
public resetRename() {
public cancelRenameAsset() {
this.resetRenameForm();
}
private setProgress(progress = 0) {
this.progress = progress;
}
private sendFailed(error: any) {
this.failed.emit(error);
}
private sendLoaded(asset: AssetDto) {
this.loaded.emit(asset);
}
private sendUpdated(asset: AssetDto) {
this.updated.emit(asset);
}
private enableRenameForm() {
this.renameForm.enable();
}
private resetRenameForm() {
this.renameForm.enable();
this.renameForm.controls['name'].setValue(this.asset.fileName);
this.renameFormSubmitted = false;
@ -172,9 +187,9 @@ export class AssetComponent extends AppComponentBase implements OnInit {
this.version = asset.version;
if (emitEvent) {
this.updated.emit(asset);
this.sendUpdated(asset);
}
this.resetRename();
this.resetRenameForm();
}
}
Loading…
Cancel
Save