mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +03:00
Chunter: file browser additional fixes (#1547)
Signed-off-by: Ruslan Izhitsky <ruslan.izhitskiy@xored.com>
This commit is contained in:
parent
469ac85e99
commit
ca2b5ba0f3
@ -334,7 +334,10 @@ export function createModel (builder: Builder): void {
|
||||
id: 'fileBrowser',
|
||||
label: attachment.string.FileBrowser,
|
||||
icon: attachment.icon.FileBrowser,
|
||||
component: attachment.component.FileBrowser
|
||||
component: attachment.component.FileBrowser,
|
||||
componentProps: {
|
||||
requestedSpaceClasses: [chunter.class.Channel, chunter.class.DirectMessage]
|
||||
}
|
||||
}
|
||||
],
|
||||
spaces: [
|
||||
|
@ -8,15 +8,18 @@
|
||||
"Close": "Close",
|
||||
"NotSelected": "Not selected",
|
||||
"Deselect": "Deselect",
|
||||
"Archived": "(archived)",
|
||||
"AddSocialLinks": "Add social links",
|
||||
"EditSocialLinks": "Edit social links",
|
||||
"Change": "Change",
|
||||
"Remove": "Remove",
|
||||
"Members": "Members",
|
||||
"Search": "Search...",
|
||||
"Spaces": "Spaces",
|
||||
"Unassigned": "Unassigned",
|
||||
"CreateMore": "Create more",
|
||||
"NumberMembers": "{count, plural, =0 {no members} =1 {1 member} other {# members}}",
|
||||
"NumberSpaces": "{count, plural, =0 {In} =1 {In 1 place} other {In # places}}",
|
||||
"InThis": "In this {space}",
|
||||
"NoMatchesInThis": "No matches in this {space}",
|
||||
"NoMatchesFound": "No matches found",
|
||||
|
@ -8,15 +8,18 @@
|
||||
"Close": "Закрыть",
|
||||
"NotSelected": "Не выбрано",
|
||||
"Deselect": "Снять выделение",
|
||||
"Archived": "(архивирован)",
|
||||
"AddSocialLinks": "Добавить контактную информацию",
|
||||
"EditSocialLinks": "Редактировать контактную информацию",
|
||||
"Change": "Изменить",
|
||||
"Remove": "Удалить",
|
||||
"Members": "Участники",
|
||||
"Search": "Поиск...",
|
||||
"Spaces": "Пространства",
|
||||
"Unassigned": "Не назначен",
|
||||
"CreateMore": "Создать еще",
|
||||
"NumberMembers": "{count, plural, =0 {нет участников} =1 {1 участник} other {# участника}}",
|
||||
"NumberSpaces": "{count, plural, =0 {В} =1 {В 1 месте} other {В # местах}}",
|
||||
"InThis": "В этом {space}",
|
||||
"NoMatchesInThis": "В этом {space} совпадения не обнаружены",
|
||||
"NoMatchesFound": "Не найдено соответсвий",
|
||||
|
@ -14,9 +14,10 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { IconFolder } from '@anticrm/ui'
|
||||
import { IconFolder, Label } from '@anticrm/ui'
|
||||
|
||||
import type { Space } from '@anticrm/core'
|
||||
import presentation from '..'
|
||||
|
||||
export let value: Space
|
||||
export let subtitle: string | undefined = undefined
|
||||
@ -27,7 +28,12 @@
|
||||
<div class="flex-center {size} caption-color flex-no-shrink"><IconFolder size={'small'} /></div>
|
||||
<div class="flex-col ml-2 min-w-0">
|
||||
{#if subtitle}<div class="content-dark-color text-sm">{subtitle}</div>{/if}
|
||||
<div class="content-accent-color overflow-label">{value.name}</div>
|
||||
<div class="content-accent-color overflow-label">
|
||||
{value.name}
|
||||
{#if value.archived}
|
||||
<Label label={presentation.string.Archived}/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -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 core, { Class, Ref, Space } from '@anticrm/core'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { translate } from '@anticrm/platform'
|
||||
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui'
|
||||
import { Tooltip, showPopup, Button } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import presentation, { SpacesMultiPopup } from '..'
|
||||
|
||||
export let selectedItems: Ref<Space>[] = []
|
||||
export let _classes: Ref<Class<Space>>[] = []
|
||||
export let label: IntlString
|
||||
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
export let size: ButtonSize = 'small'
|
||||
export let justify: 'left' | 'center' = 'center'
|
||||
export let width: string | undefined = undefined
|
||||
export let labelDirection: TooltipAlignment | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function addSpace (evt: Event): Promise<void> {
|
||||
showPopup(
|
||||
SpacesMultiPopup,
|
||||
{
|
||||
_classes,
|
||||
label,
|
||||
selectedSpaces: selectedItems
|
||||
},
|
||||
evt.target as HTMLElement,
|
||||
() => { },
|
||||
(result) => {
|
||||
if (result !== undefined) {
|
||||
selectedItems = result
|
||||
dispatch('update', selectedItems)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Tooltip {label} fill={width === '100%'} direction={labelDirection}>
|
||||
<Button
|
||||
label={selectedItems.length === 0 ? presentation.string.Spaces : undefined}
|
||||
width={width ?? 'min-content'}
|
||||
{kind} {size} {justify}
|
||||
on:click={addSpace}
|
||||
>
|
||||
<svelte:fragment slot="content">
|
||||
{#if selectedItems.length > 0}
|
||||
<div class="flex-row-center flex-nowrap">
|
||||
{#await translate(presentation.string.NumberSpaces, { count: selectedItems.length }) then text}
|
||||
<span class="ml-1-5">{text}</span>
|
||||
{/await}
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
</Tooltip>
|
114
packages/presentation/src/components/SpacesMultiPopup.svelte
Normal file
114
packages/presentation/src/components/SpacesMultiPopup.svelte
Normal file
@ -0,0 +1,114 @@
|
||||
<!--
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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 { IntlString } from '@anticrm/platform'
|
||||
import { translate } from '@anticrm/platform'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
|
||||
import core, { Class, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||
import { Tooltip, CheckBox, Label } from '@anticrm/ui'
|
||||
|
||||
import { createQuery } from '../utils'
|
||||
import presentation from '..'
|
||||
import SpaceInfo from './SpaceInfo.svelte';
|
||||
|
||||
export let _classes: Ref<Class<Space>>[] = []
|
||||
export let allowDeselect: boolean = false
|
||||
export let titleDeselect: IntlString | undefined = undefined
|
||||
export let placeholder: IntlString = presentation.string.Search
|
||||
export let selected: Ref<Space> | undefined
|
||||
export let selectedSpaces: Ref<Space>[] = []
|
||||
|
||||
let searchQuery: string = ''
|
||||
let spaces: Space[] = []
|
||||
let shownSpaces: Space[] = []
|
||||
let input: HTMLInputElement
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const query = createQuery()
|
||||
const myAccId = getCurrentAccount()._id
|
||||
|
||||
$: query.query<Space>(
|
||||
core.class.Space,
|
||||
{
|
||||
name: { $like: '%' + searchQuery + '%' },
|
||||
_class: { $in: _classes },
|
||||
},
|
||||
result => {
|
||||
spaces = result
|
||||
},
|
||||
{ limit: 200 }
|
||||
)
|
||||
|
||||
$: update(spaces)
|
||||
const update = (spaces_: Space[]) => {
|
||||
shownSpaces = spaces_.filter((sp) => {
|
||||
// don't show archived unless search is specified or this space is selected
|
||||
// show private only if it includes the current user
|
||||
return (!sp.archived || searchQuery || selectedSpaces.includes(sp._id)) && (!sp.private || sp.members.includes(myAccId))
|
||||
})
|
||||
}
|
||||
|
||||
let phTraslate: string = ''
|
||||
$: if (placeholder) translate(placeholder, {}).then(res => { phTraslate = res })
|
||||
|
||||
const isSelected = (space: Space): boolean => {
|
||||
if (selectedSpaces.filter(s => s === space._id).length > 0) return true
|
||||
return false
|
||||
}
|
||||
|
||||
const checkSelected = (space: Space): void => {
|
||||
if (isSelected(space)) {
|
||||
selectedSpaces = selectedSpaces.filter(s => s !== space._id)
|
||||
} else {
|
||||
selectedSpaces.push(space._id)
|
||||
}
|
||||
spaces = spaces
|
||||
dispatch('update', selectedSpaces)
|
||||
}
|
||||
|
||||
onMount(() => { if (input) input.focus() })
|
||||
</script>
|
||||
|
||||
<div class="selectPopup">
|
||||
<div class="header">
|
||||
<input bind:this={input} type='text' bind:value={searchQuery} placeholder={phTraslate} on:change/>
|
||||
</div>
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#each shownSpaces as space}
|
||||
<button class="menu-item" on:click={() => {
|
||||
checkSelected(space)
|
||||
}}>
|
||||
<div class="check pointer-events-none">
|
||||
<CheckBox checked={isSelected(space)} primary />
|
||||
</div>
|
||||
<SpaceInfo size={'medium'} value={space} />
|
||||
{#if allowDeselect && space._id === selected}
|
||||
<div class="check-right pointer-events-none">
|
||||
{#if titleDeselect}
|
||||
<Tooltip label={titleDeselect ?? presentation.string.Deselect}>
|
||||
<CheckBox checked circle primary />
|
||||
</Tooltip>
|
||||
{:else}
|
||||
<CheckBox checked circle primary />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -29,6 +29,8 @@ export { default as MessageBox } from './components/MessageBox.svelte'
|
||||
export { default as MessageViewer } from './components/MessageViewer.svelte'
|
||||
export { default as PDFViewer } from './components/PDFViewer.svelte'
|
||||
export { default as SpaceCreateCard } from './components/SpaceCreateCard.svelte'
|
||||
export { default as SpacesMultiPopup } from './components/SpacesMultiPopup.svelte'
|
||||
export { default as SpaceMultiBoxList } from './components/SpaceMultiBoxList.svelte'
|
||||
export { default as SpaceSelect } from './components/SpaceSelect.svelte'
|
||||
export { default as UserBox } from './components/UserBox.svelte'
|
||||
export { default as UserBoxList } from './components/UserBoxList.svelte'
|
||||
|
@ -37,15 +37,18 @@ export default plugin(presentationId, {
|
||||
Close: '' as IntlString,
|
||||
NotSelected: '' as IntlString,
|
||||
Deselect: '' as IntlString,
|
||||
Archived: '' as IntlString,
|
||||
AddSocialLinks: '' as IntlString,
|
||||
EditSocialLinks: '' as IntlString,
|
||||
Change: '' as IntlString,
|
||||
Remove: '' as IntlString,
|
||||
Members: '' as IntlString,
|
||||
Search: '' as IntlString,
|
||||
Spaces: '' as IntlString,
|
||||
Unassigned: '' as IntlString,
|
||||
CreateMore: '' as IntlString,
|
||||
NumberMembers: '' as IntlString,
|
||||
NumberSpaces: '' as IntlString,
|
||||
InThis: '' as IntlString,
|
||||
NoMatchesInThis: '' as IntlString,
|
||||
NoMatchesFound: '' as IntlString,
|
||||
|
@ -21,10 +21,13 @@
|
||||
"FileBrowserFilterIn": "In",
|
||||
"FileBrowserFilterDate": "Date",
|
||||
"FileBrowserFilterFileType": "File type",
|
||||
"FileBrowserSort": "Sort:",
|
||||
"FileBrowserSortNewest": "Newest file",
|
||||
"FileBrowserSortOldest": "Oldest file",
|
||||
"FileBrowserSortAZ": "A to Z",
|
||||
"FileBrowserSortZA": "Z to A",
|
||||
"FileBrowserSortSmallest": "Smallest file",
|
||||
"FileBrowserSortBiggest": "Biggest file",
|
||||
"FileBrowserDateFilterAny": "Any time",
|
||||
"FileBrowserDateFilterToday": "Today",
|
||||
"FileBrowserDateFilterYesterday": "Yesterday",
|
||||
|
@ -21,10 +21,13 @@
|
||||
"FileBrowserFilterIn": "В",
|
||||
"FileBrowserFilterDate": "Дата",
|
||||
"FileBrowserFilterFileType": "Тип файла",
|
||||
"FileBrowserSort": "Сортировка:",
|
||||
"FileBrowserSortNewest": "Самый новый файл",
|
||||
"FileBrowserSortOldest": "Самый старый файл",
|
||||
"FileBrowserSortAZ": "От А до Я",
|
||||
"FileBrowserSortZA": "От Я до А",
|
||||
"FileBrowserSortSmallest": "Самый маленький файл",
|
||||
"FileBrowserSortBiggest": "Самый большой файл",
|
||||
"FileBrowserDateFilterAny": "В любое время",
|
||||
"FileBrowserDateFilterToday": "Сегодня",
|
||||
"FileBrowserDateFilterYesterday": "Вчера",
|
||||
|
@ -16,127 +16,46 @@
|
||||
import { Attachment } from '@anticrm/attachment'
|
||||
import contact, { Employee } from '@anticrm/contact'
|
||||
import { EmployeeAccount } from '@anticrm/contact'
|
||||
import { Doc, getCurrentAccount, Ref, SortingOrder, SortingQuery, Space } from '@anticrm/core'
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import { getClient, UserBoxList } from '@anticrm/presentation'
|
||||
import { DropdownLabelsIntl, IconMoreV, Label, Menu as UIMenu, showPopup } from '@anticrm/ui'
|
||||
import core, { Class, Doc, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import ui, {
|
||||
getCurrentLocation,
|
||||
location,
|
||||
IconMoreV,
|
||||
IconSearch,
|
||||
Label,
|
||||
showPopup,
|
||||
navigate,
|
||||
EditWithIcon,
|
||||
Spinner
|
||||
} from '@anticrm/ui'
|
||||
import { Menu } from '@anticrm/view-resources'
|
||||
import { AttachmentPresenter } from '..'
|
||||
import { onDestroy } from 'svelte'
|
||||
import {
|
||||
AttachmentPresenter,
|
||||
FileBrowserSortMode,
|
||||
dateFileBrowserFilters,
|
||||
fileTypeFileBrowserFilters,
|
||||
sortModeToOptionObject
|
||||
} from '..'
|
||||
import attachment from '../plugin'
|
||||
|
||||
enum SortMode {
|
||||
NewestFile,
|
||||
OldestFile,
|
||||
AscendingAlphabetical,
|
||||
DescendingAlphabetical
|
||||
}
|
||||
|
||||
const msInDay = 24 * 60 * 60 * 1000
|
||||
const getBeginningOfToday = () => {
|
||||
const date = new Date()
|
||||
date.setUTCHours(0, 0, 0, 0)
|
||||
return date.getTime()
|
||||
}
|
||||
const dateObjects = [
|
||||
{
|
||||
id: 'dateAny',
|
||||
label: attachment.string.FileBrowserDateFilterAny,
|
||||
getDate: () => {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'dateToday',
|
||||
label: attachment.string.FileBrowserDateFilterToday,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfToday() }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'dateYesterday',
|
||||
label: attachment.string.FileBrowserDateFilterYesterday,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfToday() - msInDay, $lt: getBeginningOfToday() }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date7Days',
|
||||
label: attachment.string.FileBrowserDateFilter7Days,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfToday() - msInDay * 6 }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date30Days',
|
||||
label: attachment.string.FileBrowserDateFilter30Days,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfToday() - msInDay * 29 }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date3Months',
|
||||
label: attachment.string.FileBrowserDateFilter3Months,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfToday() - msInDay * 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date12Months',
|
||||
label: attachment.string.FileBrowserDateFilter12Months,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfToday() - msInDay * 364 }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const fileTypeObjects = [
|
||||
{
|
||||
id: 'typeAny',
|
||||
label: attachment.string.FileBrowserTypeFilterAny,
|
||||
getType: () => {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typeImage',
|
||||
label: attachment.string.FileBrowserTypeFilterImages,
|
||||
getType: () => {
|
||||
return { $like: '%image/%' }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typeAudio',
|
||||
label: attachment.string.FileBrowserTypeFilterAudio,
|
||||
getType: () => {
|
||||
return { $like: '%audio/%' }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typeVideo',
|
||||
label: attachment.string.FileBrowserTypeFilterVideos,
|
||||
getType: () => {
|
||||
return { $like: '%video/%' }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typePDF',
|
||||
label: attachment.string.FileBrowserTypeFilterPDFs,
|
||||
getType: () => {
|
||||
return 'application/pdf'
|
||||
}
|
||||
}
|
||||
]
|
||||
import FileBrowserFilters from './FileBrowserFilters.svelte'
|
||||
import FileBrowserSortMenu from './FileBrowserSortMenu.svelte'
|
||||
|
||||
const client = getClient()
|
||||
export let space: Space | undefined
|
||||
const loc = getCurrentLocation()
|
||||
const spaceId: Ref<Space> | undefined = loc.query?.spaceId as Ref<Space> | undefined
|
||||
export let requestedSpaceClasses: Ref<Class<Space>>[] = []
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
let participants: Ref<Employee>[] = [currentUser.employee]
|
||||
const assignee: Ref<Employee> | null = null
|
||||
let selectedParticipants: Ref<Employee>[] = [currentUser.employee]
|
||||
let selectedSpaces: Ref<Space>[] = []
|
||||
let searchQuery: string = ''
|
||||
let isLoading = false
|
||||
|
||||
let attachments: Attachment[] = []
|
||||
let selectedFileNumber: number | undefined
|
||||
|
||||
let selectedSort: SortMode = SortMode.NewestFile
|
||||
let selectedSort: FileBrowserSortMode = FileBrowserSortMode.NewestFile
|
||||
let selectedDateId = 'dateAny'
|
||||
let selectedFileTypeId = 'typeAny'
|
||||
|
||||
@ -147,135 +66,89 @@
|
||||
})
|
||||
}
|
||||
|
||||
const showSortMenu = async (ev: Event): Promise<void> => {
|
||||
showPopup(
|
||||
UIMenu,
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: sortModeToString(SortMode.NewestFile),
|
||||
action: () => {
|
||||
selectedSort = SortMode.NewestFile
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(SortMode.OldestFile),
|
||||
action: () => {
|
||||
selectedSort = SortMode.OldestFile
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(SortMode.AscendingAlphabetical),
|
||||
action: () => {
|
||||
selectedSort = SortMode.AscendingAlphabetical
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(SortMode.DescendingAlphabetical),
|
||||
action: () => {
|
||||
selectedSort = SortMode.DescendingAlphabetical
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
ev.target as HTMLElement
|
||||
)
|
||||
$: fetch(searchQuery, selectedSort, selectedFileTypeId, selectedDateId, selectedParticipants, selectedSpaces)
|
||||
|
||||
async function fetch(
|
||||
searchQuery_: string,
|
||||
selectedSort_: FileBrowserSortMode,
|
||||
selectedFileTypeId_: string,
|
||||
selectedDateId_: string,
|
||||
selectedParticipants_: Ref<Employee>[],
|
||||
selectedSpaces_: Ref<Space>[]
|
||||
) {
|
||||
isLoading = true
|
||||
|
||||
const nameQuery = searchQuery_ ? { name: { $like: '%' + searchQuery_ + '%' } } : {}
|
||||
|
||||
const accounts = await client.findAll(contact.class.EmployeeAccount, { employee: { $in: selectedParticipants_ } })
|
||||
const senderQuery = accounts.length ? { modifiedBy: { $in: accounts.map((a) => a._id) } } : {}
|
||||
|
||||
let spaceQuery: { space: any }
|
||||
if (selectedSpaces_.length) {
|
||||
spaceQuery = { space: { $in: selectedSpaces_ } }
|
||||
} else {
|
||||
// nothing is selected in space filter - show all available attachments (except for the archived channels)
|
||||
const allSpaces = await client.findAll(core.class.Space, {
|
||||
archived: false,
|
||||
_class: { $in: requestedSpaceClasses }
|
||||
})
|
||||
const availableSpaces = allSpaces
|
||||
.filter((sp) => !sp.private || sp.members.includes(currentUser._id))
|
||||
.map((sp) => sp._id)
|
||||
spaceQuery = { space: { $in: availableSpaces } }
|
||||
}
|
||||
|
||||
const sortModeToString = (sortMode: SortMode): IntlString<{}> => {
|
||||
switch (sortMode) {
|
||||
case SortMode.NewestFile:
|
||||
return attachment.string.FileBrowserSortNewest
|
||||
case SortMode.OldestFile:
|
||||
return attachment.string.FileBrowserSortOldest
|
||||
case SortMode.AscendingAlphabetical:
|
||||
return attachment.string.FileBrowserSortAZ
|
||||
case SortMode.DescendingAlphabetical:
|
||||
return attachment.string.FileBrowserSortZA
|
||||
}
|
||||
}
|
||||
|
||||
const sortModeToOptionObject = (sortMode: SortMode): SortingQuery<Attachment> => {
|
||||
switch (sortMode) {
|
||||
case SortMode.NewestFile:
|
||||
return { modifiedOn: SortingOrder.Descending }
|
||||
case SortMode.OldestFile:
|
||||
return { modifiedOn: SortingOrder.Ascending }
|
||||
case SortMode.AscendingAlphabetical:
|
||||
return { name: SortingOrder.Ascending }
|
||||
case SortMode.DescendingAlphabetical:
|
||||
return { name: SortingOrder.Descending }
|
||||
}
|
||||
}
|
||||
|
||||
$: fetch(selectedSort, selectedFileTypeId, selectedDateId)
|
||||
|
||||
async function fetch (selectedSort_: SortMode, selectedFileTypeId_: string, selectedDateId_: string) {
|
||||
const spaceQuery = space && { space: space._id }
|
||||
const fileType = fileTypeObjects.find((o) => o.id === selectedFileTypeId_)?.getType()
|
||||
const typeQuery = fileType && { type: fileType }
|
||||
const date = dateObjects.find((o) => o.id === selectedDateId_)?.getDate()
|
||||
const date = dateFileBrowserFilters.find((o) => o.id === selectedDateId_)?.getDate()
|
||||
const dateQuery = date && { modifiedOn: date }
|
||||
|
||||
const fileType = fileTypeFileBrowserFilters.find((o) => o.id === selectedFileTypeId_)?.getType()
|
||||
const fileTypeQuery = fileType && { type: fileType }
|
||||
|
||||
attachments = await client.findAll(
|
||||
attachment.class.Attachment,
|
||||
{ ...spaceQuery, ...typeQuery, ...dateQuery },
|
||||
{ ...nameQuery, ...senderQuery, ...spaceQuery, ...dateQuery, ...fileTypeQuery },
|
||||
{
|
||||
sort: sortModeToOptionObject(selectedSort_)
|
||||
sort: sortModeToOptionObject(selectedSort_),
|
||||
limit: 200
|
||||
}
|
||||
)
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
onDestroy(
|
||||
location.subscribe(async (loc) => {
|
||||
loc.query = undefined
|
||||
navigate(loc)
|
||||
})
|
||||
)
|
||||
</script>
|
||||
|
||||
<div class="ac-header full divide">
|
||||
<div class="ac-header__wrap-title">
|
||||
<span class="ac-header__title"><Label label={attachment.string.FileBrowser} /></span>
|
||||
</div>
|
||||
<EditWithIcon icon={IconSearch} bind:value={searchQuery} placeholder={ui.string.SearchDots} />
|
||||
</div>
|
||||
<div class="filterBlockContainer">
|
||||
<div class="simpleFilterButton">
|
||||
<UserBoxList
|
||||
_class={contact.class.Employee}
|
||||
items={participants}
|
||||
label={attachment.string.FileBrowserFilterFrom}
|
||||
on:update={(evt) => {
|
||||
participants = evt.detail
|
||||
}}
|
||||
noItems={attachment.string.NoParticipants}
|
||||
/>
|
||||
</div>
|
||||
<!-- TODO: wait for In filter -->
|
||||
<!-- <div class="simpleFilterButton">
|
||||
<UserBox _class={contact.class.Employee} label={attachment.string.FileBrowserFilterIn} bind:value={assignee} />
|
||||
</div> -->
|
||||
<div class="simpleFilterButton">
|
||||
<DropdownLabelsIntl
|
||||
items={dateObjects}
|
||||
placeholder={attachment.string.FileBrowserFilterDate}
|
||||
label={attachment.string.FileBrowserFilterDate}
|
||||
bind:selected={selectedDateId}
|
||||
/>
|
||||
</div>
|
||||
<div class="simpleFilterButton">
|
||||
<DropdownLabelsIntl
|
||||
items={fileTypeObjects}
|
||||
placeholder={attachment.string.FileBrowserFilterFileType}
|
||||
label={attachment.string.FileBrowserFilterFileType}
|
||||
bind:selected={selectedFileTypeId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<FileBrowserFilters
|
||||
{requestedSpaceClasses}
|
||||
{spaceId}
|
||||
bind:selectedParticipants
|
||||
bind:selectedSpaces
|
||||
bind:selectedDateId
|
||||
bind:selectedFileTypeId
|
||||
/>
|
||||
<div class="group">
|
||||
<div class="groupHeader">
|
||||
<div class="eGroupHeaderCount">
|
||||
<Label label={attachment.string.FileBrowserFileCounter} params={{ results: attachments?.length ?? 0 }} />
|
||||
</div>
|
||||
<div class="eGroupHeaderSortMenu" on:click={(event) => showSortMenu(event)}>
|
||||
{'Sort: '}
|
||||
<Label label={sortModeToString(selectedSort)} />
|
||||
<FileBrowserSortMenu bind:selectedSort />
|
||||
</div>
|
||||
{#if isLoading}
|
||||
<div class="ml-4">
|
||||
<Spinner />
|
||||
</div>
|
||||
{#if attachments?.length}
|
||||
{:else if attachments?.length}
|
||||
<div class="flex-col">
|
||||
{#each attachments as attachment, i}
|
||||
<div class="flex-between attachmentRow" class:fixed={i === selectedFileNumber}>
|
||||
@ -299,9 +172,8 @@
|
||||
|
||||
<style lang="scss">
|
||||
.group {
|
||||
border: 1px solid var(--theme-bg-focused-border);
|
||||
border-radius: 1rem;
|
||||
padding: 1rem 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.groupHeader {
|
||||
@ -313,10 +185,6 @@
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
|
||||
.eGroupHeaderSortMenu {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.attachmentRow {
|
||||
@ -360,16 +228,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filterBlockContainer {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.simpleFilterButton {
|
||||
min-width: 4rem;
|
||||
max-width: 12rem;
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,82 @@
|
||||
<!--
|
||||
// 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 contact, { Employee } from '@anticrm/contact'
|
||||
import { Class, Ref, Space } from '@anticrm/core'
|
||||
import { SpaceMultiBoxList, UserBoxList } from '@anticrm/presentation'
|
||||
import { DropdownLabelsIntl } from '@anticrm/ui'
|
||||
import attachment from '../plugin'
|
||||
import { dateFileBrowserFilters, fileTypeFileBrowserFilters } from '..'
|
||||
|
||||
export let requestedSpaceClasses: Ref<Class<Space>>[]
|
||||
export let spaceId: Ref<Space> | undefined
|
||||
export let selectedParticipants: Ref<Employee>[]
|
||||
export let selectedSpaces: Ref<Space>[]
|
||||
export let selectedDateId: string
|
||||
export let selectedFileTypeId: string
|
||||
</script>
|
||||
|
||||
<div class="filterBlockContainer">
|
||||
<div class="simpleFilterButton">
|
||||
<UserBoxList
|
||||
_class={contact.class.Employee}
|
||||
items={selectedParticipants}
|
||||
label={attachment.string.FileBrowserFilterFrom}
|
||||
on:update={(evt) => {
|
||||
selectedParticipants = evt.detail
|
||||
}}
|
||||
noItems={attachment.string.NoParticipants}
|
||||
/>
|
||||
</div>
|
||||
<div class="simpleFilterButton">
|
||||
<SpaceMultiBoxList
|
||||
_classes={requestedSpaceClasses}
|
||||
label={attachment.string.FileBrowserFilterIn}
|
||||
selectedItems={spaceId ? [spaceId] : []}
|
||||
on:update={(evt) => {
|
||||
selectedSpaces = evt.detail
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="simpleFilterButton">
|
||||
<DropdownLabelsIntl
|
||||
items={dateFileBrowserFilters}
|
||||
placeholder={attachment.string.FileBrowserFilterDate}
|
||||
label={attachment.string.FileBrowserFilterDate}
|
||||
bind:selected={selectedDateId}
|
||||
/>
|
||||
</div>
|
||||
<div class="simpleFilterButton">
|
||||
<DropdownLabelsIntl
|
||||
items={fileTypeFileBrowserFilters}
|
||||
placeholder={attachment.string.FileBrowserFilterFileType}
|
||||
label={attachment.string.FileBrowserFilterFileType}
|
||||
bind:selected={selectedFileTypeId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.filterBlockContainer {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.simpleFilterButton {
|
||||
max-width: 12rem;
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,83 @@
|
||||
<script lang="ts">
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import { Label, Menu, showPopup } from '@anticrm/ui'
|
||||
import { FileBrowserSortMode } from '..'
|
||||
import attachment from '../plugin'
|
||||
|
||||
export let selectedSort: FileBrowserSortMode
|
||||
|
||||
const sortModeToString = (sortMode: FileBrowserSortMode): IntlString<{}> => {
|
||||
switch (sortMode) {
|
||||
case FileBrowserSortMode.NewestFile:
|
||||
return attachment.string.FileBrowserSortNewest
|
||||
case FileBrowserSortMode.OldestFile:
|
||||
return attachment.string.FileBrowserSortOldest
|
||||
case FileBrowserSortMode.AscendingAlphabetical:
|
||||
return attachment.string.FileBrowserSortAZ
|
||||
case FileBrowserSortMode.DescendingAlphabetical:
|
||||
return attachment.string.FileBrowserSortZA
|
||||
case FileBrowserSortMode.SmallestSize:
|
||||
return attachment.string.FileBrowserSortSmallest
|
||||
case FileBrowserSortMode.BiggestSize:
|
||||
return attachment.string.FileBrowserSortBiggest
|
||||
}
|
||||
}
|
||||
|
||||
const showSortMenu = async (ev: Event): Promise<void> => {
|
||||
showPopup(
|
||||
Menu,
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: sortModeToString(FileBrowserSortMode.NewestFile),
|
||||
action: () => {
|
||||
selectedSort = FileBrowserSortMode.NewestFile
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(FileBrowserSortMode.OldestFile),
|
||||
action: () => {
|
||||
selectedSort = FileBrowserSortMode.OldestFile
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(FileBrowserSortMode.AscendingAlphabetical),
|
||||
action: () => {
|
||||
selectedSort = FileBrowserSortMode.AscendingAlphabetical
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(FileBrowserSortMode.DescendingAlphabetical),
|
||||
action: () => {
|
||||
selectedSort = FileBrowserSortMode.DescendingAlphabetical
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(FileBrowserSortMode.SmallestSize),
|
||||
action: () => {
|
||||
selectedSort = FileBrowserSortMode.SmallestSize
|
||||
}
|
||||
},
|
||||
{
|
||||
label: sortModeToString(FileBrowserSortMode.BiggestSize),
|
||||
action: () => {
|
||||
selectedSort = FileBrowserSortMode.BiggestSize
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
ev.target as HTMLElement
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="sortMenu" on:click={(event) => showSortMenu(event)}>
|
||||
<Label label={attachment.string.FileBrowserSort} />
|
||||
<Label label={sortModeToString(selectedSort)} />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.sortMenu {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
@ -19,11 +19,25 @@
|
||||
|
||||
<svg class="svg-{size}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g {fill}>
|
||||
<path d="M39.806,72.858h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.119c0-2.176,1.764-3.94,3.94-3.94h8.915 c2.176,0,3.94,1.764,3.94,3.94v37.799C43.746,71.094,41.982,72.858,39.806,72.858z"/>
|
||||
<path d="M68.109,72.821h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.082c0-2.176,1.764-3.94,3.94-3.94h8.915 c2.176,0,3.94,1.764,3.94,3.94v37.799C72.049,71.057,70.285,72.821,68.109,72.821z"/>
|
||||
<path d="M40.489,27.248c0.769,0.719,1.257,1.735,1.257,2.871v37.799c0,2.176-1.764,3.94-3.94,3.94h-8.915 c-0.234,0-0.46-0.03-0.683-0.069c0.704,0.658,1.643,1.069,2.683,1.069h8.915c2.176,0,3.94-1.764,3.94-3.94V31.119 C43.746,29.177,42.338,27.573,40.489,27.248z"/>
|
||||
<path d="M68.792,27.211c0.769,0.719,1.257,1.735,1.257,2.871v37.799c0,2.176-1.764,3.94-3.94,3.94h-8.915 c-0.234,0-0.46-0.03-0.683-0.069c0.704,0.658,1.643,1.069,2.683,1.069h8.915c2.176,0,3.94-1.764,3.94-3.94V31.082 C72.049,29.14,70.641,27.535,68.792,27.211z"/>
|
||||
<path d="M39.806,72.858h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.119 c0-2.176,1.764-3.94,3.94-3.94h8.915c2.176,0,3.94,1.764,3.94,3.94v37.799C43.746,71.094,41.982,72.858,39.806,72.858z" style="fill:none;stroke:#000000;stroke-miterlimit:10;"/>
|
||||
<path d="M68.109,72.821h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.082 c0-2.176,1.764-3.94,3.94-3.94h8.915c2.176,0,3.94,1.764,3.94,3.94v37.799C72.049,71.057,70.285,72.821,68.109,72.821z" style="fill:none;stroke:#000000;stroke-miterlimit:10;"/>
|
||||
<path
|
||||
d="M39.806,72.858h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.119c0-2.176,1.764-3.94,3.94-3.94h8.915 c2.176,0,3.94,1.764,3.94,3.94v37.799C43.746,71.094,41.982,72.858,39.806,72.858z"
|
||||
/>
|
||||
<path
|
||||
d="M68.109,72.821h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.082c0-2.176,1.764-3.94,3.94-3.94h8.915 c2.176,0,3.94,1.764,3.94,3.94v37.799C72.049,71.057,70.285,72.821,68.109,72.821z"
|
||||
/>
|
||||
<path
|
||||
d="M40.489,27.248c0.769,0.719,1.257,1.735,1.257,2.871v37.799c0,2.176-1.764,3.94-3.94,3.94h-8.915 c-0.234,0-0.46-0.03-0.683-0.069c0.704,0.658,1.643,1.069,2.683,1.069h8.915c2.176,0,3.94-1.764,3.94-3.94V31.119 C43.746,29.177,42.338,27.573,40.489,27.248z"
|
||||
/>
|
||||
<path
|
||||
d="M68.792,27.211c0.769,0.719,1.257,1.735,1.257,2.871v37.799c0,2.176-1.764,3.94-3.94,3.94h-8.915 c-0.234,0-0.46-0.03-0.683-0.069c0.704,0.658,1.643,1.069,2.683,1.069h8.915c2.176,0,3.94-1.764,3.94-3.94V31.082 C72.049,29.14,70.641,27.535,68.792,27.211z"
|
||||
/>
|
||||
<path
|
||||
d="M39.806,72.858h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.119 c0-2.176,1.764-3.94,3.94-3.94h8.915c2.176,0,3.94,1.764,3.94,3.94v37.799C43.746,71.094,41.982,72.858,39.806,72.858z"
|
||||
style="fill:none;stroke:#000000;stroke-miterlimit:10;"
|
||||
/>
|
||||
<path
|
||||
d="M68.109,72.821h-8.915c-2.176,0-3.94-1.764-3.94-3.94V31.082 c0-2.176,1.764-3.94,3.94-3.94h8.915c2.176,0,3.94,1.764,3.94,3.94v37.799C72.049,71.057,70.285,72.821,68.109,72.821z"
|
||||
style="fill:none;stroke:#000000;stroke-miterlimit:10;"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
@ -19,8 +19,15 @@
|
||||
|
||||
<svg class="svg-{size}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g {fill}>
|
||||
<path d="M31.356,25.677l38.625,22.3c1.557,0.899,1.557,3.147,0,4.046l-38.625,22.3c-1.557,0.899-3.504-0.225-3.504-2.023V27.7 C27.852,25.902,29.798,24.778,31.356,25.677z"/>
|
||||
<path d="M69.981,47.977l-38.625-22.3c-0.233-0.134-0.474-0.21-0.716-0.259l37.341,21.559c1.557,0.899,1.557,3.147,0,4.046 l-38.625,22.3c-0.349,0.201-0.716,0.288-1.078,0.301c0.656,0.938,1.961,1.343,3.078,0.699l38.625-22.3 C71.538,51.124,71.538,48.876,69.981,47.977z"/>
|
||||
<path d="M31.356,25.677l38.625,22.3c1.557,0.899,1.557,3.147,0,4.046 l-38.625,22.3c-1.557,0.899-3.504-0.225-3.504-2.023V27.7C27.852,25.902,29.798,24.778,31.356,25.677z" style="fill:none;stroke:#000000;stroke-miterlimit:10;"/>
|
||||
<path
|
||||
d="M31.356,25.677l38.625,22.3c1.557,0.899,1.557,3.147,0,4.046l-38.625,22.3c-1.557,0.899-3.504-0.225-3.504-2.023V27.7 C27.852,25.902,29.798,24.778,31.356,25.677z"
|
||||
/>
|
||||
<path
|
||||
d="M69.981,47.977l-38.625-22.3c-0.233-0.134-0.474-0.21-0.716-0.259l37.341,21.559c1.557,0.899,1.557,3.147,0,4.046 l-38.625,22.3c-0.349,0.201-0.716,0.288-1.078,0.301c0.656,0.938,1.961,1.343,3.078,0.699l38.625-22.3 C71.538,51.124,71.538,48.876,69.981,47.977z"
|
||||
/>
|
||||
<path
|
||||
d="M31.356,25.677l38.625,22.3c1.557,0.899,1.557,3.147,0,4.046 l-38.625,22.3c-1.557,0.899-3.504-0.225-3.504-2.023V27.7C27.852,25.902,29.798,24.778,31.356,25.677z"
|
||||
style="fill:none;stroke:#000000;stroke-miterlimit:10;"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
@ -24,9 +24,10 @@ import TxAttachmentCreate from './components/activity/TxAttachmentCreate.svelte'
|
||||
import Attachments from './components/Attachments.svelte'
|
||||
import FileBrowser from './components/FileBrowser.svelte'
|
||||
import Photos from './components/Photos.svelte'
|
||||
import { Resources } from '@anticrm/platform'
|
||||
import { uploadFile, deleteFile } from './utils'
|
||||
import attachment, { Attachment } from '@anticrm/attachment'
|
||||
import { SortingOrder, SortingQuery } from '@anticrm/core'
|
||||
import { IntlString, Resources } from '@anticrm/platform'
|
||||
import preference from '@anticrm/preference'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
|
||||
@ -41,6 +42,143 @@ export {
|
||||
AttachmentDocList
|
||||
}
|
||||
|
||||
export enum FileBrowserSortMode {
|
||||
NewestFile,
|
||||
OldestFile,
|
||||
AscendingAlphabetical,
|
||||
DescendingAlphabetical,
|
||||
SmallestSize,
|
||||
BiggestSize
|
||||
}
|
||||
|
||||
export const sortModeToOptionObject = (sortMode: FileBrowserSortMode): SortingQuery<Attachment> => {
|
||||
switch (sortMode) {
|
||||
case FileBrowserSortMode.NewestFile:
|
||||
return { modifiedOn: SortingOrder.Descending }
|
||||
case FileBrowserSortMode.OldestFile:
|
||||
return { modifiedOn: SortingOrder.Ascending }
|
||||
case FileBrowserSortMode.AscendingAlphabetical:
|
||||
return { name: SortingOrder.Ascending }
|
||||
case FileBrowserSortMode.DescendingAlphabetical:
|
||||
return { name: SortingOrder.Descending }
|
||||
case FileBrowserSortMode.SmallestSize:
|
||||
return { size: SortingOrder.Ascending }
|
||||
case FileBrowserSortMode.BiggestSize:
|
||||
return { size: SortingOrder.Descending }
|
||||
}
|
||||
}
|
||||
|
||||
const msInDay = 24 * 60 * 60 * 1000
|
||||
const getBeginningOfDate = (customDate?: Date) => {
|
||||
if (!customDate) {
|
||||
customDate = new Date()
|
||||
}
|
||||
customDate.setUTCHours(0, 0, 0, 0)
|
||||
return customDate.getTime()
|
||||
}
|
||||
|
||||
export const dateFileBrowserFilters: {
|
||||
id: string
|
||||
label: IntlString<{}>
|
||||
getDate: () => any
|
||||
}[] = [
|
||||
{
|
||||
id: 'dateAny',
|
||||
label: attachment.string.FileBrowserDateFilterAny,
|
||||
getDate: () => {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'dateToday',
|
||||
label: attachment.string.FileBrowserDateFilterToday,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfDate() }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'dateYesterday',
|
||||
label: attachment.string.FileBrowserDateFilterYesterday,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfDate() - msInDay, $lt: getBeginningOfDate() }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date7Days',
|
||||
label: attachment.string.FileBrowserDateFilter7Days,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfDate() - msInDay * 6 }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date30Days',
|
||||
label: attachment.string.FileBrowserDateFilter30Days,
|
||||
getDate: () => {
|
||||
return { $gte: getBeginningOfDate() - msInDay * 29 }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date3Months',
|
||||
label: attachment.string.FileBrowserDateFilter3Months,
|
||||
getDate: () => {
|
||||
const now = new Date()
|
||||
now.setMonth(now.getMonth() - 3)
|
||||
return { $gte: getBeginningOfDate(now) }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'date12Months',
|
||||
label: attachment.string.FileBrowserDateFilter12Months,
|
||||
getDate: () => {
|
||||
const now = new Date()
|
||||
now.setMonth(now.getMonth() - 12)
|
||||
return { $gte: getBeginningOfDate(now) }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export const fileTypeFileBrowserFilters: {
|
||||
id: string
|
||||
label: IntlString<{}>
|
||||
getType: () => any
|
||||
}[] = [
|
||||
{
|
||||
id: 'typeAny',
|
||||
label: attachment.string.FileBrowserTypeFilterAny,
|
||||
getType: () => {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typeImage',
|
||||
label: attachment.string.FileBrowserTypeFilterImages,
|
||||
getType: () => {
|
||||
return { $like: '%image/%' }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typeAudio',
|
||||
label: attachment.string.FileBrowserTypeFilterAudio,
|
||||
getType: () => {
|
||||
return { $like: '%audio/%' }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typeVideo',
|
||||
label: attachment.string.FileBrowserTypeFilterVideos,
|
||||
getType: () => {
|
||||
return { $like: '%video/%' }
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'typePDF',
|
||||
label: attachment.string.FileBrowserTypeFilterPDFs,
|
||||
getType: () => {
|
||||
return 'application/pdf'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export async function AddAttachmentToSaved(attach: Attachment): Promise<void> {
|
||||
const client = getClient()
|
||||
|
||||
|
@ -32,22 +32,13 @@ export default mergeIds(attachmentId, attachment, {
|
||||
FileBrowserFilterIn: '' as IntlString,
|
||||
FileBrowserFilterDate: '' as IntlString,
|
||||
FileBrowserFilterFileType: '' as IntlString,
|
||||
FileBrowserSort: '' as IntlString,
|
||||
FileBrowserSortNewest: '' as IntlString,
|
||||
FileBrowserSortOldest: '' as IntlString,
|
||||
FileBrowserSortAZ: '' as IntlString,
|
||||
FileBrowserSortZA: '' as IntlString,
|
||||
FileBrowserDateFilterAny: '' as IntlString,
|
||||
FileBrowserDateFilterToday: '' as IntlString,
|
||||
FileBrowserDateFilterYesterday: '' as IntlString,
|
||||
FileBrowserDateFilter7Days: '' as IntlString,
|
||||
FileBrowserDateFilter30Days: '' as IntlString,
|
||||
FileBrowserDateFilter3Months: '' as IntlString,
|
||||
FileBrowserDateFilter12Months: '' as IntlString,
|
||||
FileBrowserTypeFilterAny: '' as IntlString,
|
||||
FileBrowserTypeFilterImages: '' as IntlString,
|
||||
FileBrowserTypeFilterAudio: '' as IntlString,
|
||||
FileBrowserTypeFilterVideos: '' as IntlString,
|
||||
FileBrowserTypeFilterPDFs: '' as IntlString,
|
||||
FileBrowserSortSmallest: '' as IntlString,
|
||||
FileBrowserSortBiggest: '' as IntlString,
|
||||
AddAttachmentToSaved: '' as IntlString,
|
||||
RemoveAttachmentFromSaved: '' as IntlString
|
||||
},
|
||||
|
@ -71,6 +71,18 @@ export default plugin(attachmentId, {
|
||||
Files: '' as IntlString,
|
||||
NoFiles: '' as IntlString,
|
||||
NoParticipants: '' as IntlString,
|
||||
ShowMoreAttachments: '' as IntlString
|
||||
ShowMoreAttachments: '' as IntlString,
|
||||
FileBrowserDateFilterAny: '' as IntlString,
|
||||
FileBrowserDateFilterToday: '' as IntlString,
|
||||
FileBrowserDateFilterYesterday: '' as IntlString,
|
||||
FileBrowserDateFilter7Days: '' as IntlString,
|
||||
FileBrowserDateFilter30Days: '' as IntlString,
|
||||
FileBrowserDateFilter3Months: '' as IntlString,
|
||||
FileBrowserDateFilter12Months: '' as IntlString,
|
||||
FileBrowserTypeFilterAny: '' as IntlString,
|
||||
FileBrowserTypeFilterImages: '' as IntlString,
|
||||
FileBrowserTypeFilterAudio: '' as IntlString,
|
||||
FileBrowserTypeFilterVideos: '' as IntlString,
|
||||
FileBrowserTypeFilterPDFs: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -77,6 +77,7 @@
|
||||
on:click={() => {
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = 'fileBrowser'
|
||||
loc.query = channel ? { spaceId: channel._id } : {}
|
||||
navigate(loc)
|
||||
}}
|
||||
>
|
||||
|
Loading…
Reference in New Issue
Block a user