mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 20:25:56 +03:00
Add MyIssues (#2128)
Signed-off-by: Dvinyanin Alexandr <dvinyanin.alexandr@gmail.com>
This commit is contained in:
parent
3c037e4506
commit
dbca41afee
@ -5,7 +5,8 @@
|
||||
Tracker:
|
||||
|
||||
- Remember view options
|
||||
-
|
||||
- My issues
|
||||
|
||||
Chunter:
|
||||
|
||||
- Reactions on messages
|
||||
|
@ -280,8 +280,12 @@ export function createModel (builder: Builder): void {
|
||||
descriptor: tracker.viewlet.List,
|
||||
config: [
|
||||
{ key: '', presenter: tracker.component.PriorityEditor, props: { kind: 'list', size: 'small' } },
|
||||
'@currentTeam',
|
||||
'@statuses',
|
||||
{ key: '', presenter: tracker.component.IssuePresenter },
|
||||
{
|
||||
key: '',
|
||||
presenter: tracker.component.StatusEditor,
|
||||
props: { kind: 'list', size: 'small', justify: 'center' }
|
||||
},
|
||||
{ key: '', presenter: tracker.component.TitlePresenter, props: { shouldUseMargin: true, fixed: 'left' } },
|
||||
{ key: '', presenter: tracker.component.DueDatePresenter, props: { kind: 'list' } },
|
||||
{
|
||||
|
@ -17,7 +17,7 @@
|
||||
import { Ref } from '@anticrm/core'
|
||||
import { ObjectSearchCategory, ObjectSearchFactory } from '@anticrm/model-presentation'
|
||||
import { IntlString, mergeIds, Resource } from '@anticrm/platform'
|
||||
import { Team, trackerId } from '@anticrm/tracker'
|
||||
import { trackerId } from '@anticrm/tracker'
|
||||
import tracker from '@anticrm/tracker-resources/src/plugin'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import { ViewletDescriptor } from '@anticrm/view'
|
||||
@ -35,9 +35,6 @@ export default mergeIds(trackerId, tracker, {
|
||||
GotoTrackerApplication: '' as IntlString,
|
||||
SearchIssue: '' as IntlString
|
||||
},
|
||||
team: {
|
||||
DefaultTeam: '' as Ref<Team>
|
||||
},
|
||||
component: {
|
||||
// Required to pass build without errorsF
|
||||
Nope: '' as AnyComponent
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { AttachedDoc, Class, Doc, DocumentQuery, DocumentUpdate, FindOptions, Ref, Space } from '@anticrm/core'
|
||||
import core, { AttachedDoc, Class, Doc, DocumentQuery, DocumentUpdate, FindOptions, Ref } from '@anticrm/core'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import { getPlatformColor, ScrollBox, Scroller } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@ -22,7 +22,6 @@
|
||||
import KanbanRow from './KanbanRow.svelte'
|
||||
|
||||
export let _class: Ref<Class<Item>>
|
||||
export let space: Ref<Space>
|
||||
export let search: string
|
||||
export let options: FindOptions<Item> | undefined = undefined
|
||||
export let states: TypeState[] = []
|
||||
@ -40,7 +39,6 @@
|
||||
$: objsQ.query(
|
||||
_class,
|
||||
{
|
||||
space,
|
||||
...query,
|
||||
...(search !== '' ? { $search: search } : {})
|
||||
},
|
||||
@ -74,7 +72,7 @@
|
||||
const adoc: AttachedDoc = item as Doc as AttachedDoc
|
||||
await client.updateCollection(
|
||||
_class,
|
||||
space,
|
||||
adoc.space,
|
||||
adoc._id as Ref<Doc> as Ref<AttachedDoc>,
|
||||
adoc.attachedTo,
|
||||
adoc.attachedToClass,
|
||||
@ -331,7 +329,7 @@
|
||||
</svelte:fragment>
|
||||
</KanbanRow>
|
||||
|
||||
<slot name="afterCard" {space} {state} />
|
||||
<slot name="afterCard" {state} />
|
||||
</Scroller>
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -111,10 +111,9 @@
|
||||
<KanbanUI
|
||||
bind:this={kanbanUI}
|
||||
{_class}
|
||||
{space}
|
||||
{search}
|
||||
{options}
|
||||
query={{ doneState: null, isArchived: { $nin: [true] } }}
|
||||
query={{ doneState: null, isArchived: { $nin: [true] }, space }}
|
||||
{states}
|
||||
fieldName={'state'}
|
||||
rankFieldName={'rank'}
|
||||
@ -147,7 +146,7 @@
|
||||
<ListHeader {state} />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="afterCard" let:space={targetSpace} let:state={targetState}>
|
||||
<AddCard space={targetSpace} state={targetState} />
|
||||
<svelte:fragment slot="afterCard" let:state={targetState}>
|
||||
<AddCard {space} state={targetState} />
|
||||
</svelte:fragment>
|
||||
</KanbanUI>
|
||||
|
@ -114,10 +114,9 @@
|
||||
<KanbanUI
|
||||
bind:this={kanbanUI}
|
||||
{_class}
|
||||
{space}
|
||||
{search}
|
||||
{options}
|
||||
query={{ doneState: null }}
|
||||
query={{ doneState: null, space }}
|
||||
{states}
|
||||
fieldName={'state'}
|
||||
rankFieldName={'rank'}
|
||||
|
@ -134,6 +134,9 @@
|
||||
"FilterIsNot": "is not",
|
||||
"FilterIsEither": "is either of",
|
||||
"FilterStatesCount": "{value, plural, =1 {1 state} other {# states}}",
|
||||
"Assigned": "Assigned",
|
||||
"Created": "Created",
|
||||
"Subscribed": "Subscribed",
|
||||
|
||||
"EditIssue": "Edit {title}",
|
||||
|
||||
|
@ -134,6 +134,9 @@
|
||||
"FilterIsNot": "не является",
|
||||
"FilterIsEither": "является ли любой из",
|
||||
"FilterStatesCount": "{value, plural, =1 {1 state} other {# states}}",
|
||||
"Assigned": "Назначенные",
|
||||
"Created": "Созданные",
|
||||
"Subscribed": "Отслеживаемые",
|
||||
|
||||
"EditIssue": "Редактирование {title}",
|
||||
|
||||
|
53
plugins/tracker-resources/src/components/ModeSelector.svelte
Normal file
53
plugins/tracker-resources/src/components/ModeSelector.svelte
Normal file
@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import { Button } from '@anticrm/ui'
|
||||
|
||||
export let mode: string
|
||||
export let config: [string, IntlString][]
|
||||
export let onChange: (_mode: string) => void
|
||||
|
||||
function getButtonShape (i: number) {
|
||||
if (config.length === 1) return 'round'
|
||||
switch (i) {
|
||||
case 0:
|
||||
return 'rectangle-right'
|
||||
case config.length - 1:
|
||||
return 'rectangle-left'
|
||||
default:
|
||||
return 'rectangle'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="itemsContainer">
|
||||
<div class="flex-center">
|
||||
{#each config as [_mode, label], i}
|
||||
<div class="buttonWrapper">
|
||||
<Button
|
||||
{label}
|
||||
size="small"
|
||||
on:click={() => onChange(_mode)}
|
||||
selected={_mode === mode}
|
||||
shape={getButtonShape(i)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.itemsContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.65rem 1.35rem 0.65rem 2.25rem;
|
||||
border-top: 1px solid var(--theme-button-border-hovered);
|
||||
}
|
||||
.buttonWrapper {
|
||||
margin-right: 1px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -27,9 +27,9 @@
|
||||
tracker.class.IssueStatus,
|
||||
{ category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] } },
|
||||
(result) => {
|
||||
query = { status: { $in: result.map(({ _id }) => _id) } }
|
||||
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<IssuesView {currentSpace} {query} title={tracker.string.ActiveIssues} />
|
||||
<IssuesView {query} title={tracker.string.ActiveIssues} />
|
||||
|
@ -24,8 +24,8 @@
|
||||
const statusQuery = createQuery()
|
||||
let query: DocumentQuery<Issue> = {}
|
||||
$: statusQuery.query(tracker.class.IssueStatus, { category: tracker.issueStatusCategory.Backlog }, (result) => {
|
||||
query = { status: { $in: result.map(({ _id }) => _id) } }
|
||||
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
||||
})
|
||||
</script>
|
||||
|
||||
<IssuesView {currentSpace} {query} title={tracker.string.BacklogIssues} />
|
||||
<IssuesView {query} title={tracker.string.BacklogIssues} />
|
||||
|
@ -1,71 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { DocumentQuery, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import { DocumentQuery, WithLookup } from '@anticrm/core'
|
||||
import { Component } from '@anticrm/ui'
|
||||
import { BuildModelKey, Viewlet, ViewletPreference } from '@anticrm/view'
|
||||
import { Issue, IssueStatus, Team } from '@anticrm/tracker'
|
||||
import { createQuery } from '@anticrm/presentation'
|
||||
import { Viewlet } from '@anticrm/view'
|
||||
import { Issue } from '@anticrm/tracker'
|
||||
import { viewOptionsStore } from '../../viewOptions'
|
||||
import tracker from '../../plugin'
|
||||
|
||||
export let currentSpace: Ref<Team>
|
||||
export let viewlet: WithLookup<Viewlet>
|
||||
export let query: DocumentQuery<Issue> = {}
|
||||
|
||||
const statusesQuery = createQuery()
|
||||
const spaceQuery = createQuery()
|
||||
let currentTeam: Team | undefined
|
||||
let statusesById: ReadonlyMap<Ref<IssueStatus>, WithLookup<IssueStatus>> = new Map()
|
||||
|
||||
$: statusesQuery.query(
|
||||
tracker.class.IssueStatus,
|
||||
{ attachedTo: currentSpace },
|
||||
(issueStatuses) => {
|
||||
statusesById = new Map(issueStatuses.map((status) => [status._id, status]))
|
||||
},
|
||||
{
|
||||
lookup: { category: tracker.class.IssueStatusCategory },
|
||||
sort: { rank: SortingOrder.Ascending }
|
||||
}
|
||||
)
|
||||
|
||||
$: spaceQuery.query(tracker.class.Team, { _id: currentSpace }, (res) => {
|
||||
currentTeam = res.shift()
|
||||
})
|
||||
|
||||
$: statuses = [...statusesById.values()]
|
||||
|
||||
const replacedKeys: Map<string, BuildModelKey> = new Map<string, BuildModelKey>([
|
||||
['@currentTeam', { key: '', presenter: tracker.component.IssuePresenter, props: { currentTeam } }],
|
||||
[
|
||||
'@statuses',
|
||||
{
|
||||
key: '',
|
||||
presenter: tracker.component.StatusEditor,
|
||||
props: { statuses, kind: 'list', size: 'small', justify: 'center' }
|
||||
}
|
||||
]
|
||||
])
|
||||
|
||||
function createConfig (descr: Viewlet, preference: ViewletPreference | undefined): (string | BuildModelKey)[] {
|
||||
const base = preference?.config ?? descr.config
|
||||
const result: (string | BuildModelKey)[] = []
|
||||
for (const key of base) {
|
||||
if (typeof key === 'string') {
|
||||
result.push(replacedKeys.get(key) ?? key)
|
||||
} else {
|
||||
result.push(replacedKeys.get(key.key) ?? key)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if viewlet?.$lookup?.descriptor?.component}
|
||||
<Component
|
||||
is={viewlet.$lookup.descriptor.component}
|
||||
props={{
|
||||
currentSpace,
|
||||
config: createConfig(viewlet, undefined),
|
||||
config: viewlet.config,
|
||||
options: viewlet.options,
|
||||
viewlet,
|
||||
query,
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import core, { DocumentQuery, Ref, Space, WithLookup } from '@anticrm/core'
|
||||
import { DocumentQuery, WithLookup } from '@anticrm/core'
|
||||
import { IntlString, translate } from '@anticrm/platform'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import { Issue, Team } from '@anticrm/tracker'
|
||||
import { Issue } from '@anticrm/tracker'
|
||||
import { Button, IconDetails } from '@anticrm/ui'
|
||||
import view, { Viewlet } from '@anticrm/view'
|
||||
import { FilterBar } from '@anticrm/view-resources'
|
||||
@ -11,7 +11,6 @@
|
||||
import IssuesContent from './IssuesContent.svelte'
|
||||
import IssuesHeader from './IssuesHeader.svelte'
|
||||
|
||||
export let currentSpace: Ref<Team> | undefined
|
||||
export let query: DocumentQuery<Issue> = {}
|
||||
export let title: IntlString | undefined = undefined
|
||||
export let label: string = ''
|
||||
@ -32,23 +31,20 @@
|
||||
|
||||
let viewlets: WithLookup<Viewlet>[] = []
|
||||
|
||||
$: update(currentSpace)
|
||||
$: update()
|
||||
|
||||
async function update (currentSpace?: Ref<Space>): Promise<void> {
|
||||
const space = await client.findOne(core.class.Space, { _id: currentSpace })
|
||||
if (space) {
|
||||
viewlets = await client.findAll(
|
||||
view.class.Viewlet,
|
||||
{ attachTo: tracker.class.Issue },
|
||||
{
|
||||
lookup: {
|
||||
descriptor: view.class.ViewletDescriptor
|
||||
}
|
||||
async function update (): Promise<void> {
|
||||
viewlets = await client.findAll(
|
||||
view.class.Viewlet,
|
||||
{ attachTo: tracker.class.Issue },
|
||||
{
|
||||
lookup: {
|
||||
descriptor: view.class.ViewletDescriptor
|
||||
}
|
||||
)
|
||||
const _id = getActiveViewletId()
|
||||
viewlet = viewlets.find((viewlet) => viewlet._id === _id) || viewlets[0]
|
||||
}
|
||||
}
|
||||
)
|
||||
const _id = getActiveViewletId()
|
||||
viewlet = viewlets.find((viewlet) => viewlet._id === _id) || viewlets[0]
|
||||
}
|
||||
$: if (!label && title) {
|
||||
translate(title, {}).then((res) => {
|
||||
@ -69,31 +65,30 @@
|
||||
$: if (docWidth > 900 && docSize) docSize = false
|
||||
</script>
|
||||
|
||||
{#if currentSpace}
|
||||
<IssuesHeader {viewlets} {label} bind:viewlet bind:search>
|
||||
<svelte:fragment slot="extra">
|
||||
{#if asideFloat && $$slots.aside}
|
||||
<Button
|
||||
icon={IconDetails}
|
||||
kind={'transparent'}
|
||||
size={'medium'}
|
||||
selected={asideShown}
|
||||
on:click={() => {
|
||||
asideShown = !asideShown
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</IssuesHeader>
|
||||
<FilterBar _class={tracker.class.Issue} query={searchQuery} on:change={(e) => (resultQuery = e.detail)} />
|
||||
<div class="flex w-full h-full clear-mins">
|
||||
{#if viewlet}
|
||||
<IssuesContent {currentSpace} {viewlet} query={resultQuery} />
|
||||
<IssuesHeader {viewlets} {label} bind:viewlet bind:search>
|
||||
<svelte:fragment slot="extra">
|
||||
{#if asideFloat && $$slots.aside}
|
||||
<Button
|
||||
icon={IconDetails}
|
||||
kind={'transparent'}
|
||||
size={'medium'}
|
||||
selected={asideShown}
|
||||
on:click={() => {
|
||||
asideShown = !asideShown
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if $$slots.aside !== undefined && asideShown}
|
||||
<div class="popupPanel-body__aside" class:float={asideFloat} class:shown={asideShown}>
|
||||
<slot name="aside" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</IssuesHeader>
|
||||
<slot name="afterHeader" />
|
||||
<FilterBar _class={tracker.class.Issue} query={searchQuery} on:change={(e) => (resultQuery = e.detail)} />
|
||||
<div class="flex w-full h-full clear-mins">
|
||||
{#if viewlet}
|
||||
<IssuesContent {viewlet} query={resultQuery} />
|
||||
{/if}
|
||||
{#if $$slots.aside !== undefined && asideShown}
|
||||
<div class="popupPanel-body__aside" class:float={asideFloat} class:shown={asideShown}>
|
||||
<slot name="aside" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact from '@anticrm/contact'
|
||||
import { Class, Doc, FindOptions, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import { Class, Doc, DocumentQuery, FindOptions, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import { Kanban, TypeState } from '@anticrm/kanban'
|
||||
import notification from '@anticrm/notification'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
@ -33,17 +33,18 @@
|
||||
import IssuePresenter from './IssuePresenter.svelte'
|
||||
import PriorityEditor from './PriorityEditor.svelte'
|
||||
|
||||
export let currentSpace: Ref<Team>
|
||||
export let currentSpace: Ref<Team> = tracker.team.DefaultTeam
|
||||
export let baseMenuClass: Ref<Class<Doc>> | undefined = undefined
|
||||
export let viewOptions: ViewOptions
|
||||
export let query = {}
|
||||
export let query: DocumentQuery<Issue> = {}
|
||||
|
||||
$: currentSpace = typeof query.space === 'string' ? query.space : tracker.team.DefaultTeam
|
||||
$: ({ groupBy, shouldShowEmptyGroups, shouldShowSubIssues } = viewOptions)
|
||||
$: resultQuery = {
|
||||
...(shouldShowSubIssues ? {} : { attachedTo: tracker.ids.NoParent }),
|
||||
space: currentSpace,
|
||||
...query
|
||||
}
|
||||
} as any
|
||||
|
||||
const spaceQuery = createQuery()
|
||||
const statusesQuery = createQuery()
|
||||
@ -120,7 +121,6 @@
|
||||
<Kanban
|
||||
bind:this={kanbanUI}
|
||||
_class={tracker.class.Issue}
|
||||
space={currentSpace}
|
||||
search=""
|
||||
{states}
|
||||
{options}
|
||||
|
@ -2,8 +2,8 @@
|
||||
import { Scroller } from '@anticrm/ui'
|
||||
import IssuesListBrowser from './IssuesListBrowser.svelte'
|
||||
import tracker from '../../plugin'
|
||||
import { Issue, IssueStatus, Team, ViewOptions } from '@anticrm/tracker'
|
||||
import { Class, Doc, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import { Issue, IssueStatus, ViewOptions } from '@anticrm/tracker'
|
||||
import { Class, Doc, DocumentQuery, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import {
|
||||
getCategories,
|
||||
groupBy as groupByFunc,
|
||||
@ -16,11 +16,11 @@
|
||||
import { BuildModelKey } from '@anticrm/view'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let currentSpace: Ref<Team>
|
||||
export let config: (string | BuildModelKey)[]
|
||||
export let query = {}
|
||||
export let query: DocumentQuery<Issue> = {}
|
||||
export let viewOptions: ViewOptions
|
||||
|
||||
$: currentSpace = typeof query.space === 'string' ? query.space : tracker.team.DefaultTeam
|
||||
$: ({ groupBy, orderBy, shouldShowEmptyGroups, shouldShowSubIssues } = viewOptions)
|
||||
$: groupByKey = issuesGroupKeyMap[groupBy]
|
||||
$: orderByKey = issuesOrderKeyMap[orderBy]
|
||||
|
@ -0,0 +1,64 @@
|
||||
<!--
|
||||
// Copyright © 2022 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { DocumentQuery, getCurrentAccount, Ref, TxCollectionCUD } from '@anticrm/core'
|
||||
import type { Issue } from '@anticrm/tracker'
|
||||
import type { EmployeeAccount } from '@anticrm/contact'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { createQuery } from '@anticrm/presentation'
|
||||
import notification from '@anticrm/notification'
|
||||
|
||||
import IssuesView from '../issues/IssuesView.svelte'
|
||||
import ModeSelector from '../ModeSelector.svelte'
|
||||
import tracker from '../../plugin'
|
||||
|
||||
const config: [string, IntlString][] = [
|
||||
['assigned', tracker.string.Assigned],
|
||||
['created', tracker.string.Created],
|
||||
['subscribed', tracker.string.Subscribed]
|
||||
]
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
const queries: { [n: string]: DocumentQuery<Issue> | undefined } = { assigned: { assignee: currentUser.employee } }
|
||||
|
||||
const createdQuery = createQuery()
|
||||
$: createdQuery.query<TxCollectionCUD<Issue, Issue>>(
|
||||
core.class.TxCollectionCUD,
|
||||
{ modifiedBy: currentUser._id, objectClass: tracker.class.Issue, collection: 'subIssues' },
|
||||
(result) => {
|
||||
queries.created = { _id: { $in: result.map(({ tx: { objectId } }) => objectId) } }
|
||||
}
|
||||
)
|
||||
|
||||
const subscribedQuery = createQuery()
|
||||
$: subscribedQuery.query(
|
||||
notification.class.LastView,
|
||||
{ user: getCurrentAccount()._id, attachedToClass: tracker.class.Issue, lastView: { $gte: 0 } },
|
||||
(result) => {
|
||||
queries.subscribed = { _id: { $in: result.map(({ attachedTo }) => attachedTo as Ref<Issue>) } }
|
||||
}
|
||||
)
|
||||
|
||||
let [[mode]] = config
|
||||
function handleChangeMode (newMode: string) {
|
||||
if (newMode === mode) return
|
||||
mode = newMode
|
||||
}
|
||||
</script>
|
||||
|
||||
<IssuesView query={queries[mode]} title={tracker.string.MyIssues}>
|
||||
<svelte:fragment slot="afterHeader">
|
||||
<ModeSelector {config} {mode} onChange={handleChangeMode} />
|
||||
</svelte:fragment>
|
||||
</IssuesView>
|
@ -16,7 +16,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<IssuesView currentSpace={project.space} query={{ project: project._id }} label={project.label}>
|
||||
<IssuesView query={{ project: project._id, space: project.space }} label={project.label}>
|
||||
<svelte:fragment slot="aside">
|
||||
<div class="flex-row p-4">
|
||||
<div class="fs-title text-xl">
|
||||
|
@ -142,9 +142,6 @@ export default async (): Promise<Resources> => ({
|
||||
KanbanView,
|
||||
IssuePreview
|
||||
},
|
||||
function: {
|
||||
ProjectVisible: () => false
|
||||
},
|
||||
completion: {
|
||||
IssueQuery: async (client: Client, query: string) => await queryIssue(tracker.class.Issue, client, query)
|
||||
}
|
||||
|
@ -12,11 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
import type { IntlString, Resource } from '@anticrm/platform'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
import tracker, { trackerId } from '../../tracker/lib'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
import { Space } from '@anticrm/core'
|
||||
|
||||
export default mergeIds(trackerId, tracker, {
|
||||
string: {
|
||||
@ -160,6 +159,10 @@ export default mergeIds(trackerId, tracker, {
|
||||
AllFilters: '' as IntlString,
|
||||
NoDescription: '' as IntlString,
|
||||
|
||||
Assigned: '' as IntlString,
|
||||
Created: '' as IntlString,
|
||||
Subscribed: '' as IntlString,
|
||||
|
||||
DurMinutes: '' as IntlString,
|
||||
DurHours: '' as IntlString,
|
||||
DurDays: '' as IntlString,
|
||||
@ -203,8 +206,5 @@ export default mergeIds(trackerId, tracker, {
|
||||
ListView: '' as AnyComponent,
|
||||
KanbanView: '' as AnyComponent,
|
||||
IssuePreview: '' as AnyComponent
|
||||
},
|
||||
function: {
|
||||
ProjectVisible: '' as '' as Resource<(spaces: Space[]) => boolean>
|
||||
}
|
||||
})
|
||||
|
@ -268,5 +268,8 @@ export default plugin(trackerId, {
|
||||
action: {
|
||||
SetDueDate: '' as Ref<Action>,
|
||||
SetParent: '' as Ref<Action>
|
||||
},
|
||||
team: {
|
||||
DefaultTeam: '' as Ref<Team>
|
||||
}
|
||||
})
|
||||
|
@ -100,6 +100,10 @@ async function checkIssue (
|
||||
}
|
||||
}
|
||||
|
||||
async function openIssue (page: Page, name: string): Promise<void> {
|
||||
await page.click(`.antiList__row:has-text("${name}") .issuePresenterRoot`)
|
||||
}
|
||||
|
||||
const defaultStatuses = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
|
||||
const defaultUser = 'John Appleseed'
|
||||
enum viewletSelectors {
|
||||
@ -122,7 +126,7 @@ test('create-issue-and-sub-issue', async ({ page }) => {
|
||||
}
|
||||
await createIssue(page, props)
|
||||
await page.click('text="Issues"')
|
||||
await page.click(`.antiList__row:has-text("${props.name}") .issuePresenterRoot`)
|
||||
await openIssue(page, props.name)
|
||||
await checkIssue(page, props)
|
||||
props.name = `sub${props.name}`
|
||||
await createSubissue(page, props)
|
||||
@ -178,3 +182,21 @@ test('save-view-options', async ({ page }) => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('my-issues', async ({ page }) => {
|
||||
const name = getIssueName()
|
||||
await navigate(page)
|
||||
await createIssue(page, { name })
|
||||
await page.click('text="My issues"')
|
||||
await page.click('button:has-text("Assigned")')
|
||||
await expect(page.locator('.antiPanel-component')).not.toContainText(name)
|
||||
await page.click('button:has-text("Created")')
|
||||
await expect(page.locator('.antiPanel-component')).toContainText(name)
|
||||
await page.click('button:has-text("Subscribed")')
|
||||
await expect(page.locator('.antiPanel-component')).toContainText(name)
|
||||
await openIssue(page, name)
|
||||
// click "Don't track"
|
||||
await page.click('.popupPanel-title :nth-child(3) >> button >> nth=1')
|
||||
await page.keyboard.press('Escape')
|
||||
await expect(page.locator('.antiPanel-component')).not.toContainText(name)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user