diff --git a/src/Squidex.Infrastructure.MongoDb/CQRS/Events/MongoEventStore.cs b/src/Squidex.Infrastructure.MongoDb/CQRS/Events/MongoEventStore.cs index 841693e4a..c67ce70cc 100644 --- a/src/Squidex.Infrastructure.MongoDb/CQRS/Events/MongoEventStore.cs +++ b/src/Squidex.Infrastructure.MongoDb/CQRS/Events/MongoEventStore.cs @@ -140,6 +140,8 @@ namespace Squidex.Infrastructure.CQRS.Events }; await Collection.InsertOneAsync(document); + + notifier.NotifyEventsStored(); } catch (MongoWriteException ex) { diff --git a/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs b/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs index 365128ecd..d1d8489c8 100644 --- a/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs +++ b/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs @@ -64,7 +64,7 @@ namespace Squidex.Pipeline { error.StatusCode = statusCode; - return new ObjectResult(error) { StatusCode = 412 }; + return new ObjectResult(error) { StatusCode = statusCode }; } public override void OnActionExecuting(ActionExecutingContext context) diff --git a/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts index d4fffad12..874fb122a 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts @@ -7,11 +7,15 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; +import { Observable } from 'rxjs'; import { ApiUrlConfig, AuthService, fadeAnimation, + Notification, + NotificationService, + SchemaDetailsDto, SchemaDto, SchemasService, ValidatorsEx, @@ -30,7 +34,7 @@ const FALLBACK_NAME = 'my-schema'; }) export class SchemaFormComponent { @Output() - public created = new EventEmitter(); + public created = new EventEmitter<{ schema: SchemaDto, isAvailable: boolean }>(); @Output() public cancelled = new EventEmitter(); @@ -59,6 +63,7 @@ export class SchemaFormComponent { constructor( public readonly apiUrl: ApiUrlConfig, + private readonly notifications: NotificationService, private readonly schemas: SchemasService, private readonly formBuilder: FormBuilder, private readonly authService: AuthService @@ -90,11 +95,25 @@ export class SchemaFormComponent { const me = this.authService.user!.token; this.schemas.postSchema(this.appName, requestDto, me, undefined, schemaVersion) + .switchMap(dto => { + return this.schemas.getSchema(this.appName, dto.id) + .retryWhen(errors => errors + .delay(500) + .take(10) + .concat(Observable.throw(dto))); + }) .subscribe(dto => { - this.emitCreated(dto); + this.emitCreated(dto, true); this.resetCreateForm(); }, error => { - this.enableCreateForm(error.displayMessage); + if (error instanceof SchemaDetailsDto) { + this.notifications.notify(Notification.error('Schema has been created but is awaiting to be processed. Reload in a few seconds.')); + + this.emitCreated(error, false); + this.resetCreateForm(); + } else { + this.enableCreateForm(error.displayMessage); + } }); } } @@ -103,8 +122,8 @@ export class SchemaFormComponent { this.cancelled.emit(); } - private emitCreated(schema: SchemaDto) { - this.created.emit(schema); + private emitCreated(schema: SchemaDto, isAvailable: boolean) { + this.created.emit({ schema, isAvailable }); } private enableCreateForm(message: string) { diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html index 4c45aafdb..d1c6d1646 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html @@ -66,7 +66,7 @@ diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index 725d46c52..75c79aaa1 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -6,7 +6,7 @@ */ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { FormControl } from '@angular/forms'; import { Subscription } from 'rxjs'; @@ -46,6 +46,7 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy, constructor(apps: AppsStoreService, notifications: NotificationService, private readonly schemasService: SchemasService, private readonly messageBus: MessageBus, + private readonly router: Router, private readonly route: ActivatedRoute ) { super(notifications, apps); @@ -96,10 +97,14 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy, }); } - public onSchemaCreated(dto: SchemaDto) { + public onSchemaCreated(dto: SchemaDto, isAvailable: boolean) { this.updateSchemas(this.schemas.push(dto), this.schemaQuery); this.addSchemaDialog.hide(); + + if (isAvailable) { + this.router.navigate([ dto.name ], { relativeTo: this.route }); + } } private updateSchemas(schemas: ImmutableArray, query?: string) { diff --git a/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts b/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts index 13bf0ba28..99515513d 100644 --- a/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts +++ b/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts @@ -88,22 +88,6 @@ describe('AuthInterceptor', () => { expect(req.request.headers.get('Pragma')).toBeNull(); })); - it(`should logout for 404 status code when user is expired.`, - inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { - - authService.setup(x => x.userChanges).returns(() => { return Observable.of({ authToken: 'letmein', isExpired: true }); }); - - http.get('http://service/p/apps').subscribe( - _ => { /* NOOP */ }, - _ => { /* NOOP */ }); - - const req = httpMock.expectOne('http://service/p/apps'); - - req.error({}, { status: 404 }); - - authService.verify(x => x.logoutRedirect(), Times.once()); - })); - it(`should logout for 401 status code`, inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { diff --git a/src/Squidex/app/shared/interceptors/auth.interceptor.ts b/src/Squidex/app/shared/interceptors/auth.interceptor.ts index 5c74cd3b8..1ed8ff881 100644 --- a/src/Squidex/app/shared/interceptors/auth.interceptor.ts +++ b/src/Squidex/app/shared/interceptors/auth.interceptor.ts @@ -46,10 +46,6 @@ export class AuthInterceptor implements HttpInterceptor { .catch((error: HttpErrorResponse) => { if (error.status === 401 && renew) { return this.authService.loginSilent().switchMap(u => this.makeRequest(req, next, u)); - } else if (error.status === 404 && (!user || user.isExpired)) { - this.authService.logoutRedirect(); - - return Observable.empty>(); } else if (error.status === 401 || error.status === 403) { this.authService.logoutRedirect();