Add board to Active/Backlog (#2084)

Signed-off-by: Dvinyanin Alexandr <dvinyanin.alexandr@gmail.com>
This commit is contained in:
Alex 2022-06-16 01:04:37 +07:00 committed by GitHub
parent f4ff886ce1
commit 04a32872a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 40 deletions

View File

@ -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",

View File

@ -11,8 +11,9 @@
"Issues": "Задачи",
"Views": "Отображения",
"Active": "Активные",
"ActiveIssues": "Активные задачи {value}",
"BacklogIssues": "Пул задач {value}",
"AllIssues": "Все задачи",
"ActiveIssues": "Активные задачи",
"BacklogIssues": "Пул задач",
"Backlog": "Пул задач",
"Board": "Канбан",
"Projects": "Проекты",

View File

@ -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} />

View File

@ -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} />

View File

@ -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>

View File

@ -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()

View File

@ -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 }

View File

@ -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))
}
})
}
})