From a41090e99766a41bf73a96a07161fcbf45ceeb06 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 28 Aug 2018 20:07:47 +0200 Subject: [PATCH] Save queries. --- .../Apps/AppUISettingsGrain.cs | 20 +- .../Apps/IAppUISettingsGrain.cs | 2 +- .../Controllers/UI/Models/UpdateSettingDto.cs | 19 + .../Areas/Api/Controllers/UI/UIController.cs | 6 +- .../assets/pages/assets-page.component.html | 8 +- .../assets/pages/assets-page.component.scss | 21 - .../contents/contents-page.component.html | 34 +- .../pages/contents/contents-page.component.ts | 37 +- .../pages/contents/search-form.component.html | 37 +- .../pages/contents/search-form.component.scss | 10 +- .../pages/contents/search-form.component.ts | 48 +- src/Squidex/app/shared/internal.ts | 1 + src/Squidex/app/shared/services/ui.service.ts | 2 +- .../app/shared/state/contents.forms.ts | 14 +- .../app/shared/state/schema-queries.spec.ts | 79 + .../app/shared/state/schema-queries.ts | 78 + src/Squidex/app/shared/state/ui.state.ts | 15 +- src/Squidex/app/theme/_panels.scss | 38 + .../app/theme/icomoon/demo-files/demo.css | 8 +- src/Squidex/app/theme/icomoon/demo.html | 1052 ++++---- .../app/theme/icomoon/fonts/icomoon.eot | Bin 25320 -> 25736 bytes .../app/theme/icomoon/fonts/icomoon.svg | 3 + .../app/theme/icomoon/fonts/icomoon.ttf | Bin 25156 -> 25572 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 25232 -> 25648 bytes src/Squidex/app/theme/icomoon/selection.json | 2266 +++++++++-------- src/Squidex/app/theme/icomoon/style.css | 118 +- .../Apps/AppUISettingsGrainTests.cs | 4 +- 27 files changed, 2211 insertions(+), 1709 deletions(-) create mode 100644 src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs create mode 100644 src/Squidex/app/shared/state/schema-queries.spec.ts create mode 100644 src/Squidex/app/shared/state/schema-queries.ts diff --git a/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs b/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs index 3c88584cd..ea1e17408 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs @@ -18,8 +18,14 @@ namespace Squidex.Domain.Apps.Entities.Apps public sealed class AppUISettingsGrain : GrainOfGuid, IAppUISettingsGrain { private readonly IStore store; - private IPersistence persistence; - private JObject state = new JObject(); + private IPersistence persistence; + private State state = new State(); + + [CollectionName("UISettings")] + public sealed class State + { + public JObject Settings { get; set; } = new JObject(); + } public AppUISettingsGrain(IStore store) { @@ -30,19 +36,19 @@ namespace Squidex.Domain.Apps.Entities.Apps public override Task OnActivateAsync(Guid key) { - persistence = store.WithSnapshots(GetType(), key, x => state = x); + persistence = store.WithSnapshots(GetType(), key, x => state = x); return persistence.ReadAsync(); } public Task> GetAsync() { - return Task.FromResult(state.AsJ()); + return Task.FromResult(state.Settings.AsJ()); } - public Task SetAsync(J setting) + public Task SetAsync(J settings) { - state = setting; + state.Settings = settings; return persistence.WriteSnapshotAsync(state); } @@ -81,7 +87,7 @@ namespace Squidex.Domain.Apps.Entities.Apps key = segments[segments.Length - 1]; - var current = state; + var current = state.Settings; if (segments.Length > 1) { diff --git a/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs b/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs index 23b680e51..38fde5c74 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs @@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Entities.Apps Task SetAsync(string path, J value); - Task SetAsync(J setting); + Task SetAsync(J settings); Task RemoveAsync(string path); } diff --git a/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs b/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs new file mode 100644 index 000000000..8262de435 --- /dev/null +++ b/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs @@ -0,0 +1,19 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Newtonsoft.Json.Linq; + +namespace Squidex.Areas.Api.Controllers.UI.Models +{ + public sealed class UpdateSettingDto + { + /// + /// The value for the setting. + /// + public JToken Value { get; set; } + } +} diff --git a/src/Squidex/Areas/Api/Controllers/UI/UIController.cs b/src/Squidex/Areas/Api/Controllers/UI/UIController.cs index 80c4ea6c6..0c1d38e01 100644 --- a/src/Squidex/Areas/Api/Controllers/UI/UIController.cs +++ b/src/Squidex/Areas/Api/Controllers/UI/UIController.cs @@ -22,7 +22,9 @@ namespace Squidex.Areas.Api.Controllers.UI /// /// Manages ui settings and configs. /// + [ApiAuthorize] [ApiExceptionFilter] + [AppApi] [SwaggerTag(nameof(UI))] public sealed class UIController : ApiController { @@ -71,9 +73,9 @@ namespace Squidex.Areas.Api.Controllers.UI [HttpPut] [Route("apps/{app}/ui/settings/{key}")] [ApiCosts(0)] - public async Task PutSetting(string app, string key, [FromBody] JToken value) + public async Task PutSetting(string app, string key, [FromBody] UpdateSettingDto request) { - await grainFactory.GetGrain(App.Id).SetAsync(key, value); + await grainFactory.GetGrain(App.Id).SetAsync(key, request.Value); return NoContent(); } diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.html b/src/Squidex/app/features/assets/pages/assets-page.component.html index 38718404e..607200788 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.html +++ b/src/Squidex/app/features/assets/pages/assets-page.component.html @@ -23,18 +23,18 @@ -
- + -
+
-
\ No newline at end of file + + + +
+ + + Name your query + + + +
+ + + +
+
+ + + + + +
+
+
\ No newline at end of file diff --git a/src/Squidex/app/features/content/pages/contents/search-form.component.scss b/src/Squidex/app/features/content/pages/contents/search-form.component.scss index 20c685cc2..4eb03572e 100644 --- a/src/Squidex/app/features/content/pages/contents/search-form.component.scss +++ b/src/Squidex/app/features/content/pages/contents/search-form.component.scss @@ -10,7 +10,7 @@ } .form-control-expandable { - padding-right: 1.5rem; + padding-right: 3rem; } .form-horizontal { @@ -26,6 +26,14 @@ text-align: right; } +.save-search { + @include absolute(8px, 24px, auto, auto); + color: $color-border-dark !important; + font-size: .9rem; + font-weight: normal; + cursor: pointer !important; +} + .expand-search { @include absolute(8px, 8px, auto, auto); color: $color-border-dark !important; diff --git a/src/Squidex/app/features/content/pages/contents/search-form.component.ts b/src/Squidex/app/features/content/pages/contents/search-form.component.ts index babf2991b..200b7c404 100644 --- a/src/Squidex/app/features/content/pages/contents/search-form.component.ts +++ b/src/Squidex/app/features/content/pages/contents/search-form.component.ts @@ -5,10 +5,12 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; import { FormBuilder, FormControl } from '@angular/forms'; -import { ModalModel } from '@app/shared'; +import { ModalModel, SaveQueryForm, SchemaQueries } from '@app/shared'; +import { Observable } from 'rxjs'; +import { shareReplay } from 'rxjs/operators'; @Component({ selector: 'sqx-search-form', @@ -16,7 +18,10 @@ import { ModalModel } from '@app/shared'; templateUrl: './search-form.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -export class SearchFormComponent implements OnChanges { +export class SearchFormComponent implements OnChanges, OnInit { + @Input() + public queries: SchemaQueries; + @Input() public query = ''; @@ -29,6 +34,9 @@ export class SearchFormComponent implements OnChanges { @Output() public archivedChanged = new EventEmitter(); + @Input() + public schemaName = ''; + @Input() public canArchive = true; @@ -39,6 +47,9 @@ export class SearchFormComponent implements OnChanges { public formClass = 'form-inline search-form'; public contentsFilter = new FormControl(); + public contentsFilterValue = this.contentsFilter.valueChanges.pipe(shareReplay(1)); + + public saveKey: Observable; public searchModal = new ModalModel(); public searchForm = @@ -48,21 +59,44 @@ export class SearchFormComponent implements OnChanges { odataSearch: '' }); + public saveQueryDialog = new ModalModel(); + public saveQueryForm = new SaveQueryForm(this.formBuilder); + constructor( private readonly formBuilder: FormBuilder ) { } - public search() { - this.invalidate(this.contentsFilter.value); - - this.queryChanged.emit(this.contentsFilter.value); + public ngOnInit() { + this.saveKey = this.queries.getSaveKey(this.contentsFilter.valueChanges); } public ngOnChanges() { this.invalidate(this.query); } + public saveQuery() { + this.saveQueryDialog.show(); + } + + public saveQueryComplete() { + const value = this.saveQueryForm.submit(); + + if (value) { + this.queries.add(value.name, this.contentsFilter.value); + + this.saveQueryForm.submitCompleted(); + } + + this.saveQueryDialog.hide(); + } + + public search() { + this.invalidate(this.contentsFilter.value); + + this.queryChanged.emit(this.contentsFilter.value); + } + private invalidate(query: string) { if (query === this.contentsFilter.value) { return; diff --git a/src/Squidex/app/shared/internal.ts b/src/Squidex/app/shared/internal.ts index 669db06e0..d5bae2b7e 100644 --- a/src/Squidex/app/shared/internal.ts +++ b/src/Squidex/app/shared/internal.ts @@ -61,6 +61,7 @@ export * from './state/rule-events.state'; export * from './state/rules.state'; export * from './state/schemas.forms'; export * from './state/schemas.state'; +export * from './state/schema-queries'; export * from './state/ui.state'; export * from './utils/messages'; diff --git a/src/Squidex/app/shared/services/ui.service.ts b/src/Squidex/app/shared/services/ui.service.ts index dc590d332..9a8a43c80 100644 --- a/src/Squidex/app/shared/services/ui.service.ts +++ b/src/Squidex/app/shared/services/ui.service.ts @@ -37,7 +37,7 @@ export class UIService { public putSetting(appName: string, key: string, value: any): Observable { const url = this.apiUrl.buildUrl(`api/apps/${appName}/ui/settings/${key}`); - return this.http.put(url, value); + return this.http.put(url, { value }); } public deleteSetting(appName: string, key: string): Observable { diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index cad79f703..348124935 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -8,7 +8,7 @@ // tslint:disable:prefer-for-of -import { FormArray, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; +import { FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; import { DateTime, @@ -36,6 +36,18 @@ import { TagsFieldPropertiesDto } from './../services/schemas.types'; +export class SaveQueryForm extends Form { + constructor(formBuilder: FormBuilder) { + super(formBuilder.group({ + name: ['', + [ + Validators.required + ] + ] + })); + } +} + export class FieldFormatter implements FieldPropertiesVisitor { constructor( private readonly value: any diff --git a/src/Squidex/app/shared/state/schema-queries.spec.ts b/src/Squidex/app/shared/state/schema-queries.spec.ts new file mode 100644 index 000000000..9041ac821 --- /dev/null +++ b/src/Squidex/app/shared/state/schema-queries.spec.ts @@ -0,0 +1,79 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { BehaviorSubject } from 'rxjs'; +import { IMock, Mock, Times } from 'typemoq'; + +import { Query, SchemaQueries } from './schema-queries'; +import { UIState } from './ui.state'; + +describe('SchemaQueries', () => { + const schema = 'my-schema'; + + let uiState: IMock; + let filter = new BehaviorSubject(''); + let queries = new BehaviorSubject({}); + let schemaQueries: SchemaQueries; + + beforeEach(() => { + uiState = Mock.ofType(); + + uiState.setup(x => x.get('schemas.my-schema.queries', {})) + .returns(() => queries); + + queries.next({ + key1: 'query1', + key2: 'query2' + }); + + schemaQueries = new SchemaQueries(uiState.object, schema); + }); + + it('should load queries', () => { + let converted: Query[]; + + schemaQueries.queries.subscribe(x => { + converted = x; + }); + + expect(converted!).toEqual([ + { + name: 'key1', + nameSortable: 'KEY1', + filter: 'query1' + }, { + name: 'key2', + nameSortable: 'KEY2', + filter: 'query2' + } + ]); + }); + + it('should provide key', () => { + let key: string; + + schemaQueries.getSaveKey(filter).subscribe(x => { + key = x!; + }); + + filter.next('query2'); + + expect(key!).toEqual('key2'); + }); + + it('should forward add call to state', () => { + schemaQueries.add('key3', 'filter3'); + + uiState.verify(x => x.set('schemas.my-schema.queries.key3', 'filter3'), Times.once()); + }); + + it('should forward remove call to state', () => { + schemaQueries.remove('key3'); + + uiState.verify(x => x.remove('schemas.my-schema.queries.key3'), Times.once()); + }); +}); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/schema-queries.ts b/src/Squidex/app/shared/state/schema-queries.ts new file mode 100644 index 000000000..defa41ec1 --- /dev/null +++ b/src/Squidex/app/shared/state/schema-queries.ts @@ -0,0 +1,78 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { combineLatest, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { UIState } from './ui.state'; + +export interface Query { + name: string; + nameSortable?: string; + filter: string; +} + +export class SchemaQueries { + public queries: Observable; + + public defaultQueries: Query[] = [{ + name: 'All (newest first)', filter: '' + }, { + name: 'All (oldest first)', filter: '$orderby=lastModified desc' + }]; + + constructor( + private readonly uiState: UIState, + private readonly schemaName: string + ) { + this.queries = this.uiState.get(`schemas.${this.schemaName}.queries`, {}).pipe( + map(x => { + let queries: Query[] = Object.keys(x).map(y => ({ name: y, filter: x[y] })); + + for (let query of queries) { + query.nameSortable = query.name.toUpperCase(); + } + + queries = queries.sort((a, b) => { + if (a.nameSortable! < b.nameSortable!) { + return -1; + } + if (a.nameSortable! > b.nameSortable!) { + return 1; + } + return 0; + }); + + return queries; + }) + ); + } + + public add(key: string, filter: string) { + this.uiState.set(`schemas.${this.schemaName}.queries.${key}`, filter); + } + + public remove(key: string) { + this.uiState.remove(`schemas.${this.schemaName}.queries.${key}`); + } + + public getSaveKey(filter$: Observable): Observable { + return combineLatest(this.queries, filter$).pipe( + map(project => { + const filter = project[1]; + + if (filter) { + for (let query of project[0]) { + if (query.filter === filter) { + return query.name; + } + } + } + return null; + })); + } +} \ No newline at end of file diff --git a/src/Squidex/app/shared/state/ui.state.ts b/src/Squidex/app/shared/state/ui.state.ts index c7edafdf4..84a633a81 100644 --- a/src/Squidex/app/shared/state/ui.state.ts +++ b/src/Squidex/app/shared/state/ui.state.ts @@ -6,8 +6,7 @@ */ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map } from 'rxjs/operators'; import { State, Types } from '@app/framework'; @@ -47,19 +46,15 @@ export class UIState extends State { } } - public load(reset = false): Observable { + public load(reset = false) { if (!reset) { this.resetState(); } - return this.loadInternal(); - } - - private loadInternal(): Observable { - return this.uiService.getSettings(this.appName).pipe( - tap(dtos => { + this.uiService.getSettings(this.appName) + .subscribe(dtos => { return this.next({ settings: dtos }); - })); + }); } public set(path: string, value: any) { diff --git a/src/Squidex/app/theme/_panels.scss b/src/Squidex/app/theme/_panels.scss index 6124ea873..9631aed47 100644 --- a/src/Squidex/app/theme/_panels.scss +++ b/src/Squidex/app/theme/_panels.scss @@ -280,6 +280,44 @@ } } } + + &-section { + border-top: 1px solid $color-border; + padding: 1rem; + } + + &-item { + & { + padding: .25rem 0; + font-size: .9rem; + font-weight: normal; + } + + &-remove { + visibility: hidden; + } + + &.active { + font-weight: bold; + } + + &.active, + &:hover { + background: $color-background; + } + + &:hover { + .sidebar-item-remove { + visibility: visible; + } + } + } +} + +a { + &.sidebar-item { + cursor: pointer !important; + } } // diff --git a/src/Squidex/app/theme/icomoon/demo-files/demo.css b/src/Squidex/app/theme/icomoon/demo-files/demo.css index 9c149f296..8823845c8 100644 --- a/src/Squidex/app/theme/icomoon/demo-files/demo.css +++ b/src/Squidex/app/theme/icomoon/demo-files/demo.css @@ -147,16 +147,16 @@ p { font-size: 16px; } .fs1 { - font-size: 24px; + font-size: 32px; } .fs2 { - font-size: 32px; + font-size: 24px; } .fs3 { - font-size: 28px; + font-size: 32px; } .fs4 { - font-size: 32px; + font-size: 28px; } .fs5 { font-size: 32px; diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index 3b417bb03..993a5be49 100644 --- a/src/Squidex/app/theme/icomoon/demo.html +++ b/src/Squidex/app/theme/icomoon/demo.html @@ -9,20 +9,20 @@
-

Font Name: icomoon (Glyphs: 95)

+

Font Name: icomoon (Glyphs: 98)

-

Grid Size: 24

+

Grid Size: 16

- + - icon-backup + icon-star-full
- - + +
liga: @@ -31,14 +31,14 @@
- + - icon-support + icon-star-empty
- - + +
liga: @@ -47,14 +47,14 @@
- + - icon-control-RichText + icon-twitter
- - + +
liga: @@ -63,289 +63,289 @@
- + - icon-download + icon-action-Tweet
- - + +
liga:
-
-
-

Grid Size: Unknown

-
+
- + - icon-action-Medium + icon-hour-glass
- - + +
liga:
-
+
- + - icon-circle + icon-spinner
- - + +
liga:
-
+
- + - icon-action-Fastly + icon-clock
- - + +
liga:
-
+
- + - icon-control-Slug + icon-bin2
- - + +
liga:
-
+
- + - icon-action-Algolia + icon-earth
- - + +
liga: - +
-
+
- + - icon-type-Tags + icon-elapsed
- - + +
liga:
-
+
- + - icon-activity + icon-google
- - + +
liga:
-
+
- + - icon-history + icon-lock
- - + +
liga:
-
+
- + - icon-time + icon-microsoft
- - + +
liga:
-
+
- + - icon-add + icon-action-AzureQueue
- - + +
liga:
-
+
- + - icon-plus + icon-pause
- - + +
liga:
-
+
- + - icon-check-circle + icon-play
- - + +
liga:
-
+
- + - icon-check-circle-filled + icon-reset
- - + +
liga:
-
+
- + - icon-close + icon-settings2
- - + +
liga:
-
+
- + - icon-type-References + icon-timeout
- - + +
liga:
-
+
- + - icon-control-Checkbox + icon-unlocked
- - + +
liga:
+
+
+

Grid Size: 24

- + - icon-control-Dropdown + icon-backup
- - + +
liga: @@ -354,14 +354,14 @@
- + - icon-control-Input + icon-support
- - + +
liga: @@ -370,14 +370,14 @@
- + - icon-control-Radio + icon-control-RichText
- - + +
liga: @@ -386,577 +386,641 @@
- + - icon-control-TextArea + icon-download
- - + +
liga:
-
+
+
+

Grid Size: Unknown

+
- + - icon-control-Toggle + icon-action-Medium
- - + +
liga:
-
+
- + - icon-copy + icon-circle
- - + +
liga:
-
+
- + - icon-dashboard + icon-action-Fastly
- - + +
liga:
-
+
- + - icon-delete + icon-control-Slug
- - + +
liga:
-
+
- + - icon-bin + icon-action-Algolia
- - + +
liga:
-
+
- + - icon-delete-filled + icon-type-Tags
- - + +
liga:
-
+
- + - icon-document-delete + icon-activity
- - + +
liga:
-
+
- + - icon-document-disable + icon-history
- - + +
liga:
-
+
- + - icon-document-publish + icon-time
- - + +
liga:
-
+
- + - icon-drag + icon-add
- - + +
liga:
-
+
- + - icon-filter + icon-plus
- - + +
liga:
-
+
- + - icon-github + icon-check-circle
- - + +
liga:
-
+
- + - icon-help + icon-check-circle-filled
- - + +
liga:
-
+
- + - icon-location + icon-close
- - + +
liga:
-
+
- + - icon-control-Map + icon-type-References
- - + +
liga:
-
+
- + - icon-type-Geolocation + icon-control-Checkbox
- - + +
liga:
-
+
-
- - + +
liga:
-
+
- + - icon-media + icon-control-Input
- - + +
liga:
-
+
- + - icon-type-Assets + icon-control-Radio
- - + +
liga:
-
+
- + - icon-trigger-AssetChanged + icon-control-TextArea
- - + +
liga:
-
+
- + - icon-more + icon-control-Toggle
- - + +
liga:
-
+
- + - icon-dots + icon-copy
- - + +
liga:
-
+
- + - icon-pencil + icon-dashboard
- - + +
liga:
-
+
- + - icon-reference + icon-delete
- - + + +
+
+ liga: + +
+
+
+
+ + + + icon-bin +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-delete-filled +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-document-delete +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-document-disable +
+
+ +
liga:
-
+
- + - icon-schemas + icon-document-publish
- - + +
liga:
-
+
- + - icon-search + icon-drag
- - + +
liga:
-
+
- + - icon-settings + icon-filter
- - + +
liga:
-
+
- + - icon-type-Boolean + icon-github
- - + +
liga:
-
+
- + - icon-type-DateTime + icon-help
- - + +
liga:
-
+
- + - icon-type-Json + icon-location
- - + +
liga:
-
+
- + - icon-json + icon-control-Map
- - + +
liga:
-
+
- + - icon-type-Number + icon-type-Geolocation
- - + +
liga:
-
+
- + - icon-type-String + icon-logo
- - + +
liga:
-
+
- + - icon-user + icon-media
- - + +
liga:
-
-
-

Grid Size: 14

- + - icon-single-content + icon-type-Assets
- - + +
liga: @@ -965,14 +1029,14 @@
- + - icon-multiple-content + icon-trigger-AssetChanged
- - + +
liga: @@ -981,14 +1045,14 @@
- + - icon-type-Array + icon-more
- - + +
liga: @@ -997,14 +1061,14 @@
- + - icon-exclamation + icon-dots
- - + +
liga: @@ -1013,14 +1077,14 @@
- + - icon-action-ElasticSearch + icon-pencil
- - + +
liga: @@ -1029,14 +1093,14 @@
- + - icon-action-Slack + icon-reference
- - + +
liga: @@ -1045,14 +1109,14 @@
- + - icon-orleans + icon-schemas
- - + +
liga: @@ -1061,14 +1125,14 @@
- + - icon-document-lock + icon-search
- - + +
liga: @@ -1077,14 +1141,14 @@
- + - icon-document-unpublish + icon-settings
- - + +
liga: @@ -1093,14 +1157,14 @@
- + - icon-angle-down + icon-type-Boolean
- - + +
liga: @@ -1109,14 +1173,14 @@
- + - icon-angle-left + icon-type-DateTime
- - + +
liga: @@ -1125,14 +1189,14 @@
- + - icon-angle-right + icon-type-Json
- - + +
liga: @@ -1141,14 +1205,14 @@
- + - icon-angle-up + icon-json
- - + +
liga: @@ -1157,14 +1221,14 @@
- + - icon-api + icon-type-Number
- - + +
liga: @@ -1173,14 +1237,14 @@
- + - icon-assets + icon-type-String
- - + +
liga: @@ -1189,257 +1253,257 @@
- + - icon-bug + icon-user
- - + +
liga:
-
+
+
+

Grid Size: 14

+
- + - icon-caret-down + icon-single-content
- - + +
liga:
-
+
- + - icon-caret-left + icon-multiple-content
-
- - +
+ +
liga:
-
+
- + - icon-caret-right + icon-type-Array
- - + +
liga:
-
+
- + - icon-caret-up + icon-exclamation
- - + +
liga:
-
+
- + - icon-contents + icon-action-ElasticSearch
- - + +
liga:
-
+
- + - icon-trigger-ContentChanged + icon-action-Slack
- - + +
liga:
-
+
- + - icon-control-Date + icon-orleans
- - + +
liga:
-
+
- + - icon-control-DateTime + icon-document-lock
- - + +
liga:
-
+
- + - icon-control-Markdown + icon-document-unpublish
- - + +
liga:
-
+
- + - icon-grid + icon-angle-down
- - + +
liga:
-
+
- + - icon-list + icon-angle-left
- - + +
liga:
-
+
- + - icon-user-o + icon-angle-right
- - + +
liga:
-
+
- + - icon-rules + icon-angle-up
- - + +
liga:
-
+
- + - icon-action-Webhook + icon-api
- - + +
liga:
-
-
-

Grid Size: 16

- + - icon-hour-glass + icon-assets
- - + +
liga: @@ -1448,14 +1512,14 @@
- + - icon-spinner + icon-bug
- - + +
liga: @@ -1464,14 +1528,14 @@
- + - icon-clock + icon-caret-down
- - + +
liga: @@ -1480,14 +1544,14 @@
- + - icon-bin2 + icon-caret-left
- - + +
liga: @@ -1496,30 +1560,30 @@
- + - icon-earth + icon-caret-right
- - + +
liga: - +
- + - icon-elapsed + icon-caret-up
- - + +
liga: @@ -1528,14 +1592,14 @@
- + - icon-google + icon-contents
- - + +
liga: @@ -1544,14 +1608,14 @@
- + - icon-lock + icon-trigger-ContentChanged
- - + +
liga: @@ -1560,14 +1624,14 @@
- + - icon-microsoft + icon-control-Date
- - + +
liga: @@ -1576,14 +1640,14 @@
- + - icon-action-AzureQueue + icon-control-DateTime
- - + +
liga: @@ -1592,14 +1656,14 @@
- + - icon-pause + icon-control-Markdown
- - + +
liga: @@ -1608,14 +1672,14 @@
- + - icon-play + icon-grid
- - + +
liga: @@ -1624,14 +1688,14 @@
- + - icon-reset + icon-list
- - + +
liga: @@ -1640,14 +1704,14 @@
- + - icon-settings2 + icon-user-o
- - + +
liga: @@ -1656,14 +1720,14 @@
- + - icon-timeout + icon-rules
- - + +
liga: @@ -1672,14 +1736,14 @@
- + - icon-unlocked + icon-action-Webhook
- - + +
liga: diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 7d637f8990f194cefdf7fb70f9311affd3c82407..d3d2848311ef2866f3c4b0a8fb4675eddde93fca 100644 GIT binary patch delta 688 zcmZWmT}V@57=GV#wjHKBXC5~CEih%{AvO;?F3vcx@)7J>J$m09qgEuQJ+P7UppXU`!(3 zI;~|UmU^wMUK~rEYsDQoQ^~k-X8Tg<=Pvx9$vE7IBJ|zr`6lNe3PwBmd^zO z!Td~iQBkm^qk;Lvi>xEzt3Sedymew+mV>rN8!L)&MTxl8X7y4t3N}RSn-xqfgUR!Z zKf<7^UTownYV66?sWiuPu2`!vD-HbPJq`R2YKY`~wa6puGqXMuR11YdwSbU7S_uRu z8pW>a^Jt~Iy1tI16#(Y1u#@6{(#XY>lh}fs`~N;w`0U@TWV4k`|GzDT>dK9S4e#!* zcjJH_SM**SV5QP>zjef(_y)Bm^|6=?zT zHGq10a`KZC{ZFL!Ffhb#0m`4qO{^$jsA7x)T2TY!E952Srq1-@{0-#K0jh5+$S*Eo zU}HIf{DD!Kb(%mp|IE!2OuUhsH^u}r%j{1oxE;@L^Ob=c zWIY4J^|mxPJy{{aoH2QGL_!DSL{5WYT FBLJ$JQAPj& diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg index ff07500d5..d4bcfdb28 100644 --- a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg +++ b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg @@ -99,6 +99,9 @@ + + + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index c486ad6d3b49d3af49fe608f9197c9cd64652a75..d3f0a0fa98cf8465b7aca6679d482f0a1a2f3f66 100644 GIT binary patch delta 708 zcmZWm-%C?*6hG(Q&D(VM?x&l^oYuB`V{>b|wlSD1i6CTPWe+Clye{WRrxzSyfy{>r zp_gP38nS#ygMNUpd<*JfkiPWLLs3CJ=pP_S4=z}pYeZ4sFW>Lye9k$a^F4=erGh)J zu>c4F4KN2R1bh3AcN)z63-YLEIGvM~PqB|*0nkBwVoaV^2#v(&2@j1;T+i&?+nXhR z7hrHRJ1SqXl;1rANcB@Zk|l?Z(T)+PIJmR9{LGD2>rLX%NwYXHmF||GREkajIY|j` za`KDYX49n#_ z@|OzgP@n!l0$+U$! zqf{UgJ|Tt)HQ?xKI}+5lo_0IV`F)ZYGn!bYyDKpn3`)Eqs_LF-sfvym{Jxc30uRB%xB)jTH+q_Vb19`nqs2Zu5Z$_CR0q3g7!#D2rva|0Jy$L9S$UCI#u1`QguV|f2~%k~?KyMs~8l#dO~WAS0? jt+RdCFZdJwoxn<9hjP^K%wRtp|WAtPnMrGD%0^$5KHfXSO}sf{^5!k^9gLGb5|4@L%IV(HlLH4vGGhdT7+4|G Oyyp7*s%* zlZiDwBe$f2fgu6NWt;)RRZB%$a`Kab>iiOc0u1Lsc=eIVa=D2WK#P+=j!^*PTE?in z#N1S%SO-vJ8wk(z;{08ZUt9w8i2z(3Gmyp1d~z}mV>e^mBW1sZ0Zk-Cs)+wfFXBq$Z{?FvLj!)tG^>aJE2W22c1gO6Ug!7h)wB+O`1J(H@0M#&@0Ac?VsXe)g6+nv~k!)iDEE%*@9p^DuTZMo*r>sLVP|Ae?{Z<^znpk((o9 zf|+IZCl%a|=ePOFz|8_w%fN8G4d@*xJ^4huIb-ssgbv2ZQxcEy=*sEd(vt&+R`TY& Hq(h7V store = A.Fake>(); - private readonly IPersistence persistence = A.Fake>(); + private readonly IPersistence persistence = A.Fake>(); private readonly AppUISettingsGrain sut; public AppUISettingsGrainTests() { - A.CallTo(() => store.WithSnapshots(A.Ignored, A.Ignored, A>.Ignored)) + A.CallTo(() => store.WithSnapshots(A.Ignored, A.Ignored, A>.Ignored)) .Returns(persistence); sut = new AppUISettingsGrain(store);