Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cohort Updating/Sharing #116

Merged
merged 5 commits into from
Apr 1, 2024
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ is shown underneath each video sequence.

### Girder Client Web Development

`docker exec -it dive_name_girder_1 bash`
`docker exec -it dive-dsa-girder-1 bash`
`cd /opt/dive/src`
`apt-get update && apt-get install -y npm`
`girder build`
Expand Down
6 changes: 3 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "dive-dsa",
"version": "1.10.1",
"version": "1.10.2",
"author": {
"name": "Kitware, Inc.",
"email": "viame-web@kitware.com"
"email": "Bryon.Lewis@kitware.com"
},
"description": "DIVE annotation platform for Digital Slide Archive",
"homepage": "https://kitware.github.io/dive",
"homepage": "https://digitalslidearchive.github.io/dive-dsa/",
"license": "Apache-2.0",
"scripts": {
"serve": "vue-cli-service serve platform/web-girder/main.ts",
Expand Down
6 changes: 3 additions & 3 deletions client/platform/web-girder/api/divemetadata.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface MetadataFilterKeysItem {

}

export interface DIVEMetadaFilter {
export interface DIVEMetadataFilter {
search?: string;
metadataFilters?: Record<string, MetadataFilterItem>;
}
Expand Down Expand Up @@ -53,15 +53,15 @@ function getMetadataFilterValues(folderId: string, keys?: string[]) {
});
}

function filterDiveMetadata(folderId: string, filters: DIVEMetadaFilter, offset = 0, limit = 50, sort = 'filename', sortdir = -1) {
function filterDiveMetadata(folderId: string, filters: DIVEMetadataFilter, offset = 0, limit = 50, sort = 'filename', sortdir = -1) {
return girderRest.get<DIVEMetadataResults>(`dive_metadata/${folderId}/filter`, {
params: {
filters, offset, limit, sort, sortdir,
},
});
}

function createDiveMetadataClone(folder: string, filters: DIVEMetadaFilter, destFolder: string) {
function createDiveMetadataClone(folder: string, filters: DIVEMetadataFilter, destFolder: string) {
return girderRest.post<string>(`dive_metadata/${folder}/clone_filter`, null, {
params: {
baseFolder: folder, filters, destFolder,
Expand Down
12 changes: 11 additions & 1 deletion client/platform/web-girder/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,17 @@ const router = new Router({
path: '/metadata/:id/',
name: 'metadata',
component: DIVEMetadataSearchVue,
props: true,
props: (route) => {
if (route.query.filter) {
return {
id: route.params.id, // Map route parameter to prop
filter: JSON.parse(route.query.filter as string), // Map query parameter to prop
};
}
return {
id: route.params.id,
};
},
beforeEnter,
},
{
Expand Down
4 changes: 2 additions & 2 deletions client/platform/web-girder/views/DIVEMetadataClone.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import useRequest from 'dive-common/use/useRequest';
import { RootlessLocationType } from 'platform/web-girder/store/types';
import { useGirderRest } from 'platform/web-girder/plugins/girder';
import { useRouter } from 'vue-router/composables';
import { DIVEMetadaFilter, createDiveMetadataClone } from 'platform/web-girder/api/divemetadata.service';
import { DIVEMetadataFilter, createDiveMetadataClone } from 'platform/web-girder/api/divemetadata.service';

export default defineComponent({
components: { GirderFileManager },
Expand All @@ -19,7 +19,7 @@ export default defineComponent({
},
filter: {
// Filter to apply to the dataset
type: Object as PropType<DIVEMetadaFilter>,
type: Object as PropType<DIVEMetadataFilter>,
required: true,
},
},
Expand Down
41 changes: 34 additions & 7 deletions client/platform/web-girder/views/DIVEMetadataFilter.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import {
DIVEMetadaFilter, MetadataFilterItem, DIVEMetadataFilterValueResults, getMetadataFilterValues, FilterDisplayConfig,
DIVEMetadataFilter, MetadataFilterItem, DIVEMetadataFilterValueResults, getMetadataFilterValues, FilterDisplayConfig,
} from 'platform/web-girder/api/divemetadata.service';
import {
computed, defineComponent, onBeforeMount, PropType, Ref, ref, watch,
Expand Down Expand Up @@ -28,9 +28,14 @@ export default defineComponent({
type: Object as PropType<FilterDisplayConfig>,
required: true,
},
rootFilter: {
type: Object as PropType<DIVEMetadataFilter>,
default: () => {},

},
},
setup(props, { emit }) {
const search = ref('');
const search = ref(props.rootFilter.search || '');
const filters: Ref<DIVEMetadataFilterValueResults['metadataKeys']> = ref({});
const splitFilters = computed(() => {
const advanced: DIVEMetadataFilterValueResults['metadataKeys'] = {};
Expand All @@ -45,7 +50,7 @@ export default defineComponent({
return { advanced, displayed };
});
const filtersOn = ref(false);
const currentFilter: Ref<DIVEMetadaFilter> = ref({});
const currentFilter: Ref<DIVEMetadataFilter> = ref({});
const pageList = computed(() => {
const list = [];
for (let i = 0; i < props.totalPages; i += 1) {
Expand All @@ -58,8 +63,22 @@ export default defineComponent({
const filterData = await getMetadataFilterValues(props.id);
filters.value = filterData.data.metadataKeys;
};
onBeforeMount(() => {
getFilters();
onBeforeMount(async () => {
await getFilters();
loadCurrentFilter();
});

const loadCurrentFilter = () => {
if (props.rootFilter.metadataFilters && Object.keys(props.rootFilter.metadataFilters).length) {
currentFilter.value = props.rootFilter.metadataFilters;
}
if (props.rootFilter.search) {
search.value = props.rootFilter.search;
}
};

watch(() => props.rootFilter, () => {
loadCurrentFilter();
});

watch(search, () => {
Expand Down Expand Up @@ -94,6 +113,13 @@ export default defineComponent({
emit('update:currentPage', page - 1);
};

const getDefaultValue = (key: string) => {
if (props.rootFilter?.metadataFilters && props.rootFilter.metadataFilters[key]) {
return props.rootFilter.metadataFilters[key].value;
}
return undefined;
};

return {

pageList,
Expand All @@ -104,6 +130,7 @@ export default defineComponent({
currentFilter,
changePage,
updateFilter,
getDefaultValue,
};
},
});
Expand Down Expand Up @@ -148,7 +175,7 @@ export default defineComponent({
>
<v-spacer />
<div v-for="(filterItem, key) in splitFilters.displayed" :key="`filterItem_${key}`">
<DIVEMetadataFilterItemVue :label="key" :filter-item="filterItem" @update-value="updateFilter(key, $event)" />
<DIVEMetadataFilterItemVue :label="key" :default-value="getDefaultValue(key)" :filter-item="filterItem" @update-value="updateFilter(key, $event)" />
</div>
<v-spacer />
</v-row>
Expand All @@ -159,7 +186,7 @@ export default defineComponent({
mt-3"
>
<div v-for="(filterItem, key) in splitFilters.advanced" :key="`filterItem_${key}`">
<DIVEMetadataFilterItemVue :label="key" :filter-item="filterItem" @update-value="updateFilter(key, $event, filterItem.category)" />
<DIVEMetadataFilterItemVue :label="key" :default-value="getDefaultValue(key)" :filter-item="filterItem" @update-value="updateFilter(key, $event, filterItem.category)" />
</div>
</v-row>
<v-row class="mt-3">
Expand Down
6 changes: 5 additions & 1 deletion client/platform/web-girder/views/DIVEMetadataFilterItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ export default defineComponent({
type: String,
required: true,
},
defaultValue: {
type: [String, Number, Array, Boolean] as PropType<boolean | string | number | string[] | number[]>,
default: undefined,
},
},
setup(props, { emit }) {
const set = ref(props.filterItem.set);
const value: Ref<undefined | number | string | string[] | number[]> = ref(undefined);
const value: Ref<undefined | boolean | number | string | string[] | number[]> = ref(props.defaultValue);
const rangeFilterEnabled = ref(false);
const categoryLimit = ref(20);
watch(value, () => {
Expand Down
31 changes: 22 additions & 9 deletions client/platform/web-girder/views/DIVEMetadataSearch.vue
Original file line number Diff line number Diff line change
@@ -1,39 +1,45 @@
<script lang="ts">
import {
computed,
defineComponent, onMounted, ref, Ref,
defineComponent, onMounted, ref, Ref, PropType,
} from 'vue';
import {
DIVEMetadataResults, DIVEMetadaFilter, filterDiveMetadata, MetadataResultItem, FilterDisplayConfig,
DIVEMetadataResults, DIVEMetadataFilter, filterDiveMetadata, MetadataResultItem, FilterDisplayConfig,
} from 'platform/web-girder/api/divemetadata.service';
import { getFolder } from 'platform/web-girder/api/girder.service';
import DIVEMetadataFilter from './DIVEMetadataFilter.vue';
import { useRouter } from 'vue-router/composables';
import DIVEMetadataFilterVue from './DIVEMetadataFilter.vue';
import DIVEMetadataCloneVue from './DIVEMetadataClone.vue';

export default defineComponent({
name: 'DIVEMetadataSearch',
components: {
DIVEMetadataFilter,
DIVEMetadataFilterVue,
DIVEMetadataCloneVue,
},
props: {
id: {
type: String,
required: true,
},
filter: {
type: Object as PropType<DIVEMetadataFilter>,
default: () => { },
},
},
setup(props) {
const folderList: Ref<MetadataResultItem[]> = ref([]);
const router = useRouter();
const displayConfig: Ref<FilterDisplayConfig> = ref({ display: [], hide: [] });
const totalPages = ref(0);
const currentPage = ref(0);
const filters: Ref<DIVEMetadaFilter> = ref({ });
const filters: Ref<DIVEMetadataFilter> = ref(props.filter || {});
const locationStore = {
_id: props.id,
_modelType: 'folder',
};

const currentFilter: Ref<DIVEMetadaFilter> = ref({});
const currentFilter: Ref<DIVEMetadataFilter> = ref(props.filter || {});

const processFilteredMetadataResults = (data: DIVEMetadataResults) => {
folderList.value = data.pageResults;
Expand All @@ -51,18 +57,23 @@ export default defineComponent({
}
};

const updateURLParams = () => {
router.replace({ path: props.id, params: { id: props.id }, query: { filter: JSON.stringify(filters.value) } });
};

onMounted(() => {
getFolderInfo(props.id);
getData();
});

const updateFilter = async (filter?: DIVEMetadaFilter) => {
const updateFilter = async (filter?: DIVEMetadataFilter) => {
if (filter) {
filters.value = filter;
currentPage.value = 0;
currentFilter.value = filter;
}
const sort = 'filename';
updateURLParams();
const { data } = await filterDiveMetadata(props.id, { ...filters.value }, currentPage.value * 50, 50, sort);
processFilteredMetadataResults(data);
};
Expand Down Expand Up @@ -95,6 +106,7 @@ export default defineComponent({
folderList,
displayConfig,
advanced,
filters,
//Cloning
openClone,
currentFilter,
Expand All @@ -105,9 +117,10 @@ export default defineComponent({

<template>
<v-container>
<DIVEMetadataFilter
<DIVEMetadataFilterVue
:id="id"
:current-page="currentPage"
:root-filter="filters"
:total-pages="totalPages"
:display-config="displayConfig"
@update:currentPage="changePage($event)"
Expand Down Expand Up @@ -145,7 +158,7 @@ export default defineComponent({
<span>Create a clone of this data</span>
</v-tooltip>
</template>
</DIVEMetadataFilter>
</DIVEMetadataFilterVue>
<span v-if="!openClone">
<v-card
v-for="(item, key) in folderList"
Expand Down
18 changes: 18 additions & 0 deletions client/platform/web-girder/views/DataBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ export default defineComponent({
return item._modelType === 'folder' && item.meta.DIVEMetadata;
}

function isClonedMetadataFolder(item: GirderModel) {
if (item._modelType === 'folder' && item.meta.DIVEMetadataClonedFilter && item.meta.DIVEMetadataClonedFilterBase) {
return { id: item.meta.DIVEMetadataClonedFilterBase, filter: item.meta.DIVEMetadataClonedFilter };
}
return false;
}

const shouldShowUpload = computed(() => (
locationStore.location
&& !getters['Location/locationIsViameFolder']
Expand All @@ -72,6 +79,7 @@ export default defineComponent({
/* methods */
isAnnotationFolder,
isMetadataFolder,
isClonedMetadataFolder,
handleNotification,
setLocation,
updateUploading,
Expand Down Expand Up @@ -152,6 +160,16 @@ export default defineComponent({
>
View Metadata
</v-btn>
<v-btn
v-if="isClonedMetadataFolder(item)"
class="ml-2"
x-small
color="info"
depressed
:to="{ name: 'metadata', params: { id: isClonedMetadataFolder(item).id }, query: { filter: isClonedMetadataFolder(item).filter } }"
>
View Metadata Filter
</v-btn>

<v-chip
v-if="(item.foreign_media_id)"
Expand Down
Loading
Loading