Add CardCover type (#1856)

This commit is contained in:
Alex 2022-05-24 19:56:42 +07:00 committed by GitHub
parent 9800bc93c6
commit b470ec3769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 74 additions and 34 deletions

View File

@ -14,9 +14,9 @@
//
// To help typescript locate view plugin properly
import type { Board, Card, CardLabel, MenuPage, CommonBoardPreference } from '@anticrm/board'
import type { Board, Card, CardLabel, MenuPage, CommonBoardPreference, CardCover } from '@anticrm/board'
import type { Employee } from '@anticrm/contact'
import { DOMAIN_MODEL, IndexKind, Markup, Ref } from '@anticrm/core'
import { DOMAIN_MODEL, IndexKind, Markup, Ref, Type } from '@anticrm/core'
import {
ArrOf,
Builder,
@ -33,7 +33,7 @@ import {
import attachment from '@anticrm/model-attachment'
import chunter from '@anticrm/model-chunter'
import contact from '@anticrm/model-contact'
import core, { TAttachedDoc, TDoc } from '@anticrm/model-core'
import core, { TAttachedDoc, TDoc, TType } from '@anticrm/model-core'
import task, { TSpaceWithStates, TTask } from '@anticrm/model-task'
import view, { actionTemplates, createAction } from '@anticrm/model-view'
import workbench, { Application } from '@anticrm/model-workbench'
@ -57,6 +57,17 @@ export class TCardLabel extends TAttachedDoc implements CardLabel {
isHidden?: boolean
}
function TypeCardCover (): Type<CardCover> {
return { _class: board.class.CardCover, label: board.string.Cover }
}
@UX(board.string.Cover)
@Model(board.class.CardCover, core.class.Type)
export class TCardCover extends TType implements CardCover {
size!: 'large' | 'small'
color!: number
}
@Model(board.class.CommonBoardPreference, preference.class.Preference)
export class TCommonBoardPreference extends TPreference implements CommonBoardPreference {
@Prop(TypeRef(workbench.class.Application), board.string.CommonBoardPreference)
@ -97,6 +108,9 @@ export class TCard extends TTask implements Card {
@Prop(ArrOf(TypeRef(contact.class.Employee)), board.string.Members)
members?: Ref<Employee>[]
@Prop(TypeCardCover(), board.string.Cover)
cover?: CardCover
}
@Model(board.class.MenuPage, core.class.Doc, DOMAIN_MODEL)
@ -107,7 +121,7 @@ export class TMenuPage extends TDoc implements MenuPage {
}
export function createModel (builder: Builder): void {
builder.createModel(TBoard, TCard, TCardLabel, TMenuPage, TCommonBoardPreference)
builder.createModel(TBoard, TCard, TCardLabel, TMenuPage, TCommonBoardPreference, TCardCover)
builder.createDoc(board.class.MenuPage, core.space.Model, {
component: board.component.Archive,
@ -214,6 +228,14 @@ export function createModel (builder: Builder): void {
presenter: board.component.BoardPresenter
})
builder.mixin(board.class.CardCover, core.class.Class, view.mixin.AttributePresenter, {
presenter: board.component.CardCoverPresenter
})
builder.mixin(board.class.CardCover, core.class.Class, view.mixin.AttributeEditor, {
editor: board.component.CardCoverEditor
})
builder.createDoc(
task.class.KanbanTemplateSpace,
core.space.Model,

View File

@ -38,7 +38,9 @@ export default mergeIds(boardId, board, {
DatesActionPopup: '' as AnyComponent,
CoverActionPopup: '' as AnyComponent,
MoveActionPopup: '' as AnyComponent,
CopyActionPopup: '' as AnyComponent
CopyActionPopup: '' as AnyComponent,
CardCoverPresenter: '' as AnyComponent,
CardCoverEditor: '' as AnyComponent
},
space: {
DefaultBoard: '' as Ref<Space>

View File

@ -48,7 +48,7 @@
let handleMove: (e: Event) => void
let checklists: TodoItem[] = []
const mixins: Mixin<Doc>[] = []
const ignoreKeys = ['isArchived', 'location', 'title', 'description', 'state', 'members', 'doneState', 'number']
const ignoreKeys = ['isArchived', 'location', 'title', 'description', 'state', 'members', 'number', 'assignee']
function change (field: string, value: any) {
if (object) {

View File

@ -19,13 +19,12 @@
import { Employee } from '@anticrm/contact'
import { Ref } from '@anticrm/core'
import { getClient } from '@anticrm/presentation'
import { Button, CheckBox, Label, IconAdd } from '@anticrm/ui'
import { CheckBox, Label } from '@anticrm/ui'
import { invokeAction } from '@anticrm/view-resources'
import plugin from '../../plugin'
import { getCardActions } from '../../utils/CardActionUtils'
import { updateCardMembers } from '../../utils/CardUtils'
import ColorPresenter from '../presenters/ColorPresenter.svelte'
import UserBoxList from '../UserBoxList.svelte'
import CardLabels from './CardLabels.svelte'
@ -76,15 +75,5 @@
</div>
<CardLabels {value} />
</div>
<div class="flex-row-stretch flex-gap-1 items-center">
<div class="label w-24">
<Label label={plugin.string.Cover} />
</div>
{#if !value.cover?.color}
<Button icon={IconAdd} kind="no-border" on:click={coverHandler} />
{:else}
<ColorPresenter value={value.cover.color} on:click={coverHandler} />
{/if}
</div>
</div>
{/if}

View File

@ -0,0 +1,19 @@
<script lang="ts">
import { CardCover } from '@anticrm/board'
import { Button, eventToHTMLElement, IconAdd, showPopup } from '@anticrm/ui'
import CardCoverPicker from '../popups/CardCoverPicker.svelte'
import CardCoverPresenter from '../presenters/CardCoverPresenter.svelte'
export let value: CardCover
export let onChange: (value: any) => void
const coverHandler = (ev: MouseEvent) => {
showPopup(CardCoverPicker, { value, onChange }, eventToHTMLElement(ev))
}
</script>
{#if value}
<CardCoverPresenter {value} on:click={coverHandler} />
{:else}
<Button icon={IconAdd} kind="no-border" on:click={coverHandler} />
{/if}

View File

@ -1,25 +1,22 @@
<script lang="ts">
import { Card, CardCover } from '@anticrm/board'
import { getClient } from '@anticrm/presentation'
import { CardCover } from '@anticrm/board'
import { Button, hexColorToNumber, Icon, Label, IconCheck, IconClose } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import board from '../../plugin'
import { getBoardAvailableColors } from '../../utils/BoardUtils'
import ColorPresenter from '../presenters/ColorPresenter.svelte'
export let value: Card
let cover = value.cover
export let value: CardCover | undefined | null
export let onChange: (e: any) => void
const dispatch = createEventDispatcher()
const client = getClient()
const colorGroups = (function chunk (colors: number[]): number[][] {
return colors.length ? [colors.slice(0, 5), ...chunk(colors.slice(5))] : []
})(getBoardAvailableColors().map(hexColorToNumber))
function updateCover (newCover?: Partial<CardCover>) {
cover = newCover ? { size: 'small', ...cover, ...newCover } : null
client.update(value, { cover })
value = newCover ? { size: 'small', color: colorGroups[0][0], ...value, ...newCover } : null
onChange(value)
}
</script>
@ -49,7 +46,7 @@
<Button
icon={board.icon.Card}
width="40%"
disabled={!cover || cover.size === 'small'}
disabled={!value || value.size === 'small'}
on:click={() => {
updateCover({ size: 'small' })
}}
@ -57,7 +54,7 @@
<Button
icon={board.icon.Board}
width="40%"
disabled={!cover || cover.size === 'large'}
disabled={!value || value.size === 'large'}
on:click={() => {
updateCover({ size: 'large' })
}}
@ -89,7 +86,7 @@
updateCover({ color })
}}
>
{#if cover && cover.color === color}
{#if value && value.color === color}
<div class="flex-center flex-grow fs-title h-full">
<Icon icon={IconCheck} size="small" />
</div>

View File

@ -0,0 +1,8 @@
<script lang="ts">
import { CardCover } from '@anticrm/board'
import ColorPresenter from './ColorPresenter.svelte'
export let value: CardCover
</script>
<ColorPresenter value={value.color} size={value.size} on:click />

View File

@ -37,7 +37,8 @@ import Archive from './components/Archive.svelte'
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 CardCoverEditor from './components/editor/CardCoverEditor.svelte'
import CardCoverPresenter from './components/presenters/CardCoverPresenter.svelte'
import { createCard, getCardFromTodoItem } from './utils/CardUtils'
async function ConvertToCard (object: TodoItem): Promise<void> {
@ -71,6 +72,8 @@ export default async (): Promise<Resources> => ({
TableView,
UserBoxList,
CardLabels,
CardCoverEditor,
CardCoverPresenter,
// action popups
LabelsActionPopup: CardLabelsPopup,
DatesActionPopup: DateRangePicker,

View File

@ -15,7 +15,7 @@
//
import { Employee } from '@anticrm/contact'
import type { AttachedDoc, Class, Doc, Markup, Ref } from '@anticrm/core'
import type { AttachedDoc, Class, Doc, Markup, Ref, Type } from '@anticrm/core'
import type { Asset, IntlString, Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import type { Preference } from '@anticrm/preference'
@ -53,8 +53,7 @@ export interface CardLabel extends AttachedDoc {
* @public
*/
export interface CardCover {
color?: number
image?: string
color: number
size: 'large' | 'small'
}
@ -111,7 +110,8 @@ const boards = plugin(boardId, {
Card: '' as Ref<Class<Card>>,
CardLabel: '' as Ref<Class<CardLabel>>,
MenuPage: '' as Ref<Class<MenuPage>>,
CommonBoardPreference: '' as Ref<Class<CommonBoardPreference>>
CommonBoardPreference: '' as Ref<Class<CommonBoardPreference>>,
CardCover: '' as Ref<Class<Type<CardCover>>>
},
category: {
Card: '' as Ref<ActionCategory>