mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 04:25:03 +02:00
UBERF-4248: Task type (#4042)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -34,14 +34,15 @@
|
||||
deviceOptionsStore,
|
||||
capitalizeFirstLetter,
|
||||
formatKey,
|
||||
themeStore
|
||||
themeStore,
|
||||
ListView,
|
||||
resizeObserver
|
||||
} from '@hcengineering/ui'
|
||||
import { Action, ActionCategory, ViewContext } from '@hcengineering/view'
|
||||
import { filterActions, getSelection } from '../actions'
|
||||
import view from '../plugin'
|
||||
import { focusStore, selectionStore } from '../selection'
|
||||
import { openDoc } from '../utils'
|
||||
import { ListView, resizeObserver } from '@hcengineering/ui'
|
||||
import ObjectPresenter from './ObjectPresenter.svelte'
|
||||
import { createEventDispatcher, tick } from 'svelte'
|
||||
|
||||
|
||||
@@ -14,9 +14,21 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { Class, Doc } from '@hcengineering/core'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Component, Label } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
|
||||
export let value: Class<Doc>
|
||||
|
||||
$: presenters =
|
||||
value !== undefined ? getClient().getHierarchy().findMixinMixins(value, view.mixin.ObjectPresenter) : []
|
||||
</script>
|
||||
|
||||
<Label label={value.label} />
|
||||
<div class="flex-row-center text-nowrap">
|
||||
<Label label={value.label} />
|
||||
{#if presenters.length > 0}
|
||||
{#each presenters as presenter}
|
||||
<Component is={presenter.presenter} props={{ value }} />
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
export let columns: number = 8
|
||||
export let selected: string | undefined = undefined
|
||||
export let key: 'color' | 'icon' = 'color'
|
||||
export let embedded: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<PopupDialog label={view.string.ChooseAColor}>
|
||||
<PopupDialog label={view.string.ChooseAColor} {embedded}>
|
||||
<div class="color-grid" style="grid-template-columns: repeat({columns}, 1.5rem)">
|
||||
{#each colors as color, i}
|
||||
{@const col = key === 'color' ? color.color : color.icon}
|
||||
|
||||
@@ -14,84 +14,64 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Asset, Metadata } from '@hcengineering/platform'
|
||||
import presentation, { Card } from '@hcengineering/presentation'
|
||||
import {
|
||||
Button,
|
||||
EmojiPopup,
|
||||
Label,
|
||||
TabsControl,
|
||||
eventToHTMLElement,
|
||||
getPlatformColor,
|
||||
getPlatformColorDef,
|
||||
showPopup,
|
||||
themeStore
|
||||
} from '@hcengineering/ui'
|
||||
import { Button, EmojiPopup, TabsControl, getPlatformColor, getPlatformColorDef, themeStore } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import view from '../plugin'
|
||||
import ColorsPopup from './ColorsPopup.svelte'
|
||||
import PopupDialog from './PopupDialog.svelte'
|
||||
|
||||
export let icon: Metadata<string> | undefined = undefined
|
||||
export let icons: Asset[]
|
||||
export let iconWithEmoji: Asset = view.ids.IconWithEmoji
|
||||
export let color: number = 0
|
||||
export let showColor: boolean = true
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let _color = color
|
||||
let _icon = icon ?? icons[0]
|
||||
|
||||
function save () {
|
||||
dispatch('close', { icon: _icon, color: _color })
|
||||
}
|
||||
function pickColor (evt: MouseEvent) {
|
||||
showPopup(
|
||||
ColorsPopup,
|
||||
{ selected: getPlatformColorDef(_color, $themeStore.dark).name },
|
||||
eventToHTMLElement(evt),
|
||||
(newColor) => {
|
||||
if (newColor != null) {
|
||||
_color = newColor
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card
|
||||
label={view.string.ChooseIcon}
|
||||
okLabel={presentation.string.Save}
|
||||
okAction={save}
|
||||
canSave={_icon !== undefined}
|
||||
on:close={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
on:changeContent
|
||||
>
|
||||
<div class="float-left-box">
|
||||
<PopupDialog label={view.string.ChooseIcon} on:changeContent>
|
||||
<div class="float-left-box w-85">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<TabsControl size={'small'} model={[{ label: view.string.IconCategory }, { label: view.string.EmojiCategory }]}>
|
||||
<svelte:fragment slot="content" let:selected>
|
||||
{#if selected === 0}
|
||||
<div class="flex-row-center">
|
||||
<Label label={view.string.IconColor} />
|
||||
<div class="flex-no-shrink ml-2 color" on:click={pickColor}>
|
||||
<div class="dot" style="background-color: {getPlatformColor(_color ?? 0, $themeStore.dark)}" />
|
||||
</div>
|
||||
</div>
|
||||
{#each icons as obj}
|
||||
<div class="float-left p-2">
|
||||
<Button
|
||||
icon={obj}
|
||||
iconProps={{ fill: getPlatformColor(_color ?? 0, $themeStore.dark) }}
|
||||
size="medium"
|
||||
kind={obj === _icon ? 'primary' : 'ghost'}
|
||||
on:click={() => {
|
||||
_icon = obj
|
||||
<div class="flex-col mt-2">
|
||||
{#if icons.length > 0}
|
||||
<div class="flex">
|
||||
{#each icons as obj}
|
||||
<div class="float-left">
|
||||
<Button
|
||||
icon={obj}
|
||||
iconProps={showColor ? { fill: getPlatformColor(_color ?? 0, $themeStore.dark) } : undefined}
|
||||
size="medium"
|
||||
kind={obj === _icon ? 'primary' : 'ghost'}
|
||||
on:click={() => {
|
||||
_icon = obj
|
||||
dispatch(!showColor ? 'close' : 'update', { icon: _icon, color: _color })
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if showColor}
|
||||
<ColorsPopup
|
||||
selected={getPlatformColorDef(_color, $themeStore.dark).name}
|
||||
embedded
|
||||
on:close={(evt) => {
|
||||
_color = evt.detail
|
||||
dispatch(icons.length === 0 ? 'close' : 'update', {
|
||||
icon: icons.length === 0 ? null : _icon,
|
||||
color: _color
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<EmojiPopup
|
||||
embedded
|
||||
@@ -103,7 +83,7 @@
|
||||
</svelte:fragment>
|
||||
</TabsControl>
|
||||
</div>
|
||||
</Card>
|
||||
</PopupDialog>
|
||||
|
||||
<style lang="scss">
|
||||
.color {
|
||||
|
||||
@@ -14,12 +14,11 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { getClient, SpaceSelect } from '@hcengineering/presentation'
|
||||
import { Button, Label, Status as StatusControl, themeStore } from '@hcengineering/ui'
|
||||
|
||||
import core, { Class, Client, Doc, Ref, SortingOrder, Space } from '@hcengineering/core'
|
||||
import { OK, Resource, Status, getResource, translate } from '@hcengineering/platform'
|
||||
import { SpaceSelect } from '@hcengineering/presentation'
|
||||
import task, { Project, Task, calcRank } from '@hcengineering/task'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import view from '../plugin'
|
||||
|
||||
@@ -14,19 +14,19 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Class, Doc, DocumentQuery, FindOptions, Hierarchy, Ref } from '@hcengineering/core'
|
||||
import { Class, Doc, DocumentQuery, FindOptions, Hierarchy, Ref, mergeQueries } from '@hcengineering/core'
|
||||
import { Asset, IntlString } from '@hcengineering/platform'
|
||||
import presentation, { getClient, ObjectCreate } from '@hcengineering/presentation'
|
||||
import presentation, { ObjectCreate, getClient } from '@hcengineering/presentation'
|
||||
import {
|
||||
ActionIcon,
|
||||
AnySvelteComponent,
|
||||
Button,
|
||||
ButtonKind,
|
||||
ButtonSize,
|
||||
getEventPositionElement,
|
||||
getFocusManager,
|
||||
Label,
|
||||
LabelAndProps,
|
||||
getEventPositionElement,
|
||||
getFocusManager,
|
||||
showPanel,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
@@ -58,6 +58,8 @@
|
||||
export let searchField: string = 'name'
|
||||
export let docProps: Record<string, any> = {}
|
||||
export let shouldShowAvatar = false
|
||||
export let autoSelect = false
|
||||
export let findDefault: (() => Promise<Doc | undefined>) | undefined = undefined
|
||||
|
||||
export let create: ObjectCreate | undefined = undefined
|
||||
|
||||
@@ -68,11 +70,33 @@
|
||||
|
||||
const client = getClient()
|
||||
|
||||
async function updateSelected (value: Ref<Doc> | null | undefined) {
|
||||
selected = value ? await client.findOne(_class, { _id: value }) : undefined
|
||||
async function updateSelected (
|
||||
_value: Ref<Doc> | null | undefined,
|
||||
docQuery: DocumentQuery<Doc> | undefined = undefined
|
||||
): Promise<void> {
|
||||
selected = _value ? await client.findOne(_class, { ...(docQuery ?? {}), _id: _value }) : undefined
|
||||
|
||||
if (typeof docQuery?._id === 'object' && _value != null) {
|
||||
const merged = mergeQueries({ _id: _value }, docQuery)
|
||||
if (typeof merged._id === 'object' && Object.keys(merged._id).length === 0) {
|
||||
// We do not have match.
|
||||
selected = undefined
|
||||
}
|
||||
}
|
||||
|
||||
if (selected === undefined && autoSelect) {
|
||||
selected = (await findDefault?.()) ?? (await client.findOne(_class, { ...(docQuery ?? {}) }))
|
||||
if (selected !== undefined) {
|
||||
value = selected._id ?? undefined
|
||||
dispatch('change', value)
|
||||
}
|
||||
}
|
||||
if (selected !== undefined) {
|
||||
dispatch('object', selected)
|
||||
}
|
||||
}
|
||||
|
||||
$: updateSelected(value)
|
||||
$: void updateSelected(value, docQuery)
|
||||
|
||||
const mgr = getFocusManager()
|
||||
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
import { Label } from '@hcengineering/ui'
|
||||
|
||||
export let label: IntlString
|
||||
export let embedded: boolean = false
|
||||
</script>
|
||||
|
||||
<div class="card-container">
|
||||
<div class:card-container={!embedded}>
|
||||
<div class="overflow-label label"><Label {label} /></div>
|
||||
<div class="content"><slot /></div>
|
||||
</div>
|
||||
|
||||
@@ -24,16 +24,19 @@
|
||||
<div class="ac-header__wrap-title">
|
||||
{#if showLabelSelector}
|
||||
<slot name="label_selector" />
|
||||
{:else}
|
||||
{#if label}
|
||||
<span class="ac-header__title">{label}</span>
|
||||
{/if}
|
||||
{#if modeSelectorProps !== undefined}
|
||||
<ModeSelector props={modeSelectorProps} />
|
||||
{/if}
|
||||
{:else if label}
|
||||
<span class="ac-header__title">{label}</span>
|
||||
{/if}
|
||||
{#if $$slots.type_selector}
|
||||
<div class="ml-2">
|
||||
<slot name="type_selector" />
|
||||
</div>
|
||||
{/if}
|
||||
{#if modeSelectorProps !== undefined}
|
||||
<ModeSelector props={modeSelectorProps} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mb-1 clear-mins">
|
||||
<div class="mb-1 clear-mins flex-row-center">
|
||||
<ViewletSelector bind:viewlet bind:viewlets viewletQuery={viewletQuery ?? { attachTo: _class }} />
|
||||
<slot name="header-tools" />
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { IntlString } from '@hcengineering/platform'
|
||||
import type { ButtonSize, ButtonKind } from '@hcengineering/ui'
|
||||
import type { ButtonSize, ButtonKind, EditStyle } from '@hcengineering/ui'
|
||||
import { EditBox, Label, showPopup, eventToHTMLElement, Button } from '@hcengineering/ui'
|
||||
import EditBoxPopup from './EditBoxPopup.svelte'
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
export let size: ButtonSize = 'small'
|
||||
export let justify: 'left' | 'center' = 'center'
|
||||
export let width: string | undefined = 'fit-content'
|
||||
export let editKind: EditStyle | undefined = undefined
|
||||
|
||||
let shown: boolean = false
|
||||
|
||||
@@ -71,5 +72,5 @@
|
||||
<span class="content-dark-color"><Label label={placeholder} /></span>
|
||||
{/if}
|
||||
{:else}
|
||||
<EditBox {placeholder} bind:value {autoFocus} {select} on:change={_onchange} />
|
||||
<EditBox {placeholder} bind:value {autoFocus} {select} on:change={_onchange} kind={editKind} />
|
||||
{/if}
|
||||
|
||||
@@ -24,9 +24,10 @@
|
||||
FindOptions,
|
||||
Lookup,
|
||||
Ref,
|
||||
TxOperations
|
||||
TxOperations,
|
||||
getObjectValue,
|
||||
SortingOrder
|
||||
} from '@hcengineering/core'
|
||||
import { getObjectValue, SortingOrder } from '@hcengineering/core'
|
||||
import notification from '@hcengineering/notification'
|
||||
import { createQuery, getClient, updateAttribute } from '@hcengineering/presentation'
|
||||
import ui, {
|
||||
|
||||
@@ -75,9 +75,6 @@
|
||||
groupDepth: viewlet.viewOptions?.groupDepth
|
||||
}
|
||||
|
||||
if (classes.length > 1) {
|
||||
mergedModel.groupBy.push('_class')
|
||||
}
|
||||
for (const ev of extraViewlets) {
|
||||
mergedModel.groupBy.push(...(ev.viewOptions?.groupBy ?? []))
|
||||
mergedModel.orderBy.push(...(ev.viewOptions?.orderBy ?? []))
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
$: resultOptions = { ...options, lookup, ...(orderBy !== undefined ? { sort: { [orderBy[0]]: orderBy[1] } } : {}) }
|
||||
|
||||
let resultQuery: DocumentQuery<Doc> = query
|
||||
$: getResultQuery(query, viewOptionsConfig, viewOptions).then((p) => {
|
||||
$: void getResultQuery(query, viewOptionsConfig, viewOptions).then((p) => {
|
||||
resultQuery = mergeQueries(p, query)
|
||||
})
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
$: groupByKey = viewOptions.groupBy[level] ?? noCategory
|
||||
let categories: CategoryType[] = []
|
||||
$: updateCategories(_class, space, docs, groupByKey, viewOptions, viewOptionsConfig)
|
||||
$: void updateCategories(_class, space, docs, groupByKey, viewOptions, viewOptionsConfig)
|
||||
|
||||
$: groupByDocs = groupBy(docs, groupByKey, categories)
|
||||
|
||||
@@ -100,8 +100,8 @@
|
||||
CategoryQuery.remove(queryId)
|
||||
})
|
||||
|
||||
function update () {
|
||||
updateCategories(_class, space, docs, groupByKey, viewOptions, viewOptionsConfig)
|
||||
function update (): void {
|
||||
void updateCategories(_class, space, docs, groupByKey, viewOptions, viewOptionsConfig)
|
||||
}
|
||||
|
||||
async function updateCategories (
|
||||
@@ -111,7 +111,7 @@
|
||||
groupByKey: string,
|
||||
viewOptions: ViewOptions,
|
||||
viewOptionsModel: ViewOptionModel[] | undefined
|
||||
) {
|
||||
): Promise<void> {
|
||||
categories = await getCategories(client, _class, space, docs, groupByKey)
|
||||
if (level === 0) {
|
||||
for (const viewOption of viewOptionsModel ?? []) {
|
||||
|
||||
Reference in New Issue
Block a user