From c1fac81f50ced558a12f0e44d76ac5a7a833c7a5 Mon Sep 17 00:00:00 2001
From: Sergei Ogorelkov <sergei.ogorelkov@icloud.com>
Date: Mon, 24 Apr 2023 13:40:03 +0400
Subject: [PATCH] [TSK-1304] Fix active viewlet if viewlet list is empty
 (#3043)

Signed-off-by: Sergei Ogorelkov <sergei.ogorelkov@icloud.com>
---
 .../src/components/issues/IssuesView.svelte   | 13 ++-------
 .../components/sprints/SprintBrowser.svelte   | 13 +++------
 .../templates/IssueTemplatesView.svelte       | 11 ++-----
 plugins/view-resources/src/utils.ts           | 29 +++++++++++++++++++
 .../src/components/SpaceHeader.svelte         | 10 ++-----
 .../src/components/SpaceView.svelte           |  5 ++--
 6 files changed, 44 insertions(+), 37 deletions(-)

diff --git a/plugins/tracker-resources/src/components/issues/IssuesView.svelte b/plugins/tracker-resources/src/components/issues/IssuesView.svelte
index a1eded962e..66d81b0124 100644
--- a/plugins/tracker-resources/src/components/issues/IssuesView.svelte
+++ b/plugins/tracker-resources/src/components/issues/IssuesView.svelte
@@ -11,7 +11,7 @@
     activeViewlet,
     getViewOptions,
     makeViewletKey,
-    setActiveViewletId,
+    updateActiveViewlet,
     viewOptionStore
   } from '@hcengineering/view-resources'
   import { onDestroy } from 'svelte'
@@ -35,9 +35,9 @@
   $: if (query) updateSearchQuery(search)
   let resultQuery: DocumentQuery<Issue> = { ...searchQuery }
 
-  let viewlets: WithLookup<Viewlet>[] = []
+  let viewlets: WithLookup<Viewlet>[] | undefined
 
-  $: update(viewlets, active)
+  $: viewlet = viewlets && updateActiveViewlet(viewlets, active)
   const viewletQuery = createQuery()
   viewletQuery.query(
     view.class.Viewlet,
@@ -60,13 +60,6 @@
 
   $: active = $activeViewlet[key]
 
-  async function update (viewlets: WithLookup<Viewlet>[], active: Ref<Viewlet> | null): Promise<void> {
-    viewlet = viewlets.find((viewlet) => viewlet._id === active) ?? viewlets[0]
-    if (viewlet !== undefined) {
-      setActiveViewletId(viewlet._id)
-    }
-  }
-
   $: if (!label && title) {
     translate(title, {}).then((res) => {
       label = res
diff --git a/plugins/tracker-resources/src/components/sprints/SprintBrowser.svelte b/plugins/tracker-resources/src/components/sprints/SprintBrowser.svelte
index 73317da140..69701d6ffd 100644
--- a/plugins/tracker-resources/src/components/sprints/SprintBrowser.svelte
+++ b/plugins/tracker-resources/src/components/sprints/SprintBrowser.svelte
@@ -13,7 +13,7 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  import { DocumentQuery, Ref, WithLookup } from '@hcengineering/core'
+  import { DocumentQuery, WithLookup } from '@hcengineering/core'
   import { IntlString } from '@hcengineering/platform'
   import { createQuery } from '@hcengineering/presentation'
   import { Sprint } from '@hcengineering/tracker'
@@ -37,7 +37,7 @@
     activeViewlet,
     getViewOptions,
     makeViewletKey,
-    setActiveViewletId,
+    updateActiveViewlet,
     viewOptionStore
   } from '@hcengineering/view-resources'
   import { onDestroy } from 'svelte'
@@ -72,9 +72,9 @@
 
   let resultQuery: DocumentQuery<Sprint> = { ...searchQuery }
 
-  let viewlets: WithLookup<Viewlet>[] = []
+  let viewlets: WithLookup<Viewlet>[] | undefined
 
-  $: update(viewlets, active)
+  $: viewlet = viewlets && updateActiveViewlet(viewlets, active)
 
   const viewletQuery = createQuery()
   viewletQuery.query(view.class.Viewlet, { attachTo: tracker.class.Sprint }, (res) => (viewlets = res), {
@@ -93,11 +93,6 @@
 
   $: active = $activeViewlet[key]
 
-  async function update (viewlets: WithLookup<Viewlet>[], active: Ref<Viewlet> | null): Promise<void> {
-    viewlet = viewlets.find((viewlet) => viewlet._id === active) ?? viewlets[0]
-    setActiveViewletId(viewlet._id)
-  }
-
   let asideFloat: boolean = false
   let asideShown: boolean = true
   $: if (panelWidth < 900 && !asideFloat) asideFloat = true
diff --git a/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte b/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte
index a71a041f6c..a77b186e87 100644
--- a/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte
+++ b/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte
@@ -11,7 +11,7 @@
     activeViewlet,
     getViewOptions,
     makeViewletKey,
-    setActiveViewletId,
+    updateActiveViewlet,
     viewOptionStore
   } from '@hcengineering/view-resources'
   import { onDestroy } from 'svelte'
@@ -37,9 +37,9 @@
   $: if (query) updateSearchQuery(search)
   let resultQuery: DocumentQuery<IssueTemplate> = { ...searchQuery }
 
-  let viewlets: WithLookup<Viewlet>[] = []
+  let viewlets: WithLookup<Viewlet>[] | undefined
 
-  $: update(viewlets, active)
+  $: viewlet = viewlets && updateActiveViewlet(viewlets, active)
 
   const viewletQuery = createQuery()
   viewletQuery.query(view.class.Viewlet, { attachTo: tracker.class.IssueTemplate }, (res) => (viewlets = res), {
@@ -58,11 +58,6 @@
 
   $: active = $activeViewlet[key]
 
-  async function update (viewlets: WithLookup<Viewlet>[], active: Ref<Viewlet> | null): Promise<void> {
-    viewlet = viewlets.find((viewlet) => viewlet._id === active) ?? viewlets[0]
-    if (viewlet !== undefined) setActiveViewletId(viewlet._id)
-  }
-
   $: if (!label && title) {
     translate(title, {}).then((res) => {
       label = res
diff --git a/plugins/view-resources/src/utils.ts b/plugins/view-resources/src/utils.ts
index 14b2823d5d..4851f3a27d 100644
--- a/plugins/view-resources/src/utils.ts
+++ b/plugins/view-resources/src/utils.ts
@@ -520,6 +520,35 @@ export function getActiveViewletId (): Ref<Viewlet> | null {
   return localStorage.getItem(key) as Ref<Viewlet> | null
 }
 
+/**
+ * Updates the active viewlet, if one was found.
+ * Otherwise sets the default viewlet.
+ *
+ * @export
+ * @param {readonly Viewlet[]} viewlets
+ * @param {(Ref<Viewlet> | null | undefined)} activeViewletId
+ * @returns {(Viewlet | undefined)}
+ */
+export function updateActiveViewlet (
+  viewlets: readonly Viewlet[],
+  activeViewletId: Ref<Viewlet> | null | undefined
+): Viewlet | undefined {
+  if (viewlets.length === 0) {
+    return
+  }
+
+  let viewlet: Viewlet | undefined
+
+  if (activeViewletId !== null && activeViewletId !== undefined) {
+    viewlet = viewlets.find((viewlet) => viewlet._id === activeViewletId)
+  }
+  viewlet ??= viewlets[0]
+
+  setActiveViewletId(viewlet._id)
+
+  return viewlet
+}
+
 export type FixedWidthStore = Record<string, number>
 
 export const fixedWidthStore = writable<FixedWidthStore>({})
diff --git a/plugins/workbench-resources/src/components/SpaceHeader.svelte b/plugins/workbench-resources/src/components/SpaceHeader.svelte
index 25b1146fbb..6f0a16e2ee 100644
--- a/plugins/workbench-resources/src/components/SpaceHeader.svelte
+++ b/plugins/workbench-resources/src/components/SpaceHeader.svelte
@@ -34,7 +34,8 @@
     ViewletSettingButton,
     activeViewlet,
     makeViewletKey,
-    setActiveViewletId
+    setActiveViewletId,
+    updateActiveViewlet
   } from '@hcengineering/view-resources'
   import { createEventDispatcher, onDestroy } from 'svelte'
   import Header from './Header.svelte'
@@ -62,7 +63,7 @@
     showPopup(createItemDialog as AnyComponent, { space: spaceId }, 'top')
   }
 
-  $: update(viewlets, active)
+  $: viewlet = updateActiveViewlet(viewlets, active)
 
   $: if (prevSpaceId !== spaceId) {
     search = ''
@@ -79,11 +80,6 @@
 
   $: active = $activeViewlet[key]
 
-  async function update (viewlets: WithLookup<Viewlet>[], active: Ref<Viewlet> | null): Promise<void> {
-    viewlet = viewlets.find((viewlet) => viewlet._id === active) ?? viewlets[0]
-    setActiveViewletId(viewlet._id)
-  }
-
   $: viewslist = viewlets.map((views) => {
     return {
       id: views._id,
diff --git a/plugins/workbench-resources/src/components/SpaceView.svelte b/plugins/workbench-resources/src/components/SpaceView.svelte
index 7fb75169dd..ab662e54ca 100644
--- a/plugins/workbench-resources/src/components/SpaceView.svelte
+++ b/plugins/workbench-resources/src/components/SpaceView.svelte
@@ -22,7 +22,7 @@
     activeViewlet,
     getViewOptions,
     makeViewletKey,
-    setActiveViewletId,
+    updateActiveViewlet,
     viewOptionStore
   } from '@hcengineering/view-resources'
   import type { ViewConfiguration } from '@hcengineering/workbench'
@@ -82,8 +82,7 @@
         }
       )
       if (header !== undefined) {
-        viewlet = viewlets.find((viewlet) => viewlet._id === active) ?? viewlets[0]
-        setActiveViewletId(viewlet._id)
+        viewlet = updateActiveViewlet(viewlets, active)
       }
       _class = attachTo
     }