From 30a0413dc37dd395628d5a3021be3c2e74b13317 Mon Sep 17 00:00:00 2001
From: Ruslan Bayandinov <45530296+wazsone@users.noreply.github.com>
Date: Wed, 24 May 2023 13:47:58 +0700
Subject: [PATCH] [UBER-178] New way of All/Active/Backlog should be in URI
 (#3228)

Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
---
 models/tracker/src/index.ts                   | 26 ++++++++--
 .../src/components/issues/Issues.svelte       | 48 ++++++++++---------
 .../src/components/myissues/MyIssues.svelte   | 46 ++++++++++--------
 .../src/components/filter/FilterSave.svelte   |  1 -
 .../src/components/Workbench.svelte           | 23 ++++-----
 tests/sanity/tests/tracker.spec.ts            |  2 +-
 6 files changed, 81 insertions(+), 65 deletions(-)

diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts
index c0fc049918..838c550ec3 100644
--- a/models/tracker/src/index.ts
+++ b/models/tracker/src/index.ts
@@ -825,6 +825,7 @@ export function createModel (builder: Builder): void {
   const milestonesId = 'milestones'
   const templatesId = 'templates'
   const myIssuesId = 'my-issues'
+  const allIssuesId = 'all-issues'
   // const scrumsId = 'scrums'
 
   builder.mixin(tracker.class.Issue, core.class.Class, view.mixin.ObjectPresenter, {
@@ -999,10 +1000,17 @@ export function createModel (builder: Builder): void {
             position: 'top',
             label: tracker.string.MyIssues,
             icon: tracker.icon.MyIssues,
-            component: tracker.component.MyIssues
+            component: tracker.component.MyIssues,
+            componentProps: {
+              config: [
+                ['assigned', view.string.Assigned, {}],
+                ['created', view.string.Created, { value: 2 }],
+                ['subscribed', view.string.Subscribed, {}]
+              ]
+            }
           },
           {
-            id: 'all-issues',
+            id: allIssuesId,
             position: 'top',
             label: tracker.string.AllIssues,
             icon: tracker.icon.Issues,
@@ -1010,7 +1018,12 @@ export function createModel (builder: Builder): void {
             componentProps: {
               baseQuery: { '$lookup.space.archived': false },
               space: undefined,
-              title: tracker.string.AllIssues
+              title: tracker.string.AllIssues,
+              config: [
+                ['all', tracker.string.All, {}],
+                ['active', tracker.string.Active, {}],
+                ['backlog', tracker.string.Backlog, {}]
+              ]
             }
           }
         ],
@@ -1028,7 +1041,12 @@ export function createModel (builder: Builder): void {
                 icon: tracker.icon.Issues,
                 component: tracker.component.Issues,
                 componentProps: {
-                  title: tracker.string.Issues
+                  title: tracker.string.Issues,
+                  config: [
+                    ['all', tracker.string.All, {}],
+                    ['active', tracker.string.Active, {}],
+                    ['backlog', tracker.string.Backlog, {}]
+                  ]
                 }
               },
               {
diff --git a/plugins/tracker-resources/src/components/issues/Issues.svelte b/plugins/tracker-resources/src/components/issues/Issues.svelte
index 07fad045e4..471d05fe80 100644
--- a/plugins/tracker-resources/src/components/issues/Issues.svelte
+++ b/plugins/tracker-resources/src/components/issues/Issues.svelte
@@ -13,23 +13,25 @@
 // limitations under the License.
 -->
 <script lang="ts">
+  import { createEventDispatcher } from 'svelte'
   import { DocumentQuery, Ref } from '@hcengineering/core'
   import { Issue, Project } from '@hcengineering/tracker'
-  import tracker from '../../plugin'
-  import IssuesView from './IssuesView.svelte'
   import { IntlString } from '@hcengineering/platform'
   import { createQuery } from '@hcengineering/presentation'
+  import { resolvedLocationStore } from '@hcengineering/ui'
+
   import { IModeSelector } from '@hcengineering/ui'
+  import tracker from '../../plugin'
+  import IssuesView from './IssuesView.svelte'
 
   export let currentSpace: Ref<Project> | undefined = undefined
   export let baseQuery: DocumentQuery<Issue> = {}
   export let title: IntlString
+  export let config: [string, IntlString, object][]
 
-  const config: [string, IntlString, object][] = [
-    ['all', tracker.string.All, {}],
-    ['active', tracker.string.Active, {}],
-    ['backlog', tracker.string.Backlog, {}]
-  ]
+  const dispatch = createEventDispatcher()
+  let query: DocumentQuery<Issue> | undefined = undefined
+  let modeSelectorProps: IModeSelector | undefined = undefined
 
   $: spaceQuery = currentSpace ? { space: currentSpace } : {}
 
@@ -58,23 +60,23 @@
     }
   )
 
-  let [[mode]] = config
-  function handleChangeMode (newMode: string) {
-    if (newMode === mode) return
-    mode = newMode
+  $: queries = { all, active, backlog }
+  $: mode = $resolvedLocationStore.query?.mode ?? undefined
+  $: if (mode === undefined || queries[mode] === undefined) {
+    ;[[mode]] = config
   }
-
-  function getQuery (mode: string, queries: { [key: string]: DocumentQuery<Issue> }) {
-    return { ...queries[mode], '$lookup.space.archived': false }
+  $: if (mode !== undefined) {
+    query = { ...queries[mode], '$lookup.space.archived': false }
+    modeSelectorProps = {
+      config,
+      mode,
+      onChange: (newMode: string) => dispatch('action', { mode: newMode })
+    }
   }
-  $: query = getQuery(mode, { all, active, backlog })
-  $: modeSelectorProps = {
-    config,
-    mode,
-    onChange: handleChangeMode
-  } as IModeSelector
 </script>
 
-{#key query && currentSpace}
-  <IssuesView {query} space={currentSpace} {title} {modeSelectorProps} />
-{/key}
+{#if query !== undefined && modeSelectorProps !== undefined}
+  {#key query && currentSpace}
+    <IssuesView {query} space={currentSpace} {title} {modeSelectorProps} />
+  {/key}
+{/if}
diff --git a/plugins/tracker-resources/src/components/myissues/MyIssues.svelte b/plugins/tracker-resources/src/components/myissues/MyIssues.svelte
index 2ea9592b60..c6f7ef12e5 100644
--- a/plugins/tracker-resources/src/components/myissues/MyIssues.svelte
+++ b/plugins/tracker-resources/src/components/myissues/MyIssues.svelte
@@ -13,26 +13,28 @@
 // limitations under the License.
 -->
 <script lang="ts">
+  import { createEventDispatcher } from 'svelte'
   import type { EmployeeAccount } from '@hcengineering/contact'
   import { Doc, DocumentQuery, getCurrentAccount, Ref } from '@hcengineering/core'
   import type { IntlString } from '@hcengineering/platform'
   import { createQuery } from '@hcengineering/presentation'
   import type { Issue } from '@hcengineering/tracker'
+  import { resolvedLocationStore } from '@hcengineering/ui'
 
+  import { IModeSelector } from '@hcengineering/ui'
   import tracker from '../../plugin'
   import IssuesView from '../issues/IssuesView.svelte'
-  import { IModeSelector } from '@hcengineering/ui'
-  import view from '@hcengineering/view'
 
-  const config: [string, IntlString, object][] = [
-    ['assigned', view.string.Assigned, {}],
-    ['created', view.string.Created, {}],
-    ['subscribed', view.string.Subscribed, {}]
-  ]
+  export let config: [string, IntlString, object][] = []
+
+  const dispatch = createEventDispatcher()
   const currentUser = getCurrentAccount() as EmployeeAccount
   const assigned = { assignee: currentUser.employee }
   const created = { createdBy: currentUser._id }
   let subscribed = { _id: { $in: [] as Ref<Issue>[] } }
+  let query: DocumentQuery<Issue> | undefined = undefined
+  let modeSelectorProps: IModeSelector | undefined = undefined
+  let mode: string | undefined = undefined
 
   const subscribedQuery = createQuery()
   $: subscribedQuery.query(
@@ -48,21 +50,23 @@
     { sort: { _id: 1 } }
   )
 
-  let [[mode]] = config
-  function handleChangeMode (newMode: string) {
-    if (newMode === mode) return
-    mode = newMode
+  $: queries = { assigned, created, subscribed }
+  $: mode = $resolvedLocationStore.query?.mode ?? undefined
+  $: if (mode === undefined || queries[mode] === undefined) {
+    ;[[mode]] = config
   }
-
-  function getQuery (mode: string, queries: { [key: string]: DocumentQuery<Issue> }) {
-    return { ...queries[mode], '$lookup.space.archived': false }
+  $: if (mode !== undefined) {
+    query = { ...queries[mode], '$lookup.space.archived': false }
+    modeSelectorProps = {
+      config,
+      mode,
+      onChange: (newMode: string) => dispatch('action', { mode: newMode })
+    }
   }
-  $: query = getQuery(mode, { assigned, created, subscribed })
-  $: modeSelectorProps = {
-    config,
-    mode,
-    onChange: handleChangeMode
-  } as IModeSelector
 </script>
 
-<IssuesView {query} space={undefined} title={tracker.string.MyIssues} {modeSelectorProps} />
+{#if query !== undefined && modeSelectorProps !== undefined}
+  {#key query}
+    <IssuesView {query} space={undefined} title={tracker.string.MyIssues} {modeSelectorProps} />
+  {/key}
+{/if}
diff --git a/plugins/view-resources/src/components/filter/FilterSave.svelte b/plugins/view-resources/src/components/filter/FilterSave.svelte
index 3128e08001..943cc5d366 100644
--- a/plugins/view-resources/src/components/filter/FilterSave.svelte
+++ b/plugins/view-resources/src/components/filter/FilterSave.svelte
@@ -21,7 +21,6 @@
   async function saveFilter () {
     const loc = getCurrentResolvedLocation()
     loc.fragment = undefined
-    loc.query = undefined
     const filters = JSON.stringify($filterStore)
     await client.createDoc(view.class.FilteredView, preference.space.Preference, {
       name: filterName,
diff --git a/plugins/workbench-resources/src/components/Workbench.svelte b/plugins/workbench-resources/src/components/Workbench.svelte
index e19f82d957..3e9fcc8df9 100644
--- a/plugins/workbench-resources/src/components/Workbench.svelte
+++ b/plugins/workbench-resources/src/components/Workbench.svelte
@@ -39,6 +39,7 @@
     closePopup,
     closeTooltip,
     deviceOptionsStore as deviceInfo,
+    getCurrentLocation,
     location,
     navigate,
     openPanel,
@@ -583,21 +584,6 @@
             selected={currentAppAlias === notificationId || inboxPopup !== undefined}
             on:click={(e) => {
               if (e.metaKey || e.ctrlKey) return
-              // if (inboxPopup) {
-              //   inboxPopup.close()
-              // } else {
-              //   inboxPopup = showPopup(
-              //     notification.component.Inbox,
-              //     { visibileNav: true },
-              //     'content',
-              //     undefined,
-              //     undefined,
-              //     {
-              //       category: 'popup',
-              //       overlay: false
-              //     }
-              //   )
-              // }
               if (currentAppAlias === notificationId && lastLoc !== undefined) {
                 e.preventDefault()
                 e.stopPropagation()
@@ -690,6 +676,13 @@
           <Component
             is={specialComponent.component}
             props={{ model: navigatorModel, ...specialComponent.componentProps, currentSpace, visibileNav }}
+            on:action={(e) => {
+              if (e?.detail) {
+                const loc = getCurrentLocation()
+                loc.query = { ...loc.query, ...e.detail }
+                navigate(loc)
+              }
+            }}
           />
         {:else if currentView?.component !== undefined}
           <Component is={currentView.component} props={{ ...currentView.componentProps, currentView, visibileNav }} />
diff --git a/tests/sanity/tests/tracker.spec.ts b/tests/sanity/tests/tracker.spec.ts
index 2967683f01..664f8a4e18 100644
--- a/tests/sanity/tests/tracker.spec.ts
+++ b/tests/sanity/tests/tracker.spec.ts
@@ -39,7 +39,7 @@ test('create-issue-and-sub-issue', async ({ page }) => {
   await checkIssue(page, props)
   props.name = `sub${props.name}`
   await createSubissue(page, props)
-  await page.click(`.antiList__row:has-text("${props.name}") .name a`)
+  await openIssue(page, props.name)
   await checkIssue(page, props)
 })