@xh/hoist 71.0.0-SNAPSHOT.1733262000771 → 71.0.0-SNAPSHOT.1733266596001
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 +8 -2
- package/appcontainer/AppContainerModel.ts +2 -1
- package/build/types/cmp/viewmanager/SaveAsDialogModel.d.ts +23 -0
- package/build/types/cmp/viewmanager/View.d.ts +28 -0
- package/build/types/cmp/viewmanager/ViewInfo.d.ts +30 -0
- package/build/types/cmp/viewmanager/ViewManagerModel.d.ts +185 -0
- package/build/types/cmp/viewmanager/index.d.ts +4 -0
- package/build/types/core/XH.d.ts +2 -1
- package/build/types/core/persist/PersistOptions.d.ts +3 -1
- package/build/types/core/persist/index.d.ts +6 -5
- package/build/types/core/persist/{CustomProvider.d.ts → provider/CustomProvider.d.ts} +1 -1
- package/build/types/core/persist/{DashViewProvider.d.ts → provider/DashViewProvider.d.ts} +2 -2
- package/build/types/core/persist/{LocalStorageProvider.d.ts → provider/LocalStorageProvider.d.ts} +1 -1
- package/build/types/core/persist/{PrefProvider.d.ts → provider/PrefProvider.d.ts} +1 -2
- package/build/types/core/persist/provider/SessionStorageProvider.d.ts +10 -0
- package/build/types/core/persist/{viewmanager → provider}/ViewManagerProvider.d.ts +3 -3
- package/build/types/desktop/cmp/viewmanager/ViewManager.d.ts +9 -10
- package/build/types/desktop/cmp/viewmanager/ViewMenu.d.ts +5 -0
- package/build/types/desktop/cmp/viewmanager/dialog/EditForm.d.ts +5 -0
- package/build/types/desktop/cmp/viewmanager/dialog/EditFormModel.d.ts +18 -0
- package/build/types/desktop/cmp/viewmanager/dialog/ManageDialog.d.ts +5 -0
- package/build/types/desktop/cmp/viewmanager/dialog/ManageDialogModel.d.ts +38 -0
- package/build/types/desktop/cmp/viewmanager/dialog/SaveAsDialog.d.ts +5 -0
- package/build/types/svc/JsonBlobService.d.ts +1 -1
- package/build/types/svc/index.d.ts +2 -1
- package/build/types/svc/storage/BaseStorageService.d.ts +21 -0
- package/build/types/svc/storage/LocalStorageService.d.ts +12 -0
- package/build/types/svc/storage/SessionStorageService.d.ts +12 -0
- package/cmp/viewmanager/SaveAsDialogModel.ts +97 -0
- package/cmp/viewmanager/View.ts +56 -0
- package/cmp/viewmanager/ViewInfo.ts +58 -0
- package/cmp/viewmanager/ViewManagerModel.ts +710 -0
- package/cmp/viewmanager/index.ts +4 -0
- package/core/XH.ts +2 -0
- package/core/persist/PersistOptions.ts +4 -1
- package/core/persist/PersistenceProvider.ts +5 -0
- package/core/persist/index.ts +6 -5
- package/core/persist/{CustomProvider.ts → provider/CustomProvider.ts} +1 -1
- package/core/persist/{DashViewProvider.ts → provider/DashViewProvider.ts} +1 -1
- package/core/persist/{LocalStorageProvider.ts → provider/LocalStorageProvider.ts} +1 -1
- package/core/persist/{PrefProvider.ts → provider/PrefProvider.ts} +2 -2
- package/core/persist/provider/SessionStorageProvider.ts +35 -0
- package/core/persist/{viewmanager → provider}/ViewManagerProvider.ts +5 -9
- package/desktop/cmp/viewmanager/ViewManager.ts +47 -229
- package/desktop/cmp/viewmanager/ViewMenu.ts +191 -0
- package/desktop/cmp/viewmanager/dialog/EditForm.ts +126 -0
- package/desktop/cmp/viewmanager/dialog/EditFormModel.ts +125 -0
- package/desktop/cmp/viewmanager/dialog/ManageDialog.ts +98 -0
- package/desktop/cmp/viewmanager/dialog/ManageDialogModel.ts +279 -0
- package/desktop/cmp/viewmanager/{impl/SaveDialog.ts → dialog/SaveAsDialog.ts} +20 -12
- package/package.json +1 -1
- package/svc/JsonBlobService.ts +1 -1
- package/svc/index.ts +2 -1
- package/svc/{LocalStorageService.ts → storage/BaseStorageService.ts} +13 -23
- package/svc/storage/LocalStorageService.ts +23 -0
- package/svc/storage/SessionStorageService.ts +23 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/build/types/core/persist/viewmanager/Types.d.ts +0 -48
- package/build/types/core/persist/viewmanager/ViewManagerModel.d.ts +0 -145
- package/build/types/core/persist/viewmanager/impl/BuildViewTree.d.ts +0 -8
- package/build/types/core/persist/viewmanager/impl/ManageDialogModel.d.ts +0 -30
- package/build/types/core/persist/viewmanager/impl/SaveDialogModel.d.ts +0 -23
- package/build/types/core/persist/viewmanager/index.d.ts +0 -2
- package/build/types/desktop/cmp/viewmanager/impl/ManageDialog.d.ts +0 -6
- package/build/types/desktop/cmp/viewmanager/impl/SaveDialog.d.ts +0 -2
- package/build/types/svc/LocalStorageService.d.ts +0 -24
- package/core/persist/viewmanager/Types.ts +0 -53
- package/core/persist/viewmanager/ViewManagerModel.ts +0 -481
- package/core/persist/viewmanager/impl/BuildViewTree.ts +0 -68
- package/core/persist/viewmanager/impl/ManageDialogModel.ts +0 -276
- package/core/persist/viewmanager/impl/SaveDialogModel.ts +0 -112
- package/core/persist/viewmanager/index.ts +0 -2
- package/desktop/cmp/viewmanager/impl/ManageDialog.ts +0 -197
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import {FormModel} from '@xh/hoist/cmp/form';
|
|
2
|
-
import {GridAutosizeMode, GridModel} from '@xh/hoist/cmp/grid';
|
|
3
|
-
import {fragment, p} from '@xh/hoist/cmp/layout';
|
|
4
|
-
import {HoistModel, lookup, managed, TaskObserver, XH} from '@xh/hoist/core';
|
|
5
|
-
import {lengthIs, required} from '@xh/hoist/data';
|
|
6
|
-
import {Icon} from '@xh/hoist/icon';
|
|
7
|
-
import {makeObservable} from '@xh/hoist/mobx';
|
|
8
|
-
import {pluralize, throwIf} from '@xh/hoist/utils/js';
|
|
9
|
-
import {ViewManagerModel} from '../ViewManagerModel';
|
|
10
|
-
|
|
11
|
-
export class ManageDialogModel extends HoistModel {
|
|
12
|
-
@lookup(() => ViewManagerModel)
|
|
13
|
-
private viewManagerModel: ViewManagerModel;
|
|
14
|
-
|
|
15
|
-
@managed gridModel: GridModel;
|
|
16
|
-
@managed formModel: FormModel;
|
|
17
|
-
|
|
18
|
-
readonly saveTask = TaskObserver.trackLast();
|
|
19
|
-
readonly deleteTask = TaskObserver.trackLast();
|
|
20
|
-
|
|
21
|
-
get selectedId(): string {
|
|
22
|
-
return this.gridModel.selectedId as string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get selectedIds(): string[] {
|
|
26
|
-
return this.gridModel.selectedIds as string[];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get hasMultiSelection(): boolean {
|
|
30
|
-
return this.selectedIds.length > 1;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
get selIsShared(): boolean {
|
|
34
|
-
return this.gridModel.selectedRecords.some(rec => rec.data.isShared);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get canDelete(): boolean {
|
|
38
|
-
const {viewManagerModel, selIsShared, enableSharing, selectedIds} = this,
|
|
39
|
-
{views, enableDefault} = viewManagerModel;
|
|
40
|
-
|
|
41
|
-
// Can't delete shared views without manager role.
|
|
42
|
-
if (selIsShared && !enableSharing) return false;
|
|
43
|
-
|
|
44
|
-
// Can't delete all the views, unless default mode is enabled.
|
|
45
|
-
return enableDefault || views.length - selectedIds.length > 0;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get canEdit(): boolean {
|
|
49
|
-
return this.enableSharing || !this.selIsShared;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get enableSharing(): boolean {
|
|
53
|
-
return this.viewManagerModel.enableSharing;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
get showSaveButton(): boolean {
|
|
57
|
-
const {formModel, viewManagerModel} = this;
|
|
58
|
-
return formModel.isDirty && !formModel.readonly && !viewManagerModel.loadModel.isPending;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
get displayName(): string {
|
|
62
|
-
return this.viewManagerModel.displayName;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
get enableFavorites(): boolean {
|
|
66
|
-
return this.viewManagerModel.enableFavorites;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
constructor() {
|
|
70
|
-
super();
|
|
71
|
-
makeObservable(this);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
override onLinked() {
|
|
75
|
-
super.onLinked();
|
|
76
|
-
|
|
77
|
-
this.gridModel = this.createGridModel();
|
|
78
|
-
this.formModel = this.createFormModel();
|
|
79
|
-
|
|
80
|
-
this.addReaction(
|
|
81
|
-
{
|
|
82
|
-
track: () => this.viewManagerModel.views,
|
|
83
|
-
run: () => this.refreshAsync()
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
track: () => this.gridModel.selectedRecord,
|
|
87
|
-
run: record => {
|
|
88
|
-
if (record) {
|
|
89
|
-
this.formModel.readonly = !this.canEdit;
|
|
90
|
-
this.formModel.init(record.data);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
override async doLoadAsync() {
|
|
98
|
-
this.gridModel.loadData(this.viewManagerModel.views);
|
|
99
|
-
await this.ensureGridHasSelection();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async saveAsync() {
|
|
103
|
-
return this.doSaveAsync().linkTo(this.saveTask).catchDefault();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async deleteAsync() {
|
|
107
|
-
return this.doDeleteAsync().linkTo(this.deleteTask).catchDefault();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
//------------------------
|
|
111
|
-
// Implementation
|
|
112
|
-
//------------------------
|
|
113
|
-
private async doSaveAsync() {
|
|
114
|
-
const {formModel, viewManagerModel, enableSharing, selectedId, gridModel, displayName} =
|
|
115
|
-
this,
|
|
116
|
-
{isDirty} = formModel,
|
|
117
|
-
{name, description, isShared} = formModel.getData(),
|
|
118
|
-
isValid = await formModel.validateAsync(),
|
|
119
|
-
{token, owner} = gridModel.selectedRecord.data,
|
|
120
|
-
isOwnView = owner === XH.getUsername();
|
|
121
|
-
|
|
122
|
-
if (!isValid || !selectedId || !isDirty) return;
|
|
123
|
-
|
|
124
|
-
// Additional sanity-check before POSTing an update - non-admins should never be modifying global views.
|
|
125
|
-
throwIf(
|
|
126
|
-
isShared && !enableSharing,
|
|
127
|
-
`Cannot save changes to shared ${displayName} - missing required permission.`
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
if (formModel.getField('isShared').isDirty) {
|
|
131
|
-
const confirmMsgs = [];
|
|
132
|
-
if (isShared) {
|
|
133
|
-
confirmMsgs.push(
|
|
134
|
-
`This ${displayName} will become visible to all other ${XH.appName} users.`
|
|
135
|
-
);
|
|
136
|
-
} else if (isOwnView) {
|
|
137
|
-
confirmMsgs.push(
|
|
138
|
-
`The selected ${displayName} will revert to being private to you. It will no longer be available to other users.`
|
|
139
|
-
);
|
|
140
|
-
} else {
|
|
141
|
-
confirmMsgs.push(
|
|
142
|
-
`The selected ${displayName} will revert to being private to its owner (${owner}).`,
|
|
143
|
-
`Note that you will no longer have access to this view, meaning you will not be able to undo this change.`
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
confirmMsgs.push('Are you sure you want to proceed?');
|
|
148
|
-
|
|
149
|
-
const confirmed = await XH.confirm({
|
|
150
|
-
message: fragment(confirmMsgs.map(msg => p(msg))),
|
|
151
|
-
confirmProps: {
|
|
152
|
-
text: 'Yes, update visibility',
|
|
153
|
-
outlined: true,
|
|
154
|
-
autoFocus: false,
|
|
155
|
-
intent: 'primary'
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
if (!confirmed) return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
await XH.jsonBlobService.updateAsync(token, {
|
|
163
|
-
name,
|
|
164
|
-
description,
|
|
165
|
-
acl: isShared ? '*' : null
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
await viewManagerModel.refreshAsync();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private async doDeleteAsync() {
|
|
172
|
-
const {viewManagerModel, gridModel, displayName, selectedIds, hasMultiSelection} = this,
|
|
173
|
-
count = selectedIds.length;
|
|
174
|
-
if (!count) return;
|
|
175
|
-
|
|
176
|
-
const confirmStr = hasMultiSelection
|
|
177
|
-
? pluralize(displayName, count, true)
|
|
178
|
-
: `"${gridModel.selectedRecord.data.name}"`,
|
|
179
|
-
confirmed = await XH.confirm({
|
|
180
|
-
message: `Are you sure you want to delete ${confirmStr}?`,
|
|
181
|
-
confirmProps: {
|
|
182
|
-
text: `Yes, delete ${pluralize(displayName, count)}`,
|
|
183
|
-
outlined: true,
|
|
184
|
-
autoFocus: false,
|
|
185
|
-
intent: 'danger'
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
if (!confirmed) return;
|
|
189
|
-
|
|
190
|
-
for (const token of selectedIds) {
|
|
191
|
-
viewManagerModel.removeFavorite(token);
|
|
192
|
-
await XH.jsonBlobService.archiveAsync(token);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
await viewManagerModel.refreshAsync();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private async ensureGridHasSelection() {
|
|
199
|
-
const {gridModel, viewManagerModel} = this,
|
|
200
|
-
{selectedToken} = viewManagerModel;
|
|
201
|
-
|
|
202
|
-
if (!gridModel.hasSelection) {
|
|
203
|
-
selectedToken
|
|
204
|
-
? await gridModel.selectAsync(selectedToken)
|
|
205
|
-
: await gridModel.preSelectFirstAsync();
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private createGridModel(): GridModel {
|
|
210
|
-
return new GridModel({
|
|
211
|
-
emptyText: `No saved ${pluralize(this.displayName)} found...`,
|
|
212
|
-
sortBy: 'name',
|
|
213
|
-
groupBy: 'group',
|
|
214
|
-
hideHeaders: true,
|
|
215
|
-
showGroupRowCounts: false,
|
|
216
|
-
selModel: 'multiple',
|
|
217
|
-
contextMenu: null,
|
|
218
|
-
sizingMode: 'standard',
|
|
219
|
-
store: {
|
|
220
|
-
idSpec: 'token',
|
|
221
|
-
fields: [
|
|
222
|
-
{name: 'token', type: 'string'},
|
|
223
|
-
{name: 'name', type: 'string'},
|
|
224
|
-
{name: 'description', type: 'string'},
|
|
225
|
-
{name: 'isShared', type: 'bool'},
|
|
226
|
-
{name: 'isFavorite', type: 'bool'},
|
|
227
|
-
{name: 'acl', type: 'json'},
|
|
228
|
-
{name: 'meta', type: 'json'},
|
|
229
|
-
{name: 'dateCreated', type: 'date'},
|
|
230
|
-
{name: 'createdBy', type: 'string'},
|
|
231
|
-
{name: 'owner', type: 'string'},
|
|
232
|
-
{name: 'lastUpdatedBy', type: 'string'},
|
|
233
|
-
{name: 'lastUpdated', type: 'date'}
|
|
234
|
-
]
|
|
235
|
-
},
|
|
236
|
-
autosizeOptions: {mode: GridAutosizeMode.DISABLED},
|
|
237
|
-
columns: [
|
|
238
|
-
{field: 'name', flex: true},
|
|
239
|
-
{
|
|
240
|
-
field: 'isFavorite',
|
|
241
|
-
omit: !this.enableFavorites,
|
|
242
|
-
width: 40,
|
|
243
|
-
align: 'center',
|
|
244
|
-
headerName: Icon.favorite(),
|
|
245
|
-
highlightOnChange: true,
|
|
246
|
-
renderer: v => {
|
|
247
|
-
return Icon.favorite({
|
|
248
|
-
prefix: v ? 'fas' : 'fal',
|
|
249
|
-
className: v ? 'xh-yellow' : 'xh-text-color-muted'
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
{field: 'group', hidden: true}
|
|
254
|
-
],
|
|
255
|
-
onCellClicked: ({colDef, data: record}) => {
|
|
256
|
-
if (colDef.colId === 'isFavorite') {
|
|
257
|
-
this.viewManagerModel.toggleFavorite(record.id);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private createFormModel(): FormModel {
|
|
264
|
-
return new FormModel({
|
|
265
|
-
fields: [
|
|
266
|
-
{name: 'name', rules: [required, lengthIs({max: 255})]},
|
|
267
|
-
{name: 'description'},
|
|
268
|
-
{name: 'isShared', displayName: 'Shared'},
|
|
269
|
-
{name: 'owner', readonly: true},
|
|
270
|
-
{name: 'dateCreated', displayName: 'Created', readonly: true},
|
|
271
|
-
{name: 'lastUpdated', displayName: 'Updated', readonly: true},
|
|
272
|
-
{name: 'lastUpdatedBy', displayName: 'Updated By', readonly: true}
|
|
273
|
-
]
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import {FormModel} from '@xh/hoist/cmp/form';
|
|
2
|
-
import {HoistModel, managed, TaskObserver, XH} from '@xh/hoist/core';
|
|
3
|
-
import {ViewManagerModel} from '@xh/hoist/core/persist/viewmanager';
|
|
4
|
-
import {lengthIs, required} from '@xh/hoist/data';
|
|
5
|
-
import {makeObservable} from '@xh/hoist/mobx';
|
|
6
|
-
import {JsonBlob} from '@xh/hoist/svc';
|
|
7
|
-
import {action, observable} from 'mobx';
|
|
8
|
-
import {View} from '../Types';
|
|
9
|
-
|
|
10
|
-
export class SaveDialogModel extends HoistModel {
|
|
11
|
-
private readonly viewManagerModel: ViewManagerModel;
|
|
12
|
-
|
|
13
|
-
@managed readonly formModel: FormModel;
|
|
14
|
-
readonly saveTask = TaskObserver.trackLast();
|
|
15
|
-
|
|
16
|
-
@observable viewStub: Partial<View>;
|
|
17
|
-
@observable isOpen: boolean = false;
|
|
18
|
-
|
|
19
|
-
private resolveOpen: (value: JsonBlob) => void;
|
|
20
|
-
private invalidNames: string[] = [];
|
|
21
|
-
|
|
22
|
-
get type(): string {
|
|
23
|
-
return this.viewManagerModel.viewType;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get DisplayName(): string {
|
|
27
|
-
return this.viewManagerModel.DisplayName;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
constructor(viewManagerModel: ViewManagerModel) {
|
|
31
|
-
super();
|
|
32
|
-
makeObservable(this);
|
|
33
|
-
this.viewManagerModel = viewManagerModel;
|
|
34
|
-
this.formModel = this.createFormModel();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
@action
|
|
38
|
-
openAsync(viewStub: Partial<View>, invalidNames: string[]): Promise<JsonBlob> {
|
|
39
|
-
this.viewStub = viewStub;
|
|
40
|
-
this.invalidNames = invalidNames;
|
|
41
|
-
|
|
42
|
-
this.formModel.init({
|
|
43
|
-
name: viewStub.name ?? '',
|
|
44
|
-
description: viewStub.description
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
this.isOpen = true;
|
|
48
|
-
|
|
49
|
-
return new Promise(resolve => {
|
|
50
|
-
this.resolveOpen = resolve;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
cancel() {
|
|
55
|
-
this.close();
|
|
56
|
-
this.resolveOpen(null);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async saveAsAsync() {
|
|
60
|
-
return this.doSaveAsAsync().linkTo(this.saveTask);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
//------------------------
|
|
64
|
-
// Implementation
|
|
65
|
-
//------------------------
|
|
66
|
-
private createFormModel(): FormModel {
|
|
67
|
-
return new FormModel({
|
|
68
|
-
fields: [
|
|
69
|
-
{
|
|
70
|
-
name: 'name',
|
|
71
|
-
rules: [
|
|
72
|
-
required,
|
|
73
|
-
lengthIs({max: 255}),
|
|
74
|
-
({value}) => {
|
|
75
|
-
if (this.invalidNames.includes(value)) {
|
|
76
|
-
return `An entry with name "${value}" already exists`;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
},
|
|
81
|
-
{name: 'description'}
|
|
82
|
-
]
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
private async doSaveAsAsync() {
|
|
87
|
-
const {formModel, viewStub, type} = this,
|
|
88
|
-
{name, description} = formModel.getData(),
|
|
89
|
-
isValid = await formModel.validateAsync();
|
|
90
|
-
|
|
91
|
-
if (!isValid) return;
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
const newObj = await XH.jsonBlobService.createAsync({
|
|
95
|
-
type,
|
|
96
|
-
name,
|
|
97
|
-
description,
|
|
98
|
-
value: viewStub.value
|
|
99
|
-
});
|
|
100
|
-
this.close();
|
|
101
|
-
this.resolveOpen(newObj);
|
|
102
|
-
} catch (e) {
|
|
103
|
-
XH.handleException(e);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
@action
|
|
108
|
-
private close() {
|
|
109
|
-
this.isOpen = false;
|
|
110
|
-
this.formModel.init();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import {form} from '@xh/hoist/cmp/form';
|
|
2
|
-
import {grid} from '@xh/hoist/cmp/grid';
|
|
3
|
-
import {div, filler, hbox, hframe, hspacer, placeholder, span, vframe} from '@xh/hoist/cmp/layout';
|
|
4
|
-
import {storeFilterField} from '@xh/hoist/cmp/store';
|
|
5
|
-
import {creates, hoistCmp, HoistProps, XH} from '@xh/hoist/core';
|
|
6
|
-
import {ManageDialogModel} from '@xh/hoist/core/persist/viewmanager/impl/ManageDialogModel';
|
|
7
|
-
import {button} from '@xh/hoist/desktop/cmp/button';
|
|
8
|
-
import {formField} from '@xh/hoist/desktop/cmp/form';
|
|
9
|
-
import {select, textArea, textInput} from '@xh/hoist/desktop/cmp/input';
|
|
10
|
-
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
11
|
-
import {toolbar} from '@xh/hoist/desktop/cmp/toolbar';
|
|
12
|
-
import {fmtCompactDate} from '@xh/hoist/format';
|
|
13
|
-
import {Icon} from '@xh/hoist/icon';
|
|
14
|
-
import {dialog} from '@xh/hoist/kit/blueprint';
|
|
15
|
-
import {pluralize} from '@xh/hoist/utils/js';
|
|
16
|
-
import {capitalize} from 'lodash';
|
|
17
|
-
|
|
18
|
-
export interface ManageDialogProps extends HoistProps<ManageDialogModel> {
|
|
19
|
-
onClose: () => void;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const manageDialog = hoistCmp.factory<ManageDialogProps>({
|
|
23
|
-
displayName: 'ManageDialog',
|
|
24
|
-
className: 'xh-view-manager__manage-dialog',
|
|
25
|
-
model: creates(ManageDialogModel),
|
|
26
|
-
|
|
27
|
-
render({model, className, onClose}) {
|
|
28
|
-
const {displayName, saveTask, deleteTask} = model;
|
|
29
|
-
return dialog({
|
|
30
|
-
title: `Manage ${capitalize(pluralize(displayName))}`,
|
|
31
|
-
icon: Icon.gear(),
|
|
32
|
-
className,
|
|
33
|
-
isOpen: true,
|
|
34
|
-
style: {width: '800px', maxWidth: '90vm', minHeight: '430px'},
|
|
35
|
-
canOutsideClickClose: false,
|
|
36
|
-
onClose,
|
|
37
|
-
item: panel({
|
|
38
|
-
item: hframe(gridPanel(), formPanel({onClose})),
|
|
39
|
-
mask: [saveTask, deleteTask]
|
|
40
|
-
})
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const gridPanel = hoistCmp.factory({
|
|
46
|
-
render() {
|
|
47
|
-
return panel({
|
|
48
|
-
modelConfig: {defaultSize: 350, side: 'left', collapsible: false},
|
|
49
|
-
item: grid(),
|
|
50
|
-
bbar: [storeFilterField()]
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const formPanel = hoistCmp.factory<ManageDialogProps>({
|
|
56
|
-
render({model, onClose}) {
|
|
57
|
-
const {displayName, formModel} = model,
|
|
58
|
-
{values} = formModel,
|
|
59
|
-
isOwnView = values.owner === XH.getUsername();
|
|
60
|
-
|
|
61
|
-
if (model.hasMultiSelection) {
|
|
62
|
-
return multiSelectionPanel({onClose});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (!model.selectedId)
|
|
66
|
-
return panel({
|
|
67
|
-
item: placeholder(Icon.gears(), `Select a ${displayName}`),
|
|
68
|
-
bbar: bbar({onClose})
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
return panel({
|
|
72
|
-
item: form({
|
|
73
|
-
fieldDefaults: {
|
|
74
|
-
commitOnChange: true
|
|
75
|
-
},
|
|
76
|
-
item: vframe({
|
|
77
|
-
className: 'xh-view-manager__manage-dialog__form',
|
|
78
|
-
items: [
|
|
79
|
-
formField({
|
|
80
|
-
field: 'name',
|
|
81
|
-
item: textInput(),
|
|
82
|
-
info: model.canEdit
|
|
83
|
-
? `Organize your ${pluralize(displayName)} into folders by including the "\\" character in their names - e.g. "My folder\\My ${displayName}".`
|
|
84
|
-
: null
|
|
85
|
-
}),
|
|
86
|
-
formField({
|
|
87
|
-
field: 'description',
|
|
88
|
-
item: textArea({
|
|
89
|
-
selectOnFocus: true,
|
|
90
|
-
height: 70
|
|
91
|
-
}),
|
|
92
|
-
readonlyRenderer: v =>
|
|
93
|
-
v
|
|
94
|
-
? v
|
|
95
|
-
: span({
|
|
96
|
-
item: 'None provided',
|
|
97
|
-
className: 'xh-text-color-muted'
|
|
98
|
-
})
|
|
99
|
-
}),
|
|
100
|
-
formField({
|
|
101
|
-
field: 'isShared',
|
|
102
|
-
label: 'Visibility',
|
|
103
|
-
item: select({
|
|
104
|
-
options: [
|
|
105
|
-
{value: true, label: 'Shared with all users'},
|
|
106
|
-
{
|
|
107
|
-
value: false,
|
|
108
|
-
label: `Private to ${isOwnView ? 'me' : values.owner}`
|
|
109
|
-
}
|
|
110
|
-
],
|
|
111
|
-
enableFilter: false
|
|
112
|
-
}),
|
|
113
|
-
omit: !model.enableSharing
|
|
114
|
-
}),
|
|
115
|
-
hbox({
|
|
116
|
-
omit: !model.showSaveButton,
|
|
117
|
-
style: {margin: '10px 20px'},
|
|
118
|
-
items: [
|
|
119
|
-
button({
|
|
120
|
-
text: 'Save Changes',
|
|
121
|
-
icon: Icon.check(),
|
|
122
|
-
intent: 'success',
|
|
123
|
-
minimal: false,
|
|
124
|
-
flex: 1,
|
|
125
|
-
onClick: () => model.saveAsync()
|
|
126
|
-
}),
|
|
127
|
-
hspacer(),
|
|
128
|
-
button({
|
|
129
|
-
icon: Icon.reset(),
|
|
130
|
-
tooltip: 'Revert changes',
|
|
131
|
-
minimal: false,
|
|
132
|
-
onClick: () => formModel.reset()
|
|
133
|
-
})
|
|
134
|
-
]
|
|
135
|
-
}),
|
|
136
|
-
filler(),
|
|
137
|
-
div({
|
|
138
|
-
className: 'xh-view-manager__manage-dialog__metadata',
|
|
139
|
-
items: [
|
|
140
|
-
`Created ${fmtCompactDate(values.dateCreated)} by ${
|
|
141
|
-
values.owner === XH.getUsername() ? 'you' : values.owner
|
|
142
|
-
}. `,
|
|
143
|
-
`Updated ${fmtCompactDate(values.lastUpdated)} by ${
|
|
144
|
-
values.lastUpdatedBy === XH.getUsername()
|
|
145
|
-
? 'you'
|
|
146
|
-
: values.lastUpdatedBy
|
|
147
|
-
}.`
|
|
148
|
-
]
|
|
149
|
-
})
|
|
150
|
-
]
|
|
151
|
-
})
|
|
152
|
-
}),
|
|
153
|
-
bbar: bbar({onClose})
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
const multiSelectionPanel = hoistCmp.factory<ManageDialogProps>({
|
|
159
|
-
render({model, onClose}) {
|
|
160
|
-
const {selectedIds} = model;
|
|
161
|
-
return panel({
|
|
162
|
-
item: vframe({
|
|
163
|
-
alignItems: 'center',
|
|
164
|
-
justifyContent: 'center',
|
|
165
|
-
item: button({
|
|
166
|
-
text: `Delete ${selectedIds.length} ${pluralize(model.displayName)}`,
|
|
167
|
-
icon: Icon.delete(),
|
|
168
|
-
intent: 'danger',
|
|
169
|
-
outlined: true,
|
|
170
|
-
disabled: !model.canDelete,
|
|
171
|
-
onClick: () => model.deleteAsync()
|
|
172
|
-
})
|
|
173
|
-
}),
|
|
174
|
-
bbar: bbar({onClose})
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const bbar = hoistCmp.factory<ManageDialogProps>({
|
|
180
|
-
render({model, onClose}) {
|
|
181
|
-
return toolbar(
|
|
182
|
-
button({
|
|
183
|
-
text: 'Delete',
|
|
184
|
-
icon: Icon.delete(),
|
|
185
|
-
intent: 'danger',
|
|
186
|
-
disabled: !model.canDelete,
|
|
187
|
-
omit: model.hasMultiSelection,
|
|
188
|
-
onClick: () => model.deleteAsync()
|
|
189
|
-
}),
|
|
190
|
-
filler(),
|
|
191
|
-
button({
|
|
192
|
-
text: 'Close',
|
|
193
|
-
onClick: onClose
|
|
194
|
-
})
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
});
|