mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-27 12:04:56 +02:00
UBERF-9483 Task type improvements (#8015)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
-31
@@ -1,31 +0,0 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { ButtonIcon, IconAdd, IconFolder, Label } from '@hcengineering/ui'
|
||||
import { ProjectType, ProjectTypeDescriptor } from '@hcengineering/task'
|
||||
import task from '../../plugin'
|
||||
|
||||
export let type: ProjectType | undefined
|
||||
export let descriptor: ProjectTypeDescriptor | undefined
|
||||
export let disabled: boolean = true
|
||||
</script>
|
||||
|
||||
{#if descriptor !== undefined}
|
||||
<div class="hulyTableAttr-header font-medium-12">
|
||||
<IconFolder size="small" />
|
||||
<span><Label label={task.string.Collections} /></span>
|
||||
<ButtonIcon kind="primary" icon={IconAdd} size="small" dataId={'btnAdd'} {disabled} on:click={() => {}} />
|
||||
</div>
|
||||
{/if}
|
||||
@@ -1,10 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { Class, Doc, Ref, toIdMap } from '@hcengineering/core'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import task, { ProjectType, TaskType } from '@hcengineering/task'
|
||||
import { ButtonKind, ButtonSize, DropdownLabels } from '@hcengineering/ui'
|
||||
import { ButtonKind, ButtonSize, DropdownLabelsIntl, type DropdownIntlItem } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||
import { selectedTaskTypeStore, taskTypeStore } from '../..'
|
||||
import TaskTypeListPresenter from './TaskTypeListPresenter.svelte'
|
||||
import TaskTypeIcon from './TaskTypeIcon.svelte'
|
||||
|
||||
export let value: Ref<TaskType> | undefined
|
||||
export let projectType: Ref<ProjectType> | undefined
|
||||
@@ -28,13 +31,18 @@
|
||||
(taskTypeDescriptors.get(it.descriptor)?.allowCreate ?? false) &&
|
||||
(baseClass === undefined || client.getHierarchy().isDerived(it.targetClass, baseClass))
|
||||
)
|
||||
.map((it) => ({ id: it._id, label: it.name }))
|
||||
.map((it) => ({
|
||||
id: it._id,
|
||||
label: getEmbeddedLabel(it.name),
|
||||
icon: TaskTypeIcon,
|
||||
iconProps: { value: it }
|
||||
})) as DropdownIntlItem[]
|
||||
|
||||
$: if (
|
||||
(value === undefined && items.length > 0) ||
|
||||
(items.length > 0 && items.find((it) => it.id === value) === undefined)
|
||||
) {
|
||||
value = items[0].id
|
||||
value = items[0].id as Ref<TaskType>
|
||||
change()
|
||||
}
|
||||
|
||||
@@ -50,16 +58,17 @@
|
||||
</script>
|
||||
|
||||
{#if projectType !== undefined && (items.length > 1 || showAlways)}
|
||||
<DropdownLabels
|
||||
<DropdownLabelsIntl
|
||||
{focusIndex}
|
||||
{kind}
|
||||
{size}
|
||||
{items}
|
||||
{justify}
|
||||
{width}
|
||||
icon={TaskTypeIcon}
|
||||
iconProps={value !== undefined ? { value: $taskTypeStore.get(value) } : {}}
|
||||
dataId={'btnSelectTaskType'}
|
||||
bind:selected={value}
|
||||
enableSearch={false}
|
||||
on:selected={change}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -14,28 +14,31 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AttributeEditor, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import task, { ProjectType, TaskType, calculateStatuses, findStatusAttr } from '@hcengineering/task'
|
||||
import { Ref, SortingOrder, Status } from '@hcengineering/core'
|
||||
import { Asset, getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import {
|
||||
Label,
|
||||
showPopup,
|
||||
ButtonIcon,
|
||||
ModernButton,
|
||||
IconSquareExpand,
|
||||
IconAdd,
|
||||
Icon,
|
||||
Scroller
|
||||
} from '@hcengineering/ui'
|
||||
import { IconPicker, statusStore } from '@hcengineering/view-resources'
|
||||
import { Asset, getEmbeddedLabel, getResource } from '@hcengineering/platform'
|
||||
import { AttributeEditor, MessageBox, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { ClassAttributes, settingsStore } from '@hcengineering/setting-resources'
|
||||
import task, { ProjectType, TaskType, calculateStatuses, findStatusAttr } from '@hcengineering/task'
|
||||
import {
|
||||
ButtonIcon,
|
||||
Icon,
|
||||
IconAdd,
|
||||
IconDelete,
|
||||
IconSquareExpand,
|
||||
Label,
|
||||
ModernButton,
|
||||
Scroller,
|
||||
getCurrentLocation,
|
||||
navigate,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
import { IconPicker, deleteObjects, statusStore } from '@hcengineering/view-resources'
|
||||
import { taskTypeStore } from '../..'
|
||||
import plugin from '../../plugin'
|
||||
import StatesProjectEditor from '../state/StatesProjectEditor.svelte'
|
||||
import TaskTypeKindEditor from '../taskTypes/TaskTypeKindEditor.svelte'
|
||||
import TaskTypeRefEditor from '../taskTypes/TaskTypeRefEditor.svelte'
|
||||
import TaskTypeIcon from './TaskTypeIcon.svelte'
|
||||
import plugin from '../../plugin'
|
||||
|
||||
export let spaceType: ProjectType
|
||||
export let objectId: Ref<TaskType>
|
||||
@@ -65,13 +68,15 @@
|
||||
$: states = (taskType?.statuses.map((p) => $statusStore.byId.get(p)).filter((p) => p !== undefined) as Status[]) ?? []
|
||||
|
||||
let tasksCounter: number = 0
|
||||
let loading: boolean = true
|
||||
const tasksCounterQuery = createQuery()
|
||||
$: if (taskType !== undefined) {
|
||||
tasksCounterQuery.query(
|
||||
loading = tasksCounterQuery.query(
|
||||
task.class.Task,
|
||||
{ kind: taskType._id },
|
||||
(res) => {
|
||||
tasksCounter = res.total
|
||||
loading = false
|
||||
},
|
||||
{
|
||||
total: true,
|
||||
@@ -87,6 +92,7 @@
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
// TODO: Be aware icon equal to descriptor one will not be shown in lists.
|
||||
const icons: Asset[] = [descriptor[0].icon]
|
||||
|
||||
showPopup(
|
||||
@@ -125,6 +131,41 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: canDelete = !loading && tasksCounter === 0
|
||||
|
||||
async function handleDelete (): Promise<void> {
|
||||
if (!canDelete || readonly || taskType == null) {
|
||||
return
|
||||
}
|
||||
|
||||
showPopup(MessageBox, {
|
||||
label: plugin.string.Delete,
|
||||
message: plugin.string.Delete,
|
||||
action: async () => {
|
||||
if (taskType == null) {
|
||||
return
|
||||
}
|
||||
|
||||
await deleteObjects(client, [taskType])
|
||||
|
||||
const loc = getCurrentLocation()
|
||||
loc.path.length -= 2
|
||||
navigate(loc)
|
||||
}
|
||||
})
|
||||
}
|
||||
async function showIssuesOfTaskType (): Promise<void> {
|
||||
if (taskType == null) return
|
||||
const descriptor = client
|
||||
.getModel()
|
||||
.findAllSync(task.class.TaskTypeDescriptor, { _id: taskType?.descriptor })
|
||||
.shift()
|
||||
if (descriptor?.openTasks !== undefined) {
|
||||
const f = await getResource(descriptor.openTasks)
|
||||
await f?.(taskType)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if taskType !== undefined}
|
||||
@@ -157,15 +198,29 @@
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<ModernButton
|
||||
icon={IconSquareExpand}
|
||||
label={plugin.string.CountTasks}
|
||||
labelParams={{ count: tasksCounter }}
|
||||
disabled={tasksCounter === 0}
|
||||
kind={'tertiary'}
|
||||
size={'medium'}
|
||||
hasMenu
|
||||
/>
|
||||
<div class="flex-row">
|
||||
<ModernButton
|
||||
icon={IconSquareExpand}
|
||||
label={plugin.string.CountTasks}
|
||||
labelParams={{ count: tasksCounter }}
|
||||
disabled={tasksCounter === 0}
|
||||
kind={'tertiary'}
|
||||
size={'medium'}
|
||||
hasMenu
|
||||
on:click={() => {
|
||||
showIssuesOfTaskType()
|
||||
}}
|
||||
/>
|
||||
{#if canDelete}
|
||||
<ButtonIcon
|
||||
icon={IconDelete}
|
||||
size="small"
|
||||
kind="secondary"
|
||||
disabled={readonly}
|
||||
on:click={handleDelete}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="name" class:editable={!readonly}>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
// Copyright © 2025 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 type { TaskType } from '@hcengineering/task'
|
||||
import view from '@hcengineering/view'
|
||||
import { taskTypeStore } from '../../'
|
||||
import TaskTypeIcon from './TaskTypeIcon.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import task from '@hcengineering/task'
|
||||
|
||||
export let value: TaskType | Ref<TaskType> | undefined
|
||||
|
||||
$: _value = typeof value === 'string' ? $taskTypeStore.get(value) : value
|
||||
$: descriptor = getClient().getModel().findAllSync(task.class.TaskTypeDescriptor, { _id: _value?.descriptor }).shift()
|
||||
$: visible = !(_value?.icon === descriptor?.icon)
|
||||
</script>
|
||||
|
||||
{#if _value !== undefined && visible}
|
||||
<span class="label flex-row-center gap-1 ml-3">
|
||||
<TaskTypeIcon value={_value} size={'small'} />
|
||||
</span>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user