diff --git a/packages/theme/styles/_layouts.scss b/packages/theme/styles/_layouts.scss
index 9e8b21f01b..ad00b63991 100644
--- a/packages/theme/styles/_layouts.scss
+++ b/packages/theme/styles/_layouts.scss
@@ -194,6 +194,7 @@ input.search {
.justify-end { justify-content: flex-end; }
.justify-center { justify-content: center; }
.items-baseline { align-items: baseline; }
+.items-center { align-items: center; }
.flex-gap-3 { gap: .75rem; }
.flex-gap-2 { gap: .5rem; }
@@ -456,6 +457,7 @@ input.search {
.min-w-80 { min-width: 20rem; }
.min-w-min { min-width: min-content; }
.min-h-0 { min-height: 0; }
+.min-h-7 { min-height: 1.75rem; }
.max-h-125 { max-height: 31.25rem; }
.max-h-60 { max-height: 15rem; }
.max-w-60 { max-width: 15rem; }
@@ -540,6 +542,7 @@ a.no-line {
.text-lg { font-size: 1.125rem; }
.font-normal { font-weight: 400; }
.font-medium { font-weight: 500; }
+.font-semi-bold { font-weight: 600; }
.fs-bold { font-weight: 500; }
.uppercase { text-transform: uppercase; }
.text-left { text-align: left; }
@@ -549,6 +552,8 @@ a.no-line {
&:hover { text-decoration: underline; }
}
+.text-line-through { text-decoration: line-through; }
+
.hidden-text {
position: absolute;
visibility: hidden;
@@ -632,6 +637,7 @@ a.no-line {
.background-highlight-red { background-color: var(--highlight-red); }
.background-button-bg-color { background-color: var(--button-bg-color); }
.background-button-bg-enabled { background-color: var(--theme-button-bg-enabled); }
+.background-button-noborder-bg-hover { background-color: var(--noborder-bg-hover); }
.background-menu-divider { background-color: var(--theme-menu-divider); }
.background-card-divider { background-color: var(--theme-card-divider); }
.background-primary-color { background-color: var(--primary-button-enabled); }
diff --git a/packages/ui/src/components/Dropdown.svelte b/packages/ui/src/components/Dropdown.svelte
index 14c6b62a76..0c6f29dd89 100644
--- a/packages/ui/src/components/Dropdown.svelte
+++ b/packages/ui/src/components/Dropdown.svelte
@@ -19,7 +19,7 @@
import Label from './Label.svelte'
export let icon: Asset | AnySvelteComponent | undefined = undefined
- export let label: IntlString
+ export let label: IntlString | undefined = undefined
export let placeholder: IntlString
export let items: ListItem[] = []
export let selected: ListItem | undefined = undefined
diff --git a/packages/ui/src/components/DropdownPopup.svelte b/packages/ui/src/components/DropdownPopup.svelte
index e5be04b7e1..230fe1c46c 100644
--- a/packages/ui/src/components/DropdownPopup.svelte
+++ b/packages/ui/src/components/DropdownPopup.svelte
@@ -68,23 +68,28 @@
{/each}
diff --git a/packages/ui/src/components/EditBox.svelte b/packages/ui/src/components/EditBox.svelte
index b8ce71b202..8ad4d73d01 100644
--- a/packages/ui/src/components/EditBox.svelte
+++ b/packages/ui/src/components/EditBox.svelte
@@ -23,8 +23,8 @@
export let label: IntlString | undefined = undefined
export let icon: Asset | AnySvelteComponent | undefined = undefined
- export let maxWidth: string | undefined
- export let value: string | number | undefined
+ export let maxWidth: string | undefined = undefined
+ export let value: string | number | undefined = undefined
export let placeholder: IntlString = plugin.string.EditBoxPlaceholder
export let placeholderParam: any | undefined = undefined
export let format: 'text' | 'password' | 'number' = 'text'
diff --git a/packages/ui/src/components/Progress.svelte b/packages/ui/src/components/Progress.svelte
index ec0d96e255..ce9f8302b1 100644
--- a/packages/ui/src/components/Progress.svelte
+++ b/packages/ui/src/components/Progress.svelte
@@ -37,7 +37,9 @@
diff --git a/packages/ui/src/components/TextAriaEditor.svelte b/packages/ui/src/components/TextAriaEditor.svelte
index c22f49f632..ba47ca1682 100644
--- a/packages/ui/src/components/TextAriaEditor.svelte
+++ b/packages/ui/src/components/TextAriaEditor.svelte
@@ -12,7 +12,7 @@
export let width: string | undefined = undefined
export let height: string | undefined = undefined
export let submitLabel: IntlString = ui.string.Save
- export let placeholder: IntlString | undefined
+ export let placeholder: IntlString | undefined = undefined
const dispatch = createEventDispatcher()
let isEditing = false
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts
index a0d538e052..4b5bbd2463 100644
--- a/packages/ui/src/index.ts
+++ b/packages/ui/src/index.ts
@@ -25,6 +25,7 @@ export type {
AnySvelteComponent,
Action,
LabelAndProps,
+ ListItem,
TooltipAlignment,
AnySvelteComponentWithProps,
Location,
diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts
index 13885200c5..2c4a214822 100644
--- a/packages/ui/src/types.ts
+++ b/packages/ui/src/types.ts
@@ -93,6 +93,9 @@ export interface ListItem {
_id: string
label: string
image?: string
+ isSelectable?: boolean
+ fontWeight?: 'normal' | 'medium' | 'semi-bold'
+ paddingLeft?: number
}
export interface DropdownTextItem {
diff --git a/plugins/board-assets/lang/en.json b/plugins/board-assets/lang/en.json
index 76ea2a1173..cc57c02b2b 100644
--- a/plugins/board-assets/lang/en.json
+++ b/plugins/board-assets/lang/en.json
@@ -38,6 +38,10 @@
"NoColor": "No color.",
"NoColorInfo": "This won't show up on the front of cards.",
"Checklist": "Checklist",
+ "AddChecklistItem": "Add an item",
+ "ChecklistDropdownNone": "(none)",
+ "ShowDoneChecklistItems": "Show checked items ({done})",
+ "HideDoneChecklistItems": "Hide checked items",
"Dates": "Dates",
"Attachments": "Attachments",
"AddAttachment": "Add an attachment",
diff --git a/plugins/board-assets/lang/ru.json b/plugins/board-assets/lang/ru.json
index 01c00364ab..7c8b2a4ba2 100644
--- a/plugins/board-assets/lang/ru.json
+++ b/plugins/board-assets/lang/ru.json
@@ -38,6 +38,10 @@
"NoColor": "Без цвета.",
"NoColorInfo": "Не будет показываться на доске.",
"Checklist": "Списки",
+ "AddChecklistItem": "Добавить",
+ "ChecklistDropdownNone": "(не выбрано)",
+ "ShowDoneChecklistItems": "Показать отмеченные ({done})",
+ "HideDoneChecklistItems": "Скрыть отмеченные",
"Dates": "Дата",
"Attachments": "Прикрепленное",
"AddAttachment": "Прикрепить",
diff --git a/plugins/board-resources/src/components/EditCard.svelte b/plugins/board-resources/src/components/EditCard.svelte
index fbbeb11850..64d080e4df 100644
--- a/plugins/board-resources/src/components/EditCard.svelte
+++ b/plugins/board-resources/src/components/EditCard.svelte
@@ -19,7 +19,7 @@
import { Panel } from '@anticrm/panel'
import { getResource } from '@anticrm/platform'
import { createQuery, getClient } from '@anticrm/presentation'
- import type { State } from '@anticrm/task'
+ import type { State, TodoItem } from '@anticrm/task'
import task from '@anticrm/task'
import { StyledTextBox } from '@anticrm/text-editor'
import { Button, EditBox, Icon, Label } from '@anticrm/ui'
@@ -30,6 +30,7 @@
import { updateCard } from '../utils/CardUtils'
import CardActions from './editor/CardActions.svelte'
import CardAttachments from './editor/CardAttachments.svelte'
+ import CardChecklist from './editor/CardChecklist.svelte'
import CardDetails from './editor/CardDetails.svelte'
export let _id: Ref
@@ -38,20 +39,33 @@
const client = getClient()
const cardQuery = createQuery()
const stateQuery = createQuery()
+ const checklistsQuery = createQuery()
let object: Card | undefined
let state: State | undefined
let handleMove: (e: Event) => void
+ let checklists: TodoItem[] = []
- $: cardQuery.query(_class, { _id }, async (result) => {
+ function change (field: string, value: any) {
+ if (object) {
+ updateCard(client, object, field, value)
+ }
+ }
+
+ $: cardQuery.query(_class, { _id }, (result) => {
object = result[0]
})
$: object?.state &&
- stateQuery.query(task.class.State, { _id: object.state }, async (result) => {
+ stateQuery.query(task.class.State, { _id: object.state }, (result) => {
state = result[0]
})
+ $: object &&
+ checklistsQuery.query(task.class.TodoItem, { space: object.space, attachedTo: object._id }, (result) => {
+ checklists = result
+ })
+
getCardActions(client, { _id: board.cardAction.Move }).then(async (result) => {
if (result[0]?.handler) {
const handler = await getResource(result[0].handler)
@@ -63,12 +77,6 @@
}
})
- function change (field: string, value: any) {
- if (object) {
- updateCard(client, object, field, value)
- }
- }
-
onMount(() => {
dispatch('open', { ignoreKeys: ['comments', 'number', 'title'] })
})
@@ -130,8 +138,9 @@
-
-
+ {#each checklists as checklist}
+
+ {/each}
diff --git a/plugins/board-resources/src/components/editor/CardActivity.svelte b/plugins/board-resources/src/components/editor/CardActivity.svelte
deleted file mode 100644
index 12f0954382..0000000000
--- a/plugins/board-resources/src/components/editor/CardActivity.svelte
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-{#if value !== undefined}
-
-
-
-
-
-
-
-
-
-
- {#if isActivityShown === true}
-
-
-
- {/if}
-
-{/if}
diff --git a/plugins/board-resources/src/components/editor/CardChecklist.svelte b/plugins/board-resources/src/components/editor/CardChecklist.svelte
new file mode 100644
index 0000000000..93ffd072fb
--- /dev/null
+++ b/plugins/board-resources/src/components/editor/CardChecklist.svelte
@@ -0,0 +1,222 @@
+
+
+
+{#if value !== undefined}
+
+
+
+
+
+ {#if isEditingName}
+
+ {
+ isEditingName = false
+ }}
+ />
+
+ {:else}
+
{
+ isEditingName = true
+ }}
+ >
+ {value.name}
+
+ {#if done > 0}
+
+
+ {/if}
+
+ {/if}
+
+
+
+ {checklistItems.length > 0 ? Math.round((done / checklistItems.length) * 100) : 0}%
+
+
+
+ {#each checklistItems.filter((item) => !hideDoneItems || !item.done) as item}
+
{
+ hovered = item._id
+ }}
+ on:focus={() => {
+ hovered = item._id
+ }}
+ on:mouseout={() => {
+ hovered = undefined
+ }}
+ on:blur={() => {
+ hovered = undefined
+ }}
+ >
+
+ setDoneToChecklistItem(item, event)} />
+
+ {#if editingItemId === item._id}
+
+ {
+ editingItemId = undefined
+ updateItemName(item, event.detail)
+ }}
+ on:cancel={() => {
+ editingItemId = undefined
+ }}
+ />
+
+ {:else}
+
{
+ editingItemId = item._id
+ }}
+ >
+
+
+
+
+ {/if}
+
+ {/each}
+
+
+ {#if isAddingItem}
+
+ {
+ newItemName = ''
+ isAddingItem = false
+ }}
+ />
+
+ {:else}
+
+ {/if}
+
+
+{/if}
diff --git a/plugins/board-resources/src/components/popups/AddChecklist.svelte b/plugins/board-resources/src/components/popups/AddChecklist.svelte
new file mode 100644
index 0000000000..ed840535f9
--- /dev/null
+++ b/plugins/board-resources/src/components/popups/AddChecklist.svelte
@@ -0,0 +1,152 @@
+
+
+
diff --git a/plugins/board-resources/src/index.ts b/plugins/board-resources/src/index.ts
index 53331ba936..949e5edeb7 100644
--- a/plugins/board-resources/src/index.ts
+++ b/plugins/board-resources/src/index.ts
@@ -27,6 +27,7 @@ import CreateCard from './components/CreateCard.svelte'
import EditCard from './components/EditCard.svelte'
import KanbanCard from './components/KanbanCard.svelte'
import KanbanView from './components/KanbanView.svelte'
+import AddChecklist from './components/popups/AddChecklist.svelte'
import AttachmentPicker from './components/popups/AttachmentPicker.svelte'
import CardLabelsPopup from './components/popups/CardLabelsPopup.svelte'
import MoveCard from './components/popups/MoveCard.svelte'
@@ -73,6 +74,10 @@ async function showCardLabelsPopup (object: Card, client: Client, e?: Event): Pr
showPopup(CardLabelsPopup, { object }, getPopupAlignment(e))
}
+async function showChecklistsPopup (object: Card, client: Client, e?: Event): Promise {
+ showPopup(AddChecklist, { object }, getPopupAlignment(e))
+}
+
async function showEditMembersPopup (object: Card, client: Client, e?: Event): Promise {
showPopup(
UsersPopup,
@@ -126,6 +131,7 @@ export default async (): Promise => ({
SendToBoard: unarchiveCard,
Delete: showDeleteCardPopup,
Members: showEditMembersPopup,
+ Checklist: showChecklistsPopup,
Copy: showCopyCardPopup,
Cover: showCoverPopup
},
diff --git a/plugins/board-resources/src/plugin.ts b/plugins/board-resources/src/plugin.ts
index 5d029c2332..aa8e1519bb 100644
--- a/plugins/board-resources/src/plugin.ts
+++ b/plugins/board-resources/src/plugin.ts
@@ -59,6 +59,10 @@ export default mergeIds(boardId, board, {
NoColor: '' as IntlString,
NoColorInfo: '' as IntlString,
Checklist: '' as IntlString,
+ AddChecklistItem: '' as IntlString,
+ ChecklistDropdownNone: '' as IntlString,
+ ShowDoneChecklistItems: '' as IntlString,
+ HideDoneChecklistItems: '' as IntlString,
Dates: '' as IntlString,
Attachments: '' as IntlString,
AddAttachment: '' as IntlString,
diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts
index c2a5bee4bd..f62c72a692 100644
--- a/plugins/view-resources/src/index.ts
+++ b/plugins/view-resources/src/index.ts
@@ -55,7 +55,7 @@ export { default as LinkPresenter } from './components/LinkPresenter.svelte'
export * from './context'
export * from './selection'
export { buildModel, getCollectionCounter, getObjectPresenter, LoadingProps } from './utils'
-export { Table, TableView, DocAttributeBar, EditDoc, ColorsPopup, Menu, SpacePresenter, UpDownNavigator }
+export { HTMLPresenter, Table, TableView, DocAttributeBar, EditDoc, ColorsPopup, Menu, SpacePresenter, UpDownNavigator }
export default async (): Promise => ({
actionImpl: actionImpl,