diff --git a/conversejs/custom/plugins/tasks/muc-task-list-view.js b/conversejs/custom/plugins/tasks/muc-task-list-view.js index 6e6b10d3..236eef6c 100644 --- a/conversejs/custom/plugins/tasks/muc-task-list-view.js +++ b/conversejs/custom/plugins/tasks/muc-task-list-view.js @@ -1,6 +1,7 @@ import { CustomElement } from 'shared/components/element.js' import { api } from '@converse/headless/core' import tplMucTaskList from './templates/muc-task-list' +import { __ } from 'i18n' export default class MUCTaskListView extends CustomElement { static get properties () { @@ -18,7 +19,27 @@ export default class MUCTaskListView extends CustomElement { } render () { - return tplMucTaskList(this.model) + return tplMucTaskList(this, this.model) + } + + async deleteTaskList (ev) { + ev?.preventDefault?.() + + // eslint-disable-next-line no-undef + const i18nConfirmDelete = __(LOC_task_list_delete_confirm) + + // FIXME: when tasks are in a modal, api.confirm replaces the modal. This is not ok. + // const result = await api.confirm(i18nConfirmDelete) + const result = confirm(i18nConfirmDelete) + if (!result) { return } + + try { + await this.model.deleteItem() + } catch (err) { + api.alert( + 'error', __('Error'), [__('Error')] + ) + } } } diff --git a/conversejs/custom/plugins/tasks/task-list.js b/conversejs/custom/plugins/tasks/task-list.js index adfbdec6..ebb747d3 100644 --- a/conversejs/custom/plugins/tasks/task-list.js +++ b/conversejs/custom/plugins/tasks/task-list.js @@ -15,6 +15,10 @@ class ChatRoomTaskList extends Model { list: taskListId }) ?? [] } + + async deleteItem () { + return this.collection.chatroom.taskManager.deleteItem(this) + } } export { diff --git a/conversejs/custom/plugins/tasks/task-lists.js b/conversejs/custom/plugins/tasks/task-lists.js index c2942a75..6504625c 100644 --- a/conversejs/custom/plugins/tasks/task-lists.js +++ b/conversejs/custom/plugins/tasks/task-lists.js @@ -1,9 +1,6 @@ import { Collection } from '@converse/skeletor/src/collection.js' import { ChatRoomTaskList } from './task-list' -import { XMLNS_TASKLIST } from './constants' import { initStorage } from '@converse/headless/utils/storage.js' -import { converse, api } from '@converse/headless/core' -const { $build } = converse.env /** * A list of {@link _converse.ChatRoomTaskList} instances, representing task lists associated to a MUC. @@ -37,9 +34,7 @@ class ChatRoomTaskLists extends Collection { if (!name) { throw new Error('Missing name') } console.log('Creating task list ' + name + '...') - const item = $build('item').c('tasklist', { xmlns: XMLNS_TASKLIST }) - item.c('name').t(name) - await api.pubsub.publish(this.chatroom.get('jid'), 'livechat-tasks', item) + await this.chatroom.taskManager.createItem(this, { name }) console.log('Task list ' + name + ' created.') } } diff --git a/conversejs/custom/plugins/tasks/templates/muc-task-list.js b/conversejs/custom/plugins/tasks/templates/muc-task-list.js index 1c0c983a..06b4a3f2 100644 --- a/conversejs/custom/plugins/tasks/templates/muc-task-list.js +++ b/conversejs/custom/plugins/tasks/templates/muc-task-list.js @@ -1,11 +1,19 @@ import { html } from 'lit' import { repeat } from 'lit/directives/repeat.js' +import { __ } from 'i18n' -export default function tplMucTaskList (tasklist) { +export default function tplMucTaskList (el, tasklist) { const tasks = tasklist.getTasks() + // eslint-disable-next-line no-undef + const i18nDelete = __(LOC_task_list_delete) return html`
Tasklist: ${tasklist.get('name')} + + +
${ diff --git a/conversejs/custom/plugins/tasks/templates/muc-task-lists.js b/conversejs/custom/plugins/tasks/templates/muc-task-lists.js index 499cee39..0199e1ae 100644 --- a/conversejs/custom/plugins/tasks/templates/muc-task-lists.js +++ b/conversejs/custom/plugins/tasks/templates/muc-task-lists.js @@ -14,6 +14,13 @@ export default function tplMucTaskLists (el, tasklists) { const i18nTaskListName = __(LOC_task_list_name) return html` +
+ ${ + repeat(tasklists, (tasklist) => tasklist.get('id'), (tasklist) => { + return html`` + }) + } +
-
-
- ${ - repeat(tasklists, (tasklist) => tasklist.get('id'), (tasklist) => { - return html`` - }) - } -
` + ` } diff --git a/conversejs/custom/shared/lib/pubsub-manager.js b/conversejs/custom/shared/lib/pubsub-manager.js index 0e318622..25aec999 100644 --- a/conversejs/custom/shared/lib/pubsub-manager.js +++ b/conversejs/custom/shared/lib/pubsub-manager.js @@ -1,5 +1,5 @@ import { converse, _converse, api } from '../../../src/headless/core.js' -const { Strophe, $iq, sizzle } = converse.env +const { $build, Strophe, $iq, sizzle } = converse.env /** * This class helps to manage some objects that are stored on pubsub nodes. @@ -80,6 +80,61 @@ export class PubSubManager { } } + /** + * Created a new item + * @param collection The collection handling this object. + * @param data Object data + */ + async createItem (collection, data) { + const type = this._typeFromCollection(collection) + if (!type) { + throw new Error('Collection not found in manager') + } + + console.log('Creating item...') + const attributes = { xmlns: type.xmlns } + + for (const attrName in type.attributes ?? []) { + if (!(attrName in data)) { continue } + attributes[attrName] = data[attrName] + } + + const item = $build('item').c(type.itemTag, attributes) + + for (const fieldName in type.fields ?? []) { + if (!(fieldName in data)) { continue } + item.c(fieldName).t(data[fieldName]).up() + } + + await api.pubsub.publish(this.roomJID, this.node, item) + console.log(`Node ${this.node} created on ${this.roomJID}.`) + } + + async deleteItem (item) { + const id = item.get('id') + if (!id) { + throw new Error('Can\'t delete an empty without ID') + } + + const type = this._typeFromCollection(item.collection) + if (!type) { + throw new Error('Can\'t get type definition from item collection') + } + + console.log('Deleting item ' + id + ' on node ' + this.node + ' for room ' + this.roomJID + '...') + + const stanza = $iq({ + from: _converse.bare_jid, + type: 'set', + to: this.roomJID + }).c('pubsub', { xmlns: Strophe.NS.PUBSUB }) + .c('retract', { node: this.node }) + .c('item', { id }) + + await api.sendIQ(stanza) + console.log('Item deleted.') + } + /** * Subscribed to the pubsub node. */ @@ -245,4 +300,8 @@ export class PubSubManager { default: return v // dont know what to do } } + + _typeFromCollection (collection) { + return Object.values(this.types).find(type => type.collection === collection) + } } diff --git a/conversejs/loc.keys.js b/conversejs/loc.keys.js index ad6c6cc8..b98abb02 100644 --- a/conversejs/loc.keys.js +++ b/conversejs/loc.keys.js @@ -19,7 +19,9 @@ const locKeys = [ 'tasks', 'task_list_create', 'task_list_create_error', - 'task_list_name' + 'task_list_name', + 'task_list_delete', + 'task_list_delete_confirm' ] module.exports = locKeys diff --git a/languages/en.yml b/languages/en.yml index 55a2a5bf..7671326c 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -438,4 +438,6 @@ login_external_auth_alert_message: "Authentication failed" tasks: 'Tasks' task_list_create: 'Create new task list:' task_list_create_error: 'Error when saving the task list' -task_list_name: 'Task list name' \ No newline at end of file +task_list_name: 'Task list name' +task_list_delete: 'Delete task list' +task_list_delete_confirm: 'Are you sure you want to delete this task list?'