mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +03:00
[UBER-150] Milestones update (#3212)
Signed-off-by: Sergei Ogorelkov <sergei.ogorelkov@icloud.com>
This commit is contained in:
parent
88d62bcff5
commit
ffc3999bdf
@ -390,12 +390,6 @@ export class TMilestone extends TDoc implements Milestone {
|
||||
@Index(IndexKind.Indexed)
|
||||
status!: MilestoneStatus
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.ComponentLead)
|
||||
lead!: Ref<Employee> | null
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), tracker.string.Members)
|
||||
members!: Ref<Employee>[]
|
||||
|
||||
@Prop(Collection(chunter.class.Comment), chunter.string.Comments)
|
||||
comments!: number
|
||||
|
||||
@ -406,9 +400,6 @@ export class TMilestone extends TDoc implements Milestone {
|
||||
targetDate!: Timestamp
|
||||
|
||||
declare space: Ref<Project>
|
||||
|
||||
@Prop(TypeNumber(), tracker.string.Capacity)
|
||||
capacity!: number
|
||||
}
|
||||
|
||||
/**
|
||||
@ -955,6 +946,10 @@ export function createModel (builder: Builder): void {
|
||||
presenter: tracker.component.MilestoneRefPresenter
|
||||
})
|
||||
|
||||
builder.mixin(tracker.class.Milestone, core.class.Class, view.mixin.ObjectEditor, {
|
||||
editor: tracker.component.EditMilestone
|
||||
})
|
||||
|
||||
builder.mixin(tracker.class.Issue, core.class.Class, setting.mixin.Editable, {
|
||||
value: true
|
||||
})
|
||||
@ -1336,9 +1331,6 @@ export function createModel (builder: Builder): void {
|
||||
filters: []
|
||||
})
|
||||
|
||||
builder.mixin(tracker.class.Milestone, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: []
|
||||
})
|
||||
builder.mixin(tracker.class.Milestone, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: ['status'],
|
||||
strict: true
|
||||
@ -1766,11 +1758,10 @@ export function createModel (builder: Builder): void {
|
||||
)
|
||||
|
||||
const milestoneOptions: ViewOptionsModel = {
|
||||
groupBy: ['lead'],
|
||||
groupBy: ['status'],
|
||||
orderBy: [
|
||||
['modifiedOn', SortingOrder.Descending],
|
||||
['targetDate', SortingOrder.Descending],
|
||||
['capacity', SortingOrder.Ascending]
|
||||
['targetDate', SortingOrder.Descending]
|
||||
],
|
||||
other: []
|
||||
}
|
||||
@ -1789,26 +1780,7 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
{ key: '', presenter: tracker.component.MilestonePresenter, props: { shouldUseMargin: true } },
|
||||
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
|
||||
{
|
||||
key: '',
|
||||
presenter: contact.component.MembersPresenter,
|
||||
props: {
|
||||
kind: 'link',
|
||||
intlTitle: tracker.string.MilestoneMembersTitle,
|
||||
intlSearchPh: tracker.string.MilestoneMembersSearchPlaceholder
|
||||
}
|
||||
},
|
||||
{ key: '', presenter: tracker.component.MilestoneDatePresenter, props: { field: 'targetDate' } },
|
||||
{
|
||||
key: 'lead',
|
||||
presenter: tracker.component.MilestoneLeadPresenter,
|
||||
props: {
|
||||
_class: tracker.class.Milestone,
|
||||
defaultClass: contact.class.Employee,
|
||||
shouldShowLabel: false,
|
||||
size: 'x-small'
|
||||
}
|
||||
}
|
||||
{ key: '', presenter: tracker.component.MilestoneDatePresenter, props: { field: 'targetDate' } }
|
||||
]
|
||||
},
|
||||
tracker.viewlet.MilestoneList
|
||||
@ -1857,32 +1829,6 @@ export function createModel (builder: Builder): void {
|
||||
['comments', 'status', 'priority', 'assignee', 'subIssues', 'blockedBy', 'milestone', 'dueDate']
|
||||
)
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: view.actionImpl.ValueSelector,
|
||||
actionPopup: view.component.ValueSelector,
|
||||
actionProps: {
|
||||
attribute: 'lead',
|
||||
_class: contact.class.Employee,
|
||||
query: {},
|
||||
placeholder: tracker.string.MilestoneLead
|
||||
},
|
||||
label: tracker.string.MilestoneLead,
|
||||
icon: contact.icon.Person,
|
||||
keyBinding: [],
|
||||
input: 'none',
|
||||
category: tracker.category.Tracker,
|
||||
target: tracker.class.Milestone,
|
||||
context: {
|
||||
mode: ['context'],
|
||||
application: tracker.app.Tracker,
|
||||
group: 'edit'
|
||||
}
|
||||
},
|
||||
tracker.action.SetMilestoneLead
|
||||
)
|
||||
|
||||
const componentListViewOptions: ViewOptionsModel = {
|
||||
groupBy: ['lead'],
|
||||
orderBy: [
|
||||
|
@ -86,7 +86,6 @@ export default mergeIds(trackerId, tracker, {
|
||||
action: {
|
||||
NewRelatedIssue: '' as Ref<Action<Doc, Record<string, any>>>,
|
||||
DeleteMilestone: '' as Ref<Action<Doc, Record<string, any>>>,
|
||||
DeleteProject: '' as Ref<Action<Doc, Record<string, any>>>,
|
||||
SetMilestoneLead: '' as Ref<Action<Doc, Record<string, any>>>
|
||||
DeleteProject: '' as Ref<Action<Doc, Record<string, any>>>
|
||||
}
|
||||
})
|
||||
|
@ -207,11 +207,6 @@
|
||||
"ClosedMilestones": "Done",
|
||||
"AddToMilestone": "Add to Milestone",
|
||||
"MilestoneNamePlaceholder": "Milestone name",
|
||||
"MilestoneLead": "Lead",
|
||||
"MilestoneLeadTitle": "Milestone lead",
|
||||
"MilestoneLeadSearchPlaceholder": "Set milestone lead\u2026",
|
||||
"MilestoneMembersTitle": "Milestone members",
|
||||
"MilestoneMembersSearchPlaceholder": "Change milestone members\u2026",
|
||||
|
||||
"NewMilestone": "New Milestone",
|
||||
"CreateMilestone": "Create",
|
||||
@ -252,7 +247,6 @@
|
||||
"TimeSpendHours": "{value}h",
|
||||
"ChildEstimation": "Subissues Estimation",
|
||||
"ChildReportedTime": "Subissues Time",
|
||||
"Capacity": "Capacity",
|
||||
"CapacityValue": "of {value}d",
|
||||
"NewRelatedIssue": "New related issue",
|
||||
"RelatedIssuesNotFound": "Related issues not found",
|
||||
|
@ -207,11 +207,6 @@
|
||||
"ClosedMilestones": "Завершено",
|
||||
"AddToMilestone": "Добавить в Майлстоун",
|
||||
"MilestoneNamePlaceholder": "Название майлстоуна",
|
||||
"MilestoneLead": "Руководитель",
|
||||
"MilestoneLeadTitle": "Руководитель майлстоуна",
|
||||
"MilestoneLeadSearchPlaceholder": "Назначьте руководителя майлстоуна\u2026",
|
||||
"MilestoneMembersTitle": "Участники майлстоуна",
|
||||
"MilestoneMembersSearchPlaceholder": "Измененить участников майлстоуна\u2026",
|
||||
|
||||
"NewMilestone": "Новый Майлстоун",
|
||||
"CreateMilestone": "Создать",
|
||||
@ -252,7 +247,6 @@
|
||||
"TimeSpendHours": "{value}h",
|
||||
"ChildEstimation": "Оценка подзадач",
|
||||
"ChildReportedTime": "Время водзадач",
|
||||
"Capacity": "Вместимость",
|
||||
"CapacityValue": "из {value}d",
|
||||
"NewRelatedIssue": "Завести связанную задачу",
|
||||
"RelatedIssuesNotFound": "Связанные задачи не найдены",
|
||||
|
@ -1,89 +1,56 @@
|
||||
<!--
|
||||
// Copyright © 2023 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 { getClient } from '@hcengineering/presentation'
|
||||
import { StyledTextBox } from '@hcengineering/text-editor'
|
||||
import { Milestone } from '@hcengineering/tracker'
|
||||
import { Button, DatePresenter, EditBox, Icon, IconMoreH, Label, showPopup } from '@hcengineering/ui'
|
||||
import { ContextMenu, DocAttributeBar } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { activeMilestone } from '../../issues'
|
||||
import { EditBox } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import Expanded from '../icons/Expanded.svelte'
|
||||
import IssuesView from '../issues/IssuesView.svelte'
|
||||
import MilestonePopup from './MilestonePopup.svelte'
|
||||
|
||||
export let milestone: Milestone
|
||||
export let object: Milestone
|
||||
|
||||
const client = getClient()
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
async function change (field: string, value: any) {
|
||||
await client.update(milestone, { [field]: value })
|
||||
}
|
||||
let container: HTMLElement
|
||||
let oldLabel = ''
|
||||
let rawLabel = ''
|
||||
|
||||
function selectMilestone (): void {
|
||||
showPopup(MilestonePopup, { _class: tracker.class.Milestone }, container, (value) => {
|
||||
if (value != null) {
|
||||
milestone = value
|
||||
dispatch('milestone', milestone._id)
|
||||
}
|
||||
})
|
||||
async function change<K extends keyof Milestone> (field: K, value: Milestone[K]) {
|
||||
await client.update(object, { [field]: value })
|
||||
}
|
||||
|
||||
function showMenu (ev?: Event): void {
|
||||
if (milestone) {
|
||||
showPopup(ContextMenu, { object: milestone }, (ev as MouseEvent).target as HTMLElement)
|
||||
}
|
||||
$: if (oldLabel !== object.label) {
|
||||
oldLabel = object.label
|
||||
rawLabel = object.label
|
||||
}
|
||||
|
||||
$: $activeMilestone = milestone?._id
|
||||
|
||||
onDestroy(() => {
|
||||
$activeMilestone = undefined
|
||||
})
|
||||
onMount(() => dispatch('open', { ignoreKeys: ['label'] }))
|
||||
</script>
|
||||
|
||||
<IssuesView
|
||||
query={{ milestone: milestone._id, space: milestone.space }}
|
||||
space={milestone.space}
|
||||
label={milestone.label}
|
||||
>
|
||||
<svelte:fragment slot="label_selector">
|
||||
<div bind:this={container}>
|
||||
<Button size={'small'} kind={'link'} on:click={selectMilestone}>
|
||||
<svelte:fragment slot="content">
|
||||
<div class="ac-header__icon"><Icon icon={tracker.icon.Milestone} size={'small'} /></div>
|
||||
<span class="ac-header__title mr-1">{milestone.label}</span>
|
||||
<Icon icon={Expanded} size={'small'} />
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="afterHeader">
|
||||
<div class="ac-header search-start full divide">
|
||||
<DatePresenter value={milestone.targetDate} kind={'transparent'} size={'medium'} />
|
||||
<div class="flex-row-center ml-2">
|
||||
{#if milestone?.capacity}
|
||||
<Label label={tracker.string.CapacityValue} params={{ value: milestone?.capacity }} />
|
||||
{/if}
|
||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||
</div>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="aside">
|
||||
<div class="popupPanel-body__aside-content">
|
||||
<EditBox kind={'large-style'} bind:value={milestone.label} on:change={() => change('label', milestone.label)} />
|
||||
<div class="mt-2">
|
||||
<StyledTextBox
|
||||
alwaysEdit={true}
|
||||
showButtons={false}
|
||||
placeholder={tracker.string.Description}
|
||||
content={milestone.description ?? ''}
|
||||
on:value={(evt) => change('description', evt.detail)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DocAttributeBar object={milestone} mixins={[]} ignoreKeys={['icon', 'label', 'description']} />
|
||||
</svelte:fragment>
|
||||
</IssuesView>
|
||||
<EditBox
|
||||
bind:value={rawLabel}
|
||||
placeholder={tracker.string.MilestoneNamePlaceholder}
|
||||
kind="large-style"
|
||||
focusable
|
||||
on:blur={async () => {
|
||||
const trimmedLabel = rawLabel.trim()
|
||||
|
||||
if (trimmedLabel.length === 0) {
|
||||
rawLabel = oldLabel
|
||||
} else if (trimmedLabel !== object.label) {
|
||||
await change('label', trimmedLabel)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -138,7 +138,7 @@
|
||||
<SearchEdit bind:value={search} on:change={() => {}} />
|
||||
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
|
||||
<div class="buttons-divider" />
|
||||
<FilterButton _class={tracker.class.Issue} {space} />
|
||||
<FilterButton _class={tracker.class.Milestone} {space} />
|
||||
</div>
|
||||
<div class="ac-header-full medium-gap">
|
||||
{#if viewlet}
|
||||
|
@ -1,9 +1,8 @@
|
||||
<script lang="ts">
|
||||
import contact from '@hcengineering/contact'
|
||||
import { DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core'
|
||||
import { Milestone } from '@hcengineering/tracker'
|
||||
import { Component } from '@hcengineering/ui'
|
||||
import { BuildModelKey, Viewlet, ViewOptions } from '@hcengineering/view'
|
||||
import { Viewlet, ViewOptions } from '@hcengineering/view'
|
||||
import tracker from '../../plugin'
|
||||
import NewMilestone from './NewMilestone.svelte'
|
||||
|
||||
@ -16,19 +15,6 @@
|
||||
|
||||
const createItemDialog = NewMilestone
|
||||
const createItemLabel = tracker.string.CreateMilestone
|
||||
|
||||
const retrieveMembers = (s: Milestone) => s.members
|
||||
|
||||
function updateConfig (config: (string | BuildModelKey)[]): (string | BuildModelKey)[] {
|
||||
return config.map((it) => {
|
||||
if (typeof it === 'string') {
|
||||
return it
|
||||
}
|
||||
return it.presenter === contact.component.MembersPresenter
|
||||
? { ...it, props: { ...it.props, retrieveMembers } }
|
||||
: it
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if viewlet?.$lookup?.descriptor?.component}
|
||||
@ -36,7 +22,7 @@
|
||||
is={viewlet.$lookup.descriptor.component}
|
||||
props={{
|
||||
_class: tracker.class.Milestone,
|
||||
config: updateConfig(viewlet.config),
|
||||
config: viewlet.config,
|
||||
options: viewlet.options,
|
||||
createItemDialog,
|
||||
createItemLabel,
|
||||
|
@ -1,106 +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 contact, { Employee } from '@hcengineering/contact'
|
||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { UsersPopup } from '@hcengineering/contact-resources'
|
||||
import { Milestone } from '@hcengineering/tracker'
|
||||
import { eventToHTMLElement, IconSize, showPopup } from '@hcengineering/ui'
|
||||
import { AttributeModel } from '@hcengineering/view'
|
||||
import { getObjectPresenter } from '@hcengineering/view-resources'
|
||||
import tracker from '../../plugin'
|
||||
import LeadPopup from '../components/LeadPopup.svelte'
|
||||
|
||||
export let value: Employee | null
|
||||
export let size: IconSize = 'x-small'
|
||||
export let object: Milestone
|
||||
export let defaultClass: Ref<Class<Doc>> | undefined = undefined
|
||||
export let isEditable: boolean = true
|
||||
export let shouldShowLabel: boolean = false
|
||||
export let defaultName: IntlString | undefined = undefined
|
||||
|
||||
const client = getClient()
|
||||
|
||||
let presenter: AttributeModel | undefined
|
||||
|
||||
$: if (value || defaultClass) {
|
||||
if (value) {
|
||||
getObjectPresenter(client, value._class, { key: '' }).then((p) => {
|
||||
presenter = p
|
||||
})
|
||||
} else if (defaultClass) {
|
||||
getObjectPresenter(client, defaultClass, { key: '' }).then((p) => {
|
||||
presenter = p
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleLeadChanged = async (result: Employee | null | undefined) => {
|
||||
if (!isEditable || result === undefined) {
|
||||
return
|
||||
}
|
||||
const newLead = result === null ? null : result._id
|
||||
|
||||
await client.update(object, { lead: newLead })
|
||||
}
|
||||
|
||||
const handleLeadEditorOpened = async (event: MouseEvent) => {
|
||||
if (!isEditable) {
|
||||
return
|
||||
}
|
||||
showPopup(
|
||||
UsersPopup,
|
||||
{
|
||||
_class: contact.class.Employee,
|
||||
selected: value?._id,
|
||||
docQuery: {
|
||||
active: true
|
||||
},
|
||||
allowDeselect: true,
|
||||
placeholder: tracker.string.ComponentLeadSearchPlaceholder
|
||||
},
|
||||
eventToHTMLElement(event),
|
||||
handleLeadChanged
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if value && presenter}
|
||||
<svelte:component
|
||||
this={presenter.presenter}
|
||||
{value}
|
||||
{defaultName}
|
||||
avatarSize={size}
|
||||
disabled={false}
|
||||
shouldShowPlaceholder={true}
|
||||
shouldShowName={shouldShowLabel}
|
||||
onEmployeeEdit={handleLeadEditorOpened}
|
||||
tooltipLabels={{ component: LeadPopup, props: { lead: value } }}
|
||||
/>
|
||||
{:else if presenter}
|
||||
<svelte:component
|
||||
this={presenter.presenter}
|
||||
{value}
|
||||
{defaultName}
|
||||
avatarSize={size}
|
||||
disabled={false}
|
||||
shouldShowPlaceholder={true}
|
||||
shouldShowName={shouldShowLabel}
|
||||
onEmployeeEdit={handleLeadEditorOpened}
|
||||
tooltipLabels={{ personLabel: tracker.string.AssignedTo, placeholderLabel: tracker.string.AssignTo }}
|
||||
/>
|
||||
{/if}
|
@ -15,42 +15,26 @@
|
||||
<script lang="ts">
|
||||
import { WithLookup } from '@hcengineering/core'
|
||||
import { Milestone } from '@hcengineering/tracker'
|
||||
import { Icon, getCurrentResolvedLocation, navigate, tooltip } from '@hcengineering/ui'
|
||||
import { Icon } from '@hcengineering/ui'
|
||||
import { DocNavLink } from '@hcengineering/view-resources'
|
||||
import tracker from '../../plugin'
|
||||
|
||||
export let value: WithLookup<Milestone>
|
||||
export let shouldShowAvatar: boolean = true
|
||||
export let onClick: (() => void) | undefined = undefined
|
||||
export let shouldShowAvatar = true
|
||||
export let disabled = false
|
||||
export let inline: boolean = false
|
||||
|
||||
function navigateToMilestone () {
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
if (onClick) {
|
||||
onClick()
|
||||
}
|
||||
|
||||
const loc = getCurrentResolvedLocation()
|
||||
loc.path[4] = 'milestones'
|
||||
loc.path[5] = value._id
|
||||
loc.path.length = 6
|
||||
loc.fragment = undefined
|
||||
navigate(loc)
|
||||
}
|
||||
export let inline = false
|
||||
export let onClick: (() => void) | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="flex-presenter" class:inline-presenter={inline} on:click={navigateToMilestone}>
|
||||
<DocNavLink object={value} {disabled} {inline} {onClick}>
|
||||
<div class="flex-presenter" class:inline-presenter={inline}>
|
||||
{#if !inline && shouldShowAvatar}
|
||||
<div class="icon" use:tooltip={{ label: tracker.string.Milestone }}>
|
||||
<Icon icon={tracker.icon.Milestone} size={'small'} />
|
||||
<div class="icon">
|
||||
<Icon icon={tracker.icon.Milestone} size="small" />
|
||||
</div>
|
||||
{/if}
|
||||
<span title={value.label} class="overflow-label label">
|
||||
{value.label}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</DocNavLink>
|
||||
|
@ -15,58 +15,15 @@
|
||||
<script lang="ts">
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Milestone, Project } from '@hcengineering/tracker'
|
||||
import {
|
||||
closePopup,
|
||||
closeTooltip,
|
||||
getCurrentResolvedLocation,
|
||||
navigate,
|
||||
resolvedLocationStore
|
||||
} from '@hcengineering/ui'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { Project } from '@hcengineering/tracker'
|
||||
import tracker from '../../plugin'
|
||||
import { MilestoneViewMode } from '../../utils'
|
||||
import EditMilestone from './EditMilestone.svelte'
|
||||
import MilestoneBrowser from './MilestoneBrowser.svelte'
|
||||
|
||||
export let currentSpace: Ref<Project>
|
||||
export let label: IntlString = tracker.string.Milestones
|
||||
export let search: string = ''
|
||||
export let mode: MilestoneViewMode = 'all'
|
||||
|
||||
let milestoneId: Ref<Milestone> | undefined
|
||||
let milestone: Milestone | undefined
|
||||
|
||||
onDestroy(
|
||||
resolvedLocationStore.subscribe(async (loc) => {
|
||||
closeTooltip()
|
||||
closePopup()
|
||||
|
||||
milestoneId = loc.path[5] as Ref<Milestone>
|
||||
})
|
||||
)
|
||||
|
||||
const milestoneQuery = createQuery()
|
||||
$: if (milestoneId !== undefined) {
|
||||
milestoneQuery.query(tracker.class.Milestone, { _id: milestoneId }, (result) => {
|
||||
milestone = result.shift()
|
||||
})
|
||||
} else {
|
||||
milestoneQuery.unsubscribe()
|
||||
milestone = undefined
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if milestone}
|
||||
<EditMilestone
|
||||
{milestone}
|
||||
on:milestone={(evt) => {
|
||||
const loc = getCurrentResolvedLocation()
|
||||
loc.path[5] = evt.detail
|
||||
navigate(loc)
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<MilestoneBrowser {label} query={{ space: currentSpace }} {search} {mode} />
|
||||
{/if}
|
||||
<MilestoneBrowser {label} query={{ space: currentSpace }} {search} {mode} />
|
||||
|
@ -16,13 +16,12 @@
|
||||
import { Data, Ref } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { Card, getClient, SpaceSelector } from '@hcengineering/presentation'
|
||||
import { EmployeeBox, UserBoxList } from '@hcengineering/contact-resources'
|
||||
import { Milestone, MilestoneStatus, Project } from '@hcengineering/tracker'
|
||||
import ui, { DatePresenter, EditBox } from '@hcengineering/ui'
|
||||
import { StyledTextArea } from '@hcengineering/text-editor'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import MilestoneStatusSelector from './MilestoneStatusSelector.svelte'
|
||||
import { StyledTextArea } from '@hcengineering/text-editor'
|
||||
|
||||
export let space: Ref<Project>
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -32,11 +31,8 @@
|
||||
label: '' as IntlString,
|
||||
description: '',
|
||||
status: MilestoneStatus.Planned,
|
||||
lead: null,
|
||||
members: [],
|
||||
comments: 0,
|
||||
attachments: 0,
|
||||
capacity: 0,
|
||||
targetDate: Date.now() + 14 * 24 * 60 * 60 * 1000
|
||||
}
|
||||
|
||||
@ -83,22 +79,6 @@
|
||||
kind={'secondary'}
|
||||
size={'large'}
|
||||
/>
|
||||
<EmployeeBox
|
||||
label={tracker.string.MilestoneLead}
|
||||
placeholder={tracker.string.AssignTo}
|
||||
kind={'secondary'}
|
||||
size={'large'}
|
||||
bind:value={object.lead}
|
||||
allowDeselect
|
||||
titleDeselect={tracker.string.Unassigned}
|
||||
showNavigate={false}
|
||||
/>
|
||||
<UserBoxList
|
||||
bind:items={object.members}
|
||||
label={tracker.string.MilestoneMembersSearchPlaceholder}
|
||||
kind={'secondary'}
|
||||
size={'large'}
|
||||
/>
|
||||
<DatePresenter
|
||||
bind:value={object.targetDate}
|
||||
editable
|
||||
|
@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import contact from '@hcengineering/contact'
|
||||
import { Ref, SortingOrder } from '@hcengineering/core'
|
||||
import { ScrumRecord, Milestone, Project } from '@hcengineering/tracker'
|
||||
import { ScrumRecord, Project, Scrum } from '@hcengineering/tracker'
|
||||
import { Button, Icon, IconAdd, Label, showPopup } from '@hcengineering/ui'
|
||||
import { ActionContext, List } from '@hcengineering/view-resources'
|
||||
import tracker from '../../plugin'
|
||||
@ -31,7 +31,7 @@
|
||||
showPopup(NewScrum, { space: currentSpace, targetElement: null }, null)
|
||||
}
|
||||
|
||||
const retrieveMembers = (s: Milestone) => s.members
|
||||
const retrieveMembers = (s: Scrum) => s.members
|
||||
</script>
|
||||
|
||||
<ActionContext
|
||||
|
@ -69,7 +69,7 @@ import RelationsPopup from './components/RelationsPopup.svelte'
|
||||
import SetDueDateActionPopup from './components/SetDueDateActionPopup.svelte'
|
||||
import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.svelte'
|
||||
import MilestoneDatePresenter from './components/milestones/MilestoneDatePresenter.svelte'
|
||||
import MilestoneLeadPresenter from './components/milestones/MilestoneLeadPresenter.svelte'
|
||||
import EditMilestone from './components/milestones/EditMilestone.svelte'
|
||||
import CreateIssueTemplate from './components/templates/CreateIssueTemplate.svelte'
|
||||
import Views from './components/views/Views.svelte'
|
||||
import Statuses from './components/workflow/Statuses.svelte'
|
||||
@ -423,6 +423,7 @@ export default async (): Promise<Resources> => ({
|
||||
CreateIssueTemplate,
|
||||
Milestones,
|
||||
MilestonePresenter,
|
||||
EditMilestone,
|
||||
Scrums,
|
||||
ScrumRecordPanel,
|
||||
MilestoneStatusPresenter,
|
||||
@ -450,7 +451,6 @@ export default async (): Promise<Resources> => ({
|
||||
DeleteComponentPresenter,
|
||||
TimeSpendReportPopup,
|
||||
MilestoneDatePresenter,
|
||||
MilestoneLeadPresenter,
|
||||
NotificationIssuePresenter,
|
||||
MilestoneFilter,
|
||||
PriorityFilterValuePresenter,
|
||||
|
@ -229,11 +229,6 @@ export default mergeIds(trackerId, tracker, {
|
||||
ActiveMilestones: '' as IntlString,
|
||||
ClosedMilestones: '' as IntlString,
|
||||
MilestoneNamePlaceholder: '' as IntlString,
|
||||
MilestoneLead: '' as IntlString,
|
||||
MilestoneLeadTitle: '' as IntlString,
|
||||
MilestoneLeadSearchPlaceholder: '' as IntlString,
|
||||
MilestoneMembersTitle: '' as IntlString,
|
||||
MilestoneMembersSearchPlaceholder: '' as IntlString,
|
||||
|
||||
NewMilestone: '' as IntlString,
|
||||
CreateMilestone: '' as IntlString,
|
||||
@ -277,7 +272,6 @@ export default mergeIds(trackerId, tracker, {
|
||||
|
||||
ChildEstimation: '' as IntlString,
|
||||
ChildReportedTime: '' as IntlString,
|
||||
Capacity: '' as IntlString,
|
||||
CapacityValue: '' as IntlString,
|
||||
AddedReference: '' as IntlString,
|
||||
AddedAsBlocked: '' as IntlString,
|
||||
@ -360,7 +354,7 @@ export default mergeIds(trackerId, tracker, {
|
||||
MilestoneStatusPresenter: '' as AnyComponent,
|
||||
MilestoneTitlePresenter: '' as AnyComponent,
|
||||
MilestoneDatePresenter: '' as AnyComponent,
|
||||
MilestoneLeadPresenter: '' as AnyComponent,
|
||||
EditMilestone: '' as AnyComponent,
|
||||
ReportedTimeEditor: '' as AnyComponent,
|
||||
TimeSpendReport: '' as AnyComponent,
|
||||
EstimationEditor: '' as AnyComponent,
|
||||
|
@ -124,18 +124,12 @@ export interface Milestone extends Doc {
|
||||
|
||||
status: MilestoneStatus
|
||||
|
||||
lead: Ref<Employee> | null
|
||||
members: Ref<Employee>[]
|
||||
|
||||
space: Ref<Project>
|
||||
|
||||
comments: number
|
||||
attachments?: number
|
||||
|
||||
targetDate: Timestamp
|
||||
|
||||
// Capacity in man days.
|
||||
capacity: number
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user