mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
UBERF-5348: Fix new status creation (#4567)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
0d884fa93d
commit
6e67c57035
@ -13,12 +13,12 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher, ComponentType } from 'svelte'
|
|
||||||
import type { Asset, IntlString } from '@hcengineering/platform'
|
import type { Asset, IntlString } from '@hcengineering/platform'
|
||||||
import { deepEqual } from 'fast-equals'
|
import { deepEqual } from 'fast-equals'
|
||||||
|
import { ComponentType, createEventDispatcher } from 'svelte'
|
||||||
|
import { closePopup, showPopup } from '..'
|
||||||
import { AnySvelteComponent, DropdownIntlItem } from '../types'
|
import { AnySvelteComponent, DropdownIntlItem } from '../types'
|
||||||
import ButtonBase from './ButtonBase.svelte'
|
import ButtonBase from './ButtonBase.svelte'
|
||||||
import { showPopup, closePopup, eventToHTMLElement } from '..'
|
|
||||||
import ModernPopup from './ModernPopup.svelte'
|
import ModernPopup from './ModernPopup.svelte'
|
||||||
|
|
||||||
export let title: string | undefined = undefined
|
export let title: string | undefined = undefined
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
import plugin from '../plugin'
|
import plugin from '../plugin'
|
||||||
|
|
||||||
export let embedded = false
|
export let embedded = false
|
||||||
|
export let selected: string | undefined
|
||||||
|
|
||||||
interface Category {
|
interface Category {
|
||||||
id: string
|
id: string
|
||||||
@ -179,7 +180,9 @@
|
|||||||
{#if emoji !== undefined}
|
{#if emoji !== undefined}
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div class="element" on:click={() => dispatch('close', emoji)}>{emoji}</div>
|
<div class="element" class:selected={emoji === selected} on:click={() => dispatch('close', emoji)}>
|
||||||
|
{emoji}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@ -250,6 +253,7 @@
|
|||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
background-color: var(--theme-popup-header);
|
background-color: var(--theme-popup-header);
|
||||||
|
border: 1px solid var(--theme-popup-divider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -13,31 +13,30 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Asset, Metadata, getEmbeddedLabel } from '@hcengineering/platform'
|
import core, { Attribute, Class, Ref, Status, StatusCategory } from '@hcengineering/core'
|
||||||
import { Attribute, Class, Ref, Status, StatusCategory } from '@hcengineering/core'
|
import { Asset, getEmbeddedLabel } from '@hcengineering/platform'
|
||||||
import presentation, { getClient } from '@hcengineering/presentation'
|
import presentation, { getClient } from '@hcengineering/presentation'
|
||||||
|
import { clearSettingsStore } from '@hcengineering/setting-resources'
|
||||||
import { ProjectType, TaskType, calculateStatuses, createState } from '@hcengineering/task'
|
import { ProjectType, TaskType, calculateStatuses, createState } from '@hcengineering/task'
|
||||||
import {
|
import {
|
||||||
ModernEditbox,
|
ButtonIcon,
|
||||||
getColorNumberByText,
|
|
||||||
Modal,
|
|
||||||
Label,
|
|
||||||
ButtonMenu,
|
ButtonMenu,
|
||||||
|
EmojiPopup,
|
||||||
|
IconCopy,
|
||||||
|
IconDelete,
|
||||||
IconSettings,
|
IconSettings,
|
||||||
|
IconWithEmoji,
|
||||||
|
Label,
|
||||||
|
Modal,
|
||||||
|
ModernEditbox,
|
||||||
TextArea,
|
TextArea,
|
||||||
getPlatformColorDef,
|
getPlatformColorDef,
|
||||||
themeStore,
|
themeStore
|
||||||
EmojiPopup,
|
|
||||||
ButtonIcon,
|
|
||||||
IconDelete,
|
|
||||||
IconCopy
|
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { statusStore, ColorsPopup } from '@hcengineering/view-resources'
|
import { ColorsPopup, statusStore } from '@hcengineering/view-resources'
|
||||||
import view from '@hcengineering/view-resources/src/plugin'
|
import view from '@hcengineering/view-resources/src/plugin'
|
||||||
import { clearSettingsStore } from '@hcengineering/setting-resources'
|
|
||||||
import task from '../plugin'
|
|
||||||
import { taskTypeStore } from '..'
|
import { taskTypeStore } from '..'
|
||||||
import IconLink from './icons/Link.svelte'
|
import task from '../plugin'
|
||||||
|
|
||||||
export let status: Status | undefined = undefined
|
export let status: Status | undefined = undefined
|
||||||
export let _class: Ref<Class<Status>> | undefined = status?._class
|
export let _class: Ref<Class<Status>> | undefined = status?._class
|
||||||
@ -49,13 +48,19 @@
|
|||||||
export let color: number | undefined = undefined
|
export let color: number | undefined = undefined
|
||||||
export let icons: Asset[]
|
export let icons: Asset[]
|
||||||
export let iconWithEmoji: Asset = view.ids.IconWithEmoji
|
export let iconWithEmoji: Asset = view.ids.IconWithEmoji
|
||||||
|
export let icon: Asset | undefined
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
let description: string | undefined = status?.description
|
let description: string | undefined = status?.description
|
||||||
|
|
||||||
|
$: allowEditCategory = status === undefined
|
||||||
|
|
||||||
$: needUpdate =
|
$: needUpdate =
|
||||||
(status?.name.trim() !== value.trim() || description !== status?.description || color !== status?.color) &&
|
(status === undefined ||
|
||||||
|
status.name.trim() !== value.trim() ||
|
||||||
|
description !== status?.description ||
|
||||||
|
color !== status.color) &&
|
||||||
value.trim() !== ''
|
value.trim() !== ''
|
||||||
|
|
||||||
async function save (): Promise<void> {
|
async function save (): Promise<void> {
|
||||||
@ -73,6 +78,13 @@
|
|||||||
const lastIndex = states.findLastIndex((p) => p.category === category)
|
const lastIndex = states.findLastIndex((p) => p.category === category)
|
||||||
const statuses = [...taskType.statuses.slice(0, lastIndex + 1), _id, ...taskType.statuses.slice(lastIndex + 1)]
|
const statuses = [...taskType.statuses.slice(0, lastIndex + 1), _id, ...taskType.statuses.slice(lastIndex + 1)]
|
||||||
|
|
||||||
|
type.statuses.push({
|
||||||
|
_id,
|
||||||
|
color,
|
||||||
|
icon,
|
||||||
|
taskType: taskType._id
|
||||||
|
})
|
||||||
|
|
||||||
await client.update(type, {
|
await client.update(type, {
|
||||||
statuses: calculateStatuses(type, $taskTypeStore, [{ taskTypeId: taskType._id, statuses }])
|
statuses: calculateStatuses(type, $taskTypeStore, [{ taskTypeId: taskType._id, statuses }])
|
||||||
})
|
})
|
||||||
@ -89,35 +101,42 @@
|
|||||||
})
|
})
|
||||||
const index = taskType.statuses.indexOf(status._id)
|
const index = taskType.statuses.indexOf(status._id)
|
||||||
const statuses = [...taskType.statuses.slice(0, index), _id, ...taskType.statuses.slice(index + 1)]
|
const statuses = [...taskType.statuses.slice(0, index), _id, ...taskType.statuses.slice(index + 1)]
|
||||||
|
for (const status of type.statuses) {
|
||||||
|
if (status._id === _id) {
|
||||||
|
status.color = color
|
||||||
|
status.icon = icon as any // Fix me
|
||||||
|
}
|
||||||
|
}
|
||||||
await client.update(type, {
|
await client.update(type, {
|
||||||
statuses: calculateStatuses(type, $taskTypeStore, [{ taskTypeId: taskType._id, statuses }])
|
statuses: calculateStatuses(type, $taskTypeStore, [{ taskTypeId: taskType._id, statuses }])
|
||||||
})
|
})
|
||||||
await client.update(taskType, {
|
await client.update(taskType, {
|
||||||
statuses
|
statuses
|
||||||
})
|
})
|
||||||
const projects = await client.findAll(task.class.Project, { type: type._id })
|
if (status._id !== _id) {
|
||||||
while (true) {
|
const projects = await client.findAll(task.class.Project, { type: type._id })
|
||||||
const docs = await client.findAll(
|
while (true) {
|
||||||
task.class.Task,
|
const docs = await client.findAll(
|
||||||
{
|
task.class.Task,
|
||||||
status: status._id,
|
{
|
||||||
space: { $in: projects.map((p) => p._id) }
|
status: status._id,
|
||||||
},
|
space: { $in: projects.map((p) => p._id) }
|
||||||
{ limit: 1000 }
|
},
|
||||||
)
|
{ limit: 1000 }
|
||||||
if (docs.length === 0) {
|
)
|
||||||
break
|
if (docs.length === 0) {
|
||||||
}
|
break
|
||||||
|
}
|
||||||
|
|
||||||
const op = client.apply(_id)
|
const op = client.apply(_id)
|
||||||
docs.map((p) => op.update(p, { status: _id }))
|
docs.map((p) => op.update(p, { status: _id }))
|
||||||
await op.commit()
|
await op.commit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearSettingsStore()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected: number = 0
|
let selected: number = icon === iconWithEmoji ? 1 : 0
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
id: 'color',
|
id: 'color',
|
||||||
@ -128,12 +147,22 @@
|
|||||||
label: view.string.EmojiCategory
|
label: view.string.EmojiCategory
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
$: allCategories = getClient()
|
||||||
|
.getModel()
|
||||||
|
.findAllSync(core.class.StatusCategory, { _id: { $in: taskType.statusCategories } })
|
||||||
|
|
||||||
|
$: categories = allCategories.map((it) => ({
|
||||||
|
id: it._id,
|
||||||
|
label: it.label,
|
||||||
|
icon: it.icon
|
||||||
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
label={task.string.StatusPopupTitle}
|
label={task.string.StatusPopupTitle}
|
||||||
type={'type-aside'}
|
type={'type-aside'}
|
||||||
okLabel={presentation.string.Save}
|
okLabel={status === undefined ? presentation.string.Create : presentation.string.Save}
|
||||||
okAction={save}
|
okAction={save}
|
||||||
canSave={needUpdate}
|
canSave={needUpdate}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
@ -157,28 +186,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="hulyModal-content__settingsSet">
|
<div class="hulyModal-content__settingsSet">
|
||||||
<div class="hulyModal-content__settingsSet-line">
|
<div class="hulyModal-content__settingsSet-line">
|
||||||
<span class="label"><Label label={task.string.Group} /></span>
|
<span class="label"><Label label={getEmbeddedLabel('Status Category')} /></span>
|
||||||
<!-- <ButtonMenu
|
<ButtonMenu
|
||||||
{items}
|
items={categories}
|
||||||
{selected}
|
selected={category}
|
||||||
icon={IconLink}
|
disabled={!allowEditCategory}
|
||||||
label={getEmbeddedLabel('Compeletd')}
|
icon={categories.find((it) => it.id === category)?.icon}
|
||||||
|
label={categories.find((it) => it.id === category)?.label}
|
||||||
kind={'secondary'}
|
kind={'secondary'}
|
||||||
size={'medium'}
|
size={'medium'}
|
||||||
on:selected={() => {}}
|
on:selected={(it) => {
|
||||||
/> -->
|
category = it.detail
|
||||||
</div>
|
}}
|
||||||
<div class="hulyModal-content__settingsSet-line">
|
/>
|
||||||
<span class="label"><Label label={task.string.Type} /></span>
|
|
||||||
<!-- <ButtonMenu
|
|
||||||
{items}
|
|
||||||
{selected}
|
|
||||||
icon={IconLink}
|
|
||||||
label={getEmbeddedLabel('Success')}
|
|
||||||
kind={'secondary'}
|
|
||||||
size={'medium'}
|
|
||||||
on:selected={() => {}}
|
|
||||||
/> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hulyModal-content__settingsSet table">
|
<div class="hulyModal-content__settingsSet table">
|
||||||
@ -192,9 +212,17 @@
|
|||||||
kind={'secondary'}
|
kind={'secondary'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
on:selected={(event) => {
|
on:selected={(event) => {
|
||||||
if (event.detail) selected = items.findIndex((it) => it.id === event.detail)
|
if (event.detail) {
|
||||||
|
selected = items.findIndex((it) => it.id === event.detail)
|
||||||
|
if (selected === 1) {
|
||||||
|
icon = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
{#if icon === iconWithEmoji}
|
||||||
|
<IconWithEmoji icon={color ?? 0} size={'medium'} />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="hulyTableAttr-content" class:mb-2={selected === 1}>
|
<div class="hulyTableAttr-content" class:mb-2={selected === 1}>
|
||||||
{#if selected === 0}
|
{#if selected === 0}
|
||||||
@ -204,13 +232,16 @@
|
|||||||
columns={'auto'}
|
columns={'auto'}
|
||||||
on:close={(evt) => {
|
on:close={(evt) => {
|
||||||
color = evt.detail
|
color = evt.detail
|
||||||
|
icon = undefined
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<EmojiPopup
|
<EmojiPopup
|
||||||
embedded
|
embedded
|
||||||
|
selected={String.fromCodePoint(color ?? 0)}
|
||||||
on:close={(evt) => {
|
on:close={(evt) => {
|
||||||
color = evt.detail.codePointAt(0)
|
color = evt.detail.codePointAt(0)
|
||||||
|
icon = iconWithEmoji
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { IdMap, Ref, Status, StatusCategory } from '@hcengineering/core'
|
import core, { IdMap, Ref, Status, StatusCategory } from '@hcengineering/core'
|
||||||
|
import { Asset } from '@hcengineering/platform'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import task, { Project, ProjectType, TaskType } from '@hcengineering/task'
|
import task, { Project, ProjectType, TaskType } from '@hcengineering/task'
|
||||||
import {
|
import {
|
||||||
@ -31,10 +32,10 @@
|
|||||||
import { createEventDispatcher, onMount } from 'svelte'
|
import { createEventDispatcher, onMount } from 'svelte'
|
||||||
import { typeStore } from '../..'
|
import { typeStore } from '../..'
|
||||||
import IconBacklog from '../icons/IconBacklog.svelte'
|
import IconBacklog from '../icons/IconBacklog.svelte'
|
||||||
import IconUnstarted from '../icons/IconUnstarted.svelte'
|
|
||||||
import IconCanceled from '../icons/IconCanceled.svelte'
|
import IconCanceled from '../icons/IconCanceled.svelte'
|
||||||
import IconCompleted from '../icons/IconCompleted.svelte'
|
import IconCompleted from '../icons/IconCompleted.svelte'
|
||||||
import IconStarted from '../icons/IconStarted.svelte'
|
import IconStarted from '../icons/IconStarted.svelte'
|
||||||
|
import IconUnstarted from '../icons/IconUnstarted.svelte'
|
||||||
|
|
||||||
export let value: Status | undefined
|
export let value: Status | undefined
|
||||||
export let shouldShowAvatar = true
|
export let shouldShowAvatar = true
|
||||||
@ -80,20 +81,10 @@
|
|||||||
|
|
||||||
$: projectState = type?.statuses.find((p) => p._id === value?._id)
|
$: projectState = type?.statuses.find((p) => p._id === value?._id)
|
||||||
|
|
||||||
const dispatchAccentColor = (color?: ColorDefinition): void => {
|
|
||||||
dispatch('accent-color', color)
|
|
||||||
}
|
|
||||||
|
|
||||||
$: color = getPlatformColorDef(
|
$: color = getPlatformColorDef(
|
||||||
projectState?.color ?? category?.color ?? getColorNumberByText(value?.name ?? ''),
|
projectState?.color ?? category?.color ?? getColorNumberByText(value?.name ?? ''),
|
||||||
$themeStore.dark
|
$themeStore.dark
|
||||||
)
|
)
|
||||||
$: dispatchAccentColor(color)
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
dispatchAccentColor(color)
|
|
||||||
})
|
|
||||||
|
|
||||||
$: void updateCategory(value)
|
$: void updateCategory(value)
|
||||||
|
|
||||||
async function updateCategory (value: Status | undefined): Promise<void> {
|
async function updateCategory (value: Status | undefined): Promise<void> {
|
||||||
@ -119,8 +110,21 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
$: index = sameCategory.findIndex((it) => it._id === value?._id) + 1
|
$: index = sameCategory.findIndex((it) => it._id === value?._id) + 1
|
||||||
|
|
||||||
$: icon = projectState?.icon === view.ids.IconWithEmoji ? IconWithEmoji : projectState?.icon
|
$: icon = projectState?.icon === view.ids.IconWithEmoji ? IconWithEmoji : projectState?.icon
|
||||||
|
|
||||||
|
const dispatchAccentColor = (color?: ColorDefinition, icon?: Asset | typeof IconWithEmoji): void => {
|
||||||
|
if (icon === undefined) {
|
||||||
|
dispatch('accent-color', color)
|
||||||
|
} else {
|
||||||
|
dispatch('accent-color', null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: dispatchAccentColor(color, icon)
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
dispatchAccentColor(color, icon)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if value}
|
{#if value}
|
||||||
|
@ -13,36 +13,21 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { Attribute, IdMap, Ref, Status, StatusCategory, toIdMap } from '@hcengineering/core'
|
import core, { IdMap, Ref, Status, StatusCategory, toIdMap } from '@hcengineering/core'
|
||||||
import { Asset } from '@hcengineering/platform'
|
import { Asset } from '@hcengineering/platform'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import { ProjectStatus, ProjectType, TaskType, findStatusAttr } from '@hcengineering/task'
|
import { settingsStore } from '@hcengineering/setting-resources'
|
||||||
import {
|
import { ProjectStatus, ProjectType, TaskType } from '@hcengineering/task'
|
||||||
CircleButton,
|
import { IconMoreV2, IconOpenedArrow, Label } from '@hcengineering/ui'
|
||||||
ColorDefinition,
|
import { ObjectPresenter } from '@hcengineering/view-resources'
|
||||||
IconOpenedArrow,
|
|
||||||
IconMoreV2,
|
|
||||||
IconMoreH,
|
|
||||||
Label,
|
|
||||||
defaultBackground,
|
|
||||||
eventToHTMLElement,
|
|
||||||
getColorNumberByText,
|
|
||||||
getPlatformColorDef,
|
|
||||||
showPopup,
|
|
||||||
themeStore
|
|
||||||
} from '@hcengineering/ui'
|
|
||||||
import { ColorsPopup, IconPicker, ObjectPresenter, statusStore } from '@hcengineering/view-resources'
|
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import task from '../../plugin'
|
import task from '../../plugin'
|
||||||
import StatusesPopup from './StatusesPopup.svelte'
|
|
||||||
import { settingsStore, clearSettingsStore } from '@hcengineering/setting-resources'
|
|
||||||
|
|
||||||
export let taskType: TaskType
|
export let taskType: TaskType
|
||||||
export let type: ProjectType
|
export let type: ProjectType
|
||||||
export let states: Status[] = []
|
export let states: Status[] = []
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
const elements: HTMLElement[] = []
|
const elements: HTMLElement[] = []
|
||||||
let selected: number | undefined
|
let selected: number | undefined
|
||||||
@ -74,42 +59,6 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onColor (state: Status, color: ColorDefinition, el: HTMLElement): void {
|
|
||||||
showPopup(ColorsPopup, { selected: color.name }, el, async (res) => {
|
|
||||||
if (res == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const targetColors = type.statuses.filter((p) => p._id === state._id)
|
|
||||||
for (const targetColor of targetColors) {
|
|
||||||
targetColor.color = res
|
|
||||||
}
|
|
||||||
await client.update(type, { statuses: type.statuses })
|
|
||||||
type = type
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function add (ofAttribute: Ref<Attribute<Status>> | undefined, cat: Ref<StatusCategory>): void {
|
|
||||||
if (ofAttribute === undefined) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showPopup(task.component.CreateStatePopup, {
|
|
||||||
ofAttribute,
|
|
||||||
_class: taskType.statusClass,
|
|
||||||
category: cat,
|
|
||||||
taskType,
|
|
||||||
type
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function edit (status: Status): void {
|
|
||||||
showPopup(task.component.CreateStatePopup, {
|
|
||||||
status,
|
|
||||||
taskType,
|
|
||||||
type,
|
|
||||||
ofAttribute: status.ofAttribute
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let categories: StatusCategory[] = []
|
let categories: StatusCategory[] = []
|
||||||
let categoriesMap: IdMap<StatusCategory> = new Map()
|
let categoriesMap: IdMap<StatusCategory> = new Map()
|
||||||
let groups = new Map<Ref<StatusCategory>, Status[]>()
|
let groups = new Map<Ref<StatusCategory>, Status[]>()
|
||||||
@ -119,35 +68,10 @@
|
|||||||
categoriesMap = toIdMap(res)
|
categoriesMap = toIdMap(res)
|
||||||
})
|
})
|
||||||
|
|
||||||
function click (ev: MouseEvent, state: Status): void {
|
function getProjectStatus (type: ProjectType, state: Status): ProjectStatus | undefined {
|
||||||
showPopup(
|
|
||||||
StatusesPopup,
|
|
||||||
{
|
|
||||||
onDelete: () => dispatch('delete', { state }),
|
|
||||||
showDelete: states.filter((it) => it.category === state.category).length > 1,
|
|
||||||
onUpdate: () => {
|
|
||||||
edit(state)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
eventToHTMLElement(ev),
|
|
||||||
() => {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProjectStatus (
|
|
||||||
type: ProjectType,
|
|
||||||
state: Status,
|
|
||||||
categoriesMap: IdMap<StatusCategory>
|
|
||||||
): ProjectStatus | undefined {
|
|
||||||
return type.statuses.find((p) => p._id === state._id)
|
return type.statuses.find((p) => p._id === state._id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getColor (type: ProjectType, state: Status, categoriesMap: IdMap<StatusCategory>): ColorDefinition {
|
|
||||||
const category = state.category !== undefined ? categoriesMap.get(state.category) : undefined
|
|
||||||
const targetColor = getProjectStatus(type, state, categoriesMap)?.color ?? state.color ?? category?.color
|
|
||||||
return getPlatformColorDef(targetColor ?? getColorNumberByText(state.name), $themeStore.dark)
|
|
||||||
}
|
|
||||||
|
|
||||||
function group (categories: StatusCategory[], states: Status[]): Map<Ref<StatusCategory>, Status[]> {
|
function group (categories: StatusCategory[], states: Status[]): Map<Ref<StatusCategory>, Status[]> {
|
||||||
const map = new Map<Ref<StatusCategory>, Status[]>(categories.map((p) => [p._id, []]))
|
const map = new Map<Ref<StatusCategory>, Status[]>(categories.map((p) => [p._id, []]))
|
||||||
for (const state of states) {
|
for (const state of states) {
|
||||||
@ -171,23 +95,6 @@
|
|||||||
}
|
}
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
function selectIcon (el: HTMLElement, state: Status): void {
|
|
||||||
const icons: Asset[] = []
|
|
||||||
const projectStatus = getProjectStatus(type, state, categoriesMap)
|
|
||||||
showPopup(IconPicker, { icon: projectStatus?.icon, color: projectStatus?.color, icons }, el, async (result) => {
|
|
||||||
if (result !== undefined && result !== null) {
|
|
||||||
const targetColors = type.statuses.filter((p) => p._id === state._id)
|
|
||||||
for (const targetColor of targetColors) {
|
|
||||||
targetColor.color = result.color
|
|
||||||
targetColor.icon = result.icon
|
|
||||||
}
|
|
||||||
if (targetColors.length > 0) {
|
|
||||||
await client.update(type, { statuses: type.statuses })
|
|
||||||
type = type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
settingsStore.subscribe((value) => {
|
settingsStore.subscribe((value) => {
|
||||||
if ((value.id === undefined && opened !== undefined) || (value.id !== undefined && value.id !== opened)) {
|
if ((value.id === undefined && opened !== undefined) || (value.id !== undefined && value.id !== opened)) {
|
||||||
opened = undefined
|
opened = undefined
|
||||||
@ -197,7 +104,9 @@
|
|||||||
if (opened === undefined || opened !== _status._id) {
|
if (opened === undefined || opened !== _status._id) {
|
||||||
opened = _status._id
|
opened = _status._id
|
||||||
const icons: Asset[] = []
|
const icons: Asset[] = []
|
||||||
const projectStatus = getProjectStatus(type, _status, categoriesMap)
|
const category = _status.category !== undefined ? categoriesMap.get(_status.category) : undefined
|
||||||
|
const projectStatus = getProjectStatus(type, _status)
|
||||||
|
const color = getProjectStatus(type, _status)?.color ?? _status.color ?? category?.color
|
||||||
$settingsStore = {
|
$settingsStore = {
|
||||||
id: opened,
|
id: opened,
|
||||||
component: task.component.CreateStatePopup,
|
component: task.component.CreateStatePopup,
|
||||||
@ -207,13 +116,10 @@
|
|||||||
type,
|
type,
|
||||||
ofAttribute: _status.ofAttribute,
|
ofAttribute: _status.ofAttribute,
|
||||||
icon: projectStatus?.icon,
|
icon: projectStatus?.icon,
|
||||||
color: projectStatus?.color,
|
color,
|
||||||
icons
|
icons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (opened === _status._id) {
|
|
||||||
clearSettingsStore()
|
|
||||||
opened = undefined
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -224,27 +130,15 @@
|
|||||||
<div class="hulyTableAttr-content class withTitle">
|
<div class="hulyTableAttr-content class withTitle">
|
||||||
<div class="hulyTableAttr-content__title">
|
<div class="hulyTableAttr-content__title">
|
||||||
<Label label={cat.label} />
|
<Label label={cat.label} />
|
||||||
<!-- <CircleButton
|
|
||||||
icon={IconAdd}
|
|
||||||
size={'medium'}
|
|
||||||
on:click={() => {
|
|
||||||
add(findStatusAttr(getClient().getHierarchy(), taskType.ofClass)?._id, cat._id)
|
|
||||||
}}
|
|
||||||
/> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="hulyTableAttr-content__wrapper">
|
<div class="hulyTableAttr-content__wrapper">
|
||||||
{#each states as state, i}
|
{#each states as state, i}
|
||||||
{@const color = getColor(type, state, categoriesMap)}
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- style:background={color.background ?? defaultBackground($themeStore.dark)} -->
|
|
||||||
<button
|
<button
|
||||||
bind:this={elements[prevIndex + i]}
|
bind:this={elements[prevIndex + i]}
|
||||||
class="hulyTableAttr-content__row"
|
class="hulyTableAttr-content__row"
|
||||||
class:selected={state._id === opened}
|
class:selected={state._id === opened}
|
||||||
draggable={true}
|
draggable={true}
|
||||||
on:contextmenu|preventDefault={(e) => {
|
|
||||||
click(e, state)
|
|
||||||
}}
|
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
handleSelect(state)
|
handleSelect(state)
|
||||||
}}
|
}}
|
||||||
@ -270,13 +164,6 @@
|
|||||||
objectId={state._id}
|
objectId={state._id}
|
||||||
value={state}
|
value={state}
|
||||||
props={{ projectType: type._id, taskType: taskType._id, kind: 'table-attrs' }}
|
props={{ projectType: type._id, taskType: taskType._id, kind: 'table-attrs' }}
|
||||||
on:click={(ev) => {
|
|
||||||
if (state.category !== undefined) {
|
|
||||||
selectIcon(elements[i + prevIndex], state)
|
|
||||||
} else {
|
|
||||||
onColor(state, color, elements[i + prevIndex])
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<div class="hulyTableAttr-content__row-arrow">
|
<div class="hulyTableAttr-content__row-arrow">
|
||||||
<IconOpenedArrow size={'small'} />
|
<IconOpenedArrow size={'small'} />
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AttributeEditor, getClient } from '@hcengineering/presentation'
|
import { AttributeEditor, getClient } from '@hcengineering/presentation'
|
||||||
import task, { ProjectType, TaskType, calculateStatuses } from '@hcengineering/task'
|
import task, { ProjectType, TaskType, calculateStatuses, findStatusAttr } from '@hcengineering/task'
|
||||||
import { Ref, Status } from '@hcengineering/core'
|
import { Ref, Status } from '@hcengineering/core'
|
||||||
import { Asset, getEmbeddedLabel } from '@hcengineering/platform'
|
import { Asset, getEmbeddedLabel } from '@hcengineering/platform'
|
||||||
import { Label, showPopup, ButtonIcon, ModernButton, IconSquareExpand, IconAdd, Icon } from '@hcengineering/ui'
|
import { Label, showPopup, ButtonIcon, ModernButton, IconSquareExpand, IconAdd, Icon } from '@hcengineering/ui'
|
||||||
import { IconPicker, statusStore } from '@hcengineering/view-resources'
|
import { IconPicker, statusStore } from '@hcengineering/view-resources'
|
||||||
import { ClassAttributes } from '@hcengineering/setting-resources'
|
import { ClassAttributes, settingsStore } from '@hcengineering/setting-resources'
|
||||||
import { taskTypeStore } from '../..'
|
import { taskTypeStore } from '../..'
|
||||||
import StatesProjectEditor from '../state/StatesProjectEditor.svelte'
|
import StatesProjectEditor from '../state/StatesProjectEditor.svelte'
|
||||||
import TaskTypeKindEditor from '../taskTypes/TaskTypeKindEditor.svelte'
|
import TaskTypeKindEditor from '../taskTypes/TaskTypeKindEditor.svelte'
|
||||||
@ -52,6 +52,25 @@
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
function handleAddStatus (el: MouseEvent): void {
|
||||||
|
const icons: Asset[] = []
|
||||||
|
const attr = findStatusAttr(getClient().getHierarchy(), taskType.ofClass)
|
||||||
|
$settingsStore = {
|
||||||
|
id: '#',
|
||||||
|
component: task.component.CreateStatePopup,
|
||||||
|
props: {
|
||||||
|
status: undefined,
|
||||||
|
taskType,
|
||||||
|
_class: taskType.statusClass,
|
||||||
|
category: task.statusCategory.Active,
|
||||||
|
type: projectType,
|
||||||
|
ofAttribute: attr,
|
||||||
|
icon: undefined,
|
||||||
|
color: 0,
|
||||||
|
icons
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="hulyComponent-content__column-group mt-4">
|
<div class="hulyComponent-content__column-group mt-4">
|
||||||
@ -105,7 +124,7 @@
|
|||||||
<div class="hulyTableAttr-header font-medium-12">
|
<div class="hulyTableAttr-header font-medium-12">
|
||||||
<Icon icon={task.icon.ManageTemplates} size={'small'} />
|
<Icon icon={task.icon.ManageTemplates} size={'small'} />
|
||||||
<span><Label label={plugin.string.ProcessStates} /></span>
|
<span><Label label={plugin.string.ProcessStates} /></span>
|
||||||
<ButtonIcon kind={'primary'} icon={IconAdd} size={'small'} on:click={(ev) => {}} />
|
<ButtonIcon kind={'primary'} icon={IconAdd} size={'small'} on:click={handleAddStatus} />
|
||||||
</div>
|
</div>
|
||||||
<StatesProjectEditor
|
<StatesProjectEditor
|
||||||
{taskType}
|
{taskType}
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<EmojiPopup
|
<EmojiPopup
|
||||||
embedded
|
embedded
|
||||||
|
selected={String.fromCodePoint(color ?? 0)}
|
||||||
on:close={(evt) => {
|
on:close={(evt) => {
|
||||||
dispatch('close', { icon: iconWithEmoji, color: evt.detail.codePointAt(0) })
|
dispatch('close', { icon: iconWithEmoji, color: evt.detail.codePointAt(0) })
|
||||||
}}
|
}}
|
||||||
|
Loading…
Reference in New Issue
Block a user