mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
Add AddMultipleCardsPopup
(#1374)
Signed-off-by: Sergey Semenov <lvfx@ya.ru>
This commit is contained in:
parent
fa2e1b3229
commit
13750963c8
@ -21,6 +21,7 @@
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let labelParams: Record<string, any> = {}
|
||||
export let kind: 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'dangerous' = 'secondary'
|
||||
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'medium'
|
||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||
@ -67,7 +68,7 @@
|
||||
<Spinner />
|
||||
{:else}
|
||||
{#if label}
|
||||
<Label {label} />
|
||||
<Label {label} params={labelParams}/>
|
||||
{:else if $$slots.content}
|
||||
<slot name="content" />
|
||||
{/if}
|
||||
|
@ -53,6 +53,10 @@
|
||||
"NewListPlaceholder": "Enter list title...",
|
||||
"AddACard": "Add a card",
|
||||
"AddCard": "Add card",
|
||||
"CardTitlePlaceholder": "Enter a title for this card..."
|
||||
"CardTitlePlaceholder": "Enter a title for this card...",
|
||||
"Create": "Create",
|
||||
"CreateDescription": "If you want, we can create a card for every new line ({number}). You can also create one card with a long title.",
|
||||
"CreateSingle": "Just one card",
|
||||
"CreateMultiple": "Create {number} cards"
|
||||
}
|
||||
}
|
@ -53,6 +53,10 @@
|
||||
"NewListPlaceholder": "Введите заголовок колонки...",
|
||||
"AddACard": "Добавить карточку",
|
||||
"AddCard": "Добавить карточку",
|
||||
"CardTitlePlaceholder": "Введите заголовок для этой карточки..."
|
||||
"CardTitlePlaceholder": "Введите заголовок для этой карточки...",
|
||||
"Create": "Создать",
|
||||
"CreateDescription": "Можно создать отдельные карточки для каждой строки ({number}) или одну с длинным названием.",
|
||||
"CreateSingle": "Создать одну",
|
||||
"CreateMultiple": "Создать несколько ({number})"
|
||||
}
|
||||
}
|
@ -17,17 +17,20 @@
|
||||
import board from '../../plugin'
|
||||
import task, { calcRank } from '@anticrm/task'
|
||||
import { AttachedData, generateId, Ref, SortingOrder, Space } from '@anticrm/core'
|
||||
import { IconAdd, Button } from '@anticrm/ui'
|
||||
import { IconAdd, Button, showPopup, AnySvelteComponent } from '@anticrm/ui'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import AddCardEditor from './AddCardEditor.svelte'
|
||||
import AddMultipleCardsPopup from './AddMultipleCardsPopup.svelte'
|
||||
|
||||
export let space: Ref<Space>
|
||||
export let state: any
|
||||
|
||||
let anchorRef: HTMLDivElement
|
||||
const client = getClient()
|
||||
let newCardId = generateId() as Ref<BoardCard>
|
||||
|
||||
async function addCard(title: string) {
|
||||
const newCardId = generateId() as Ref<BoardCard>
|
||||
|
||||
const sequence = await client.findOne(task.class.Sequence, { attachedTo: board.class.Card })
|
||||
if (sequence === undefined) {
|
||||
throw new Error('sequence object not found')
|
||||
@ -52,9 +55,51 @@
|
||||
location: ''
|
||||
}
|
||||
|
||||
await client.addCollection(board.class.Card, space, space, board.class.Board, 'cards', value, newCardId)
|
||||
return client.addCollection(board.class.Card, space, space, board.class.Board, 'cards', value, newCardId)
|
||||
}
|
||||
|
||||
newCardId = generateId() as Ref<BoardCard>
|
||||
async function addCards(title: string, checkNewLine: boolean = false) {
|
||||
if (!checkNewLine) {
|
||||
return addCard(title.replace('\n', ' '))
|
||||
}
|
||||
|
||||
const splittedTitle = title.split('\n')
|
||||
|
||||
if (splittedTitle.length === 1) {
|
||||
return addCard(splittedTitle[0])
|
||||
}
|
||||
|
||||
return new Promise<'single' | 'multiple' | 'close'>((resolve) => {
|
||||
const popupOpts = {
|
||||
onAddSingle: () => {
|
||||
closePopup()
|
||||
resolve('single')
|
||||
},
|
||||
onAddMultiple: () => {
|
||||
closePopup()
|
||||
resolve('multiple')
|
||||
},
|
||||
onClose: () => {
|
||||
closePopup()
|
||||
resolve('close')
|
||||
},
|
||||
cardsNumber: splittedTitle.length
|
||||
}
|
||||
|
||||
const closePopup = showPopup(AddMultipleCardsPopup, popupOpts, anchorRef, () => resolve('close'))
|
||||
}).then((value) => {
|
||||
if (value === 'single' || value === 'close') {
|
||||
return addCard(title.replace('\n', ' ')).then((res) => {
|
||||
if (value === 'close') {
|
||||
onClose()
|
||||
}
|
||||
|
||||
return [res]
|
||||
})
|
||||
}
|
||||
|
||||
return Promise.all(splittedTitle.map((titlePart) => addCard(titlePart)))
|
||||
})
|
||||
}
|
||||
|
||||
let isOpened = false
|
||||
@ -70,8 +115,9 @@
|
||||
</script>
|
||||
|
||||
<div class="flex-col step-tb75">
|
||||
<div bind:this={anchorRef} style:position="absolute" />
|
||||
{#if isOpened}
|
||||
<AddCardEditor {onClose} onAdd={addCard} />
|
||||
<AddCardEditor {onClose} onAdd={addCards} />
|
||||
{:else}
|
||||
<Button
|
||||
icon={IconAdd}
|
||||
|
@ -3,8 +3,9 @@
|
||||
import board from '../../plugin'
|
||||
|
||||
export let onClose: () => void
|
||||
export let onAdd: (title: string) => Promise<void>
|
||||
export let onAdd: (title: string, checkNewLine?: boolean) => Promise<any>
|
||||
|
||||
let isEditing = false
|
||||
let title = ''
|
||||
let inputRef: TextArea
|
||||
let openedContainerRef: HTMLDivElement
|
||||
@ -15,12 +16,13 @@
|
||||
return
|
||||
}
|
||||
|
||||
await onAdd(title)
|
||||
isEditing = false
|
||||
await onAdd(title, true)
|
||||
title = ''
|
||||
}
|
||||
|
||||
async function onClickOutside(e: any) {
|
||||
if (openedContainerRef && !openedContainerRef.contains(e.target) && !e.defaultPrevented) {
|
||||
if (openedContainerRef && !openedContainerRef.contains(e.target) && !e.defaultPrevented && isEditing) {
|
||||
if (title) {
|
||||
await onAdd(title)
|
||||
}
|
||||
@ -39,6 +41,7 @@
|
||||
};
|
||||
|
||||
$: if (inputRef && !title) {
|
||||
isEditing = true
|
||||
inputRef.focus()
|
||||
}
|
||||
</script>
|
||||
|
@ -0,0 +1,52 @@
|
||||
<script lang="ts">
|
||||
import board from '../../plugin'
|
||||
import { Button, ActionIcon, IconClose, Label } from '@anticrm/ui'
|
||||
|
||||
export let cardsNumber: number
|
||||
export let onAddSingle: () => void
|
||||
export let onAddMultiple: () => void
|
||||
export let onClose: () => void
|
||||
</script>
|
||||
|
||||
<div class="antiPopup container p-3">
|
||||
<div class="flex-row-center header">
|
||||
<div class="flex-center flex-grow">
|
||||
<Label label={board.string.Create} />
|
||||
</div>
|
||||
<div class="close-icon">
|
||||
<ActionIcon icon={IconClose} size={'small'} action={onClose} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<Label label={board.string.CreateDescription} params={{ number: cardsNumber }} />
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<Button
|
||||
label={board.string.CreateMultiple}
|
||||
labelParams={{ number: cardsNumber }}
|
||||
kind="no-border"
|
||||
width={'100%'}
|
||||
on:click={onAddMultiple}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<Button label={board.string.CreateSingle} kind="no-border" width={'100%'} on:click={onAddSingle} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
max-width: 20rem;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
position: absolute;
|
||||
top: .75rem;
|
||||
right: .75rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding-bottom: .5rem;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
</style>
|
@ -74,7 +74,11 @@ export default mergeIds(boardId, board, {
|
||||
NewListPlaceholder: '' as IntlString,
|
||||
AddACard: '' as IntlString,
|
||||
AddCard: '' as IntlString,
|
||||
CardTitlePlaceholder: '' as IntlString
|
||||
CardTitlePlaceholder: '' as IntlString,
|
||||
Create: '' as IntlString,
|
||||
CreateDescription: '' as IntlString,
|
||||
CreateSingle: '' as IntlString,
|
||||
CreateMultiple: '' as IntlString
|
||||
},
|
||||
component: {
|
||||
CreateCustomer: '' as AnyComponent,
|
||||
|
Loading…
Reference in New Issue
Block a user