mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +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,
|
||||
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,
|
||||
label: tracker.string.Components,
|
||||
|
@ -1,26 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { TabList } from '@hcengineering/ui'
|
||||
import { IModeSelector } from '../utils'
|
||||
|
||||
export let mode: string
|
||||
export let config: [string, IntlString, object][]
|
||||
export let onChange: (_mode: string) => void
|
||||
export let props: IModeSelector
|
||||
|
||||
$: modeList = config.map((c) => {
|
||||
$: modeList = props.config.map((c) => {
|
||||
return {
|
||||
id: c[0],
|
||||
labelIntl: c[1],
|
||||
labelParams: c[2],
|
||||
action: () => onChange(c[0])
|
||||
action: () => props.onChange(c[0])
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="ac-header tabs-start full divide">
|
||||
<div class="ac-header tabs-start full">
|
||||
<TabList
|
||||
items={modeList}
|
||||
selected={mode}
|
||||
kind={'plain'}
|
||||
selected={props.mode}
|
||||
kind={'separated'}
|
||||
on:select={(result) => {
|
||||
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.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { Project } from '@hcengineering/tracker'
|
||||
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 { IModeSelector } from '../../utils'
|
||||
|
||||
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>
|
||||
|
||||
<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 { TabList, SearchEdit } from '@hcengineering/ui'
|
||||
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 { 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 viewlet: WithLookup<Viewlet> | undefined
|
||||
@ -13,6 +14,7 @@
|
||||
export let label: string
|
||||
export let search: string
|
||||
export let showLabelSelector = false
|
||||
export let modeSelectorProps: IModeSelector | undefined = undefined
|
||||
|
||||
$: viewslist = viewlets.map((views) => {
|
||||
return {
|
||||
@ -21,16 +23,25 @@
|
||||
tooltip: views.$lookup?.descriptor?.label
|
||||
}
|
||||
})
|
||||
|
||||
// $: twoRows = $deviceInfo.twoRows
|
||||
$: count = $focusStore.provider?.docs().length
|
||||
$: headerTitle = count === undefined ? label : `${label} (${count})`
|
||||
</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">
|
||||
{#if showLabelSelector}
|
||||
<slot name="label_selector" />
|
||||
{: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}
|
||||
</div>
|
||||
<div class="mb-1 clear-mins">
|
||||
@ -65,3 +76,13 @@
|
||||
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
|
||||
</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 IssuesContent from './IssuesContent.svelte'
|
||||
import IssuesHeader from './IssuesHeader.svelte'
|
||||
import { IModeSelector } from '../../utils'
|
||||
|
||||
export let space: Ref<Space> | undefined = undefined
|
||||
export let query: DocumentQuery<Issue> = {}
|
||||
export let title: IntlString | undefined = undefined
|
||||
export let label: string = ''
|
||||
|
||||
export let panelWidth: number = 0
|
||||
export let modeSelectorProps: IModeSelector | undefined = undefined
|
||||
|
||||
let viewlet: WithLookup<Viewlet> | undefined = undefined
|
||||
let search = ''
|
||||
@ -81,7 +82,15 @@
|
||||
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
|
||||
</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">
|
||||
<slot name="label_selector" />
|
||||
</svelte:fragment>
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
import tracker from '../../plugin'
|
||||
import IssuesView from '../issues/IssuesView.svelte'
|
||||
import ModeSelector from '../ModeSelector.svelte'
|
||||
import { IModeSelector } from '../../utils'
|
||||
|
||||
const config: [string, IntlString, object][] = [
|
||||
['assigned', tracker.string.Assigned, {}],
|
||||
['created', tracker.string.Created, { value: 0 }],
|
||||
['created', tracker.string.Created, {}],
|
||||
['subscribed', tracker.string.Subscribed, {}]
|
||||
]
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
@ -57,10 +57,11 @@
|
||||
return { ...queries[mode], '$lookup.space.archived': false }
|
||||
}
|
||||
$: query = getQuery(mode, { assigned, created, subscribed })
|
||||
$: modeSelectorProps = {
|
||||
config,
|
||||
mode,
|
||||
onChange: handleChangeMode
|
||||
} as IModeSelector
|
||||
</script>
|
||||
|
||||
<IssuesView {query} space={undefined} title={tracker.string.MyIssues}>
|
||||
<svelte:fragment slot="afterHeader">
|
||||
<ModeSelector {config} {mode} onChange={handleChangeMode} />
|
||||
</svelte:fragment>
|
||||
</IssuesView>
|
||||
<IssuesView {query} space={undefined} title={tracker.string.MyIssues} {modeSelectorProps} />
|
||||
|
@ -41,9 +41,7 @@ import ProjectComponents from './components/components/ProjectComponents.svelte'
|
||||
import TargetDatePresenter from './components/components/TargetDatePresenter.svelte'
|
||||
import CreateIssue from './components/CreateIssue.svelte'
|
||||
import Inbox from './components/inbox/Inbox.svelte'
|
||||
import Active from './components/issues/Active.svelte'
|
||||
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
||||
import Backlog from './components/issues/Backlog.svelte'
|
||||
import DueDatePresenter from './components/issues/DueDatePresenter.svelte'
|
||||
import EditIssue from './components/issues/edit/EditIssue.svelte'
|
||||
import IssueItem from './components/issues/IssueItem.svelte'
|
||||
@ -385,8 +383,6 @@ export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
NopeComponent,
|
||||
Issues,
|
||||
Active,
|
||||
Backlog,
|
||||
Inbox,
|
||||
MyIssues,
|
||||
Components,
|
||||
|
@ -324,8 +324,6 @@ export default mergeIds(trackerId, tracker, {
|
||||
MyIssues: '' as AnyComponent,
|
||||
Views: '' as AnyComponent,
|
||||
Issues: '' as AnyComponent,
|
||||
Active: '' as AnyComponent,
|
||||
Backlog: '' as AnyComponent,
|
||||
Components: '' as AnyComponent,
|
||||
ComponentsTimeline: '' as AnyComponent,
|
||||
IssuePresenter: '' as AnyComponent,
|
||||
|
@ -671,3 +671,12 @@ export function issueToAttachedData (issue: Issue): AttachedData<Issue> {
|
||||
const { _id, _class, space, ...data } = issue
|
||||
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