diff --git a/packages/theme/styles/_layouts.scss b/packages/theme/styles/_layouts.scss index 818a36801e..145aa44989 100644 --- a/packages/theme/styles/_layouts.scss +++ b/packages/theme/styles/_layouts.scss @@ -544,6 +544,7 @@ a.no-line { } /* Backgrounds & Colors */ +.background-theme-content-accent { background-color: var(--theme-content-accent-color); } .background-theme-bg-color { background-color: var(--theme-bg-color); } .background-highlight-red { background-color: var(--highlight-red); } .background-button-bg-color { background-color: var(--button-bg-color); } diff --git a/plugins/attachment-resources/src/components/AddAttachment.svelte b/plugins/attachment-resources/src/components/AddAttachment.svelte new file mode 100644 index 0000000000..2fe19c89be --- /dev/null +++ b/plugins/attachment-resources/src/components/AddAttachment.svelte @@ -0,0 +1,62 @@ + + + +
+ {#if $$slots.control} + + {:else} + + {/if} + +
diff --git a/plugins/attachment-resources/src/components/AttachmentDroppable.svelte b/plugins/attachment-resources/src/components/AttachmentDroppable.svelte new file mode 100644 index 0000000000..c2348083b4 --- /dev/null +++ b/plugins/attachment-resources/src/components/AttachmentDroppable.svelte @@ -0,0 +1,66 @@ + + + +
{ + if (canDrop?.(e) ?? true) { + dragover = true + e.preventDefault() + } + }} + on:dragleave={() => { + dragover = false + }} + on:drop={fileDrop} +> + +
diff --git a/plugins/attachment-resources/src/components/Attachments.svelte b/plugins/attachment-resources/src/components/Attachments.svelte index 43688320ef..5665e10368 100644 --- a/plugins/attachment-resources/src/components/Attachments.svelte +++ b/plugins/attachment-resources/src/components/Attachments.svelte @@ -15,63 +15,25 @@ -->
@@ -80,54 +42,31 @@ {#if loading} {:else} - { - inputFile.click() - }} - /> + {/if} -
- {#if (attachments === 0) && !loading} -
{ - dragover = true - }} - on:dragleave={() => { - dragover = false - }} - on:drop|preventDefault|stopPropagation={fileDrop} - > - -
-
+ {:else} + loadingProps={{ length: attachments ?? 0 }} /> {/if} @@ -150,6 +89,9 @@ background: var(--theme-bg-accent-color); border: 1px dashed var(--theme-zone-border-lite); border-radius: 0.75rem; - &.solid { border-style: solid; } + &.solid { + border-style: solid; + } } + diff --git a/plugins/attachment-resources/src/index.ts b/plugins/attachment-resources/src/index.ts index 82554a6bb3..04b7d96a4a 100644 --- a/plugins/attachment-resources/src/index.ts +++ b/plugins/attachment-resources/src/index.ts @@ -13,6 +13,8 @@ // limitations under the License. // +import AddAttachment from './components/AddAttachment.svelte' +import AttachmentDroppable from './components/AttachmentDroppable.svelte' import AttachmentsPresenter from './components/AttachmentsPresenter.svelte' import AttachmentPresenter from './components/AttachmentPresenter.svelte' import AttachmentDocList from './components/AttachmentDocList.svelte' @@ -24,7 +26,7 @@ import Photos from './components/Photos.svelte' import { Resources } from '@anticrm/platform' import { uploadFile, deleteFile } from './utils' -export { Attachments, AttachmentsPresenter, AttachmentPresenter, AttachmentRefInput, AttachmentList, AttachmentDocList } +export { AddAttachment, AttachmentDroppable, Attachments, AttachmentsPresenter, AttachmentPresenter, AttachmentRefInput, AttachmentList, AttachmentDocList } export default async (): Promise => ({ component: { diff --git a/plugins/attachment-resources/src/utils.ts b/plugins/attachment-resources/src/utils.ts index 341cfec351..bcc700d847 100644 --- a/plugins/attachment-resources/src/utils.ts +++ b/plugins/attachment-resources/src/utils.ts @@ -14,11 +14,13 @@ // limitations under the License. // -import type { Doc, Ref, Space } from '@anticrm/core' +import type { Class, Doc, Ref, Space, TxOperations as Client } from '@anticrm/core' import login from '@anticrm/login' -import { getMetadata } from '@anticrm/platform' +import { getMetadata, setPlatformStatus, unknownError } from '@anticrm/platform' -export async function uploadFile (file: File, opts?: { space: Ref, attachedTo: Ref }): Promise { +import attachment from './plugin' + +export async function uploadFile(file: File, opts?: { space: Ref; attachedTo: Ref }): Promise { const uploadUrl = getMetadata(login.metadata.UploadUrl) if (uploadUrl === undefined) { @@ -28,12 +30,16 @@ export async function uploadFile (file: File, opts?: { space: Ref, attach const data = new FormData() data.append('file', file) - const params = opts !== undefined - ? [['space', opts.space], ['attachedTo', opts.attachedTo]] - .filter((x): x is [string, Ref] => x[1] !== undefined) - .map(([name, value]) => `${name}=${value}`) - .join('&') - : '' + const params = + opts !== undefined + ? [ + ['space', opts.space], + ['attachedTo', opts.attachedTo] + ] + .filter((x): x is [string, Ref] => x[1] !== undefined) + .map(([name, value]) => `${name}=${value}`) + .join('&') + : '' const suffix = params === '' ? params : `?${params}` const url = `${uploadUrl}${suffix}` @@ -52,7 +58,7 @@ export async function uploadFile (file: File, opts?: { space: Ref, attach return await resp.text() } -export async function deleteFile (id: string): Promise { +export async function deleteFile(id: string): Promise { const uploadUrl = getMetadata(login.metadata.UploadUrl) const url = `${uploadUrl as string}?file=${id}` @@ -68,7 +74,33 @@ export async function deleteFile (id: string): Promise { } } -export function getType (type: string): 'image' | 'video' | 'audio' | 'pdf' | 'other' { +export async function createAttachments( + client: Client, + list: FileList, + attachTo: { objectClass: Ref>; space: Ref; objectId: Ref } +) { + const { objectClass, objectId, space } = attachTo + try { + for (let index = 0; index < list.length; index++) { + const file = list.item(index) + if (file !== null) { + const uuid = await uploadFile(file, { space, attachedTo: objectId }) + console.log('uploaded file uuid', uuid) + client.addCollection(attachment.class.Attachment, space, objectId, objectClass, 'attachments', { + name: file.name, + file: uuid, + type: file.type, + size: file.size, + lastModified: file.lastModified + }) + } + } + } catch (err: any) { + setPlatformStatus(unknownError(err)) + } +} + +export function getType(type: string): 'image' | 'video' | 'audio' | 'pdf' | 'other' { if (type.startsWith('image/')) { return 'image' } diff --git a/plugins/board-assets/lang/en.json b/plugins/board-assets/lang/en.json index b092f60269..75e01c6ec3 100644 --- a/plugins/board-assets/lang/en.json +++ b/plugins/board-assets/lang/en.json @@ -33,6 +33,8 @@ "Checklist": "Checklist", "Dates": "Dates", "Attachments": "Attachments", + "AddAttachment": "Add an attachment", + "DropFileToUpload": "Drop files to upload.", "CustomFields": "Custom Fields", "Automation": "Automation", "AddButton": "Add Button", diff --git a/plugins/board-assets/lang/ru.json b/plugins/board-assets/lang/ru.json index 7c457c9673..3fd205ab48 100644 --- a/plugins/board-assets/lang/ru.json +++ b/plugins/board-assets/lang/ru.json @@ -33,6 +33,8 @@ "Checklist": "Списки", "Dates": "Дата", "Attachments": "Прикрепленное", + "AddAttachment": "Прикрепить", + "DropFileToUpload": "Добавьте файлы.", "CustomFields": "Дополнительно", "Automation": "Автоматизация", "AddButton": "Добавить", diff --git a/plugins/board-resources/package.json b/plugins/board-resources/package.json index 3461c2e718..065f81761a 100644 --- a/plugins/board-resources/package.json +++ b/plugins/board-resources/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "@anticrm/activity": "~0.6.0", + "@anticrm/attachment": "~0.6.1", "@anticrm/attachment-resources": "~0.6.0", "@anticrm/board": "~0.6.0", "@anticrm/chunter": "~0.6.1", diff --git a/plugins/board-resources/src/components/EditCard.svelte b/plugins/board-resources/src/components/EditCard.svelte index faf9377980..725bb91e38 100644 --- a/plugins/board-resources/src/components/EditCard.svelte +++ b/plugins/board-resources/src/components/EditCard.svelte @@ -29,6 +29,7 @@ import { updateCard } from '../utils/CardUtils' import CardActions from './editor/CardActions.svelte' import CardActivity from './editor/CardActivity.svelte' + import CardAttachments from './editor/CardAttachments.svelte' import CardDetails from './editor/CardDetails.svelte' export let _id: Ref @@ -123,7 +124,7 @@ /> - + diff --git a/plugins/board-resources/src/components/KanbanCard.svelte b/plugins/board-resources/src/components/KanbanCard.svelte index e59efa3376..3614074bee 100644 --- a/plugins/board-resources/src/components/KanbanCard.svelte +++ b/plugins/board-resources/src/components/KanbanCard.svelte @@ -14,58 +14,82 @@ // limitations under the License. --> -
-
-
-
{object.title}
-
-
-
- + +
+ {#if dragoverAttachment} +
+
+
+ {/if} +
+
+
{object.title}
+
+
+
+ +
+ { + showMenu(evt) + }} + icon={IconMoreH} + size="small" /> +
+
+
+
+ {#if (object.attachments ?? 0) > 0} +
+ +
+ {/if} + {#if (object.comments ?? 0) > 0} +
+ +
+ {/if}
- { - showMenu(evt) - }} - icon={IconMoreH} - size={'small'} - />
-
-
- {#if (object.attachments ?? 0) > 0} -
- -
- {/if} - {#if (object.comments ?? 0) > 0} -
- -
- {/if} -
-
-
+
diff --git a/plugins/board-resources/src/components/editor/CardActions.svelte b/plugins/board-resources/src/components/editor/CardActions.svelte index e3691630ad..687c554f52 100644 --- a/plugins/board-resources/src/components/editor/CardActions.svelte +++ b/plugins/board-resources/src/components/editor/CardActions.svelte @@ -27,15 +27,15 @@ export let value: Card const client = getClient() + const suggestedActions: CardAction[] = [] + const addToCardActions: CardAction[] = [] + const automationActions: CardAction[] = [] + const actions: CardAction[] = [] + let actionGroups: { label: IntlString; actions: CardAction[] }[] = [] async function fetch() { - const suggestedActions: CardAction[] = [] - const addToCardActions: CardAction[] = [] - const automationActions: CardAction[] = [] - const actions: CardAction[] = [] const result = await getCardActions(client) - for (const action of result) { let supported = true if (action.supported) { @@ -77,12 +77,7 @@ ] } - fetch() - - $: value.members && fetch() - $: value.isArchived && fetch() - $: !value.isArchived && fetch() - + $: fetch() {#if value} @@ -107,8 +102,7 @@ const handler = await getResource(action.handler) handler(value, client) } - }} - /> + }} /> {/if} {/each}
diff --git a/plugins/board-resources/src/components/editor/CardActivity.svelte b/plugins/board-resources/src/components/editor/CardActivity.svelte index 324f038adf..9491938d25 100644 --- a/plugins/board-resources/src/components/editor/CardActivity.svelte +++ b/plugins/board-resources/src/components/editor/CardActivity.svelte @@ -26,8 +26,6 @@ {#if value !== undefined}
- -
diff --git a/plugins/board-resources/src/components/editor/CardAttachments.svelte b/plugins/board-resources/src/components/editor/CardAttachments.svelte new file mode 100644 index 0000000000..6d3d7494d8 --- /dev/null +++ b/plugins/board-resources/src/components/editor/CardAttachments.svelte @@ -0,0 +1,65 @@ + + + +{#if value !== undefined && value.attachments !== undefined && value.attachments > 0} +
+
+
+ +
+
+
+
+
+
+
+ {#each attachments as attach} + + {/each} +
+ + +
+
+
+
+{/if} diff --git a/plugins/board-resources/src/components/presenters/AttachmentPresenter.svelte b/plugins/board-resources/src/components/presenters/AttachmentPresenter.svelte new file mode 100644 index 0000000000..4704c18aaf --- /dev/null +++ b/plugins/board-resources/src/components/presenters/AttachmentPresenter.svelte @@ -0,0 +1,26 @@ + + + +
+ +
diff --git a/plugins/board-resources/src/plugin.ts b/plugins/board-resources/src/plugin.ts index 52183d47a3..5742a886e3 100644 --- a/plugins/board-resources/src/plugin.ts +++ b/plugins/board-resources/src/plugin.ts @@ -54,6 +54,8 @@ export default mergeIds(boardId, board, { Checklist: '' as IntlString, Dates: '' as IntlString, Attachments: '' as IntlString, + AddAttachment: '' as IntlString, + DropFileToUpload: '' as IntlString, CustomFields: '' as IntlString, Automation: '' as IntlString, AddButton: '' as IntlString,