diff --git a/packages/backend/src/apps/miro/actions/create-card-widget/index.ts b/packages/backend/src/apps/miro/actions/create-card-widget/index.ts new file mode 100644 index 00000000..c1cb4746 --- /dev/null +++ b/packages/backend/src/apps/miro/actions/create-card-widget/index.ts @@ -0,0 +1,168 @@ +import defineAction from '../../../../helpers/define-action'; + +type Body = { + data: { + title: string; + description?: string; + dueDate?: string; + }; + style?: { + cardTheme?: string; + }; + parent: { + id: string; + }; +}; + +export default defineAction({ + name: 'Create card widget', + key: 'createCardWidget', + description: 'Creates a new card widget on an existing board.', + arguments: [ + { + label: 'Board', + key: 'boardId', + type: 'dropdown' as const, + required: true, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listBoards', + }, + ], + }, + }, + { + label: 'Frame', + key: 'frameId', + type: 'dropdown' as const, + required: true, + dependsOn: ['parameters.boardId'], + description: + 'You need to create a frame prior to this step. Switch frame to grid mode to avoid cards overlap.', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listFrames', + }, + { + name: 'parameters.boardId', + value: '{parameters.boardId}', + }, + ], + }, + }, + { + label: 'Card Title', + key: 'cardTitle', + type: 'string' as const, + required: true, + description: '', + variables: true, + }, + { + label: 'Card Title Link', + key: 'cardTitleLink', + type: 'string' as const, + required: false, + description: '', + variables: true, + }, + { + label: 'Card Description', + key: 'cardDescription', + type: 'string' as const, + required: false, + description: '', + variables: true, + }, + { + label: 'Card Due Date', + key: 'cardDueDate', + type: 'string' as const, + required: false, + description: + 'format: date-time. Example value: 2023-10-12 22:00:55+00:00', + variables: true, + }, + { + label: 'Card Border Color', + key: 'cardBorderColor', + type: 'dropdown' as const, + required: false, + description: 'In hex format. Default is blue (#2399F3).', + variables: true, + options: [ + { label: 'white', value: '#FFFFFF' }, + { label: 'yellow', value: '#FEF445' }, + { label: 'orange', value: '#FAC710' }, + { label: 'red', value: '#F24726' }, + { label: 'bright red', value: '#DA0063' }, + { label: 'light gray', value: '#E6E6E6' }, + { label: 'gray', value: '#808080' }, + { label: 'black', value: '#1A1A1A' }, + { label: 'light green', value: '#CEE741' }, + { label: 'green', value: '#8FD14F' }, + { label: 'dark green', value: '#0CA789' }, + { label: 'light blue', value: '#12CDD4' }, + { label: 'blue', value: '#2D9BF0' }, + { label: 'dark blue', value: '#414BB2' }, + { label: 'purple', value: '#9510AC' }, + { label: 'dark purple', value: '#652CB3' }, + ], + }, + ], + + async run($) { + const { + boardId, + frameId, + cardTitle, + cardTitleLink, + cardDescription, + cardDueDate, + cardBorderColor, + } = $.step.parameters; + + let title; + if (cardTitleLink) { + title = `${cardTitle}`; + } else { + title = cardTitle; + } + + const body: Body = { + data: { + title: title as string, + description: cardDescription as string, + }, + style: {}, + parent: { + id: frameId as string, + }, + }; + + if (cardBorderColor) { + body.style.cardTheme = cardBorderColor as string; + } + + if (cardDueDate) { + body.data.dueDate = cardDueDate as string; + } + + const response = await $.http.post(`/v2/boards/${boardId}/cards`, body); + + $.setActionItem({ + raw: response.data, + }); + }, +}); diff --git a/packages/backend/src/apps/miro/actions/index.ts b/packages/backend/src/apps/miro/actions/index.ts index 24f3edaf..896dd73f 100644 --- a/packages/backend/src/apps/miro/actions/index.ts +++ b/packages/backend/src/apps/miro/actions/index.ts @@ -1,4 +1,5 @@ import copyBoard from './copy-board'; import createBoard from './create-board'; +import createCardWidget from './create-card-widget'; -export default [copyBoard, createBoard]; +export default [copyBoard, createBoard, createCardWidget]; diff --git a/packages/backend/src/apps/miro/dynamic-data/index.ts b/packages/backend/src/apps/miro/dynamic-data/index.ts index b1d11dac..ade1d40a 100644 --- a/packages/backend/src/apps/miro/dynamic-data/index.ts +++ b/packages/backend/src/apps/miro/dynamic-data/index.ts @@ -1,3 +1,4 @@ import listBoards from './list-boards'; +import listFrames from './list-frames'; -export default [listBoards]; +export default [listBoards, listFrames]; diff --git a/packages/backend/src/apps/miro/dynamic-data/list-frames/index.ts b/packages/backend/src/apps/miro/dynamic-data/list-frames/index.ts new file mode 100644 index 00000000..8a234c1a --- /dev/null +++ b/packages/backend/src/apps/miro/dynamic-data/list-frames/index.ts @@ -0,0 +1,44 @@ +import { IGlobalVariable, IJSONObject } from '@automatisch/types'; + +export default { + name: 'List frames', + key: 'listFrames', + + async run($: IGlobalVariable) { + const frames: { + data: IJSONObject[]; + } = { + data: [], + }; + + const boardId = $.step.parameters.boardId; + + if (!boardId) { + return { data: [] }; + } + + let next; + do { + const { + data: { data, links }, + } = await $.http.get(`/v2/boards/${boardId}/items`); + + next = links?.next; + + const allFrames = data.filter( + (item: IJSONObject) => item.type === 'frame' + ); + + if (allFrames.length) { + for (const frame of allFrames) { + frames.data.push({ + value: frame.id, + name: frame.data.title, + }); + } + } + } while (next); + + return frames; + }, +}; diff --git a/packages/docs/pages/apps/miro/actions.md b/packages/docs/pages/apps/miro/actions.md index b20693f3..6cb8da69 100644 --- a/packages/docs/pages/apps/miro/actions.md +++ b/packages/docs/pages/apps/miro/actions.md @@ -5,6 +5,8 @@ items: desc: Creates a new board. - name: Copy board desc: Creates a copy of an existing board. + - name: Create card widget + desc: Creates a new card widget on an existing board. ---