@journeyapps-labs/reactor-mod-data-browser 2.3.0 → 2.4.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/@types/actions/schema-model/ViewSchemaModelAsJsonAction.d.ts +9 -0
  3. package/dist/@types/forms/TypeEngine.d.ts +13 -2
  4. package/dist/@types/forms/inputs/DirtyWrapperInput.d.ts +1 -0
  5. package/dist/@types/index.d.ts +2 -0
  6. package/dist/@types/panels/_shared/SharedModelPanelFactory.d.ts +22 -0
  7. package/dist/@types/panels/model/ModelPanelFactory.d.ts +4 -20
  8. package/dist/@types/panels/model-json/ModelJsonPanelFactory.d.ts +27 -0
  9. package/dist/@types/panels/model-json/ModelJsonPanelWidget.d.ts +6 -0
  10. package/dist/DataBrowserModule.js +4 -0
  11. package/dist/DataBrowserModule.js.map +1 -1
  12. package/dist/actions/schema-model/ViewSchemaModelAsJsonAction.js +46 -0
  13. package/dist/actions/schema-model/ViewSchemaModelAsJsonAction.js.map +1 -0
  14. package/dist/core/SchemaModelDefinition.js +1 -1
  15. package/dist/core/SchemaModelDefinition.js.map +1 -1
  16. package/dist/core/query/widgets/CellDisplayWidget.js +14 -81
  17. package/dist/core/query/widgets/CellDisplayWidget.js.map +1 -1
  18. package/dist/entities/ConnectionEntityDefinition.js +5 -0
  19. package/dist/entities/ConnectionEntityDefinition.js.map +1 -1
  20. package/dist/entities/SchemaModelDefinitionEntityDefinition.js +3 -1
  21. package/dist/entities/SchemaModelDefinitionEntityDefinition.js.map +1 -1
  22. package/dist/forms/SchemaModelForm.js +1 -1
  23. package/dist/forms/SchemaModelForm.js.map +1 -1
  24. package/dist/forms/TypeEngine.js +223 -5
  25. package/dist/forms/TypeEngine.js.map +1 -1
  26. package/dist/forms/inputs/DirtyWrapperInput.js +14 -0
  27. package/dist/forms/inputs/DirtyWrapperInput.js.map +1 -1
  28. package/dist/forms/inputs/LocationInput.js +13 -7
  29. package/dist/forms/inputs/LocationInput.js.map +1 -1
  30. package/dist/index.js +2 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/panels/_shared/SharedModelPanelFactory.js +77 -0
  33. package/dist/panels/_shared/SharedModelPanelFactory.js.map +1 -0
  34. package/dist/panels/model/ModelPanelFactory.js +7 -75
  35. package/dist/panels/model/ModelPanelFactory.js.map +1 -1
  36. package/dist/panels/model-json/ModelJsonPanelFactory.js +62 -0
  37. package/dist/panels/model-json/ModelJsonPanelFactory.js.map +1 -0
  38. package/dist/panels/model-json/ModelJsonPanelWidget.js +70 -0
  39. package/dist/panels/model-json/ModelJsonPanelWidget.js.map +1 -0
  40. package/dist/tsconfig.tsbuildinfo +1 -1
  41. package/dist-module/bundle.js +47 -26
  42. package/dist-module/bundle.js.map +1 -1
  43. package/package.json +9 -8
  44. package/src/DataBrowserModule.ts +4 -0
  45. package/src/actions/schema-model/ViewSchemaModelAsJsonAction.ts +33 -0
  46. package/src/core/SchemaModelDefinition.ts +1 -1
  47. package/src/core/query/widgets/CellDisplayWidget.tsx +15 -106
  48. package/src/entities/ConnectionEntityDefinition.tsx +5 -0
  49. package/src/entities/SchemaModelDefinitionEntityDefinition.ts +4 -0
  50. package/src/forms/SchemaModelForm.tsx +1 -1
  51. package/src/forms/TypeEngine.tsx +451 -0
  52. package/src/forms/inputs/DirtyWrapperInput.tsx +20 -0
  53. package/src/forms/inputs/LocationInput.tsx +14 -7
  54. package/src/index.ts +6 -0
  55. package/src/panels/_shared/SharedModelPanelFactory.tsx +54 -0
  56. package/src/panels/model/ModelPanelFactory.tsx +10 -51
  57. package/src/panels/model-json/ModelJsonPanelFactory.tsx +61 -0
  58. package/src/panels/model-json/ModelJsonPanelWidget.tsx +92 -0
  59. package/webpack.config.js +9 -2
  60. package/src/forms/TypeEngine.ts +0 -160
@@ -0,0 +1,451 @@
1
+ import {
2
+ Attachment,
3
+ AttachmentType,
4
+ BooleanType,
5
+ DatetimeType,
6
+ DateType,
7
+ Day,
8
+ Location,
9
+ LocationType,
10
+ MultipleChoiceIntegerType,
11
+ MultipleChoiceType,
12
+ NumberType,
13
+ PhotoType,
14
+ SignatureType,
15
+ SingleChoiceIntegerType,
16
+ SingleChoiceType,
17
+ TextType,
18
+ Type
19
+ } from '@journeyapps/db';
20
+ import {
21
+ AbstractMedia,
22
+ BooleanInput,
23
+ CheckboxWidget,
24
+ DateInput,
25
+ DateTimePickerType,
26
+ FileInput,
27
+ FormInput,
28
+ ImageInput,
29
+ ImageMedia,
30
+ inject,
31
+ MediaEngine,
32
+ MetadataWidget,
33
+ NumberInput,
34
+ PanelButtonWidget,
35
+ SelectInput,
36
+ SmartDateDisplayWidget,
37
+ styled,
38
+ TableButtonWidget,
39
+ TextAreaInput,
40
+ TextInput,
41
+ TextInputType,
42
+ MultiSelectInput,
43
+ WorkspaceStore
44
+ } from '@journeyapps-labs/reactor-mod';
45
+ import {} from '@journeyapps-labs/reactor-mod-editor';
46
+ import { LocationInput } from './inputs/LocationInput';
47
+ import * as React from 'react';
48
+ import { JSX } from 'react';
49
+ import { SchemaModelObject } from '../core/SchemaModelObject';
50
+ import * as _ from 'lodash';
51
+ import { ModelJsonPanelModel } from '../panels/model-json/ModelJsonPanelFactory';
52
+
53
+ const MAX_NUMBER_OF_ARR_ITEMS_TO_DISPLAY = 3;
54
+
55
+ export interface TypeHandler<T extends Type = Type, ENCODED = any, DECODED = any> {
56
+ matches: (type: Type) => boolean;
57
+ generateField: (event: { label: string; name: string; type: T }) => FormInput;
58
+ generateDisplay: (event: {
59
+ label: string;
60
+ name: string;
61
+ type: T;
62
+ value: ENCODED;
63
+ model: SchemaModelObject;
64
+ }) => JSX.Element | string;
65
+ decode: (value: ENCODED) => Promise<DECODED>;
66
+ encode: (value: DECODED) => Promise<ENCODED>;
67
+ }
68
+
69
+ export class TypeEngine {
70
+ handlers: Set<TypeHandler>;
71
+
72
+ @inject(MediaEngine)
73
+ accessor mediaEngine: MediaEngine;
74
+
75
+ @inject(WorkspaceStore)
76
+ accessor workspaceStore: WorkspaceStore;
77
+
78
+ private _mediaCache: Map<string, AbstractMedia>;
79
+
80
+ constructor() {
81
+ this.handlers = new Set();
82
+ this._mediaCache = new Map();
83
+ this.register({
84
+ matches: (type) => type instanceof DatetimeType || type instanceof DateType,
85
+ encode: async (value: Date) => new Day(value),
86
+ decode: async (value: Day | Date) => {
87
+ if (value instanceof Day) {
88
+ return value.toDate();
89
+ }
90
+ return value;
91
+ },
92
+ generateField: ({ label, name, type }) => {
93
+ return new DateInput({
94
+ name,
95
+ label,
96
+ type: type instanceof DatetimeType ? DateTimePickerType.DATETIME : DateTimePickerType.DATE
97
+ });
98
+ },
99
+ generateDisplay: ({ value }) => {
100
+ if (value instanceof Day) {
101
+ return <SmartDateDisplayWidget date={value.toDate()} />;
102
+ }
103
+ return <SmartDateDisplayWidget date={value} />;
104
+ }
105
+ });
106
+
107
+ this.register({
108
+ matches: (type) => type instanceof SignatureType || type instanceof PhotoType,
109
+ encode: async (value: ImageMedia) => {
110
+ return Attachment.create({
111
+ data: await value.toArrayBuffer()
112
+ });
113
+ },
114
+ decode: async (value: Attachment) => {
115
+ if (this._mediaCache.has(value.id)) {
116
+ return this._mediaCache.get(value.id);
117
+ }
118
+ let media = this.mediaEngine.getMediaTypeForPath('.jpg').generateMedia({
119
+ content: await value.toArrayBuffer(),
120
+ name: value.id,
121
+ uid: value.id
122
+ });
123
+
124
+ this._mediaCache.set(value.id, media);
125
+ return media;
126
+ },
127
+ generateField: ({ label, name }) => {
128
+ return new ImageInput({
129
+ name,
130
+ label
131
+ });
132
+ },
133
+ generateDisplay: ({ value, type }) => {
134
+ if (value.uploaded()) {
135
+ return (
136
+ <S.Preview
137
+ onClick={() => {
138
+ this.getHandler(type)
139
+ .decode(value)
140
+ .then((media: ImageMedia) => {
141
+ if (media instanceof ImageMedia) {
142
+ media.open();
143
+ } else {
144
+ window.open(value.url(), '_blank');
145
+ }
146
+ });
147
+ }}
148
+ src={value.urls['thumbnail']}
149
+ />
150
+ );
151
+ }
152
+ return <S.Empty>Not uploaded</S.Empty>;
153
+ }
154
+ });
155
+
156
+ this.register({
157
+ matches: (type) => type instanceof AttachmentType,
158
+ encode: async (value: File) => {
159
+ return Attachment.create({
160
+ data: await value.arrayBuffer(),
161
+ filename: value.name
162
+ });
163
+ },
164
+ decode: async (value: Attachment) => {
165
+ return new File([await value.toArrayBuffer()], value.id);
166
+ },
167
+ generateField: ({ label, name }) => {
168
+ return new FileInput({
169
+ name,
170
+ label
171
+ });
172
+ },
173
+ generateDisplay: ({ value }) => {
174
+ return (
175
+ <TableButtonWidget
176
+ icon="download"
177
+ action={() => {
178
+ window.open(value.url(), '_blank');
179
+ }}
180
+ />
181
+ );
182
+ }
183
+ });
184
+ this.register({
185
+ matches: (type) => type instanceof BooleanType,
186
+ encode: async (value: boolean) => value,
187
+ decode: async (value: boolean) => value,
188
+ generateField: ({ label, name }) => {
189
+ return new BooleanInput({
190
+ name,
191
+ label
192
+ });
193
+ },
194
+ generateDisplay: ({ value, type, name, model }) => {
195
+ return (
196
+ <CheckboxWidget
197
+ checked={value}
198
+ onChange={(checked) => {
199
+ model.set(name, checked);
200
+ }}
201
+ />
202
+ );
203
+ }
204
+ });
205
+
206
+ this.register({
207
+ matches: (type) => type instanceof NumberType,
208
+ encode: async (value: number) => value,
209
+ decode: async (value: number) => value,
210
+ generateField: ({ label, name }) => {
211
+ return new NumberInput({
212
+ name,
213
+ label
214
+ });
215
+ },
216
+ generateDisplay: ({ value, type, name, model }) => {
217
+ return `${value}`;
218
+ }
219
+ });
220
+
221
+ this.register<TextType, string, string>({
222
+ matches: (type) => type instanceof TextType,
223
+ encode: async (value: string) => value,
224
+ decode: async (value: string) => value,
225
+ generateField: ({ label, name, type }) => {
226
+ if (type.subType == 'paragraph') {
227
+ return new TextAreaInput({
228
+ name,
229
+ label
230
+ });
231
+ }
232
+
233
+ if (type.subType == 'password') {
234
+ return new TextInput({
235
+ name,
236
+ label,
237
+ inputType: TextInputType.PASSWORD
238
+ });
239
+ }
240
+
241
+ return new TextInput({
242
+ name,
243
+ label
244
+ });
245
+ },
246
+ generateDisplay: ({ value, type, name, model }) => {
247
+ if (value.trim() === '') {
248
+ return <S.Empty>empty</S.Empty>;
249
+ }
250
+
251
+ if (type.subType == 'password') {
252
+ return '****';
253
+ }
254
+
255
+ if (type.subType == 'paragraph') {
256
+ // could be JSON
257
+ if ((value.startsWith('[') && value.endsWith(']')) || (value.startsWith('{') && value.endsWith('}'))) {
258
+ try {
259
+ let parsed = JSON.parse(value);
260
+
261
+ return (
262
+ <TableButtonWidget
263
+ icon="code"
264
+ label="JSON"
265
+ action={() => {
266
+ this.workspaceStore.addModel(
267
+ new ModelJsonPanelModel({
268
+ definition: model.definition,
269
+ model: model,
270
+ field: name
271
+ })
272
+ );
273
+ }}
274
+ />
275
+ );
276
+ } catch (ex) {}
277
+ }
278
+ }
279
+
280
+ if (type.subType == 'url') {
281
+ return (
282
+ <S.Container>
283
+ {value}
284
+ <TableButtonWidget
285
+ icon="arrow-right"
286
+ action={() => {
287
+ window.open(value, '_blank');
288
+ }}
289
+ />
290
+ </S.Container>
291
+ );
292
+ }
293
+
294
+ return <S.Max>{value}</S.Max>;
295
+ }
296
+ });
297
+ this.register({
298
+ matches: (type) => type instanceof LocationType,
299
+ encode: async (value: Location) => value,
300
+ decode: async (value: Location) => value,
301
+ generateField: ({ label, name }) => {
302
+ return new LocationInput({
303
+ name,
304
+ label
305
+ });
306
+ },
307
+ generateDisplay: ({ value }) => {
308
+ return (
309
+ <>
310
+ <MetadataWidget label={'Lat'} value={`${value.latitude}`} />
311
+ <MetadataWidget label={'Long'} value={`${value.longitude}`} />
312
+ </>
313
+ );
314
+ }
315
+ });
316
+
317
+ this.register({
318
+ matches: (type) => type instanceof SingleChoiceIntegerType,
319
+ encode: async (value: string) => parseInt(value),
320
+ decode: async (value: number) => `${value}`,
321
+ generateField: ({ label, name, type }) => {
322
+ return new SelectInput({
323
+ name,
324
+ label,
325
+ options: _.mapValues(type.options, (o) => `${o.value}`)
326
+ });
327
+ },
328
+ generateDisplay: ({ value, type, name, model, label }) => {
329
+ return `${value}`;
330
+ }
331
+ });
332
+
333
+ this.register({
334
+ matches: (type) => type instanceof SingleChoiceType,
335
+ encode: async (value: string) => value,
336
+ decode: async (value: string) => value,
337
+ generateField: ({ label, name, type }) => {
338
+ return new SelectInput({
339
+ name,
340
+ label,
341
+ options: _.mapValues(type.options, (o) => `${o.value}`)
342
+ });
343
+ },
344
+ generateDisplay: ({ value }) => {
345
+ return value;
346
+ }
347
+ });
348
+
349
+ this.register({
350
+ matches: (type) => type instanceof MultipleChoiceType,
351
+ encode: async (value: string[]) => value,
352
+ decode: async (value: string[]) => value,
353
+ generateField: ({ label, name, type }) => {
354
+ return new MultiSelectInput({
355
+ name,
356
+ label,
357
+ options: _.mapValues(type.options, (o) => `${o.value}`)
358
+ });
359
+ },
360
+ generateDisplay: ({ value }) => {
361
+ return this.displayArray(value);
362
+ }
363
+ });
364
+
365
+ this.register({
366
+ matches: (type) => type instanceof MultipleChoiceIntegerType,
367
+ encode: async (value: string[]) => value.map((v) => parseInt(v)),
368
+ decode: async (value: number[]) => value.map((v) => `${v}`),
369
+ generateField: ({ label, name, type }) => {
370
+ return new MultiSelectInput({
371
+ name,
372
+ label,
373
+ options: _.mapValues(type.options, (o) => `${o.value}`)
374
+ });
375
+ },
376
+ generateDisplay: ({ value }) => {
377
+ return this.displayArray(value);
378
+ }
379
+ });
380
+ }
381
+
382
+ displayArray(value: any[]) {
383
+ if (value.length === 0) {
384
+ return <S.Empty>empty array</S.Empty>;
385
+ }
386
+ let items = _.slice(value, 0, MAX_NUMBER_OF_ARR_ITEMS_TO_DISPLAY);
387
+ return (
388
+ <S.Pills>
389
+ {items.map((c) => {
390
+ return <S.pill key={c}>{c}</S.pill>;
391
+ })}
392
+ {items.length !== value.length ? '...' : null}
393
+ </S.Pills>
394
+ );
395
+ }
396
+
397
+ getHandler(type: Type) {
398
+ for (let handler of this.handlers) {
399
+ if (handler.matches(type)) {
400
+ return handler;
401
+ }
402
+ }
403
+ return null;
404
+ }
405
+
406
+ register<T extends Type = Type, ENCODED = any, DECODED = any>(handler: TypeHandler<T, ENCODED, DECODED>) {
407
+ this.handlers.add(handler);
408
+ }
409
+ }
410
+
411
+ namespace S {
412
+ export const Preview = styled.img`
413
+ max-height: 40px;
414
+ max-width: 40px;
415
+ cursor: pointer;
416
+ `;
417
+
418
+ export const Empty = styled.div`
419
+ opacity: 0.2;
420
+ `;
421
+
422
+ export const Max = styled.div`
423
+ max-width: 500px;
424
+ white-space: pre;
425
+ display: inline;
426
+ overflow: hidden;
427
+ text-overflow: ellipsis;
428
+ `;
429
+
430
+ export const Container = styled.div`
431
+ display: flex;
432
+ flex-direction: row;
433
+ column-gap: 5px;
434
+ align-items: center;
435
+ justify-content: space-between;
436
+ flex-grow: 1;
437
+ `;
438
+
439
+ export const pill = styled.div`
440
+ padding: 2px 4px;
441
+ background: ${(p) => p.theme.table.pills};
442
+ border-radius: 3px;
443
+ font-size: 12px;
444
+ `;
445
+
446
+ export const Pills = styled.div`
447
+ display: flex;
448
+ column-gap: 2px;
449
+ row-gap: 2px;
450
+ `;
451
+ }
@@ -29,6 +29,12 @@ export class DirtyWrapperInput extends FormInput {
29
29
  }
30
30
  }
31
31
 
32
+ clear() {
33
+ if (this.object) {
34
+ this.object.set(this.input.name, null);
35
+ }
36
+ }
37
+
32
38
  @computed get dirty() {
33
39
  return this.object?.patch.has(this.input.name);
34
40
  }
@@ -54,6 +60,14 @@ export const Wrapper: React.FC<React.PropsWithChildren<WrapperProps>> = observer
54
60
  }}
55
61
  />
56
62
  ) : null}
63
+ {props.input.value != null ? (
64
+ <S.ClearButton
65
+ icon="close"
66
+ onClick={() => {
67
+ props.input.clear();
68
+ }}
69
+ />
70
+ ) : null}
57
71
  </S.Container>
58
72
  );
59
73
  });
@@ -72,4 +86,10 @@ namespace S {
72
86
  padding: 5px;
73
87
  cursor: pointer;
74
88
  `;
89
+ export const ClearButton = styled(FontAwesomeIcon)`
90
+ color: ${(p) => p.theme.text.secondary};
91
+ font-size: 12px;
92
+ padding: 5px;
93
+ cursor: pointer;
94
+ `;
75
95
  }
@@ -21,12 +21,12 @@ export class LocationInput extends FormInput<FormInputGenerics & { VALUE: Locati
21
21
  this.latitude = new NumberInput({
22
22
  name: 'latitude',
23
23
  label: 'Latitude',
24
- value: options.value?.latitude
24
+ value: options.value?.latitude || null
25
25
  });
26
26
  this.longitude = new NumberInput({
27
27
  name: 'longitude',
28
28
  label: 'Longitude',
29
- value: options.value?.longitude
29
+ value: options.value?.longitude || null
30
30
  });
31
31
 
32
32
  this.update();
@@ -42,19 +42,26 @@ export class LocationInput extends FormInput<FormInputGenerics & { VALUE: Locati
42
42
 
43
43
  setValue(value: Location) {
44
44
  super.setValue(value);
45
- if (this.latitude.value !== value?.latitude) {
46
- this.latitude.setValue(value?.latitude);
45
+
46
+ let lat = value?.latitude || null;
47
+ let lon = value?.longitude || null;
48
+
49
+ if (this.latitude.value !== lat) {
50
+ this.latitude.setValue(lat);
47
51
  }
48
- if (this.longitude.value !== value?.longitude) {
49
- this.longitude.setValue(value?.longitude);
52
+ if (this.longitude.value !== lon) {
53
+ this.longitude.setValue(lon);
50
54
  }
51
55
  }
52
56
 
53
57
  update() {
54
58
  let lat = this.latitude.value;
55
59
  let long = this.longitude.value;
56
- if (lat == null || long === null) {
60
+ if (lat == null && long === null) {
57
61
  this.setValue(null);
62
+ this.setError(null);
63
+ } else if (lat == null || long === null) {
64
+ this.setError('Invalid location');
58
65
  } else {
59
66
  this.setValue(
60
67
  new Location({
package/src/index.ts CHANGED
@@ -10,18 +10,24 @@ export * from './core/query/AbstractQuery';
10
10
  export * from './core/query/Page';
11
11
  export * from './core/types/ManualConnectionFactory';
12
12
  export * from './core/types/ManualConnection';
13
+
13
14
  export * from './entities/QueryEntityDefinition';
14
15
  export * from './entities/ConnectionEntityDefinition';
15
16
  export * from './entities/ConnectionFactoryEntityDefinition';
16
17
  export * from './entities/SchemaModelDefinitionEntityDefinition';
17
18
  export * from './entities/SchemaModelObjectEntityDefinition';
19
+
18
20
  export * from './panels/query/QueryPanelFactory';
19
21
  export * from './panels/model/ModelPanelFactory';
22
+ export * from './panels/_shared/SharedModelPanelFactory';
23
+
20
24
  export * from './stores/ConnectionStore';
25
+
21
26
  export * from './actions/connections/AddConnectionAction';
22
27
  export * from './actions/connections/RemoveConnectionAction';
23
28
  export * from './actions/schema-definitions/CreateModelAction';
24
29
  export * from './actions/schema-definitions/QuerySchemaModelAction';
25
30
  export * from './actions/schema-model/EditSchemaModelAction';
31
+ export * from './actions/schema-model/EditSchemaModelAction';
26
32
 
27
33
  export default DataBrowserModule;
@@ -0,0 +1,54 @@
1
+ import { inject, ReactorPanelFactory, ReactorPanelModel } from '@journeyapps-labs/reactor-mod';
2
+ import { ConnectionStore } from '../../stores/ConnectionStore';
3
+ import { observable } from 'mobx';
4
+ import { SchemaModelDefinition } from '../../core/SchemaModelDefinition';
5
+ import { SchemaModelObject } from '../../core/SchemaModelObject';
6
+
7
+ export interface SharedModelPanelModelOptions {
8
+ definition: SchemaModelDefinition;
9
+ model: SchemaModelObject;
10
+ }
11
+
12
+ export class SharedModelPanelModel extends ReactorPanelModel {
13
+ @inject(ConnectionStore)
14
+ accessor connStore: ConnectionStore;
15
+
16
+ @observable
17
+ accessor definition: SchemaModelDefinition;
18
+
19
+ @observable
20
+ accessor model: SchemaModelObject;
21
+
22
+ constructor(type: string, options?: SharedModelPanelModelOptions) {
23
+ super(type);
24
+ this.setExpand(false, true);
25
+ this.definition = options?.definition;
26
+ this.model = options?.model;
27
+ }
28
+
29
+ encodeEntities() {
30
+ return {
31
+ definition: this.definition,
32
+ model: this.model?.model ? this.model : null
33
+ };
34
+ }
35
+
36
+ async decodeEntities(data: ReturnType<this['encodeEntities']>) {
37
+ this.definition = data.definition;
38
+ this.model = data.model || (await data.definition.generateNewModelObject());
39
+ }
40
+ }
41
+
42
+ export abstract class SharedModelPanelFactory<T extends SharedModelPanelModel> extends ReactorPanelFactory<T> {
43
+ getSimpleName(model: T) {
44
+ let _model = model.model;
45
+ let _definition = model.definition;
46
+ if (!_definition) {
47
+ return super.getSimpleName(model);
48
+ }
49
+ if (_model) {
50
+ return `${_definition.definition.label}: ${_model.data?.display || '(new object)'}`;
51
+ }
52
+ return `${_definition.definition.label}`;
53
+ }
54
+ }
@@ -1,48 +1,19 @@
1
1
  import * as React from 'react';
2
- import { inject, ReactorPanelFactory, ReactorPanelModel } from '@journeyapps-labs/reactor-mod';
3
2
  import { ModelPanelWidget } from './ModelPanelWidget';
4
- import { ConnectionStore } from '../../stores/ConnectionStore';
5
- import { observable } from 'mobx';
6
3
  import { WorkspaceModelFactoryEvent } from '@projectstorm/react-workspaces-core';
7
- import { SchemaModelDefinition } from '../../core/SchemaModelDefinition';
8
- import { SchemaModelObject } from '../../core/SchemaModelObject';
9
-
10
- export interface ModelPanelModelOptions {
11
- definition: SchemaModelDefinition;
12
- model: SchemaModelObject;
13
- }
14
-
15
- export class ModelPanelModel extends ReactorPanelModel {
16
- @inject(ConnectionStore)
17
- accessor connStore: ConnectionStore;
18
-
19
- @observable
20
- accessor definition: SchemaModelDefinition;
21
-
22
- @observable
23
- accessor model: SchemaModelObject;
24
-
25
- constructor(options?: ModelPanelModelOptions) {
26
- super(ModelPanelFactory.TYPE);
27
- this.setExpand(false, true);
28
- this.definition = options?.definition;
29
- this.model = options?.model;
30
- }
31
-
32
- encodeEntities() {
33
- return {
34
- definition: this.definition,
35
- model: this.model?.model ? this.model : null
36
- };
37
- }
38
-
39
- async decodeEntities(data: ReturnType<this['encodeEntities']>) {
40
- this.definition = data.definition;
41
- this.model = data.model || (await data.definition.generateNewModelObject());
4
+ import {
5
+ SharedModelPanelFactory,
6
+ SharedModelPanelModel,
7
+ SharedModelPanelModelOptions
8
+ } from '../_shared/SharedModelPanelFactory';
9
+
10
+ export class ModelPanelModel extends SharedModelPanelModel {
11
+ constructor(options?: SharedModelPanelModelOptions) {
12
+ super(ModelPanelFactory.TYPE, options);
42
13
  }
43
14
  }
44
15
 
45
- export class ModelPanelFactory extends ReactorPanelFactory<ModelPanelModel> {
16
+ export class ModelPanelFactory extends SharedModelPanelFactory<ModelPanelModel> {
46
17
  static TYPE = 'databrowser/model';
47
18
 
48
19
  constructor() {
@@ -58,18 +29,6 @@ export class ModelPanelFactory extends ReactorPanelFactory<ModelPanelModel> {
58
29
  });
59
30
  }
60
31
 
61
- getSimpleName(model: ModelPanelModel) {
62
- let _model = model.model;
63
- let _definition = model.definition;
64
- if (!_definition) {
65
- return super.getSimpleName(model);
66
- }
67
- if (_model) {
68
- return `${_definition.definition.label}: ${_model.data?.display || '(new object)'}`;
69
- }
70
- return `${_definition.definition.label}`;
71
- }
72
-
73
32
  _generateModel(): ModelPanelModel {
74
33
  return new ModelPanelModel(null);
75
34
  }