mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-29 21:15:06 +02:00
Board: Add card details (members, labels, date) (#1376)
Signed-off-by: Anna No <anna.no@xored.com>
This commit is contained in:
@@ -14,10 +14,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { boardId, Card, CardAction } from '@anticrm/board'
|
||||
import { boardId } from '@anticrm/board'
|
||||
import board from '@anticrm/board-resources/src/plugin'
|
||||
import type { TxOperations as Client, Ref, Space } from '@anticrm/core'
|
||||
import { mergeIds, Resource } from '@anticrm/platform'
|
||||
import type { Ref, Space } from '@anticrm/core'
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
import { KanbanTemplate, Sequence } from '@anticrm/task'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import { ViewletDescriptor } from '@anticrm/view'
|
||||
@@ -32,48 +32,6 @@ export default mergeIds(boardId, board, {
|
||||
Cards: '' as AnyComponent,
|
||||
KanbanView: '' as AnyComponent
|
||||
},
|
||||
cardAction: {
|
||||
Cover: '' as Ref<CardAction>,
|
||||
Join: '' as Ref<CardAction>,
|
||||
Members: '' as Ref<CardAction>,
|
||||
Labels: '' as Ref<CardAction>,
|
||||
Checklist: '' as Ref<CardAction>,
|
||||
Dates: '' as Ref<CardAction>,
|
||||
Attachments: '' as Ref<CardAction>,
|
||||
CustomFields: '' as Ref<CardAction>,
|
||||
AddButton: '' as Ref<CardAction>,
|
||||
Move: '' as Ref<CardAction>,
|
||||
Copy: '' as Ref<CardAction>,
|
||||
MakeTemplate: '' as Ref<CardAction>,
|
||||
Watch: '' as Ref<CardAction>,
|
||||
Archive: '' as Ref<CardAction>,
|
||||
SendToBoard: '' as Ref<CardAction>,
|
||||
Delete: '' as Ref<CardAction>
|
||||
},
|
||||
cardActionHandler: {
|
||||
Cover: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Join: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Members: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Labels: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Checklist: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Dates: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Attachments: '' as Resource<(card: Card, client: Client) => void>,
|
||||
CustomFields: '' as Resource<(card: Card, client: Client) => void>,
|
||||
AddButton: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Move: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Copy: '' as Resource<(card: Card, client: Client) => void>,
|
||||
MakeTemplate: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Watch: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Archive: '' as Resource<(card: Card, client: Client) => void>,
|
||||
SendToBoard: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Delete: '' as Resource<(card: Card, client: Client) => void>
|
||||
},
|
||||
cardActionSupportedHandler: {
|
||||
Join: '' as Resource<(card: Card, client: Client) => boolean>,
|
||||
Archive: '' as Resource<(card: Card, client: Client) => boolean>,
|
||||
SendToBoard: '' as Resource<(card: Card, client: Client) => boolean>,
|
||||
Delete: '' as Resource<(card: Card, client: Client) => boolean>
|
||||
},
|
||||
space: {
|
||||
DefaultBoard: '' as Ref<Space>
|
||||
},
|
||||
|
||||
@@ -374,6 +374,8 @@ p:last-child { margin-block-end: 0; }
|
||||
.w-85 {width: 21.25rem; }
|
||||
.w-165 {width: 41.25rem; }
|
||||
.min-w-0 { min-width: 0; }
|
||||
.min-w-4 { min-width: 1rem; }
|
||||
.min-w-9 { min-width: 2.25rem; }
|
||||
.min-h-0 { min-height: 0; }
|
||||
.clear-mins {
|
||||
min-width: 0;
|
||||
@@ -530,6 +532,7 @@ a.no-line {
|
||||
/* Backgrounds & Colors */
|
||||
.background-theme-bg-color { background-color: var(--theme-bg-color); }
|
||||
.background-highlight-red { background-color: var(--highlight-red); }
|
||||
.background-button-bg-color { background-color: var(--button-bg-color); }
|
||||
.background-button-bg-enabled { background-color: var(--theme-button-bg-enabled); }
|
||||
.background-menu-divider { background-color: var(--theme-menu-divider); }
|
||||
.background-card-divider { background-color: var(--theme-card-divider); }
|
||||
@@ -545,7 +548,10 @@ a.no-line {
|
||||
|
||||
.red-color { color: var(--highlight-red); }
|
||||
|
||||
.border-radius-3 {border-radius: 0.75rem;}
|
||||
.border-radius-4 { border-radius: 1rem; }
|
||||
.border-radius-3 { border-radius: 0.75rem; }
|
||||
.border-radius-2 { border-radius: 0.5rem; }
|
||||
.border-radius-1 { border-radius: 0.25rem; }
|
||||
.border-bg-accent {border: 1px solid var(--theme-bg-accent-color);}
|
||||
.border-primary-button { border-color: var(--primary-button-border); }
|
||||
.border-button-enabled { border: 1px solid var(--theme-button-border-enabled); }
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
export let width: string | undefined = undefined
|
||||
export let resetIconSize: boolean = false
|
||||
export let focus: boolean = false
|
||||
export let isCircle: boolean = false
|
||||
|
||||
export let input: HTMLButtonElement | undefined = undefined
|
||||
|
||||
@@ -47,6 +48,8 @@
|
||||
bind:this={input}
|
||||
class="button {kind} {size} jf-{justify}"
|
||||
class:only-icon={iconOnly}
|
||||
class:border-radius-1={!isCircle}
|
||||
class:border-radius-4={isCircle}
|
||||
disabled={disabled || loading}
|
||||
style={width ? 'width: ' + width : ''}
|
||||
on:click
|
||||
@@ -101,7 +104,6 @@
|
||||
color: var(--accent-color);
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
border-radius: .25rem;
|
||||
transition-property: border, background-color, color, box-shadow;
|
||||
transition-duration: .15s;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import type { AnySvelteComponent } from '../types'
|
||||
import Icon from './Icon.svelte'
|
||||
|
||||
export let icon: Asset | AnySvelteComponent
|
||||
export let icon: Asset | AnySvelteComponent | undefined
|
||||
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'large'
|
||||
export let transparent: boolean = false
|
||||
export let selected: boolean = false
|
||||
@@ -27,7 +27,12 @@
|
||||
|
||||
<div class="flex-center icon-button icon-{size}" class:selected class:transparent class:primary on:click|stopPropagation on:mousemove>
|
||||
<div class="content">
|
||||
<Icon {icon} size={'full'} />
|
||||
{#if $$slots.content}
|
||||
<slot name="content" />
|
||||
{:else if icon}
|
||||
<Icon {icon} size={'full'} />
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -25,28 +25,34 @@
|
||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||
export let rightSection: boolean = false
|
||||
export let reverseCommands = false
|
||||
export let showHeader = true
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
</script>
|
||||
|
||||
<div class="antiPanel antiComponent">
|
||||
<div class:panel-content={!rightSection} class:ad-section-50={rightSection} class:divide={rightSection}>
|
||||
<div class="ac-header short mirror divide">
|
||||
<div class="ac-header__wrap-title">
|
||||
{#if icon}<div class="ac-header__icon"><Icon {icon} size={'large'} /></div>{/if}
|
||||
<div class="ac-header__wrap-description">
|
||||
{#if title}
|
||||
<span class="ac-header__title">{title}</span>
|
||||
{#if showHeader}
|
||||
<div class="ac-header short mirror divide">
|
||||
<div class="ac-header__wrap-title">
|
||||
{#if icon}
|
||||
<div class="ac-header__icon">
|
||||
<Icon {icon} size={'large'} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if subtitle}<span class="ac-header__description">{subtitle}</span>{/if}
|
||||
<div class="ac-header__wrap-description">
|
||||
{#if title}<span class="ac-header__title">{title}</span>{/if}
|
||||
{#if subtitle}<span class="ac-header__description">{subtitle}</span>{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if rightSection}
|
||||
<div class="flex">
|
||||
<slot name="commands" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if rightSection}
|
||||
<div class="flex">
|
||||
<slot name="commands" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if $$slots.subtitle}
|
||||
<div class="ac-subtitle">
|
||||
<div class="ac-subtitle-content">
|
||||
@@ -54,13 +60,13 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class='flex-col'>
|
||||
<div class="flex-col">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if rightSection}
|
||||
<slot name='rightSection'/>
|
||||
<slot name="rightSection" />
|
||||
{/if}
|
||||
|
||||
<div class="ad-tools" class:grow-reverse={reverseCommands}>
|
||||
@@ -69,15 +75,14 @@
|
||||
<slot name="commands" />
|
||||
</div>
|
||||
{/if}
|
||||
<slot name='actions'/>
|
||||
<slot name="actions" />
|
||||
<div class="tool">
|
||||
<ActionIcon
|
||||
icon={IconClose}
|
||||
size={'medium'}
|
||||
action={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
/>
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,4 +94,5 @@
|
||||
flex-direction: column;
|
||||
align-content: stretch;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
export let icon: 'normal' | 'warning' | 'overdue' = 'normal'
|
||||
export let labelOver: IntlString | undefined = undefined // label instead of date
|
||||
export let labelNull: IntlString = ui.string.NoDate
|
||||
export let showIcon = true
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -64,9 +65,11 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="btn-icon {icon}">
|
||||
<Icon icon={icon === 'overdue' ? DPCalendarOver : DPCalendar} size={'full'}/>
|
||||
</div>
|
||||
{#if showIcon}
|
||||
<div class="btn-icon {icon}">
|
||||
<Icon icon={icon === 'overdue' ? DPCalendarOver : DPCalendar} size={'full'}/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if value !== null && value !== undefined}
|
||||
{#if labelOver !== undefined}
|
||||
<Label label={labelOver} />
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
export let value: Card
|
||||
export let inline: boolean = false
|
||||
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
|
||||
@@ -16,17 +16,20 @@
|
||||
<script lang="ts">
|
||||
import type { Card } from '@anticrm/board'
|
||||
import { Class, Ref } from '@anticrm/core'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import type { State } from '@anticrm/task'
|
||||
import task from '@anticrm/task'
|
||||
import { StyledTextBox } from '@anticrm/text-editor'
|
||||
import { Button, EditBox, Icon, IconClose, Label, Scroller } from '@anticrm/ui'
|
||||
import { EditBox, Icon, Label, Panel, Scroller } from '@anticrm/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
|
||||
import board from '../plugin'
|
||||
import { getCardActions } from '../utils/CardActionUtils'
|
||||
import { updateCard } from '../utils/CardUtils'
|
||||
import CardActions from './editor/CardActions.svelte'
|
||||
import CardActivity from './editor/CardActivity.svelte'
|
||||
import CardFields from './editor/CardFields.svelte'
|
||||
import CardDetails from './editor/CardDetails.svelte'
|
||||
|
||||
export let _id: Ref<Card>
|
||||
export let _class: Ref<Class<Card>>
|
||||
@@ -36,6 +39,7 @@
|
||||
|
||||
let object: Card | undefined
|
||||
let state: State | undefined
|
||||
let handleMove: () => void
|
||||
|
||||
$: _id &&
|
||||
_class &&
|
||||
@@ -48,7 +52,18 @@
|
||||
state = result[0]
|
||||
})
|
||||
|
||||
function change (field: string, value: any) {
|
||||
getCardActions(client, { _id: board.cardAction.Move }).then(async (result) => {
|
||||
if (result[0]?.handler) {
|
||||
const handler = await getResource(result[0].handler)
|
||||
handleMove = () => {
|
||||
if (object) {
|
||||
handler(object, client)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function change(field: string, value: any) {
|
||||
if (object) {
|
||||
updateCard(client, object, field, value)
|
||||
}
|
||||
@@ -60,61 +75,66 @@
|
||||
</script>
|
||||
|
||||
{#if object !== undefined}
|
||||
<Scroller>
|
||||
<div class="flex-col-stretch h-full w-165 p-6">
|
||||
<!-- TODO cover -->
|
||||
<div class="close-button">
|
||||
<Button icon={IconClose} kind="transparent" size="large" on:click={() => dispatch('close')} />
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9">
|
||||
<Icon icon={board.icon.Card} size="large" />
|
||||
</div>
|
||||
<div class="fs-title text-lg">
|
||||
<EditBox bind:value={object.title} maxWidth="39rem" focus on:change={() => change('title', object?.title)} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9" />
|
||||
<div>
|
||||
<Label label={board.string.InList} /><span class="state-name ml-1">{state?.title}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="flex-grow mr-4">
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9" />
|
||||
<CardFields value={object} />
|
||||
<Panel showHeader={false} on:close={() => dispatch('close')}>
|
||||
<Scroller>
|
||||
<div class="flex-col-stretch h-full w-165 p-6">
|
||||
<!-- TODO cover -->
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9">
|
||||
<Icon icon={board.icon.Card} size="large" />
|
||||
</div>
|
||||
<div class="flex-row-streach mt-4 mb-2">
|
||||
<div class="w-9">
|
||||
<Icon icon={board.icon.Card} size="large" />
|
||||
</div>
|
||||
<div class="fs-title">
|
||||
<Label label={board.string.Description} />
|
||||
</div>
|
||||
<div class="fs-title text-lg">
|
||||
<EditBox
|
||||
bind:value={object.title}
|
||||
maxWidth="39rem"
|
||||
focus
|
||||
on:change={() => change('title', object?.title)}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9" />
|
||||
<div class="background-bg-accent border-bg-accent border-radius-3 p-2 w-full">
|
||||
<StyledTextBox
|
||||
alwaysEdit={true}
|
||||
showButtons={false}
|
||||
placeholder={board.string.DescriptionPlaceholder}
|
||||
bind:content={object.description}
|
||||
on:value={(evt) => change('description', evt.detail)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO attachments-->
|
||||
<!-- TODO checklists -->
|
||||
<CardActivity value={object} />
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9" />
|
||||
<div>
|
||||
<Label label={board.string.InList} />
|
||||
<span class="state-name ml-1" on:click={handleMove}>{state?.title}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="flex-grow mr-4">
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9" />
|
||||
<CardDetails value={object} />
|
||||
</div>
|
||||
<div class="flex-row-streach mt-4 mb-2">
|
||||
<div class="w-9">
|
||||
<Icon icon={board.icon.Card} size="large" />
|
||||
</div>
|
||||
<div class="fs-title">
|
||||
<Label label={board.string.Description} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row-streach">
|
||||
<div class="w-9" />
|
||||
<div class="background-bg-accent border-bg-accent border-radius-3 p-2 w-full">
|
||||
<StyledTextBox
|
||||
alwaysEdit={true}
|
||||
showButtons={false}
|
||||
placeholder={board.string.DescriptionPlaceholder}
|
||||
bind:content={object.description}
|
||||
on:value={(evt) => change('description', evt.detail)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO attachments-->
|
||||
<!-- TODO checklists -->
|
||||
<CardActivity value={object} />
|
||||
</div>
|
||||
|
||||
<CardActions value={object} />
|
||||
<CardActions value={object} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Scroller>
|
||||
</Scroller>
|
||||
</Panel>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
export let object: WithLookup<Card>
|
||||
export let dragged: boolean
|
||||
|
||||
function showMenu (ev?: Event): void {
|
||||
function showMenu(ev?: Event): void {
|
||||
showPopup(ContextMenu, { object }, (ev as MouseEvent).target as HTMLElement)
|
||||
}
|
||||
|
||||
function showLead () {
|
||||
function showLead() {
|
||||
showPanel(board.component.EditCard, object._id, object._class, 'middle')
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 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 type { Card, CardLabel } from '@anticrm/board'
|
||||
|
||||
import contact, { Employee } from '@anticrm/contact'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import { Button, IconAdd, Label } from '@anticrm/ui'
|
||||
|
||||
import board from '../../plugin'
|
||||
import { getCardActions } from '../../utils/CardActionUtils'
|
||||
import { hasDate } from '../../utils/CardUtils'
|
||||
import DatePresenter from '../presenters/DatePresenter.svelte'
|
||||
import LabelPresenter from '../presenters/LabelPresenter.svelte'
|
||||
import MemberPresenter from '../presenters/MemberPresenter.svelte'
|
||||
|
||||
export let value: Card
|
||||
const query = createQuery()
|
||||
const client = getClient()
|
||||
let members: Employee[]
|
||||
let labels: CardLabel[]
|
||||
let membersHandler: () => void
|
||||
let labelsHandler: () => void
|
||||
let dateHandler: () => void
|
||||
|
||||
$: value.members &&
|
||||
value.members.length > 0 &&
|
||||
query.query(contact.class.Employee, { _id: { $in: value.members } }, (result) => {
|
||||
members = result
|
||||
})
|
||||
|
||||
$: value.labels &&
|
||||
value.labels.length > 0 &&
|
||||
query.query(board.class.CardLabel, { _id: { $in: value.labels } }, (result) => {
|
||||
labels = result
|
||||
})
|
||||
|
||||
getCardActions(client, {
|
||||
_id: { $in: [board.cardAction.Dates, board.cardAction.Labels, board.cardAction.Members] }
|
||||
}).then(async (result) => {
|
||||
for (const action of result) {
|
||||
if (action.handler) {
|
||||
const handler = await getResource(action.handler)
|
||||
if (action._id === board.cardAction.Dates) {
|
||||
dateHandler = () => handler(value, client)
|
||||
} else if (action._id === board.cardAction.Labels) {
|
||||
labelsHandler = () => handler(value, client)
|
||||
} else if (action._id === board.cardAction.Members) {
|
||||
membersHandler = () => handler(value, client)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{#if members && members.length > 0}
|
||||
<div class="flex-col mt-4 mr-6">
|
||||
<div class="text-md font-medium">
|
||||
<Label label={board.string.Members} />
|
||||
</div>
|
||||
<div class="flex-row-center flex-gap-1">
|
||||
{#each members as member}
|
||||
<MemberPresenter value={member} size="large" />
|
||||
{/each}
|
||||
<Button icon={IconAdd} isCircle={true} kind="no-border" size="large" on:click={membersHandler} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if labels && labels.length > 0}
|
||||
<div class="flex-col mt-4 mr6">
|
||||
<div class="text-md font-medium">
|
||||
<Label label={board.string.Labels} />
|
||||
</div>
|
||||
<div class="flex-row-center flex-gap-1">
|
||||
{#each labels as label}
|
||||
<LabelPresenter value={label} size="large" on:click={labelsHandler} />
|
||||
{/each}
|
||||
<Button icon={IconAdd} kind="no-border" size="large" on:click={labelsHandler} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if value.date && hasDate(value)}
|
||||
<div class="flex-col mt-4">
|
||||
<div class="text-md font-medium">
|
||||
<Label label={board.string.Dates} />
|
||||
</div>
|
||||
<DatePresenter value={value.date} on:click={dateHandler} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -1,24 +0,0 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 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 type { Card } from '@anticrm/board'
|
||||
|
||||
export let value: Card
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div />
|
||||
{/if}
|
||||
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import type { CardDate } from '@anticrm/board'
|
||||
import { CheckBox, DatePresenter } from '@anticrm/ui'
|
||||
|
||||
// TODO: implement
|
||||
export let value: CardDate
|
||||
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class="flex-presenter flex-gap-1 h-full">
|
||||
<CheckBox checked={value.isChecked} />
|
||||
<div class="flex-center h-full">
|
||||
<div class="flex-row-center background-button-bg-color border-radius-1 w-full">
|
||||
{#if value.startDate && value.dueDate}
|
||||
<DatePresenter bind:value={value.startDate} showIcon={false} />
|
||||
-
|
||||
<DatePresenter bind:value={value.dueDate} withTime={true} showIcon={false} />
|
||||
{:else if value.startDate}
|
||||
<DatePresenter bind:value={value.startDate} />
|
||||
{:else if value.dueDate}
|
||||
<DatePresenter bind:value={value.dueDate} withTime={true} showIcon={false} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { Button, getPlatformColor } from '@anticrm/ui'
|
||||
import type { CardLabel } from '@anticrm/board'
|
||||
|
||||
export let value: CardLabel
|
||||
export let size: 'large' | 'medium'
|
||||
|
||||
const background = getPlatformColor(value.color)
|
||||
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div style:background class="border-radius-1">
|
||||
<Button {size} kind="transparent" on:click>
|
||||
<div class="flex-center h-full w-full min-w-4" slot="content">{value.title ?? ''}</div>
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,25 @@
|
||||
<script lang="ts">
|
||||
import type { Employee } from '@anticrm/contact'
|
||||
import { getFirstName, getLastName } from '@anticrm/contact'
|
||||
import { ContactPresenter } from '@anticrm/contact-resources'
|
||||
import { Button, showPopup } from '@anticrm/ui'
|
||||
|
||||
export let value: Employee
|
||||
export let size: 'large' | 'medium'
|
||||
const firstName = getFirstName(value.name)
|
||||
const lastName = getLastName(value.name)
|
||||
const nameLabel = `${firstName?.[0] ?? ''}${lastName?.[0] ?? ''}`.toUpperCase()
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<Button
|
||||
{size}
|
||||
kind="no-border"
|
||||
isCircle={true}
|
||||
on:click={() => {
|
||||
showPopup(ContactPresenter, { value }) // TODO: show proper popup
|
||||
}}
|
||||
>
|
||||
<div slot="content" class="text-md">{nameLabel}</div>
|
||||
</Button>
|
||||
{/if}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { CardAction } from '@anticrm/board'
|
||||
import { Client } from '@anticrm/core'
|
||||
import { Client, DocumentQuery } from '@anticrm/core'
|
||||
import board from '../plugin'
|
||||
|
||||
export const cardActionSorter = (a1: CardAction, a2: CardAction) => a1.position - a2.position
|
||||
|
||||
export const getCardActions = (client: Client) => {
|
||||
return client.findAll(board.class.CardAction, {})
|
||||
export const getCardActions = (client: Client, query?: DocumentQuery<CardAction>) => {
|
||||
return client.findAll(board.class.CardAction, query ?? {})
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ export function hasCover (card: Card): boolean {
|
||||
return !!card.coverColor || !!card.coverImage
|
||||
}
|
||||
|
||||
export function hasDate (card: Card): boolean {
|
||||
return !!card.date && (!!card.date.dueDate || !!card.date.startDate)
|
||||
}
|
||||
|
||||
export function addCurrentUser (card: Card, client: Client): void {
|
||||
const employee = (getCurrentAccount() as EmployeeAccount).employee
|
||||
card.members = card.members ?? []
|
||||
|
||||
@@ -108,14 +108,6 @@ const boards = plugin(boardId, {
|
||||
app: {
|
||||
Board: '' as Ref<Doc>
|
||||
},
|
||||
cardActionType: {
|
||||
Suggested: 'Suggested',
|
||||
Editor: 'Editor',
|
||||
Cover: 'Cover',
|
||||
AddToCard: 'AddToCard',
|
||||
Automation: 'Automation',
|
||||
Action: 'Action'
|
||||
},
|
||||
class: {
|
||||
Board: '' as Ref<Class<Board>>,
|
||||
Card: '' as Ref<Class<Card>>,
|
||||
@@ -128,6 +120,56 @@ const boards = plugin(boardId, {
|
||||
},
|
||||
space: {
|
||||
BoardTemplates: '' as Ref<KanbanTemplateSpace>
|
||||
},
|
||||
cardActionType: {
|
||||
Suggested: 'Suggested',
|
||||
Editor: 'Editor',
|
||||
Cover: 'Cover',
|
||||
AddToCard: 'AddToCard',
|
||||
Automation: 'Automation',
|
||||
Action: 'Action'
|
||||
},
|
||||
cardAction: {
|
||||
Cover: '' as Ref<CardAction>,
|
||||
Join: '' as Ref<CardAction>,
|
||||
Members: '' as Ref<CardAction>,
|
||||
Labels: '' as Ref<CardAction>,
|
||||
Checklist: '' as Ref<CardAction>,
|
||||
Dates: '' as Ref<CardAction>,
|
||||
Attachments: '' as Ref<CardAction>,
|
||||
CustomFields: '' as Ref<CardAction>,
|
||||
AddButton: '' as Ref<CardAction>,
|
||||
Move: '' as Ref<CardAction>,
|
||||
Copy: '' as Ref<CardAction>,
|
||||
MakeTemplate: '' as Ref<CardAction>,
|
||||
Watch: '' as Ref<CardAction>,
|
||||
Archive: '' as Ref<CardAction>,
|
||||
SendToBoard: '' as Ref<CardAction>,
|
||||
Delete: '' as Ref<CardAction>
|
||||
},
|
||||
cardActionHandler: {
|
||||
Cover: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Join: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Members: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Labels: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Checklist: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Dates: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Attachments: '' as Resource<(card: Card, client: Client) => void>,
|
||||
CustomFields: '' as Resource<(card: Card, client: Client) => void>,
|
||||
AddButton: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Move: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Copy: '' as Resource<(card: Card, client: Client) => void>,
|
||||
MakeTemplate: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Watch: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Archive: '' as Resource<(card: Card, client: Client) => void>,
|
||||
SendToBoard: '' as Resource<(card: Card, client: Client) => void>,
|
||||
Delete: '' as Resource<(card: Card, client: Client) => void>
|
||||
},
|
||||
cardActionSupportedHandler: {
|
||||
Join: '' as Resource<(card: Card, client: Client) => boolean>,
|
||||
Archive: '' as Resource<(card: Card, client: Client) => boolean>,
|
||||
SendToBoard: '' as Resource<(card: Card, client: Client) => boolean>,
|
||||
Delete: '' as Resource<(card: Card, client: Client) => boolean>
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user