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:
Anna No 2022-04-21 22:39:33 +07:00 committed by GitHub
parent 70579c2f47
commit c1a697ee5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 16 deletions

View File

@ -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,

View File

@ -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}

View File

@ -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}