Allow to specify project to sprints (#2275)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2022-09-22 00:32:48 +07:00
committed by GitHub
parent 5b6ef778f3
commit 40fd5a4532
174 changed files with 1122 additions and 1306 deletions
@@ -18,7 +18,7 @@
import login from '@hcengineering/login'
import { setMetadata } from '@hcengineering/platform'
import { Avatar, createQuery } from '@hcengineering/presentation'
import setting, { SettingsCategory, settingId } from '@hcengineering/setting'
import setting, { settingId, SettingsCategory } from '@hcengineering/setting'
import {
closePopup,
fetchMetadataLocalStorage,
@@ -380,8 +380,12 @@
}}
/>
<EstimationEditor kind={'no-border'} size={'small'} value={object} />
<ProjectSelector value={object.project} onProjectIdChange={handleProjectIdChanged} />
<SprintSelector value={object.sprint} onSprintIdChange={handleSprintIdChanged} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<SprintSelector
value={object.sprint}
onChange={handleSprintIdChanged}
useProject={object.project ?? undefined}
/>
{#if object.dueDate !== null}
<DatePresenter bind:value={object.dueDate} editable />
{/if}
@@ -24,7 +24,7 @@
export let value: Ref<Project> | null | undefined
export let shouldShowLabel: boolean = true
export let isEditable: boolean = true
export let onProjectIdChange: ((newProjectId: Ref<Project> | undefined) => void) | undefined = undefined
export let onChange: ((newProjectId: Ref<Project> | undefined) => void) | undefined = undefined
export let popupPlaceholder: IntlString = tracker.string.AddToProject
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
@@ -87,7 +87,7 @@
SelectPopup,
{ value: projectsInfo, placeholder: popupPlaceholder, searchable: true },
eventToHTMLElement(event),
onProjectIdChange
onChange
)
}
</script>
@@ -15,17 +15,19 @@
<script lang="ts">
import contact, { Employee } from '@hcengineering/contact'
import { Class, Doc, Ref } from '@hcengineering/core'
import { Project } from '@hcengineering/tracker'
import { Project, Sprint } from '@hcengineering/tracker'
import { UsersPopup, getClient } from '@hcengineering/presentation'
import { AttributeModel } from '@hcengineering/view'
import { eventToHTMLElement, showPopup } from '@hcengineering/ui'
import { eventToHTMLElement, IconSize, showPopup } from '@hcengineering/ui'
import { getObjectPresenter } from '@hcengineering/view-resources'
import { IntlString } from '@hcengineering/platform'
import tracker from '../../plugin'
import LeadPopup from './LeadPopup.svelte'
export let value: Employee | null
export let projectId: Ref<Project>
export let _class: Ref<Class<Project | Sprint>>
export let size: IconSize = 'x-small'
export let parentId: Ref<Project>
export let defaultClass: Ref<Class<Doc>> | undefined = undefined
export let isEditable: boolean = true
export let shouldShowLabel: boolean = false
@@ -52,15 +54,15 @@
return
}
const currentProject = await client.findOne(tracker.class.Project, { _id: projectId })
const currentParent = await client.findOne(_class, { _id: parentId })
if (currentProject === undefined) {
if (currentParent === undefined) {
return
}
const newLead = result === null ? null : result._id
await client.update(currentProject, { lead: newLead })
await client.update(currentParent, { lead: newLead })
}
const handleLeadEditorOpened = async (event: MouseEvent) => {
@@ -89,7 +91,7 @@
this={presenter.presenter}
{value}
{defaultName}
avatarSize={'tiny'}
avatarSize={size}
isInteractive={true}
shouldShowPlaceholder={true}
shouldShowName={shouldShowLabel}
@@ -101,7 +103,7 @@
this={presenter.presenter}
{value}
{defaultName}
avatarSize={'tiny'}
avatarSize={size}
isInteractive={true}
shouldShowPlaceholder={true}
shouldShowName={shouldShowLabel}
@@ -157,7 +157,7 @@
{
key: '$lookup.lead',
presenter: tracker.component.LeadPresenter,
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
props: { _class: tracker.class.Project, defaultClass: contact.class.Employee, shouldShowLabel: false }
},
{ key: '', presenter: tracker.component.ProjectMembersPresenter, props: { kind: 'link' } },
{ key: '', presenter: tracker.component.TargetDatePresenter },
@@ -72,7 +72,7 @@
{onlyIcon}
{enlargedText}
value={value.project}
onProjectIdChange={handleProjectIdChanged}
onChange={handleProjectIdChanged}
/>
</div>
{/if}
@@ -14,16 +14,17 @@
-->
<script lang="ts">
import contact from '@hcengineering/contact'
import { DocumentQuery, FindOptions, SortingOrder } from '@hcengineering/core'
import { DocumentQuery, FindOptions, SortingOrder, WithLookup } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
import { Sprint } from '@hcengineering/tracker'
import { Button, Icon, IconAdd, Label, showPopup } from '@hcengineering/ui'
import { Button, defaultSP, Icon, IconAdd, Label, Scroller, showPopup } from '@hcengineering/ui'
import tracker from '../../plugin'
import { getIncludedSprintStatuses, sprintTitleMap, SprintViewMode } from '../../utils'
import NewSprint from './NewSprint.svelte'
import SprintDatePresenter from './SprintDatePresenter.svelte'
import SprintListBrowser from './SprintListBrowser.svelte'
import SprintProjectEditor from './SprintProjectEditor.svelte'
export let label: IntlString
export let query: DocumentQuery<Sprint> = {}
@@ -36,10 +37,13 @@
const sprintOptions: FindOptions<Sprint> = {
sort: { startDate: SortingOrder.Descending },
limit: ENTRIES_LIMIT,
lookup: { lead: contact.class.Employee }
lookup: {
lead: contact.class.Employee,
project: tracker.class.Project
}
}
let resultSprints: Sprint[] = []
let resultSprints: WithLookup<Sprint>[] = []
$: includedSprintStatuses = getIncludedSprintStatuses(mode)
$: title = sprintTitleMap[mode]
@@ -75,57 +79,56 @@
}
</script>
<div>
<div class="fs-title flex-between header">
<div class="fs-title flex-between header">
<div class="flex-center">
<Label {label} />
<div class="projectTitle">
› <Label label={title} />
</div>
</div>
<Button size="small" icon={IconAdd} label={tracker.string.Sprint} kind="secondary" on:click={showCreateDialog} />
</div>
<div class="itemsContainer">
<div class="flex-center">
<div class="flex-center">
<Label {label} />
<div class="projectTitle">
› <Label label={title} />
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-right"
selected={mode === 'all'}
label={tracker.string.AllSprints}
on:click={() => handleViewModeChanged('all')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'planned'}
label={tracker.string.PlannedSprints}
on:click={() => handleViewModeChanged('planned')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'active'}
label={tracker.string.ActiveSprints}
on:click={() => handleViewModeChanged('active')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-left"
selected={mode === 'closed'}
label={tracker.string.ClosedSprints}
on:click={() => handleViewModeChanged('closed')}
/>
</div>
</div>
<Button size="small" icon={IconAdd} label={tracker.string.Sprint} kind="secondary" on:click={showCreateDialog} />
</div>
<div class="itemsContainer">
<div class="flex-center">
<div class="flex-center">
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-right"
selected={mode === 'all'}
label={tracker.string.AllSprints}
on:click={() => handleViewModeChanged('all')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'planned'}
label={tracker.string.PlannedSprints}
on:click={() => handleViewModeChanged('planned')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'active'}
label={tracker.string.ActiveSprints}
on:click={() => handleViewModeChanged('active')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-left"
selected={mode === 'closed'}
label={tracker.string.ClosedSprints}
on:click={() => handleViewModeChanged('closed')}
/>
</div>
</div>
<!-- <div class="ml-3 filterButton">
<!-- <div class="ml-3 filterButton">
<Button
size="small"
icon={IconAdd}
@@ -135,8 +138,8 @@
on:click={() => {}}
/>
</div> -->
</div>
<!-- <div class="flex-center">
</div>
<!-- <div class="flex-center">
<div class="flex-center">
<div class="buttonWrapper">
<Button selected size="small" shape="rectangle-right" icon={tracker.icon.ProjectsList} />
@@ -149,23 +152,32 @@
<Button size="small" icon={IconOptions} />
</div>
</div> -->
</div>
<SprintListBrowser
_class={tracker.class.Sprint}
itemsConfig={[
{ key: '', presenter: Icon, props: { icon: tracker.icon.Sprint, size: 'small' } },
{ key: '', presenter: tracker.component.SprintPresenter, props: { kind: 'list' } },
{
key: '$lookup.lead',
presenter: tracker.component.LeadPresenter,
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
},
{ key: '', presenter: SprintDatePresenter, props: { field: 'startDate' } },
{ key: '', presenter: SprintDatePresenter, props: { field: 'targetDate' } },
{ key: '', presenter: tracker.component.SprintStatusPresenter }
]}
sprints={resultSprints}
/>
</div>
<div class="w-full h-full clear-mins">
<Scroller fade={defaultSP}>
<SprintListBrowser
_class={tracker.class.Sprint}
itemsConfig={[
{ key: '', presenter: Icon, props: { icon: tracker.icon.Sprint, size: 'small' } },
{ key: '', presenter: tracker.component.SprintPresenter, props: { kind: 'list' } },
{ key: '', presenter: SprintProjectEditor, props: { kind: 'list' } },
{
key: '$lookup.lead',
presenter: tracker.component.LeadPresenter,
props: {
_class: tracker.class.Sprint,
defaultClass: contact.class.Employee,
shouldShowLabel: false,
size: 'x-small'
}
},
{ key: '', presenter: SprintDatePresenter, props: { field: 'startDate' } },
{ key: '', presenter: SprintDatePresenter, props: { field: 'targetDate' } },
{ key: '', presenter: tracker.component.SprintStatusPresenter }
]}
sprints={resultSprints}
/>
</Scroller>
</div>
<style lang="scss">
@@ -13,10 +13,10 @@
// limitations under the License.
-->
<script lang="ts">
import { Ref } from '@hcengineering/core'
import { Ref, WithLookup } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Issue, Sprint } from '@hcengineering/tracker'
import { Issue, IssueStatus, Sprint } from '@hcengineering/tracker'
import { ButtonKind, ButtonShape, ButtonSize, Label, tooltip } from '@hcengineering/ui'
import DatePresenter from '@hcengineering/ui/src/components/calendar/DatePresenter.svelte'
import { activeSprint } from '../../issues'
@@ -61,15 +61,41 @@
$: ids = new Set(issues?.map((it) => it._id) ?? [])
$: noParents = issues?.filter((it) => !ids.has(it.attachedTo as Ref<Issue>))
const statuses = createQuery()
let issueStatuses: Map<Ref<IssueStatus>, WithLookup<IssueStatus>> = new Map()
$: if (noParents !== undefined) {
statuses.query(tracker.class.IssueStatus, { _id: { $in: Array.from(noParents.map((it) => it.status)) } }, (res) => {
issueStatuses = new Map(res.map((it) => [it._id, it]))
})
} else {
statuses.unsubscribe()
}
$: totalEstimation = (noParents ?? [{ estimation: 0, childInfo: [] } as unknown as Issue])
.map((it) => {
const cat = issueStatuses.get(it.status)?.category
let retEst = it.estimation
if (it.childInfo?.length > 0) {
const cEstimation = it.childInfo.map((ct) => ct.estimation).reduce((a, b) => a + b, 0)
const cReported = it.childInfo.map((ct) => ct.reportedTime).reduce((a, b) => a + b, 0)
if (cEstimation !== 0) {
return cEstimation
retEst = cEstimation
if (cat === tracker.issueStatusCategory.Completed || cat === tracker.issueStatusCategory.Canceled) {
if (cReported < cEstimation) {
retEst = cReported
}
}
}
} else {
if (cat === tracker.issueStatusCategory.Completed || cat === tracker.issueStatusCategory.Canceled) {
if (it.reportedTime < it.estimation) {
return it.reportedTime
}
}
}
return it.estimation
return retEst
})
.reduce((it, cur) => {
return it + cur
@@ -79,7 +105,7 @@
if (it.childInfo?.length > 0) {
const cReported = it.childInfo.map((ct) => ct.reportedTime).reduce((a, b) => a + b, 0)
if (cReported !== 0) {
return cReported
return cReported + it.reportedTime
}
}
return it.reportedTime
@@ -114,7 +140,7 @@
{onlyIcon}
{enlargedText}
value={value.sprint}
onSprintIdChange={handleSprintIdChanged}
onChange={handleSprintIdChanged}
/>
</div>
{/if}
@@ -14,20 +14,21 @@
-->
<script lang="ts">
import contact from '@hcengineering/contact'
import { Class, Doc, FindOptions, getObjectValue, Ref } from '@hcengineering/core'
import { Class, Doc, FindOptions, getObjectValue, Ref, WithLookup } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { Issue, Sprint } from '@hcengineering/tracker'
import { CheckBox, Spinner, tooltip } from '@hcengineering/ui'
import { Issue, Project, Sprint } from '@hcengineering/tracker'
import { CheckBox, ExpandCollapse, Spinner, tooltip } from '@hcengineering/ui'
import { BuildModelKey } from '@hcengineering/view'
import { buildModel, LoadingProps } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import tracker from '../../plugin'
import SprintProjectEditor from './SprintProjectEditor.svelte'
export let _class: Ref<Class<Doc>>
export let itemsConfig: (BuildModelKey | string)[]
export let selectedObjectIds: Doc[] = []
export let selectedRowIndex: number | undefined = undefined
export let sprints: Sprint[] | undefined = undefined
export let sprints: WithLookup<Sprint>[] | undefined = undefined
export let loadingProps: LoadingProps | undefined = undefined
const dispatch = createEventDispatcher()
@@ -46,6 +47,12 @@
$: selectedObjectIdsSet = new Set<Ref<Doc>>(selectedObjectIds.map((it) => it._id))
$: objectRefs.length = sprints?.length ?? 0
$: byProject = sprints?.reduce((s, cur) => {
const pid = cur.project ?? ''
s.set(pid, [...(s.get(pid) ?? []), cur])
return s
}, new Map<Ref<Project> | '', WithLookup<Sprint>[]>())
export const onObjectChecked = (docs: Doc[], value: boolean) => {
dispatch('check', { docs, value })
}
@@ -90,66 +97,97 @@
return props.length
}
const isCollapsedMap: Record<any, boolean> = {}
$: {
const exkeys = new Set(Object.keys(isCollapsedMap))
for (const c of byProject?.keys() ?? []) {
if (!exkeys.delete(c)) {
isCollapsedMap[c] = false
}
}
for (const k of exkeys) {
delete isCollapsedMap[k]
}
}
const handleCollapseCategory = (category: any) => (isCollapsedMap[category] = !isCollapsedMap[category])
</script>
{#await buildModel({ client, _class, keys: itemsConfig, lookup: options.lookup }) then itemModels}
<div class="listRoot">
{#if sprints}
{#each sprints as docObject (docObject._id)}
<div
bind:this={objectRefs[sprints.findIndex((x) => x === docObject)]}
class="listGrid"
class:mListGridChecked={selectedObjectIdsSet.has(docObject._id)}
class:mListGridFixed={selectedRowIndex === sprints.findIndex((x) => x === docObject)}
class:mListGridSelected={selectedRowIndex === sprints.findIndex((x) => x === docObject)}
on:focus={() => {}}
on:mouseover={() => handleRowFocused(docObject)}
>
<div class="contentWrapper">
{#each itemModels as attributeModel, attributeModelIndex}
{#if attributeModelIndex === 0}
<div class="gridElement">
<div
class="eListGridCheckBox"
use:tooltip={{ direction: 'bottom', label: tracker.string.SelectIssue }}
>
<CheckBox
checked={selectedObjectIdsSet.has(docObject._id)}
on:value={(event) => {
onObjectChecked([docObject], event.detail)
}}
/>
</div>
<div class="iconPresenter">
<svelte:component
this={attributeModel.presenter}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
{...attributeModel.props}
/>
</div>
</div>
{:else if attributeModelIndex === 1}
<div class="projectPresenter flex-grow">
<svelte:component
this={attributeModel.presenter}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
{...attributeModel.props}
/>
</div>
<div class="filler" />
{:else}
<div class="gridElement">
<svelte:component
this={attributeModel.presenter}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
projectId={docObject._id}
{...attributeModel.props}
/>
</div>
{/if}
{/each}
{#each Array.from(byProject?.entries() ?? []) as e}
<div class="flex-between categoryHeader row" on:click={() => handleCollapseCategory(e[0])}>
<div class="flex-row-center gap-2 clear-mins">
<SprintProjectEditor
isEditable={false}
value={e[1][0]}
enlargedText={true}
kind={'list-header'}
shouldShowPlaceholder={false}
/>
</div>
</div>
<ExpandCollapse isExpanded={!isCollapsedMap[e[0]]} duration={400}>
{#each e[1] as docObject (docObject._id)}
<div
bind:this={objectRefs[sprints.findIndex((x) => x === docObject)]}
class="listGrid"
class:mListGridChecked={selectedObjectIdsSet.has(docObject._id)}
class:mListGridFixed={selectedRowIndex === sprints.findIndex((x) => x === docObject)}
class:mListGridSelected={selectedRowIndex === sprints.findIndex((x) => x === docObject)}
on:focus={() => {}}
on:mouseover={() => handleRowFocused(docObject)}
>
<div class="contentWrapper">
{#each itemModels as attributeModel, attributeModelIndex}
{#if attributeModelIndex === 0}
<div class="gridElement">
<div
class="eListGridCheckBox"
use:tooltip={{ direction: 'bottom', label: tracker.string.SelectIssue }}
>
<CheckBox
checked={selectedObjectIdsSet.has(docObject._id)}
on:value={(event) => {
onObjectChecked([docObject], event.detail)
}}
/>
</div>
<div class="iconPresenter">
<svelte:component
this={attributeModel.presenter}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
{...attributeModel.props}
/>
</div>
</div>
{:else if attributeModelIndex === 1}
<div class="projectPresenter flex-grow">
<svelte:component
this={attributeModel.presenter}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
{...attributeModel.props}
/>
</div>
<div class="filler" />
{:else}
<div class="gridElement">
<svelte:component
this={attributeModel.presenter}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
projectId={docObject._id}
{...attributeModel.props}
/>
</div>
{/if}
{/each}
</div>
</div>
{/each}
</ExpandCollapse>
{/each}
{:else if loadingProps !== undefined}
{#each Array(getLoadingElementsLength(loadingProps, options)) as _, rowIndex}
@@ -173,6 +211,17 @@
width: 100%;
}
.categoryHeader {
position: sticky;
top: 0;
padding: 0 1.5rem 0 2.25rem;
height: 3rem;
min-height: 3rem;
min-width: 0;
background-color: var(--accent-bg-color);
z-index: 5;
}
.contentWrapper {
display: flex;
align-items: center;
@@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import type { Class, Doc, Ref } from '@hcengineering/core'
import type { Class, Doc, Ref, WithLookup } from '@hcengineering/core'
import { Sprint } from '@hcengineering/tracker'
import { BuildModelKey } from '@hcengineering/view'
import {
@@ -30,7 +30,7 @@
export let _class: Ref<Class<Doc>>
export let itemsConfig: (BuildModelKey | string)[]
export let loadingProps: LoadingProps | undefined = undefined
export let sprints: Sprint[] = []
export let sprints: WithLookup<Sprint>[] = []
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
if (dir === 'vertical') {
@@ -0,0 +1,70 @@
<!--
// 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 { Ref } from '@hcengineering/core'
import { Sprint, Project } from '@hcengineering/tracker'
import { getClient } from '@hcengineering/presentation'
import { ButtonKind, ButtonShape, ButtonSize, tooltip } from '@hcengineering/ui'
import { IntlString } from '@hcengineering/platform'
import tracker from '../../plugin'
import ProjectSelector from '../ProjectSelector.svelte'
import { activeProject } from '../../issues'
export let value: Sprint
export let isEditable: boolean = true
export let shouldShowLabel: boolean = true
export let popupPlaceholder: IntlString = tracker.string.MoveToProject
export let shouldShowPlaceholder = true
export let kind: ButtonKind = 'link'
export let size: ButtonSize = 'large'
export let shape: ButtonShape = undefined
export let justify: 'left' | 'center' = 'left'
export let width: string | undefined = '100%'
export let onlyIcon: boolean = false
export let groupBy: string | undefined = undefined
export let enlargedText = false
const client = getClient()
const handleProjectIdChanged = async (newProjectId: Ref<Project> | null | undefined) => {
if (!isEditable || newProjectId === undefined || value.project === newProjectId) {
return
}
await client.update(value, { project: newProjectId ?? undefined })
}
</script>
{#if (value.project && value.project !== $activeProject && groupBy !== 'project') || shouldShowPlaceholder}
<div
class="clear-mins"
use:tooltip={{ label: value.project ? tracker.string.MoveToProject : tracker.string.AddToProject }}
>
<ProjectSelector
{kind}
{size}
{shape}
{width}
{justify}
{isEditable}
{shouldShowLabel}
{popupPlaceholder}
{onlyIcon}
{enlargedText}
value={value.project}
onChange={handleProjectIdChanged}
/>
</div>
{/if}
@@ -16,7 +16,7 @@
import { Ref, SortingOrder } from '@hcengineering/core'
import { getEmbeddedLabel, IntlString, translate } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
import { Sprint } from '@hcengineering/tracker'
import { Project, Sprint } from '@hcengineering/tracker'
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
import { Button, ButtonShape, eventToHTMLElement, SelectPopup, showPopup, Label } from '@hcengineering/ui'
import tracker from '../../plugin'
@@ -25,7 +25,7 @@
export let value: Ref<Sprint> | null | undefined
export let shouldShowLabel: boolean = true
export let isEditable: boolean = true
export let onSprintIdChange: ((newSprintId: Ref<Sprint> | undefined) => void) | undefined = undefined
export let onChange: ((newSprintId: Ref<Sprint> | undefined) => void) | undefined = undefined
export let popupPlaceholder: IntlString = tracker.string.AddToSprint
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
@@ -35,6 +35,8 @@
export let onlyIcon: boolean = false
export let enlargedText = false
export let useProject: Ref<Project> | undefined = undefined
let selectedSprint: Sprint | undefined
let defaultSprintLabel = ''
@@ -42,7 +44,7 @@
let rawSprints: Sprint[] = []
query.query(
tracker.class.Sprint,
{},
useProject ? { project: useProject } : {},
(res) => {
rawSprints = res
},
@@ -87,7 +89,7 @@
SelectPopup,
{ value: sprintInfo, placeholder: popupPlaceholder, searchable: true },
eventToHTMLElement(event),
onSprintIdChange
onChange
)
}
</script>