mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 03:40:48 +00:00
Allow attachments customizations. (#2414)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
0ba152665c
commit
1bcc1dfc82
@ -79,6 +79,8 @@
|
||||
|
||||
export let field: string | undefined = undefined
|
||||
|
||||
export let autoOverflow = false
|
||||
|
||||
const ydoc = (getContext(CollaborationIds.Doc) as Y.Doc | undefined) ?? new Y.Doc()
|
||||
const contextProvider = getContext(CollaborationIds.Provider) as WebsocketProvider | undefined
|
||||
const wsProvider =
|
||||
@ -464,7 +466,7 @@
|
||||
let showDiff = true
|
||||
</script>
|
||||
|
||||
<div class="ref-container">
|
||||
<div class="ref-container" class:autoOverflow>
|
||||
<div class="flex">
|
||||
{#if isFormatting && !readonly}
|
||||
<div class="formatPanel buttons-group xsmall-gap mb-4">
|
||||
@ -709,4 +711,7 @@
|
||||
span.deletion {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.autoOverflow {
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
@ -13,11 +13,13 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Class, Doc, Ref, Space } from '@hcengineering/core'
|
||||
import { Attachment } from '@hcengineering/attachment'
|
||||
import { Class, Data, Doc, Ref, Space } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Button, IconAdd } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { createAttachments } from '../utils'
|
||||
import attachment from '../plugin'
|
||||
|
||||
export let loading: number = 0
|
||||
export let inputFile: HTMLInputElement
|
||||
@ -25,6 +27,8 @@
|
||||
export let objectClass: Ref<Class<Doc>>
|
||||
export let objectId: Ref<Doc>
|
||||
export let space: Ref<Space>
|
||||
export let attachmentClass: Ref<Class<Attachment>> = attachment.class.Attachment
|
||||
export let attachmentClassOptions: Partial<Data<Attachment>> = {}
|
||||
|
||||
const client = getClient()
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -35,7 +39,7 @@
|
||||
|
||||
loading++
|
||||
try {
|
||||
await createAttachments(client, list, { objectClass, objectId, space })
|
||||
await createAttachments(client, list, { objectClass, objectId, space }, attachmentClass, attachmentClassOptions)
|
||||
} finally {
|
||||
loading--
|
||||
}
|
||||
|
@ -14,9 +14,10 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Class, Doc, DocumentQuery, Ref, Space } from '@hcengineering/core'
|
||||
import { Icon, Label, Spinner, resizeObserver, Scroller } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { Attachment } from '@hcengineering/attachment'
|
||||
import { Class, Data, Doc, DocumentQuery, Ref, Space } from '@hcengineering/core'
|
||||
import { Icon, Label, resizeObserver, Scroller, Spinner } from '@hcengineering/ui'
|
||||
import view, { BuildModelKey } from '@hcengineering/view'
|
||||
import { Table } from '@hcengineering/view-resources'
|
||||
import attachment from '../plugin'
|
||||
import AddAttachment from './AddAttachment.svelte'
|
||||
@ -28,7 +29,11 @@
|
||||
export let space: Ref<Space>
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let query: DocumentQuery<Doc> = {}
|
||||
|
||||
export let attachmentClass: Ref<Class<Attachment>> = attachment.class.Attachment
|
||||
export let attachmentClassOptions: Partial<Data<Attachment>> = {}
|
||||
export let extraConfig: (BuildModelKey | string)[] = []
|
||||
export let readonly = false
|
||||
export let showHeader = true
|
||||
export let attachments: number | undefined = undefined
|
||||
|
||||
let inputFile: HTMLInputElement
|
||||
@ -40,19 +45,33 @@
|
||||
<div class="antiSection" use:resizeObserver={(element) => (wSection = element.clientWidth)}>
|
||||
<div class="antiSection-header">
|
||||
<div class="antiSection-header__icon">
|
||||
<Icon icon={IconAttachment} size={'small'} />
|
||||
{#if showHeader}
|
||||
<Icon icon={IconAttachment} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
<span class="antiSection-header__title"><Label label={attachment.string.Attachments} /></span>
|
||||
<span class="antiSection-header__title">
|
||||
{#if showHeader}
|
||||
<Label label={attachment.string.Attachments} />
|
||||
{/if}
|
||||
</span>
|
||||
<div class="buttons-group small-gap">
|
||||
{#if loading}
|
||||
<Spinner />
|
||||
{:else}
|
||||
<AddAttachment bind:loading bind:inputFile objectClass={_class} {objectId} {space} />
|
||||
{:else if !readonly}
|
||||
<AddAttachment
|
||||
bind:loading
|
||||
bind:inputFile
|
||||
objectClass={_class}
|
||||
{objectId}
|
||||
{space}
|
||||
{attachmentClass}
|
||||
{attachmentClassOptions}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if !loading && (attachments === null || attachments === 0)}
|
||||
{#if !loading && (attachments === null || attachments === 0) && !readonly}
|
||||
<AttachmentDroppable bind:loading bind:dragover objectClass={_class} {objectId} {space}>
|
||||
<div class="antiSection-empty attachments flex-col mt-3" class:solid={dragover}>
|
||||
<div class="flex-center content-accent-color">
|
||||
@ -74,7 +93,7 @@
|
||||
{:else if wSection < 640}
|
||||
<Scroller horizontal>
|
||||
<Table
|
||||
_class={attachment.class.Attachment}
|
||||
_class={attachmentClass}
|
||||
config={[
|
||||
'',
|
||||
'description',
|
||||
@ -84,6 +103,7 @@
|
||||
label: attachment.string.Pinned,
|
||||
sortingKey: 'pinned'
|
||||
},
|
||||
...extraConfig,
|
||||
'lastModified'
|
||||
]}
|
||||
options={{ sort: { pinned: -1 } }}
|
||||
@ -92,11 +112,12 @@
|
||||
on:content={(evt) => {
|
||||
attachments = evt.detail.length
|
||||
}}
|
||||
{readonly}
|
||||
/>
|
||||
</Scroller>
|
||||
{:else}
|
||||
<Table
|
||||
_class={attachment.class.Attachment}
|
||||
_class={attachmentClass}
|
||||
config={[
|
||||
'',
|
||||
'description',
|
||||
@ -106,6 +127,7 @@
|
||||
label: attachment.string.Pinned,
|
||||
sortingKey: 'pinned'
|
||||
},
|
||||
...extraConfig,
|
||||
'lastModified'
|
||||
]}
|
||||
options={{ sort: { pinned: -1 } }}
|
||||
@ -114,6 +136,7 @@
|
||||
on:content={(evt) => {
|
||||
attachments = evt.detail.length
|
||||
}}
|
||||
{readonly}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -14,7 +14,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Class, Doc, Ref, Space, TxOperations as Client } from '@hcengineering/core'
|
||||
import { Attachment } from '@hcengineering/attachment'
|
||||
import type { Class, Data, Doc, Ref, Space, TxOperations as Client } from '@hcengineering/core'
|
||||
import login from '@hcengineering/login'
|
||||
import { getMetadata, setPlatformStatus, unknownError } from '@hcengineering/platform'
|
||||
|
||||
@ -77,7 +78,9 @@ export async function deleteFile (id: string): Promise<void> {
|
||||
export async function createAttachments (
|
||||
client: Client,
|
||||
list: FileList,
|
||||
attachTo: { objectClass: Ref<Class<Doc>>, space: Ref<Space>, objectId: Ref<Doc> }
|
||||
attachTo: { objectClass: Ref<Class<Doc>>, space: Ref<Space>, objectId: Ref<Doc> },
|
||||
attachmentClass: Ref<Class<Attachment>> = attachment.class.Attachment,
|
||||
extraData: Partial<Data<Attachment>> = {}
|
||||
): Promise<void> {
|
||||
const { objectClass, objectId, space } = attachTo
|
||||
try {
|
||||
@ -85,7 +88,8 @@ export async function createAttachments (
|
||||
const file = list.item(index)
|
||||
if (file !== null) {
|
||||
const uuid = await uploadFile(file, { space, attachedTo: objectId })
|
||||
await client.addCollection(attachment.class.Attachment, space, objectId, objectClass, 'attachments', {
|
||||
await client.addCollection(attachmentClass, space, objectId, objectClass, 'attachments', {
|
||||
...extraData,
|
||||
name: file.name,
|
||||
file: uuid,
|
||||
type: file.type,
|
||||
|
@ -29,6 +29,7 @@
|
||||
export let showLabel: IntlString | undefined = undefined
|
||||
export let defaultCollapsed = false
|
||||
export let draft = false
|
||||
export let showHeader: boolean = true
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
@ -47,42 +48,44 @@
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="attrbar-header"
|
||||
class:collapsed
|
||||
on:click={() => {
|
||||
collapsed = !collapsed
|
||||
}}
|
||||
>
|
||||
<div class="flex-row-center">
|
||||
<span class="overflow-label">
|
||||
<Label {label} />
|
||||
</span>
|
||||
<div class="icon-arrow">
|
||||
<svg fill="var(--dark-color)" viewBox="0 0 6 6" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0,0L6,3L0,6Z" />
|
||||
</svg>
|
||||
{#if showHeader}
|
||||
<div
|
||||
class="attrbar-header"
|
||||
class:collapsed
|
||||
on:click={() => {
|
||||
collapsed = !collapsed
|
||||
}}
|
||||
>
|
||||
<div class="flex-row-center">
|
||||
<span class="overflow-label">
|
||||
<Label {label} />
|
||||
</span>
|
||||
<div class="icon-arrow">
|
||||
<svg fill="var(--dark-color)" viewBox="0 0 6 6" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0,0L6,3L0,6Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tool">
|
||||
<Button
|
||||
icon={setting.icon.Setting}
|
||||
kind={'transparent'}
|
||||
showTooltip={{ label: setting.string.ClassSetting }}
|
||||
on:click={(ev) => {
|
||||
ev.stopPropagation()
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = settingId
|
||||
loc.path[3] = 'setting'
|
||||
loc.path[4] = 'classes'
|
||||
loc.path.length = 5
|
||||
loc.query = { _class }
|
||||
loc.fragment = undefined
|
||||
navigate(loc)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tool">
|
||||
<Button
|
||||
icon={setting.icon.Setting}
|
||||
kind={'transparent'}
|
||||
showTooltip={{ label: setting.string.ClassSetting }}
|
||||
on:click={(ev) => {
|
||||
ev.stopPropagation()
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = settingId
|
||||
loc.path[3] = 'setting'
|
||||
loc.path[4] = 'classes'
|
||||
loc.path.length = 5
|
||||
loc.query = { _class }
|
||||
loc.fragment = undefined
|
||||
navigate(loc)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if keys.length}
|
||||
<div class="collapsed-container" class:collapsed>
|
||||
<AttributesBar {_class} {object} keys={keys.map((p) => p.key)} {readonly} {draft} on:update />
|
||||
|
@ -44,6 +44,7 @@
|
||||
export let baseMenuClass: Ref<Class<Doc>> | undefined = undefined
|
||||
export let config: (BuildModelKey | string)[]
|
||||
export let tableId: string | undefined = undefined
|
||||
export let readonly = false
|
||||
|
||||
// If defined, will show a number of dummy items before real data will appear.
|
||||
export let loadingProps: LoadingProps | undefined = undefined
|
||||
@ -243,7 +244,11 @@
|
||||
on:mouseover={() => onRow(object)}
|
||||
on:focus={() => {}}
|
||||
bind:this={refs[row]}
|
||||
on:contextmenu|preventDefault={(ev) => showMenu(ev, object, row)}
|
||||
on:contextmenu|preventDefault={(ev) => {
|
||||
if (!readonly) {
|
||||
showMenu(ev, object, row)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#each model as attribute, cell}
|
||||
{#if !cell}
|
||||
|
Loading…
Reference in New Issue
Block a user