Board: Add convert checklist to card action (#1805)

This commit is contained in:
Alex 2022-05-21 18:20:34 +07:00 committed by GitHub
parent 549949b392
commit 0e11085407
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 107 additions and 8 deletions

View File

@ -420,6 +420,24 @@ export function createModel (builder: Builder): void {
builder.mixin(board.class.Card, core.class.Class, view.mixin.IgnoreActions, {
actions: [view.action.Delete, task.action.Move]
})
// TODO: update query when nested query is available
createAction(
builder,
{
action: board.actionImpl.ConvertToCard,
label: board.string.ConvertToCard,
icon: board.icon.Card,
category: board.category.Card,
query: {
attachedToClass: task.class.TodoItem
},
input: 'any',
target: task.class.TodoItem,
context: { mode: ['context', 'browser'] }
},
board.action.ConvertToCard
)
}
export { boardOperation } from './migration'

View File

@ -20,7 +20,7 @@ import type { Ref, Space } from '@anticrm/core'
import { IntlString, mergeIds } from '@anticrm/platform'
import { KanbanTemplate, Sequence } from '@anticrm/task'
import type { AnyComponent } from '@anticrm/ui'
import { ViewletDescriptor } from '@anticrm/view'
import { Action, ViewAction, ViewletDescriptor } from '@anticrm/view'
export default mergeIds(boardId, board, {
component: {
@ -55,6 +55,13 @@ export default mergeIds(boardId, board, {
Table: '' as Ref<ViewletDescriptor>
},
string: {
CommonBoardPreference: '' as IntlString
CommonBoardPreference: '' as IntlString,
ConvertToCard: '' as IntlString
},
action: {
ConvertToCard: '' as Ref<Action>
},
actionImpl: {
ConvertToCard: '' as ViewAction
}
})

View File

@ -106,6 +106,7 @@
"Size": "Size",
"RemoveCover": "Remove cover",
"DeleteChecklist": "Delete checklist",
"DeleteChecklistConfirm": "Deleting a checklist is permanent and there is no way to get it back."
"DeleteChecklistConfirm": "Deleting a checklist is permanent and there is no way to get it back.",
"ConvertToCard": "Convert to card"
}
}

View File

@ -106,6 +106,7 @@
"Size": "Размер",
"RemoveCover": "Удалить обложку",
"DeleteChecklist": "Удалить список задач",
"DeleteChecklistConfirm": "Удаление списка задач необратимо, и не будет возможности его вернуть."
"DeleteChecklistConfirm": "Удаление списка задач необратимо, и не будет возможности его вернуть.",
"ConvertToCard": "Конвертировать в карточку"
}
}

View File

@ -117,7 +117,7 @@
}
function showItemMenu (item: TodoItem, e?: Event) {
showPopup(ContextMenu, { object: item, baseMenuClass: board.class.Card }, getPopupAlignment(e))
showPopup(ContextMenu, { object: item }, getPopupAlignment(e))
}
$: checklistItemsQuery.query(task.class.TodoItem, { space: value.space, attachedTo: value._id }, (result) => {

View File

@ -10,7 +10,7 @@
export let size: 'small' | 'medium' | 'large' = 'small'
const todoListQuery = createQuery()
let todoLists: Ref<TodoItem>[]
let todoLists: Ref<TodoItem>[] = []
$: todoListQuery.query(task.class.TodoItem, { space: value.space, attachedTo: value._id }, (result) => {
todoLists = result.map(({ _id }) => _id)
})
@ -19,6 +19,7 @@
$: query.query(task.class.TodoItem, { space: value.space, attachedTo: { $in: todoLists } }, (result) => {
total = result.total
done = result.filter((t) => t.done).length
if (!total) return
item = result.reduce((min, cur) =>
cur.dueTo === null ? min : min.dueTo === null || cur.dueTo < min.dueTo ? cur : min
)

View File

@ -14,6 +14,9 @@
// limitations under the License.
//
import { Resources } from '@anticrm/platform'
import { TodoItem } from '@anticrm/task'
import { getClient } from '@anticrm/presentation'
import board from '@anticrm/board'
import BoardPresenter from './components/BoardPresenter.svelte'
import CardPresenter from './components/CardPresenter.svelte'
@ -37,6 +40,23 @@ import TableView from './components/TableView.svelte'
import UserBoxList from './components/UserBoxList.svelte'
import CardLabels from './components/editor/CardLabels.svelte'
import CardCoverEditor from './components/popups/CardCoverEditor.svelte'
import { createCard, getCardFromTodoItem } from './utils/CardUtils'
async function ConvertToCard (object: TodoItem): Promise<void> {
const client = getClient()
const todoItemCard = await getCardFromTodoItem(client, object)
if (todoItemCard === undefined) return
const date =
object.dueTo === null
? {}
: { date: { _class: board.class.CardDate, dueDate: object.dueTo, isChecked: object.done } }
await createCard(client, todoItemCard.space, todoItemCard.state, {
title: object.name,
assignee: object.assignee,
...date
})
await client.remove(object)
}
export default async (): Promise<Resources> => ({
component: {
@ -63,5 +83,8 @@ export default async (): Promise<Resources> => ({
CoverActionPopup: CardCoverEditor,
MoveActionPopup: MoveCard,
CopyActionPopup: CopyCard
},
actionImpl: {
ConvertToCard
}
})

View File

@ -1,10 +1,58 @@
import { Card } from '@anticrm/board'
import { Employee, EmployeeAccount } from '@anticrm/contact'
import { TxOperations as Client, TxResult, getCurrentAccount, Ref } from '@anticrm/core'
import {
TxOperations as Client,
TxResult,
getCurrentAccount,
Ref,
Space,
AttachedData,
SortingOrder
} from '@anticrm/core'
import { showPanel } from '@anticrm/ui'
import task, { calcRank, State, TodoItem } from '@anticrm/task'
import board from '../plugin'
export async function createCard (
client: Client,
space: Ref<Space>,
state: Ref<State>,
attribues: Partial<AttachedData<Card>>
): Promise<Ref<Card>> {
const sequence = await client.findOne(task.class.Sequence, { attachedTo: board.class.Card })
if (sequence === undefined) {
throw new Error('sequence object not found')
}
const lastOne = await client.findOne(board.class.Card, { state }, { sort: { rank: SortingOrder.Descending } })
const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)
const value: AttachedData<Card> = {
title: '',
state,
doneState: null,
number: (incResult as any).object.sequence,
rank: calcRank(lastOne, undefined),
assignee: null,
description: '',
labels: [],
...attribues
}
return await client.addCollection(board.class.Card, space, space, board.class.Board, 'cards', value)
}
export async function getCardFromTodoItem (client: Client, todoItem: TodoItem | undefined): Promise<Card | undefined> {
if (todoItem === undefined) return
if (todoItem.attachedToClass === todoItem._class) {
return await getCardFromTodoItem(
client,
await client.findOne(todoItem._class, { _id: todoItem.attachedTo as Ref<TodoItem> })
)
}
return await client.findOne(board.class.Card, { _id: todoItem.attachedTo as Ref<Card> })
}
export function updateCard (client: Client, card: Card, field: string, value: any): Promise<TxResult> | undefined {
if (card === undefined) {
return