From ac47e6314fcdac9ec110e7c947af143df766b320 Mon Sep 17 00:00:00 2001 From: John Livingston Date: Sun, 12 May 2024 18:45:51 +0200 Subject: [PATCH] Task lists WIP: * new icon for the task app * create task message action --- conversejs/custom/plugins/tasks/index.js | 6 ++- .../plugins/tasks/modals/pick-task-list.js | 51 +++++++++++++++++++ .../tasks/modals/templates/pick-task-list.js | 36 +++++++++++++ conversejs/custom/plugins/tasks/utils.js | 42 ++++++++++++++- .../custom/shared/components/font-awesome.js | 9 ++-- conversejs/loc.keys.js | 5 +- languages/en.yml | 8 ++- 7 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 conversejs/custom/plugins/tasks/modals/pick-task-list.js create mode 100644 conversejs/custom/plugins/tasks/modals/templates/pick-task-list.js diff --git a/conversejs/custom/plugins/tasks/index.js b/conversejs/custom/plugins/tasks/index.js index 5f01d921..86fe7526 100644 --- a/conversejs/custom/plugins/tasks/index.js +++ b/conversejs/custom/plugins/tasks/index.js @@ -2,12 +2,13 @@ import { _converse, converse } from '../../../src/headless/core.js' import { ChatRoomTaskLists } from './task-lists.js' import { ChatRoomTaskList } from './task-list.js' import { ChatRoomTasks } from './tasks.js' -import { getHeadingButtons, initOrDestroyChatRoomTaskLists } from './utils.js' +import { getHeadingButtons, getMessageActionButtons, initOrDestroyChatRoomTaskLists } from './utils.js' import { XMLNS_TASK, XMLNS_TASKLIST } from './constants.js' import './components/muc-task-view.js' // FIXME: here or in another file? import './components/muc-task-list-view.js' // FIXME: here or in another file? import './components/muc-task-lists-view.js' // FIXME: here or in another file? import './components/muc-task-app-view.js' // FIXME: here or in another file? +import './modals/pick-task-list.js' // FIXME: here or in another file? converse.plugins.add('livechat-converse-tasks', { dependencies: ['converse-muc', 'converse-disco', 'converse-pubsub'], @@ -48,5 +49,8 @@ converse.plugins.add('livechat-converse-tasks', { // adding the "Tasks" button in the MUC heading buttons: _converse.api.listen.on('getHeadingButtons', getHeadingButtons) + + // Adding buttons on message: + _converse.api.listen.on('getMessageActionButtons', getMessageActionButtons) } }) diff --git a/conversejs/custom/plugins/tasks/modals/pick-task-list.js b/conversejs/custom/plugins/tasks/modals/pick-task-list.js new file mode 100644 index 00000000..e397f5a9 --- /dev/null +++ b/conversejs/custom/plugins/tasks/modals/pick-task-list.js @@ -0,0 +1,51 @@ +import BaseModal from 'plugins/modal/modal.js' +import tplPickTaskList from './templates/pick-task-list.js' +import { api } from '@converse/headless/core' +import { __ } from 'i18n' + +export default class PickTaskListModal extends BaseModal { + constructor (options) { + super(options) + this.muc = options.muc + this.message = options.message + } + + initialize () { + super.initialize(...arguments) + this.addEventListener('shown.bs.modal', () => { + this.querySelector('select[name="tasklist"]').focus() + }) + } + + getModalTitle () { + // eslint-disable-next-line no-undef + return __(LOC_task_list_pick_title) + } + + renderModal () { + return tplPickTaskList(this) + } + + onPick (ev) { + ev.preventDefault() + const tlId = ev.target?.tasklist?.value + if (!tlId) { return } + + const tasklists = this.muc.tasklists + if (!tasklists) { return } + + const tasklist = tasklists.get(tlId) + if (!tasklist) { return } + + const message = this.message + tasklist.createTask({ + name: message.get('nick'), + description: message.get('body') + }).then( + () => this.modal.hide(), + console.error + ) + } +} + +api.elements.define('livechat-converse-pick-task-list-modal', PickTaskListModal) diff --git a/conversejs/custom/plugins/tasks/modals/templates/pick-task-list.js b/conversejs/custom/plugins/tasks/modals/templates/pick-task-list.js new file mode 100644 index 00000000..41be199b --- /dev/null +++ b/conversejs/custom/plugins/tasks/modals/templates/pick-task-list.js @@ -0,0 +1,36 @@ +import { html } from 'lit' +import { repeat } from 'lit/directives/repeat.js' +import { __ } from 'i18n' + +export default function (el) { + const muc = el.muc + if (!muc?.tasklists?.length) { + // eslint-disable-next-line no-undef + const i18nEmpty = __(LOC_task_list_pick_empty) + return html`

${i18nEmpty}

` + } + + // eslint-disable-next-line no-undef + const i18nMessage = __(LOC_task_list_pick_message) + + return html` +
el.onPick(ev)}> +
+ + + ${i18nMessage} + +
+ +
+ + +
+
` +} diff --git a/conversejs/custom/plugins/tasks/utils.js b/conversejs/custom/plugins/tasks/utils.js index 96cc98a5..216547f3 100644 --- a/conversejs/custom/plugins/tasks/utils.js +++ b/conversejs/custom/plugins/tasks/utils.js @@ -25,13 +25,45 @@ export function getHeadingButtons (view, buttons) { taskAppEl.toggleApp() }, a_class: '', - icon_class: 'fa-list', // FIXME + icon_class: 'fa-list-check', name: 'muc-tasks' }) return buttons } +export function getMessageActionButtons (messageActionsEl, buttons) { + const messageModel = messageActionsEl.model + if (messageModel.get('type') !== 'groupchat') { + // only on groupchat message. + return buttons + } + + const muc = messageModel.collection?.chatbox + if (!muc?.tasklists) { + return buttons + } + + // eslint-disable-next-line no-undef + const i18nCreate = __(LOC_task_create) + + buttons.push({ + i18n_text: i18nCreate, + handler: async (ev) => { + ev.preventDefault() + api.modal.show('livechat-converse-pick-task-list-modal', { + muc, + message: messageModel + }, ev) + }, + button_class: '', + icon_class: 'fa fa-list-check', + name: 'muc-task-create-from-message' + }) + + return buttons +} + function _initChatRoomTaskLists (mucModel) { if (mucModel.taskManager) { // already initiliazed @@ -70,6 +102,10 @@ function _initChatRoomTaskLists (mucModel) { } ) mucModel.taskManager.start().catch(err => console.log(err)) + + // We must requestUpdate for all message actions, to add the "create task" button. + // FIXME: this should not be done here (but it is simplier for now) + document.querySelectorAll('converse-message-actions').forEach(el => el.requestUpdate()) } function _destroyChatRoomTaskLists (mucModel) { @@ -81,6 +117,10 @@ function _destroyChatRoomTaskLists (mucModel) { // mucModel.tasklists.unload() FIXME: add a method to unregister from the pubsub, and empty the tasklist. mucModel.tasklists = undefined mucModel.tasks = undefined + + // We must requestUpdate for all message actions, to remove the "create task" button. + // FIXME: this should not be done here (but it is simplier for now) + document.querySelectorAll('converse-message-actions').forEach(el => el.requestUpdate()) } export function initOrDestroyChatRoomTaskLists (mucModel) { diff --git a/conversejs/custom/shared/components/font-awesome.js b/conversejs/custom/shared/components/font-awesome.js index fe544efc..7225e544 100644 --- a/conversejs/custom/shared/components/font-awesome.js +++ b/conversejs/custom/shared/components/font-awesome.js @@ -9,13 +9,10 @@ export default () => { return html` ${converseJsIcons} - - - + + + ` diff --git a/conversejs/loc.keys.js b/conversejs/loc.keys.js index 9d2129bb..ee31e53a 100644 --- a/conversejs/loc.keys.js +++ b/conversejs/loc.keys.js @@ -27,7 +27,10 @@ const locKeys = [ 'task_description', 'task_delete', 'task_delete_confirm', - 'task_app_info' + 'task_app_info', + 'task_list_pick_title', + 'task_list_pick_empty', + 'task_list_pick_message' ] module.exports = locKeys diff --git a/languages/en.yml b/languages/en.yml index c976eaff..ae5b8ebf 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -448,4 +448,10 @@ task_delete: 'Delete task' task_delete_confirm: 'Are you sure you want to delete this task?' task_app_info: | You can create tasks and task lists, which are shared between all room's admins. - See the livechat streamers documentation for more information. \ No newline at end of file + See the livechat streamers documentation for more information. +task_list_pick_title: 'Please choose a task list' +task_list_pick_empty: 'There is no task list for now, please first create one' +task_list_pick_message: | + Once you have chosen a task list, a new task will be created. + To see the task, open the task application using the top menu. + More information in the livechat plugin documentation.