From 04a32872a3e578a534fc82c172943ba9ae59e943 Mon Sep 17 00:00:00 2001
From: Alex <41288429+Dvinyanin@users.noreply.github.com>
Date: Thu, 16 Jun 2022 01:04:37 +0700
Subject: [PATCH] Add board to Active/Backlog (#2084)

Signed-off-by: Dvinyanin Alexandr <dvinyanin.alexandr@gmail.com>
---
 plugins/tracker-assets/lang/en.json           |  6 +-
 plugins/tracker-assets/lang/ru.json           |  5 +-
 .../src/components/issues/Active.svelte       | 24 ++++----
 .../src/components/issues/Backlog.svelte      | 20 +++----
 .../components/issues/IssuesContent.svelte    |  6 +-
 .../src/components/issues/IssuesView.svelte   | 15 +++--
 plugins/tracker-resources/src/utils.ts        |  4 +-
 tests/sanity/tests/tracker.spec.ts            | 57 ++++++++++++++++---
 8 files changed, 97 insertions(+), 40 deletions(-)

diff --git a/plugins/tracker-assets/lang/en.json b/plugins/tracker-assets/lang/en.json
index 52116da60d..304f89523b 100644
--- a/plugins/tracker-assets/lang/en.json
+++ b/plugins/tracker-assets/lang/en.json
@@ -11,9 +11,9 @@
     "Issues": "Issues",
     "Views": "Views",
     "Active": "Active",
-    "AllIssues": "All issues {value}",
-    "ActiveIssues": "Active issues {value}",
-    "BacklogIssues": "Backlog {value}",
+    "AllIssues": "All issues",
+    "ActiveIssues": "Active issues",
+    "BacklogIssues": "Backlog",
     "Backlog": "Backlog",
     "Board": "Board",
     "Projects": "Projects",
diff --git a/plugins/tracker-assets/lang/ru.json b/plugins/tracker-assets/lang/ru.json
index 4d2764dd5d..f1b5ee5edb 100644
--- a/plugins/tracker-assets/lang/ru.json
+++ b/plugins/tracker-assets/lang/ru.json
@@ -11,8 +11,9 @@
     "Issues": "Задачи",
     "Views": "Отображения",
     "Active": "Активные",
-    "ActiveIssues": "Активные задачи {value}",
-    "BacklogIssues": "Пул задач {value}",
+    "AllIssues": "Все задачи",
+    "ActiveIssues": "Активные задачи",
+    "BacklogIssues": "Пул задач",
     "Backlog": "Пул задач",
     "Board": "Канбан",
     "Projects": "Проекты",
diff --git a/plugins/tracker-resources/src/components/issues/Active.svelte b/plugins/tracker-resources/src/components/issues/Active.svelte
index 30aa36e195..55a2830fb2 100644
--- a/plugins/tracker-resources/src/components/issues/Active.svelte
+++ b/plugins/tracker-resources/src/components/issues/Active.svelte
@@ -13,19 +13,23 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  import { Ref } from '@anticrm/core'
-  import { Team, IssuesDateModificationPeriod } from '@anticrm/tracker'
+  import { DocumentQuery, Ref } from '@anticrm/core'
+  import { createQuery } from '@anticrm/presentation'
+  import { Issue, Team } from '@anticrm/tracker'
   import tracker from '../../plugin'
-  import Issues from './Issues.svelte'
+  import IssuesView from './IssuesView.svelte'
 
   export let currentSpace: Ref<Team>
 
-  const completedIssuesPeriod: IssuesDateModificationPeriod | null = null
+  const statusQuery = createQuery()
+  let query: DocumentQuery<Issue>
+  $: statusQuery.query(
+    tracker.class.IssueStatus,
+    { category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] } },
+    (result) => {
+      query = { status: { $in: result.map(({ _id }) => _id) } }
+    }
+  )
 </script>
 
-<Issues
-  {currentSpace}
-  {completedIssuesPeriod}
-  includedGroups={{ status: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] }}
-  title={tracker.string.ActiveIssues}
-/>
+<IssuesView {currentSpace} {query} title={tracker.string.ActiveIssues} />
diff --git a/plugins/tracker-resources/src/components/issues/Backlog.svelte b/plugins/tracker-resources/src/components/issues/Backlog.svelte
index 00df49d0e3..e67f50238a 100644
--- a/plugins/tracker-resources/src/components/issues/Backlog.svelte
+++ b/plugins/tracker-resources/src/components/issues/Backlog.svelte
@@ -13,19 +13,19 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  import { Ref } from '@anticrm/core'
-  import { Team, IssuesDateModificationPeriod } from '@anticrm/tracker'
+  import { DocumentQuery, Ref } from '@anticrm/core'
+  import { createQuery } from '@anticrm/presentation'
+  import { Issue, Team } from '@anticrm/tracker'
   import tracker from '../../plugin'
-  import Issues from './Issues.svelte'
+  import IssuesView from './IssuesView.svelte'
 
   export let currentSpace: Ref<Team>
 
-  const completedIssuesPeriod: IssuesDateModificationPeriod | null = null
+  const statusQuery = createQuery()
+  let query: DocumentQuery<Issue> = {}
+  $: statusQuery.query(tracker.class.IssueStatus, { category: tracker.issueStatusCategory.Backlog }, (result) => {
+    query = { status: { $in: result.map(({ _id }) => _id) } }
+  })
 </script>
 
-<Issues
-  title={tracker.string.BacklogIssues}
-  {currentSpace}
-  {completedIssuesPeriod}
-  includedGroups={{ status: [tracker.issueStatusCategory.Backlog] }}
-/>
+<IssuesView {currentSpace} {query} title={tracker.string.BacklogIssues} />
diff --git a/plugins/tracker-resources/src/components/issues/IssuesContent.svelte b/plugins/tracker-resources/src/components/issues/IssuesContent.svelte
index b9a21c1043..3966c3cb0d 100644
--- a/plugins/tracker-resources/src/components/issues/IssuesContent.svelte
+++ b/plugins/tracker-resources/src/components/issues/IssuesContent.svelte
@@ -1,13 +1,13 @@
 <script lang="ts">
-  import type { Ref, WithLookup } from '@anticrm/core'
+  import type { DocumentQuery, Ref, WithLookup } from '@anticrm/core'
   import { Component } from '@anticrm/ui'
   import { BuildModelKey, Viewlet } from '@anticrm/view'
-  import { Team, ViewOptions } from '@anticrm/tracker'
+  import { Issue, Team, ViewOptions } from '@anticrm/tracker'
 
   export let currentSpace: Ref<Team>
   export let viewlet: WithLookup<Viewlet> | undefined
   export let config: (string | BuildModelKey)[] | undefined = undefined
-  export let query = {}
+  export let query: DocumentQuery<Issue> = {}
   export let viewOptions: ViewOptions
 </script>
 
diff --git a/plugins/tracker-resources/src/components/issues/IssuesView.svelte b/plugins/tracker-resources/src/components/issues/IssuesView.svelte
index 0ad3657e05..a905b88af2 100644
--- a/plugins/tracker-resources/src/components/issues/IssuesView.svelte
+++ b/plugins/tracker-resources/src/components/issues/IssuesView.svelte
@@ -1,8 +1,15 @@
 <script lang="ts">
-  import core, { Ref, Space, WithLookup } from '@anticrm/core'
+  import core, { DocumentQuery, Ref, Space, WithLookup } from '@anticrm/core'
   import { IntlString, translate } from '@anticrm/platform'
   import { getClient } from '@anticrm/presentation'
-  import { IssuesDateModificationPeriod, IssuesGrouping, IssuesOrdering, Team, ViewOptions } from '@anticrm/tracker'
+  import {
+    Issue,
+    IssuesDateModificationPeriod,
+    IssuesGrouping,
+    IssuesOrdering,
+    Team,
+    ViewOptions
+  } from '@anticrm/tracker'
   import { Button, IconDetails } from '@anticrm/ui'
   import view, { Filter, Viewlet } from '@anticrm/view'
   import { FilterBar } from '@anticrm/view-resources'
@@ -11,7 +18,7 @@
   import IssuesHeader from './IssuesHeader.svelte'
 
   export let currentSpace: Ref<Team> | undefined
-  export let query = {}
+  export let query: DocumentQuery<Issue> = {}
   export let title: IntlString | undefined = undefined
   export let label: string = ''
 
@@ -26,7 +33,7 @@
     shouldShowEmptyGroups: false,
     shouldShowSubIssues: false
   }
-  let resultQuery = {}
+  let resultQuery: DocumentQuery<Issue> = {}
 
   const client = getClient()
 
diff --git a/plugins/tracker-resources/src/utils.ts b/plugins/tracker-resources/src/utils.ts
index 03b0fd04f7..210443d32e 100644
--- a/plugins/tracker-resources/src/utils.ts
+++ b/plugins/tracker-resources/src/utils.ts
@@ -400,6 +400,9 @@ export async function getKanbanStatuses (
   issueQuery: DocumentQuery<Issue>,
   shouldShowEmptyGroups: boolean
 ): Promise<TypeState[]> {
+  if (groupBy === IssuesGrouping.NoGrouping) {
+    return [{ _id: undefined, color: 0, title: await translate(tracker.string.NoGrouping, {}) }]
+  }
   if (groupBy === IssuesGrouping.Status && shouldShowEmptyGroups) {
     return (
       await client.findAll(
@@ -417,7 +420,6 @@ export async function getKanbanStatuses (
       icon: status.$lookup?.category?.icon ?? undefined
     }))
   }
-  if (groupBy === IssuesGrouping.NoGrouping) return []
   if (groupBy === IssuesGrouping.Priority) {
     const issues = await client.findAll(tracker.class.Issue, issueQuery, {
       sort: { priority: SortingOrder.Ascending }
diff --git a/tests/sanity/tests/tracker.spec.ts b/tests/sanity/tests/tracker.spec.ts
index bb28bd2f0e..07528b69c4 100644
--- a/tests/sanity/tests/tracker.spec.ts
+++ b/tests/sanity/tests/tracker.spec.ts
@@ -1,4 +1,4 @@
-import { test, expect } from '@playwright/test'
+import { test, expect, Page } from '@playwright/test'
 import { generateId, PlatformSetting, PlatformURI } from './utils'
 test.use({
   storageState: PlatformSetting
@@ -33,20 +33,63 @@ test('create-issue-and-sub-issue', async ({ page }) => {
   await page.click('span.name:text("sub-issue")')
 })
 
-test('use-kanban', async ({ page }) => {
+async function navigate (page: Page): Promise<void> {
   await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp`)
   await page.click('[id="app-tracker\\:string\\:TrackerApplication"]')
   await expect(page).toHaveURL(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/tracker%3Aapp%3ATracker`)
+}
 
-  const issueName = 'issue-' + generateId(5)
+async function createIssue (page: Page, props: { [p: string]: string } = {}): Promise<void> {
   await page.click('button:has-text("New issue")')
   await page.click('[placeholder="Issue\\ title"]')
-  await page.fill('[placeholder="Issue\\ title"]', issueName)
-  await page.click('button:has-text("Backlog")')
-  await page.click('button:has-text("In Progress")')
+  await page.fill('[placeholder="Issue\\ title"]', props.name ?? '')
+  if (props.status !== undefined) {
+    await page.click('button:has-text("Backlog")')
+    await page.click(`.menu-item:has-text("${props.status}")`)
+  }
   await page.click('button:has-text("Save issue")')
+}
+
+const getIssueName = (postfix: string = generateId(5)): string => `issue-${postfix}`
+
+test('use-kanban', async ({ page }) => {
+  await navigate(page)
+  const name = getIssueName()
+  const status = 'In Progress'
+  await createIssue(page, { name, status })
 
   await page.locator('text="Issues"').click()
   await page.click('[name="tooltip-tracker:string:Board"]')
-  await expect(page.locator('.panel-container:has-text("In Progress")')).toContainText(issueName)
+  await expect(page.locator(`.panel-container:has-text("${status}")`)).toContainText(name)
+})
+
+const defaultStatuses = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
+
+test.describe('issues-status-display', () => {
+  const panelStatusMap = new Map([
+    ['Issues', defaultStatuses],
+    ['Active', ['Todo', 'In Progress']],
+    ['Backlog', ['Backlog']]
+  ])
+  test.beforeEach(async ({ page }) => {
+    await navigate(page)
+    for (const status of defaultStatuses) {
+      await createIssue(page, { name: getIssueName(status), status })
+    }
+  })
+  for (const [panel, statuses] of panelStatusMap) {
+    const excluded = defaultStatuses.filter((status) => !statuses.includes(status))
+    test(`${panel}-panel`, async ({ page }) => {
+      const locator = page.locator('.antiPanel-component >> .antiPanel-component')
+      await page.locator(`text="${panel}"`).click()
+      await page.click('[name="tooltip-view:string:Table"]')
+      await expect(locator).toContainText(statuses)
+      if (excluded.length > 0) await expect(locator).not.toContainText(excluded)
+      await page.click('[name="tooltip-tracker:string:Board"]')
+      if (excluded.length > 0) await expect(locator).not.toContainText(excluded)
+      for (const status of statuses) {
+        await expect(page.locator(`.panel-container:has-text("${status}")`)).toContainText(getIssueName(status))
+      }
+    })
+  }
 })