Skip to content

Commit

Permalink
1265: Make Card Actions extensible
Browse files Browse the repository at this point in the history
Signed-off-by: Anna No <anna.no@xored.com>
  • Loading branch information
annano committed Apr 7, 2022
1 parent a53277f commit a5aaa1b
Show file tree
Hide file tree
Showing 6 changed files with 303 additions and 107 deletions.
181 changes: 177 additions & 4 deletions models/board/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@
//

// To help typescript locate view plugin properly
import type { Board, Card } from '@anticrm/board'
import type { Board, Card, CardAction } from '@anticrm/board'
import type { Employee } from '@anticrm/contact'
import { Doc, FindOptions, IndexKind, Ref } from '@anticrm/core'
import { Doc, DOMAIN_MODEL, FindOptions, IndexKind, Ref } from '@anticrm/core'
import { Builder, Collection, Index, Model, Prop, TypeMarkup, TypeRef, TypeString, UX } from '@anticrm/model'
import attachment from '@anticrm/model-attachment'
import chunter from '@anticrm/model-chunter'
import contact from '@anticrm/model-contact'
import core from '@anticrm/model-core'
import core, { TDoc } from '@anticrm/model-core'
import task, { TSpaceWithStates, TTask } from '@anticrm/model-task'
import view from '@anticrm/model-view'
import workbench from '@anticrm/model-workbench'
import { Asset, IntlString, Resource } from '@anticrm/platform'
import type {} from '@anticrm/view'
import board from './plugin'

Expand Down Expand Up @@ -64,8 +65,21 @@ export class TCard extends TTask implements Card {
members!: Ref<Employee>[]
}

@Model(board.class.CardAction, core.class.Doc, DOMAIN_MODEL)
export class TCardAction extends TDoc implements CardAction {
hint?: IntlString
icon!: Asset
isInline?: boolean
isTransparent?: boolean
label!: IntlString
position!: number
type!: string
handler?: Resource<(card: Card) => void>
supported?: Resource<(card: Card) => boolean>
}

export function createModel (builder: Builder): void {
builder.createModel(TBoard, TCard)
builder.createModel(TBoard, TCard, TCardAction)

builder.mixin(board.class.Board, core.class.Class, workbench.mixin.SpaceView, {
view: {
Expand Down Expand Up @@ -187,6 +201,165 @@ export function createModel (builder: Builder): void {
},
board.viewlet.Kanban
)

// card actions
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: true,
label: board.string.Members,
position: 10,
type: board.cardActionType.AddToCard,
handler: board.cardActionHandler.Members
},
board.cardAction.Members
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: true,
label: board.string.Labels,
position: 20,
type: board.cardActionType.AddToCard,
handler: board.cardActionHandler.Labels
},
board.cardAction.Labels
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: false,
label: board.string.Checklist,
position: 30,
type: board.cardActionType.AddToCard,
handler: board.cardActionHandler.Checklist
},
board.cardAction.Checklist
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: true,
label: board.string.Dates,
position: 40,
type: board.cardActionType.AddToCard,
handler: board.cardActionHandler.Dates
},
board.cardAction.Dates
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: false,
label: board.string.Attachments,
position: 50,
type: board.cardActionType.AddToCard,
handler: board.cardActionHandler.Attachments
},
board.cardAction.Attachments
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: false,
label: board.string.CustomFields,
position: 60,
type: board.cardActionType.AddToCard,
handler: board.cardActionHandler.CustomFields
},
board.cardAction.CustomFields
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: false,
isTransparent: true,
label: board.string.AddButton,
position: 70,
type: board.cardActionType.Automation,
handler: board.cardActionHandler.AddButton
},
board.cardAction.AddButton
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: true,
label: board.string.Move,
position: 80,
type: board.cardActionType.Action,
handler: board.cardActionHandler.Move
},
board.cardAction.Move
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: true,
label: board.string.Copy,
position: 90,
type: board.cardActionType.Action,
handler: board.cardActionHandler.Copy
},
board.cardAction.Copy
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: false,
label: board.string.MakeTemplate,
position: 100,
type: board.cardActionType.Action,
handler: board.cardActionHandler.MakeTemplate
},
board.cardAction.MakeTemplate
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: false,
label: board.string.Watch,
position: 110,
type: board.cardActionType.Action,
handler: board.cardActionHandler.Watch
},
board.cardAction.Watch
)
builder.createDoc(
board.class.CardAction,
core.space.Model,
{
icon: board.icon.Card,
isInline: true,
label: board.string.Archive,
position: 120,
type: board.cardActionType.Action,
handler: board.cardActionHandler.Archive
},
board.cardAction.Archive
)
}

export { createDeps } from './creation'
Expand Down
3 changes: 1 addition & 2 deletions models/board/src/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ async function createSpace (tx: TxOperations): Promise<void> {
}

export const boardOperation: MigrateOperation = {
async migrate (client: MigrationClient): Promise<void> {
},
async migrate (client: MigrationClient): Promise<void> {},
async upgrade (client: MigrationUpgradeClient): Promise<void> {
const ops = new TxOperations(client, core.account.System)
await createSpace(ops)
Expand Down
32 changes: 30 additions & 2 deletions models/board/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
// limitations under the License.
//

import { boardId } from '@anticrm/board'
import { boardId, Card, CardAction } from '@anticrm/board'
import board from '@anticrm/board-resources/src/plugin'
import type { Ref, Space } from '@anticrm/core'
import { mergeIds } from '@anticrm/platform'
import { mergeIds, Resource } from '@anticrm/platform'
import { KanbanTemplate, Sequence } from '@anticrm/task'
import type { AnyComponent } from '@anticrm/ui'
import { ViewletDescriptor } from '@anticrm/view'
Expand All @@ -32,6 +32,34 @@ export default mergeIds(boardId, board, {
Cards: '' as AnyComponent,
KanbanView: '' as AnyComponent
},
cardAction: {
Members: '' as Ref<CardAction>,
Labels: '' as Ref<CardAction>,
Checklist: '' as Ref<CardAction>,
Dates: '' as Ref<CardAction>,
Attachments: '' as Ref<CardAction>,
CustomFields: '' as Ref<CardAction>,
AddButton: '' as Ref<CardAction>,
Move: '' as Ref<CardAction>,
Copy: '' as Ref<CardAction>,
MakeTemplate: '' as Ref<CardAction>,
Watch: '' as Ref<CardAction>,
Archive: '' as Ref<CardAction>
},
cardActionHandler: {
Members: '' as Resource<(card: Card) => void>,
Labels: '' as Resource<(card: Card) => void>,
Checklist: '' as Resource<(card: Card) => void>,
Dates: '' as Resource<(card: Card) => void>,
Attachments: '' as Resource<(card: Card) => void>,
CustomFields: '' as Resource<(card: Card) => void>,
AddButton: '' as Resource<(card: Card) => void>,
Move: '' as Resource<(card: Card) => void>,
Copy: '' as Resource<(card: Card) => void>,
MakeTemplate: '' as Resource<(card: Card) => void>,
Watch: '' as Resource<(card: Card) => void>,
Archive: '' as Resource<(card: Card) => void>
},
space: {
DefaultBoard: '' as Ref<Space>
},
Expand Down
81 changes: 66 additions & 15 deletions plugins/board-resources/src/components/editor/CardActions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,81 @@
// limitations under the License.
-->
<script lang="ts">
import type { Card } from '@anticrm/board'
import board from '@anticrm/board'
import type { Card, CardAction } from '@anticrm/board'
import { IntlString, getResource } from '@anticrm/platform'
import { getClient } from '@anticrm/presentation'
import { Button, Label } from '@anticrm/ui'
import { getEditorCardActionGroups } from '../../utils/CardActionUtils'
import plugin from '../../plugin'
import { cardActionSorter, getCardActions } from '../../utils/CardActionUtils'
export let value: Card
const client = getClient()
let addToCardActions: CardAction[] = []
let automationActions: CardAction[] = []
let actions: CardAction[] = []
let actionGroups: { label: IntlString; actions: CardAction[] }[] = []
getCardActions(client).then((result) => {
result.forEach(async (action) => {
let supported = true
if (action.supported) {
const supportedHandler = await getResource(action.supported)
supported = supportedHandler(value)
}
if (supported) {
if (action.type === board.cardActionType.AddToCard) {
addToCardActions.push(action)
} else if (action.type === board.cardActionType.Automation) {
automationActions.push(action)
} else if (action.type === board.cardActionType.Action) {
actions.push(action)
}
}
})
actionGroups = [
{
label: plugin.string.AddToCard,
actions: addToCardActions.sort(cardActionSorter)
},
{
label: plugin.string.Automation,
actions: automationActions.sort(cardActionSorter)
},
{
label: plugin.string.Actions,
actions: actions.sort(cardActionSorter)
}
]
})
const actionGroups = getEditorCardActionGroups(value)
</script>

{#if value}
<div class="flex-col flex-gap-3">
{#each actionGroups as group}
<div class="flex-col flex-gap-1">
<Label label={group.label} />
{#each group.actions as action}
<Button
icon={action.icon}
label={action.label}
kind={action.isTransparent ? 'transparent' : 'no-border'}
justify="left"
on:click={() => action.handler?.(value)}
/>
{/each}
</div>
{#if group.actions.length > 0}
<div class="flex-col flex-gap-1">
<Label label={group.label} />
{#each group.actions as action}
<Button
icon={action.icon}
label={action.label}
kind={action.isTransparent ? 'transparent' : 'no-border'}
justify="left"
on:click={async () => {
if (action.handler) {
const handler = await getResource(action.handler)
handler(value)
}
}} />
{/each}
</div>
{/if}
{/each}
</div>
{/if}
Loading

0 comments on commit a5aaa1b

Please sign in to comment.