@journeyapps-labs/reactor-mod-data-browser 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/dist/@types/actions/connections/SetConnectionColorAction.d.ts +11 -0
- package/dist/@types/actions/saved-queries/OpenSavedQueryAction.d.ts +10 -0
- package/dist/@types/actions/saved-queries/RemoveSavedQueryAction.d.ts +9 -0
- package/dist/@types/core/AbstractConnection.d.ts +2 -0
- package/dist/@types/core/SchemaModelDefinition.d.ts +5 -0
- package/dist/@types/core/connection-colors.d.ts +10 -0
- package/dist/@types/core/query/StandardModelFields.d.ts +5 -0
- package/dist/@types/core/query/filters.d.ts +46 -5
- package/dist/@types/core/query/query-simple/SimplePage.d.ts +2 -0
- package/dist/@types/core/query/query-simple/SimpleQuery.d.ts +12 -3
- package/dist/@types/core/query/query-simple/SimpleQueryColumns.d.ts +12 -0
- package/dist/@types/core/query/query-simple/SimpleQueryFilterState.d.ts +37 -0
- package/dist/@types/core/query/query-simple/SimpleQueryPlanner.d.ts +4 -0
- package/dist/@types/core/query/query-simple/SimpleQuerySortState.d.ts +23 -0
- package/dist/@types/core/query/query-simple/SimpleQueryTypes.d.ts +24 -0
- package/dist/@types/core/query/widgets/ColumnDisplayWidget.d.ts +1 -0
- package/dist/@types/core/query/widgets/PeekRelationshipButton.d.ts +7 -0
- package/dist/@types/core/query/widgets/SmartColumnWidget.d.ts +3 -0
- package/dist/@types/core/query/widgets/SmartFilterWidget.d.ts +6 -0
- package/dist/@types/entities/ConnectionEntityDefinition.d.ts +2 -0
- package/dist/@types/entities/SavedQueryEntityDefinition.d.ts +8 -0
- package/dist/@types/entities.d.ts +2 -1
- package/dist/@types/forms/APIConnectionForm.d.ts +1 -0
- package/dist/@types/forms/TypeEngine.d.ts +3 -21
- package/dist/@types/forms/types/attachment-handler.d.ts +2 -0
- package/dist/@types/forms/types/boolean-handler.d.ts +2 -0
- package/dist/@types/forms/types/date-handler.d.ts +2 -0
- package/dist/@types/forms/types/filters/ClearableFilterFormDialogDirective.d.ts +10 -0
- package/dist/@types/forms/types/filters/ConditionalFilterForm.d.ts +23 -0
- package/dist/@types/forms/types/image-handler.d.ts +2 -0
- package/dist/@types/forms/types/location-handler.d.ts +2 -0
- package/dist/@types/forms/types/multiple-choice-handler.d.ts +2 -0
- package/dist/@types/forms/types/multiple-choice-integer-handler.d.ts +2 -0
- package/dist/@types/forms/types/number-handler.d.ts +2 -0
- package/dist/@types/forms/types/shared/type-handler.d.ts +37 -0
- package/dist/@types/forms/types/shared/ui.d.ts +768 -0
- package/dist/@types/forms/types/single-choice-handler.d.ts +2 -0
- package/dist/@types/forms/types/single-choice-integer-handler.d.ts +2 -0
- package/dist/@types/forms/types/text-handler.d.ts +3 -0
- package/dist/@types/index.d.ts +1 -0
- package/dist/@types/panels/_shared/SharedConnectionPanelFactory.d.ts +19 -0
- package/dist/@types/panels/_shared/SharedModelPanelFactory.d.ts +5 -2
- package/dist/@types/panels/query/QueryPanelFactory.d.ts +6 -2
- package/dist/@types/panels/query/TableControlsWidget.d.ts +2 -0
- package/dist/@types/panels/query/table-controls/ChangesControlsWidget.d.ts +8 -0
- package/dist/@types/panels/query/table-controls/FilterControlsWidget.d.ts +7 -0
- package/dist/@types/panels/query/table-controls/PageControlsWidget.d.ts +9 -0
- package/dist/@types/panels/query/table-controls/QueryControlsWidget.d.ts +11 -0
- package/dist/@types/panels/query/table-controls/SortChipWidget.d.ts +10 -0
- package/dist/@types/panels/query/table-controls/SortControlsWidget.d.ts +7 -0
- package/dist/@types/preferences/QueryControlPreferences.d.ts +7 -0
- package/dist/@types/stores/SavedQueryStore.d.ts +34 -0
- package/dist/@types/widgets/EmptyValueWidget.d.ts +7 -0
- package/dist/DataBrowserModule.js +21 -7
- package/dist/DataBrowserModule.js.map +1 -1
- package/dist/actions/connections/AddConnectionAction.js +2 -2
- package/dist/actions/connections/AddConnectionAction.js.map +1 -1
- package/dist/actions/connections/RemoveConnectionAction.js +2 -2
- package/dist/actions/connections/RemoveConnectionAction.js.map +1 -1
- package/dist/actions/connections/SetConnectionColorAction.js +63 -0
- package/dist/actions/connections/SetConnectionColorAction.js.map +1 -0
- package/dist/actions/saved-queries/OpenSavedQueryAction.js +58 -0
- package/dist/actions/saved-queries/OpenSavedQueryAction.js.map +1 -0
- package/dist/actions/saved-queries/RemoveSavedQueryAction.js +43 -0
- package/dist/actions/saved-queries/RemoveSavedQueryAction.js.map +1 -0
- package/dist/actions/schema-definitions/CreateModelAction.js +2 -2
- package/dist/actions/schema-definitions/CreateModelAction.js.map +1 -1
- package/dist/actions/schema-definitions/QuerySchemaModelAction.js +2 -2
- package/dist/actions/schema-definitions/QuerySchemaModelAction.js.map +1 -1
- package/dist/actions/schema-model/EditSchemaModelAction.js +2 -2
- package/dist/actions/schema-model/EditSchemaModelAction.js.map +1 -1
- package/dist/actions/schema-model/ViewSchemaModelAsJsonAction.js +2 -2
- package/dist/actions/schema-model/ViewSchemaModelAsJsonAction.js.map +1 -1
- package/dist/core/AbstractConnection.js +116 -90
- package/dist/core/AbstractConnection.js.map +1 -1
- package/dist/core/SchemaModelDefinition.js +14 -0
- package/dist/core/SchemaModelDefinition.js.map +1 -1
- package/dist/core/connection-colors.js +36 -0
- package/dist/core/connection-colors.js.map +1 -0
- package/dist/core/query/StandardModelFields.js +10 -0
- package/dist/core/query/StandardModelFields.js.map +1 -0
- package/dist/core/query/filters.js +86 -4
- package/dist/core/query/filters.js.map +1 -1
- package/dist/core/query/query-simple/SimplePage.js +2 -4
- package/dist/core/query/query-simple/SimplePage.js.map +1 -1
- package/dist/core/query/query-simple/SimpleQuery.js +64 -68
- package/dist/core/query/query-simple/SimpleQuery.js.map +1 -1
- package/dist/core/query/query-simple/SimpleQueryColumns.js +88 -0
- package/dist/core/query/query-simple/SimpleQueryColumns.js.map +1 -0
- package/dist/core/query/query-simple/SimpleQueryFilterState.js +136 -0
- package/dist/core/query/query-simple/SimpleQueryFilterState.js.map +1 -0
- package/dist/core/query/query-simple/SimpleQueryPlanner.js +14 -0
- package/dist/core/query/query-simple/SimpleQueryPlanner.js.map +1 -0
- package/dist/core/query/query-simple/SimpleQuerySortState.js +140 -0
- package/dist/core/query/query-simple/SimpleQuerySortState.js.map +1 -0
- package/dist/core/query/query-simple/SimpleQueryTypes.js +44 -0
- package/dist/core/query/query-simple/SimpleQueryTypes.js.map +1 -0
- package/dist/core/query/widgets/BelongsToDisplayWidget.js +14 -7
- package/dist/core/query/widgets/BelongsToDisplayWidget.js.map +1 -1
- package/dist/core/query/widgets/CellDisplayWidget.js +5 -9
- package/dist/core/query/widgets/CellDisplayWidget.js.map +1 -1
- package/dist/core/query/widgets/ColumnDisplayWidget.js +13 -12
- package/dist/core/query/widgets/ColumnDisplayWidget.js.map +1 -1
- package/dist/core/query/widgets/PeekRelationshipButton.js +128 -0
- package/dist/core/query/widgets/PeekRelationshipButton.js.map +1 -0
- package/dist/core/query/widgets/SmartColumnWidget.js +18 -3
- package/dist/core/query/widgets/SmartColumnWidget.js.map +1 -1
- package/dist/core/query/widgets/SmartFilterWidget.js +88 -51
- package/dist/core/query/widgets/SmartFilterWidget.js.map +1 -1
- package/dist/entities/ConnectionEntityDefinition.js +32 -7
- package/dist/entities/ConnectionEntityDefinition.js.map +1 -1
- package/dist/entities/SavedQueryEntityDefinition.js +68 -0
- package/dist/entities/SavedQueryEntityDefinition.js.map +1 -0
- package/dist/entities/SchemaModelDefinitionEntityDefinition.js +3 -1
- package/dist/entities/SchemaModelDefinitionEntityDefinition.js.map +1 -1
- package/dist/entities.js +1 -0
- package/dist/entities.js.map +1 -1
- package/dist/forms/APIConnectionForm.js +11 -2
- package/dist/forms/APIConnectionForm.js.map +1 -1
- package/dist/forms/TypeEngine.js +30 -306
- package/dist/forms/TypeEngine.js.map +1 -1
- package/dist/forms/types/attachment-handler.js +29 -0
- package/dist/forms/types/attachment-handler.js.map +1 -0
- package/dist/forms/types/boolean-handler.js +22 -0
- package/dist/forms/types/boolean-handler.js.map +1 -0
- package/dist/forms/types/date-handler.js +97 -0
- package/dist/forms/types/date-handler.js.map +1 -0
- package/dist/forms/types/filters/ClearableFilterFormDialogDirective.js +25 -0
- package/dist/forms/types/filters/ClearableFilterFormDialogDirective.js.map +1 -0
- package/dist/forms/types/filters/ConditionalFilterForm.js +87 -0
- package/dist/forms/types/filters/ConditionalFilterForm.js.map +1 -0
- package/dist/forms/types/image-handler.js +82 -0
- package/dist/forms/types/image-handler.js.map +1 -0
- package/dist/forms/types/location-handler.js +49 -0
- package/dist/forms/types/location-handler.js.map +1 -0
- package/dist/forms/types/multiple-choice-handler.js +37 -0
- package/dist/forms/types/multiple-choice-handler.js.map +1 -0
- package/dist/forms/types/multiple-choice-integer-handler.js +37 -0
- package/dist/forms/types/multiple-choice-integer-handler.js.map +1 -0
- package/dist/forms/types/number-handler.js +79 -0
- package/dist/forms/types/number-handler.js.map +1 -0
- package/dist/forms/types/shared/type-handler.js +2 -0
- package/dist/forms/types/shared/type-handler.js.map +1 -0
- package/dist/forms/types/shared/ui.js +33 -0
- package/dist/forms/types/shared/ui.js.map +1 -0
- package/dist/forms/types/single-choice-handler.js +41 -0
- package/dist/forms/types/single-choice-handler.js.map +1 -0
- package/dist/forms/types/single-choice-integer-handler.js +41 -0
- package/dist/forms/types/single-choice-integer-handler.js.map +1 -0
- package/dist/forms/types/text-handler.js +170 -0
- package/dist/forms/types/text-handler.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/panels/_shared/SharedConnectionPanelFactory.js +48 -0
- package/dist/panels/_shared/SharedConnectionPanelFactory.js.map +1 -0
- package/dist/panels/_shared/SharedModelPanelFactory.js +7 -2
- package/dist/panels/_shared/SharedModelPanelFactory.js.map +1 -1
- package/dist/panels/query/PageResultsWidget.js +28 -11
- package/dist/panels/query/PageResultsWidget.js.map +1 -1
- package/dist/panels/query/QueryPanelFactory.js +17 -2
- package/dist/panels/query/QueryPanelFactory.js.map +1 -1
- package/dist/panels/query/QueryPanelWidget.js +55 -9
- package/dist/panels/query/QueryPanelWidget.js.map +1 -1
- package/dist/panels/query/TableControlsWidget.js +29 -67
- package/dist/panels/query/TableControlsWidget.js.map +1 -1
- package/dist/panels/query/table-controls/ChangesControlsWidget.js +36 -0
- package/dist/panels/query/table-controls/ChangesControlsWidget.js.map +1 -0
- package/dist/panels/query/table-controls/FilterControlsWidget.js +106 -0
- package/dist/panels/query/table-controls/FilterControlsWidget.js.map +1 -0
- package/dist/panels/query/table-controls/PageControlsWidget.js +65 -0
- package/dist/panels/query/table-controls/PageControlsWidget.js.map +1 -0
- package/dist/panels/query/table-controls/QueryControlsWidget.js +85 -0
- package/dist/panels/query/table-controls/QueryControlsWidget.js.map +1 -0
- package/dist/panels/query/table-controls/SortChipWidget.js +75 -0
- package/dist/panels/query/table-controls/SortChipWidget.js.map +1 -0
- package/dist/panels/query/table-controls/SortControlsWidget.js +65 -0
- package/dist/panels/query/table-controls/SortControlsWidget.js.map +1 -0
- package/dist/preferences/QueryControlPreferences.js +28 -0
- package/dist/preferences/QueryControlPreferences.js.map +1 -0
- package/dist/stores/ConnectionStore.js +2 -0
- package/dist/stores/ConnectionStore.js.map +1 -1
- package/dist/stores/SavedQueryStore.js +131 -0
- package/dist/stores/SavedQueryStore.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/widgets/EmptyValueWidget.js +15 -0
- package/dist/widgets/EmptyValueWidget.js.map +1 -0
- package/dist-module/bundle.js +181 -51
- package/dist-module/bundle.js.map +1 -1
- package/package.json +13 -13
- package/src/DataBrowserModule.ts +21 -7
- package/src/actions/connections/AddConnectionAction.tsx +2 -2
- package/src/actions/connections/RemoveConnectionAction.tsx +2 -2
- package/src/actions/connections/SetConnectionColorAction.ts +52 -0
- package/src/actions/saved-queries/OpenSavedQueryAction.ts +43 -0
- package/src/actions/saved-queries/RemoveSavedQueryAction.ts +27 -0
- package/src/actions/schema-definitions/CreateModelAction.ts +9 -2
- package/src/actions/schema-definitions/QuerySchemaModelAction.ts +9 -2
- package/src/actions/schema-model/EditSchemaModelAction.ts +9 -2
- package/src/actions/schema-model/ViewSchemaModelAsJsonAction.ts +9 -2
- package/src/core/AbstractConnection.ts +7 -1
- package/src/core/SchemaModelDefinition.ts +16 -0
- package/src/core/connection-colors.ts +49 -0
- package/src/core/query/StandardModelFields.ts +9 -0
- package/src/core/query/filters.ts +121 -6
- package/src/core/query/query-simple/SimplePage.ts +4 -5
- package/src/core/query/query-simple/SimpleQuery.tsx +83 -86
- package/src/core/query/query-simple/SimpleQueryColumns.tsx +126 -0
- package/src/core/query/query-simple/SimpleQueryFilterState.ts +160 -0
- package/src/core/query/query-simple/SimpleQueryPlanner.ts +18 -0
- package/src/core/query/query-simple/SimpleQuerySortState.ts +133 -0
- package/src/core/query/query-simple/SimpleQueryTypes.ts +61 -0
- package/src/core/query/widgets/BelongsToDisplayWidget.tsx +19 -11
- package/src/core/query/widgets/CellDisplayWidget.tsx +5 -10
- package/src/core/query/widgets/ColumnDisplayWidget.tsx +24 -20
- package/src/core/query/widgets/PeekRelationshipButton.tsx +161 -0
- package/src/core/query/widgets/SmartColumnWidget.tsx +26 -4
- package/src/core/query/widgets/SmartFilterWidget.tsx +119 -69
- package/src/entities/ConnectionEntityDefinition.tsx +33 -4
- package/src/entities/SavedQueryEntityDefinition.ts +72 -0
- package/src/entities/SchemaModelDefinitionEntityDefinition.ts +5 -2
- package/src/entities.ts +2 -1
- package/src/forms/APIConnectionForm.tsx +15 -2
- package/src/forms/TypeEngine.tsx +35 -421
- package/src/forms/types/attachment-handler.tsx +35 -0
- package/src/forms/types/boolean-handler.tsx +28 -0
- package/src/forms/types/date-handler.tsx +125 -0
- package/src/forms/types/filters/ClearableFilterFormDialogDirective.ts +32 -0
- package/src/forms/types/filters/ConditionalFilterForm.tsx +109 -0
- package/src/forms/types/image-handler.tsx +90 -0
- package/src/forms/types/location-handler.tsx +53 -0
- package/src/forms/types/multiple-choice-handler.tsx +37 -0
- package/src/forms/types/multiple-choice-integer-handler.tsx +37 -0
- package/src/forms/types/number-handler.tsx +100 -0
- package/src/forms/types/shared/type-handler.ts +36 -0
- package/src/forms/types/shared/ui.tsx +40 -0
- package/src/forms/types/single-choice-handler.tsx +47 -0
- package/src/forms/types/single-choice-integer-handler.tsx +47 -0
- package/src/forms/types/text-handler.tsx +247 -0
- package/src/index.ts +1 -0
- package/src/panels/_shared/SharedConnectionPanelFactory.tsx +55 -0
- package/src/panels/_shared/SharedModelPanelFactory.tsx +8 -2
- package/src/panels/query/PageResultsWidget.tsx +40 -28
- package/src/panels/query/QueryPanelFactory.tsx +19 -2
- package/src/panels/query/QueryPanelWidget.tsx +64 -9
- package/src/panels/query/TableControlsWidget.tsx +42 -120
- package/src/panels/query/table-controls/ChangesControlsWidget.tsx +72 -0
- package/src/panels/query/table-controls/FilterControlsWidget.tsx +145 -0
- package/src/panels/query/table-controls/PageControlsWidget.tsx +97 -0
- package/src/panels/query/table-controls/QueryControlsWidget.tsx +127 -0
- package/src/panels/query/table-controls/SortChipWidget.tsx +119 -0
- package/src/panels/query/table-controls/SortControlsWidget.tsx +95 -0
- package/src/preferences/QueryControlPreferences.ts +34 -0
- package/src/stores/ConnectionStore.ts +2 -0
- package/src/stores/SavedQueryStore.ts +121 -0
- package/src/widgets/EmptyValueWidget.tsx +20 -0
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { inject, TableColumn } from '@journeyapps-labs/reactor-mod';
|
|
1
|
+
import { inject, ioc, TableColumn } from '@journeyapps-labs/reactor-mod';
|
|
2
2
|
import { ConnectionStore } from '../../../stores/ConnectionStore';
|
|
3
|
-
import { Promise
|
|
4
|
-
import { Page, PageRow } from '../Page';
|
|
5
|
-
import { SchemaModelDefinition } from '../../SchemaModelDefinition';
|
|
3
|
+
import { Promise } from '@journeyapps/db';
|
|
6
4
|
import * as _ from 'lodash';
|
|
7
|
-
import
|
|
5
|
+
import { Page } from '../Page';
|
|
6
|
+
import { SchemaModelDefinition } from '../../SchemaModelDefinition';
|
|
8
7
|
import { action, observable } from 'mobx';
|
|
9
|
-
import { CellDisplayWidget } from '../widgets/CellDisplayWidget';
|
|
10
|
-
import { SmartColumnWidget } from '../widgets/SmartColumnWidget';
|
|
11
|
-
import { SimpleFilter } from '../filters';
|
|
12
|
-
import { SmartCellDisplayWidget } from '../widgets/SmartCellDisplayWidget';
|
|
13
8
|
import { SchemaModelObject } from '../../SchemaModelObject';
|
|
14
9
|
import { SimplePage } from './SimplePage';
|
|
15
10
|
import { AbstractQueryEncoded, AbstractSerializableQuery } from '../AbstractSerializableQuery';
|
|
16
|
-
import {
|
|
11
|
+
import { SerializedSimpleFilter } from '../filters';
|
|
12
|
+
import { TypeEngine } from '../../../forms/TypeEngine';
|
|
13
|
+
import { SerializedSimpleQuerySort, SimpleQuerySort, SortDirection } from './SimpleQueryTypes';
|
|
14
|
+
import { applyFiltersAndSorts } from './SimpleQueryPlanner';
|
|
15
|
+
import { buildSimpleQueryColumns } from './SimpleQueryColumns';
|
|
16
|
+
import { SimpleQuerySortState } from './SimpleQuerySortState';
|
|
17
|
+
import { SimpleQueryFilterState } from './SimpleQueryFilterState';
|
|
17
18
|
|
|
18
19
|
export interface SimpleQueryOptions {
|
|
19
20
|
definition?: SchemaModelDefinition;
|
|
@@ -23,8 +24,12 @@ export interface SimpleQueryOptions {
|
|
|
23
24
|
export interface SimpleQueryEncoded extends AbstractQueryEncoded {
|
|
24
25
|
limit: number;
|
|
25
26
|
definition: string;
|
|
27
|
+
filters?: SerializedSimpleFilter[];
|
|
28
|
+
sorts?: SerializedSimpleQuerySort[];
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
export { SortDirection, SimpleQuerySort, type SerializedSimpleQuerySort };
|
|
32
|
+
|
|
28
33
|
export class SimpleQuery extends AbstractSerializableQuery<SimpleQueryEncoded> {
|
|
29
34
|
@inject(ConnectionStore)
|
|
30
35
|
accessor connStore: ConnectionStore;
|
|
@@ -35,34 +40,70 @@ export class SimpleQuery extends AbstractSerializableQuery<SimpleQueryEncoded> {
|
|
|
35
40
|
@observable
|
|
36
41
|
accessor _pages: Page[];
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
readonly sortState: SimpleQuerySortState;
|
|
44
|
+
readonly filterState: SimpleQueryFilterState;
|
|
45
|
+
private suspendStateLoad: boolean;
|
|
46
|
+
private readonly scheduleLoad: () => void;
|
|
39
47
|
|
|
40
48
|
constructor(public options: SimpleQueryOptions = {}) {
|
|
41
49
|
super('simple', options.definition?.connection);
|
|
42
50
|
this._totalPages = 0;
|
|
43
51
|
this._pages = [];
|
|
44
|
-
this.
|
|
52
|
+
this.sortState = new SimpleQuerySortState(options.definition);
|
|
53
|
+
this.filterState = new SimpleQueryFilterState({
|
|
54
|
+
definition: options.definition,
|
|
55
|
+
typeEngine: ioc.get(TypeEngine)
|
|
56
|
+
});
|
|
57
|
+
this.suspendStateLoad = false;
|
|
58
|
+
this.scheduleLoad = _.debounce(
|
|
59
|
+
() => {
|
|
60
|
+
if (this.suspendStateLoad) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.load();
|
|
64
|
+
},
|
|
65
|
+
10,
|
|
66
|
+
{ trailing: true, leading: false }
|
|
67
|
+
);
|
|
68
|
+
const onStateChange = () => {
|
|
69
|
+
if (this.suspendStateLoad) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.scheduleLoad();
|
|
73
|
+
};
|
|
74
|
+
this.sortState.registerListener({
|
|
75
|
+
changed: () => {
|
|
76
|
+
onStateChange();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
this.filterState.registerListener({
|
|
80
|
+
changed: () => {
|
|
81
|
+
onStateChange();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
45
84
|
}
|
|
46
85
|
|
|
47
86
|
@action async load() {
|
|
48
87
|
this._pages = [];
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
88
|
+
const collection = await this.options.definition.getCollection();
|
|
89
|
+
const query = applyFiltersAndSorts(
|
|
90
|
+
collection.all(),
|
|
91
|
+
Array.from(this.filterState.simpleFilters.values()),
|
|
92
|
+
this.sortState.sorts
|
|
93
|
+
);
|
|
94
|
+
const results = await (collection.adapter as any).doApiQuery(query);
|
|
55
95
|
this._totalPages = Math.ceil(results.total / this.options.limit);
|
|
56
96
|
}
|
|
57
97
|
|
|
58
98
|
getPage(number: number): Page {
|
|
59
99
|
if (!this._pages[number]) {
|
|
60
|
-
|
|
100
|
+
const page = new SimplePage({
|
|
61
101
|
offset: number * this.options.limit,
|
|
62
102
|
limit: this.options.limit,
|
|
63
103
|
definition: this.options.definition,
|
|
64
104
|
index: number,
|
|
65
|
-
filters: Array.from(this.
|
|
105
|
+
filters: Array.from(this.filterState.simpleFilters.values()),
|
|
106
|
+
sorts: this.sortState.sorts
|
|
66
107
|
});
|
|
67
108
|
page.load();
|
|
68
109
|
this._pages[number] = page;
|
|
@@ -78,76 +119,35 @@ export class SimpleQuery extends AbstractSerializableQuery<SimpleQueryEncoded> {
|
|
|
78
119
|
return {
|
|
79
120
|
...super.serialize(),
|
|
80
121
|
definition: this.options.definition.definition.name,
|
|
81
|
-
limit: this.options.limit
|
|
122
|
+
limit: this.options.limit,
|
|
123
|
+
filters: this.filterState.getSerializedFilters(),
|
|
124
|
+
sorts: this.sortState.getSerializedSorts()
|
|
82
125
|
};
|
|
83
126
|
}
|
|
84
127
|
|
|
85
128
|
async deserialize(connectionStore: ConnectionStore, data: SimpleQueryEncoded): Promise<void> {
|
|
86
129
|
await super.deserialize(connectionStore, data);
|
|
87
|
-
this.
|
|
88
|
-
|
|
130
|
+
this.suspendStateLoad = true;
|
|
131
|
+
try {
|
|
132
|
+
this.options.limit = data.limit;
|
|
133
|
+
const definition = await this.connection.waitForSchemaModelDefinitionByName(data.definition);
|
|
134
|
+
this.options.definition = definition;
|
|
135
|
+
this.sortState.setDefinition(definition);
|
|
136
|
+
this.filterState.setDefinition(definition);
|
|
137
|
+
this.filterState.hydrateFilters(data.filters || []);
|
|
138
|
+
this.sortState.hydrateSorts(data.sorts || []);
|
|
139
|
+
} finally {
|
|
140
|
+
this.suspendStateLoad = false;
|
|
141
|
+
}
|
|
89
142
|
}
|
|
90
143
|
|
|
91
144
|
getColumns(): TableColumn[] {
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
key: 'updated_at',
|
|
101
|
-
display: 'Updated at',
|
|
102
|
-
noWrap: true,
|
|
103
|
-
shrink: true,
|
|
104
|
-
accessor: (cell, row: PageRow) => {
|
|
105
|
-
return <CellDisplayWidget name="updated_at" cell={row.model.updated_at} row={row} />;
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
..._.map(this.options.definition.definition.belongsToIdVars, (a) => {
|
|
109
|
-
return {
|
|
110
|
-
key: a.name,
|
|
111
|
-
display: (
|
|
112
|
-
<SmartColumnWidget
|
|
113
|
-
variable={this.options.definition.definition.belongsToVars[a.relationship]}
|
|
114
|
-
type={this.options.definition.definition.belongsTo[a.relationship].foreignType}
|
|
115
|
-
filterChanged={(filter) => {}}
|
|
116
|
-
/>
|
|
117
|
-
),
|
|
118
|
-
noWrap: true,
|
|
119
|
-
shrink: true,
|
|
120
|
-
accessor: (cell, row: PageRow) => {
|
|
121
|
-
return <SmartBelongsToDisplayWidget variable_id={a} row={row} connection={this.connection} />;
|
|
122
|
-
}
|
|
123
|
-
} as TableColumn;
|
|
124
|
-
}),
|
|
125
|
-
..._.map(this.options.definition.definition.attributes, (a) => {
|
|
126
|
-
return {
|
|
127
|
-
key: a.name,
|
|
128
|
-
display: (
|
|
129
|
-
<SmartColumnWidget
|
|
130
|
-
variable={a}
|
|
131
|
-
filter={this.simple_filters.get(a)}
|
|
132
|
-
filterChanged={(filter) => {
|
|
133
|
-
if (!filter) {
|
|
134
|
-
this.simple_filters.delete(a);
|
|
135
|
-
this.load();
|
|
136
|
-
} else {
|
|
137
|
-
this.simple_filters.set(a, filter);
|
|
138
|
-
this.load();
|
|
139
|
-
}
|
|
140
|
-
}}
|
|
141
|
-
/>
|
|
142
|
-
),
|
|
143
|
-
noWrap: true,
|
|
144
|
-
shrink: true,
|
|
145
|
-
accessor: (cell, row: PageRow) => {
|
|
146
|
-
return <SmartCellDisplayWidget name={a.name} row={row} />;
|
|
147
|
-
}
|
|
148
|
-
} as TableColumn;
|
|
149
|
-
})
|
|
150
|
-
];
|
|
145
|
+
return buildSimpleQueryColumns({
|
|
146
|
+
definition: this.options.definition,
|
|
147
|
+
connection: this.connection,
|
|
148
|
+
sortState: this.sortState,
|
|
149
|
+
filterState: this.filterState
|
|
150
|
+
});
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
getSimpleName(): string {
|
|
@@ -155,9 +155,6 @@ export class SimpleQuery extends AbstractSerializableQuery<SimpleQueryEncoded> {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
getDirtyObjects(): SchemaModelObject[] {
|
|
158
|
-
return
|
|
159
|
-
this._pages.filter((p) => !!p),
|
|
160
|
-
(page) => page.getDirtyObjects()
|
|
161
|
-
);
|
|
158
|
+
return this._pages.flatMap((page) => page?.getDirtyObjects() || []);
|
|
162
159
|
}
|
|
163
160
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { TableColumn } from '@journeyapps-labs/reactor-mod';
|
|
3
|
+
import * as _ from 'lodash';
|
|
4
|
+
import { PageRow } from '../Page';
|
|
5
|
+
import { CellDisplayWidget } from '../widgets/CellDisplayWidget';
|
|
6
|
+
import { SmartColumnWidget } from '../widgets/SmartColumnWidget';
|
|
7
|
+
import { SmartCellDisplayWidget } from '../widgets/SmartCellDisplayWidget';
|
|
8
|
+
import { SmartBelongsToDisplayWidget } from '../widgets/SmartBelongsToDisplayWidget';
|
|
9
|
+
import { ColumnDisplayWidget } from '../widgets/ColumnDisplayWidget';
|
|
10
|
+
import { SchemaModelDefinition } from '../../SchemaModelDefinition';
|
|
11
|
+
import { AbstractConnection } from '../../AbstractConnection';
|
|
12
|
+
import { SimpleQuerySort, SortDirection } from './SimpleQueryTypes';
|
|
13
|
+
import { SimpleQuerySortState } from './SimpleQuerySortState';
|
|
14
|
+
import { SimpleQueryFilterState } from './SimpleQueryFilterState';
|
|
15
|
+
import { STANDARD_MODEL_FIELD_LABELS, StandardModelFields } from '../StandardModelFields';
|
|
16
|
+
|
|
17
|
+
export interface BuildSimpleQueryColumnsOptions {
|
|
18
|
+
definition: SchemaModelDefinition;
|
|
19
|
+
connection: AbstractConnection;
|
|
20
|
+
sortState: SimpleQuerySortState;
|
|
21
|
+
filterState: SimpleQueryFilterState;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const buildSimpleQueryColumns = (options: BuildSimpleQueryColumnsOptions): TableColumn[] => {
|
|
25
|
+
const getSortLabel = (field: string, label: string) => {
|
|
26
|
+
const direction = options.sortState.getSort(field)?.direction;
|
|
27
|
+
if (!direction) {
|
|
28
|
+
return label;
|
|
29
|
+
}
|
|
30
|
+
return `${label} ${direction === SortDirection.ASC ? '↑' : '↓'}`;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return [
|
|
34
|
+
{
|
|
35
|
+
key: StandardModelFields.ID,
|
|
36
|
+
display: (
|
|
37
|
+
<ColumnDisplayWidget
|
|
38
|
+
label={getSortLabel(StandardModelFields.ID, STANDARD_MODEL_FIELD_LABELS[StandardModelFields.ID])}
|
|
39
|
+
onClick={async () => {
|
|
40
|
+
const sort = options.sortState.getSort(StandardModelFields.ID);
|
|
41
|
+
if (!sort) {
|
|
42
|
+
options.sortState.addSort(SimpleQuerySort.create(StandardModelFields.ID));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
sort.toggle();
|
|
46
|
+
}}
|
|
47
|
+
/>
|
|
48
|
+
),
|
|
49
|
+
noWrap: true,
|
|
50
|
+
shrink: true
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
key: StandardModelFields.UPDATED_AT,
|
|
54
|
+
display: (
|
|
55
|
+
<ColumnDisplayWidget
|
|
56
|
+
label={getSortLabel(
|
|
57
|
+
StandardModelFields.UPDATED_AT,
|
|
58
|
+
STANDARD_MODEL_FIELD_LABELS[StandardModelFields.UPDATED_AT]
|
|
59
|
+
)}
|
|
60
|
+
onClick={async () => {
|
|
61
|
+
const sort = options.sortState.getSort(StandardModelFields.UPDATED_AT);
|
|
62
|
+
if (!sort) {
|
|
63
|
+
options.sortState.addSort(SimpleQuerySort.create(StandardModelFields.UPDATED_AT));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
sort.toggle();
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
69
|
+
),
|
|
70
|
+
noWrap: true,
|
|
71
|
+
shrink: true,
|
|
72
|
+
accessor: (cell, row: PageRow) => {
|
|
73
|
+
return <CellDisplayWidget name={StandardModelFields.UPDATED_AT} cell={row.model.updated_at} row={row} />;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
..._.map(options.definition.definition.belongsToIdVars, (a) => {
|
|
77
|
+
return {
|
|
78
|
+
key: a.name,
|
|
79
|
+
display: (
|
|
80
|
+
<SmartColumnWidget
|
|
81
|
+
variable={options.definition.definition.belongsToVars[a.relationship]}
|
|
82
|
+
type={options.definition.definition.belongsTo[a.relationship].foreignType}
|
|
83
|
+
filterChanged={(filter) => {}}
|
|
84
|
+
/>
|
|
85
|
+
),
|
|
86
|
+
noWrap: true,
|
|
87
|
+
shrink: true,
|
|
88
|
+
accessor: (cell, row: PageRow) => {
|
|
89
|
+
return <SmartBelongsToDisplayWidget variable_id={a} row={row} connection={options.connection} />;
|
|
90
|
+
}
|
|
91
|
+
} as TableColumn;
|
|
92
|
+
}),
|
|
93
|
+
..._.map(options.definition.definition.attributes, (a) => {
|
|
94
|
+
return {
|
|
95
|
+
key: a.name,
|
|
96
|
+
display: (
|
|
97
|
+
<SmartColumnWidget
|
|
98
|
+
variable={a}
|
|
99
|
+
filter={options.filterState.getFilter(a.name)}
|
|
100
|
+
sortDirection={options.sortState.getSort(a.name)?.direction}
|
|
101
|
+
onToggleSort={async () => {
|
|
102
|
+
const sort = options.sortState.getSort(a.name);
|
|
103
|
+
if (!sort) {
|
|
104
|
+
options.sortState.addSort(SimpleQuerySort.create(a.name));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
sort.toggle();
|
|
108
|
+
}}
|
|
109
|
+
filterChanged={async (filter) => {
|
|
110
|
+
if (!filter) {
|
|
111
|
+
options.filterState.getFilter(a.name)?.delete();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
options.filterState.setFilter(a.name, filter);
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
),
|
|
118
|
+
noWrap: true,
|
|
119
|
+
shrink: true,
|
|
120
|
+
accessor: (cell, row: PageRow) => {
|
|
121
|
+
return <SmartCellDisplayWidget name={a.name} row={row} />;
|
|
122
|
+
}
|
|
123
|
+
} as TableColumn;
|
|
124
|
+
})
|
|
125
|
+
];
|
|
126
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Variable } from '@journeyapps/db';
|
|
2
|
+
import * as _ from 'lodash';
|
|
3
|
+
import { BaseObserver } from '@journeyapps-labs/common-utils';
|
|
4
|
+
import { SchemaModelDefinition } from '../../SchemaModelDefinition';
|
|
5
|
+
import { SerializedSimpleFilter, SimpleFilter } from '../filters';
|
|
6
|
+
import { TypeEngine } from '../../../forms/TypeEngine';
|
|
7
|
+
|
|
8
|
+
export interface SimpleQueryFilterStateListener {
|
|
9
|
+
changed: () => any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SimpleQueryFilterStateOptions {
|
|
13
|
+
definition?: SchemaModelDefinition;
|
|
14
|
+
typeEngine: TypeEngine;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ActiveFilterEntry {
|
|
18
|
+
variable: Variable;
|
|
19
|
+
filter: SimpleFilter;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class SimpleQueryFilterState extends BaseObserver<SimpleQueryFilterStateListener> {
|
|
23
|
+
readonly simpleFilters: Map<Variable, SimpleFilter>;
|
|
24
|
+
accessor definition: SchemaModelDefinition | undefined;
|
|
25
|
+
readonly typeEngine: TypeEngine;
|
|
26
|
+
|
|
27
|
+
constructor(options: SimpleQueryFilterStateOptions) {
|
|
28
|
+
super();
|
|
29
|
+
this.simpleFilters = new Map();
|
|
30
|
+
this.definition = options.definition;
|
|
31
|
+
this.typeEngine = options.typeEngine;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get filters(): SimpleFilter[] {
|
|
35
|
+
return Array.from(this.simpleFilters.values());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
clear() {
|
|
39
|
+
this.filters.forEach((filter) => filter.delete());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
setDefinition(definition: SchemaModelDefinition | undefined) {
|
|
43
|
+
const definitionChanged = this.definition?.definition?.name !== definition?.definition?.name;
|
|
44
|
+
this.definition = definition;
|
|
45
|
+
const hadFilters = this.simpleFilters.size > 0;
|
|
46
|
+
if (definitionChanged) {
|
|
47
|
+
this.clear();
|
|
48
|
+
}
|
|
49
|
+
if (definitionChanged && !hadFilters) {
|
|
50
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
51
|
+
}
|
|
52
|
+
return definitionChanged || hadFilters;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getFilterableFields(): { key: string; label: string }[] {
|
|
56
|
+
if (!this.definition?.definition) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
return this.definition.getFilterableFields(this.typeEngine);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getActiveFilters(): ActiveFilterEntry[] {
|
|
63
|
+
return Array.from(this.simpleFilters.entries()).map(([variable, filter]) => {
|
|
64
|
+
return {
|
|
65
|
+
variable,
|
|
66
|
+
filter
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getFilter(field: string): SimpleFilter | undefined {
|
|
72
|
+
const variable = this.resolveAttribute(field);
|
|
73
|
+
return variable ? this.simpleFilters.get(variable) : undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getSerializedFilters() {
|
|
77
|
+
return this.filters.map((filter) => filter.serialize());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
hydrateFilters(filters: SerializedSimpleFilter[]) {
|
|
81
|
+
this.clear();
|
|
82
|
+
const definition = this.definition;
|
|
83
|
+
if (!definition?.definition) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
(filters || []).forEach((filter) => {
|
|
87
|
+
if (!SimpleFilter.canDeserialize(filter)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const variable = _.find(_.values(definition.definition.attributes), (attribute) => {
|
|
91
|
+
return attribute.name === filter.variable;
|
|
92
|
+
});
|
|
93
|
+
if (!variable) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this.addFilter(variable, SimpleFilter.deserialize(variable, filter));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
setFilter(field: string, filter: SimpleFilter) {
|
|
101
|
+
const variable = this.resolveAttribute(field);
|
|
102
|
+
if (!variable) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
return this.addFilter(variable, filter);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async setupFilterForField(field: string, position?: MouseEvent): Promise<boolean> {
|
|
109
|
+
const variable = this.resolveAttribute(field);
|
|
110
|
+
if (!variable) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
const handler = this.typeEngine.getHandler(variable.type);
|
|
114
|
+
if (!handler?.setupFilter) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
const existing = this.simpleFilters.get(variable);
|
|
118
|
+
const nextFilter = await handler.setupFilter({
|
|
119
|
+
variable,
|
|
120
|
+
filter: existing,
|
|
121
|
+
position
|
|
122
|
+
});
|
|
123
|
+
if (!nextFilter) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return this.addFilter(variable, nextFilter);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private addFilter(variable: Variable, filter: SimpleFilter): boolean {
|
|
130
|
+
const existing = this.simpleFilters.get(variable);
|
|
131
|
+
if (existing && existing !== filter) {
|
|
132
|
+
existing.delete();
|
|
133
|
+
}
|
|
134
|
+
if (existing === filter) {
|
|
135
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
let unsubscribe = filter.registerListener({
|
|
139
|
+
removeRequested: () => {
|
|
140
|
+
unsubscribe();
|
|
141
|
+
if (this.simpleFilters.get(variable) === filter) {
|
|
142
|
+
this.simpleFilters.delete(variable);
|
|
143
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
this.simpleFilters.set(variable, filter);
|
|
148
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private resolveAttribute(field: string): Variable | undefined {
|
|
153
|
+
if (!this.definition?.definition) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return _.find(_.values(this.definition.definition.attributes), (attribute) => {
|
|
157
|
+
return attribute.name === field;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Query } from '@journeyapps/db';
|
|
2
|
+
import { AbstractFilter } from '../filters';
|
|
3
|
+
import { SimpleQuerySort, SortDirection } from './SimpleQueryTypes';
|
|
4
|
+
|
|
5
|
+
export const applyFiltersAndSorts = (query: Query, filters: AbstractFilter[], sorts: SimpleQuerySort[] = []): Query => {
|
|
6
|
+
let next = query;
|
|
7
|
+
(filters || []).forEach((filter) => {
|
|
8
|
+
next = filter.augment(next);
|
|
9
|
+
});
|
|
10
|
+
if (sorts.length > 0) {
|
|
11
|
+
next = next.orderBy(
|
|
12
|
+
...sorts.map((sort) => {
|
|
13
|
+
return sort.direction === SortDirection.DESC ? `-${sort.field}` : sort.field;
|
|
14
|
+
})
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
return next;
|
|
18
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { observable } from 'mobx';
|
|
2
|
+
import * as _ from 'lodash';
|
|
3
|
+
import { BaseObserver } from '@journeyapps-labs/common-utils';
|
|
4
|
+
import { SchemaModelDefinition } from '../../SchemaModelDefinition';
|
|
5
|
+
import { SerializedSimpleQuerySort, SimpleQuerySort, SortDirection } from './SimpleQueryTypes';
|
|
6
|
+
import { STANDARD_MODEL_FIELD_LABELS, StandardModelFields } from '../StandardModelFields';
|
|
7
|
+
|
|
8
|
+
export interface SimpleQuerySortStateListener {
|
|
9
|
+
changed: () => any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class SimpleQuerySortState extends BaseObserver<SimpleQuerySortStateListener> {
|
|
13
|
+
@observable
|
|
14
|
+
accessor sorts: SimpleQuerySort[];
|
|
15
|
+
|
|
16
|
+
accessor definition: SchemaModelDefinition | undefined;
|
|
17
|
+
|
|
18
|
+
constructor(definition?: SchemaModelDefinition) {
|
|
19
|
+
super();
|
|
20
|
+
this.sorts = [];
|
|
21
|
+
this.definition = definition;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setDefinition(definition: SchemaModelDefinition | undefined) {
|
|
25
|
+
const changed = this.definition?.definition?.name !== definition?.definition?.name;
|
|
26
|
+
this.definition = definition;
|
|
27
|
+
if (changed) {
|
|
28
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
29
|
+
}
|
|
30
|
+
return changed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getSort(field: string): SimpleQuerySort | undefined {
|
|
34
|
+
return this.sorts.find((sort) => sort.field === field);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
addSort(sort: SimpleQuerySort): boolean {
|
|
38
|
+
if (!sort?.field) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const existing = this.getSort(sort.field);
|
|
42
|
+
if (existing) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
let unsubscribe = sort.registerListener({
|
|
46
|
+
changed: () => {
|
|
47
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
48
|
+
},
|
|
49
|
+
removeRequested: () => {
|
|
50
|
+
unsubscribe();
|
|
51
|
+
this.sorts = this.sorts.filter((entry) => entry !== sort);
|
|
52
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
this.sorts = [...this.sorts, sort];
|
|
56
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
moveSortBefore(sourceField: string, targetField: string): boolean {
|
|
61
|
+
if (!sourceField || !targetField || sourceField === targetField) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const sourceIndex = this.sorts.findIndex((sort) => sort.field === sourceField);
|
|
65
|
+
const targetIndex = this.sorts.findIndex((sort) => sort.field === targetField);
|
|
66
|
+
if (sourceIndex < 0 || targetIndex < 0) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const next = [...this.sorts];
|
|
70
|
+
const [source] = next.splice(sourceIndex, 1);
|
|
71
|
+
const nextTargetIndex = next.findIndex((sort) => sort.field === targetField);
|
|
72
|
+
const insertIndex = sourceIndex < targetIndex ? nextTargetIndex + 1 : nextTargetIndex;
|
|
73
|
+
next.splice(insertIndex, 0, source);
|
|
74
|
+
this.sorts = next;
|
|
75
|
+
this.iterateListeners((cb) => cb.changed?.());
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
setSorts(sorts: SimpleQuerySort[]) {
|
|
80
|
+
const next = this.normalizeSorts(sorts);
|
|
81
|
+
[...this.sorts].forEach((sort) => sort.remove());
|
|
82
|
+
this.sorts = [];
|
|
83
|
+
next.forEach((sort) => this.addSort(sort));
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
hydrateSorts(serializedSorts: SerializedSimpleQuerySort[] = []) {
|
|
88
|
+
const next = (serializedSorts || []).map((sort) => SimpleQuerySort.deserialize(sort));
|
|
89
|
+
return this.setSorts(next);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getSerializedSorts(): SerializedSimpleQuerySort[] {
|
|
93
|
+
return this.sorts.map((sort) => sort.serialize());
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getSortableFields(): { key: string; label: string }[] {
|
|
97
|
+
const definition = this.definition;
|
|
98
|
+
if (!definition?.definition) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const dynamic = _.map(definition.definition.attributes, (attribute) => {
|
|
102
|
+
return {
|
|
103
|
+
key: attribute.name,
|
|
104
|
+
label: attribute.label || attribute.name
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
return [
|
|
108
|
+
{ key: StandardModelFields.ID, label: STANDARD_MODEL_FIELD_LABELS[StandardModelFields.ID] },
|
|
109
|
+
{
|
|
110
|
+
key: StandardModelFields.UPDATED_AT,
|
|
111
|
+
label: STANDARD_MODEL_FIELD_LABELS[StandardModelFields.UPDATED_AT]
|
|
112
|
+
},
|
|
113
|
+
...dynamic
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private normalizeSorts(sorts: SimpleQuerySort[]): SimpleQuerySort[] {
|
|
118
|
+
const seen = new Set<string>();
|
|
119
|
+
return (sorts || []).filter((sort) => {
|
|
120
|
+
if (!sort?.field) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (!(sort.direction === SortDirection.ASC || sort.direction === SortDirection.DESC)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
if (seen.has(sort.field)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
seen.add(sort.field);
|
|
130
|
+
return true;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|