platform/plugins/attachment-resources/src/components/AttachmentPopup.svelte
2024-06-27 20:27:00 +07:00

161 lines
3.9 KiB
Svelte

<!--
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { Attachment } from '@hcengineering/attachment'
import { createQuery, getClient, getFileMetadata, uploadFile } from '@hcengineering/presentation'
import { ActionIcon, IconAdd, Label, Loading } from '@hcengineering/ui'
import type { Doc, WithLookup } from '@hcengineering/core'
import core from '@hcengineering/core'
import { setPlatformStatus, unknownError } from '@hcengineering/platform'
import { AttachmentPresenter } from '..'
import attachment from '../plugin'
// export let attachments: number
export let object: Doc
export let canAdd = true
export let canRemove = true
const client = getClient()
let docs: WithLookup<Attachment>[] = []
let progress = false
const query = createQuery()
$: query.query(
attachment.class.Attachment,
{
attachedTo: object._id
},
(res) => {
docs = res
},
{
lookup: {
file: core.class.Blob
}
}
)
function add () {
if (canAdd) {
inputFile.click()
}
}
async function createAttachment (file: File) {
try {
const uuid = await uploadFile(file)
const metadata = await getFileMetadata(file, uuid)
await client.addCollection(attachment.class.Attachment, object.space, object._id, object._class, 'attachments', {
name: file.name,
file: uuid,
type: file.type,
size: file.size,
lastModified: file.lastModified,
metadata
})
} catch (e) {
void setPlatformStatus(unknownError(e))
}
}
async function fileSelected (): Promise<void> {
progress = true
const list = inputFile.files
if (list === null || list.length === 0) return
for (let index = 0; index < list.length; index++) {
const file = list.item(index)
if (file !== null) {
await createAttachment(file)
}
}
inputFile.value = ''
progress = false
}
let inputFile: HTMLInputElement
async function remove (doc: Attachment): Promise<void> {
if (canRemove) {
await client.remove(doc)
}
}
</script>
<div class="container">
<input
bind:this={inputFile}
multiple
type="file"
name="file"
id="file"
style="display: none"
disabled={inputFile == null}
on:change={fileSelected}
/>
<div class="flex flex-between flex-grow header clear-mins">
<div class="fs-title">
<Label label={attachment.string.Attachments} />
</div>
{#if canAdd}
<div>
{#if progress}
<Loading />
{:else}
<ActionIcon size={'medium'} icon={IconAdd} action={add} />
{/if}
</div>
{/if}
</div>
<div class="content">
{#each docs as doc}
<div class="item">
<AttachmentPresenter value={doc} showPreview removable={canRemove} on:remove={() => remove(doc)} />
</div>
{/each}
</div>
</div>
<style lang="scss">
.header {
border-bottom: 1px solid var(--theme-divider-color);
padding: 1rem 1.5rem;
margin-right: -0.5rem;
margin-left: -0.5rem;
margin-bottom: 1rem;
}
.container {
max-height: 30rem;
overflow: hidden;
display: flex;
flex-direction: column;
}
.content {
overflow-y: scroll;
flex: 1;
}
.item {
margin: 0.5rem 1rem;
}
</style>