Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/components/DataBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import PatientBrowser from './PatientBrowser.vue';
import PatientList from './dicom-web/PatientList.vue';
import { useDICOMStore } from '../store/datasets-dicom';
import { useImageStore } from '../store/datasets-images';
import { useDataBrowserStore } from '../store/data-browser';
import { removeFromArray } from '../utils';

const SAMPLE_DATA_KEY = 'sampleData';
Expand All @@ -25,6 +26,7 @@ export default defineComponent({
const dicomStore = useDICOMStore();
const imageStore = useImageStore();
const dicomWeb = useDicomWebStore();
const dataBrowserStore = useDataBrowserStore();

// TODO show patient ID in parens if there is a name conflict
const patients = computed(() =>
Expand Down Expand Up @@ -61,6 +63,8 @@ export default defineComponent({
}
);

const hideSampleData = computed(() => dataBrowserStore.hideSampleData);

return {
panels,
patients,
Expand All @@ -70,6 +74,7 @@ export default defineComponent({
SAMPLE_DATA_KEY,
ANONYMOUS_DATA_KEY,
DICOM_WEB_KEY,
hideSampleData,
};
},
});
Expand All @@ -78,7 +83,12 @@ export default defineComponent({
<template>
<div id="data-module" class="mx-1 fill-height">
<div id="data-panels">
<v-expansion-panels v-model="panels" multiple variant="accordion">
<v-expansion-panels
v-model="panels"
multiple
variant="accordion"
class="no-panels"
>
<v-expansion-panel
v-if="hasAnonymousImages"
:value="ANONYMOUS_DATA_KEY"
Expand Down Expand Up @@ -140,7 +150,7 @@ export default defineComponent({
</v-expansion-panel-text>
</v-expansion-panel>

<v-expansion-panel :value="SAMPLE_DATA_KEY">
<v-expansion-panel v-if="!hideSampleData" :value="SAMPLE_DATA_KEY">
<v-expansion-panel-title>
<v-icon class="collection-header-icon">mdi-card-bulleted</v-icon>
<span>Sample Data</span>
Expand All @@ -150,6 +160,7 @@ export default defineComponent({
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
<div class="empty-state ma-4 text-center">No data loaded</div>
</div>
</div>
</template>
Expand Down Expand Up @@ -184,4 +195,12 @@ export default defineComponent({
text-overflow: ellipsis;
white-space: nowrap;
}

.empty-state {
display: none;
}

.no-panels:empty + .empty-state {
display: block;
}
</style>
45 changes: 32 additions & 13 deletions src/io/import/processors/handleConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,46 @@ import { z } from 'zod';
import { ImportHandler } from '@/src/io/import/common';
import { useRectangleStore } from '@/src/store/tools/rectangles';
import { useRulerStore } from '@/src/store/tools/rulers';
import { useDataBrowserStore } from '@/src/store/data-browser';

const Color = z.string();
const color = z.string();

const Label = z.object({
color: Color,
const label = z.object({
color,
});

const RulerLabel = Label;
const rulerLabel = label;

const RectangleLabel = z.intersection(
Label,
const rectangleLabel = z.intersection(
label,
z.object({
fillColor: Color,
fillColor: color,
})
);

const Config = z.object({
labels: z.record(Label).or(z.null()).optional(),
rulerLabels: z.record(RulerLabel).or(z.null()).optional(),
rectangleLabels: z.record(RectangleLabel).or(z.null()).optional(),
const dataBrowser = z
.object({
hideSampleData: z.boolean().optional(),
})
.optional();

const config = z.object({
labels: z.record(label).or(z.null()).optional(),
rulerLabels: z.record(rulerLabel).or(z.null()).optional(),
rectangleLabels: z.record(rectangleLabel).or(z.null()).optional(),
dataBrowser,
});

type Config = z.infer<typeof config>;

const readConfigFile = async (configFile: File) => {
const decoder = new TextDecoder();
const ab = await configFile.arrayBuffer();
const text = decoder.decode(new Uint8Array(ab));
return Config.parse(JSON.parse(text));
return config.parse(JSON.parse(text));
};

const applyConfig = (manifest: z.infer<typeof Config>) => {
const applyLabels = (manifest: Config) => {
// pass through null labels, use fallback labels if undefined
const labelsIfUndefined = (toolLabels: typeof manifest.labels) => {
if (toolLabels === undefined) return manifest.labels;
Expand All @@ -42,6 +52,15 @@ const applyConfig = (manifest: z.infer<typeof Config>) => {
useRectangleStore().mergeLabels(labelsIfUndefined(manifest.rectangleLabels));
};

const applySampleData = (manifest: Config) => {
useDataBrowserStore().hideSampleData = !!manifest.dataBrowser?.hideSampleData;
};

const applyConfig = (manifest: Config) => {
applyLabels(manifest);
applySampleData(manifest);
};

/**
* Reads a JSON file with label config and updates stores.
* @param dataSource
Expand Down
9 changes: 9 additions & 0 deletions src/store/data-browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';

export const useDataBrowserStore = defineStore('data-browser', () => {
const hideSampleData = ref(false);
return {
hideSampleData,
};
});