@journeyapps-labs/reactor-mod-data-browser 3.2.0 → 3.3.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 (33) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/@types/core/AbstractConnection.d.ts +12 -0
  3. package/dist/@types/core/query/widgets/SmartColumnWidget.d.ts +1 -1
  4. package/dist/@types/core/types/ManualConnection.d.ts +1 -0
  5. package/dist/@types/entities/ConnectionEntityDefinition.d.ts +2 -1
  6. package/dist/@types/forms/types/shared/ui.d.ts +12 -0
  7. package/dist/@types/panels/query/QueryPanelFactory.d.ts +2 -2
  8. package/dist/core/AbstractConnection.js +58 -5
  9. package/dist/core/AbstractConnection.js.map +1 -1
  10. package/dist/core/query/query-simple/SimpleQueryColumns.js +1 -1
  11. package/dist/core/query/widgets/SmartColumnWidget.js +4 -1
  12. package/dist/core/query/widgets/SmartColumnWidget.js.map +1 -1
  13. package/dist/core/types/ManualConnection.js +3 -0
  14. package/dist/core/types/ManualConnection.js.map +1 -1
  15. package/dist/entities/ConnectionEntityDefinition.js +29 -6
  16. package/dist/entities/ConnectionEntityDefinition.js.map +1 -1
  17. package/dist/panels/model-json/ModelJsonPanelWidget.js +4 -3
  18. package/dist/panels/model-json/ModelJsonPanelWidget.js.map +1 -1
  19. package/dist/panels/query/QueryPanelFactory.js.map +1 -1
  20. package/dist/stores/ConnectionStore.js +15 -3
  21. package/dist/stores/ConnectionStore.js.map +1 -1
  22. package/dist/tsconfig.tsbuildinfo +1 -1
  23. package/dist-module/bundle.js +34 -34
  24. package/dist-module/bundle.js.map +1 -1
  25. package/package.json +4 -4
  26. package/src/core/AbstractConnection.ts +45 -2
  27. package/src/core/query/query-simple/SimpleQueryColumns.tsx +1 -1
  28. package/src/core/query/widgets/SmartColumnWidget.tsx +6 -5
  29. package/src/core/types/ManualConnection.ts +4 -0
  30. package/src/entities/ConnectionEntityDefinition.tsx +32 -4
  31. package/src/panels/model-json/ModelJsonPanelWidget.tsx +8 -6
  32. package/src/panels/query/QueryPanelFactory.tsx +2 -2
  33. package/src/stores/ConnectionStore.ts +17 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@journeyapps-labs/reactor-mod-data-browser",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "main": "./dist/index.js",
5
5
  "typings": "./dist/@types/index",
6
6
  "publishConfig": {
@@ -21,8 +21,8 @@
21
21
  "@journeyapps-labs/common-sdk": "^1.0.3",
22
22
  "@journeyapps-labs/common-utils": "^1.0.1",
23
23
  "@journeyapps-labs/lib-reactor-data-layer": "1.0.10",
24
- "@journeyapps-labs/reactor-mod": "5.1.0",
25
- "@journeyapps-labs/reactor-mod-editor": "2.1.0",
24
+ "@journeyapps-labs/reactor-mod": "5.3.1",
25
+ "@journeyapps-labs/reactor-mod-editor": "2.2.1",
26
26
  "@journeyapps/db": "^8.1.1",
27
27
  "@journeyapps/parser-schema": "^8.2.5",
28
28
  "@projectstorm/react-workspaces-core": "4.2.3",
@@ -34,7 +34,7 @@
34
34
  "uuid": "^13.0.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@journeyapps-labs/lib-reactor-builder": "2.0.5",
37
+ "@journeyapps-labs/lib-reactor-builder": "3.0.1",
38
38
  "@types/async": "^3.2.25",
39
39
  "@types/lodash": "^4.17.24",
40
40
  "@types/react": "^19.2.14",
@@ -7,7 +7,7 @@ import { v4 } from 'uuid';
7
7
  import { BaseObserver } from '@journeyapps-labs/common-utils';
8
8
  import { Collection, LifecycleCollection } from '@journeyapps-labs/lib-reactor-data-layer';
9
9
  import { when } from 'mobx';
10
- import { observable } from 'mobx';
10
+ import { computed, observable } from 'mobx';
11
11
  import { EntityDescription } from '@journeyapps-labs/reactor-mod';
12
12
  import { V4BackendClient, V4Index, V4Indexes } from '@journeyapps-labs/client-backend-v4';
13
13
  import { SchemaModelObject } from './SchemaModelObject';
@@ -24,18 +24,27 @@ export interface AbstractConnectionListener {
24
24
  removed: () => any;
25
25
  }
26
26
 
27
+ export enum ConnectionOnlineState {
28
+ OFFLINE = 'offline',
29
+ LOADING = 'loading',
30
+ ONLINE = 'online'
31
+ }
32
+
27
33
  export abstract class AbstractConnection extends BaseObserver<AbstractConnectionListener> {
28
34
  id: string;
29
35
  @observable accessor color: string;
36
+ @observable accessor onlineState: ConnectionOnlineState;
30
37
 
31
38
  schema_models_collection: Collection<ObjectType>;
32
39
  schema_models: LifecycleCollection<ObjectType, SchemaModelDefinition>;
33
40
  private fetch_indexes_promise: Promise<V4Indexes['models']>;
41
+ private initialize_online_promise: Promise<void>;
34
42
 
35
43
  constructor(public factory: AbstractConnectionFactory) {
36
44
  super();
37
45
  this.id = v4();
38
46
  this.color = getDefaultConnectionColor(this.id);
47
+ this.onlineState = ConnectionOnlineState.OFFLINE;
39
48
  this.schema_models_collection = new Collection();
40
49
  this.schema_models = new LifecycleCollection({
41
50
  collection: this.schema_models_collection,
@@ -88,7 +97,16 @@ export abstract class AbstractConnection extends BaseObserver<AbstractConnection
88
97
  return this.schema_models.items.find((i) => i.definition.name === name);
89
98
  }
90
99
 
100
+ @computed get isOnline() {
101
+ return this.onlineState === ConnectionOnlineState.ONLINE;
102
+ }
103
+
104
+ @computed get isLoadingOnline() {
105
+ return this.onlineState === ConnectionOnlineState.LOADING;
106
+ }
107
+
91
108
  async waitForSchemaModelDefinitionByName(name: string) {
109
+ await this.ensureOnline();
92
110
  await when(() => !!this.getSchemaModelDefinitionByName(name));
93
111
  return this.getSchemaModelDefinitionByName(name);
94
112
  }
@@ -107,10 +125,35 @@ export abstract class AbstractConnection extends BaseObserver<AbstractConnection
107
125
  });
108
126
  }
109
127
 
110
- async init() {
128
+ async init() {}
129
+
130
+ protected async connectOnline() {
111
131
  await this.reload();
112
132
  }
113
133
 
134
+ async ensureOnline() {
135
+ if (this.isOnline) {
136
+ return;
137
+ }
138
+ if (!this.initialize_online_promise) {
139
+ this.initialize_online_promise = this.initializeOnline();
140
+ }
141
+ await this.initialize_online_promise;
142
+ }
143
+
144
+ private async initializeOnline() {
145
+ this.onlineState = ConnectionOnlineState.LOADING;
146
+ try {
147
+ await this.connectOnline();
148
+ this.onlineState = ConnectionOnlineState.ONLINE;
149
+ } finally {
150
+ if (this.onlineState === ConnectionOnlineState.LOADING) {
151
+ this.onlineState = ConnectionOnlineState.OFFLINE;
152
+ }
153
+ this.initialize_online_promise = null;
154
+ }
155
+ }
156
+
114
157
  protected async getSchemaModelDefinitions() {
115
158
  const schema = await this.getSchema();
116
159
  return _.map(schema.objects, (o) => {
@@ -27,7 +27,7 @@ export const buildSimpleQueryColumns = (options: BuildSimpleQueryColumnsOptions)
27
27
  if (!direction) {
28
28
  return label;
29
29
  }
30
- return `${label} ${direction === SortDirection.ASC ? '' : ''}`;
30
+ return `${label} ${direction === SortDirection.ASC ? '' : ''}`;
31
31
  };
32
32
 
33
33
  return [
@@ -1,11 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import styled from '@emotion/styled';
3
- import { ObjectType, Type, Variable } from '@journeyapps/db';
3
+ import { ObjectType, Variable } from '@journeyapps/db';
4
4
  import { ColumnDisplayWidget } from './ColumnDisplayWidget';
5
- import { SmartFilterMetadataWidget, SmartFilterWidget } from './SmartFilterWidget';
5
+ import { SmartFilterWidget } from './SmartFilterWidget';
6
6
  import { SimpleFilter } from '../filters';
7
- import { PanelTitleToolbarButtonWidget } from '@journeyapps-labs/reactor-mod';
8
- import type { SortDirection } from '../query-simple/SimpleQuery';
7
+ import { SortDirection } from '../query-simple/SimpleQuery';
9
8
 
10
9
  export interface SmartColumnWidgetProps {
11
10
  variable: Variable;
@@ -18,7 +17,9 @@ export interface SmartColumnWidgetProps {
18
17
 
19
18
  export const SmartColumnWidget: React.FC<SmartColumnWidgetProps> = (props) => {
20
19
  const baseLabel = props.variable.label || props.variable.name;
21
- const displayLabel = props.sortDirection ? `${baseLabel} ${props.sortDirection === 'asc' ? '↑' : '↓'}` : baseLabel;
20
+ const displayLabel = props.sortDirection
21
+ ? `${baseLabel} ${props.sortDirection === SortDirection.ASC ? '↓' : '↑'}`
22
+ : baseLabel;
22
23
  let display = <ColumnDisplayWidget label={displayLabel} onClick={props.onToggleSort} />;
23
24
  if (props.type) {
24
25
  display = (
@@ -22,6 +22,10 @@ export class ManualConnection extends AbstractConnection {
22
22
  return Database.instance(this.options);
23
23
  }
24
24
 
25
+ async init() {
26
+ await this.ensureOnline();
27
+ }
28
+
25
29
  _serialize(): ManualConnectionDetails {
26
30
  return this.options;
27
31
  }
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  DescendantEntityProviderComponent,
3
+ DescendantLoadingEntityProviderComponent,
3
4
  EntityCardsPresenterComponent,
4
5
  EntityDefinition,
5
6
  EntityDescriberComponent,
@@ -7,13 +8,17 @@ import {
7
8
  inject,
8
9
  InlineTreePresenterComponent,
9
10
  SearchableTreeSearchScope,
10
- SimpleEntitySearchEngineComponent
11
+ SimpleEntitySearchEngineComponent,
12
+ TreeBadgeWidget,
13
+ ThemeStore
11
14
  } from '@journeyapps-labs/reactor-mod';
15
+ import * as React from 'react';
12
16
  import { DataBrowserEntities } from '../entities';
13
17
  import { ConnectionStore } from '../stores/ConnectionStore';
14
18
  import { AbstractConnection } from '../core/AbstractConnection';
15
19
  import { AddConnectionAction } from '../actions/connections/AddConnectionAction';
16
20
  import { SavedQueryEntity, SavedQueryStore } from '../stores/SavedQueryStore';
21
+ import { SchemaModelDefinition } from '../core/SchemaModelDefinition';
17
22
 
18
23
  export class ConnectionEntityDefinition extends EntityDefinition<AbstractConnection> {
19
24
  @inject(ConnectionStore)
@@ -22,6 +27,9 @@ export class ConnectionEntityDefinition extends EntityDefinition<AbstractConnect
22
27
  @inject(SavedQueryStore)
23
28
  accessor savedQueryStore: SavedQueryStore;
24
29
 
30
+ @inject(ThemeStore)
31
+ accessor themeStore: ThemeStore;
32
+
25
33
  constructor() {
26
34
  super({
27
35
  type: DataBrowserEntities.CONNECTION,
@@ -56,14 +64,30 @@ export class ConnectionEntityDefinition extends EntityDefinition<AbstractConnect
56
64
  new InlineTreePresenterComponent<AbstractConnection>({
57
65
  loadChildrenAsNodesAreOpened: true,
58
66
  cacheTreeEntities: true,
59
- searchScope: SearchableTreeSearchScope.VISIBLE_ONLY
67
+ searchScope: SearchableTreeSearchScope.VISIBLE_ONLY,
68
+ augmentTreeNodeProps: (entity) => {
69
+ if (!entity.isOnline) {
70
+ return {};
71
+ }
72
+ const theme = this.themeStore.getCurrentTheme();
73
+ return {
74
+ rightChildren: (
75
+ <TreeBadgeWidget
76
+ icon="bolt"
77
+ background={'transparent'}
78
+ iconColor={theme.status.success}
79
+ tooltip="Connection online"
80
+ />
81
+ )
82
+ };
83
+ }
60
84
  })
61
85
  );
62
86
 
63
87
  this.registerComponent(new EntityCardsPresenterComponent<AbstractConnection>());
64
88
 
65
89
  this.registerComponent(
66
- new DescendantEntityProviderComponent<AbstractConnection>({
90
+ new DescendantLoadingEntityProviderComponent<AbstractConnection, SchemaModelDefinition>({
67
91
  descendantType: DataBrowserEntities.SCHEMA_MODEL_DEFINITION,
68
92
  generateOptions: (parent) => {
69
93
  return {
@@ -71,7 +95,11 @@ export class ConnectionEntityDefinition extends EntityDefinition<AbstractConnect
71
95
  label: 'Models',
72
96
  icon: 'cube'
73
97
  },
74
- descendants: parent.schema_models.items
98
+ descendants: parent.schema_models.items,
99
+ loading: () => parent.isLoadingOnline,
100
+ refreshDescendants: async () => {
101
+ await parent.ensureOnline();
102
+ }
75
103
  };
76
104
  }
77
105
  })
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
- import { useEffect, useState } from 'react';
2
+ import { JSX, useEffect, useState } from 'react';
3
3
  import { observer } from 'mobx-react';
4
4
  import styled from '@emotion/styled';
5
5
  import { BorderLayoutWidget, LoadingPanelWidget, PanelToolbarWidget } from '@journeyapps-labs/reactor-mod';
6
- import { saveFile, copyTextToClipboard } from '@journeyapps-labs/lib-reactor-utils';
6
+ import { copyTextToClipboard, saveFile } from '@journeyapps-labs/lib-reactor-utils';
7
7
  import { ModelJsonPanelModel } from './ModelJsonPanelFactory';
8
8
  import { SimpleEditorWidget } from '@journeyapps-labs/reactor-mod-editor';
9
9
 
@@ -25,7 +25,7 @@ namespace S {
25
25
  }
26
26
 
27
27
  export const ModelJsonPanelWidget: React.FC<QueryPanelWidgetProps> = observer((props) => {
28
- const [json, setJson] = useState(null);
28
+ const [json, setJson] = useState<string | null>(null);
29
29
 
30
30
  useEffect(() => {
31
31
  if (!props.model?.model?.data) {
@@ -39,8 +39,8 @@ export const ModelJsonPanelWidget: React.FC<QueryPanelWidgetProps> = observer((p
39
39
  }
40
40
  }, [props.model.model?.data]);
41
41
 
42
- let top = null;
43
- if (props.model.model) {
42
+ let top: JSX.Element;
43
+ if (props.model.model && json) {
44
44
  top = (
45
45
  <PanelToolbarWidget
46
46
  btns={[
@@ -67,6 +67,8 @@ export const ModelJsonPanelWidget: React.FC<QueryPanelWidgetProps> = observer((p
67
67
  label: 'ID',
68
68
  value: props.model?.id
69
69
  },
70
+
71
+ // @ts-ignore FIXME, this can take null
70
72
  props.model?.field
71
73
  ? {
72
74
  label: 'Field',
@@ -83,7 +85,7 @@ export const ModelJsonPanelWidget: React.FC<QueryPanelWidgetProps> = observer((p
83
85
  {() => {
84
86
  return (
85
87
  <BorderLayoutWidget top={top}>
86
- <S.SimpleEditor lang="application/json" path={`${props.model.model.id}`} text={json} />
88
+ <S.SimpleEditor lang="application/json" path={`${props.model.model.id}`} text={json!} />
87
89
  </BorderLayoutWidget>
88
90
  );
89
91
  }}
@@ -4,7 +4,7 @@ import { QueryPanelWidget } from './QueryPanelWidget';
4
4
  import { AbstractQuery } from '../../core/query/AbstractQuery';
5
5
  import { ConnectionStore } from '../../stores/ConnectionStore';
6
6
  import { observable } from 'mobx';
7
- import { WorkspaceModelFactoryEvent } from '@projectstorm/react-workspaces-core';
7
+ import { WorkspaceEngine, WorkspaceModelFactoryEvent } from '@projectstorm/react-workspaces-core';
8
8
  import { AbstractSerializableQuery } from '../../core/query/AbstractSerializableQuery';
9
9
  import { SavedQueryStore } from '../../stores/SavedQueryStore';
10
10
  import { AbstractConnection } from '../../core/AbstractConnection';
@@ -48,7 +48,7 @@ export class QueryPanelModel extends ReactorPanelModel {
48
48
  };
49
49
  }
50
50
 
51
- fromArray(data: ReturnType<this['toArray']>, engine) {
51
+ fromArray(data: ReturnType<this['toArray']>, engine: WorkspaceEngine) {
52
52
  super.fromArray(data, engine);
53
53
  this.current_page = data.current_page || 0;
54
54
  }
@@ -1,6 +1,6 @@
1
1
  import { AbstractStore, LocalStorageSerializer } from '@journeyapps-labs/reactor-mod';
2
2
  import { AbstractConnection, AbstractConnectionSerialized } from '../core/AbstractConnection';
3
- import { action, computed, observable, runInAction, when } from 'mobx';
3
+ import { computed, observable, runInAction, when } from 'mobx';
4
4
  import { AbstractConnectionFactory } from '../core/AbstractConnectionFactory';
5
5
  import { getDefaultConnectionColor } from '../core/connection-colors';
6
6
 
@@ -51,9 +51,18 @@ export class ConnectionStore extends AbstractStore<ConnectionStoreSerialized> {
51
51
  }
52
52
 
53
53
  async deserializeConnection(data: AbstractConnectionSerialized) {
54
- let conn = this._connectionFactories.get(data.factory).generateConnection();
54
+ let conn = this._connectionFactories.get(data.factory)?.generateConnection();
55
+ if (!conn) {
56
+ return null;
57
+ }
58
+
55
59
  conn.id = data.id;
56
- await conn._deSerialize(data.payload);
60
+ try {
61
+ await conn._deSerialize(data.payload);
62
+ } catch (ex) {
63
+ this.logger.error(`Failed to deserialize connection: [${conn.id}]`, ex);
64
+ return null;
65
+ }
57
66
  conn.color = data.color || getDefaultConnectionColor(conn.id);
58
67
  return conn;
59
68
  }
@@ -66,9 +75,11 @@ export class ConnectionStore extends AbstractStore<ConnectionStoreSerialized> {
66
75
  return this.deserializeConnection(connSer);
67
76
  })
68
77
  );
69
- connections.forEach((c) => {
70
- this.addConnection(c);
71
- });
78
+ connections
79
+ .filter((c) => !!c)
80
+ .forEach((c) => {
81
+ this.addConnection(c);
82
+ });
72
83
  });
73
84
  }
74
85