Skip to content

Commit 720a81f

Browse files
committed
feat: add config URL parameter to load configs before data
Implements ?config= URL parameter to ensure configuration files are loaded before data files, eliminating race conditions when both are specified. Fixes #817
1 parent 533c4bb commit 720a81f

File tree

6 files changed

+40
-45
lines changed

6 files changed

+40
-45
lines changed

docs/configuration_file.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ By loading a JSON file, you can set VolView's configuration:
88
- Visibility of Sample Data section
99
- Keyboard shortcuts
1010

11+
## Loading Configuration Files
12+
13+
Use the `config` URL parameter to load configuration before data files:
14+
15+
```
16+
https://volview.kitware.com/?config=https://example.com/config.json&urls=https://example.com/data.nrrd
17+
```
18+
1119
## View Layouts
1220

1321
Define one or more named layouts using the `layouts` key. VolView will use the first layout as the default. Each named layout will be in the layout selector menu. Layout are specified in three formats:

src/actions/loadUserFiles.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -323,17 +323,25 @@ export async function loadUserPromptedFiles() {
323323
return loadFiles(files);
324324
}
325325

326+
function urlsToDataSources(urls: string[], names: string[] = []): DataSource[] {
327+
return urls.map((url, idx) => {
328+
const defaultName =
329+
basename(parseUrl(url, window.location.href).pathname) || url;
330+
return uriToDataSource(url, names[idx] || defaultName);
331+
});
332+
}
333+
326334
export async function loadUrls(params: UrlParams) {
327-
const urls = wrapInArray(params.urls);
328-
const names = wrapInArray(params.names ?? []); // optional names should resolve to [] if params.names === undefined
329-
const sources = urls.map((url, idx) =>
330-
uriToDataSource(
331-
url,
332-
names[idx] ||
333-
basename(parseUrl(url, window.location.href).pathname) ||
334-
url
335-
)
336-
);
335+
if (params.config) {
336+
const configUrls = wrapInArray(params.config);
337+
const configSources = urlsToDataSources(configUrls);
338+
await loadDataSources(configSources);
339+
}
337340

338-
return loadDataSources(sources);
341+
if (params.urls) {
342+
const urls = wrapInArray(params.urls);
343+
const names = wrapInArray(params.names ?? []);
344+
const sources = urlsToDataSources(urls, names);
345+
await loadDataSources(sources);
346+
}
339347
}

src/components/App.vue

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,6 @@ export default defineComponent({
149149
const urlParams = vtkURLExtract.extractURLParameters() as UrlParams;
150150
151151
onMounted(() => {
152-
if (!urlParams.urls) {
153-
return;
154-
}
155-
156152
loadUrls(urlParams);
157153
});
158154

tests/specs/configTestUtils.ts

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,18 @@ export type DatasetResource = {
3131
name?: string;
3232
};
3333

34-
export const createConfigManifest = async (
34+
export const openConfigAndDataset = async (
3535
config: unknown,
3636
name: string,
3737
dataset: DatasetResource = ONE_CT_SLICE_DICOM
3838
) => {
3939
const configFileName = `${name}-config.json`;
40-
const manifestFileName = `${name}-manifest.json`;
41-
4240
await writeManifestToFile(config, configFileName);
4341

44-
const manifest = {
45-
resources: [{ url: `/tmp/${configFileName}` }, dataset],
46-
};
47-
48-
await writeManifestToFile(manifest, manifestFileName);
49-
return manifestFileName;
50-
};
51-
52-
export const openConfigAndWait = async (
53-
config: unknown,
54-
name: string,
55-
dataset: DatasetResource = ONE_CT_SLICE_DICOM
56-
) => {
57-
const manifestFileNameOnDisk = await createConfigManifest(
58-
config,
59-
name,
60-
dataset
42+
await volViewPage.open(
43+
`?config=[tmp/${configFileName}]&urls=${dataset.url}&names=${
44+
dataset.name ?? ''
45+
}`
6146
);
62-
63-
await volViewPage.open(`?urls=[tmp/${manifestFileNameOnDisk}]`);
6447
await volViewPage.waitForViews();
6548
};

tests/specs/layout-config.e2e.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { volViewPage } from '../pageobjects/volview.page';
2-
import { PROSTATEX_DATASET, openConfigAndWait } from './configTestUtils';
2+
import { PROSTATEX_DATASET, openConfigAndDataset } from './configTestUtils';
33

44
describe('VolView Layout Configuration', () => {
55
it('should create a 2x2 grid layout from simple string array', async () => {
@@ -12,7 +12,7 @@ describe('VolView Layout Configuration', () => {
1212
},
1313
};
1414

15-
await openConfigAndWait(config, 'layout-grid');
15+
await openConfigAndDataset(config, 'layout-grid');
1616

1717
await volViewPage.waitForViewCounts(3, true);
1818
});
@@ -33,7 +33,7 @@ describe('VolView Layout Configuration', () => {
3333
},
3434
};
3535

36-
await openConfigAndWait(config, 'layout-nested');
36+
await openConfigAndDataset(config, 'layout-nested');
3737

3838
await volViewPage.waitForViewCounts(3, true);
3939
});
@@ -68,7 +68,7 @@ describe('VolView Layout Configuration', () => {
6868
},
6969
};
7070

71-
await openConfigAndWait(config, 'layout-custom-views');
71+
await openConfigAndDataset(config, 'layout-custom-views');
7272

7373
await volViewPage.waitForViewCounts(2, true);
7474
});
@@ -85,7 +85,7 @@ describe('VolView Layout Configuration', () => {
8585
},
8686
};
8787

88-
await openConfigAndWait(config, 'multiple-layouts', PROSTATEX_DATASET);
88+
await openConfigAndDataset(config, 'multiple-layouts', PROSTATEX_DATASET);
8989

9090
await volViewPage.waitForViewCounts(4, false);
9191

@@ -129,7 +129,7 @@ describe('VolView Layout Configuration', () => {
129129
disabledViewTypes: ['3D', 'Oblique'],
130130
};
131131

132-
await openConfigAndWait(config, 'disabled-view-types');
132+
await openConfigAndDataset(config, 'disabled-view-types');
133133

134134
await volViewPage.waitForViewCounts(4, false);
135135

tests/specs/windowing-config.e2e.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { volViewPage } from '../pageobjects/volview.page';
22
import { openUrls } from './utils';
33
import {
4-
openConfigAndWait,
4+
openConfigAndDataset,
55
ONE_CT_SLICE_DICOM,
66
MINIMAL_DICOM,
77
} from './configTestUtils';
@@ -17,7 +17,7 @@ describe('VolView windowing configuration', () => {
1717
windowing: runtimeWindowLevel,
1818
};
1919

20-
await openConfigAndWait(config, 'windowing');
20+
await openConfigAndDataset(config, 'windowing');
2121

2222
const view = await $('div[data-testid="vtk-view vtk-two-view"]');
2323

0 commit comments

Comments
 (0)