@journeyapps-labs/reactor-mod-data-browser 3.1.2 → 3.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@journeyapps-labs/reactor-mod-data-browser",
3
- "version": "3.1.2",
3
+ "version": "3.2.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.0.2",
25
- "@journeyapps-labs/reactor-mod-editor": "2.0.2",
24
+ "@journeyapps-labs/reactor-mod": "5.1.0",
25
+ "@journeyapps-labs/reactor-mod-editor": "2.1.0",
26
26
  "@journeyapps/db": "^8.1.1",
27
27
  "@journeyapps/parser-schema": "^8.2.5",
28
28
  "@projectstorm/react-workspaces-core": "4.2.3",
@@ -15,6 +15,7 @@ import { buildSimpleQueryColumns } from './SimpleQueryColumns';
15
15
  import { SimpleQuerySortState } from './SimpleQuerySortState';
16
16
  import { SimpleQueryFilterState } from './SimpleQueryFilterState';
17
17
  import { AbstractQuery } from '../AbstractQuery';
18
+ import { StandardModelFields } from '../StandardModelFields';
18
19
  import * as _ from 'lodash';
19
20
 
20
21
  export interface SimpleQueryOptions {
@@ -81,6 +82,12 @@ export class SimpleQuery extends AbstractSerializableQuery<SimpleQueryEncoded> {
81
82
  onStateChange();
82
83
  }
83
84
  });
85
+
86
+ // Some code paths construct a shell query (no definition) before deserialize/hydration.
87
+ // Only seed the default sort once a definition exists to avoid premature load() calls.
88
+ if (options.definition && this.sortState.sorts.length === 0) {
89
+ this.sortState.addSort(SimpleQuerySort.create(StandardModelFields.UPDATED_AT, SortDirection.DESC));
90
+ }
84
91
  }
85
92
 
86
93
  matches(query: AbstractQuery): boolean {
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { useEffect, useRef } from 'react';
2
3
  import { Page } from '../../core/query/Page';
3
4
  import { themed, ioc, ScrollableDivCss, System, TableWidget, LoadingPanelWidget } from '@journeyapps-labs/reactor-mod';
4
5
  import { AbstractQuery } from '../../core/query/AbstractQuery';
@@ -9,14 +10,39 @@ import { SchemaModelObject } from '../../core/SchemaModelObject';
9
10
  export interface PageResultsWidgetProps {
10
11
  page: Page;
11
12
  query: AbstractQuery;
13
+ scrollTop: number;
14
+ scrollLeft: number;
15
+ onScroll: (offsets: { top: number; left: number }) => void;
12
16
  }
13
17
 
14
18
  export const PageResultsWidget: React.FC<PageResultsWidgetProps> = observer((props) => {
15
19
  const system = ioc.get(System);
16
20
  const rows = props.page.loading ? [] : props.page.asRows();
21
+ const ref = useRef<HTMLDivElement>(null);
22
+
23
+ useEffect(() => {
24
+ if (!ref.current) {
25
+ return;
26
+ }
27
+ if (ref.current.scrollTop !== props.scrollTop) {
28
+ ref.current.scrollTop = props.scrollTop;
29
+ }
30
+ if (ref.current.scrollLeft !== props.scrollLeft) {
31
+ ref.current.scrollLeft = props.scrollLeft;
32
+ }
33
+ }, [props.scrollLeft, props.scrollTop]);
17
34
 
18
35
  return (
19
- <S.Container>
36
+ <S.Container
37
+ ref={ref}
38
+ onScroll={(event) => {
39
+ const target = event.currentTarget;
40
+ props.onScroll({
41
+ top: target.scrollTop,
42
+ left: target.scrollLeft
43
+ });
44
+ }}
45
+ >
20
46
  <TableWidget
21
47
  onContextMenu={(event, row) => {
22
48
  system
@@ -9,6 +9,7 @@ import { AbstractSerializableQuery } from '../../core/query/AbstractSerializable
9
9
  import { SavedQueryStore } from '../../stores/SavedQueryStore';
10
10
  import { AbstractConnection } from '../../core/AbstractConnection';
11
11
  import { SharedConnectionPanelFactory } from '../_shared/SharedConnectionPanelFactory';
12
+ import { Page } from '../../core/query/Page';
12
13
 
13
14
  export class QueryPanelModel extends ReactorPanelModel {
14
15
  @inject(ConnectionStore)
@@ -20,11 +21,20 @@ export class QueryPanelModel extends ReactorPanelModel {
20
21
  @observable
21
22
  accessor current_page: number;
22
23
 
24
+ @observable.ref
25
+ accessor current_page_data: Page | null;
26
+
27
+ accessor table_scroll_top: number;
28
+ accessor table_scroll_left: number;
29
+
23
30
  constructor(query: AbstractQuery) {
24
31
  super(QueryPanelFactory.TYPE);
25
32
  this.setExpand(true, true);
26
33
  this.query = query;
27
34
  this.current_page = 0;
35
+ this.current_page_data = null;
36
+ this.table_scroll_top = 0;
37
+ this.table_scroll_left = 0;
28
38
  }
29
39
 
30
40
  isSerializable() {
@@ -51,6 +61,7 @@ export class QueryPanelModel extends ReactorPanelModel {
51
61
 
52
62
  decodeEntities(data: ReturnType<this['encodeEntities']>) {
53
63
  this.query = data.query;
64
+ this.current_page_data = null;
54
65
  }
55
66
 
56
67
  async loadSavedQuery(id: string): Promise<void> {
@@ -59,6 +70,7 @@ export class QueryPanelModel extends ReactorPanelModel {
59
70
  return;
60
71
  }
61
72
  this.current_page = 0;
73
+ this.current_page_data = null;
62
74
  this.query = query;
63
75
  await query.load();
64
76
  }
@@ -22,28 +22,34 @@ namespace S {
22
22
  }
23
23
 
24
24
  export const QueryPanelWidget: React.FC<QueryPanelWidgetProps> = observer((props) => {
25
- const [displayPage, setDisplayPage] = useState<Page>(null);
26
25
  const [loading, setLoading] = useState(false);
27
- const displayPageRef = useRef<Page>(null);
28
26
  const pendingDisposerRef = useRef<() => void>(null);
29
27
 
30
28
  const setVisiblePage = (page: Page) => {
31
- displayPageRef.current = page;
32
- setDisplayPage(page);
29
+ props.model.current_page_data = page;
33
30
  };
34
31
 
35
32
  useEffect(() => {
36
- if (!props.model.query) {
37
- return;
38
- }
39
- props.model.query.load();
40
- }, [props.model.query]);
33
+ return autorun(() => {
34
+ const query = props.model.query;
35
+ if (!query) {
36
+ return;
37
+ }
38
+ if (props.model.current_page_data) {
39
+ return;
40
+ }
41
+ if (query.totalPages !== 0) {
42
+ return;
43
+ }
44
+ void query.load();
45
+ });
46
+ }, [props.model]);
41
47
 
42
48
  useEffect(() => {
43
49
  return autorun(() => {
44
50
  if (props.model.query) {
45
51
  const nextPage = props.model.query.getPage(props.model.current_page);
46
- const currentPage = displayPageRef.current;
52
+ const currentPage = props.model.current_page_data;
47
53
 
48
54
  if (!currentPage) {
49
55
  setVisiblePage(nextPage);
@@ -76,7 +82,7 @@ export const QueryPanelWidget: React.FC<QueryPanelWidgetProps> = observer((props
76
82
  });
77
83
  }
78
84
  });
79
- }, [props.model.query]);
85
+ }, [props.model]);
80
86
 
81
87
  useEffect(() => {
82
88
  return () => {
@@ -85,7 +91,8 @@ export const QueryPanelWidget: React.FC<QueryPanelWidgetProps> = observer((props
85
91
  };
86
92
  }, []);
87
93
 
88
- const activePage = displayPage || (props.model.query ? props.model.query.getPage(props.model.current_page) : null);
94
+ const activePage =
95
+ props.model.current_page_data || (props.model.query ? props.model.query.getPage(props.model.current_page) : null);
89
96
 
90
97
  return (
91
98
  <LoadingPanelWidget loading={!props.model.query || !activePage}>
@@ -120,7 +127,16 @@ export const QueryPanelWidget: React.FC<QueryPanelWidgetProps> = observer((props
120
127
  />
121
128
  }
122
129
  >
123
- <PageResultsWidget query={props.model.query} page={activePage} />
130
+ <PageResultsWidget
131
+ query={props.model.query}
132
+ page={activePage}
133
+ scrollTop={props.model.table_scroll_top}
134
+ scrollLeft={props.model.table_scroll_left}
135
+ onScroll={({ top, left }) => {
136
+ props.model.table_scroll_top = top;
137
+ props.model.table_scroll_left = left;
138
+ }}
139
+ />
124
140
  </BorderLayoutWidget>
125
141
  </S.Container>
126
142
  );