From 68520c303f086dfe4ca935a3ada18eb216c73a10 Mon Sep 17 00:00:00 2001 From: Theo Lesage <tlesage@teklia.com> Date: Mon, 25 Mar 2024 15:26:30 +0000 Subject: [PATCH] Add a field for deleting worker results by filtering worker runs --- src/api/mlresults.ts | 5 + .../Process/Workers/DeleteResultsModal.vue | 183 +++++++++++++----- 2 files changed, 141 insertions(+), 47 deletions(-) diff --git a/src/api/mlresults.ts b/src/api/mlresults.ts index 497acb32f..e8ac9116e 100644 --- a/src/api/mlresults.ts +++ b/src/api/mlresults.ts @@ -8,6 +8,11 @@ export type DeleteWorkerResultsParameters = { */ element_id?: UUID + /** + * Delete results produced by a specific worker run + */ + worker_run_id?: UUID + /** * Delete results produced with a specific worker version. */ diff --git a/src/components/Process/Workers/DeleteResultsModal.vue b/src/components/Process/Workers/DeleteResultsModal.vue index 3c702b0fa..a41907c56 100644 --- a/src/components/Process/Workers/DeleteResultsModal.vue +++ b/src/components/Process/Workers/DeleteResultsModal.vue @@ -5,7 +5,9 @@ :is-large="!advancedMode" > <template v-slot:header> - <p class="modal-card-title mr-5">{{ truncateLong('Delete results ' + originDescription) }}</p> + <p class="modal-card-title mr-5"> + {{ truncateLong('Delete results ' + originDescription) }} + </p> <span class="ml-auto"> <input id="advancedModeSwitch" @@ -13,11 +15,36 @@ class="switch is-rtl is-rounded is-info" v-model="advancedMode" /> - <label class="is-pulled-right mr-4" for="advancedModeSwitch">Advanced mode</label> + <label + class="is-pulled-right mr-4" + for="advancedModeSwitch" + >Advanced mode</label> </span> </template> <div v-if="advancedMode" class="content"> + <div class="field"> + <label class="label">Worker run UUID</label> + <div class="control"> + <input + type="text" + placeholder="00000000-0000-0000-0000-000000000000" + maxlength="36" + class="input uuid-input" + v-model="workerRunId" + :disabled="loading || undefined" + /> + <template v-if="errors.worker_run_id"> + <p + class="help is-danger" + v-for="err in errors.worker_run_id" + :key="err" + > + {{ err }} + </p> + </template> + </div> + </div> <div class="field"> <label class="label">Worker version UUID</label> <div class="control"> @@ -27,7 +54,7 @@ maxlength="36" class="input uuid-input" v-model="workerVersionId" - :disabled="loading || null" + :disabled="inWorkerRunMode || loading || undefined" /> <template v-if="errors.worker_version_id"> <p @@ -49,7 +76,7 @@ maxlength="36" class="input uuid-input" v-model="modelVersionId" - :disabled="loading || null" + :disabled="inWorkerRunMode || loading || undefined" /> <template v-if="errors.model_version_id"> <p @@ -68,16 +95,19 @@ <span class="control"> <label v-for="(value, label) in configurationRadio" - :key="value" + :key="label" class="radio ml-4" - :class="{ 'active': configurationField === value }" + :class="{ active: configurationField === value }" v-on:click.capture="setConfigurationField(value)" > <input class="is-checkradio" type="radio" - :checked="configurationField === value || null" - :disabled="loading || null" + :checked=" + (configurationField === value && !inWorkerRunMode) || + undefined + " + :disabled="inWorkerRunMode || loading || undefined" /> {{ label }} </label> @@ -91,7 +121,12 @@ maxlength="36" class="input uuid-input" v-model="configurationId" - :disabled="configurationField !== true || loading || null" + :disabled=" + inWorkerRunMode || + configurationField !== true || + loading || + undefined + " /> <template v-if="errors.configuration_id"> <p @@ -104,11 +139,7 @@ </template> </div> </div> - <button - class="button is-danger is-light" - type="button" - v-on:click="checkManual" - > + <button class="button is-danger" type="button" v-on:click="checkManual"> Delete </button> </div> @@ -124,16 +155,28 @@ </tr> </thead> <tbody> - <tr v-for="({ worker_version, worker_configuration, model_version }, cacheId) in workerVersionsCache" :key="cacheId"> + <tr + v-for="( + { worker_version, worker_configuration, model_version }, cacheId + ) in workerVersionsCache" + :key="cacheId" + > <td> <WorkerVersionSummary :worker-version="worker_version" /> </td> <td> - <ModelVersionSummary v-if="model_version" :model-version="model_version" /> + <ModelVersionSummary + v-if="model_version" + :model-version="model_version" + /> <template v-else>—</template> </td> <td> - <ConfigurationSummary v-if="worker_configuration" :configuration="worker_configuration" :worker-version="worker_version" /> + <ConfigurationSummary + v-if="worker_configuration" + :configuration="worker_configuration" + :worker-version="worker_version" + /> <template v-else>—</template> </td> <td> @@ -154,13 +197,16 @@ </template> </Modal> - <Modal - v-model="confirmationModal" - title="Confirm deletion" - > + <Modal v-model="confirmationModal" title="Confirm deletion"> <div class="content"> - <template v-if="deletesAll"> - You are about to delete <strong>all worker results</strong> {{ originDescription }}. + <template v-if="inWorkerRunMode"> + You are about to delete all results from worker run <strong>{{ workerRunId }}</strong> + {{ originDescription }}. + </template> + + <template v-else-if="deletesAll"> + You are about to delete <strong>all worker results</strong> + {{ originDescription }}. </template> <template v-else> @@ -169,13 +215,21 @@ </p> </template> <hr class="my-3" /> - <p class="mb-0">Child elements of these results will also be deleted recursively.</p> + <p class="mb-0"> + Child elements of these results will also be deleted recursively. + </p> <p>This action is irreversible.</p> </div> <template v-slot:footer="{ close }"> <button class="button" v-on:click="close">Cancel</button> - <button class="button is-danger ml-auto" v-on:click="performDelete" :title="originDescription">{{ truncateLong('Delete results ' + originDescription) }}</button> + <button + class="button is-danger ml-auto" + v-on:click="performDelete" + :title="originDescription" + > + {{ truncateLong('Delete results ' + originDescription) }} + </button> </template> </Modal> </template> @@ -196,10 +250,7 @@ import ModelVersionSummary from '@/components/Model/Versions/Summary.vue' import ConfigurationSummary from '@/components/Process/Workers/Configurations/Summary.vue' export default defineComponent({ - mixins: [ - corporaMixin, - truncateMixin - ], + mixins: [corporaMixin, truncateMixin], components: { Modal, WorkerVersionSummary, @@ -219,7 +270,7 @@ export default defineComponent({ */ corpusId: { type: String as PropType<UUID>, - validator: value => typeof value === 'string' && UUID_REGEX.test(value), + validator: (value) => typeof value === 'string' && UUID_REGEX.test(value), required: true }, /** @@ -228,7 +279,7 @@ export default defineComponent({ */ elementId: { type: String as PropType<UUID>, - validator: value => typeof value === 'string' && UUID_REGEX.test(value), + validator: (value) => typeof value === 'string' && UUID_REGEX.test(value), default: null }, /** @@ -250,6 +301,7 @@ export default defineComponent({ /** * Custom fields for manual deletion */ + workerRunId: '', workerVersionId: '', modelVersionId: '', configurationId: '', @@ -302,40 +354,64 @@ export default defineComponent({ messages.push(`You are about to delete results ${this.originDescription}`) // Worker version const versionName = this.truncateLong( - this.versionCacheToDelete?.worker_version?.worker?.name || this.workerVersionId || 'Any' + this.versionCacheToDelete?.worker_version?.worker?.name || + this.workerVersionId || + 'Any' ) messages.push(`• Worker version: ${versionName}`) // Model version if (this.advancedMode) { messages.push(`• Model version: ${this.modelVersionId || 'Any'}`) } else if (this.versionCacheToDelete?.model_version) { - messages.push(`• Model version: ${this.versionCacheToDelete.model_version.model.name}`) + messages.push( + `• Model version: ${this.versionCacheToDelete.model_version.model.name}` + ) } // Worker configuration const confName = this.advancedMode - ? this.configurationId || (this.configurationField === null && 'Any') || 'None' - : this.truncateLong(this.versionCacheToDelete?.worker_configuration?.name || 'None') + ? this.configurationId || + (this.configurationField === null && 'Any') || + 'None' + : this.truncateLong( + this.versionCacheToDelete?.worker_configuration?.name || 'None' + ) messages.push(`• Configuration: ${confName}`) return messages }, payload () { - const payload: DeleteWorkerResultsParameters = { use_selection: this.selection } + const payload: DeleteWorkerResultsParameters = { + use_selection: this.selection + } if (this.elementId) payload.element_id = this.elementId if (this.advancedMode) { - if (this.workerVersionId) payload.worker_version_id = this.workerVersionId + if (this.workerRunId) payload.worker_run_id = this.workerRunId + if (this.workerVersionId) { payload.worker_version_id = this.workerVersionId } if (this.modelVersionId) payload.model_version_id = this.modelVersionId - if (this.configurationField !== null) { payload.configuration_id = this.configurationField ? this.configurationId : false } + if (this.configurationField !== null) { + payload.configuration_id = this.configurationField + ? this.configurationId + : false + } } else if (this.versionCacheToDelete !== null) { payload.worker_version_id = this.versionCacheToDelete.worker_version.id - payload.configuration_id = this.versionCacheToDelete?.worker_configuration?.id ?? false - if (this.versionCacheToDelete?.model_version?.id) payload.model_version_id = this.versionCacheToDelete.model_version.id + payload.configuration_id = + this.versionCacheToDelete?.worker_configuration?.id ?? false + if (this.versionCacheToDelete?.model_version?.id) { payload.model_version_id = this.versionCacheToDelete.model_version.id } } return payload + }, + inWorkerRunMode (): boolean { + return this.workerRunId !== '' } }, methods: { - ...mapActions(useMLResultsStore, ['listWorkerVersionsCache', 'deleteWorkerResults']), - updateModelValue (value: boolean) { this.$emit('update:modelValue', value) }, + ...mapActions(useMLResultsStore, [ + 'listWorkerVersionsCache', + 'deleteWorkerResults' + ]), + updateModelValue (value: boolean) { + this.$emit('update:modelValue', value) + }, select (cacheId: UUID) { this.cacheUUIDToDelete = cacheId this.confirmationModal = true @@ -345,11 +421,24 @@ export default defineComponent({ }, checkManual () { this.errors = {} - if (this.workerVersionId && !UUID_REGEX.test(this.workerVersionId)) { this.errors.worker_version_id = ['This value must be a valid UUID.'] } - if (this.modelVersionId && !UUID_REGEX.test(this.modelVersionId)) { this.errors.model_version_id = ['This value must be a valid UUID.'] } - if (this.configurationId && !UUID_REGEX.test(this.configurationId)) { this.errors.configuration_id = ['This value must be a valid UUID.'] } - if (this.configurationField === true && this.configurationId === '') { this.errors.configuration_id = ['This value must be set.'] } - if (Object.keys(this.errors).length === 0) { this.confirmationModal = true } + if (this.workerRunId && !UUID_REGEX.test(this.workerRunId)) { + this.errors.worker_run_id = ['This value must be a valid UUID.'] + } + if (this.workerVersionId && !UUID_REGEX.test(this.workerVersionId)) { + this.errors.worker_version_id = ['This value must be a valid UUID.'] + } + if (this.modelVersionId && !UUID_REGEX.test(this.modelVersionId)) { + this.errors.model_version_id = ['This value must be a valid UUID.'] + } + if (this.configurationId && !UUID_REGEX.test(this.configurationId)) { + this.errors.configuration_id = ['This value must be a valid UUID.'] + } + if (this.configurationField === true && this.configurationId === '') { + this.errors.configuration_id = ['This value must be set.'] + } + if (Object.keys(this.errors).length === 0) { + this.confirmationModal = true + } }, async performDelete () { this.errors = {} -- GitLab