mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 04:23:58 +03:00
[UBER-74] Update issues header (#3202)
Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
This commit is contained in:
parent
d816b99e54
commit
cc3afc40a3
@ -1051,16 +1051,6 @@ export function createModel (builder: Builder): void {
|
|||||||
icon: tracker.icon.Issues,
|
icon: tracker.icon.Issues,
|
||||||
component: tracker.component.Issues
|
component: tracker.component.Issues
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: activeId,
|
|
||||||
label: tracker.string.Active,
|
|
||||||
component: tracker.component.Active
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: backlogId,
|
|
||||||
label: tracker.string.Backlog,
|
|
||||||
component: tracker.component.Backlog
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: componentsId,
|
id: componentsId,
|
||||||
label: tracker.string.Components,
|
label: tracker.string.Components,
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { IntlString } from '@hcengineering/platform'
|
|
||||||
import { TabList } from '@hcengineering/ui'
|
import { TabList } from '@hcengineering/ui'
|
||||||
|
import { IModeSelector } from '../utils'
|
||||||
|
|
||||||
export let mode: string
|
export let props: IModeSelector
|
||||||
export let config: [string, IntlString, object][]
|
|
||||||
export let onChange: (_mode: string) => void
|
|
||||||
|
|
||||||
$: modeList = config.map((c) => {
|
$: modeList = props.config.map((c) => {
|
||||||
return {
|
return {
|
||||||
id: c[0],
|
id: c[0],
|
||||||
labelIntl: c[1],
|
labelIntl: c[1],
|
||||||
labelParams: c[2],
|
labelParams: c[2],
|
||||||
action: () => onChange(c[0])
|
action: () => props.onChange(c[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header tabs-start full divide">
|
<div class="ac-header tabs-start full">
|
||||||
<TabList
|
<TabList
|
||||||
items={modeList}
|
items={modeList}
|
||||||
selected={mode}
|
selected={props.mode}
|
||||||
kind={'plain'}
|
kind={'separated'}
|
||||||
on:select={(result) => {
|
on:select={(result) => {
|
||||||
if (result.detail !== undefined && result.detail.action) result.detail.action()
|
if (result.detail !== undefined && result.detail.action) result.detail.action()
|
||||||
}}
|
}}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
<!--
|
|
||||||
// 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 { DocumentQuery, Ref } from '@hcengineering/core'
|
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
|
||||||
import { Issue, Project } from '@hcengineering/tracker'
|
|
||||||
import tracker from '../../plugin'
|
|
||||||
import IssuesView from './IssuesView.svelte'
|
|
||||||
|
|
||||||
export let currentSpace: Ref<Project>
|
|
||||||
|
|
||||||
const statusQuery = createQuery()
|
|
||||||
let query: DocumentQuery<Issue>
|
|
||||||
$: statusQuery.query(
|
|
||||||
tracker.class.IssueStatus,
|
|
||||||
{
|
|
||||||
category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] },
|
|
||||||
space: currentSpace
|
|
||||||
},
|
|
||||||
(result) => {
|
|
||||||
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<IssuesView {query} space={currentSpace} title={tracker.string.ActiveIssues} />
|
|
@ -1,35 +0,0 @@
|
|||||||
<!--
|
|
||||||
// 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 { DocumentQuery, Ref } from '@hcengineering/core'
|
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
|
||||||
import { Issue, Project } from '@hcengineering/tracker'
|
|
||||||
import tracker from '../../plugin'
|
|
||||||
import IssuesView from './IssuesView.svelte'
|
|
||||||
|
|
||||||
export let currentSpace: Ref<Project>
|
|
||||||
|
|
||||||
const statusQuery = createQuery()
|
|
||||||
let query: DocumentQuery<Issue> = {}
|
|
||||||
$: statusQuery.query(
|
|
||||||
tracker.class.IssueStatus,
|
|
||||||
{ category: tracker.issueStatusCategory.Backlog, space: currentSpace },
|
|
||||||
(result) => {
|
|
||||||
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<IssuesView {query} space={currentSpace} title={tracker.string.BacklogIssues} />
|
|
@ -13,14 +13,62 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Ref } from '@hcengineering/core'
|
import { DocumentQuery, Ref } from '@hcengineering/core'
|
||||||
import { Project } from '@hcengineering/tracker'
|
import { Issue, Project } from '@hcengineering/tracker'
|
||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import IssuesView from './IssuesView.svelte'
|
import IssuesView from './IssuesView.svelte'
|
||||||
|
import { IntlString } from '@hcengineering/platform'
|
||||||
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
|
import { IModeSelector } from '../../utils'
|
||||||
|
|
||||||
export let currentSpace: Ref<Project>
|
export let currentSpace: Ref<Project>
|
||||||
|
|
||||||
$: query = { space: currentSpace }
|
const config: [string, IntlString, object][] = [
|
||||||
|
['all', tracker.string.All, {}],
|
||||||
|
['active', tracker.string.Active, {}],
|
||||||
|
['backlog', tracker.string.Backlog, {}]
|
||||||
|
]
|
||||||
|
|
||||||
|
$: all = { space: currentSpace }
|
||||||
|
|
||||||
|
const activeStatusQuery = createQuery()
|
||||||
|
let active: DocumentQuery<Issue>
|
||||||
|
$: activeStatusQuery.query(
|
||||||
|
tracker.class.IssueStatus,
|
||||||
|
{
|
||||||
|
category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] },
|
||||||
|
space: currentSpace
|
||||||
|
},
|
||||||
|
(result) => {
|
||||||
|
active = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const backlogStatusQuery = createQuery()
|
||||||
|
let backlog: DocumentQuery<Issue> = {}
|
||||||
|
$: backlogStatusQuery.query(
|
||||||
|
tracker.class.IssueStatus,
|
||||||
|
{ category: tracker.issueStatusCategory.Backlog, space: currentSpace },
|
||||||
|
(result) => {
|
||||||
|
backlog = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let [[mode]] = config
|
||||||
|
function handleChangeMode (newMode: string) {
|
||||||
|
if (newMode === mode) return
|
||||||
|
mode = newMode
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQuery (mode: string, queries: { [key: string]: DocumentQuery<Issue> }) {
|
||||||
|
return { ...queries[mode], '$lookup.space.archived': false }
|
||||||
|
}
|
||||||
|
$: query = getQuery(mode, { all, active, backlog })
|
||||||
|
$: modeSelectorProps = {
|
||||||
|
config,
|
||||||
|
mode,
|
||||||
|
onChange: handleChangeMode
|
||||||
|
} as IModeSelector
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<IssuesView {query} space={currentSpace} title={tracker.string.Issues} />
|
<IssuesView {query} space={currentSpace} title={tracker.string.Issues} {modeSelectorProps} />
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
import { Ref, Space } from '@hcengineering/core'
|
import { Ref, Space } from '@hcengineering/core'
|
||||||
import { TabList, SearchEdit } from '@hcengineering/ui'
|
import { TabList, SearchEdit } from '@hcengineering/ui'
|
||||||
import { Viewlet } from '@hcengineering/view'
|
import { Viewlet } from '@hcengineering/view'
|
||||||
import { FilterButton, setActiveViewletId } from '@hcengineering/view-resources'
|
import { focusStore, FilterButton, setActiveViewletId } from '@hcengineering/view-resources'
|
||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import { WithLookup } from '@hcengineering/core'
|
import { WithLookup } from '@hcengineering/core'
|
||||||
// import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
import ModeSelector from '../ModeSelector.svelte'
|
||||||
|
import { IModeSelector } from '../../utils'
|
||||||
|
|
||||||
export let space: Ref<Space> | undefined = undefined
|
export let space: Ref<Space> | undefined = undefined
|
||||||
export let viewlet: WithLookup<Viewlet> | undefined
|
export let viewlet: WithLookup<Viewlet> | undefined
|
||||||
@ -13,6 +14,7 @@
|
|||||||
export let label: string
|
export let label: string
|
||||||
export let search: string
|
export let search: string
|
||||||
export let showLabelSelector = false
|
export let showLabelSelector = false
|
||||||
|
export let modeSelectorProps: IModeSelector | undefined = undefined
|
||||||
|
|
||||||
$: viewslist = viewlets.map((views) => {
|
$: viewslist = viewlets.map((views) => {
|
||||||
return {
|
return {
|
||||||
@ -21,16 +23,25 @@
|
|||||||
tooltip: views.$lookup?.descriptor?.label
|
tooltip: views.$lookup?.descriptor?.label
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
$: count = $focusStore.provider?.docs().length
|
||||||
// $: twoRows = $deviceInfo.twoRows
|
$: headerTitle = count === undefined ? label : `${label} (${count})`
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header full divide">
|
<div
|
||||||
|
class="ac-header full divide"
|
||||||
|
class:header-with-mode-selector={modeSelectorProps !== undefined}
|
||||||
|
class:header-without-label={!label}
|
||||||
|
>
|
||||||
<div class="ac-header__wrap-title">
|
<div class="ac-header__wrap-title">
|
||||||
{#if showLabelSelector}
|
{#if showLabelSelector}
|
||||||
<slot name="label_selector" />
|
<slot name="label_selector" />
|
||||||
{:else}
|
{:else}
|
||||||
<span class="ac-header__title">{label}</span>
|
{#if label}
|
||||||
|
<span class="ac-header__title">{headerTitle}</span>
|
||||||
|
{/if}
|
||||||
|
{#if modeSelectorProps !== undefined}
|
||||||
|
<ModeSelector props={modeSelectorProps} />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-1 clear-mins">
|
<div class="mb-1 clear-mins">
|
||||||
@ -65,3 +76,13 @@
|
|||||||
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
|
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.header-with-mode-selector {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
.header-without-label {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -18,13 +18,14 @@
|
|||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import IssuesContent from './IssuesContent.svelte'
|
import IssuesContent from './IssuesContent.svelte'
|
||||||
import IssuesHeader from './IssuesHeader.svelte'
|
import IssuesHeader from './IssuesHeader.svelte'
|
||||||
|
import { IModeSelector } from '../../utils'
|
||||||
|
|
||||||
export let space: Ref<Space> | undefined = undefined
|
export let space: Ref<Space> | undefined = undefined
|
||||||
export let query: DocumentQuery<Issue> = {}
|
export let query: DocumentQuery<Issue> = {}
|
||||||
export let title: IntlString | undefined = undefined
|
export let title: IntlString | undefined = undefined
|
||||||
export let label: string = ''
|
export let label: string = ''
|
||||||
|
|
||||||
export let panelWidth: number = 0
|
export let panelWidth: number = 0
|
||||||
|
export let modeSelectorProps: IModeSelector | undefined = undefined
|
||||||
|
|
||||||
let viewlet: WithLookup<Viewlet> | undefined = undefined
|
let viewlet: WithLookup<Viewlet> | undefined = undefined
|
||||||
let search = ''
|
let search = ''
|
||||||
@ -81,7 +82,15 @@
|
|||||||
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
|
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<IssuesHeader {viewlets} {label} {space} bind:viewlet bind:search showLabelSelector={$$slots.label_selector}>
|
<IssuesHeader
|
||||||
|
bind:viewlet
|
||||||
|
bind:search
|
||||||
|
showLabelSelector={$$slots.label_selector}
|
||||||
|
{viewlets}
|
||||||
|
{label}
|
||||||
|
{space}
|
||||||
|
{modeSelectorProps}
|
||||||
|
>
|
||||||
<svelte:fragment slot="label_selector">
|
<svelte:fragment slot="label_selector">
|
||||||
<slot name="label_selector" />
|
<slot name="label_selector" />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import IssuesView from '../issues/IssuesView.svelte'
|
import IssuesView from '../issues/IssuesView.svelte'
|
||||||
import ModeSelector from '../ModeSelector.svelte'
|
import { IModeSelector } from '../../utils'
|
||||||
|
|
||||||
const config: [string, IntlString, object][] = [
|
const config: [string, IntlString, object][] = [
|
||||||
['assigned', tracker.string.Assigned, {}],
|
['assigned', tracker.string.Assigned, {}],
|
||||||
['created', tracker.string.Created, { value: 0 }],
|
['created', tracker.string.Created, {}],
|
||||||
['subscribed', tracker.string.Subscribed, {}]
|
['subscribed', tracker.string.Subscribed, {}]
|
||||||
]
|
]
|
||||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||||
@ -57,10 +57,11 @@
|
|||||||
return { ...queries[mode], '$lookup.space.archived': false }
|
return { ...queries[mode], '$lookup.space.archived': false }
|
||||||
}
|
}
|
||||||
$: query = getQuery(mode, { assigned, created, subscribed })
|
$: query = getQuery(mode, { assigned, created, subscribed })
|
||||||
|
$: modeSelectorProps = {
|
||||||
|
config,
|
||||||
|
mode,
|
||||||
|
onChange: handleChangeMode
|
||||||
|
} as IModeSelector
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<IssuesView {query} space={undefined} title={tracker.string.MyIssues}>
|
<IssuesView {query} space={undefined} title={tracker.string.MyIssues} {modeSelectorProps} />
|
||||||
<svelte:fragment slot="afterHeader">
|
|
||||||
<ModeSelector {config} {mode} onChange={handleChangeMode} />
|
|
||||||
</svelte:fragment>
|
|
||||||
</IssuesView>
|
|
||||||
|
@ -41,9 +41,7 @@ import ProjectComponents from './components/components/ProjectComponents.svelte'
|
|||||||
import TargetDatePresenter from './components/components/TargetDatePresenter.svelte'
|
import TargetDatePresenter from './components/components/TargetDatePresenter.svelte'
|
||||||
import CreateIssue from './components/CreateIssue.svelte'
|
import CreateIssue from './components/CreateIssue.svelte'
|
||||||
import Inbox from './components/inbox/Inbox.svelte'
|
import Inbox from './components/inbox/Inbox.svelte'
|
||||||
import Active from './components/issues/Active.svelte'
|
|
||||||
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
||||||
import Backlog from './components/issues/Backlog.svelte'
|
|
||||||
import DueDatePresenter from './components/issues/DueDatePresenter.svelte'
|
import DueDatePresenter from './components/issues/DueDatePresenter.svelte'
|
||||||
import EditIssue from './components/issues/edit/EditIssue.svelte'
|
import EditIssue from './components/issues/edit/EditIssue.svelte'
|
||||||
import IssueItem from './components/issues/IssueItem.svelte'
|
import IssueItem from './components/issues/IssueItem.svelte'
|
||||||
@ -385,8 +383,6 @@ export default async (): Promise<Resources> => ({
|
|||||||
component: {
|
component: {
|
||||||
NopeComponent,
|
NopeComponent,
|
||||||
Issues,
|
Issues,
|
||||||
Active,
|
|
||||||
Backlog,
|
|
||||||
Inbox,
|
Inbox,
|
||||||
MyIssues,
|
MyIssues,
|
||||||
Components,
|
Components,
|
||||||
|
@ -324,8 +324,6 @@ export default mergeIds(trackerId, tracker, {
|
|||||||
MyIssues: '' as AnyComponent,
|
MyIssues: '' as AnyComponent,
|
||||||
Views: '' as AnyComponent,
|
Views: '' as AnyComponent,
|
||||||
Issues: '' as AnyComponent,
|
Issues: '' as AnyComponent,
|
||||||
Active: '' as AnyComponent,
|
|
||||||
Backlog: '' as AnyComponent,
|
|
||||||
Components: '' as AnyComponent,
|
Components: '' as AnyComponent,
|
||||||
ComponentsTimeline: '' as AnyComponent,
|
ComponentsTimeline: '' as AnyComponent,
|
||||||
IssuePresenter: '' as AnyComponent,
|
IssuePresenter: '' as AnyComponent,
|
||||||
|
@ -671,3 +671,12 @@ export function issueToAttachedData (issue: Issue): AttachedData<Issue> {
|
|||||||
const { _id, _class, space, ...data } = issue
|
const { _id, _class, space, ...data } = issue
|
||||||
return { ...data }
|
return { ...data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IModeSelector {
|
||||||
|
mode: string
|
||||||
|
config: Array<[string, IntlString, object]>
|
||||||
|
onChange: (_mode: string) => void
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user