@vitessce/vit-s 2.0.3 → 3.0.1
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/dist/index.js +44072 -0
- package/dist-tsc/CallbackPublisher.d.ts +18 -0
- package/dist-tsc/CallbackPublisher.d.ts.map +1 -0
- package/dist-tsc/CallbackPublisher.js +62 -0
- package/dist-tsc/LoadingIndicator.d.ts +2 -0
- package/dist-tsc/LoadingIndicator.d.ts.map +1 -0
- package/dist-tsc/LoadingIndicator.js +26 -0
- package/dist-tsc/TitleInfo.d.ts +2 -0
- package/dist-tsc/TitleInfo.d.ts.map +1 -0
- package/dist-tsc/TitleInfo.js +74 -0
- package/dist-tsc/VitS.d.ts +50 -0
- package/dist-tsc/VitS.d.ts.map +1 -0
- package/dist-tsc/VitS.js +139 -0
- package/dist-tsc/VitessceGrid.d.ts +23 -0
- package/dist-tsc/VitessceGrid.d.ts.map +1 -0
- package/dist-tsc/VitessceGrid.js +63 -0
- package/dist-tsc/VitessceGrid.test.d.ts +2 -0
- package/dist-tsc/VitessceGrid.test.d.ts.map +1 -0
- package/dist-tsc/VitessceGrid.test.js +43 -0
- package/dist-tsc/Warning.d.ts +2 -0
- package/dist-tsc/Warning.d.ts.map +1 -0
- package/dist-tsc/Warning.js +45 -0
- package/dist-tsc/classNames.d.ts +8 -0
- package/dist-tsc/classNames.d.ts.map +1 -0
- package/dist-tsc/classNames.js +8 -0
- package/dist-tsc/data/AbstractLoader.d.ts +22 -0
- package/dist-tsc/data/AbstractLoader.d.ts.map +1 -0
- package/dist-tsc/data/AbstractLoader.js +18 -0
- package/dist-tsc/data/AbstractTwoStepLoader.d.ts +6 -0
- package/dist-tsc/data/AbstractTwoStepLoader.d.ts.map +1 -0
- package/dist-tsc/data/AbstractTwoStepLoader.js +7 -0
- package/dist-tsc/data/LoaderResult.d.ts +12 -0
- package/dist-tsc/data/LoaderResult.d.ts.map +1 -0
- package/dist-tsc/data/LoaderResult.js +12 -0
- package/dist-tsc/data/index.d.ts +4 -0
- package/dist-tsc/data/index.d.ts.map +1 -0
- package/dist-tsc/data/index.js +3 -0
- package/dist-tsc/data/loader-registry.d.ts +9 -0
- package/dist-tsc/data/loader-registry.d.ts.map +1 -0
- package/dist-tsc/data/loader-registry.js +27 -0
- package/dist-tsc/data-hook-utils.d.ts +65 -0
- package/dist-tsc/data-hook-utils.d.ts.map +1 -0
- package/dist-tsc/data-hook-utils.js +191 -0
- package/dist-tsc/data-hooks.d.ts +73 -0
- package/dist-tsc/data-hooks.d.ts.map +1 -0
- package/dist-tsc/data-hooks.js +254 -0
- package/dist-tsc/errors/AbstractLoaderError.d.ts +10 -0
- package/dist-tsc/errors/AbstractLoaderError.d.ts.map +1 -0
- package/dist-tsc/errors/AbstractLoaderError.js +13 -0
- package/dist-tsc/errors/DataSourceFetchError.d.ts +8 -0
- package/dist-tsc/errors/DataSourceFetchError.d.ts.map +1 -0
- package/dist-tsc/errors/DataSourceFetchError.js +13 -0
- package/dist-tsc/errors/DatasetNotFoundError.d.ts +6 -0
- package/dist-tsc/errors/DatasetNotFoundError.d.ts.map +1 -0
- package/dist-tsc/errors/DatasetNotFoundError.js +17 -0
- package/dist-tsc/errors/LoaderNotFoundError.d.ts +10 -0
- package/dist-tsc/errors/LoaderNotFoundError.d.ts.map +1 -0
- package/dist-tsc/errors/LoaderNotFoundError.js +17 -0
- package/dist-tsc/errors/LoaderValidationError.d.ts +10 -0
- package/dist-tsc/errors/LoaderValidationError.d.ts.map +1 -0
- package/dist-tsc/errors/LoaderValidationError.js +15 -0
- package/dist-tsc/errors/index.d.ts +6 -0
- package/dist-tsc/errors/index.d.ts.map +1 -0
- package/dist-tsc/errors/index.js +5 -0
- package/dist-tsc/hooks.d.ts +76 -0
- package/dist-tsc/hooks.d.ts.map +1 -0
- package/dist-tsc/hooks.js +262 -0
- package/dist-tsc/index.d.ts +12 -0
- package/dist-tsc/index.d.ts.map +1 -0
- package/dist-tsc/index.js +11 -17
- package/dist-tsc/mui-utils.d.ts +2 -0
- package/dist-tsc/mui-utils.d.ts.map +1 -0
- package/dist-tsc/mui-utils.js +44 -0
- package/dist-tsc/plugins.test.fixtures.d.ts +61 -0
- package/dist-tsc/plugins.test.fixtures.d.ts.map +1 -0
- package/dist-tsc/plugins.test.fixtures.js +76 -0
- package/dist-tsc/shared-mui/components.d.ts +2 -0
- package/dist-tsc/shared-mui/components.d.ts.map +1 -0
- package/dist-tsc/shared-mui/components.js +29 -0
- package/dist-tsc/shared-mui/container.d.ts +2 -0
- package/dist-tsc/shared-mui/container.d.ts.map +1 -0
- package/dist-tsc/shared-mui/container.js +211 -0
- package/dist-tsc/shared-mui/styles.d.ts +5 -0
- package/dist-tsc/shared-mui/styles.d.ts.map +1 -0
- package/dist-tsc/shared-mui/styles.js +109 -0
- package/dist-tsc/shared-plot-options/CellColorEncodingOption.d.ts +2 -0
- package/dist-tsc/shared-plot-options/CellColorEncodingOption.d.ts.map +1 -0
- package/dist-tsc/shared-plot-options/CellColorEncodingOption.js +17 -0
- package/dist-tsc/shared-plot-options/OptionSelect.d.ts +2 -0
- package/dist-tsc/shared-plot-options/OptionSelect.d.ts.map +1 -0
- package/dist-tsc/shared-plot-options/OptionSelect.js +12 -0
- package/dist-tsc/shared-plot-options/OptionsContainer.d.ts +2 -0
- package/dist-tsc/shared-plot-options/OptionsContainer.d.ts.map +1 -0
- package/dist-tsc/shared-plot-options/OptionsContainer.js +9 -0
- package/dist-tsc/shared-plot-options/index.d.ts +5 -0
- package/dist-tsc/shared-plot-options/index.d.ts.map +1 -0
- package/dist-tsc/shared-plot-options/index.js +4 -0
- package/dist-tsc/shared-plot-options/styles.d.ts +2 -0
- package/dist-tsc/shared-plot-options/styles.d.ts.map +1 -0
- package/dist-tsc/shared-plot-options/styles.js +48 -0
- package/dist-tsc/state/hooks.d.ts +242 -0
- package/dist-tsc/state/hooks.d.ts.map +1 -0
- package/dist-tsc/state/hooks.js +615 -0
- package/dist-tsc/title-styles.d.ts +2 -0
- package/dist-tsc/title-styles.d.ts.map +1 -0
- package/dist-tsc/title-styles.js +72 -0
- package/dist-tsc/view-config-utils.d.ts +31 -0
- package/dist-tsc/view-config-utils.d.ts.map +1 -0
- package/dist-tsc/view-config-utils.js +240 -0
- package/dist-tsc/view-config-utils.test.d.ts +2 -0
- package/dist-tsc/view-config-utils.test.d.ts.map +1 -0
- package/dist-tsc/view-config-utils.test.fixtures.d.ts +1049 -0
- package/dist-tsc/view-config-utils.test.fixtures.d.ts.map +1 -0
- package/dist-tsc/view-config-utils.test.fixtures.js +883 -0
- package/dist-tsc/view-config-utils.test.js +210 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.d.ts +8 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.d.ts.map +1 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.js +114 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.d.ts +2 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.d.ts.map +1 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.js +48 -0
- package/dist-tsc/vitessce-grid-layout/index.d.ts +2 -0
- package/dist-tsc/vitessce-grid-layout/index.d.ts.map +1 -0
- package/dist-tsc/vitessce-grid-layout/index.js +1 -0
- package/dist-tsc/vitessce-grid-layout/layout-utils.d.ts +15 -0
- package/dist-tsc/vitessce-grid-layout/layout-utils.d.ts.map +1 -0
- package/dist-tsc/vitessce-grid-layout/layout-utils.js +61 -0
- package/dist-tsc/vitessce-grid-layout/layout-utils.test.d.ts +2 -0
- package/dist-tsc/vitessce-grid-layout/layout-utils.test.d.ts.map +1 -0
- package/dist-tsc/vitessce-grid-layout/layout-utils.test.js +149 -0
- package/dist-tsc/vitessce-grid-utils.d.ts +13 -0
- package/dist-tsc/vitessce-grid-utils.d.ts.map +1 -0
- package/dist-tsc/vitessce-grid-utils.js +141 -0
- package/package.json +25 -11
- package/src/CallbackPublisher.js +7 -11
- package/src/LoadingIndicator.js +1 -2
- package/src/TitleInfo.js +12 -85
- package/src/VitS.js +143 -85
- package/src/VitessceGrid.js +35 -21
- package/src/VitessceGrid.test.jsx +23 -8
- package/src/Warning.js +4 -4
- package/src/data/AbstractLoader.js +2 -25
- package/src/data/AbstractTwoStepLoader.js +1 -1
- package/src/data/LoaderResult.js +5 -0
- package/src/data/index.js +3 -3
- package/src/data/loader-registry.js +22 -13
- package/src/data-hook-utils.js +119 -86
- package/src/data-hooks.js +150 -131
- package/src/errors/DataSourceFetchError.js +2 -2
- package/src/errors/DatasetNotFoundError.js +1 -1
- package/src/errors/LoaderNotFoundError.js +1 -1
- package/src/errors/LoaderValidationError.js +1 -1
- package/src/errors/index.js +5 -6
- package/src/hooks.js +81 -26
- package/src/index.js +23 -46
- package/src/mui-utils.js +52 -0
- package/src/shared-mui/components.js +10 -8
- package/src/shared-mui/container.js +1 -1
- package/src/shared-mui/styles.js +5 -2
- package/src/shared-plot-options/CellColorEncodingOption.js +3 -4
- package/src/shared-plot-options/OptionSelect.js +3 -3
- package/src/shared-plot-options/OptionsContainer.js +2 -5
- package/src/shared-plot-options/index.js +4 -4
- package/src/shared-plot-options/styles.js +2 -2
- package/src/state/hooks.js +75 -23
- package/src/title-styles.js +73 -0
- package/src/view-config-utils.js +54 -98
- package/src/view-config-utils.test.jsx +223 -0
- package/src/vitessce-grid-layout/VitessceGridLayout.js +51 -30
- package/src/vitessce-grid-layout/VitessceGridLayout.test.jsx +17 -9
- package/src/vitessce-grid-layout/index.js +1 -1
- package/src/vitessce-grid-layout/layout-utils.js +1 -1
- package/src/vitessce-grid-layout/layout-utils.test.js +2 -1
- package/src/vitessce-grid-utils.js +27 -15
- package/dist/index.mjs +0 -84801
- package/src/component-registry.js +0 -21
- package/src/errors/OptionsValidationError.js +0 -25
- package/src/file-options-schemas-legacy.js +0 -139
- package/src/file-options-schemas-legacy.test.js +0 -138
- package/src/file-options-schemas.js +0 -327
- package/src/file-options-schemas.test.js +0 -26
- package/src/joint-file-types-legacy.js +0 -298
- package/src/joint-file-types-legacy.test.js +0 -412
- package/src/joint-file-types.js +0 -171
- package/src/joint-file-types.test.js +0 -144
- package/src/json-schemas.js +0 -9
- package/src/plugins.js +0 -186
- package/src/plugins.test.js +0 -42
- package/src/schemas/config-0.1.0.schema.json +0 -85
- package/src/schemas/config-1.0.0.schema.json +0 -733
- package/src/schemas/config-1.0.1.schema.json +0 -909
- package/src/schemas/config-1.0.10.schema.json +0 -969
- package/src/schemas/config-1.0.11.schema.json +0 -990
- package/src/schemas/config-1.0.12.schema.json +0 -997
- package/src/schemas/config-1.0.13.schema.json +0 -1013
- package/src/schemas/config-1.0.14.schema.json +0 -1048
- package/src/schemas/config-1.0.15.schema.json +0 -1048
- package/src/schemas/config-1.0.16.schema.json +0 -1069
- package/src/schemas/config-1.0.16.schema.test.js +0 -32
- package/src/schemas/config-1.0.2.schema.json +0 -911
- package/src/schemas/config-1.0.3.schema.json +0 -911
- package/src/schemas/config-1.0.4.schema.json +0 -949
- package/src/schemas/config-1.0.5.schema.json +0 -949
- package/src/schemas/config-1.0.6.schema.json +0 -950
- package/src/schemas/config-1.0.7.schema.json +0 -950
- package/src/schemas/config-1.0.8.schema.json +0 -966
- package/src/schemas/config-1.0.9.schema.json +0 -965
- package/src/schemas/obsSets.schema.js +0 -195
- package/src/schemas/obsSetsTabular.schema.js +0 -39
- package/src/schemas/raster.schema.js +0 -121
- package/src/schemas/schema-schema.sh +0 -34
- package/src/schemas/schema.test-old.js +0 -49
- package/src/view-config-upgraders.js +0 -628
- package/src/view-config-utils.test.js +0 -95
- package/src/view-config-versions.js +0 -68
package/src/VitS.js
CHANGED
|
@@ -1,36 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
import React, { useEffect, useMemo } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useCallback } from 'react';
|
|
3
2
|
import {
|
|
4
3
|
ThemeProvider,
|
|
5
4
|
StylesProvider,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
} from '@material-ui/core';
|
|
6
|
+
import {
|
|
7
|
+
QueryClient,
|
|
8
|
+
QueryClientProvider,
|
|
9
|
+
} from '@tanstack/react-query';
|
|
10
|
+
import { isEqual } from 'lodash-es';
|
|
11
|
+
import { buildConfigSchema, latestConfigSchema } from '@vitessce/schemas';
|
|
12
|
+
import { muiTheme } from './shared-mui/styles.js';
|
|
11
13
|
import {
|
|
12
14
|
ViewConfigProvider,
|
|
13
15
|
createViewConfigStore,
|
|
14
16
|
AuxiliaryProvider,
|
|
15
17
|
createAuxiliaryStore,
|
|
16
|
-
} from './state/hooks';
|
|
18
|
+
} from './state/hooks.js';
|
|
17
19
|
|
|
18
|
-
import VitessceGrid from './VitessceGrid';
|
|
19
|
-
import { Warning } from './Warning';
|
|
20
|
-
import CallbackPublisher from './CallbackPublisher';
|
|
21
|
-
import { getComponent } from './component-registry';
|
|
20
|
+
import VitessceGrid from './VitessceGrid.js';
|
|
21
|
+
import { Warning } from './Warning.js';
|
|
22
|
+
import CallbackPublisher from './CallbackPublisher.js';
|
|
22
23
|
import {
|
|
23
|
-
checkTypes,
|
|
24
24
|
initialize,
|
|
25
|
-
|
|
26
|
-
} from './view-config-utils';
|
|
25
|
+
logConfig,
|
|
26
|
+
} from './view-config-utils.js';
|
|
27
|
+
import { createLoaders } from './vitessce-grid-utils.js';
|
|
28
|
+
import { createGenerateClassName } from './mui-utils.js';
|
|
27
29
|
|
|
28
|
-
function logConfig(config, name) {
|
|
29
|
-
console.groupCollapsed(`🚄 Vitessce (${META_VERSION.version}) ${name}`);
|
|
30
|
-
console.info(`data:,${JSON.stringify(config)}`);
|
|
31
|
-
console.info(JSON.stringify(config, null, 2));
|
|
32
|
-
console.groupEnd();
|
|
33
|
-
}
|
|
34
30
|
|
|
35
31
|
/**
|
|
36
32
|
* The Vitessce component.
|
|
@@ -38,7 +34,7 @@ function logConfig(config, name) {
|
|
|
38
34
|
* @param {object} props.config A Vitessce view config.
|
|
39
35
|
* If the config is valid, the VitessceGrid will be rendered as a child.
|
|
40
36
|
* If the config is invalid, a Warning will be rendered instead.
|
|
41
|
-
* @param {number} props.rowHeight Row height for grid layout. Optional.
|
|
37
|
+
* @param {undefined|number} props.rowHeight Row height for grid layout. Optional.
|
|
42
38
|
* @param {number} props.height Total height for grid layout. Optional.
|
|
43
39
|
* @param {string} props.theme The theme, used for styling as
|
|
44
40
|
* light or dark. Optional. By default, "dark"
|
|
@@ -47,12 +43,22 @@ function logConfig(config, name) {
|
|
|
47
43
|
* updates. Optional.
|
|
48
44
|
* @param {function} props.onLoaderChange A callback for loader
|
|
49
45
|
* updates. Optional.
|
|
46
|
+
* @param {boolean} props.validateConfig Whether to validate or not. Only to be
|
|
47
|
+
* set to false in controlled component situations, where bypassing validation
|
|
48
|
+
* is required for performance, and the parent knows the config
|
|
49
|
+
* is already valid (e.g., it originated from onConfigChange). By default, true.
|
|
50
50
|
* @param {boolean} props.validateOnConfigChange Whether to validate
|
|
51
51
|
* against the view config schema when publishing changes. Use for debugging
|
|
52
52
|
* purposes, as this may have a performance impact. By default, false.
|
|
53
|
-
* @param {
|
|
53
|
+
* @param {null|string} props.uid A unique identifier for this Vitessce instance,
|
|
54
54
|
* for the purpose of avoiding CSS autogenerated class name conflicts. Must be valid as part
|
|
55
55
|
* of a CSS class name string.
|
|
56
|
+
* @param {array} props.viewTypes Plugin view types.
|
|
57
|
+
* @param {array} props.fileTypes Plugin file types.
|
|
58
|
+
* @param {array} props.jointFileTypes Plugin joint file types.
|
|
59
|
+
* @param {array} props.coordinationTypes Plugin coordination types.
|
|
60
|
+
* @param {null|object} props.warning A warning to render within the Vitessce grid,
|
|
61
|
+
* provided by the parent.
|
|
56
62
|
*/
|
|
57
63
|
export function VitS(props) {
|
|
58
64
|
const {
|
|
@@ -63,18 +69,43 @@ export function VitS(props) {
|
|
|
63
69
|
onWarn,
|
|
64
70
|
onConfigChange,
|
|
65
71
|
onLoaderChange,
|
|
72
|
+
validateConfig = true,
|
|
66
73
|
validateOnConfigChange = false,
|
|
67
|
-
onConfigUpgrade,
|
|
68
74
|
isBounded = false,
|
|
69
|
-
uid,
|
|
75
|
+
uid = null,
|
|
76
|
+
viewTypes: viewTypesProp,
|
|
77
|
+
fileTypes: fileTypesProp,
|
|
78
|
+
jointFileTypes: jointFileTypesProp,
|
|
79
|
+
coordinationTypes: coordinationTypesProp,
|
|
80
|
+
warning,
|
|
70
81
|
} = props;
|
|
71
82
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
const viewTypes = useMemo(() => (viewTypesProp || []), [viewTypesProp]);
|
|
84
|
+
const fileTypes = useMemo(() => (fileTypesProp || []), [fileTypesProp]);
|
|
85
|
+
const jointFileTypes = useMemo(
|
|
86
|
+
() => (jointFileTypesProp || []),
|
|
87
|
+
[jointFileTypesProp],
|
|
88
|
+
);
|
|
89
|
+
const coordinationTypes = useMemo(
|
|
90
|
+
() => (coordinationTypesProp || []),
|
|
91
|
+
[coordinationTypesProp],
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const generateClassName = useMemo(() => createGenerateClassName(uid), [uid]);
|
|
95
|
+
|
|
96
|
+
const configVersion = config?.version;
|
|
97
|
+
|
|
98
|
+
// If config.uid exists, then use it for hook dependencies to detect changes
|
|
99
|
+
// (controlled component case). If not, then use the config object itself
|
|
100
|
+
// and assume the un-controlled component case.
|
|
101
|
+
const configKey = config?.uid || config;
|
|
102
|
+
|
|
103
|
+
const pluginSpecificConfigSchema = useMemo(() => buildConfigSchema(
|
|
104
|
+
fileTypes,
|
|
105
|
+
jointFileTypes,
|
|
106
|
+
coordinationTypes,
|
|
107
|
+
viewTypes,
|
|
108
|
+
), [viewTypes, fileTypes, jointFileTypes, coordinationTypes]);
|
|
78
109
|
|
|
79
110
|
// Process the view config and memoize the result:
|
|
80
111
|
// - Validate.
|
|
@@ -82,46 +113,35 @@ export function VitS(props) {
|
|
|
82
113
|
// - Validate after upgrade, if legacy schema.
|
|
83
114
|
// - Initialize (based on initStrategy).
|
|
84
115
|
const [configOrWarning, success] = useMemo(() => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return [
|
|
88
|
-
{
|
|
89
|
-
title: 'No such dataset',
|
|
90
|
-
unformatted: 'The dataset configuration could not be found.',
|
|
91
|
-
},
|
|
92
|
-
false,
|
|
93
|
-
];
|
|
94
|
-
}
|
|
95
|
-
// If the view config is missing a version, show a warning message.
|
|
96
|
-
if (!config.version) {
|
|
97
|
-
return [
|
|
98
|
-
{
|
|
99
|
-
title: 'Missing version',
|
|
100
|
-
unformatted:
|
|
101
|
-
'The dataset configuration is missing a version, preventing validation.',
|
|
102
|
-
},
|
|
103
|
-
false,
|
|
104
|
-
];
|
|
116
|
+
if (warning) {
|
|
117
|
+
return [warning, false];
|
|
105
118
|
}
|
|
106
119
|
logConfig(config, 'input view config');
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
logConfig(upgradedConfig, '
|
|
120
|
+
if (!validateConfig) {
|
|
121
|
+
return [config, true];
|
|
122
|
+
}
|
|
123
|
+
const result = latestConfigSchema.safeParse(config);
|
|
124
|
+
if (result.success) {
|
|
125
|
+
const upgradedConfig = result.data;
|
|
126
|
+
logConfig(upgradedConfig, 'parsed view config');
|
|
127
|
+
// Perform second round of parsing against plugin-specific config schema.
|
|
128
|
+
const pluginSpecificResult = pluginSpecificConfigSchema.safeParse(upgradedConfig);
|
|
114
129
|
// Initialize the view config according to the initStrategy.
|
|
115
|
-
|
|
116
|
-
if (typeCheckSuccess) {
|
|
130
|
+
if (pluginSpecificResult.success) {
|
|
117
131
|
try {
|
|
118
|
-
const
|
|
132
|
+
const upgradedConfigWithValidPlugins = pluginSpecificResult.data;
|
|
133
|
+
const initializedConfig = initialize(
|
|
134
|
+
upgradedConfigWithValidPlugins,
|
|
135
|
+
jointFileTypes,
|
|
136
|
+
coordinationTypes,
|
|
137
|
+
viewTypes,
|
|
138
|
+
);
|
|
119
139
|
logConfig(initializedConfig, 'initialized view config');
|
|
120
140
|
return [initializedConfig, true];
|
|
121
141
|
} catch (e) {
|
|
122
142
|
return [
|
|
123
143
|
{
|
|
124
|
-
title: '
|
|
144
|
+
title: 'Config initialization failed.',
|
|
125
145
|
unformatted: e.message,
|
|
126
146
|
},
|
|
127
147
|
false,
|
|
@@ -130,14 +150,28 @@ export function VitS(props) {
|
|
|
130
150
|
}
|
|
131
151
|
return [
|
|
132
152
|
{
|
|
133
|
-
title: '
|
|
134
|
-
unformatted:
|
|
153
|
+
title: 'Config validation failed on second pass.',
|
|
154
|
+
unformatted: pluginSpecificResult.error.message,
|
|
135
155
|
},
|
|
136
156
|
false,
|
|
137
157
|
];
|
|
138
158
|
}
|
|
139
|
-
return [
|
|
140
|
-
|
|
159
|
+
return [{
|
|
160
|
+
title: 'Config validation failed on first pass.',
|
|
161
|
+
unformatted: result.error.message,
|
|
162
|
+
}, result.success];
|
|
163
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
164
|
+
}, [configKey, configVersion, pluginSpecificConfigSchema, warning]);
|
|
165
|
+
|
|
166
|
+
const queryClient = useMemo(() => new QueryClient({
|
|
167
|
+
// Reference: https://tanstack.com/query/latest/docs/react/guides/window-focus-refetching
|
|
168
|
+
defaultOptions: {
|
|
169
|
+
queries: {
|
|
170
|
+
refetchOnWindowFocus: false,
|
|
171
|
+
retry: 2,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
}), [configKey]);
|
|
141
175
|
|
|
142
176
|
// Emit the upgraded/initialized view config
|
|
143
177
|
// to onConfigChange if necessary.
|
|
@@ -145,29 +179,53 @@ export function VitS(props) {
|
|
|
145
179
|
if (success && !isEqual(configOrWarning, config) && onConfigChange) {
|
|
146
180
|
onConfigChange(configOrWarning);
|
|
147
181
|
}
|
|
148
|
-
|
|
182
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
183
|
+
}, [success, configKey, configOrWarning, onConfigChange]);
|
|
184
|
+
|
|
185
|
+
// Initialize the view config and loaders in the global state.
|
|
186
|
+
const createViewConfigStoreClosure = useCallback(() => {
|
|
187
|
+
if (success) {
|
|
188
|
+
const loaders = createLoaders(
|
|
189
|
+
configOrWarning.datasets,
|
|
190
|
+
configOrWarning.description,
|
|
191
|
+
fileTypes,
|
|
192
|
+
coordinationTypes,
|
|
193
|
+
);
|
|
194
|
+
return createViewConfigStore(loaders, configOrWarning);
|
|
195
|
+
}
|
|
196
|
+
// No config found, so clear the loaders.
|
|
197
|
+
return createViewConfigStore(null, null);
|
|
198
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
199
|
+
}, [success, configKey]);
|
|
149
200
|
|
|
150
201
|
return success ? (
|
|
151
202
|
<StylesProvider generateClassName={generateClassName}>
|
|
152
203
|
<ThemeProvider theme={muiTheme[theme]}>
|
|
153
|
-
<
|
|
154
|
-
<
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
204
|
+
<QueryClientProvider client={queryClient}>
|
|
205
|
+
<ViewConfigProvider createStore={createViewConfigStoreClosure}>
|
|
206
|
+
<AuxiliaryProvider createStore={createAuxiliaryStore}>
|
|
207
|
+
<VitessceGrid
|
|
208
|
+
success={success}
|
|
209
|
+
configKey={configKey}
|
|
210
|
+
viewTypes={viewTypes}
|
|
211
|
+
fileTypes={fileTypes}
|
|
212
|
+
coordinationTypes={coordinationTypes}
|
|
213
|
+
config={configOrWarning}
|
|
214
|
+
rowHeight={rowHeight}
|
|
215
|
+
height={height}
|
|
216
|
+
theme={theme}
|
|
217
|
+
isBounded={isBounded}
|
|
218
|
+
/>
|
|
219
|
+
<CallbackPublisher
|
|
220
|
+
onWarn={onWarn}
|
|
221
|
+
onConfigChange={onConfigChange}
|
|
222
|
+
onLoaderChange={onLoaderChange}
|
|
223
|
+
validateOnConfigChange={validateOnConfigChange}
|
|
224
|
+
pluginSpecificConfigSchema={pluginSpecificConfigSchema}
|
|
225
|
+
/>
|
|
226
|
+
</AuxiliaryProvider>
|
|
227
|
+
</ViewConfigProvider>
|
|
228
|
+
</QueryClientProvider>
|
|
171
229
|
</ThemeProvider>
|
|
172
230
|
</StylesProvider>
|
|
173
231
|
) : (
|
package/src/VitessceGrid.js
CHANGED
|
@@ -3,9 +3,9 @@ import React, {
|
|
|
3
3
|
useCallback,
|
|
4
4
|
} from 'react';
|
|
5
5
|
import clsx from 'clsx';
|
|
6
|
-
import { VITESSCE_CONTAINER } from './classNames';
|
|
7
|
-
import { VitessceGridLayout } from './vitessce-grid-layout';
|
|
8
|
-
import { useRowHeight, createLoaders } from './vitessce-grid-utils';
|
|
6
|
+
import { VITESSCE_CONTAINER } from './classNames.js';
|
|
7
|
+
import { VitessceGridLayout } from './vitessce-grid-layout/index.js';
|
|
8
|
+
import { useRowHeight, createLoaders } from './vitessce-grid-utils.js';
|
|
9
9
|
import {
|
|
10
10
|
useViewConfigStoreApi,
|
|
11
11
|
useSetViewConfig,
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
useRemoveComponent,
|
|
15
15
|
useChangeLayout,
|
|
16
16
|
useLayout,
|
|
17
|
-
} from './state/hooks';
|
|
17
|
+
} from './state/hooks.js';
|
|
18
18
|
import {
|
|
19
19
|
useClosestVitessceContainerSize,
|
|
20
|
-
} from './hooks';
|
|
21
|
-
import { useVitessceContainerStyles } from './shared-mui/container';
|
|
22
|
-
import { useTitleStyles } from './
|
|
20
|
+
} from './hooks.js';
|
|
21
|
+
import { useVitessceContainerStyles } from './shared-mui/container.js';
|
|
22
|
+
import { useTitleStyles } from './title-styles.js';
|
|
23
23
|
|
|
24
24
|
const padding = 10;
|
|
25
25
|
const margin = 5;
|
|
@@ -29,20 +29,25 @@ const margin = 5;
|
|
|
29
29
|
* @param {object} props
|
|
30
30
|
* @param {number} props.rowHeight The height of each grid row. Optional.
|
|
31
31
|
* @param {object} props.config The view config.
|
|
32
|
-
* @param {function} props.getComponent A function that maps component names to their
|
|
33
|
-
* React counterparts.
|
|
34
32
|
* @param {string} props.theme The theme name.
|
|
35
33
|
* @param {number} props.height Total height for grid. Optional.
|
|
36
34
|
* @param {function} props.onWarn A callback for warning messages. Optional.
|
|
35
|
+
* @param {PluginViewType[]} props.viewTypes
|
|
36
|
+
* @param {PluginFileType[]} props.fileTypes
|
|
37
|
+
* @param {PluginCoordinationType[]} props.coordinationTypes
|
|
37
38
|
*/
|
|
38
39
|
export default function VitessceGrid(props) {
|
|
39
40
|
const {
|
|
41
|
+
success,
|
|
42
|
+
configKey,
|
|
40
43
|
rowHeight: initialRowHeight,
|
|
41
44
|
config,
|
|
42
|
-
getComponent,
|
|
43
45
|
theme,
|
|
44
46
|
height,
|
|
45
47
|
isBounded,
|
|
48
|
+
viewTypes,
|
|
49
|
+
fileTypes,
|
|
50
|
+
coordinationTypes,
|
|
46
51
|
} = props;
|
|
47
52
|
|
|
48
53
|
const [rowHeight, containerRef] = useRowHeight(config, initialRowHeight, height, margin, padding);
|
|
@@ -72,29 +77,38 @@ export default function VitessceGrid(props) {
|
|
|
72
77
|
}, [changeLayout, componentWidth]);
|
|
73
78
|
|
|
74
79
|
// Update the view config and loaders in the global state.
|
|
80
|
+
// This effect is needed for the controlled component case in which
|
|
81
|
+
// the store has already been initialized with a view config,
|
|
82
|
+
// and we want to replace it with a new view config.
|
|
75
83
|
useEffect(() => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
let newLoaders = null;
|
|
85
|
+
let newConfig = null;
|
|
86
|
+
if (success) {
|
|
87
|
+
newLoaders = createLoaders(
|
|
88
|
+
config.datasets,
|
|
89
|
+
config.description,
|
|
90
|
+
fileTypes,
|
|
91
|
+
coordinationTypes,
|
|
92
|
+
);
|
|
93
|
+
newConfig = config;
|
|
83
94
|
}
|
|
84
|
-
|
|
95
|
+
setViewConfig(newConfig);
|
|
96
|
+
setLoaders(newLoaders);
|
|
97
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
98
|
+
}, [success, configKey]);
|
|
85
99
|
|
|
86
100
|
return (
|
|
87
101
|
<div
|
|
88
102
|
ref={containerRef}
|
|
89
103
|
className={clsx(VITESSCE_CONTAINER, classes.vitessceContainer)}
|
|
90
104
|
>
|
|
91
|
-
{layout
|
|
105
|
+
{layout ? (
|
|
92
106
|
<VitessceGridLayout
|
|
93
107
|
layout={layout}
|
|
94
108
|
height={height}
|
|
95
109
|
rowHeight={rowHeight}
|
|
96
110
|
theme={theme}
|
|
97
|
-
|
|
111
|
+
viewTypes={viewTypes}
|
|
98
112
|
draggableHandle={titleClasses.title}
|
|
99
113
|
margin={margin}
|
|
100
114
|
padding={padding}
|
|
@@ -104,7 +118,7 @@ export default function VitessceGrid(props) {
|
|
|
104
118
|
onResize={onResize}
|
|
105
119
|
onResizeStop={onResize}
|
|
106
120
|
/>
|
|
107
|
-
)}
|
|
121
|
+
) : null}
|
|
108
122
|
</div>
|
|
109
123
|
);
|
|
110
124
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
1
2
|
import '@testing-library/jest-dom';
|
|
2
|
-
import { cleanup, render, screen } from '@testing-library/react'
|
|
3
|
-
import { afterEach } from 'vitest'
|
|
3
|
+
import { cleanup, render, screen } from '@testing-library/react';
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { PluginViewType } from '@vitessce/plugins';
|
|
7
|
+
import VitessceGrid from './VitessceGrid.js';
|
|
6
8
|
import {
|
|
7
9
|
ViewConfigProvider, createViewConfigStore,
|
|
8
10
|
AuxiliaryProvider, createAuxiliaryStore,
|
|
9
|
-
} from './state/hooks';
|
|
11
|
+
} from './state/hooks.js';
|
|
10
12
|
|
|
11
13
|
afterEach(() => {
|
|
12
|
-
cleanup()
|
|
14
|
+
cleanup();
|
|
13
15
|
});
|
|
14
16
|
|
|
15
17
|
describe('VitessceGrid.js', () => {
|
|
@@ -31,14 +33,27 @@ describe('VitessceGrid.js', () => {
|
|
|
31
33
|
],
|
|
32
34
|
};
|
|
33
35
|
|
|
36
|
+
function createViewConfigStoreClosure() {
|
|
37
|
+
return createViewConfigStore(null, config);
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
function FakeComponent() {
|
|
35
41
|
return <p>FakeComponent!</p>;
|
|
36
42
|
}
|
|
37
|
-
const
|
|
43
|
+
const viewTypes = [new PluginViewType('FakeComponent', FakeComponent, [])];
|
|
44
|
+
const fileTypes = [];
|
|
45
|
+
const coordinationTypes = [];
|
|
38
46
|
render(
|
|
39
|
-
<ViewConfigProvider createStore={
|
|
47
|
+
<ViewConfigProvider createStore={createViewConfigStoreClosure}>
|
|
40
48
|
<AuxiliaryProvider createStore={createAuxiliaryStore}>
|
|
41
|
-
<VitessceGrid
|
|
49
|
+
<VitessceGrid
|
|
50
|
+
success
|
|
51
|
+
configKey={null}
|
|
52
|
+
config={config}
|
|
53
|
+
viewTypes={viewTypes}
|
|
54
|
+
fileTypes={fileTypes}
|
|
55
|
+
coordinationTypes={coordinationTypes}
|
|
56
|
+
/>
|
|
42
57
|
</AuxiliaryProvider>
|
|
43
58
|
</ViewConfigProvider>,
|
|
44
59
|
);
|
package/src/Warning.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import { makeStyles } from '@material-ui/core
|
|
3
|
-
import { VITESSCE_CONTAINER } from './classNames';
|
|
2
|
+
import { makeStyles } from '@material-ui/core';
|
|
3
|
+
import { VITESSCE_CONTAINER } from './classNames.js';
|
|
4
4
|
|
|
5
5
|
const useStyles = makeStyles(theme => ({
|
|
6
6
|
warningLayout: {
|
|
@@ -20,7 +20,7 @@ const useStyles = makeStyles(theme => ({
|
|
|
20
20
|
row: {
|
|
21
21
|
flexGrow: '1',
|
|
22
22
|
},
|
|
23
|
-
|
|
23
|
+
warningCard: {
|
|
24
24
|
border: `1px solid ${theme.palette.cardBorder}`,
|
|
25
25
|
flex: '1 1 auto',
|
|
26
26
|
minHeight: '1px',
|
|
@@ -50,7 +50,7 @@ export function Warning(props) {
|
|
|
50
50
|
<div className={VITESSCE_CONTAINER}>
|
|
51
51
|
<div className={clsx(classes.warningLayout, classes.containerFluid)}>
|
|
52
52
|
<div className={classes.row}>
|
|
53
|
-
<div className={classes.
|
|
53
|
+
<div className={classes.warningCard}>
|
|
54
54
|
<h1>{title}</h1>
|
|
55
55
|
{preformatted ? (<pre>{preformatted}</pre>) : null}
|
|
56
56
|
<p>{unformatted}</p>
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import Ajv from 'ajv';
|
|
2
|
-
import { OptionsValidationError } from '../errors/index';
|
|
3
|
-
import { emptySchema } from '../file-options-schemas';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
2
|
* A loader ancestor class containing a default constructor
|
|
7
3
|
* and a stub for the required load() method.
|
|
@@ -18,29 +14,10 @@ export default class AbstractLoader {
|
|
|
18
14
|
this.requestInit = requestInit;
|
|
19
15
|
this.options = options;
|
|
20
16
|
this.coordinationValues = coordinationValues;
|
|
21
|
-
this.optionsSchema = emptySchema;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
validateOptions() {
|
|
25
|
-
const { optionsSchema, options } = this;
|
|
26
|
-
const validate = new Ajv().compile(optionsSchema);
|
|
27
|
-
const valid = validate(options || null);
|
|
28
|
-
if (!valid) {
|
|
29
|
-
return [false, validate.errors];
|
|
30
|
-
}
|
|
31
|
-
return [true, null];
|
|
32
17
|
}
|
|
33
18
|
|
|
19
|
+
// eslint-disable-next-line class-methods-use-this
|
|
34
20
|
load() {
|
|
35
|
-
|
|
36
|
-
fileType, url, options,
|
|
37
|
-
} = this;
|
|
38
|
-
const [optionsAreValid, optionsFailureReason] = this.validateOptions();
|
|
39
|
-
if (!optionsAreValid) {
|
|
40
|
-
return Promise.reject(
|
|
41
|
-
new OptionsValidationError(fileType, url, options, optionsFailureReason),
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
return Promise.resolve(optionsAreValid);
|
|
21
|
+
return Promise.resolve(true);
|
|
45
22
|
}
|
|
46
23
|
}
|
package/src/data/LoaderResult.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
export default class LoaderResult {
|
|
3
|
+
/**
|
|
4
|
+
* @param {*} data
|
|
5
|
+
* @param {object[]|string|null} url Single URL or array of { url, name } objects.
|
|
6
|
+
* @param {object} coordinationValues
|
|
7
|
+
*/
|
|
3
8
|
constructor(data, url, coordinationValues = null) {
|
|
4
9
|
this.data = data;
|
|
5
10
|
this.url = url;
|
package/src/data/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { default as AbstractLoader } from './AbstractLoader';
|
|
2
|
-
export { default as AbstractTwoStepLoader } from './AbstractTwoStepLoader';
|
|
3
|
-
export { default as LoaderResult } from './LoaderResult';
|
|
1
|
+
export { default as AbstractLoader } from './AbstractLoader.js';
|
|
2
|
+
export { default as AbstractTwoStepLoader } from './AbstractTwoStepLoader.js';
|
|
3
|
+
export { default as LoaderResult } from './LoaderResult.js';
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export function getSourceAndLoaderFromFileType(type) {
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return pluginFileType;
|
|
1
|
+
/**
|
|
2
|
+
* Get the data source and data loader class.
|
|
3
|
+
* @param {string} type The fileType name.
|
|
4
|
+
* @param {PluginFileType[]} fileTypes The array of file types.
|
|
5
|
+
* @returns {array} [dataSourceClass, dataLoaderClass].
|
|
6
|
+
*/
|
|
7
|
+
export function getSourceAndLoaderFromFileType(type, fileTypes) {
|
|
8
|
+
if (Array.isArray(fileTypes)) {
|
|
9
|
+
const matchingFileType = fileTypes.find(ft => ft.name === type);
|
|
10
|
+
if (matchingFileType) {
|
|
11
|
+
return matchingFileType.getSourceAndLoader();
|
|
12
|
+
}
|
|
14
13
|
}
|
|
15
14
|
// Fallback to JSON.
|
|
16
15
|
// TODO(monorepo)
|
|
17
16
|
// return [JsonSource, JsonLoader];
|
|
18
17
|
return [null, null];
|
|
19
18
|
}
|
|
19
|
+
|
|
20
|
+
export function getDataTypeFromFileType(type, fileTypes) {
|
|
21
|
+
if (Array.isArray(fileTypes)) {
|
|
22
|
+
const matchingFileType = fileTypes.find(ft => ft.name === type);
|
|
23
|
+
if (matchingFileType) {
|
|
24
|
+
return matchingFileType.dataType;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|