mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 11:31:57 +03:00
Board: Add kanban card edit mode (#1484)
* Board: Extend popup positioning for Kanban card Signed-off-by: Anna No <anna.no@xored.com> * Reformat code Signed-off-by: Anna No <anna.no@xored.com> * Remove console output Signed-off-by: Anna No <anna.no@xored.com> * Board: Add Kanban Card edit mode Signed-off-by: Anna No <anna.no@xored.com>
This commit is contained in:
parent
70579c2f47
commit
c1a697ee5e
@ -342,7 +342,7 @@ export function createModel (builder: Builder): void {
|
|||||||
core.space.Model,
|
core.space.Model,
|
||||||
{
|
{
|
||||||
icon: board.icon.Card,
|
icon: board.icon.Card,
|
||||||
isInline: false,
|
isInline: true,
|
||||||
label: board.string.Cover,
|
label: board.string.Cover,
|
||||||
position: 70,
|
position: 70,
|
||||||
type: board.cardActionType.Cover,
|
type: board.cardActionType.Cover,
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
import type { Ref, WithLookup } from '@anticrm/core'
|
import type { Ref, WithLookup } from '@anticrm/core'
|
||||||
import notification from '@anticrm/notification'
|
import notification from '@anticrm/notification'
|
||||||
import { getClient, UserBoxList } from '@anticrm/presentation'
|
import { getClient, UserBoxList } from '@anticrm/presentation'
|
||||||
import { Button, Component, IconEdit, Label, showPanel, showPopup } from '@anticrm/ui'
|
import { Button, Component, EditBox, IconEdit, Label, showPanel, showPopup } from '@anticrm/ui'
|
||||||
import { ContextMenu } from '@anticrm/view-resources'
|
|
||||||
import board from '../plugin'
|
import board from '../plugin'
|
||||||
import { hasDate } from '../utils/CardUtils'
|
import { hasDate, updateCard } from '../utils/CardUtils'
|
||||||
import { getElementPopupAlignment } from '../utils/PopupUtils'
|
import { getElementPopupAlignment } from '../utils/PopupUtils'
|
||||||
|
import CardInlineActions from './editor/CardInlineActions.svelte'
|
||||||
import CardLabels from './editor/CardLabels.svelte'
|
import CardLabels from './editor/CardLabels.svelte'
|
||||||
import DatePresenter from './presenters/DatePresenter.svelte'
|
import DatePresenter from './presenters/DatePresenter.svelte'
|
||||||
|
|
||||||
@ -37,9 +37,20 @@
|
|||||||
let ref: HTMLElement
|
let ref: HTMLElement
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
let isEditMode = false
|
||||||
|
|
||||||
function showMenu (): void {
|
function exitEditMode (): void {
|
||||||
showPopup(ContextMenu, { object }, getElementPopupAlignment(ref, { h: 'right', v: 'top' }))
|
isEditMode = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function enterEditMode (): void {
|
||||||
|
isEditMode = true
|
||||||
|
showPopup(
|
||||||
|
CardInlineActions,
|
||||||
|
{ value: object },
|
||||||
|
getElementPopupAlignment(ref, { h: 'right', v: 'top' }),
|
||||||
|
exitEditMode
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCard () {
|
function showCard () {
|
||||||
@ -80,22 +91,34 @@
|
|||||||
<div class="ml-1">
|
<div class="ml-1">
|
||||||
<CardLabels bind:value={object} isInline={true} />
|
<CardLabels bind:value={object} isInline={true} />
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute mr-1 mt-1" style:top="0" style:right="0">
|
{#if !isEditMode}
|
||||||
<Button icon={IconEdit} kind="transparent" on:click={showMenu}/>
|
<div class="absolute mr-1 mt-1" style:top="0" style:right="0">
|
||||||
</div>
|
<Button icon={IconEdit} kind="transparent" on:click={enterEditMode} />
|
||||||
<div class="flex-between pb-2 ml-1" style:pointer-events={dragoverAttachment ? 'none' : 'all'} on:click={showCard}>
|
|
||||||
<div class="flex-row-center w-full" >
|
|
||||||
<div class="fs-title cursor-pointer">{object.title}</div>
|
|
||||||
<div class="ml-2">
|
|
||||||
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="flex-between pb-2 ml-1" style:pointer-events={dragoverAttachment ? 'none' : 'all'} on:click={showCard}>
|
||||||
|
{#if isEditMode}
|
||||||
|
<div class="fs-title text-lg">
|
||||||
|
<EditBox
|
||||||
|
bind:value={object.title}
|
||||||
|
maxWidth="39rem"
|
||||||
|
focus
|
||||||
|
on:change={() => updateCard(client, object, 'title', object?.title)} />
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex-row-center w-full">
|
||||||
|
<div class="fs-title cursor-pointer">{object.title}</div>
|
||||||
|
<div class="ml-2">
|
||||||
|
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-between mb-1" style:pointer-events={dragoverAttachment ? 'none' : 'all'}>
|
<div class="flex-between mb-1" style:pointer-events={dragoverAttachment ? 'none' : 'all'}>
|
||||||
<div class="float-left-box">
|
<div class="float-left-box">
|
||||||
{#if object.date && hasDate(object)}
|
{#if object.date && hasDate(object)}
|
||||||
<div class="float-left ml-1">
|
<div class="float-left ml-1">
|
||||||
<DatePresenter value={object.date} isInline={true} size="x-small" on:update={updateDate} />
|
<DatePresenter value={object.date} isInline={true} size="x-small" on:update={updateDate} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if (object.attachments ?? 0) > 0}
|
{#if (object.attachments ?? 0) > 0}
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
<!--
|
||||||
|
// 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 type { Card, CardAction } from '@anticrm/board'
|
||||||
|
import { getResource } from '@anticrm/platform'
|
||||||
|
import { getClient } from '@anticrm/presentation'
|
||||||
|
import { Button, Component } from '@anticrm/ui'
|
||||||
|
|
||||||
|
import { cardActionSorter, getCardActions } from '../../utils/CardActionUtils'
|
||||||
|
|
||||||
|
export let value: Card
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
let actions: CardAction[] = []
|
||||||
|
|
||||||
|
async function fetch () {
|
||||||
|
actions = []
|
||||||
|
const result = await getCardActions(client, { isInline: true })
|
||||||
|
for (const action of result) {
|
||||||
|
if (!action.supported) {
|
||||||
|
actions.push(action)
|
||||||
|
} else {
|
||||||
|
const supportedHandler = await getResource(action.supported)
|
||||||
|
if (supportedHandler(value, client)) {
|
||||||
|
actions.push(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actions = actions.sort(cardActionSorter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if value && !value.isArchived}
|
||||||
|
<div class="flex-col flex-gap-1">
|
||||||
|
{#each actions as action}
|
||||||
|
{#if action.component}
|
||||||
|
<Component is={action.component} props={{ object: value, isInline: true }}>
|
||||||
|
<slot />
|
||||||
|
</Component>
|
||||||
|
{:else}
|
||||||
|
<Button
|
||||||
|
icon={action.icon}
|
||||||
|
label={action.label}
|
||||||
|
kind="no-border"
|
||||||
|
justify="left"
|
||||||
|
on:click={async (e) => {
|
||||||
|
if (action.handler) {
|
||||||
|
const handler = await getResource(action.handler)
|
||||||
|
handler(value, client, e)
|
||||||
|
}
|
||||||
|
}} />
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
Loading…
Reference in New Issue
Block a user