From f58fcd85b189ebb82309926f55cd75f8b71cb050 Mon Sep 17 00:00:00 2001 From: garrettmills Date: Thu, 4 Feb 2021 20:41:03 -0600 Subject: [PATCH] Noded/frontend#75 - support searching file boxes and files from universal search --- app/IonicUnit.js | 3 + app/controllers/api/v1/FileBox.controller.js | 14 +++++ app/controllers/api/v1/Misc.controller.js | 60 ++++++++++++++++++- app/models/api/files/FileBox.model.js | 7 +++ app/routing/routers/api/v1/file-box.routes.js | 5 ++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/app/IonicUnit.js b/app/IonicUnit.js index 2084f27..400c7ae 100644 --- a/app/IonicUnit.js +++ b/app/IonicUnit.js @@ -54,6 +54,9 @@ class IonicUnit extends Unit { const files = this.scaffold.collection('upload__File') await files.createIndex({ original_name: 'text' }) + + const boxes = this.scaffold.collection('api_files_FileBox') + await boxes.createIndex({ name: 'text' }) } } diff --git a/app/controllers/api/v1/FileBox.controller.js b/app/controllers/api/v1/FileBox.controller.js index 2e697dc..eb4b60d 100644 --- a/app/controllers/api/v1/FileBox.controller.js +++ b/app/controllers/api/v1/FileBox.controller.js @@ -179,9 +179,23 @@ class FileBoxController extends Controller { const { file_box, file } = req.form file_box.fileIds = file_box.fileIds.filter(x => `${x}` !== `${file.id}`) await file_box.save() + await file.delete() return res.api() } + async get_box_history_path(req, res, next) { + const { file_box } = req.form + + const history = [] + let current = file_box + while ( current.parentUUID ) { + current = await current.parent() + history.push(current) + } + + return res.api(await Promise.all(history.reverse().map(x => x.to_api()))) + } + file_to_api(file) { return { type: 'file', diff --git a/app/controllers/api/v1/Misc.controller.js b/app/controllers/api/v1/Misc.controller.js index 87678e5..c34c68b 100644 --- a/app/controllers/api/v1/Misc.controller.js +++ b/app/controllers/api/v1/Misc.controller.js @@ -11,7 +11,7 @@ class Misc extends Controller { #default_token_grants = ['database'] static get services() { - return [...super.services, 'models'] + return [...super.services, 'models', 'injector'] } async get_token(req, res, next) { @@ -36,6 +36,7 @@ class Misc extends Controller { const Database = this.models.get('api:db:Database') const FileGroup = this.models.get('api:FileGroup') const File = this.models.get('upload::File') + const FileBox = this.models.get('api:files:FileBox') const all_user_page_ids = (await req.user.get_accessible_pages()).map(x => x.UUID) const results = [] @@ -125,12 +126,41 @@ class Misc extends Controller { return self.indexOf(value) === index } + const matching_boxes = await FileBox.find({ + active: true, + pageId: { $in: all_user_page_ids }, + $text: { $search: query }, + }) + + for ( const box of matching_boxes ) { + const page = await box.page() + results.push({ + title: box.name, + short_title: `${box.name.replace(/(<([^>]+)>)/ig, '').slice(0, snip_length)}${box.name.length > snip_length ? '...' : ''}`, + type: 'file_box', + id: box.nodeId, + boxId: box.UUID, + associated: { + title: page.Name, + short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`, + type: 'page', + id: page.UUID, + }, + }) + } + + const all_boxes = await FileBox.find({ + active: true, + pageId: { $in: all_user_page_ids }, + }) + const all_file_groups = await FileGroup.find({ PageId: { $in: all_user_page_ids }, }) let all_file_ids = [] const file_id_x_group = {} + const file_id_x_box = {} for ( const group of all_file_groups ) { group.FileIds.forEach(id => { all_file_ids.push(id) @@ -138,6 +168,13 @@ class Misc extends Controller { }) } + for ( const box of all_boxes ) { + box.fileIds.forEach(id => { + all_file_ids.push(id) + file_id_x_box[id] = box + }) + } + const unique_file_ids = all_file_ids.filter(unique).map(x => File.ObjectId(x)) const matching_files = await File.find({ @@ -147,7 +184,24 @@ class Misc extends Controller { for ( const file of matching_files ) { const group = file_id_x_group[file.id] - if ( group ) { + const box = file_id_x_box[file.id] + + if ( box ) { + const page = await box.page() + results.push({ + title: file.original_name, + short_title: `${file.original_name.slice(0, snip_length)}${file.original_name.length > snip_length ? '...' : ''}`, + type: `file_box-${this.injector.get('controllers').get('api:v1:FileBox.get_file_category')(file.mime_type)}`, + id: box.nodeId, + boxId: box.UUID, + associated: { + title: page.Name, + short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`, + type: 'page', + id: page.UUID, + }, + }) + } else if ( group ) { const page = await group.page results.push({ title: file.original_name, @@ -159,7 +213,7 @@ class Misc extends Controller { short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`, type: 'page', id: page.UUID, - } + }, }) } } diff --git a/app/models/api/files/FileBox.model.js b/app/models/api/files/FileBox.model.js index 47a70c8..ad2a33c 100644 --- a/app/models/api/files/FileBox.model.js +++ b/app/models/api/files/FileBox.model.js @@ -20,6 +20,13 @@ class FileBoxModel extends Model { } } + async page() { + const Page = this.models.get('api:Page') + return Page.findOne({ + UUID: this.pageId, + }) + } + async parent() { return this.constructor.findOne({ UUID: this.parentUUID, diff --git a/app/routing/routers/api/v1/file-box.routes.js b/app/routing/routers/api/v1/file-box.routes.js index 5414bf2..2f93716 100644 --- a/app/routing/routers/api/v1/file-box.routes.js +++ b/app/routing/routers/api/v1/file-box.routes.js @@ -10,6 +10,11 @@ module.exports = exports = { ['middleware::api:DataInjection', { access_level: 'view' }], 'controller::api:v1:FileBox.get_box', ], + '/:PageId/:NodeId/:FileBoxId/history': [ + 'middleware::auth:ApiRoute', + ['middleware::api:DataInjection', { access_level: 'view' }], + 'controller::api:v1:FileBox.get_box_history_path', + ], '/:PageId/:NodeId/:FileBoxId/files': [ 'middleware::auth:ApiRoute', ['middleware::api:DataInjection', { access_level: 'view' }],