Drive to cards (#6841)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2024-10-08 22:34:57 +05:00 committed by GitHub
parent 30c08f494b
commit 62e330d111
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 117 additions and 70 deletions

View File

@ -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()

View File

@ -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
} }
]) ])
}, },

View File

@ -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'
} }
}) })
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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">

View File

@ -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}

View File

@ -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'

View File

@ -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' }}

View File

@ -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}

View File

@ -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>

View File

@ -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'

View File

@ -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'

View File

@ -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}

View File

@ -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}

View File

@ -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>

View File

@ -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}

View File

@ -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> {

View File

@ -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}

View File

@ -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()
} }
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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,

View File

@ -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,