mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-21 15:59:15 +00:00
Chunter: Download file action (#1570)
Signed-off-by: Denis Bunakalya <denis.bunakalya@xored.com>
This commit is contained in:
parent
5fb0565aee
commit
fec4d180ed
@ -0,0 +1,73 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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 type { Attachment } from '@anticrm/attachment'
|
||||||
|
import { getResource } from '@anticrm/platform'
|
||||||
|
import { showPopup, ActionIcon, IconMoreH, Menu, Icon } from '@anticrm/ui'
|
||||||
|
import { Action } from '@anticrm/view'
|
||||||
|
import { getFileUrl } from '@anticrm/presentation'
|
||||||
|
|
||||||
|
import attachmentPlugin from '../plugin'
|
||||||
|
import FileDownload from './icons/FileDownload.svelte'
|
||||||
|
|
||||||
|
export let attachment: Attachment
|
||||||
|
export let isSaved = false
|
||||||
|
|
||||||
|
$: saveAttachmentAction = isSaved
|
||||||
|
? ({
|
||||||
|
label: attachmentPlugin.string.RemoveAttachmentFromSaved,
|
||||||
|
action: attachmentPlugin.actionImpl.DeleteAttachmentFromSaved
|
||||||
|
} as Action)
|
||||||
|
: ({
|
||||||
|
label: attachmentPlugin.string.AddAttachmentToSaved,
|
||||||
|
action: attachmentPlugin.actionImpl.AddAttachmentToSaved
|
||||||
|
} as Action)
|
||||||
|
|
||||||
|
const showMenu = (ev: Event) => {
|
||||||
|
showPopup(
|
||||||
|
Menu,
|
||||||
|
{
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: saveAttachmentAction.label,
|
||||||
|
icon: saveAttachmentAction.icon,
|
||||||
|
action: async (evt: MouseEvent) => {
|
||||||
|
const impl = await getResource(saveAttachmentAction.action)
|
||||||
|
await impl(attachment, evt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
ev.target as HTMLElement
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
<a class="downloadButton" href={getFileUrl(attachment.file)} download={attachment.name} on:click|stopPropagation>
|
||||||
|
<Icon icon={FileDownload} size={'small'} />
|
||||||
|
</a>
|
||||||
|
<ActionIcon icon={IconMoreH} size={'small'} action={showMenu} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.downloadButton {
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
}
|
||||||
|
</style>
|
@ -15,48 +15,17 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Attachment } from '@anticrm/attachment'
|
import type { Attachment } from '@anticrm/attachment'
|
||||||
import { getResource } from '@anticrm/platform'
|
|
||||||
import { getFileUrl, PDFViewer } from '@anticrm/presentation'
|
import { getFileUrl, PDFViewer } from '@anticrm/presentation'
|
||||||
import { showPopup, closeTooltip, ActionIcon, IconMoreH, Menu } from '@anticrm/ui'
|
import { showPopup, closeTooltip } from '@anticrm/ui'
|
||||||
import { Action } from '@anticrm/view'
|
|
||||||
import { getType } from '../utils'
|
import { getType } from '../utils'
|
||||||
import AttachmentPresenter from './AttachmentPresenter.svelte'
|
import AttachmentPresenter from './AttachmentPresenter.svelte'
|
||||||
|
import AttachmentActions from './AttachmentActions.svelte'
|
||||||
import AudioPlayer from './AudioPlayer.svelte'
|
import AudioPlayer from './AudioPlayer.svelte'
|
||||||
import attachment from '../plugin'
|
|
||||||
|
|
||||||
export let value: Attachment
|
export let value: Attachment
|
||||||
export let isSaved: boolean = false
|
export let isSaved: boolean = false
|
||||||
|
|
||||||
$: type = getType(value.type)
|
$: type = getType(value.type)
|
||||||
|
|
||||||
$: saveAttachmentAction = isSaved
|
|
||||||
? ({
|
|
||||||
label: attachment.string.RemoveAttachmentFromSaved,
|
|
||||||
action: attachment.actionImpl.DeleteAttachmentFromSaved
|
|
||||||
} as Action)
|
|
||||||
: ({
|
|
||||||
label: attachment.string.AddAttachmentToSaved,
|
|
||||||
action: attachment.actionImpl.AddAttachmentToSaved
|
|
||||||
} as Action)
|
|
||||||
|
|
||||||
const showMenu = (ev: Event) => {
|
|
||||||
showPopup(
|
|
||||||
Menu,
|
|
||||||
{
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
label: saveAttachmentAction.label,
|
|
||||||
icon: saveAttachmentAction.icon,
|
|
||||||
action: async (evt: MouseEvent) => {
|
|
||||||
const impl = await getResource(saveAttachmentAction.action)
|
|
||||||
await impl(value, evt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
ev.target as HTMLElement
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex-row-center">
|
<div class="flex-row-center">
|
||||||
@ -69,27 +38,15 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img src={getFileUrl(value.file)} alt={value.name} />
|
<img src={getFileUrl(value.file)} alt={value.name} />
|
||||||
<div class="more">
|
<div class="actions">
|
||||||
<ActionIcon
|
<AttachmentActions attachment={value} {isSaved} />
|
||||||
icon={IconMoreH}
|
|
||||||
size={'small'}
|
|
||||||
action={(e) => {
|
|
||||||
showMenu(e)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if type === 'audio'}
|
{:else if type === 'audio'}
|
||||||
<div class="buttonContainer">
|
<div class="buttonContainer">
|
||||||
<AudioPlayer {value} />
|
<AudioPlayer {value} />
|
||||||
<div class="more">
|
<div class="actions">
|
||||||
<ActionIcon
|
<AttachmentActions attachment={value} {isSaved} />
|
||||||
icon={IconMoreH}
|
|
||||||
size={'small'}
|
|
||||||
action={(e) => {
|
|
||||||
showMenu(e)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if type === 'video'}
|
{:else if type === 'video'}
|
||||||
@ -101,27 +58,15 @@
|
|||||||
<AttachmentPresenter {value} />
|
<AttachmentPresenter {value} />
|
||||||
</div>
|
</div>
|
||||||
</video>
|
</video>
|
||||||
<div class="more">
|
<div class="actions">
|
||||||
<ActionIcon
|
<AttachmentActions attachment={value} {isSaved} />
|
||||||
icon={IconMoreH}
|
|
||||||
size={'small'}
|
|
||||||
action={(e) => {
|
|
||||||
showMenu(e)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex container buttonContainer">
|
<div class="flex container buttonContainer">
|
||||||
<AttachmentPresenter {value} />
|
<AttachmentPresenter {value} />
|
||||||
<div class="more">
|
<div class="actions">
|
||||||
<ActionIcon
|
<AttachmentActions attachment={value} {isSaved} />
|
||||||
icon={IconMoreH}
|
|
||||||
size={'small'}
|
|
||||||
action={(e) => {
|
|
||||||
showMenu(e)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@ -137,14 +82,14 @@
|
|||||||
|
|
||||||
.buttonContainer {
|
.buttonContainer {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
.more {
|
.actions {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonContainer:hover {
|
.buttonContainer:hover {
|
||||||
.more {
|
.actions {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import contact, { Employee } from '@anticrm/contact'
|
import contact, { Employee } from '@anticrm/contact'
|
||||||
import { EmployeeAccount } from '@anticrm/contact'
|
import { EmployeeAccount } from '@anticrm/contact'
|
||||||
import core, { Class, Doc, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
import core, { Class, Doc, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||||
import { getClient } from '@anticrm/presentation'
|
import { getClient, getFileUrl } from '@anticrm/presentation'
|
||||||
import ui, {
|
import ui, {
|
||||||
getCurrentLocation,
|
getCurrentLocation,
|
||||||
location,
|
location,
|
||||||
@ -27,7 +27,8 @@
|
|||||||
showPopup,
|
showPopup,
|
||||||
navigate,
|
navigate,
|
||||||
EditWithIcon,
|
EditWithIcon,
|
||||||
Spinner
|
Spinner,
|
||||||
|
Icon
|
||||||
} from '@anticrm/ui'
|
} from '@anticrm/ui'
|
||||||
import { Menu } from '@anticrm/view-resources'
|
import { Menu } from '@anticrm/view-resources'
|
||||||
import { onDestroy } from 'svelte'
|
import { onDestroy } from 'svelte'
|
||||||
@ -39,6 +40,7 @@
|
|||||||
sortModeToOptionObject
|
sortModeToOptionObject
|
||||||
} from '..'
|
} from '..'
|
||||||
import attachment from '../plugin'
|
import attachment from '../plugin'
|
||||||
|
import FileDownload from './icons/FileDownload.svelte'
|
||||||
import FileBrowserFilters from './FileBrowserFilters.svelte'
|
import FileBrowserFilters from './FileBrowserFilters.svelte'
|
||||||
import FileBrowserSortMenu from './FileBrowserSortMenu.svelte'
|
import FileBrowserSortMenu from './FileBrowserSortMenu.svelte'
|
||||||
|
|
||||||
@ -156,6 +158,9 @@
|
|||||||
<AttachmentPresenter value={attachment} />
|
<AttachmentPresenter value={attachment} />
|
||||||
</div>
|
</div>
|
||||||
<div class="eAttachmentRowActions" class:fixed={i === selectedFileNumber}>
|
<div class="eAttachmentRowActions" class:fixed={i === selectedFileNumber}>
|
||||||
|
<a href={getFileUrl(attachment.file)} download={attachment.name}>
|
||||||
|
<Icon icon={FileDownload} size={'small'} />
|
||||||
|
</a>
|
||||||
<div id="context-menu" class="eAttachmentRowMenu" on:click={(event) => showFileMenu(event, attachment, i)}>
|
<div id="context-menu" class="eAttachmentRowMenu" on:click={(event) => showFileMenu(event, attachment, i)}>
|
||||||
<IconMoreV size={'small'} />
|
<IconMoreV size={'small'} />
|
||||||
</div>
|
</div>
|
||||||
@ -195,6 +200,7 @@
|
|||||||
padding: 0.25rem 0;
|
padding: 0.25rem 0;
|
||||||
|
|
||||||
.eAttachmentRowActions {
|
.eAttachmentRowActions {
|
||||||
|
display: flex;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
border: 1px solid var(--theme-bg-focused-border);
|
border: 1px solid var(--theme-bg-focused-border);
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
@ -202,6 +208,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.eAttachmentRowMenu {
|
.eAttachmentRowMenu {
|
||||||
|
margin-left: 0.2rem;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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">
|
||||||
|
export let size: 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" {fill} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||||
|
<path
|
||||||
|
d="M11.2 0H5.8c-.1 0-.3.1-.4.2L1.3 4.5c-.1.1-.1.2-.1.3v7.5c0 2 1.5 3.6 3.5 3.7h6.6c2 0 3.6-1.7 3.5-3.7V3.5c0-1.9-1.6-3.5-3.6-3.5zM5.5 1.4V3c0 1-.7 1.8-1.6 1.8H2.2l3.3-3.4zm8.4 11c0 1.5-1.1 2.7-2.7 2.7H4.7c-1.5-.1-2.6-1.2-2.6-2.7V5.8h1.8c1.4 0 2.6-1.2 2.6-2.8V1h4.8c1.4 0 2.6 1.2 2.7 2.6v8.8h-.1z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M7.7 11.9s.1.1.2.1H8.2c.1 0 .1-.1.2-.1l2-2.1c.2-.2.2-.5 0-.7-.2-.2-.5-.2-.7 0l-1.3 1.3V6.2c.1-.3-.1-.5-.4-.5-.3 0-.5.2-.5.5v4.2L6.2 9.1C6.1 9 6 9 5.9 9s-.2 0-.3.1c-.2.2-.2.5 0 .7l2.1 2.1z"
|
||||||
|
/>
|
||||||
|
</svg>
|
@ -24,6 +24,7 @@ import TxAttachmentCreate from './components/activity/TxAttachmentCreate.svelte'
|
|||||||
import Attachments from './components/Attachments.svelte'
|
import Attachments from './components/Attachments.svelte'
|
||||||
import FileBrowser from './components/FileBrowser.svelte'
|
import FileBrowser from './components/FileBrowser.svelte'
|
||||||
import Photos from './components/Photos.svelte'
|
import Photos from './components/Photos.svelte'
|
||||||
|
import FileDownload from './components/icons/FileDownload.svelte'
|
||||||
import { uploadFile, deleteFile } from './utils'
|
import { uploadFile, deleteFile } from './utils'
|
||||||
import attachment, { Attachment } from '@anticrm/attachment'
|
import attachment, { Attachment } from '@anticrm/attachment'
|
||||||
import { SortingOrder, SortingQuery } from '@anticrm/core'
|
import { SortingOrder, SortingQuery } from '@anticrm/core'
|
||||||
@ -39,7 +40,8 @@ export {
|
|||||||
AttachmentPresenter,
|
AttachmentPresenter,
|
||||||
AttachmentRefInput,
|
AttachmentRefInput,
|
||||||
AttachmentList,
|
AttachmentList,
|
||||||
AttachmentDocList
|
AttachmentDocList,
|
||||||
|
FileDownload
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FileBrowserSortMode {
|
export enum FileBrowserSortMode {
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import attachment, { Attachment } from '@anticrm/attachment'
|
import attachment, { Attachment } from '@anticrm/attachment'
|
||||||
import { AttachmentPresenter } from '@anticrm/attachment-resources'
|
import { AttachmentPresenter, FileDownload } from '@anticrm/attachment-resources'
|
||||||
import { ChunterSpace } from '@anticrm/chunter'
|
import { ChunterSpace } from '@anticrm/chunter'
|
||||||
import { Doc, SortingOrder } from '@anticrm/core'
|
import { Doc, SortingOrder } from '@anticrm/core'
|
||||||
import { createQuery } from '@anticrm/presentation'
|
import { createQuery, getFileUrl } from '@anticrm/presentation'
|
||||||
import { Menu } from '@anticrm/view-resources'
|
import { Menu } from '@anticrm/view-resources'
|
||||||
import { getCurrentLocation, showPopup, IconMoreV, Label, navigate } from '@anticrm/ui'
|
import { getCurrentLocation, showPopup, IconMoreV, Label, navigate, Icon } from '@anticrm/ui'
|
||||||
|
|
||||||
export let channel: ChunterSpace | undefined
|
export let channel: ChunterSpace | undefined
|
||||||
|
|
||||||
@ -65,6 +65,9 @@
|
|||||||
<AttachmentPresenter value={attachment} />
|
<AttachmentPresenter value={attachment} />
|
||||||
</div>
|
</div>
|
||||||
<div class="eAttachmentRowActions" class:fixed={i === selectedRowNumber}>
|
<div class="eAttachmentRowActions" class:fixed={i === selectedRowNumber}>
|
||||||
|
<a href={getFileUrl(attachment.file)} download={attachment.name}>
|
||||||
|
<Icon icon={FileDownload} size={'small'} />
|
||||||
|
</a>
|
||||||
<div id="context-menu" class="eAttachmentRowMenu" on:click={(event) => showMenu(event, attachment, i)}>
|
<div id="context-menu" class="eAttachmentRowMenu" on:click={(event) => showMenu(event, attachment, i)}>
|
||||||
<IconMoreV size={'small'} />
|
<IconMoreV size={'small'} />
|
||||||
</div>
|
</div>
|
||||||
@ -126,6 +129,7 @@
|
|||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
|
|
||||||
.eAttachmentRowActions {
|
.eAttachmentRowActions {
|
||||||
|
display: flex;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
border: 1px solid var(--theme-bg-focused-border);
|
border: 1px solid var(--theme-bg-focused-border);
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
@ -133,6 +137,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.eAttachmentRowMenu {
|
.eAttachmentRowMenu {
|
||||||
|
margin-left: 0.2rem;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
Loading…
Reference in New Issue
Block a user