diff --git a/app/components/commander/action_buttons.hbs b/app/components/commander/action_buttons.hbs index 7a48b3542d3c7463e5768c1f8774909a75288c2e..d1d78d4563ee268c34190a3e91dc54b0503986db 100644 --- a/app/components/commander/action_buttons.hbs +++ b/app/components/commander/action_buttons.hbs @@ -1,33 +1,75 @@ <div> {{#if this.one_node_selected}} - <button - class="btn btn-success" - type="button" - {{on "click" this.onRename}}> - <i class="fa fa-edit"></i> - Rename - </button> <Button::Download @inProgress={{this.download_in_progress}} @onDownloadNodes={{this.onDownloadNodes}} /> + + <button class="btn btn-light" + {{on "click" this.onRename}} + {{tooltip title='Rename' placement='bottom'}}> + <i class="fa fa-edit"></i> + </button> + <button - class="btn btn-danger mx-5" type="button" - {{on "click" @openConfirmDeletionModal}}> - <i class="fa fa-times"></i> - Delete + data-bs-toggle="dropdown" + class="btn btn-light dropdown-toggle mx-1" + {{tooltip title='More' placement='right'}}> + ... </button> + <ul class="dropdown-menu" + aria-expand="false" + aria-labelledby="display-mode"> + <li> + <a class="dropdown-item" + role='button' + {{on "click" @openTagsModal}}> + <i class="bi bi-tag"></i> + Tags + </a> + </li> + <li><hr class="dropdown-divider"></li> + <li> + <a class="dropdown-item" + role='button' + {{on "click" @openConfirmDeletionModal}}> + <i class="bi bi-trash"></i> + Delete + </a> + </li> + </ul> {{else if this.multiple_nodes_selected}} <Button::Download @inProgress={{this.download_in_progress}} @onDownloadNodes={{this.onDownloadNodes}} /> + <button - class="btn btn-danger mx-5" type="button" - {{on "click" @openConfirmDeletionModal}}> - <i class="fa fa-times"></i> - Delete + data-bs-toggle="dropdown" + class="btn btn-light dropdown-toggle mx-1" + {{tooltip title='More ...' placement='right'}}> + ... </button> + <ul class="dropdown-menu" + aria-expand="false" + aria-labelledby="display-mode"> + <li> + <a class="dropdown-item" + role='button' + {{on "click" @openTagsModal}}> + <i class="bi bi-tag"></i> + Tags + </a> + </li> + <li> + <a class="dropdown-item" + role='button' + {{on "click" @openConfirmDeletionModal}}> + <i class="bi bi-trash"></i> + Delete + </a> + </li> + </ul> {{else}} {{! No nodes are currently selected }} <Button::Upload diff --git a/app/components/commander/context_menu/index.hbs b/app/components/commander/context_menu/index.hbs index c98e0157999e793e8fd0c98eb43723b8d75edad1..f7ea66fbbec8a8e7b6b3de37a7d95e0704817c79 100644 --- a/app/components/commander/context_menu/index.hbs +++ b/app/components/commander/context_menu/index.hbs @@ -1,3 +1,4 @@ + <ul class="dropdown-menu context-menu"> <li> <a class="dropdown-item" @@ -36,6 +37,13 @@ </li> {{/if}} {{#if this.one_or_multiple_nodes_selected}} + <li> + <a class="dropdown-item" + role='button' + {{on "click" this.onTags }}> + <i class="bi bi-tag mx-2"></i>Tags + </a> + </li> <li> <a class="dropdown-item" role='button' diff --git a/app/components/commander/context_menu/index.js b/app/components/commander/context_menu/index.js index ff6e9124087148fab40f8a7e396d575d78c0fc21..8c4c7939ede68a998947a807d4b5f066769ab1aa 100644 --- a/app/components/commander/context_menu/index.js +++ b/app/components/commander/context_menu/index.js @@ -79,6 +79,13 @@ export default class ContextMenuComponent extends Component { ); } + @action + onTags() { + this.args.openTagsModal( + this.args.selectedNodes + ); + } + @action async onDownloadNodes() { this.download_in_progress = true; diff --git a/app/components/commander/index.hbs b/app/components/commander/index.hbs index 0b62aaa7ac140516c992fcc8ad29bbd3dac1992f..998fc2c091572b866fb88d8a61f3ac5e99f5258e 100644 --- a/app/components/commander/index.hbs +++ b/app/components/commander/index.hbs @@ -16,6 +16,7 @@ <Commander::ContextMenu @openNewFolderModal={{this.openNewFolderModal}} @openConfirmDeletionModal={{this.openConfirmDeletionModal}} + @openTagsModal={{this.openTagsModal}} @onSelectionChanged={{this.onSelectionChanged}} @nodes={{this.children}} @selectedNodes={{this.selected_nodes}} @@ -27,6 +28,7 @@ @openNewFolderModal={{this.openNewFolderModal}} @openRenameModal={{this.openRenameModal}} @openConfirmDeletionModal={{this.openConfirmDeletionModal}} + @openTagsModal={{this.openTagsModal}} @onCreateDocumentModel={{this.onCreateDocumentModel}} @onDownloadNodes={{this.onDownloadNodes}} @selectedNodes={{this.selected_nodes}} @@ -67,6 +69,11 @@ @onSubmit={{this.onSubmitMovePages}} {{show-when this.show_confirm_move_pages_modal}} /> + <Modal::Tags + @onSubmit={{this.onSubmitTagsModal}} + @onCancel={{this.onCancelTagsModal}} + {{show-when this.show_tags_modal}}/> + <Breadcrumb @node={{@node}} @extranode={{@extranode}} diff --git a/app/components/commander/index.js b/app/components/commander/index.js index 40b05e4435b9933fc2cf77a216089e6734bd7157..822693b5dce6bade39a934a5267bc6e02f15cc99 100644 --- a/app/components/commander/index.js +++ b/app/components/commander/index.js @@ -33,6 +33,7 @@ export default class CommanderComponent extends Component { @tracked show_rename_node_modal = false; @tracked show_confirm_deletion_modal = false; + @tracked show_tags_modal = false; // localStorage is tracked @localStorage left_view_mode = 'list'; @@ -130,6 +131,11 @@ export default class CommanderComponent extends Component { this.__deleted_records = deleted_records; } + @action + openTagsModal() { + this.show_tags_modal = true; + } + @action onCreateDocumentModel(new_record) { /* @@ -328,6 +334,16 @@ export default class CommanderComponent extends Component { this.router.refresh(); } + @action + async onSubmitTagsModal(tags) { + this.show_tags_modal = false; + } + + @action + onCancelTagsModal() { + this.show_tags_modal = false; + } + @action onDragEnter({event, element}) { event.preventDefault(); diff --git a/app/components/modal/tags.hbs b/app/components/modal/tags.hbs new file mode 100644 index 0000000000000000000000000000000000000000..318fce149a336147a8d08e9cd227e508964cf75e --- /dev/null +++ b/app/components/modal/tags.hbs @@ -0,0 +1,11 @@ +<Modal::Base + @title="Tags" + @actionTitle="Submit" + @onClose={{@onClose}} + @onSubmit={{this.onSubmit}} + @onCancel={{this.onCancel}} + ...attributes +> + <label for="folder-title" class="form-label">Tags editor:</label> + <TagInput /> +</Modal::Base> \ No newline at end of file diff --git a/app/components/modal/tags.js b/app/components/modal/tags.js new file mode 100644 index 0000000000000000000000000000000000000000..21a788b31fa276f63ce4b4f8d89bc01e6f74029d --- /dev/null +++ b/app/components/modal/tags.js @@ -0,0 +1,22 @@ +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; +import { service } from '@ember/service'; + + +export default class TagsModalComponent extends Component { + @tracked tags = ''; + @service store; + @service currentUser; + + @action + async onSubmit() { + this.args.onSubmit(this.tags); + } + + @action + onCancel() { + this.args.onCancel(); + this.title = ''; + } +} diff --git a/app/components/tag_input/index.hbs b/app/components/tag_input/index.hbs new file mode 100644 index 0000000000000000000000000000000000000000..dfe00c952a5d3b1f1072c5e945fca5614d6e94aa --- /dev/null +++ b/app/components/tag_input/index.hbs @@ -0,0 +1,19 @@ +<div class="tag-input d-flex align-items-center"> + {{#each this.tags as |tag index|}} + <TagInput::Item + @tag={{tag}} + @index={{index}} + @onRemoveTagItem={{this.onRemoveTagItem}} /> + {{/each}} + + <li class="tag-input-new"> + <Input + disabled={{this.readOnly}} + class={{concat 'tag-input-new-item' (if this.readOnly ' is-disabled')}} + placeholder={{this.placeholder}} + {{on-key "Space" this.onAddTag }} + {{on-key "Comma" this.onAddTag }} + {{on-key "Enter" this.onAddTag }} + @value={{this.new_tag_value}} /> + </li> +</div> diff --git a/app/components/tag_input/index.js b/app/components/tag_input/index.js new file mode 100644 index 0000000000000000000000000000000000000000..8a29f63686421a108f1cef03ccd23c9511675102 --- /dev/null +++ b/app/components/tag_input/index.js @@ -0,0 +1,32 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from 'tracked-built-ins'; +import { TrackedArray } from 'tracked-built-ins'; + + +export default class TagInputComponent extends Component { + + @tracked tags = new TrackedArray([]); + @tracked new_tag_value = ''; + + @action + onAddTag() { + this.tags.push({ + name: this.new_tag_value + }); + this.new_tag_value = ''; + } + + @action + onRemoveTagItem(index) { + this.tags.splice(index, 1); + } + + get placeholder() { + return "Add a tag..." + } + + get readOnly() { + return false; + } +} diff --git a/app/components/tag_input/item.hbs b/app/components/tag_input/item.hbs new file mode 100644 index 0000000000000000000000000000000000000000..101305664f76f7882e320808d5e1d231e8dd3135 --- /dev/null +++ b/app/components/tag_input/item.hbs @@ -0,0 +1,5 @@ +<div class="tag"> + <span>{{@tag.name}}</span> + <i class="bi bi-x" role='button' + {{on "click" this.onRemoveTagItem}}></i> +</div> \ No newline at end of file diff --git a/app/components/tag_input/item.js b/app/components/tag_input/item.js new file mode 100644 index 0000000000000000000000000000000000000000..ff30ee7189c4e61d778e2f4b5148c2e548308f91 --- /dev/null +++ b/app/components/tag_input/item.js @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + + +export default class TagInputItemComponent extends Component { + + @action + onRemoveTagItem() { + this.args.onRemoveTagItem(this.args.index); + } +} \ No newline at end of file diff --git a/app/styles/app.scss b/app/styles/app.scss index 3bd27afe138dadb007d0555eda0abf8f70fb8302..775220f3c8f96737be6dfabf83323daed5ffe2f0 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -11,6 +11,7 @@ @import "./ui_select.scss"; @import "./context_menu.scss"; @import "./zoom.scss"; +@import "./components/tag_input.scss"; body { diff --git a/app/styles/components/tag_input.scss b/app/styles/components/tag_input.scss new file mode 100644 index 0000000000000000000000000000000000000000..313cfe7acfa8839ca7505dd4443ec94d86c7c2b1 --- /dev/null +++ b/app/styles/components/tag_input.scss @@ -0,0 +1,13 @@ +.tag-input { + border: 1px solid #888; + padding: 0.5rem; + + li.tag-input-new { + list-style: none; + + input { + border: none; + outline: none; + } + } +} \ No newline at end of file