Browse Source

Improved search form.

pull/313/head
Sebastian Stehle 8 years ago
parent
commit
e9a5e5c2ae
  1. 42
      src/Squidex/app/features/assets/pages/assets-page.component.html
  2. 28
      src/Squidex/app/features/assets/pages/assets-page.component.ts
  3. 1
      src/Squidex/app/features/content/declarations.ts
  4. 6
      src/Squidex/app/features/content/module.ts
  5. 52
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  6. 6
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  7. 4
      src/Squidex/app/features/content/shared/assets-editor.component.ts
  8. 4
      src/Squidex/app/features/content/shared/contents-selector.component.html
  9. 20
      src/Squidex/app/shared/components/assets-selector.component.html
  10. 9
      src/Squidex/app/shared/components/assets-selector.component.ts
  11. 36
      src/Squidex/app/shared/components/search-form.component.html
  12. 0
      src/Squidex/app/shared/components/search-form.component.scss
  13. 20
      src/Squidex/app/shared/components/search-form.component.ts
  14. 1
      src/Squidex/app/shared/declarations.ts
  15. 2
      src/Squidex/app/shared/internal.ts
  16. 5
      src/Squidex/app/shared/module.ts
  17. 4
      src/Squidex/app/shared/state/assets.state.ts
  18. 24
      src/Squidex/app/shared/state/queries.spec.ts
  19. 10
      src/Squidex/app/shared/state/queries.ts

42
src/Squidex/app/features/assets/pages/assets-page.component.html

@ -6,16 +6,25 @@
</ng-container> </ng-container>
<ng-container menu> <ng-container menu>
<button class="btn btn-link btn-secondary mr-1" (click)="reload()" title="Refresh Assets (CTRL + SHIFT + R)"> <div class="row no-gutters pl-1">
<i class="icon-reset"></i> Refresh <div class="col col-auto offset-xl-4">
</button> <sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut> <button class="btn btn-link btn-secondary" (click)="reload()" title="Refresh Contents (CTRL + SHIFT + R)">
<sqx-shortcut keys="ctrl+shift+f" (trigger)="inputFind.focus()"></sqx-shortcut> <i class="icon-reset"></i> Refresh
</button>
</div>
<div class="col pl-1">
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<form class="form-inline" (ngSubmit)="search()"> <sqx-search-form formClass="form" placeholder="Search for assets" fieldExample="fileSize"
<input class="form-control" #inputFind [formControl]="assetsFilter" placeholder="Search for assets" /> (queryChanged)="search($event)"
</form> [query]="assetsState.assetsQuery | async"
[queries]="queries"
enableShortcut="true">
</sqx-search-form>
</div>
</div>
</ng-container> </ng-container>
<ng-container content> <ng-container content>
@ -26,7 +35,7 @@
<div class="sidebar-section"> <div class="sidebar-section">
<a class="row sidebar-item" (click)="resetTags()" [class.active]="assetsState.isTagSelectionEmpty()"> <a class="row sidebar-item" (click)="resetTags()" [class.active]="assetsState.isTagSelectionEmpty()">
<div class="col"> <div class="col">
All Assets All tags
</div> </div>
</a> </a>
</div> </div>
@ -43,5 +52,20 @@
</div> </div>
</a> </a>
</div> </div>
<div class="sidebar-section">
<h3>Saved queries</h3>
<a class="row sidebar-item" *ngFor="let query of queries.queries | async" (click)="search(query.filter)" [class.active]="isSelectedQuery(query.filter)">
<div class="col truncate">
{{query.name}}
</div>
<div class="col col-auto">
<a class="sidebar-item-remove" (click)="queries.remove(query.name)">
<i class="icon-close"></i>
</a>
</div>
</a>
</div>
</ng-container> </ng-container>
</sqx-panel> </sqx-panel>

28
src/Squidex/app/features/assets/pages/assets-page.component.ts

@ -11,7 +11,12 @@ import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { onErrorResumeNext } from 'rxjs/operators'; import { onErrorResumeNext } from 'rxjs/operators';
import { AppsState, AssetsState } from '@app/shared'; import {
AppsState,
AssetsState,
Queries,
UIState
} from '@app/shared';
@Component({ @Component({
selector: 'sqx-assets-page', selector: 'sqx-assets-page',
@ -21,9 +26,12 @@ import { AppsState, AssetsState } from '@app/shared';
export class AssetsPageComponent implements OnInit { export class AssetsPageComponent implements OnInit {
public assetsFilter = new FormControl(); public assetsFilter = new FormControl();
public queries = new Queries(this.uiState, 'assets');
constructor( constructor(
public readonly appsState: AppsState, public readonly appsState: AppsState,
public readonly assetsState: AssetsState public readonly assetsState: AssetsState,
private readonly uiState: UIState
) { ) {
} }
@ -35,18 +43,18 @@ export class AssetsPageComponent implements OnInit {
this.assetsState.load(true).pipe(onErrorResumeNext()).subscribe(); this.assetsState.load(true).pipe(onErrorResumeNext()).subscribe();
} }
public search() { public search(query: string) {
this.assetsState.search(this.assetsFilter.value).pipe(onErrorResumeNext()).subscribe(); this.assetsState.search(query).pipe(onErrorResumeNext()).subscribe();
}
public resetTags() {
this.assetsState.resetTags().pipe(onErrorResumeNext()).subscribe();
} }
public toggleTag(tag: string) { public toggleTag(tag: string) {
this.assetsState.toggleTag(tag).pipe(onErrorResumeNext()).subscribe(); this.assetsState.toggleTag(tag).pipe(onErrorResumeNext()).subscribe();
} }
public resetTags() {
this.assetsState.resetTags().pipe(onErrorResumeNext()).subscribe();
}
public goNext() { public goNext() {
this.assetsState.goNext().pipe(onErrorResumeNext()).subscribe(); this.assetsState.goNext().pipe(onErrorResumeNext()).subscribe();
} }
@ -54,5 +62,9 @@ export class AssetsPageComponent implements OnInit {
public goPrev() { public goPrev() {
this.assetsState.goPrev().pipe(onErrorResumeNext()).subscribe(); this.assetsState.goPrev().pipe(onErrorResumeNext()).subscribe();
} }
public isSelectedQuery(query: string) {
return query === this.assetsState.snapshot.assetsQuery || (!query && !this.assetsState.assetsQuery);
}
} }

1
src/Squidex/app/features/content/declarations.ts

@ -9,7 +9,6 @@ export * from './pages/content/content-field.component';
export * from './pages/content/content-history.component'; export * from './pages/content/content-history.component';
export * from './pages/content/content-page.component'; export * from './pages/content/content-page.component';
export * from './pages/contents/contents-page.component'; export * from './pages/contents/contents-page.component';
export * from './pages/contents/search-form.component';
export * from './pages/schemas/schemas-page.component'; export * from './pages/schemas/schemas-page.component';
export * from './shared/array-editor.component'; export * from './shared/array-editor.component';

6
src/Squidex/app/features/content/module.ts

@ -32,8 +32,7 @@ import {
DueTimeSelectorComponent, DueTimeSelectorComponent,
FieldEditorComponent, FieldEditorComponent,
ReferencesEditorComponent, ReferencesEditorComponent,
SchemasPageComponent, SchemasPageComponent
SearchFormComponent
} from './declarations'; } from './declarations';
const routes: Routes = [ const routes: Routes = [
@ -100,8 +99,7 @@ const routes: Routes = [
DueTimeSelectorComponent, DueTimeSelectorComponent,
FieldEditorComponent, FieldEditorComponent,
ReferencesEditorComponent, ReferencesEditorComponent,
SchemasPageComponent, SchemasPageComponent
SearchFormComponent
] ]
}) })
export class SqxFeatureContentModule { } export class SqxFeatureContentModule { }

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

@ -14,19 +14,21 @@
<ng-container menu> <ng-container menu>
<div class="row no-gutters pl-1"> <div class="row no-gutters pl-1">
<div class="col col-auto offset-xl-4"> <div class="col col-auto offset-xl-4">
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<button class="btn btn-link btn-secondary" (click)="reload()" title="Refresh Contents (CTRL + SHIFT + R)"> <button class="btn btn-link btn-secondary" (click)="reload()" title="Refresh Contents (CTRL + SHIFT + R)">
<i class="icon-reset"></i> Refresh <i class="icon-reset"></i> Refresh
</button> </button>
</div> </div>
<div class="col pl-1"> <div class="col pl-1">
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut> <sqx-search-form formClass="form" placeholder="Search for content" fieldExample="data/[MY_FIELD]/iv"
<sqx-search-form formClass="form"
(queryChanged)="search($event)" (queryChanged)="search($event)"
[query]="contentsState.contentsQuery | async" [query]="contentsState.contentsQuery | async"
[queries]="schemaQueries" [queries]="schemaQueries"
(archivedChanged)="goArchive($event)" (archivedChanged)="goArchive($event)"
[archived]="contentsState.isArchive | async" [archived]="contentsState.isArchive | async"
expandable="true"
enableArchive="true"
enableShortcut="true"> enableShortcut="true">
</sqx-search-form> </sqx-search-form>
</div> </div>
@ -122,32 +124,28 @@
</ng-container> </ng-container>
<ng-container sidebar> <ng-container sidebar>
<ng-container *ngIf="schemaQueries.queries | async; let queries"> <div class="sidebar-section">
<div class="sidebar-section"> <a class="row sidebar-item" *ngFor="let query of schemaQueries.defaultQueries" (click)="search(query.filter)" [class.active]="isSelectedQuery(query.filter)">
<h3>Queries</h3> <div class="col truncate">
{{query.name}}
<a class="row sidebar-item" *ngFor="let query of schemaQueries.defaultQueries" (click)="search(query.filter)" [class.active]="isSelectedQuery(query.filter)"> </div>
<div class="col truncate"> </a>
{{query.name}} </div>
</div>
</a>
</div>
<div class="sidebar-section" *ngIf="queries.length > 0"> <div class="sidebar-section">
<h3>Bookmarks</h3> <h3>Saved queries</h3>
<a class="row sidebar-item" *ngFor="let query of queries" (click)="search(query.filter)" [class.active]="isSelectedQuery(query.filter)"> <a class="row sidebar-item" *ngFor="let query of schemaQueries.queries | async" (click)="search(query.filter)" [class.active]="isSelectedQuery(query.filter)">
<div class="col truncate"> <div class="col truncate">
{{query.name}} {{query.name}}
</div> </div>
<div class="col col-auto"> <div class="col col-auto">
<a class="sidebar-item-remove" (click)="schemaQueries.remove(query.name)"> <a class="sidebar-item-remove" (click)="schemaQueries.remove(query.name)">
<i class="icon-close"></i> <i class="icon-close"></i>
</a> </a>
</div> </div>
</a> </a>
</div> </div>
</ng-container>
</ng-container> </ng-container>
</sqx-panel> </sqx-panel>

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

@ -17,8 +17,8 @@ import {
ImmutableArray, ImmutableArray,
LanguagesState, LanguagesState,
ModalModel, ModalModel,
Queries,
SchemaDetailsDto, SchemaDetailsDto,
SchemaQueries,
SchemasState, SchemasState,
UIState UIState
} from '@app/shared'; } from '@app/shared';
@ -36,7 +36,7 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
private selectedSchemaSubscription: Subscription; private selectedSchemaSubscription: Subscription;
public schema: SchemaDetailsDto; public schema: SchemaDetailsDto;
public schemaQueries: SchemaQueries; public schemaQueries: Queries;
public searchModal = new ModalModel(); public searchModal = new ModalModel();
@ -76,7 +76,7 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
this.resetSelection(); this.resetSelection();
this.schema = schema!; this.schema = schema!;
this.schemaQueries = new SchemaQueries(this.uiState, this.schema.name); this.schemaQueries = new Queries(this.uiState, `schemas.${this.schema.name}`);
this.contentsState.init().pipe(onErrorResumeNext()).subscribe(); this.contentsState.init().pipe(onErrorResumeNext()).subscribe();
}); });

4
src/Squidex/app/features/content/shared/assets-editor.component.ts

@ -14,8 +14,8 @@ import {
AppsState, AppsState,
AssetDto, AssetDto,
AssetsService, AssetsService,
DialogModel,
ImmutableArray, ImmutableArray,
ModalModel,
Types Types
} from '@app/shared'; } from '@app/shared';
@ -35,7 +35,7 @@ export class AssetsEditorComponent implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ }; private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ }; private callTouched = () => { /* NOOP */ };
public assetsDialog = new ModalModel(); public assetsDialog = new DialogModel();
public newAssets = ImmutableArray.empty<File>(); public newAssets = ImmutableArray.empty<File>();
public oldAssets = ImmutableArray.empty<AssetDto>(); public oldAssets = ImmutableArray.empty<AssetDto>();

4
src/Squidex/app/features/content/shared/contents-selector.component.html

@ -11,10 +11,10 @@
</button> </button>
</div> </div>
<div class="col pl-1"> <div class="col pl-1">
<sqx-search-form formClass="form" <sqx-search-form formClass="form" placeholder="Search for content" fieldExample="data/[MY_FIELD]/iv"
[query]="contentsState.contentsQuery | async" [query]="contentsState.contentsQuery | async"
(queryChanged)="search($event)" (queryChanged)="search($event)"
[canArchive]="false"> expandable="true">
</sqx-search-form> </sqx-search-form>
<ng-container *ngIf="languages.length > 1"> <ng-container *ngIf="languages.length > 1">

20
src/Squidex/app/shared/components/assets-selector.component.html

@ -4,13 +4,19 @@
</ng-container> </ng-container>
<ng-container tabs> <ng-container tabs>
<button class="float-right btn btn-link btn-secondary" (click)="reload()"> <div class="row no-gutters">
<i class="icon-reset"></i> Refresh <div class="col col-auto offset-lg-4">
</button> <button class="btn btn-link btn-secondary" (click)="reload()">
<i class="icon-reset"></i> Refresh
<form class="float-left form-inline" (ngSubmit)="search()"> </button>
<input class="form-control" [formControl]="assetsFilter" placeholder="Search for assets" /> </div>
</form> <div class="col pl-1">
<sqx-search-form formClass="form" placeholder="Search for assets" fieldExample="fileSize"
[query]="state.assetsQuery | async"
(queryChanged)="search($event)">
</sqx-search-form>
</div>
</div>
</ng-container> </ng-container>
<ng-container content> <ng-container content>

9
src/Squidex/app/shared/components/assets-selector.component.ts

@ -8,7 +8,6 @@
// tslint:disable:prefer-for-of // tslint:disable:prefer-for-of
import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import { onErrorResumeNext } from 'rxjs/operators'; import { onErrorResumeNext } from 'rxjs/operators';
import { import {
@ -32,8 +31,6 @@ export class AssetsSelectorComponent implements OnInit {
@Output() @Output()
public selected = new EventEmitter<AssetDto[]>(); public selected = new EventEmitter<AssetDto[]>();
public assetsFilter = new FormControl('');
constructor( constructor(
public readonly state: AssetsDialogState public readonly state: AssetsDialogState
) { ) {
@ -41,16 +38,14 @@ export class AssetsSelectorComponent implements OnInit {
public ngOnInit() { public ngOnInit() {
this.state.load().pipe(onErrorResumeNext()).subscribe(); this.state.load().pipe(onErrorResumeNext()).subscribe();
this.assetsFilter.setValue(this.state.snapshot.assetsQuery);
} }
public reload() { public reload() {
this.state.load(true).pipe(onErrorResumeNext()).subscribe(); this.state.load(true).pipe(onErrorResumeNext()).subscribe();
} }
public search() { public search(query: string) {
this.state.search(this.assetsFilter.value).pipe(onErrorResumeNext()).subscribe(); this.state.search(query).pipe(onErrorResumeNext()).subscribe();
} }
public complete() { public complete() {

36
src/Squidex/app/features/content/pages/contents/search-form.component.html → src/Squidex/app/shared/components/search-form.component.html

@ -3,23 +3,27 @@
</ng-container> </ng-container>
<form [class]="formClass" (ngSubmit)="search()"> <form [class]="formClass" (ngSubmit)="search()">
<input class="form-control form-control-expandable" #inputFind [formControl]="contentsFilter" placeholder="Search for content" /> <input class="form-control form-control-expandable" #inputFind [formControl]="contentsFilter" [placeholder]="placeholder" />
<a class="expand-search" (click)="searchModal.toggle()" #archive> <ng-container *ngIf="expandable">
<i class="icon-caret-down"></i> <a class="expand-search" (click)="searchModal.toggle()" #archive>
</a> <i class="icon-caret-down"></i>
<ng-container *ngIf="saveKey | async; else notBookmarked; let key">
<a class="save-search" (click)="queries.remove(key)">
<i class="icon-star-full"></i>
</a> </a>
</ng-container> </ng-container>
<ng-template #notBookmarked> <ng-container *ngIf="queries">
<a class="save-search" (click)="saveQuery()" *ngIf="contentsFilterValue | async"> <ng-container *ngIf="saveKey | async; else notBookmarked; let key">
<i class="icon-star-empty"></i> <a class="save-search" (click)="queries.remove(key)">
</a> <i class="icon-star-full"></i>
</ng-template> </a>
</ng-container>
<ng-template #notBookmarked>
<a class="save-search" (click)="saveQuery()" *ngIf="contentsFilterValue | async">
<i class="icon-star-empty"></i>
</a>
</ng-template>
</ng-container>
</form> </form>
<sqx-onboarding-tooltip id="contentArchive" [for]="archive" position="bottomRight" after="60000"> <sqx-onboarding-tooltip id="contentArchive" [for]="archive" position="bottomRight" after="60000">
@ -45,7 +49,7 @@
<label class="col col-2 col-form-label" for="filter">Filter</label> <label class="col col-2 col-form-label" for="filter">Filter</label>
<div class="col col-10"> <div class="col col-10">
<input type="input" class="form-control" id="filter" (blur)="updateQuery()" formControlName="odataFilter" placeholder="data/[MY_FIELD]/iv eq 100" /> <input type="input" class="form-control" id="filter" (blur)="updateQuery()" formControlName="odataFilter" placeholder="{{fieldExample}} eq [VALUE]" />
</div> </div>
</div> </div>
@ -53,12 +57,12 @@
<label class="col col-2 col-form-label" for="orderBy">Order</label> <label class="col col-2 col-form-label" for="orderBy">Order</label>
<div class="col col-10"> <div class="col col-10">
<input type="input" class="form-control" id="orderBy" (blur)="updateQuery()" formControlName="odataOrderBy" placeholder="data/[MY_FIELD]/iv desc" /> <input type="input" class="form-control" id="orderBy" (blur)="updateQuery()" formControlName="odataOrderBy" placeholder="{{fieldExample}} desc" />
</div> </div>
</div> </div>
</div> </div>
<div class="form-check" *ngIf="canArchive"> <div class="form-check" *ngIf="enableArchive">
<input class="form-check-input" type="checkbox" id="archivedItems" [ngModel]="archived" (ngModelChange)="archivedChanged.emit($event)" /> <input class="form-check-input" type="checkbox" id="archivedItems" [ngModel]="archived" (ngModelChange)="archivedChanged.emit($event)" />
<label class="form-check-label" for="archivedItems"> <label class="form-check-label" for="archivedItems">
Archived items Archived items

0
src/Squidex/app/features/content/pages/contents/search-form.component.scss → src/Squidex/app/shared/components/search-form.component.scss

20
src/Squidex/app/features/content/pages/contents/search-form.component.ts → src/Squidex/app/shared/components/search-form.component.ts

@ -8,7 +8,12 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
import { FormBuilder, FormControl } from '@angular/forms'; import { FormBuilder, FormControl } from '@angular/forms';
import { ModalModel, SaveQueryForm, SchemaQueries } from '@app/shared'; import {
ModalModel,
Queries,
SaveQueryForm
} from '@app/shared/internal';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { shareReplay } from 'rxjs/operators'; import { shareReplay } from 'rxjs/operators';
@ -20,7 +25,16 @@ import { shareReplay } from 'rxjs/operators';
}) })
export class SearchFormComponent implements OnChanges, OnInit { export class SearchFormComponent implements OnChanges, OnInit {
@Input() @Input()
public queries: SchemaQueries; public queries: Queries;
@Input()
public placeholder = '';
@Input()
public fieldExample = '[MY_FIELD]';
@Input()
public expandable = false;
@Input() @Input()
public query = ''; public query = '';
@ -38,7 +52,7 @@ export class SearchFormComponent implements OnChanges, OnInit {
public schemaName = ''; public schemaName = '';
@Input() @Input()
public canArchive = true; public enableArchive = false;
@Input() @Input()
public enableShortcut = false; public enableShortcut = false;

1
src/Squidex/app/shared/declarations.ts

@ -18,5 +18,6 @@ export * from './components/markdown-editor.component';
export * from './components/pipes'; export * from './components/pipes';
export * from './components/rich-editor.component'; export * from './components/rich-editor.component';
export * from './components/schema-category.component'; export * from './components/schema-category.component';
export * from './components/search-form.component';
export * from './internal'; export * from './internal';

2
src/Squidex/app/shared/internal.ts

@ -57,11 +57,11 @@ export * from './state/languages.state';
export * from './state/patterns.forms'; export * from './state/patterns.forms';
export * from './state/patterns.state'; export * from './state/patterns.state';
export * from './state/plans.state'; export * from './state/plans.state';
export * from './state/queries';
export * from './state/rule-events.state'; export * from './state/rule-events.state';
export * from './state/rules.state'; export * from './state/rules.state';
export * from './state/schemas.forms'; export * from './state/schemas.forms';
export * from './state/schemas.state'; export * from './state/schemas.state';
export * from './state/schema-queries';
export * from './state/ui.state'; export * from './state/ui.state';
export * from './utils/messages'; export * from './utils/messages';

5
src/Squidex/app/shared/module.ts

@ -66,6 +66,7 @@ import {
SchemaMustExistPublishedGuard, SchemaMustExistPublishedGuard,
SchemasService, SchemasService,
SchemasState, SchemasState,
SearchFormComponent,
UIService, UIService,
UIState, UIState,
UnsetAppGuard, UnsetAppGuard,
@ -108,7 +109,8 @@ import {
UserNameRefPipe, UserNameRefPipe,
UserPicturePipe, UserPicturePipe,
UserPictureRefPipe, UserPictureRefPipe,
RichEditorComponent RichEditorComponent,
SearchFormComponent
], ],
exports: [ exports: [
AppFormComponent, AppFormComponent,
@ -126,6 +128,7 @@ import {
MarkdownEditorComponent, MarkdownEditorComponent,
RouterModule, RouterModule,
SchemaCategoryComponent, SchemaCategoryComponent,
SearchFormComponent,
UserDtoPicture, UserDtoPicture,
UserIdPicturePipe, UserIdPicturePipe,
UserNamePipe, UserNamePipe,

4
src/Squidex/app/shared/state/assets.state.ts

@ -45,6 +45,10 @@ export class AssetsState extends State<Snapshot> {
this.changes.pipe(map(x => x.assets), this.changes.pipe(map(x => x.assets),
distinctUntilChanged()); distinctUntilChanged());
public assetsQuery =
this.changes.pipe(map(x => x.assetsQuery),
distinctUntilChanged());
public assetsPager = public assetsPager =
this.changes.pipe(map(x => x.assetsPager), this.changes.pipe(map(x => x.assetsPager),
distinctUntilChanged()); distinctUntilChanged());

24
src/Squidex/app/shared/state/schema-queries.spec.ts → src/Squidex/app/shared/state/queries.spec.ts

@ -8,35 +8,35 @@
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { IMock, Mock, Times } from 'typemoq'; import { IMock, Mock, Times } from 'typemoq';
import { Query, SchemaQueries } from './schema-queries'; import { Queries, Query } from './queries';
import { UIState } from './ui.state'; import { UIState } from './ui.state';
describe('SchemaQueries', () => { describe('Queries', () => {
const schema = 'my-schema'; const prefix = 'schemas.my-schema';
let uiState: IMock<UIState>; let uiState: IMock<UIState>;
let filter = new BehaviorSubject(''); let filter = new BehaviorSubject('');
let queries = new BehaviorSubject({}); let queries$ = new BehaviorSubject({});
let schemaQueries: SchemaQueries; let queries: Queries;
beforeEach(() => { beforeEach(() => {
uiState = Mock.ofType<UIState>(); uiState = Mock.ofType<UIState>();
uiState.setup(x => x.get('schemas.my-schema.queries', {})) uiState.setup(x => x.get('schemas.my-schema.queries', {}))
.returns(() => queries); .returns(() => queries$);
queries.next({ queries$.next({
key1: 'query1', key1: 'query1',
key2: 'query2' key2: 'query2'
}); });
schemaQueries = new SchemaQueries(uiState.object, schema); queries = new Queries(uiState.object, prefix);
}); });
it('should load queries', () => { it('should load queries', () => {
let converted: Query[]; let converted: Query[];
schemaQueries.queries.subscribe(x => { queries.queries.subscribe(x => {
converted = x; converted = x;
}); });
@ -56,7 +56,7 @@ describe('SchemaQueries', () => {
it('should provide key', () => { it('should provide key', () => {
let key: string; let key: string;
schemaQueries.getSaveKey(filter).subscribe(x => { queries.getSaveKey(filter).subscribe(x => {
key = x!; key = x!;
}); });
@ -66,13 +66,13 @@ describe('SchemaQueries', () => {
}); });
it('should forward add call to state', () => { it('should forward add call to state', () => {
schemaQueries.add('key3', 'filter3'); queries.add('key3', 'filter3');
uiState.verify(x => x.set('schemas.my-schema.queries.key3', 'filter3'), Times.once()); uiState.verify(x => x.set('schemas.my-schema.queries.key3', 'filter3'), Times.once());
}); });
it('should forward remove call to state', () => { it('should forward remove call to state', () => {
schemaQueries.remove('key3'); queries.remove('key3');
uiState.verify(x => x.remove('schemas.my-schema.queries.key3'), Times.once()); uiState.verify(x => x.remove('schemas.my-schema.queries.key3'), Times.once());
}); });

10
src/Squidex/app/shared/state/schema-queries.ts → src/Squidex/app/shared/state/queries.ts

@ -16,7 +16,7 @@ export interface Query {
filter: string; filter: string;
} }
export class SchemaQueries { export class Queries {
public queries: Observable<Query[]>; public queries: Observable<Query[]>;
public defaultQueries: Query[] = [{ public defaultQueries: Query[] = [{
@ -27,9 +27,9 @@ export class SchemaQueries {
constructor( constructor(
private readonly uiState: UIState, private readonly uiState: UIState,
private readonly schemaName: string private readonly prefix: string
) { ) {
this.queries = this.uiState.get(`schemas.${this.schemaName}.queries`, {}).pipe( this.queries = this.uiState.get(`${this.prefix}.queries`, {}).pipe(
map(x => { map(x => {
let queries: Query[] = Object.keys(x).map(y => ({ name: y, filter: x[y] })); let queries: Query[] = Object.keys(x).map(y => ({ name: y, filter: x[y] }));
@ -53,11 +53,11 @@ export class SchemaQueries {
} }
public add(key: string, filter: string) { public add(key: string, filter: string) {
this.uiState.set(`schemas.${this.schemaName}.queries.${key}`, filter); this.uiState.set(`${this.prefix}.queries.${key}`, filter);
} }
public remove(key: string) { public remove(key: string) {
this.uiState.remove(`schemas.${this.schemaName}.queries.${key}`); this.uiState.remove(`${this.prefix}.queries.${key}`);
} }
public getSaveKey(filter$: Observable<string>): Observable<string | null> { public getSaveKey(filter$: Observable<string>): Observable<string | null> {
Loading…
Cancel
Save