Open mahsashadi opened 2 years ago
I had a look, and the Search
is exported, but it's not possible to override it:
This should probably be exposed via the DesktopServiceProvider
as done with everything else.
Feel free to open a PR on this (or anyone stumbling across this).
Should be a fairly easy modification :)
Just thought of a thing. This could probably benefit from an Adapter pattern so that you don't have to override the actual Search
abstraction, but rather have a layer on top that can gather results from different sources.
// Changed core service
import VFSSearchAdapter from './adapters/search/vfs'
class Search {
constructor(core, options) {
// The options would come from the Service provider
const providedAdapters = options.adapters || []
const useAdapters = [VFSSearchAdapter, ...providedAdapters]
this.adapters = useAdapters.map(A => new A(core))
}
async init() {
await Promise.all(this.adapters.map(a => a.init()))
}
async search(pattern) {
const results = await Promise.all(this.adapters.map(a => a.search(pattern)))
// Maybe sorted ?! Maybe provide grouping in UI ?!
// Start simple with a flat result ?!
return results.flat(1)
}
}
// Changed core service initialization
this.search = core.config('search.enabled')
? new Search(core, options.search || {})
: null;
// A custom adapter in the distro
// Uses the standard interface as the rest of OS.js
export default class MySearchAdapter {
constructor(core) {
this.core = core
// If settings are needed it can be provided via a custom config entry
const config = core.config('search.mySearchAdapterSetttings', {})
this.settings = deepmerge({
someDefault: 'value',
}, config)
}
destroy() {}
async init() {
// For custom stuff during boot
}
async search(pattern) {
return []
}
}
// Desktop service provider can now do this
import MySearchAdapter from './SearchAdapter'
osjs.register(DesktopServiceProvider, {
args: {
search: {
adapters: [MySearchAdapter],
}
}
});
Since we have previously developed and contributed our VFS Adapter, isn't it enough to only implement search
function of ours, which returns an array
of files metadata?
It seems here it loops over mountpoints and execute all search functions.
Before going ahead, I create a PR for search function annotation. https://github.com/os-js/osjs-server/pull/70
Since we have previously developed and contributed our VFS Adapter, isn't it enough to only implement search function of ours, which returns an array of files metadata?
Yes.
But adding this could allow for custom searches, not just VFS. It could return http links for example as paths and open tabs, etc :)
@andersevenrud
// Changed core service
import VFSSearchAdapter from './adapters/search/vfs'
class Search {
constructor(core, options) {
// The options would come from the Service provider
const providedAdapters = options.adapters || []
const useAdapters = [VFSSearchAdapter, ...providedAdapters]
this.adapters = useAdapters.map(A => new A(core))
}
async init() {
await Promise.all(this.adapters.map(a => a.init()))
}
async search(pattern) {
const results = await Promise.all(this.adapters.map(a => a.search(pattern)))
// Maybe sorted ?! Maybe provide grouping in UI ?!
// Start simple with a flat result ?!
return results.flat(1)
}
}
// Changed core service initialization
this.search = core.config('search.enabled')
? new Search(core, options.search || {})
: null;
Hi , Now in which file and where should we put this piece of code? And what changes should we make?
This would be the search.js
(core service) and desktop.js
(where search
is inited) respectively.
And then move the existing search implementation to a new adapter (path in import in example).
On Mon, 5 Dec 2022, 19:33 mahdi norouzi, @.***> wrote:
// Changed core service import VFSSearchAdapter from './adapters/search/vfs'
class Search { constructor(core, options) { // The options would come from the Service provider const providedAdapters = options.adapters || [] const useAdapters = [VFSSearchAdapter, ...providedAdapters] this.adapters = useAdapters.map(A => new A(core)) }
async init() { await Promise.all(this.adapters.map(a => a.init())) }
async search(pattern) { const results = await Promise.all(this.adapters.map(a => a.search(pattern))) // Maybe sorted ?! Maybe provide grouping in UI ?! // Start simple with a flat result ?! return results.flat(1) } }
// Changed core service initialization this.search = core.config('search.enabled') ? new Search(core, options.search || {}) : null;
Hi , Now in which file and where should we put this piece of code? And what changes should we make?
— Reply to this email directly, view it on GitHub https://github.com/os-js/OS.js/issues/812#issuecomment-1337911285, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABHODAQMXS2AW67YO2UZUTWLYYPPANCNFSM6AAAAAARMWS7IM . You are receiving this because you commented.Message ID: <os-js/OS. @.***>
@andersevenrud
Should a part of the search be deleted or how can I replace it?
I can't go into much more detail because I'm on mobile.
The brief overview of code changes I gave should be enough to get started. It's just a matter of moving some code and then implement an adapter pattern + pass on some options from provider.
Open a PR as it's easier to do reviews than me just writing out the code myself in issues.
On Mon, 5 Dec 2022, 20:57 mahdi norouzi, @.***> wrote:
@andersevenrud https://github.com/andersevenrud
Should a part of the search be deleted or how can I replace it?
— Reply to this email directly, view it on GitHub https://github.com/os-js/OS.js/issues/812#issuecomment-1338086321, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABHODHAJE3BVJMPVPKLZWLWLZCJLANCNFSM6AAAAAARMWS7IM . You are receiving this because you were mentioned.Message ID: <os-js/OS. @.***>
@andersevenrud hi this file search.js : Should I change like this?
I am newcomer to this project
export default class Search {
/**
* Create Search instance
* @param {Core} core Core reference
*/
constructor(core, options) {
const providedAdapters = options.adapters || []
const useAdapters = [VFSSearchAdapter, ...providedAdapters]
this.adapters = useAdapters.map(A => new A(core))
/**
* Core instance reference
* @type {Core}
* @readonly
*/
this.core = core;
/**
* Wired actions
* @type {Object}
*/
this.ui = null;
/**
* Last focused window
* @type {Window}
*/
this.focusLastWindow = null;
/**
* Search root DOM element
* @type {Element}
* @readonly
*/
this.$element = document.createElement('div');
}
init() {
const {icon} = this.core.make('osjs/theme');
const _ = this.core.make('osjs/locale').translate;
this.$element.className = 'osjs-search';
this.core.$root.appendChild(this.$element);
this.core.make('osjs/tray').create({
title: _('LBL_SEARCH_TOOLTOP', 'F3'),
icon: icon('system-search.png')
}, () => this.show());
this.ui = createUI(this.core, this.$element);
this.ui.on('hide', () => this.hide());
this.ui.on('open', iter => this.core.open(iter));
this.ui.on('search', query => {
this.search(query)
.then(results => this.ui.emit('success', results))
.catch(error => this.ui.emit('error', error));
});
await Promise.all(this.adapters.map(a => a.init()))
}
search(pattern) {
const results = await Promise.all(this.adapters.map(a => a.search(pattern)))
// Maybe sorted ?! Maybe provide grouping in UI ?!
// Start simple with a flat result ?!
const vfs = this.core.make('osjs/vfs');
const promises = this.core.make('osjs/fs')
.mountpoints()
.map(mount => `${mount.name}:/`)
.map(path => {
return vfs.search({path}, pattern)
.catch(error => {
logger.warn('Error while searching', error);
return [];
});
});
return results.flat(1)
}
....
....
and file desktop.js in constructor:
Should I change like this?
/**
* Search instance
* @type {Search|null}
* @readonly
*/
this.search = core.config('search.enabled') ? new Search(core) : null;
Please open a PR so I can write reviews. It's a bit hard in issues.
On Thu, 8 Dec 2022, 20:35 mahdi norouzi, @.***> wrote:
@andersevenrud https://github.com/andersevenrud hi this file search.js : Should I change like this?
I am newcomer to this project
export default class Search { /**
- Create Search instance
@param {Core} core Core reference */ constructor(core, options) { const providedAdapters = options.adapters || [] const useAdapters = [VFSSearchAdapter, ...providedAdapters] this.adapters = useAdapters.map(A => new A(core))
/**
- Core instance reference
- @type {Core}
- @readonly */ this.core = core;
/**
- Wired actions
- @type {Object} */ this.ui = null;
/**
- Last focused window
- @type {Window} */ this.focusLastWindow = null;
/**
- Search root DOM element
- @type {Element}
- @readonly */ this.$element = document.createElement('div');
}
init() { const {icon} = this.core.make('osjs/theme'); const _ = this.core.make('osjs/locale').translate;
this.$element.className = 'osjs-search'; this.core.$root.appendChild(this.$element);
this.core.make('osjs/tray').create({ title: _('LBL_SEARCH_TOOLTOP', 'F3'), icon: icon('system-search.png') }, () => this.show());
this.ui = createUI(this.core, this.$element); this.ui.on('hide', () => this.hide()); this.ui.on('open', iter => this.core.open(iter)); this.ui.on('search', query => { this.search(query) .then(results => this.ui.emit('success', results)) .catch(error => this.ui.emit('error', error)); }); await Promise.all(this.adapters.map(a => a.init()))
}
search(pattern) { const results = await Promise.all(this.adapters.map(a => a.search(pattern))) // Maybe sorted ?! Maybe provide grouping in UI ?! // Start simple with a flat result ?!
const vfs = this.core.make('osjs/vfs'); const promises = this.core.make('osjs/fs') .mountpoints() .map(mount => `${mount.name}:/`) .map(path => { return vfs.search({path}, pattern) .catch(error => { logger.warn('Error while searching', error); return []; }); }); return results.flat(1)
}
.... ....
and file desktop.js in constructor: Should I change like this?
/** * Search instance * @type {Search|null} * @readonly */ this.search = core.config('search.enabled') ? new Search(core) : null;
— Reply to this email directly, view it on GitHub https://github.com/os-js/OS.js/issues/812#issuecomment-1343258396, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABHODAR53ICPQHH7R5WRDLWMI2AFANCNFSM6AAAAAARMWS7IM . You are receiving this because you were mentioned.Message ID: <os-js/OS. @.***>
I wanted to know that I did the change right?
It's not fully correct.
If you open a PR i can make annotatilns where you need to fix stuff. On Thu, 8 Dec 2022, 20:39 mahdi norouzi, @.***> wrote:
I wanted to know that I did the change right?
— Reply to this email directly, view it on GitHub https://github.com/os-js/OS.js/issues/812#issuecomment-1343261915, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABHODBMX7PA6O4UVWWTQPLWMI2OHANCNFSM6AAAAAARMWS7IM . You are receiving this because you were mentioned.Message ID: <os-js/OS. @.***>
@andersevenrud i opened pr for your reviews
@andersevenrud Many ambiguities have arisen for me in relation to changing the codes, for example, which sections should be deleted, which sections should remain, or which sections should be defined.
Many ambiguities have arisen for me in relation to changing the codes, for example, which sections should be deleted, which sections should remain, or which sections should be defined.\
That was kind of the whole point of this. I wrote some ideas and suggestions on how it could be solved.
If I were to point out (or write here) exactly what sections should be deleted/changed, I could just have written it myself.
I wanted this to be an easy exercise into getting familiar with how everything works, and I thought that I had explained myself clearly.
But maybe there is some kind of language barrier here or some knowledge gap which makes it very hard for me to give the information needed.
Based on my comments, this is basically what's needed to make this work as I explained:
src/adapters/search/vfs.js
export default class VFSSearchAdapter {
constructor(core) {
this.core = core
}
destroy() {}
async init() {}
async search(pattern) {
const vfs = this.core.make('osjs/vfs');
const promises = this.core.make('osjs/fs')
.mountpoints()
.map(mount => `${mount.name}:/`)
.map(path => {
return vfs.search({path}, pattern)
.catch(error => {
logger.warn('Error while searching', error);
return [];
});
});
return Promise.all(promises)
.then(lists => [].concat(...lists));
}
}
src/search.js
// New import to adapter that replaces search function
import VFSSearchAdapter from './adapters/search/vfs.js';
export default class Search {
constructor(core) {
// ...
// New lines on bottom
const providedAdapters = options.adapters || []
const useAdapters = [VFSSearchAdapter, ...providedAdapters]
this.adapters = useAdapters.map(A => new A(core))
}
async destroy() {
// ...
// New lines on bottom
await this.adapters.map(a => a.destroy())
}
/**
* Initializes Search Service
*/
init() {
// ...
// New lines on bottom
await Promise.all(this.adapters.map(a => a.init()))
}
async search(pattern) {
// Replace with this
const results = await Promise.all(this.adapters.map(a => a.search(pattern)))
return results.flat(1)
}
}
src/desktop.js
export default class Desktop extends EventEmitter {
constructor(core, options = {}) {
// Replace the old construtor with this
this.search = core.config('search.enabled')
? new Search(core, options.search || {})
: null;
}
}
@andersevenrud very thanks i again reviews code
@andersevenrud
Excuse me, one question how MySearchAdapter be connected (I mean is override) to search through the DesktopServiceProvider ? what is bridge between these?
Hi. How can we extend osjs-search-engine? Imagine we have a search engine like
Elasticsearch
, what kind of interface osjs-search-engine needs to sync with our search engine?