mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-17 22:03:09 +00:00
UBERF-7853 Drive search (#6318)
This commit is contained in:
parent
840d26dd01
commit
de06891111
@ -32,6 +32,7 @@
|
||||
"@hcengineering/model": "^0.6.11",
|
||||
"@hcengineering/model-core": "^0.6.0",
|
||||
"@hcengineering/model-preference": "^0.6.0",
|
||||
"@hcengineering/model-presentation": "^0.6.0",
|
||||
"@hcengineering/model-print": "^0.6.0",
|
||||
"@hcengineering/model-tracker": "^0.6.0",
|
||||
"@hcengineering/model-view": "^0.6.0",
|
||||
|
@ -55,6 +55,7 @@ import {
|
||||
UX
|
||||
} from '@hcengineering/model'
|
||||
import { TAttachedDoc, TDoc, TType, TTypedSpace } from '@hcengineering/model-core'
|
||||
import presentation from '@hcengineering/model-presentation'
|
||||
import print from '@hcengineering/model-print'
|
||||
import tracker from '@hcengineering/model-tracker'
|
||||
import view, { type Viewlet, actionTemplates, classPresenter, createAction } from '@hcengineering/model-view'
|
||||
@ -432,6 +433,22 @@ function defineFolder (builder: Builder): void {
|
||||
encode: drive.function.FolderLinkProvider
|
||||
})
|
||||
|
||||
// Search
|
||||
|
||||
builder.createDoc(
|
||||
presentation.class.ObjectSearchCategory,
|
||||
core.space.Model,
|
||||
{
|
||||
title: drive.string.Folders,
|
||||
icon: drive.icon.Drive,
|
||||
label: presentation.string.Search,
|
||||
query: drive.completion.FolderQuery,
|
||||
context: ['search', 'mention', 'spotlight'],
|
||||
classToSearch: drive.class.Folder
|
||||
},
|
||||
drive.completion.FolderCategory
|
||||
)
|
||||
|
||||
// Actions
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, view.mixin.IgnoreActions, {
|
||||
@ -566,6 +583,22 @@ function defineFile (builder: Builder): void {
|
||||
components: { input: chunter.component.ChatMessageInput }
|
||||
})
|
||||
|
||||
// Search
|
||||
|
||||
builder.createDoc(
|
||||
presentation.class.ObjectSearchCategory,
|
||||
core.space.Model,
|
||||
{
|
||||
title: drive.string.Files,
|
||||
icon: drive.icon.Drive,
|
||||
label: presentation.string.Search,
|
||||
query: drive.completion.FileQuery,
|
||||
context: ['search', 'mention', 'spotlight'],
|
||||
classToSearch: drive.class.File
|
||||
},
|
||||
drive.completion.FileCategory
|
||||
)
|
||||
|
||||
// Actions
|
||||
|
||||
builder.mixin(drive.class.File, core.class.Class, view.mixin.IgnoreActions, {
|
||||
|
@ -17,6 +17,7 @@ import type { Doc, Ref } from '@hcengineering/core'
|
||||
import {} from '@hcengineering/core'
|
||||
import { driveId } from '@hcengineering/drive'
|
||||
import drive from '@hcengineering/drive-resources/src/plugin'
|
||||
import { type ObjectSearchCategory, type ObjectSearchFactory } from '@hcengineering/model-presentation'
|
||||
import { type IntlString, type Resource, mergeIds } from '@hcengineering/platform'
|
||||
import { type AnyComponent, type Location } from '@hcengineering/ui'
|
||||
import {
|
||||
@ -55,6 +56,12 @@ export default mergeIds(driveId, drive, {
|
||||
CanRenameFile: '' as Resource<ViewActionAvailabilityFunction>,
|
||||
CanRenameFolder: '' as Resource<ViewActionAvailabilityFunction>
|
||||
},
|
||||
completion: {
|
||||
FileQuery: '' as Resource<ObjectSearchFactory>,
|
||||
FileCategory: '' as Ref<ObjectSearchCategory>,
|
||||
FolderQuery: '' as Resource<ObjectSearchFactory>,
|
||||
FolderCategory: '' as Ref<ObjectSearchCategory>
|
||||
},
|
||||
viewlet: {
|
||||
Grid: '' as Ref<ViewletDescriptor>,
|
||||
DriveTable: '' as Ref<Viewlet>,
|
||||
@ -93,6 +100,8 @@ export default mergeIds(driveId, drive, {
|
||||
Parent: '' as IntlString,
|
||||
Path: '' as IntlString,
|
||||
Drives: '' as IntlString,
|
||||
Files: '' as IntlString,
|
||||
Folders: '' as IntlString,
|
||||
Version: '' as IntlString,
|
||||
Restore: '' as IntlString
|
||||
}
|
||||
|
@ -39,4 +39,18 @@ export function createModel (builder: Builder): void {
|
||||
collectDocs: serverDrive.function.FindFolderResources
|
||||
}
|
||||
)
|
||||
|
||||
builder.mixin(drive.class.File, core.class.Class, serverCore.mixin.SearchPresenter, {
|
||||
searchConfig: {
|
||||
icon: drive.icon.File,
|
||||
title: 'name'
|
||||
}
|
||||
})
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, serverCore.mixin.SearchPresenter, {
|
||||
searchConfig: {
|
||||
icon: drive.icon.Folder,
|
||||
title: 'name'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -4,9 +4,11 @@
|
||||
"Drives": "Drives",
|
||||
"Grid": "Grid",
|
||||
"File": "File",
|
||||
"Files": "Files",
|
||||
"FileVersion": "File version",
|
||||
"FileVersions": "File versions",
|
||||
"Folder": "Folder",
|
||||
"Folders": "Folders",
|
||||
"Resource": "Resource",
|
||||
"Name": "Name",
|
||||
"Description": "Description",
|
||||
|
@ -4,9 +4,11 @@
|
||||
"Drives": "Unidades",
|
||||
"Grid": "Red",
|
||||
"File": "Archivo",
|
||||
"Files": "Archivos",
|
||||
"FileVersion": "Versión del archivo",
|
||||
"FileVersions": "Versiones de archivos",
|
||||
"Folder": "Carpeta",
|
||||
"Folders": "Carpetas",
|
||||
"Resource": "Recurso",
|
||||
"Name": "Nombre",
|
||||
"Description": "Descripción",
|
||||
|
@ -4,9 +4,11 @@
|
||||
"Drives": "Disques",
|
||||
"Grid": "Grille",
|
||||
"File": "Fichier",
|
||||
"Files": "Fichiers",
|
||||
"FileVersion": "Version du fichier",
|
||||
"FileVersions": "Versions de fichiers",
|
||||
"Folder": "Dossier",
|
||||
"Folders": "Dossiers",
|
||||
"Resource": "Ressource",
|
||||
"Name": "Nom",
|
||||
"Description": "Description",
|
||||
|
@ -4,9 +4,11 @@
|
||||
"Drives": "Unidades",
|
||||
"Grid": "Grade",
|
||||
"File": "Ficheiro",
|
||||
"Files": "Ficheiros",
|
||||
"FileVersion": "Versão do ficheiro",
|
||||
"FileVersions": "Versões de ficheiro",
|
||||
"Folder": "Pasta",
|
||||
"Folders": "Pastas",
|
||||
"Resource": "Recurso",
|
||||
"Name": "Nome",
|
||||
"Description": "Descrição",
|
||||
|
@ -4,9 +4,11 @@
|
||||
"Drives": "Диски",
|
||||
"Grid": "Сетка",
|
||||
"File": "Файл",
|
||||
"Files": "Файлы",
|
||||
"FileVersion": "Версия файла",
|
||||
"FileVersions": "Версии файла",
|
||||
"Folder": "Папка",
|
||||
"Folders": "Папки",
|
||||
"Resource": "Ресурс",
|
||||
"Name": "Название",
|
||||
"Description": "Описание",
|
||||
|
@ -4,9 +4,11 @@
|
||||
"Drives": "磁盘",
|
||||
"Grid": "网格",
|
||||
"File": "文件",
|
||||
"Files": "文件",
|
||||
"FileVersion": "檔案版本",
|
||||
"FileVersions": "檔案版本",
|
||||
"Folder": "文件夹",
|
||||
"Folders": "文件夹",
|
||||
"Resource": "资源",
|
||||
"Name": "名称",
|
||||
"Description": "描述",
|
||||
|
35
plugins/drive-resources/src/components/FileSearchItem.svelte
Normal file
35
plugins/drive-resources/src/components/FileSearchItem.svelte
Normal file
@ -0,0 +1,35 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { WithLookup } from '@hcengineering/core'
|
||||
import { File } from '@hcengineering/drive'
|
||||
import { Icon } from '@hcengineering/ui'
|
||||
|
||||
import { getFileTypeIcon } from '../utils'
|
||||
|
||||
export let value: WithLookup<File>
|
||||
|
||||
$: icon = getFileTypeIcon(value.$lookup?.file?.type ?? '')
|
||||
</script>
|
||||
|
||||
<div class="flex-row-center">
|
||||
<div class="flex-center p-1 content-dark-color flex-no-shrink mr-2-5">
|
||||
<Icon {icon} size={'medium'} />
|
||||
</div>
|
||||
<span class="overflow-label">
|
||||
{value.name}
|
||||
</span>
|
||||
</div>
|
@ -0,0 +1,31 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { WithLookup } from '@hcengineering/core'
|
||||
import drive, { Folder } from '@hcengineering/drive'
|
||||
import { Icon } from '@hcengineering/ui'
|
||||
|
||||
export let value: WithLookup<Folder>
|
||||
</script>
|
||||
|
||||
<div class="flex-row-center">
|
||||
<div class="flex-center p-1 content-dark-color flex-no-shrink mr-2-5">
|
||||
<Icon icon={drive.icon.Folder} size={'medium'} />
|
||||
</div>
|
||||
<span class="overflow-label">
|
||||
{value.name}
|
||||
</span>
|
||||
</div>
|
@ -13,9 +13,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type Doc, type Ref, type WithLookup } from '@hcengineering/core'
|
||||
import type { Class, Client, Doc, DocumentQuery, Ref, RelatedDocument, WithLookup } from '@hcengineering/core'
|
||||
import drive, { type Drive, type File, type FileVersion, type Folder } from '@hcengineering/drive'
|
||||
import { type Resources } from '@hcengineering/platform'
|
||||
import { type ObjectSearchResult, getFileUrl } from '@hcengineering/presentation'
|
||||
import { showPopup, type Location } from '@hcengineering/ui'
|
||||
|
||||
import CreateDrive from './components/CreateDrive.svelte'
|
||||
@ -27,19 +28,72 @@ import EditFile from './components/EditFile.svelte'
|
||||
import EditFolder from './components/EditFolder.svelte'
|
||||
import FilePanel from './components/FilePanel.svelte'
|
||||
import FilePresenter from './components/FilePresenter.svelte'
|
||||
import FileSearchItem from './components/FileSearchItem.svelte'
|
||||
import FileSizePresenter from './components/FileSizePresenter.svelte'
|
||||
import FileVersionPresenter from './components/FileVersionPresenter.svelte'
|
||||
import FileVersionVersionPresenter from './components/FileVersionVersionPresenter.svelte'
|
||||
import FolderPanel from './components/FolderPanel.svelte'
|
||||
import FolderPresenter from './components/FolderPresenter.svelte'
|
||||
import FolderSearchItem from './components/FolderSearchItem.svelte'
|
||||
import GridView from './components/GridView.svelte'
|
||||
import MoveResource from './components/MoveResource.svelte'
|
||||
import ResourcePresenter from './components/ResourcePresenter.svelte'
|
||||
|
||||
import { getFileUrl } from '@hcengineering/presentation'
|
||||
import { getDriveLink, getFileLink, getFolderLink, resolveLocation } from './navigation'
|
||||
import { restoreFileVersion, showCreateFolderPopup, showRenameResourcePopup } from './utils'
|
||||
|
||||
const toFileObjectSearchResult = (e: WithLookup<File>): ObjectSearchResult => ({
|
||||
doc: e,
|
||||
title: e.name,
|
||||
icon: drive.icon.File,
|
||||
component: FileSearchItem
|
||||
})
|
||||
|
||||
const toFolderObjectSearchResult = (e: WithLookup<Folder>): ObjectSearchResult => ({
|
||||
doc: e,
|
||||
title: e.name,
|
||||
icon: drive.icon.Folder,
|
||||
component: FolderSearchItem
|
||||
})
|
||||
|
||||
async function queryFile (
|
||||
_class: Ref<Class<File>>,
|
||||
client: Client,
|
||||
search: string,
|
||||
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
||||
): Promise<ObjectSearchResult[]> {
|
||||
const q: DocumentQuery<File> = { name: { $like: `%${search}%` } }
|
||||
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
||||
q._id = {}
|
||||
if (filter.in !== undefined) {
|
||||
q._id.$in = filter.in?.map((it) => it._id as Ref<File>)
|
||||
}
|
||||
if (filter.nin !== undefined) {
|
||||
q._id.$nin = filter.nin?.map((it) => it._id as Ref<File>)
|
||||
}
|
||||
}
|
||||
return (await client.findAll(_class, q, { limit: 200 })).map(toFileObjectSearchResult)
|
||||
}
|
||||
|
||||
async function queryFolder (
|
||||
_class: Ref<Class<Folder>>,
|
||||
client: Client,
|
||||
search: string,
|
||||
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
||||
): Promise<ObjectSearchResult[]> {
|
||||
const q: DocumentQuery<Folder> = { name: { $like: `%${search}%` } }
|
||||
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
||||
q._id = {}
|
||||
if (filter.in !== undefined) {
|
||||
q._id.$in = filter.in?.map((it) => it._id as Ref<Folder>)
|
||||
}
|
||||
if (filter.nin !== undefined) {
|
||||
q._id.$nin = filter.nin?.map((it) => it._id as Ref<Folder>)
|
||||
}
|
||||
}
|
||||
return (await client.findAll(_class, q, { limit: 200 })).map(toFolderObjectSearchResult)
|
||||
}
|
||||
|
||||
async function CreateRootFolder (doc: Drive): Promise<void> {
|
||||
await showCreateFolderPopup(doc._id, drive.ids.Root)
|
||||
}
|
||||
@ -135,6 +189,12 @@ export default async (): Promise<Resources> => ({
|
||||
RenameFolder,
|
||||
RestoreFileVersion
|
||||
},
|
||||
completion: {
|
||||
FileQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) =>
|
||||
await queryFile(drive.class.File, client, query, filter),
|
||||
FolderQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) =>
|
||||
await queryFolder(drive.class.Folder, client, query, filter)
|
||||
},
|
||||
function: {
|
||||
DriveLinkProvider,
|
||||
FileLinkProvider,
|
||||
|
Loading…
Reference in New Issue
Block a user