mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-21 16:09:12 +03:00
Drive to cards (#6841)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
30c08f494b
commit
62e330d111
@ -54,7 +54,7 @@ import {
|
|||||||
TypeTimestamp,
|
TypeTimestamp,
|
||||||
UX
|
UX
|
||||||
} from '@hcengineering/model'
|
} from '@hcengineering/model'
|
||||||
import { TAttachedDoc, TDoc, TType, TTypedSpace } from '@hcengineering/model-core'
|
import { TAttachedDoc, TCard, TType, TTypedSpace } from '@hcengineering/model-core'
|
||||||
import presentation from '@hcengineering/model-presentation'
|
import presentation from '@hcengineering/model-presentation'
|
||||||
import print from '@hcengineering/model-print'
|
import print from '@hcengineering/model-print'
|
||||||
import tracker from '@hcengineering/model-tracker'
|
import tracker from '@hcengineering/model-tracker'
|
||||||
@ -84,19 +84,19 @@ export class TDefaultDriveTypeData extends TDrive implements RolesAssignment {
|
|||||||
[key: Ref<Role>]: Ref<Account>[]
|
[key: Ref<Role>]: Ref<Account>[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(drive.class.Resource, core.class.Doc, DOMAIN_DRIVE)
|
@Model(drive.class.Resource, core.class.Card, DOMAIN_DRIVE)
|
||||||
@UX(drive.string.Resource)
|
@UX(drive.string.Resource)
|
||||||
export class TResource extends TDoc implements Resource {
|
export class TResource extends TCard implements Resource {
|
||||||
declare space: Ref<Drive>
|
declare space: Ref<Drive>
|
||||||
|
|
||||||
@Prop(TypeString(), drive.string.Name)
|
@Prop(TypeString(), drive.string.Name)
|
||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
name!: string
|
declare title: string
|
||||||
|
|
||||||
@Prop(TypeRef(drive.class.Resource), drive.string.Parent)
|
@Prop(TypeRef(drive.class.Resource), drive.string.Parent)
|
||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
@ReadOnly()
|
@ReadOnly()
|
||||||
parent!: Ref<Resource>
|
declare parent: Ref<Resource>
|
||||||
|
|
||||||
@Prop(TypeRef(drive.class.Resource), drive.string.Path)
|
@Prop(TypeRef(drive.class.Resource), drive.string.Path)
|
||||||
@ReadOnly()
|
@ReadOnly()
|
||||||
@ -169,7 +169,7 @@ export class TFileVersion extends TAttachedDoc implements FileVersion {
|
|||||||
|
|
||||||
@Prop(TypeString(), drive.string.Name)
|
@Prop(TypeString(), drive.string.Name)
|
||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
name!: string
|
title!: string
|
||||||
|
|
||||||
@Prop(TypeRef(core.class.Blob), drive.string.File)
|
@Prop(TypeRef(core.class.Blob), drive.string.File)
|
||||||
@ReadOnly()
|
@ReadOnly()
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import core, { type Blob, type Ref, DOMAIN_BLOB, generateId, toIdMap } from '@hcengineering/core'
|
import core, { type Blob, type Ref, DOMAIN_BLOB, generateId, toIdMap } from '@hcengineering/core'
|
||||||
import type { File, FileVersion } from '@hcengineering/drive'
|
import type { Drive, File, FileVersion, Resource } from '@hcengineering/drive'
|
||||||
import {
|
import {
|
||||||
type MigrateOperation,
|
type MigrateOperation,
|
||||||
type MigrationClient,
|
type MigrationClient,
|
||||||
@ -56,8 +56,8 @@ async function migrateFileVersions (client: MigrationClient): Promise<void> {
|
|||||||
collection: 'versions',
|
collection: 'versions',
|
||||||
modifiedOn: file.modifiedOn,
|
modifiedOn: file.modifiedOn,
|
||||||
modifiedBy: file.modifiedBy,
|
modifiedBy: file.modifiedBy,
|
||||||
space: file.space,
|
space: file.space as Ref<Drive>,
|
||||||
name: exfile.name,
|
title: exfile.title,
|
||||||
file: blob._id,
|
file: blob._id,
|
||||||
size: blob.size,
|
size: blob.size,
|
||||||
lastModified: blob.modifiedOn,
|
lastModified: blob.modifiedOn,
|
||||||
@ -86,12 +86,52 @@ async function migrateFileVersions (client: MigrationClient): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function renameFields (client: MigrationClient): Promise<void> {
|
||||||
|
const resources = await client.find<Resource>(DOMAIN_DRIVE, {
|
||||||
|
_class: { $in: [drive.class.Resource, drive.class.File, drive.class.Folder] },
|
||||||
|
name: { $exists: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const resource of resources) {
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_DRIVE,
|
||||||
|
{ _id: resource._id },
|
||||||
|
{
|
||||||
|
$rename: {
|
||||||
|
name: 'title'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const versions = await client.find<FileVersion>(DOMAIN_DRIVE, {
|
||||||
|
_class: drive.class.FileVersion,
|
||||||
|
name: { $exists: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const version of versions) {
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_DRIVE,
|
||||||
|
{ _id: version._id },
|
||||||
|
{
|
||||||
|
$rename: {
|
||||||
|
name: 'title'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const driveOperation: MigrateOperation = {
|
export const driveOperation: MigrateOperation = {
|
||||||
async migrate (client: MigrationClient): Promise<void> {
|
async migrate (client: MigrationClient): Promise<void> {
|
||||||
await tryMigrate(client, driveId, [
|
await tryMigrate(client, driveId, [
|
||||||
{
|
{
|
||||||
state: 'file-versions',
|
state: 'file-versions',
|
||||||
func: migrateFileVersions
|
func: migrateFileVersions
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: 'renameFields',
|
||||||
|
func: renameFields
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
@ -43,14 +43,14 @@ export function createModel (builder: Builder): void {
|
|||||||
builder.mixin(drive.class.File, core.class.Class, serverCore.mixin.SearchPresenter, {
|
builder.mixin(drive.class.File, core.class.Class, serverCore.mixin.SearchPresenter, {
|
||||||
searchConfig: {
|
searchConfig: {
|
||||||
icon: drive.icon.File,
|
icon: drive.icon.File,
|
||||||
title: 'name'
|
title: 'title'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(drive.class.Folder, core.class.Class, serverCore.mixin.SearchPresenter, {
|
builder.mixin(drive.class.Folder, core.class.Class, serverCore.mixin.SearchPresenter, {
|
||||||
searchConfig: {
|
searchConfig: {
|
||||||
icon: drive.icon.Folder,
|
icon: drive.icon.Folder,
|
||||||
title: 'name'
|
title: 'title'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ export interface Doc<S extends Space = Space> extends Obj {
|
|||||||
|
|
||||||
export interface Card extends Doc {
|
export interface Card extends Doc {
|
||||||
title: string
|
title: string
|
||||||
description: CollaborativeDoc | null
|
description?: CollaborativeDoc | null
|
||||||
identifier?: string
|
identifier?: string
|
||||||
parent?: Ref<Card> | null
|
parent?: Ref<Card> | null
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data: Omit<Data<Folder>, 'path'> = {
|
const data: Omit<Data<Folder>, 'path'> = {
|
||||||
name: getTitle(name),
|
title: getTitle(name),
|
||||||
parent: _parent ?? drive.ids.Root
|
parent: _parent ?? drive.ids.Root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
let descendants: Map<Ref<Folder>, Folder[]> = new Map<Ref<Folder>, Folder[]>()
|
let descendants: Map<Ref<Folder>, Folder[]> = new Map<Ref<Folder>, Folder[]>()
|
||||||
|
|
||||||
function getDescendants (obj: Ref<Folder>): Ref<Folder>[] {
|
function getDescendants (obj: Ref<Folder>): Ref<Folder>[] {
|
||||||
return (descendants.get(obj) ?? []).sort((a, b) => a.name.localeCompare(b.name)).map((p) => p._id)
|
return (descendants.get(obj) ?? []).sort((a, b) => a.title.localeCompare(b.title)).map((p) => p._id)
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected: Ref<Doc> | undefined
|
let selected: Ref<Doc> | undefined
|
||||||
@ -134,7 +134,7 @@
|
|||||||
_id={folder._id}
|
_id={folder._id}
|
||||||
folderIcon
|
folderIcon
|
||||||
iconProps={{ fill: 'var(--global-accent-IconColor)' }}
|
iconProps={{ fill: 'var(--global-accent-IconColor)' }}
|
||||||
title={folder.name}
|
title={folder.title}
|
||||||
selected
|
selected
|
||||||
isFold
|
isFold
|
||||||
empty
|
empty
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if object !== undefined && version !== undefined && blob !== undefined && contentType !== undefined}
|
{#if object !== undefined && version !== undefined && blob !== undefined && contentType !== undefined}
|
||||||
<FilePreview file={blob} {contentType} name={version.name} metadata={version.metadata} fit />
|
<FilePreview file={blob} {contentType} name={version.title} metadata={version.metadata} fit />
|
||||||
|
|
||||||
{#if object.versions > 1}
|
{#if object.versions > 1}
|
||||||
<div class="w-full mt-6">
|
<div class="w-full mt-6">
|
||||||
|
@ -13,14 +13,19 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Folder } from '@hcengineering/drive'
|
import { type Drive, type Folder } from '@hcengineering/drive'
|
||||||
|
|
||||||
|
import { type Ref } from '@hcengineering/core'
|
||||||
import FolderBrowser from './FolderBrowser.svelte'
|
import FolderBrowser from './FolderBrowser.svelte'
|
||||||
|
|
||||||
export let object: Folder
|
export let object: Folder
|
||||||
export let readonly: boolean = false
|
export let readonly: boolean = false
|
||||||
|
|
||||||
|
function getSpace (object: Folder): Ref<Drive> {
|
||||||
|
return object.space as Ref<Drive>
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if object}
|
{#if object}
|
||||||
<FolderBrowser space={object.space} parent={object._id} {readonly} type={'folder'} />
|
<FolderBrowser space={getSpace(object)} parent={object._id} {readonly} type={'folder'} />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Ref } from '@hcengineering/core'
|
import { type Ref, type Space } from '@hcengineering/core'
|
||||||
import { type Drive, type Folder } from '@hcengineering/drive'
|
import { type Drive, type Folder } from '@hcengineering/drive'
|
||||||
import { uploadFilesToDrive } from '../utils'
|
import { uploadFilesToDrive } from '../utils'
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
async (uuid, name, file, path, metadata) => {
|
async (uuid, name, file, path, metadata) => {
|
||||||
const data = {
|
const data = {
|
||||||
file: uuid,
|
file: uuid,
|
||||||
name,
|
title: name,
|
||||||
size: file.size,
|
size: file.size,
|
||||||
type: file.type,
|
type: file.type,
|
||||||
lastModified: file instanceof File ? file.lastModified : Date.now(),
|
lastModified: file instanceof File ? file.lastModified : Date.now(),
|
||||||
@ -108,7 +108,7 @@
|
|||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="utils">
|
<svelte:fragment slot="utils">
|
||||||
<a class="no-line" href={getFileUrl(version.file, object.name)} download={object.name} bind:this={download}>
|
<a class="no-line" href={getFileUrl(version.file, object.title)} download={object.title} bind:this={download}>
|
||||||
<Button
|
<Button
|
||||||
icon={IconDownload}
|
icon={IconDownload}
|
||||||
iconProps={{ size: 'medium' }}
|
iconProps={{ size: 'medium' }}
|
||||||
|
@ -42,14 +42,14 @@
|
|||||||
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
||||||
{:else if type === 'link'}
|
{:else if type === 'link'}
|
||||||
<DocNavLink object={value} {disabled} {accent} {noUnderline}>
|
<DocNavLink object={value} {disabled} {accent} {noUnderline}>
|
||||||
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.title) }}>
|
||||||
{#if shouldShowAvatar}
|
{#if shouldShowAvatar}
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<Icon {icon} size={'small'} />
|
<Icon {icon} size={'small'} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="label nowrap flex flex-gap-2" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
<div class="label nowrap flex flex-gap-2" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
||||||
<span>{value.name}</span>
|
<span>{value.title}</span>
|
||||||
{#if shouldShowVersion}
|
{#if shouldShowVersion}
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>{formatFileVersion(value.version)}</span>
|
<span>{formatFileVersion(value.version)}</span>
|
||||||
@ -58,8 +58,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</DocNavLink>
|
</DocNavLink>
|
||||||
{:else if type === 'text'}
|
{:else if type === 'text'}
|
||||||
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.title) }}>
|
||||||
{value.name}
|
{value.title}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -30,6 +30,6 @@
|
|||||||
<Icon {icon} size={'medium'} />
|
<Icon {icon} size={'medium'} />
|
||||||
</div>
|
</div>
|
||||||
<span class="overflow-label">
|
<span class="overflow-label">
|
||||||
{value.name}
|
{value.title}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
{
|
{
|
||||||
file: value.file,
|
file: value.file,
|
||||||
contentType: value.type,
|
contentType: value.type,
|
||||||
name: value.name,
|
name: value.title,
|
||||||
metadata: value.metadata
|
metadata: value.metadata
|
||||||
},
|
},
|
||||||
'centered'
|
'centered'
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Doc, type DocumentQuery, type Ref, type WithLookup } from '@hcengineering/core'
|
import { type Doc, type DocumentQuery, type Space, type Ref, type WithLookup } from '@hcengineering/core'
|
||||||
import drive, { type Drive, type Folder } from '@hcengineering/drive'
|
import drive, { type Drive, type Folder } from '@hcengineering/drive'
|
||||||
import { Scroller, SearchInput, Panel, Button, IconMoreH } from '@hcengineering/ui'
|
import { Scroller, SearchInput, Panel, Button, IconMoreH } from '@hcengineering/ui'
|
||||||
import view, { Viewlet, ViewOptions } from '@hcengineering/view'
|
import view, { Viewlet, ViewOptions } from '@hcengineering/view'
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Ref } from '@hcengineering/core'
|
import { type Ref } from '@hcengineering/core'
|
||||||
import drive, { type Folder } from '@hcengineering/drive'
|
import drive, { Drive, type Folder } from '@hcengineering/drive'
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import { showMenu } from '@hcengineering/view-resources'
|
import { showMenu } from '@hcengineering/view-resources'
|
||||||
|
|
||||||
@ -34,11 +34,13 @@
|
|||||||
$: query.query(drive.class.Folder, { _id }, (res) => {
|
$: query.query(drive.class.Folder, { _id }, (res) => {
|
||||||
;[object] = res
|
;[object] = res
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$: space = object?.space as Ref<Drive>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if object}
|
{#if object}
|
||||||
<FolderBrowser
|
<FolderBrowser
|
||||||
space={object.space}
|
{space}
|
||||||
parent={object._id}
|
parent={object._id}
|
||||||
{object}
|
{object}
|
||||||
{embedded}
|
{embedded}
|
||||||
|
@ -37,20 +37,20 @@
|
|||||||
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
||||||
{:else if type === 'link'}
|
{:else if type === 'link'}
|
||||||
<DocNavLink {disabled} object={value} {accent} {noUnderline}>
|
<DocNavLink {disabled} object={value} {accent} {noUnderline}>
|
||||||
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.title) }}>
|
||||||
{#if shouldShowAvatar}
|
{#if shouldShowAvatar}
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<Icon icon={FolderIcon} size={'small'} fill="var(--global-accent-IconColor)" />
|
<Icon icon={FolderIcon} size={'small'} fill="var(--global-accent-IconColor)" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="label nowrap" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
<span class="label nowrap" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
||||||
{value.name}
|
{value.title}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</DocNavLink>
|
</DocNavLink>
|
||||||
{:else if type === 'text'}
|
{:else if type === 'text'}
|
||||||
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.title) }}>
|
||||||
{value.name}
|
{value.title}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -26,6 +26,6 @@
|
|||||||
<Icon icon={drive.icon.Folder} size={'medium'} />
|
<Icon icon={drive.icon.Folder} size={'medium'} />
|
||||||
</div>
|
</div>
|
||||||
<span class="overflow-label">
|
<span class="overflow-label">
|
||||||
{value.name}
|
{value.title}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
function getDescendants (obj: Ref<Folder>): Ref<Folder>[] {
|
function getDescendants (obj: Ref<Folder>): Ref<Folder>[] {
|
||||||
return (descendants.get(obj) ?? []).sort((a, b) => a.name.localeCompare(b.name)).map((p) => p._id)
|
return (descendants.get(obj) ?? []).sort((a, b) => a.title.localeCompare(b.title)).map((p) => p._id)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getActions (obj: Folder): Promise<Action[]> {
|
async function getActions (obj: Folder): Promise<Action[]> {
|
||||||
@ -67,7 +67,7 @@
|
|||||||
<TreeItem
|
<TreeItem
|
||||||
_id={doc._id}
|
_id={doc._id}
|
||||||
folderIcon
|
folderIcon
|
||||||
title={doc.name}
|
title={doc.title}
|
||||||
selected={selected === doc._id}
|
selected={selected === doc._id}
|
||||||
isFold
|
isFold
|
||||||
empty={desc.length === 0}
|
empty={desc.length === 0}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let space: Ref<Drive> = value.space
|
let space: Ref<Drive> = value.space as Ref<Drive>
|
||||||
let parent: Ref<Folder> = value.parent as Ref<Folder>
|
let parent: Ref<Folder> = value.parent as Ref<Folder>
|
||||||
|
|
||||||
async function save (): Promise<void> {
|
async function save (): Promise<void> {
|
||||||
|
@ -44,13 +44,13 @@
|
|||||||
{#if isFolder}
|
{#if isFolder}
|
||||||
<Icon icon={IconFolderThumbnail} size={'full'} fill={'var(--global-no-priority-PriorityColor)'} />
|
<Icon icon={IconFolderThumbnail} size={'full'} fill={'var(--global-no-priority-PriorityColor)'} />
|
||||||
{:else if previewRef != null && isImage && !isError}
|
{:else if previewRef != null && isImage && !isError}
|
||||||
{#await getBlobRef(previewRef, object.name, sizeToWidth(size)) then blobSrc}
|
{#await getBlobRef(previewRef, object.title, sizeToWidth(size)) then blobSrc}
|
||||||
<img
|
<img
|
||||||
draggable="false"
|
draggable="false"
|
||||||
class="img-fit"
|
class="img-fit"
|
||||||
src={blobSrc.src}
|
src={blobSrc.src}
|
||||||
srcset={blobSrc.srcset}
|
srcset={blobSrc.srcset}
|
||||||
alt={object.name}
|
alt={object.title}
|
||||||
on:error={() => {
|
on:error={() => {
|
||||||
isError = true
|
isError = true
|
||||||
}}
|
}}
|
||||||
@ -58,7 +58,7 @@
|
|||||||
{/await}
|
{/await}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex-center ext-icon">
|
<div class="flex-center ext-icon">
|
||||||
{extensionIconLabel(object.name)}
|
{extensionIconLabel(object.title)}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@ -44,14 +44,14 @@ import { restoreFileVersion, showCreateFolderPopup, showRenameResourcePopup } fr
|
|||||||
|
|
||||||
const toFileObjectSearchResult = (e: WithLookup<File>): ObjectSearchResult => ({
|
const toFileObjectSearchResult = (e: WithLookup<File>): ObjectSearchResult => ({
|
||||||
doc: e,
|
doc: e,
|
||||||
title: e.name,
|
title: e.title,
|
||||||
icon: drive.icon.File,
|
icon: drive.icon.File,
|
||||||
component: FileSearchItem
|
component: FileSearchItem
|
||||||
})
|
})
|
||||||
|
|
||||||
const toFolderObjectSearchResult = (e: WithLookup<Folder>): ObjectSearchResult => ({
|
const toFolderObjectSearchResult = (e: WithLookup<Folder>): ObjectSearchResult => ({
|
||||||
doc: e,
|
doc: e,
|
||||||
title: e.name,
|
title: e.title,
|
||||||
icon: drive.icon.Folder,
|
icon: drive.icon.Folder,
|
||||||
component: FolderSearchItem
|
component: FolderSearchItem
|
||||||
})
|
})
|
||||||
@ -62,7 +62,7 @@ async function queryFile (
|
|||||||
search: string,
|
search: string,
|
||||||
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
||||||
): Promise<ObjectSearchResult[]> {
|
): Promise<ObjectSearchResult[]> {
|
||||||
const q: DocumentQuery<File> = { name: { $like: `%${search}%` } }
|
const q: DocumentQuery<File> = { title: { $like: `%${search}%` } }
|
||||||
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
||||||
q._id = {}
|
q._id = {}
|
||||||
if (filter.in !== undefined) {
|
if (filter.in !== undefined) {
|
||||||
@ -81,7 +81,7 @@ async function queryFolder (
|
|||||||
search: string,
|
search: string,
|
||||||
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
||||||
): Promise<ObjectSearchResult[]> {
|
): Promise<ObjectSearchResult[]> {
|
||||||
const q: DocumentQuery<Folder> = { name: { $like: `%${search}%` } }
|
const q: DocumentQuery<Folder> = { title: { $like: `%${search}%` } }
|
||||||
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
||||||
q._id = {}
|
q._id = {}
|
||||||
if (filter.in !== undefined) {
|
if (filter.in !== undefined) {
|
||||||
@ -111,12 +111,12 @@ async function DownloadFile (doc: WithLookup<File> | Array<WithLookup<File>>): P
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const version = file.$lookup?.file
|
const version = file.$lookup?.file
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
const href = getFileUrl(version.file, version.name)
|
const href = getFileUrl(version.file, version.title)
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
link.style.display = 'none'
|
link.style.display = 'none'
|
||||||
link.target = '_blank'
|
link.target = '_blank'
|
||||||
link.href = href
|
link.href = href
|
||||||
link.download = file.name
|
link.download = file.title
|
||||||
link.click()
|
link.click()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,16 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { type Class, type Doc, type Ref, toIdMap } from '@hcengineering/core'
|
import { type Class, type Doc, type Ref, type Space, toIdMap } from '@hcengineering/core'
|
||||||
import {
|
import drive, {
|
||||||
type Drive,
|
type Drive,
|
||||||
type FileVersion,
|
type FileVersion,
|
||||||
type Folder,
|
type Folder,
|
||||||
type Resource,
|
type Resource,
|
||||||
|
createFile,
|
||||||
createFolder,
|
createFolder,
|
||||||
DriveEvents
|
DriveEvents
|
||||||
} from '@hcengineering/drive'
|
} from '@hcengineering/drive'
|
||||||
import drive, { createFile } from '@hcengineering/drive'
|
|
||||||
import { type Asset, setPlatformStatus, unknownError } from '@hcengineering/platform'
|
import { type Asset, setPlatformStatus, unknownError } from '@hcengineering/platform'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { type AnySvelteComponent, showPopup } from '@hcengineering/ui'
|
import { type AnySvelteComponent, showPopup } from '@hcengineering/ui'
|
||||||
@ -38,12 +38,12 @@ import CreateDrive from './components/CreateDrive.svelte'
|
|||||||
import CreateFolder from './components/CreateFolder.svelte'
|
import CreateFolder from './components/CreateFolder.svelte'
|
||||||
import RenamePopup from './components/RenamePopup.svelte'
|
import RenamePopup from './components/RenamePopup.svelte'
|
||||||
|
|
||||||
|
import { Analytics } from '@hcengineering/analytics'
|
||||||
import FileTypeAudio from './components/icons/FileTypeAudio.svelte'
|
import FileTypeAudio from './components/icons/FileTypeAudio.svelte'
|
||||||
import FileTypeImage from './components/icons/FileTypeImage.svelte'
|
import FileTypeImage from './components/icons/FileTypeImage.svelte'
|
||||||
import FileTypeVideo from './components/icons/FileTypeVideo.svelte'
|
|
||||||
import FileTypePdf from './components/icons/FileTypePdf.svelte'
|
import FileTypePdf from './components/icons/FileTypePdf.svelte'
|
||||||
import FileTypeText from './components/icons/FileTypeText.svelte'
|
import FileTypeText from './components/icons/FileTypeText.svelte'
|
||||||
import { Analytics } from '@hcengineering/analytics'
|
import FileTypeVideo from './components/icons/FileTypeVideo.svelte'
|
||||||
|
|
||||||
async function navigateToDoc (_id: Ref<Doc>, _class: Ref<Class<Doc>>): Promise<void> {
|
async function navigateToDoc (_id: Ref<Doc>, _class: Ref<Class<Doc>>): Promise<void> {
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
@ -58,7 +58,7 @@ export function formatFileVersion (version: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function showCreateFolderPopup (
|
export async function showCreateFolderPopup (
|
||||||
space: Ref<Drive> | undefined,
|
space: Ref<Space> | undefined,
|
||||||
parent: Ref<Folder>,
|
parent: Ref<Folder>,
|
||||||
open = false
|
open = false
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
@ -82,10 +82,10 @@ export async function showEditDrivePopup (drive: Drive): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function showRenameResourcePopup (resource: Resource): Promise<void> {
|
export async function showRenameResourcePopup (resource: Resource): Promise<void> {
|
||||||
showPopup(RenamePopup, { value: resource.name, format: 'text' }, undefined, async (res) => {
|
showPopup(RenamePopup, { value: resource.title }, undefined, async (res) => {
|
||||||
if (res != null && res !== resource.name) {
|
if (res != null && res !== resource.title) {
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
await client.update(resource, { name: res })
|
await client.update(resource, { title: res })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ export async function resolveParents (object: Resource): Promise<Doc[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const root = await client.findOne(drive.class.Drive, { _id: object.space })
|
const root = await client.findOne(drive.class.Drive, { _id: object.space as Ref<Drive> })
|
||||||
if (root !== undefined) {
|
if (root !== undefined) {
|
||||||
parents.push(root)
|
parents.push(root)
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@ async function fileUploadCallback (space: Ref<Drive>, parent: Ref<Folder>): Prom
|
|||||||
|
|
||||||
const query = parent !== drive.ids.Root ? { space, path: parent } : { space }
|
const query = parent !== drive.ids.Root ? { space, path: parent } : { space }
|
||||||
const folders = await client.findAll(drive.class.Folder, query)
|
const folders = await client.findAll(drive.class.Folder, query)
|
||||||
const foldersByName = new Map(folders.map((folder) => [folder.name, folder]))
|
const foldersByName = new Map(folders.map((folder) => [folder.title, folder]))
|
||||||
|
|
||||||
const findParent = async (path: string | undefined): Promise<Ref<Folder>> => {
|
const findParent = async (path: string | undefined): Promise<Ref<Folder>> => {
|
||||||
if (path == null || path.length === 0) {
|
if (path == null || path.length === 0) {
|
||||||
@ -217,16 +217,16 @@ async function fileUploadCallback (space: Ref<Drive>, parent: Ref<Folder>): Prom
|
|||||||
|
|
||||||
let current = parent
|
let current = parent
|
||||||
while (segments.length > 1) {
|
while (segments.length > 1) {
|
||||||
const name = segments.shift()
|
const title = segments.shift()
|
||||||
if (name !== undefined) {
|
if (title !== undefined) {
|
||||||
let folder = foldersByName.get(name)
|
let folder = foldersByName.get(title)
|
||||||
if (folder !== undefined) {
|
if (folder !== undefined) {
|
||||||
current = folder._id
|
current = folder._id
|
||||||
} else {
|
} else {
|
||||||
current = await createFolder(client, space, { name, parent: current })
|
current = await createFolder(client, space, { title, parent: current })
|
||||||
folder = await client.findOne(drive.class.Folder, { _id: current })
|
folder = await client.findOne(drive.class.Folder, { _id: current })
|
||||||
if (folder !== undefined) {
|
if (folder !== undefined) {
|
||||||
foldersByName.set(folder.name, folder)
|
foldersByName.set(folder.title, folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ async function fileUploadCallback (space: Ref<Drive>, parent: Ref<Folder>): Prom
|
|||||||
size: file.size,
|
size: file.size,
|
||||||
type: file.type,
|
type: file.type,
|
||||||
lastModified: file instanceof File ? file.lastModified : Date.now(),
|
lastModified: file instanceof File ? file.lastModified : Date.now(),
|
||||||
name,
|
title: name,
|
||||||
metadata
|
metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { AttachedDoc, Blob, CollectionSize, Doc, Ref, Type, TypedSpace } from '@hcengineering/core'
|
import { AttachedDoc, Blob, Card, CollectionSize, Ref, Type, TypedSpace } from '@hcengineering/core'
|
||||||
|
|
||||||
import drive from './plugin'
|
import drive from './plugin'
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ export function TypeFileVersion (): Type<number> {
|
|||||||
export interface Drive extends TypedSpace {}
|
export interface Drive extends TypedSpace {}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export interface Resource extends Doc<Drive> {
|
export interface Resource extends Card {
|
||||||
name: string
|
title: string
|
||||||
parent: Ref<Resource>
|
parent: Ref<Resource>
|
||||||
path: Ref<Resource>[]
|
path: Ref<Resource>[]
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ export interface File extends Resource {
|
|||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export interface FileVersion extends AttachedDoc<File, 'versions', Drive> {
|
export interface FileVersion extends AttachedDoc<File, 'versions', Drive> {
|
||||||
name: string
|
title: string
|
||||||
file: Ref<Blob>
|
file: Ref<Blob>
|
||||||
size: number
|
size: number
|
||||||
type: string
|
type: string
|
||||||
|
@ -51,7 +51,7 @@ export async function createFile (
|
|||||||
const versionId: Ref<FileVersion> = generateId()
|
const versionId: Ref<FileVersion> = generateId()
|
||||||
|
|
||||||
const fileId = await client.createDoc(drive.class.File, space, {
|
const fileId = await client.createDoc(drive.class.File, space, {
|
||||||
name: data.name,
|
title: data.title,
|
||||||
parent,
|
parent,
|
||||||
path,
|
path,
|
||||||
file: versionId,
|
file: versionId,
|
||||||
|
@ -64,7 +64,7 @@ export class WorkspaceClient {
|
|||||||
if (blob !== undefined) {
|
if (blob !== undefined) {
|
||||||
const data = {
|
const data = {
|
||||||
file: uuid as Ref<Blob>,
|
file: uuid as Ref<Blob>,
|
||||||
name,
|
title: name,
|
||||||
size: blob.size,
|
size: blob.size,
|
||||||
type: blob.contentType,
|
type: blob.contentType,
|
||||||
lastModified: blob.modifiedOn,
|
lastModified: blob.modifiedOn,
|
||||||
|
Loading…
Reference in New Issue
Block a user