Browse Source

UI fix and backup fix.

pull/344/head
Sebastian Stehle 7 years ago
parent
commit
714bc232ed
  1. 11
      src/Squidex.Domain.Apps.Entities/Contents/BackupContents.cs
  2. 3
      src/Squidex.Domain.Apps.Entities/Schemas/BackupSchemas.cs
  3. 9
      src/Squidex/app/features/content/pages/contents/contents-filters-page.component.ts
  4. 11
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  5. 2
      src/Squidex/app/features/content/pages/schemas/schemas-page.component.html
  6. 8
      src/Squidex/app/framework/angular/routers/router-utils.ts
  7. 5
      src/Squidex/app/shared/components/schema-category.component.ts
  8. 2
      src/Squidex/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts
  9. 6
      src/Squidex/app/shared/state/apps.state.ts
  10. 6
      src/Squidex/app/shared/state/contents.state.ts
  11. 6
      src/Squidex/app/shared/state/schemas.state.ts

11
src/Squidex.Domain.Apps.Entities/Contents/BackupContents.cs

@ -7,10 +7,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Backup; using Squidex.Domain.Apps.Entities.Backup;
using Squidex.Domain.Apps.Entities.Contents.State; using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.States; using Squidex.Infrastructure.States;
@ -20,7 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
public sealed class BackupContents : BackupHandlerWithStore public sealed class BackupContents : BackupHandlerWithStore
{ {
private readonly HashSet<Guid> contentIds = new HashSet<Guid>(); private readonly Dictionary<Guid, HashSet<Guid>> contentIdsBySchemaId = new Dictionary<Guid, HashSet<Guid>>();
public override string Name { get; } = "Contents"; public override string Name { get; } = "Contents";
@ -34,7 +36,10 @@ namespace Squidex.Domain.Apps.Entities.Contents
switch (@event.Payload) switch (@event.Payload)
{ {
case ContentCreated contentCreated: case ContentCreated contentCreated:
contentIds.Add(contentCreated.ContentId); contentIdsBySchemaId.GetOrAddNew(contentCreated.SchemaId.Id).Add(contentCreated.ContentId);
break;
case SchemaDeleted schemaDeleted:
contentIdsBySchemaId.Remove(schemaDeleted.SchemaId.Id);
break; break;
} }
@ -43,6 +48,8 @@ namespace Squidex.Domain.Apps.Entities.Contents
public override Task RestoreAsync(Guid appId, BackupReader reader) public override Task RestoreAsync(Guid appId, BackupReader reader)
{ {
var contentIds = contentIdsBySchemaId.Values.SelectMany(x => x);
return RebuildManyAsync(contentIds, id => RebuildAsync<ContentState, ContentGrain>(id, (e, s) => s.Apply(e))); return RebuildManyAsync(contentIds, id => RebuildAsync<ContentState, ContentGrain>(id, (e, s) => s.Apply(e)));
} }
} }

3
src/Squidex.Domain.Apps.Entities/Schemas/BackupSchemas.cs

@ -39,6 +39,9 @@ namespace Squidex.Domain.Apps.Entities.Schemas
case SchemaCreated schemaCreated: case SchemaCreated schemaCreated:
schemasByName[schemaCreated.SchemaId.Name] = schemaCreated.SchemaId.Id; schemasByName[schemaCreated.SchemaId.Name] = schemaCreated.SchemaId.Id;
break; break;
case SchemaDeleted schemaDeleted:
schemasByName.Remove(schemaDeleted.SchemaId.Name);
break;
} }
return TaskHelper.True; return TaskHelper.True;

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

@ -6,13 +6,11 @@
*/ */
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { filter, onErrorResumeNext, takeUntil } from 'rxjs/operators'; import { onErrorResumeNext } from 'rxjs/operators';
import { import {
ContentsState, ContentsState,
navigatedToOtherComponent,
Queries, Queries,
SchemasState, SchemasState,
UIState UIState
@ -31,7 +29,6 @@ export class ContentsFiltersPageComponent implements OnDestroy, OnInit {
constructor( constructor(
private readonly contentsState: ContentsState, private readonly contentsState: ContentsState,
private readonly schemasState: SchemasState, private readonly schemasState: SchemasState,
private readonly router: Router,
private readonly uiState: UIState private readonly uiState: UIState
) { ) {
} }
@ -41,10 +38,8 @@ export class ContentsFiltersPageComponent implements OnDestroy, OnInit {
} }
public ngOnInit() { public ngOnInit() {
const routeChanged = this.router.events.pipe(filter(navigatedToOtherComponent(this.router)));
this.selectedSchemaSubscription = this.selectedSchemaSubscription =
this.schemasState.selectedSchema.pipe(takeUntil(routeChanged)) this.schemasState.selectedSchema
.subscribe(schema => { .subscribe(schema => {
if (schema) { if (schema) {
this.schemaQueries = new Queries(this.uiState, `schemas.${schema.name}`); this.schemaQueries = new Queries(this.uiState, `schemas.${schema.name}`);

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

@ -6,9 +6,8 @@
*/ */
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { filter, onErrorResumeNext, switchMap, takeUntil, tap } from 'rxjs/operators'; import { onErrorResumeNext, switchMap, tap } from 'rxjs/operators';
import { import {
AppLanguageDto, AppLanguageDto,
@ -18,7 +17,6 @@ import {
ImmutableArray, ImmutableArray,
LanguagesState, LanguagesState,
ModalModel, ModalModel,
navigatedToOtherComponent,
Queries, Queries,
SchemaDetailsDto, SchemaDetailsDto,
SchemasState, SchemasState,
@ -61,7 +59,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
public readonly contentsState: ContentsState, public readonly contentsState: ContentsState,
private readonly languagesState: LanguagesState, private readonly languagesState: LanguagesState,
private readonly schemasState: SchemasState, private readonly schemasState: SchemasState,
private readonly router: Router,
private readonly uiState: UIState private readonly uiState: UIState
) { ) {
} }
@ -73,10 +70,8 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
} }
public ngOnInit() { public ngOnInit() {
const routeChanged = this.router.events.pipe(filter(navigatedToOtherComponent(this.router)));
this.selectedSchemaSubscription = this.selectedSchemaSubscription =
this.schemasState.selectedSchema.pipe(takeUntil(routeChanged)) this.schemasState.selectedSchema
.subscribe(schema => { .subscribe(schema => {
this.resetSelection(); this.resetSelection();
@ -87,7 +82,7 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
}); });
this.contentsSubscription = this.contentsSubscription =
this.contentsState.contents.pipe(takeUntil(routeChanged)) this.contentsState.contents
.subscribe(() => { .subscribe(() => {
this.updateSelectionSummary(); this.updateSelectionSummary();
}); });

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

@ -17,7 +17,7 @@
<ng-container content> <ng-container content>
<ng-container *ngIf="schemasState.publishedSchemas | async; let schemas"> <ng-container *ngIf="schemasState.publishedSchemas | async; let schemas">
<sqx-schema-category *ngFor="let category of schemasState.categories | async; trackBy: trackByCategory" suffix="filters" <sqx-schema-category *ngFor="let category of schemasState.categories | async; trackBy: trackByCategory"
[name]="category" [name]="category"
[schemas]="schemas" [schemas]="schemas"
[schemasFilter]="schemasFilter.valueChanges | async" [schemasFilter]="schemasFilter.valueChanges | async"

8
src/Squidex/app/framework/angular/routers/router-utils.ts

@ -5,9 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
import { ActivatedRoute, ActivatedRouteSnapshot, Data, Params, Router, RouterEvent, RouterStateSnapshot, RoutesRecognized } from '@angular/router'; import { ActivatedRoute, ActivatedRouteSnapshot, Data, Params, RouterStateSnapshot } from '@angular/router';
import { Types } from './../../utils/types';
export function allData(value: ActivatedRouteSnapshot | ActivatedRoute): Data { export function allData(value: ActivatedRouteSnapshot | ActivatedRoute): Data {
let snapshot: ActivatedRouteSnapshot | null = value['snapshot'] || value; let snapshot: ActivatedRouteSnapshot | null = value['snapshot'] || value;
@ -56,8 +54,4 @@ export function childComponent(value: RouterStateSnapshot) {
} }
return current.component; return current.component;
}
export function navigatedToOtherComponent(router: Router) {
return (e: RouterEvent) => Types.is(e, RoutesRecognized) && childComponent(e.state) !== childComponent(router.routerState.snapshot);
} }

5
src/Squidex/app/shared/components/schema-category.component.ts

@ -46,9 +46,6 @@ export class SchemaCategoryComponent implements OnInit, OnChanges {
@Input() @Input()
public schemas: ImmutableArray<SchemaDto>; public schemas: ImmutableArray<SchemaDto>;
@Input()
public suffix: string;
public displayName: string; public displayName: string;
public schemasFiltered: ImmutableArray<SchemaDto>; public schemasFiltered: ImmutableArray<SchemaDto>;
@ -106,8 +103,6 @@ export class SchemaCategoryComponent implements OnInit, OnChanges {
public schemaRoute(schema: SchemaDto) { public schemaRoute(schema: SchemaDto) {
if (schema.isSingleton && this.routeSingletonToContent) { if (schema.isSingleton && this.routeSingletonToContent) {
return [schema.name, schema.id]; return [schema.name, schema.id];
} else if (this.suffix) {
return [schema.name, this.suffix];
} else { } else {
return [schema.name]; return [schema.name];
} }

2
src/Squidex/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts

@ -56,7 +56,7 @@ describe('SchemaMustNotBeSingletonGuard', () => {
const state: RouterStateSnapshot = <any>{ url: 'schemas/name/' }; const state: RouterStateSnapshot = <any>{ url: 'schemas/name/' };
schemasState.setup(x => x.selectedSchema) schemasState.setup(x => x.selectedSchema)
.returns(() => of(null)); .returns(() => of(undefined));
let result: boolean; let result: boolean;

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

@ -28,6 +28,10 @@ interface Snapshot {
selectedApp: AppDto | null; selectedApp: AppDto | null;
} }
function sameApp(lhs: AppDto, rhs?: AppDto): boolean {
return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id);
}
@Injectable() @Injectable()
export class AppsState extends State<Snapshot> { export class AppsState extends State<Snapshot> {
public get appName() { public get appName() {
@ -36,7 +40,7 @@ export class AppsState extends State<Snapshot> {
public selectedApp = public selectedApp =
this.changes.pipe(map(s => s.selectedApp), this.changes.pipe(map(s => s.selectedApp),
distinctUntilChanged()); distinctUntilChanged(sameApp));
public apps = public apps =
this.changes.pipe(map(s => s.apps), this.changes.pipe(map(s => s.apps),

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

@ -39,10 +39,14 @@ interface Snapshot {
selectedContent?: ContentDto | null; selectedContent?: ContentDto | null;
} }
function sameContent(lhs: ContentDto, rhs?: ContentDto): boolean {
return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id && lhs.version === rhs.version);
}
export abstract class ContentsStateBase extends State<Snapshot> { export abstract class ContentsStateBase extends State<Snapshot> {
public selectedContent = public selectedContent =
this.changes.pipe(map(x => x.selectedContent), this.changes.pipe(map(x => x.selectedContent),
distinctUntilChanged()); distinctUntilChanged(sameContent));
public contents = public contents =
this.changes.pipe(map(x => x.contents), this.changes.pipe(map(x => x.contents),

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

@ -53,11 +53,15 @@ interface Snapshot {
selectedSchema?: SchemaDetailsDto | null; selectedSchema?: SchemaDetailsDto | null;
} }
function sameSchema(lhs: SchemaDetailsDto | null, rhs?: SchemaDetailsDto | null): boolean {
return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id && lhs.version === rhs.version);
}
@Injectable() @Injectable()
export class SchemasState extends State<Snapshot> { export class SchemasState extends State<Snapshot> {
public selectedSchema = public selectedSchema =
this.changes.pipe(map(x => x.selectedSchema), this.changes.pipe(map(x => x.selectedSchema),
distinctUntilChanged()); distinctUntilChanged(sameSchema));
public categories = public categories =
this.changes.pipe(map(x => ImmutableArray.of(Object.keys(x.categories)).sortByStringAsc(s => s)), this.changes.pipe(map(x => ImmutableArray.of(Object.keys(x.categories)).sortByStringAsc(s => s)),

Loading…
Cancel
Save