From cdfa734457e3c6e69e9f04a9bd282dd3e9776427 Mon Sep 17 00:00:00 2001 From: Eugen Ciur <eugen@papermerge.com> Date: Thu, 20 Jan 2022 20:42:45 +0100 Subject: [PATCH] user can upload files by dragging them from desktop file manager --- app/components/button/upload.js | 2 +- app/components/choice_field/index.hbs | 8 +++- app/components/choice_field/index.js | 4 ++ app/components/commander/index.js | 69 ++++++++++++++++++++++----- app/helpers/is_equal.js | 1 + app/modifiers/droppable.js | 54 +++++++++++++++++++-- app/services/current-user.js | 2 +- app/services/preferences.js | 37 ++++++++++++++ app/services/uploader.js | 14 ++++++ 9 files changed, 173 insertions(+), 18 deletions(-) create mode 100644 app/services/preferences.js create mode 100644 app/services/uploader.js diff --git a/app/components/button/upload.js b/app/components/button/upload.js index d0e25d0..1926025 100644 --- a/app/components/button/upload.js +++ b/app/components/button/upload.js @@ -1,6 +1,6 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; -import { inject as service } from '@ember/service'; +import { service } from '@ember/service'; export default class UploadButtonComponent extends Component { diff --git a/app/components/choice_field/index.hbs b/app/components/choice_field/index.hbs index 500a12b..5b9bf2a 100644 --- a/app/components/choice_field/index.hbs +++ b/app/components/choice_field/index.hbs @@ -2,7 +2,13 @@ <label for={{this.name}} class="form-label">{{capitalize this.name}}</label>: <select class="form-select" {{on 'change' this.onChange}}> {{#each this.choices as |choice|}} - <option value="{{get choice 0}}">{{get choice 1}}</option> + {{#let (get choice 0) (get choice 1) as |choice_key choice_value|}} + {{#if (is_equal choice_key this.value)}} + <option selected value="{{choice_key}}">{{choice_value}}</option> + {{else}} + <option value="{{choice_key}}">{{choice_value}}</option> + {{/if}} + {{/let}} {{/each}} </select> </div> \ No newline at end of file diff --git a/app/components/choice_field/index.js b/app/components/choice_field/index.js index e1d4392..d17f9dd 100644 --- a/app/components/choice_field/index.js +++ b/app/components/choice_field/index.js @@ -41,6 +41,10 @@ export default class PreferenceChoiceFieldComponent extends Component { return this.args.model.identifier; } + get value() { + return this.args.model.value; + } + @action onChange(event) { const new_value = event.target.value; diff --git a/app/components/commander/index.js b/app/components/commander/index.js index 28b0edc..7d2a997 100644 --- a/app/components/commander/index.js +++ b/app/components/commander/index.js @@ -20,6 +20,8 @@ export default class CommanderComponent extends Component { @service ws_nodes_move; @service store; @service requests; + @service preferences; + @service uploader; // show create new folder modal dialog? @tracked show_new_folder_modal = false; @@ -200,19 +202,64 @@ export default class CommanderComponent extends Component { } @action - onDrop(source_data) { - let nodes_move_data; - - nodes_move_data = { - 'nodes': [{ 'id': source_data.node.id }], - 'source_parent': { - 'id': source_data.source_parent.id - }, - 'target_parent': { - 'id': this.args.node.id + onDrop(data) { + /** + * data is a dictionary of following format: + * { + * 'application/x.node': source_data + * 'application/x.desktop': source_data + * } + * + * (1) 'application/x.node' - when incoming data is a node + * being dropped from another commander panel + * (2) 'application/x.desktop' - when incoming data is being + * drop from desktop's file manager + * + * In (1) case, source_data is { + * node: <node being droppped> + * source_parent: <parent of the node being droppped> + * } + * + * In (2) case, source_data is an array of File instances + * */ + let nodes_move_data, + source_data; + + /* + Data can be droppped from: + - another panel i.e. as x.node + - from desktop file manager i.e. as x.desktop + */ + + if (data['application/x.node']) { + + // dropping items from another panel + source_data = data['application/x.node']; + nodes_move_data = { + 'nodes': [{ 'id': source_data.node.id }], + 'source_parent': { + 'id': source_data.source_parent.id + }, + 'target_parent': { + 'id': this.args.node.id + } } + this.requests.nodesMove(nodes_move_data); + + } else if (data['application/x.desktop']) { + + // dropping items from the Desktop file manager + this.uploader.upload({ + files: data['application/x.desktop'], + parent_id: this.args.node.id, + lang: this.preferences.get_value({ + key: 'ocr__lang', + default_value: 'deu' + }) + }); + } - this.requests.nodesMove(nodes_move_data); + } @action diff --git a/app/helpers/is_equal.js b/app/helpers/is_equal.js index 84c9bad..bffc2db 100644 --- a/app/helpers/is_equal.js +++ b/app/helpers/is_equal.js @@ -1,6 +1,7 @@ import { helper } from '@ember/component/helper'; import { isEqual as emberIsEqual } from '@ember/utils'; + export function is_equal([a, b]) { return emberIsEqual(a, b); } diff --git a/app/modifiers/droppable.js b/app/modifiers/droppable.js index e0340af..3ec0d98 100644 --- a/app/modifiers/droppable.js +++ b/app/modifiers/droppable.js @@ -30,16 +30,28 @@ export default class DrappableModifier extends Modifier { @action onDrop(event) { - let data; - const isNode = event.dataTransfer.types.includes("application/x.node"); + let data, files_list; + const isNodeDrop = event.dataTransfer.types.includes("application/x.node"); const callback = this.args.named['onDrop']; event.preventDefault(); this.element.classList.remove('droparea'); - if (isNode && callback) { + + if (isNodeDrop && callback) { + // drop incoming from another panel data = event.dataTransfer.getData('application/x.node'); - callback(JSON.parse(data)); + if (data) { + callback(JSON.parse({ + 'application/x.node': data + })); + } + } else if (this._is_desktop_drop(event)) { + files_list = this._get_desktop_files(event); + callback({ + 'application/x.desktop': files_list + }); } + } @action @@ -63,4 +75,38 @@ export default class DrappableModifier extends Modifier { event.preventDefault(); this.element.classList.remove('droparea'); } + + _is_desktop_drop(event) { + // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop + let items = event.dataTransfer.items; + let files = event.dataTransfer.files; + + if (items && items.length > 0) { + return true; + } + + return files && files.length > 0; + } + + _get_desktop_files(event) { + // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop + let result = [], i; + + if (event.dataTransfer.items) { + // Use DataTransferItemList interface to access the file(s) + for (i = 0; i < event.dataTransfer.items.length; i++) { + // If dropped items aren't files, reject them + if (event.dataTransfer.items[i].kind === 'file') { + result.push(event.dataTransfer.items[i].getAsFile()); + } + } + } else { + // Use DataTransfer interface to access the file(s) + for (i = 0; i < event.dataTransfer.files.length; i++) { + result.push(event.dataTransfer.files[i]); + } + } + + return result; + } } diff --git a/app/services/current-user.js b/app/services/current-user.js index e44dee0..809e7f3 100644 --- a/app/services/current-user.js +++ b/app/services/current-user.js @@ -1,5 +1,5 @@ import Service from '@ember/service'; -import { inject as service } from '@ember/service'; +import { service } from '@ember/service'; export default class CurrentUserService extends Service { diff --git a/app/services/preferences.js b/app/services/preferences.js new file mode 100644 index 0000000..1cff4c0 --- /dev/null +++ b/app/services/preferences.js @@ -0,0 +1,37 @@ +import Service from '@ember/service'; +import { service } from '@ember/service'; + + +export default class Preferences extends Service { + + @service requests; + + constructor(owner, args) { + super(owner, args); + + let that = this; + + this.preferences = []; + + this.requests.preferences().then( + request => request.json() + ).then(json_data => json_data.data).then( + list_of_attrs => { + that.preferences = list_of_attrs.map(attr => attr.attributes); + }); + } + + get_value({key, default_value}) { + let found_item; + + found_item = this.preferences.find( + item => item.idendifier == key + ); + + if (found_item) { + return found_item['value']; + } + + return default_value; + } +} \ No newline at end of file diff --git a/app/services/uploader.js b/app/services/uploader.js new file mode 100644 index 0000000..4080794 --- /dev/null +++ b/app/services/uploader.js @@ -0,0 +1,14 @@ +import Service from '@ember/service'; +import { service } from '@ember/service'; + + +export default class Uploader extends Service { + + @service requests; + + upload({files, lang, parent_id}) { + console.log( + `Uploading files=${files} lang=${lang} parent_id=${parent_id}` + ); + } +} \ No newline at end of file -- GitLab