mirror of https://github.com/Squidex/squidex.git
Browse Source
* Started with resizable columns. * Store settings together. * Finalized. * Fix drag preview. * Some more design fixes. * Mini improvements. * Modernization. * Wrapping * Fix tests. * Refactorings.pull/853/head
committed by
GitHub
90 changed files with 1174 additions and 473 deletions
@ -1,7 +1,11 @@ |
|||||
<ng-container *ngIf="isPlain; else html"> |
<ng-container *ngIf="isPlain; else html"> |
||||
<span> |
<div class="value-container"> |
||||
<span class="truncate">{{value}}</span> |
<div #valueElement [class.truncate]="!wrapping">{{value}}</div> |
||||
</span> |
</div> |
||||
|
|
||||
|
<button class="btn btn-icon" *ngIf="isString && fields" (click)="toggle()" sqxStopClick> |
||||
|
<i class="icon-wrap_text"></i> |
||||
|
</button> |
||||
</ng-container> |
</ng-container> |
||||
<ng-template #html> |
<ng-template #html> |
||||
<div class="html-value" [innerHTML]="value.html"></div> |
<div class="html-value" [innerHTML]="value.html"></div> |
||||
|
|||||
@ -1,131 +0,0 @@ |
|||||
/* |
|
||||
* Squidex Headless CMS |
|
||||
* |
|
||||
* @license |
|
||||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|
||||
*/ |
|
||||
|
|
||||
import { of } from 'rxjs'; |
|
||||
import { IMock, Mock, Times } from 'typemoq'; |
|
||||
import { DateTime, Version } from '@app/framework'; |
|
||||
import { createProperties, MetaFields, RootFieldDto, SchemaDto, TableField, TableFields, UIState } from '@app/shared/internal'; |
|
||||
|
|
||||
describe('TableFields', () => { |
|
||||
let uiState: IMock<UIState>; |
|
||||
|
|
||||
const schema = |
|
||||
new SchemaDto({}, |
|
||||
'1', |
|
||||
DateTime.now(), 'me', |
|
||||
DateTime.now(), 'me', |
|
||||
new Version('1'), |
|
||||
'my-schema', |
|
||||
'my-category', |
|
||||
'Default', |
|
||||
false, |
|
||||
{}, |
|
||||
[ |
|
||||
new RootFieldDto({}, 1, 'string', createProperties('String'), 'invariant'), |
|
||||
]); |
|
||||
|
|
||||
beforeEach(() => { |
|
||||
uiState = Mock.ofType<UIState>(); |
|
||||
}); |
|
||||
|
|
||||
const INVALID_CONFIGS = [ |
|
||||
{ case: 'empty', fields: [] }, |
|
||||
{ case: 'invalid', fields: ['invalid'] }, |
|
||||
]; |
|
||||
|
|
||||
INVALID_CONFIGS.forEach(test => { |
|
||||
it(`should provide default fields if config is ${test.case}`, async () => { |
|
||||
let fields: ReadonlyArray<TableField>; |
|
||||
let fieldNames: ReadonlyArray<string>; |
|
||||
|
|
||||
uiState.setup(x => x.getUser<string[]>('schemas.my-schema.view', [])) |
|
||||
.returns(() => of(test.fields)); |
|
||||
|
|
||||
const tableFields = new TableFields(uiState.object, schema); |
|
||||
|
|
||||
tableFields.listFields.subscribe(result => { |
|
||||
fields = result; |
|
||||
}); |
|
||||
|
|
||||
tableFields.listFieldNames.subscribe(result => { |
|
||||
fieldNames = result; |
|
||||
}); |
|
||||
|
|
||||
expect(fields!).toEqual([ |
|
||||
MetaFields.lastModifiedByAvatar, |
|
||||
schema.fields[0], |
|
||||
MetaFields.statusColor, |
|
||||
MetaFields.lastModified, |
|
||||
]); |
|
||||
|
|
||||
expect(fieldNames!).toEqual([ |
|
||||
MetaFields.lastModifiedByAvatar, |
|
||||
schema.fields[0].name, |
|
||||
MetaFields.statusColor, |
|
||||
MetaFields.lastModified, |
|
||||
]); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
INVALID_CONFIGS.forEach(test => { |
|
||||
it(`should remove ui state if config is ${test.case}`, () => { |
|
||||
uiState.setup(x => x.getUser<string[]>('schemas.my-schema.view', [])) |
|
||||
.returns(() => of([])); |
|
||||
|
|
||||
const tableFields = new TableFields(uiState.object, schema); |
|
||||
|
|
||||
tableFields.updateFields(test.fields, true); |
|
||||
|
|
||||
uiState.verify(x => x.removeUser('schemas.my-schema.view'), Times.once()); |
|
||||
|
|
||||
expect().nothing(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
it('should eliminate invalid fields from the config', () => { |
|
||||
let fields: ReadonlyArray<TableField>; |
|
||||
let fieldNames: ReadonlyArray<string>; |
|
||||
|
|
||||
const config = ['invalid', MetaFields.version]; |
|
||||
|
|
||||
uiState.setup(x => x.getUser<string[]>('schemas.my-schema.view', [])) |
|
||||
.returns(() => of(config)); |
|
||||
|
|
||||
const tableFields = new TableFields(uiState.object, schema); |
|
||||
|
|
||||
tableFields.listFields.subscribe(result => { |
|
||||
fields = result; |
|
||||
}); |
|
||||
|
|
||||
tableFields.listFieldNames.subscribe(result => { |
|
||||
fieldNames = result; |
|
||||
}); |
|
||||
|
|
||||
expect(fields!).toEqual([ |
|
||||
MetaFields.version, |
|
||||
]); |
|
||||
|
|
||||
expect(fieldNames!).toEqual([ |
|
||||
MetaFields.version, |
|
||||
]); |
|
||||
}); |
|
||||
|
|
||||
it('should update config if fields are saved', () => { |
|
||||
uiState.setup(x => x.getUser<string[]>('schemas.my-schema.view', [])) |
|
||||
.returns(() => of([])); |
|
||||
|
|
||||
const tableFields = new TableFields(uiState.object, schema); |
|
||||
|
|
||||
const config = ['invalid', MetaFields.version]; |
|
||||
|
|
||||
tableFields.updateFields(config, true); |
|
||||
|
|
||||
uiState.verify(x => x.set('schemas.my-schema.view', [MetaFields.version], true), Times.once()); |
|
||||
|
|
||||
expect().nothing(); |
|
||||
}); |
|
||||
}); |
|
||||
@ -1,62 +0,0 @@ |
|||||
/* |
|
||||
* Squidex Headless CMS |
|
||||
* |
|
||||
* @license |
|
||||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|
||||
*/ |
|
||||
|
|
||||
import { BehaviorSubject, Observable } from 'rxjs'; |
|
||||
import { take } from 'rxjs/operators'; |
|
||||
import { MetaFields, SchemaDto, TableField } from './../services/schemas.service'; |
|
||||
import { UIState } from './ui.state'; |
|
||||
|
|
||||
const META_FIELD_NAMES = Object.values(MetaFields); |
|
||||
|
|
||||
export class TableFields { |
|
||||
private readonly listField$ = new BehaviorSubject<ReadonlyArray<TableField>>([]); |
|
||||
private readonly listFieldName$ = new BehaviorSubject<ReadonlyArray<string>>([]); |
|
||||
private readonly settingsKey: string; |
|
||||
|
|
||||
public readonly allFields: ReadonlyArray<string>; |
|
||||
|
|
||||
public get listFields(): Observable<ReadonlyArray<TableField>> { |
|
||||
return this.listField$; |
|
||||
} |
|
||||
|
|
||||
public get listFieldNames(): Observable<ReadonlyArray<string>> { |
|
||||
return this.listFieldName$; |
|
||||
} |
|
||||
|
|
||||
constructor( |
|
||||
private readonly uiState: UIState, |
|
||||
private readonly schema: SchemaDto, |
|
||||
) { |
|
||||
this.allFields = [...this.schema.contentFields.map(x => x.name), ...META_FIELD_NAMES].sort(); |
|
||||
|
|
||||
this.settingsKey = `schemas.${this.schema.name}.view`; |
|
||||
|
|
||||
this.uiState.getUser<string[]>(this.settingsKey, []).pipe(take(1)) |
|
||||
.subscribe(fieldNames => { |
|
||||
this.updateFields(fieldNames, false); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
public updateFields(fieldNames: ReadonlyArray<string>, save = true) { |
|
||||
fieldNames = fieldNames.filter(x => this.allFields.indexOf(x) >= 0); |
|
||||
|
|
||||
if (fieldNames.length === 0) { |
|
||||
fieldNames = this.schema.defaultListFields.map(x => x['name'] || x); |
|
||||
|
|
||||
if (save) { |
|
||||
this.uiState.removeUser(this.settingsKey); |
|
||||
} |
|
||||
} else if (save) { |
|
||||
this.uiState.set(this.settingsKey, fieldNames, true); |
|
||||
} |
|
||||
|
|
||||
const fields: ReadonlyArray<TableField> = fieldNames.map(n => this.schema.fields.find(f => f.name === n) || n); |
|
||||
|
|
||||
this.listField$.next(fields); |
|
||||
this.listFieldName$.next(fieldNames); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,329 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { of } from 'rxjs'; |
||||
|
import { IMock, It, Mock, Times } from 'typemoq'; |
||||
|
import { DateTime, Version } from '@app/framework'; |
||||
|
import { createProperties, MetaFields, RootFieldDto, SchemaDto, TableField, TableSettings, FieldSizes, UIState } from '@app/shared/internal'; |
||||
|
import { FieldWrappings } from '..'; |
||||
|
|
||||
|
describe('TableSettings', () => { |
||||
|
let uiState: IMock<UIState>; |
||||
|
|
||||
|
const schema = |
||||
|
new SchemaDto({}, |
||||
|
'1', |
||||
|
DateTime.now(), 'me', |
||||
|
DateTime.now(), 'me', |
||||
|
new Version('1'), |
||||
|
'my-schema', |
||||
|
'my-category', |
||||
|
'Default', |
||||
|
false, |
||||
|
{}, |
||||
|
[ |
||||
|
new RootFieldDto({}, 1, 'string', createProperties('String'), 'invariant'), |
||||
|
]); |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
uiState = Mock.ofType<UIState>(); |
||||
|
}); |
||||
|
|
||||
|
const INVALID_CONFIGS = [ |
||||
|
{ case: 'blank', fields: [] }, |
||||
|
{ case: 'broken', fields: ['invalid'] }, |
||||
|
]; |
||||
|
|
||||
|
const EMPTY = { fields: [], sizes: {}, wrappings: {} }; |
||||
|
|
||||
|
INVALID_CONFIGS.forEach(test => { |
||||
|
it(`should provide default fields if config is ${test.case}`, () => { |
||||
|
let listFields: ReadonlyArray<TableField>; |
||||
|
let listFieldNames: ReadonlyArray<string>; |
||||
|
let fieldSizes: FieldSizes; |
||||
|
let fieldWrappings: FieldWrappings; |
||||
|
|
||||
|
const config = { |
||||
|
fields: test.fields, |
||||
|
sizes: { |
||||
|
field1: 100, |
||||
|
field2: 200, |
||||
|
}, |
||||
|
wrappings: { |
||||
|
field3: true, |
||||
|
field4: false, |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(config)); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.listFields.subscribe(result => { |
||||
|
listFields = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.listFieldNames.subscribe(result => { |
||||
|
listFieldNames = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.fieldSizes.subscribe(result => { |
||||
|
fieldSizes = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.fieldWrappings.subscribe(result => { |
||||
|
fieldWrappings = result; |
||||
|
}); |
||||
|
|
||||
|
expect(listFields!).toEqual([ |
||||
|
MetaFields.lastModifiedByAvatar, |
||||
|
schema.fields[0], |
||||
|
MetaFields.statusColor, |
||||
|
MetaFields.lastModified, |
||||
|
]); |
||||
|
|
||||
|
expect(listFieldNames!).toEqual([ |
||||
|
MetaFields.lastModifiedByAvatar, |
||||
|
schema.fields[0].name, |
||||
|
MetaFields.statusColor, |
||||
|
MetaFields.lastModified, |
||||
|
]); |
||||
|
|
||||
|
expect(fieldSizes!).toEqual({ |
||||
|
field1: 100, |
||||
|
field2: 200, |
||||
|
}); |
||||
|
|
||||
|
expect(fieldWrappings!).toEqual({ |
||||
|
field3: true, |
||||
|
field4: false, |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
INVALID_CONFIGS.forEach(test => { |
||||
|
it(`should remove ui state if config is ${test.case}`, () => { |
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.updateFields(test.fields, true); |
||||
|
|
||||
|
uiState.verify(x => x.removeUser('schemas.my-schema.config'), Times.once()); |
||||
|
|
||||
|
expect().nothing(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('should eliminate invalid fields from the config', () => { |
||||
|
let listFields: ReadonlyArray<TableField>; |
||||
|
let listFieldNames: ReadonlyArray<string>; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({ fields: ['invalid', MetaFields.version] }))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.listFields.subscribe(result => { |
||||
|
listFields = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.listFieldNames.subscribe(result => { |
||||
|
listFieldNames = result; |
||||
|
}); |
||||
|
|
||||
|
expect(listFields!).toEqual([ |
||||
|
MetaFields.version, |
||||
|
]); |
||||
|
|
||||
|
expect(listFieldNames!).toEqual([ |
||||
|
MetaFields.version, |
||||
|
]); |
||||
|
}); |
||||
|
|
||||
|
it('should update config if fields are saved', () => { |
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
const config = ['invalid', MetaFields.version]; |
||||
|
|
||||
|
tableSettings.updateFields(config, true); |
||||
|
|
||||
|
uiState.verify(x => x.set('schemas.my-schema.config', { ...EMPTY, fields: [MetaFields.version] }, true), Times.once()); |
||||
|
|
||||
|
expect().nothing(); |
||||
|
}); |
||||
|
|
||||
|
it('should remove config if fields are saved', () => { |
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.updateFields([], true); |
||||
|
|
||||
|
uiState.verify(x => x.removeUser('schemas.my-schema.config'), Times.once()); |
||||
|
|
||||
|
expect().nothing(); |
||||
|
}); |
||||
|
|
||||
|
it('should update config if fields are only updated', () => { |
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
const config = ['invalid', MetaFields.version]; |
||||
|
|
||||
|
tableSettings.updateFields(config, false); |
||||
|
|
||||
|
uiState.verify(x => x.set('schemas.my-schema.config', It.isAny(), true), Times.never()); |
||||
|
|
||||
|
expect().nothing(); |
||||
|
}); |
||||
|
|
||||
|
it('should update config if sizes are saved', () => { |
||||
|
let fieldSizes: FieldSizes; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.fieldSizes.subscribe(result => { |
||||
|
fieldSizes = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.updateSize(MetaFields.version, 100, true); |
||||
|
|
||||
|
uiState.verify(x => x.set('schemas.my-schema.config', { ...EMPTY, sizes: { [MetaFields.version]: 100 } }, true), Times.once()); |
||||
|
|
||||
|
expect(fieldSizes!).toEqual({ [MetaFields.version]: 100 }); |
||||
|
}); |
||||
|
|
||||
|
it('should update config if sizes are only updated', () => { |
||||
|
let fieldSizes: FieldSizes; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.fieldSizes.subscribe(result => { |
||||
|
fieldSizes = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.updateSize(MetaFields.version, 100, false); |
||||
|
|
||||
|
uiState.verify(x => x.set('schemas.my-schema.config', It.isAny(), true), Times.never()); |
||||
|
|
||||
|
expect(fieldSizes!).toEqual({ [MetaFields.version]: 100 }); |
||||
|
}); |
||||
|
|
||||
|
it('should update config if wrapping is toggled', () => { |
||||
|
let fieldWrappings: FieldWrappings; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.fieldWrappings.subscribe(result => { |
||||
|
fieldWrappings = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.toggleWrapping(MetaFields.version, true); |
||||
|
|
||||
|
uiState.verify(x => x.set('schemas.my-schema.config', { ...EMPTY, wrappings: { [MetaFields.version]: true } }, true), Times.once()); |
||||
|
|
||||
|
expect(fieldWrappings!).toEqual({ [MetaFields.version]: true }); |
||||
|
}); |
||||
|
|
||||
|
it('should update config if wrapping is toggled and only updated', () => { |
||||
|
let fieldWrappings: FieldWrappings; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(({}))); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.fieldWrappings.subscribe(result => { |
||||
|
fieldWrappings = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.toggleWrapping(MetaFields.version, false); |
||||
|
|
||||
|
uiState.verify(x => x.set('schemas.my-schema.config', It.isAny(), true), Times.never()); |
||||
|
|
||||
|
expect(fieldWrappings!).toEqual({ [MetaFields.version]: true }); |
||||
|
}); |
||||
|
|
||||
|
it('should provide default fields if reset', () => { |
||||
|
let listFields: ReadonlyArray<TableField>; |
||||
|
let listFieldNames: ReadonlyArray<string>; |
||||
|
let fieldSizes: FieldSizes; |
||||
|
let fieldWrappings: FieldWrappings; |
||||
|
|
||||
|
const config = { |
||||
|
fields: [ |
||||
|
MetaFields.version, |
||||
|
], |
||||
|
sizes: { |
||||
|
field1: 100, |
||||
|
field2: 200, |
||||
|
}, |
||||
|
wrappings: { |
||||
|
field3: true, |
||||
|
field4: false, |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
uiState.setup(x => x.getUser<any>('schemas.my-schema.config', {})) |
||||
|
.returns(() => of(config)); |
||||
|
|
||||
|
const tableSettings = new TableSettings(uiState.object, schema); |
||||
|
|
||||
|
tableSettings.listFields.subscribe(result => { |
||||
|
listFields = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.listFieldNames.subscribe(result => { |
||||
|
listFieldNames = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.fieldSizes.subscribe(result => { |
||||
|
fieldSizes = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.fieldWrappings.subscribe(result => { |
||||
|
fieldWrappings = result; |
||||
|
}); |
||||
|
|
||||
|
tableSettings.reset(); |
||||
|
|
||||
|
expect(listFields!).toEqual([ |
||||
|
MetaFields.lastModifiedByAvatar, |
||||
|
schema.fields[0], |
||||
|
MetaFields.statusColor, |
||||
|
MetaFields.lastModified, |
||||
|
]); |
||||
|
|
||||
|
expect(listFieldNames!).toEqual([ |
||||
|
MetaFields.lastModifiedByAvatar, |
||||
|
schema.fields[0].name, |
||||
|
MetaFields.statusColor, |
||||
|
MetaFields.lastModified, |
||||
|
]); |
||||
|
|
||||
|
expect(fieldSizes!).toEqual({}); |
||||
|
expect(fieldWrappings!).toEqual({}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,152 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { take } from 'rxjs/operators'; |
||||
|
import { State, Types } from '@app/framework'; |
||||
|
import { MetaFields, SchemaDto, TableField } from './../services/schemas.service'; |
||||
|
import { UIState } from './ui.state'; |
||||
|
|
||||
|
const META_FIELD_NAMES = Object.values(MetaFields); |
||||
|
|
||||
|
export type FieldSizes = { [name: string]: number }; |
||||
|
export type FieldWrappings = { [name: string]: boolean }; |
||||
|
|
||||
|
interface Snapshot { |
||||
|
// The table fields in the right order.
|
||||
|
fields: ReadonlyArray<string>; |
||||
|
|
||||
|
// The sizes of the columns if overriden.
|
||||
|
sizes: FieldSizes; |
||||
|
|
||||
|
// True to enable wrapping.
|
||||
|
wrappings: FieldWrappings; |
||||
|
} |
||||
|
|
||||
|
export class TableSettings extends State<Snapshot> { |
||||
|
private readonly settingsKey: string; |
||||
|
|
||||
|
public readonly schemaFields: ReadonlyArray<string>; |
||||
|
public readonly schemaDefaults: ReadonlyArray<string>; |
||||
|
|
||||
|
public fieldSizes = |
||||
|
this.project(x => x.sizes); |
||||
|
|
||||
|
public fieldWrappings = |
||||
|
this.project(x => x.wrappings); |
||||
|
|
||||
|
public fields = |
||||
|
this.project(x => x.fields); |
||||
|
|
||||
|
public listFieldNames = |
||||
|
this.projectFrom(this.fields, x => this.getListFieldNames(x)); |
||||
|
|
||||
|
public listFields = |
||||
|
this.projectFrom(this.listFieldNames, x => this.getListFields(x)); |
||||
|
|
||||
|
constructor( |
||||
|
private readonly uiState: UIState, |
||||
|
private readonly schema: SchemaDto, |
||||
|
) { |
||||
|
super({ fields: [], sizes: {}, wrappings: {} }); |
||||
|
|
||||
|
this.schemaFields = [...schema.contentFields.map(x => x.name), ...META_FIELD_NAMES].sort(); |
||||
|
this.schemaDefaults = schema.defaultListFields.map(x => x['name'] || x); |
||||
|
|
||||
|
this.settingsKey = `schemas.${this.schema.name}.config`; |
||||
|
|
||||
|
this.uiState.getUser<any>(this.settingsKey, {}).pipe(take(1)) |
||||
|
.subscribe(settings => { |
||||
|
if (!Types.isArrayOfString(settings.fields)) { |
||||
|
settings.fields = []; |
||||
|
} |
||||
|
|
||||
|
if (!Types.isObject(settings.sizes)) { |
||||
|
settings.sizes = {}; |
||||
|
} |
||||
|
|
||||
|
if (!Types.isObject(settings.wrappings)) { |
||||
|
settings.wrappings = {}; |
||||
|
} |
||||
|
|
||||
|
this.publishSizes(settings.sizes); |
||||
|
this.publishFields(settings.fields); |
||||
|
this.publishWrappings(settings.wrappings); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public reset() { |
||||
|
super.resetState(); |
||||
|
|
||||
|
this.saveConfig(); |
||||
|
} |
||||
|
|
||||
|
public updateSize(field: string, size: number, save = true) { |
||||
|
this.next(s => ({ |
||||
|
...s, |
||||
|
sizes: { |
||||
|
...s.sizes, |
||||
|
[field]: size, |
||||
|
}, |
||||
|
})); |
||||
|
|
||||
|
if (save) { |
||||
|
this.saveConfig(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public toggleWrapping(field: string, save = true) { |
||||
|
this.next(s => ({ |
||||
|
...s, |
||||
|
wrappings: { |
||||
|
...s.wrappings, |
||||
|
[field]: !s.wrappings[field], |
||||
|
}, |
||||
|
})); |
||||
|
|
||||
|
if (save) { |
||||
|
this.saveConfig(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public updateFields(fields: ReadonlyArray<string>, save = true) { |
||||
|
this.publishFields(fields); |
||||
|
|
||||
|
if (save) { |
||||
|
this.saveConfig(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private publishSizes(sizes: FieldSizes) { |
||||
|
this.next({ sizes }); |
||||
|
} |
||||
|
|
||||
|
private publishWrappings(wrappings: FieldWrappings) { |
||||
|
this.next({ wrappings }); |
||||
|
} |
||||
|
|
||||
|
private publishFields(fields: ReadonlyArray<string>) { |
||||
|
this.next({ fields: fields.filter(x => this.schemaFields.includes(x)) }); |
||||
|
} |
||||
|
|
||||
|
private saveConfig() { |
||||
|
const { sizes, fields, wrappings } = this.snapshot; |
||||
|
|
||||
|
if (Object.keys(sizes).length === 0 && Object.keys(wrappings).length === 0 && fields.length === 0) { |
||||
|
this.uiState.removeUser(this.settingsKey); |
||||
|
} else { |
||||
|
this.uiState.set(this.settingsKey, this.snapshot, true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private getListFields(names: ReadonlyArray<string>): ReadonlyArray<TableField> { |
||||
|
return names.map(n => this.schema.fields.find(f => f.name === n) || n); |
||||
|
} |
||||
|
|
||||
|
private getListFieldNames(names: ReadonlyArray<string>): ReadonlyArray<string> { |
||||
|
return names.length === 0 ? this.schemaDefaults : names; |
||||
|
} |
||||
|
} |
||||
Binary file not shown.
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue