diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 418d92d9825c5497471ac1ab0b5e30b1bd1cb20a..a7c26ecaf6b095e88c46063e1372e98a2da5316d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -440,7 +440,7 @@ load-website:prod: - WIKI_POD=$(kubectl --namespace ${NAMESPACE} get pods -l "app.kubernetes.io/name=df-wiki" --output jsonpath='{.items[0].metadata.name}') - kubectl --namespace ${NAMESPACE} cp .output/public/ ${WIKI_POD}:/website - kubectl --namespace ${NAMESPACE} exec ${WIKI_POD} -- bash -c 'cd /structure-data/sanitized-dump && find * -type d -exec sh -c "for d in $@; do (cd /usr/share/nginx/html/$d; cp --archive --recursive --symbolic-link /structure-data/sanitized-dump/$d/* .) done" argv0 {} +' - + diff --git a/components/ServerDbTable.vue b/components/ServerDbTable.vue index 4366407259772f91119f30e0807813f276a4fc5a..66a56ee6c6b6851004bcd82c81e6a36e43bedf4e 100644 --- a/components/ServerDbTable.vue +++ b/components/ServerDbTable.vue @@ -1,8 +1,6 @@ <script setup lang="ts"> // import type { FacetDistribution } from "meilisearch"; import { useCsvDownload } from "@/composables/useCsvDownload" -import { useNumericalFilter } from "@/composables/useNumericalfilter" - import { useSlots } from 'vue' import { useDisplay } from "vuetify"; import * as Plot from "@observablehq/plot"; @@ -32,6 +30,7 @@ export interface Props { db?: string sortBy?: SortItem[] facets: MaybeRef<string[]> + numericalFilters?: MaybeRef<string | undefined> dataTableServerProps: Record<string, any> columnsToDownload?: MaybeRef<string[] | undefined> } @@ -50,6 +49,7 @@ const props = withDefaults(defineProps<Props>(), { db: 'refseq', columnsToDownload: undefined, sortBy: () => [{ key: "type", order: "asc" }], + numericalFilters: undefined }); @@ -127,14 +127,9 @@ onMounted(async () => { -const { range: plddtsRange, stringifyFilter: plddtsFilter, reset: plddtsReset } = useNumericalFilter("plddts", 0, 100) -const { range: iptmRange, stringifyFilter: iptmFilter, reset: iptmReset } = useNumericalFilter("iptm+ptm", 0, 1) -const { range: pdockqRange, stringifyFilter: pdockqFilter, reset: pdockqReset } = useNumericalFilter("pDockQ", 0, 1) - - const computedFilter = computed(() => { - return [toValue(msFilter), toValue(plddtsFilter), toValue(iptmFilter), toValue(pdockqFilter)].filter(f => f !== undefined).join(" AND ") + return [toValue(msFilter), props.numericalFilters].filter(f => f !== undefined).join(" AND ") }) @@ -311,37 +306,7 @@ async function downloadData() { <v-card-text> </v-card-text> <v-card-text> - <v-row v-if="props.db === 'structure'"> - - <v-col md="12" lg="4"> - <v-range-slider v-model="plddtsRange" strict density="compact" hide-details="auto" label="pLDDT" - step="0.5" :min="0" :max="100" thumb-label="always" @update:modelValue="throttleSearch()"> - <template #append> - <v-btn variant="text" icon="md:restart_alt" @click="plddtsReset()"></v-btn> - </template> - </v-range-slider> - </v-col> - <v-col md="12" lg="4"> - - <v-range-slider v-model="iptmRange" strict density="compact" hide-details="auto" label="iptm+ptm" - step="0.1" :min="0" :max="1" thumb-label="always" @update:modelValue="throttleSearch()"> - <template #append> - <v-btn variant="text" icon="md:restart_alt" @click="iptmReset()"></v-btn> - </template> - </v-range-slider> - - - </v-col> - <!-- pdockqReset --> - <v-col md="12" lg="4"> - <v-range-slider v-model="pdockqRange" strict density="compact" hide-details="auto" label="pDockQ" - step="0.1" :min="0" :max="1" thumb-label="always" @update:modelValue="throttleSearch()"> - <template #append> - <v-btn variant="text" icon="md:restart_alt" @click="pdockqReset()"></v-btn> - </template> - </v-range-slider> - </v-col> - </v-row> + <slot name="numerical-filters" :search="throttleSearch"></slot> </v-card-text> <v-toolbar flat color="transparent"> </v-toolbar> <v-data-table-server v-if="!msError" v-model:page="page" color="primary" v-bind="dataTableServerProps" diff --git a/components/content/StructureDb.vue b/components/content/StructureDb.vue index 8aac14395478ca671a8c4f4281bc27bf594191bd..e4f533a4aed3690cfc417a15800e4359ea1294f2 100644 --- a/components/content/StructureDb.vue +++ b/components/content/StructureDb.vue @@ -2,6 +2,8 @@ import * as Plot from "@observablehq/plot"; import PlotFigure from "~/components/PlotFigure"; import type { SortItem } from "@/components/ServerDbTable.vue" +import { useNumericalFilter } from "@/composables/useNumericalfilter" + import { ServerDbTable } from "#components" const sortBy: Ref<SortItem[]> = ref([{ key: 'system', order: "asc" }]) @@ -27,6 +29,14 @@ const headers: Ref<Object[]> = ref([ ]) const { search: msSearch, result: msResult } = useMeiliSearch('structure') +const { range: plddtsRange, stringifyFilter: plddtsFilter, reset: plddtsReset } = useNumericalFilter("plddts", 0, 100) +const { range: iptmRange, stringifyFilter: iptmFilter, reset: iptmReset } = useNumericalFilter("iptm+ptm", 0, 1) +const { range: pdockqRange, stringifyFilter: pdockqFilter, reset: pdockqReset } = useNumericalFilter("pDockQ", 0, 1) + +const numericalFilters = computed(() => { + const listFilters = [plddtsFilter, iptmFilter, pdockqFilter].map(f => toValue(f)).filter(f => f !== undefined) + return listFilters.length > 0 ? listFilters.join(" AND ") : undefined +}) const defaultDataTableServerProps = ref({ showExpand: false @@ -43,6 +53,7 @@ const dataTableServerProps = computed(() => { + function namesToCollapsibleChips(names: string[], file: string | null = null) { if (file === null) { return names.filter((it) => it !== "").map(it => ({ title: it.split("__").pop() })) @@ -79,14 +90,44 @@ const plddtDistribution = computed(() => { -function remove(key) { - headers.value = headers.value.filter(header => header.key !== key) -} </script> <template> <ServerDbTable title="Predicted Structures" db="structure" :sortBy="sortBy" :facets="facets" - :data-table-server-props="dataTableServerProps"> + :data-table-server-props="dataTableServerProps" :numerical-filters="numericalFilters"> + + + + <template #numerical-filters="{ search }"> + <v-row> + <v-col md="12" lg="4"> + <v-range-slider v-model="plddtsRange" strict density="compact" hide-details="auto" label="pLDDT" + step="0.5" :min="0" :max="100" thumb-label="always" @update:modelValue="search()"> + <template #append> + <v-btn variant="text" icon="md:restart_alt" @click="plddtsReset()"></v-btn> + </template> + </v-range-slider> + </v-col> + <v-col md="12" lg="4"> + + <v-range-slider v-model="iptmRange" strict density="compact" hide-details="auto" label="iptm+ptm" + step="0.1" :min="0" :max="1" thumb-label="always" @update:modelValue="search()"> + <template #append> + <v-btn variant="text" icon="md:restart_alt" @click="iptmReset()"></v-btn> + </template> + </v-range-slider> + </v-col> + <!-- pdockqReset --> + <v-col md="12" lg="4"> + <v-range-slider v-model="pdockqRange" strict density="compact" hide-details="auto" label="pDockQ" + step="0.1" :min="0" :max="1" thumb-label="always" @update:modelValue="search()"> + <template #append> + <v-btn variant="text" icon="md:restart_alt" @click="pdockqReset()"></v-btn> + </template> + </v-range-slider> + </v-col> + </v-row> + </template> <template #[`item.proteins_in_the_prediction`]="{ item }"> <CollapsibleChips :items="namesToCollapsibleChips(item.proteins_in_the_prediction, item.fasta_file)">