From eec2d60a7641a0ef4956784d099ce1dd1c68b392 Mon Sep 17 00:00:00 2001
From: mlbonhomme <bonhomme@teklia.com>
Date: Thu, 16 Jan 2025 12:53:27 +0100
Subject: [PATCH 1/4] simple mode / advanced mode / all version

---
 src/api/worker.ts                             |   3 +
 .../Process/Workers/Versions/List.vue         | 174 ++++++++++++------
 src/stores/workers.ts                         |  10 +
 tests/unit/stores/workers.spec.js             |  16 ++
 4 files changed, 148 insertions(+), 55 deletions(-)

diff --git a/src/api/worker.ts b/src/api/worker.ts
index dab24d177..69d4b745f 100644
--- a/src/api/worker.ts
+++ b/src/api/worker.ts
@@ -34,6 +34,9 @@ export const listWorkerVersions = unique(async (workerId: UUID, params: WorkerVe
 // Retrieve a worker version
 export const retrieveWorkerVersion = unique(async (id: UUID): Promise<WorkerVersion> => (await axios.get(`/workers/versions/${id}/`)).data)
 
+// Retrieve the recommended worker version for a worker
+export const retrieveRecommendedWorkerVersion = unique(async(workerId: UUID): Promise<WorkerVersion> => (await axios.get(`/workers/${workerId}/versions/recommended/`)).data)
+
 // Retrieve a worker
 export const retrieveWorker = unique(async (id: UUID): Promise<Worker> => (await axios.get(`/workers/${id}/`)).data)
 
diff --git a/src/components/Process/Workers/Versions/List.vue b/src/components/Process/Workers/Versions/List.vue
index 1f2a62822..4f607497c 100644
--- a/src/components/Process/Workers/Versions/List.vue
+++ b/src/components/Process/Workers/Versions/List.vue
@@ -1,58 +1,99 @@
 <template>
-  <template v-if="worker.repository_url">
-    <input
-      id="switchAll"
-      type="checkbox"
-      class="switch is-rtl is-rounded is-info"
-      v-model="advancedMode"
-    />
-    <label class="is-pulled-right ml-3" for="switchAll">Display all versions</label>
+  <div class="columns">
+    <div class="column"><h2 class="title is-4">Versions</h2></div>
+    <div class="column is-narrow">
+      <span class="select">
+        <select
+          v-model="advancedMode"
+        >
+          <option :value="false">Simple mode</option>
+          <option :value="true">Advanced mode</option>
+        </select>
+      </span>
+    </div>
+  </div>
+  <template v-if="advancedMode">
+    <div class="columns">
+      <div class="column"></div>
+      <div class="column is-narrow">
+        <template v-if="worker.repository_url">
+          <input
+            id="switchAll"
+            type="checkbox"
+            class="switch is-rtl is-rounded is-info"
+            v-model="allVersions"
+          />
+          <label class="ml-3" for="switchAll">Display all versions</label>
+        </template>
+        <CreateForm :worker-id="worker.id" class="is-pulled-right ml-3" v-on:created="fetchVersions" />
+      </div>
+    </div>
+
+    <span class="is-clearfix"></span>
+    <div v-if="versionsError" class="notification is-warning">{{ versionsError }}</div>
+    <Paginator
+      v-else
+      :response="versionsPage"
+      :loading="loading"
+      v-slot="{ results }"
+      v-model:page="page"
+      :page-size="pageSize"
+      singular="version"
+      plural="versions"
+    >
+      <table class="table is-fullwidth is-hoverable">
+        <thead>
+          <tr>
+            <th>Id</th>
+            <th>Version</th>
+            <th>Tag</th>
+            <th>Branch</th>
+            <th>State</th>
+            <th>Docker image</th>
+            <th>Created</th>
+            <th v-if="processId || selectable || haveRevisions(results)">Actions</th>
+          </tr>
+        </thead>
+        <tbody>
+          <Row
+            :process-id="processId"
+            :selectable="selectable"
+            :local="local"
+            :key="version.id"
+            :version="version"
+            v-for="version in results"
+            v-on:selected-version="$emit('selected-version', $event)"
+          />
+        </tbody>
+      </table>
+    </Paginator>
+  </template>
+  <template v-else>
+    <div v-if="loading">
+      <span class="loader is-size-2 mx-auto"></span>
+    </div>
+    <div class="columns is-vcentered" v-else-if="recommendedWorkerVersions[worker.id]">
+      <div class="column is-narrow">
+        Worker version <span class="tag">{{ recommendedWorkerVersions[worker.id].branch || recommendedWorkerVersions[worker.id].tag }}</span> (recommended)
+      </div>
+      <div class="column">
+        <button class="button is-success ml-2">
+          use this version
+        </button>
+      </div>
+    </div>
+    <div class="notification is-error" v-else-if="recommendedVersionError">
+      An error occurred while loading the recommended worker version: {{ recommendedVersionError }}
+    </div>
+    <div class="notification is-warning" v-else>
+      There is no recommended worker version for this worker. Please select the "advanced mode" in the menu above to see all worker versions and select one.
+    </div>
   </template>
-  <CreateForm :worker-id="worker.id" class="is-pulled-right" v-on:created="fetchVersions" />
-  <h2 class="title is-4">Versions</h2>
-  <span class="is-clearfix"></span>
-  <div v-if="versionsError" class="notification is-warning">{{ versionsError }}</div>
-  <Paginator
-    v-else
-    :response="versionsPage"
-    :loading="loading"
-    v-slot="{ results }"
-    v-model:page="page"
-    :page-size="pageSize"
-    singular="version"
-    plural="versions"
-  >
-    <table class="table is-fullwidth is-hoverable">
-      <thead>
-        <tr>
-          <th>Id</th>
-          <th>Version</th>
-          <th>Tag</th>
-          <th>Branch</th>
-          <th>State</th>
-          <th>Docker image</th>
-          <th>Created</th>
-          <th v-if="processId || selectable || haveRevisions(results)">Actions</th>
-        </tr>
-      </thead>
-      <tbody>
-        <Row
-          :process-id="processId"
-          :selectable="selectable"
-          :local="local"
-          :key="version.id"
-          :version="version"
-          v-for="version in results"
-          v-on:selected-version="$emit('selected-version', $event)"
-        />
-      </tbody>
-    </table>
-  </Paginator>
 </template>
 
 <script lang="ts">
 import { PropType, defineComponent } from 'vue'
-import { mapActions } from 'pinia'
+import { mapActions, mapState } from 'pinia'
 import { errorParser } from '@/helpers'
 import Paginator from '@/components/Paginator.vue'
 import Row from './Row.vue'
@@ -99,13 +140,17 @@ export default defineComponent({
   },
   data: () => ({
     versionsError: null as string | null,
+    recommendedVersionError: null as string | null,
     versionsPage: null as PageNumberPagination<WorkerVersion> | null,
     loading: false,
     page: 1,
-    // If set to false, only display versions with a tag
-    advancedMode: false
+    // If set to false, only show the "recommended" version for this worker
+    advancedMode: false,
+    // If set to false, only display versions with a tag or from the master/main branch
+    allVersions: false
   }),
   computed: {
+    ...mapState(useWorkerStore, ['recommendedWorkerVersions']),
     pageSize () {
       // Use a small page size when not in process creation mode because members are displayed on the same column
       return this.processId ? 20 : 5
@@ -113,13 +158,14 @@ export default defineComponent({
   },
   methods: {
     ...mapActions(useNotificationStore, ['notify']),
-    ...mapActions(useWorkerStore, ['listVersions']),
+    ...mapActions(useWorkerStore, ['listVersions', 'getRecommendedWorkerVersion']),
     async fetchVersions () {
+      if (!this.advancedMode) return
       this.versionsPage = null
       this.versionsError = null
       this.loading = true
       let mode = 'complete' as WorkerVersionListParameters['mode']
-      if (this.worker.repository_url) mode = this.advancedMode ? 'complete' : 'simple'
+      if (this.worker.repository_url) mode = this.allVersions ? 'complete' : 'simple'
       const payload: WorkerVersionListParameters = {
         page: this.page,
         page_size: this.pageSize,
@@ -135,19 +181,37 @@ export default defineComponent({
     },
     haveRevisions (results: WorkerVersion[]) {
       return (results.some(workerVersion => workerVersion.revision_url !== null))
+    },
+    async fetchRecommendedVersion () {
+      this.loading = true
+      try {
+        await this.getRecommendedWorkerVersion(this.worker.id)
+      } catch (err) {
+        this.recommendedVersionError = errorParser(err)
+      } finally {
+        this.loading = false
+      }
     }
   },
   watch: {
     page: 'fetchVersions',
+    advancedMode: {
+      immediate: true,
+      handler (newValue) {
+        if (String(newValue) === 'false') this.fetchRecommendedVersion()
+        else this.fetchVersions()
+      }
+    },
     worker: {
       immediate: true,
       handler (newValue, oldValue) {
         if (oldValue?.id === newValue.id) return
         this.page = 1
-        this.fetchVersions()
+        if (this.advancedMode) this.fetchVersions()
+        else this.fetchRecommendedVersion()
       }
     },
-    advancedMode: {
+    allVersions: {
       handler () {
         this.page = 1
         this.fetchVersions()
diff --git a/src/stores/workers.ts b/src/stores/workers.ts
index a2960a414..dc99803f4 100644
--- a/src/stores/workers.ts
+++ b/src/stores/workers.ts
@@ -19,6 +19,7 @@ import {
   listWorkerVersions,
   PageNumberPaginationParameters,
   retrieveFeatureWorkerVersion,
+  retrieveRecommendedWorkerVersion,
   retrieveWorker,
   retrieveWorkerConfiguration,
   retrieveWorkerRun,
@@ -49,6 +50,9 @@ interface State {
   workerVersions: {
     [workerVersionId: UUID]: WorkerVersion
   },
+  recommendedWorkerVersions: {
+    [workerId: UUID]: WorkerVersion
+  },
   featureWorkerVersionIds: {
     [feature in ArkindexFeature]?: UUID
   },
@@ -63,6 +67,7 @@ export const useWorkerStore = defineStore('worker', {
     workerTypes: {},
     workerConfigurations: {},
     workerVersions: {},
+    recommendedWorkerVersions: {},
     featureWorkerVersionIds: {},
     workerRuns: {}
   }),
@@ -205,6 +210,11 @@ export const useWorkerStore = defineStore('worker', {
       this.workerVersions[workerVersionId] = await retrieveWorkerVersion(workerVersionId)
     },
 
+    async getRecommendedWorkerVersion (workerId: UUID) {
+      const resp = await retrieveRecommendedWorkerVersion(workerId)
+      if (resp.id) this.recommendedWorkerVersions[workerId] = resp
+    },
+
     async getFeatureWorkerVersion (feature: ArkindexFeature) {
       try {
         const workerVersion = await retrieveFeatureWorkerVersion(feature)
diff --git a/tests/unit/stores/workers.spec.js b/tests/unit/stores/workers.spec.js
index 845746911..803a86849 100644
--- a/tests/unit/stores/workers.spec.js
+++ b/tests/unit/stores/workers.spec.js
@@ -561,5 +561,21 @@ describe('workers', () => {
         })
       })
     })
+
+    describe('getRecommendedWorkerVersion', () => {
+      it('retrieves the recommended worker version for a worker', async () => {
+        mock.onGet('/workers/workerid/versions/recommended/').reply(200, workerVersionsSample['results'][0])
+
+        await store.getRecommendedWorkerVersion('workerid')
+
+        assert.deepStrictEqual(mock.history.all.map(req => pick(req, ['method', 'url'])), [
+          {
+            method: 'get',
+            url: '/workers/workerid/versions/recommended/'
+          }
+        ])
+        assert.deepStrictEqual(store.recommendedWorkerVersions, { workerid: workerVersionsSample['results'][0] })
+      })
+    })
   })
 })
-- 
GitLab


From 069094496375915fe48a4f76cdf8e0c822e3fc27 Mon Sep 17 00:00:00 2001
From: mlbonhomme <bonhomme@teklia.com>
Date: Thu, 16 Jan 2025 14:38:31 +0100
Subject: [PATCH 2/4] minmal worker version row

---
 .../Process/Workers/Versions/List.vue         | 39 +++++---
 .../Process/Workers/Versions/SimpleRow.vue    | 97 +++++++++++++++++++
 tests/unit/stores/workers.spec.js             |  4 +-
 3 files changed, 123 insertions(+), 17 deletions(-)
 create mode 100644 src/components/Process/Workers/Versions/SimpleRow.vue

diff --git a/src/components/Process/Workers/Versions/List.vue b/src/components/Process/Workers/Versions/List.vue
index 4f607497c..d118557d4 100644
--- a/src/components/Process/Workers/Versions/List.vue
+++ b/src/components/Process/Workers/Versions/List.vue
@@ -1,6 +1,6 @@
 <template>
-  <div class="columns">
-    <div class="column"><h2 class="title is-4">Versions</h2></div>
+  <div class="columns mb-0">
+    <div class="column"><h2 class="title is-4">{{ versionsTitle }}</h2></div>
     <div class="column is-narrow">
       <span class="select">
         <select
@@ -29,7 +29,6 @@
       </div>
     </div>
 
-    <span class="is-clearfix"></span>
     <div v-if="versionsError" class="notification is-warning">{{ versionsError }}</div>
     <Paginator
       v-else
@@ -72,21 +71,25 @@
     <div v-if="loading">
       <span class="loader is-size-2 mx-auto"></span>
     </div>
-    <div class="columns is-vcentered" v-else-if="recommendedWorkerVersions[worker.id]">
-      <div class="column is-narrow">
-        Worker version <span class="tag">{{ recommendedWorkerVersions[worker.id].branch || recommendedWorkerVersions[worker.id].tag }}</span> (recommended)
-      </div>
-      <div class="column">
-        <button class="button is-success ml-2">
-          use this version
-        </button>
-      </div>
-    </div>
+    <table class="table" v-else-if="recommendedWorkerVersions[worker.id]">
+      <thead>
+        <tr>
+          <th>Id</th>
+          <th>Tag</th>
+          <th>Branch</th>
+          <th>State</th>
+          <th v-if="processId">Actions</th>
+        </tr>
+      </thead>
+      <tbody>
+        <SimpleRow :process-id="processId" :version="recommendedWorkerVersions[worker.id]" />
+      </tbody>
+    </table>
     <div class="notification is-error" v-else-if="recommendedVersionError">
       An error occurred while loading the recommended worker version: {{ recommendedVersionError }}
     </div>
     <div class="notification is-warning" v-else>
-      There is no recommended worker version for this worker. Please select the "advanced mode" in the menu above to see all worker versions and select one.
+      There is no recommended worker version for this worker. Please select the "advanced mode" in the menu above to see all worker versions.
     </div>
   </template>
 </template>
@@ -97,6 +100,7 @@ import { mapActions, mapState } from 'pinia'
 import { errorParser } from '@/helpers'
 import Paginator from '@/components/Paginator.vue'
 import Row from './Row.vue'
+import SimpleRow from './SimpleRow.vue'
 import { useNotificationStore, useWorkerStore } from '@/stores'
 import { WorkerVersionListParameters } from '@/api'
 import { PageNumberPagination } from '@/types'
@@ -107,7 +111,8 @@ export default defineComponent({
   components: {
     CreateForm,
     Paginator,
-    Row
+    Row,
+    SimpleRow
   },
   emits: ['selected-version'],
   props: {
@@ -154,6 +159,10 @@ export default defineComponent({
     pageSize () {
       // Use a small page size when not in process creation mode because members are displayed on the same column
       return this.processId ? 20 : 5
+    },
+    versionsTitle () {
+      if (this.advancedMode) return 'Versions'
+      return 'Recommended version'
     }
   },
   methods: {
diff --git a/src/components/Process/Workers/Versions/SimpleRow.vue b/src/components/Process/Workers/Versions/SimpleRow.vue
new file mode 100644
index 000000000..1c8b0d710
--- /dev/null
+++ b/src/components/Process/Workers/Versions/SimpleRow.vue
@@ -0,0 +1,97 @@
+<template>
+  <tr>
+    <td :class="{ 'shrink': version.revision_url }">
+      <ItemId :item-id="version.id" />
+    </td>
+    <td>
+      <span v-if="version.tag" class="tag">{{ version.tag }}</span>
+      <template v-else>—</template>
+    </td>
+    <td>
+      <span v-if="version.branch" class="tag">{{ version.branch }}</span>
+      <template v-else>—</template>
+    </td>
+    <td>
+      <span
+        v-if="version.state"
+        class="tag is-capitalized"
+        :class="stateClass(version.state)"
+      >
+        {{ version.state }}
+      </span>
+    </td>
+    <td class="shrink" v-if="processId">
+      <div class="has-text-centered">
+        <!-- Allows to select a worker version -->
+        <a
+          class="button is-success is-small"
+          v-on:click="addWorkerRun"
+          :class="{ 'is-loading': loading }"
+          title="Add the recommended worker version to the process"
+        >
+          <i class="icon-plus"></i>
+        </a>
+      </div>
+    </td>
+  </tr>
+</template>
+
+<script>
+import {
+  mapState as mapVuexState,
+  mapActions as mapVuexActions
+} from 'vuex'
+import { mapActions } from 'pinia'
+
+import { errorParser } from '@/helpers'
+import { WORKER_VERSION_STATE_COLORS } from '@/config'
+import { truncateMixin } from '@/mixins'
+import { useNotificationStore } from '@/stores'
+
+import ItemId from '@/components/ItemId.vue'
+
+export default {
+  emits: ['selected-version'],
+  mixins: [
+    truncateMixin
+  ],
+  components: {
+    ItemId
+  },
+  props: {
+    version: {
+      type: Object,
+      required: true
+    },
+    processId: {
+      type: String,
+      default: ''
+    }
+  },
+  data: () => ({
+    loading: false
+  }),
+  computed: {
+    ...mapVuexState('process', ['processWorkerRuns'])
+  },
+  methods: {
+    ...mapVuexActions('process', ['createWorkerRun', 'deleteWorkerRun']),
+    ...mapActions(useNotificationStore, ['notify']),
+    async addWorkerRun () {
+      this.$emit('selected-version', this.version)
+      if (this.loading || !this.processId) return
+      this.loading = true
+      try {
+        await this.createWorkerRun({ processId: this.processId, workerRun: { worker_version_id: this.version.id, parents: [] } })
+      } catch (err) {
+        this.notify({ type: 'error', text: errorParser(err) })
+      } finally {
+        this.loading = false
+      }
+    },
+    stateClass (state) {
+      return WORKER_VERSION_STATE_COLORS[state]
+    }
+  }
+}
+</script>
diff --git a/tests/unit/stores/workers.spec.js b/tests/unit/stores/workers.spec.js
index 803a86849..b539f2132 100644
--- a/tests/unit/stores/workers.spec.js
+++ b/tests/unit/stores/workers.spec.js
@@ -564,7 +564,7 @@ describe('workers', () => {
 
     describe('getRecommendedWorkerVersion', () => {
       it('retrieves the recommended worker version for a worker', async () => {
-        mock.onGet('/workers/workerid/versions/recommended/').reply(200, workerVersionsSample['results'][0])
+        mock.onGet('/workers/workerid/versions/recommended/').reply(200, workerVersionsSample.results[0])
 
         await store.getRecommendedWorkerVersion('workerid')
 
@@ -574,7 +574,7 @@ describe('workers', () => {
             url: '/workers/workerid/versions/recommended/'
           }
         ])
-        assert.deepStrictEqual(store.recommendedWorkerVersions, { workerid: workerVersionsSample['results'][0] })
+        assert.deepStrictEqual(store.recommendedWorkerVersions, { workerid: workerVersionsSample.results[0] })
       })
     })
   })
-- 
GitLab


From d3b0ccbc79f68c331a0fa54ea25feb220be16715 Mon Sep 17 00:00:00 2001
From: mlbonhomme <bonhomme@teklia.com>
Date: Tue, 21 Jan 2025 17:09:39 +0100
Subject: [PATCH 3/4] wip apply review

---
 .../Process/Workers/Versions/List.vue         | 62 ++++++++++---------
 src/stores/workers.ts                         | 15 ++++-
 tests/unit/stores/workers.spec.js             | 14 +++++
 3 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/src/components/Process/Workers/Versions/List.vue b/src/components/Process/Workers/Versions/List.vue
index d118557d4..3f8b96aef 100644
--- a/src/components/Process/Workers/Versions/List.vue
+++ b/src/components/Process/Workers/Versions/List.vue
@@ -67,31 +67,29 @@
       </table>
     </Paginator>
   </template>
-  <template v-else>
-    <div v-if="loading">
-      <span class="loader is-size-2 mx-auto"></span>
-    </div>
-    <table class="table" v-else-if="recommendedWorkerVersions[worker.id]">
-      <thead>
-        <tr>
-          <th>Id</th>
-          <th>Tag</th>
-          <th>Branch</th>
-          <th>State</th>
-          <th v-if="processId">Actions</th>
-        </tr>
-      </thead>
-      <tbody>
-        <SimpleRow :process-id="processId" :version="recommendedWorkerVersions[worker.id]" />
-      </tbody>
-    </table>
-    <div class="notification is-error" v-else-if="recommendedVersionError">
-      An error occurred while loading the recommended worker version: {{ recommendedVersionError }}
-    </div>
-    <div class="notification is-warning" v-else>
-      There is no recommended worker version for this worker. Please select the "advanced mode" in the menu above to see all worker versions.
-    </div>
-  </template>
+  <div v-else-if="loading">
+    <span class="loader is-size-2 mx-auto"></span>
+  </div>
+  <table class="table" v-else-if="recommendedVersion">
+    <thead>
+      <tr>
+        <th>Id</th>
+        <th>Tag</th>
+        <th>Branch</th>
+        <th>State</th>
+        <th v-if="processId">Actions</th>
+      </tr>
+    </thead>
+    <tbody>
+      <SimpleRow :process-id="processId" :version="recommendedVersion" />
+    </tbody>
+  </table>
+  <div class="notification is-danger" v-else-if="recommendedVersionError">
+    An error occurred while loading the recommended worker version: {{ recommendedVersionError }}
+  </div>
+  <div class="notification is-warning" v-else>
+    There is no recommended worker version for this worker. Please select the "advanced mode" in the menu above to see all worker versions.
+  </div>
 </template>
 
 <script lang="ts">
@@ -149,9 +147,13 @@ export default defineComponent({
     versionsPage: null as PageNumberPagination<WorkerVersion> | null,
     loading: false,
     page: 1,
-    // If set to false, only show the "recommended" version for this worker
+    /**
+     * If set to false, only show the "recommended" version for this worker
+     */
     advancedMode: false,
-    // If set to false, only display versions with a tag or from the master/main branch
+    /**
+     * If set to false, only display versions with a tag or from the master/main branch
+     */
     allVersions: false
   }),
   computed: {
@@ -163,6 +165,10 @@ export default defineComponent({
     versionsTitle () {
       if (this.advancedMode) return 'Versions'
       return 'Recommended version'
+    },
+    recommendedVersion () {
+      if (this.recommendedWorkerVersions[this.worker.id]) return this.recommendedWorkerVersions[this.worker.id]
+      return undefined
     }
   },
   methods: {
@@ -207,7 +213,7 @@ export default defineComponent({
     advancedMode: {
       immediate: true,
       handler (newValue) {
-        if (String(newValue) === 'false') this.fetchRecommendedVersion()
+        if (newValue === false) this.fetchRecommendedVersion()
         else this.fetchVersions()
       }
     },
diff --git a/src/stores/workers.ts b/src/stores/workers.ts
index dc99803f4..19deeedf2 100644
--- a/src/stores/workers.ts
+++ b/src/stores/workers.ts
@@ -51,7 +51,7 @@ interface State {
     [workerVersionId: UUID]: WorkerVersion
   },
   recommendedWorkerVersions: {
-    [workerId: UUID]: WorkerVersion
+    [workerId: UUID]: WorkerVersion | null
   },
   featureWorkerVersionIds: {
     [feature in ArkindexFeature]?: UUID
@@ -211,8 +211,17 @@ export const useWorkerStore = defineStore('worker', {
     },
 
     async getRecommendedWorkerVersion (workerId: UUID) {
-      const resp = await retrieveRecommendedWorkerVersion(workerId)
-      if (resp.id) this.recommendedWorkerVersions[workerId] = resp
+      try {
+        const resp = await retrieveRecommendedWorkerVersion(workerId)
+        this.recommendedWorkerVersions[workerId] = resp
+        return resp
+      } catch (err) {
+        if (isAxiosError(err) && err.response?.status === 404) {
+          this.recommendedWorkerVersions[workerId] = null
+          return null
+        }
+        else throw err
+      }
     },
 
     async getFeatureWorkerVersion (feature: ArkindexFeature) {
diff --git a/tests/unit/stores/workers.spec.js b/tests/unit/stores/workers.spec.js
index b539f2132..1ca877b8e 100644
--- a/tests/unit/stores/workers.spec.js
+++ b/tests/unit/stores/workers.spec.js
@@ -576,6 +576,20 @@ describe('workers', () => {
         ])
         assert.deepStrictEqual(store.recommendedWorkerVersions, { workerid: workerVersionsSample.results[0] })
       })
+
+      it('handles the case when no recommended version is found', async () => {
+        mock.onGet('/workers/workerid/versions/recommended/').reply(404, { detail: 'nothing here' })
+
+        await store.getRecommendedWorkerVersion('workerid')
+
+        assert.deepStrictEqual(mock.history.all.map(req => pick(req, ['method', 'url'])), [
+          {
+            method: 'get',
+            url: '/workers/workerid/versions/recommended/'
+          }
+        ])
+        assert.deepStrictEqual(store.recommendedWorkerVersions, { workerid: null })
+      })
     })
   })
 })
-- 
GitLab


From 6e4046bc4601633b9cc444aa08b3eef055be7b1a Mon Sep 17 00:00:00 2001
From: mlbonhomme <bonhomme@teklia.com>
Date: Wed, 22 Jan 2025 14:04:05 +0100
Subject: [PATCH 4/4] switch to advanced mode when ther is no recommended
 worker version

---
 src/components/Process/Workers/Versions/List.vue | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/components/Process/Workers/Versions/List.vue b/src/components/Process/Workers/Versions/List.vue
index 3f8b96aef..cd323a15f 100644
--- a/src/components/Process/Workers/Versions/List.vue
+++ b/src/components/Process/Workers/Versions/List.vue
@@ -5,6 +5,7 @@
       <span class="select">
         <select
           v-model="advancedMode"
+          :disabled="!recommendedVersion && !recommendedVersionError"
         >
           <option :value="false">Simple mode</option>
           <option :value="true">Advanced mode</option>
@@ -200,7 +201,8 @@ export default defineComponent({
     async fetchRecommendedVersion () {
       this.loading = true
       try {
-        await this.getRecommendedWorkerVersion(this.worker.id)
+        const resp = await this.getRecommendedWorkerVersion(this.worker.id)
+        if (!resp) this.advancedMode = true
       } catch (err) {
         this.recommendedVersionError = errorParser(err)
       } finally {
@@ -222,8 +224,8 @@ export default defineComponent({
       handler (newValue, oldValue) {
         if (oldValue?.id === newValue.id) return
         this.page = 1
-        if (this.advancedMode) this.fetchVersions()
-        else this.fetchRecommendedVersion()
+        this.advancedMode = false
+        this.fetchRecommendedVersion()
       }
     },
     allVersions: {
-- 
GitLab