From 56b9b195a9f024122c736ef6212c9679e0bf9b37 Mon Sep 17 00:00:00 2001
From: mlbonhomme <bonhomme@teklia.com>
Date: Tue, 20 Jun 2023 15:44:43 +0000
Subject: [PATCH] Show only compatible workers first when listing models

---
 src/components/Model/ModelPicker.vue | 30 +++++++++++++++++--
 src/components/Model/Selection.vue   |  7 ++++-
 src/views/Model/List.vue             | 43 +++++++++++++++++++++++-----
 src/views/TrainingProcessCreate.vue  |  1 +
 4 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/src/components/Model/ModelPicker.vue b/src/components/Model/ModelPicker.vue
index 387598b24..36e8b22cf 100644
--- a/src/components/Model/ModelPicker.vue
+++ b/src/components/Model/ModelPicker.vue
@@ -11,12 +11,23 @@
     <Modal is-large v-model="opened" :title="placeholder">
       <button
         type="button"
-        class="button is-info is-pulled-right"
+        class="button is-info is-pulled-right mb-2"
         v-on:click="creationModal = true"
       >
         Create a model
       </button>
-      <div class="title is-4">Available Models</div>
+
+      <template v-if="compatibleWorkerId">
+        <input
+          id="allModelsToggle"
+          type="checkbox"
+          class="switch is-rtl is-rounded is-info"
+          :checked="allModels"
+          v-on:change="allModels = !allModels"
+        />
+        <label for="allModelsToggle">Show all models</label>
+        <p class="help all-models-help mb-2">By default, only models compatible with the selected worker are shown.</p>
+      </template>
 
       <form
         v-if="modelsPage"
@@ -124,6 +135,10 @@ export default {
     placeholder: {
       type: String,
       default: 'Pick a model…'
+    },
+    compatibleWorkerId: {
+      type: String,
+      default: ''
     }
   },
   data: () => ({
@@ -132,7 +147,8 @@ export default {
     page: 1,
     modelsPage: null,
     nameFilter: '',
-    creationModal: false
+    creationModal: false,
+    allModels: false
   }),
   methods: {
     ...mapMutations('notifications', ['notify']),
@@ -142,6 +158,7 @@ export default {
       try {
         const payload = { page: this.page }
         if (this.nameFilter) payload.name = this.nameFilter
+        if (this.compatibleWorkerId && !this.allModels) payload.compatible_worker = this.compatibleWorkerId
         this.modelsPage = await this.listModels(payload)
       } catch (err) {
         this.notify({ type: 'error', text: `An error occurred listing models: ${errorParser(err)}` })
@@ -169,6 +186,10 @@ export default {
     opened: {
       // Reload in case the list has changed e.g. after a model is created
       handler: 'updateModelsPage'
+    },
+    allModels: {
+      immediate: true,
+      handler: 'updateModelsPage'
     }
   }
 }
@@ -179,4 +200,7 @@ export default {
 button {
   border-radius: 4px !important;
 }
+.all-models-help {
+  margin-top: -0.5em;
+}
 </style>
diff --git a/src/components/Model/Selection.vue b/src/components/Model/Selection.vue
index b5d2c9823..e709ed952 100644
--- a/src/components/Model/Selection.vue
+++ b/src/components/Model/Selection.vue
@@ -22,7 +22,12 @@
       is-large
       title="Select a model version for this worker"
     >
-      <ModelList :process-id="processId" :worker-run-id="runId" :create-button="false" />
+      <ModelList
+        :process-id="processId"
+        :worker-run-id="runId"
+        :compatible-worker-id="workerRun.worker_version.worker.id"
+        :training-mode="false"
+      />
     </Modal>
   </span>
 </template>
diff --git a/src/views/Model/List.vue b/src/views/Model/List.vue
index 38eb04f0d..31a800f56 100644
--- a/src/views/Model/List.vue
+++ b/src/views/Model/List.vue
@@ -5,12 +5,23 @@
         <router-link
           class="button is-primary is-pulled-right"
           :to="{ name: 'model-create' }"
-          v-if="createButton"
+          v-if="trainingMode"
         >
           Create a model
         </router-link>
 
-        <div class="title is-4">Available Models</div>
+        <div v-if="compatibleWorkerId">
+          <input
+            id="allModelsToggle"
+            type="checkbox"
+            class="switch is-rtl is-rounded is-info"
+            :checked="allModels"
+            v-on:change="allModels = !allModels"
+          />
+          <label class="is-pulled-right" for="allModelsToggle">Show all models</label>
+          <p class="help all-models-help is-pulled-right mb-2">By default, only models compatible with the selected worker are shown.</p>
+        </div>
+
         <!-- Selection of a worker is required to list versions -->
         <form
           v-if="modelsPage"
@@ -97,7 +108,7 @@ export default {
   },
   props: {
     processId: {
-      /*
+      /**
        * If a process ID is defined, this component allows to select a model
        * and add one of its version to the process workflow.
        * Otherwise, list models with their versions and members.
@@ -109,14 +120,23 @@ export default {
       type: String,
       default: ''
     },
-    /*
+    /**
      * When selecting a model to use with a worker in a Workers process, it does
      * not make sense to show the Create model button to create an empty model
-     * version. This prop can be used to show or hide that button.
+     * version. This prop can be used to signal whether or not this component is
+     * being used to configure a training process.
      */
-    createButton: {
+    trainingMode: {
       type: Boolean,
       default: true
+    },
+    /**
+     * A Worker UUID can be passed down by the parent component to allow
+     * filtering models by compatible_worker.
+     */
+    compatibleWorkerId: {
+      type: String,
+      default: ''
     }
   },
   data: () => ({
@@ -125,7 +145,8 @@ export default {
     // ID of the selected model
     selectedModel: null,
     page: 1,
-    nameFilter: ''
+    nameFilter: '',
+    allModels: false
   }),
   methods: {
     ...mapMutations('notifications', ['notify']),
@@ -136,6 +157,7 @@ export default {
         this.selectedModel = null
         const payload = { page: this.page }
         if (this.nameFilter) payload.name = this.nameFilter
+        if (this.compatibleWorkerId && !this.allModels) payload.compatible_worker = this.compatibleWorkerId
         this.modelsPage = await this.listModels(payload)
       } catch (err) {
         this.notify({ type: 'error', text: `An error occurred listing models: ${errorParser(err)}` })
@@ -153,6 +175,10 @@ export default {
     page: {
       immediate: true,
       handler: 'updateModelsPage'
+    },
+    allModels: {
+      immediate: true,
+      handler: 'updateModelsPage'
     }
   }
 }
@@ -168,4 +194,7 @@ export default {
     }
   }
 }
+.all-models-help {
+  margin-top: -0.5em;
+}
 </style>
diff --git a/src/views/TrainingProcessCreate.vue b/src/views/TrainingProcessCreate.vue
index 0e90e5691..b493e67fd 100644
--- a/src/views/TrainingProcessCreate.vue
+++ b/src/views/TrainingProcessCreate.vue
@@ -125,6 +125,7 @@
             v-model="model"
             placeholder="Select a model to train"
             :class="{ 'is-danger': fieldErrors.model_id }"
+            :compatible-worker-id="workerVersion?.worker.id"
           />
         </div>
         <div class="control" v-if="model">
-- 
GitLab