diff --git a/conversejs/custom/plugins/notes/components/muc-note-occupant-view.js b/conversejs/custom/plugins/notes/components/muc-note-occupant-view.js new file mode 100644 index 00000000..51ed79ae --- /dev/null +++ b/conversejs/custom/plugins/notes/components/muc-note-occupant-view.js @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { CustomElement } from 'shared/components/element.js' +import { tplMucNoteOccupant } from '../templates/muc-note-occupant' +import { api } from '@converse/headless' + +import '../styles/muc-note-occupant.scss' + +export default class MUCNoteOccupantView extends CustomElement { + static get properties () { + return { + model: { type: Object, attribute: true }, + full_display: { type: Boolean, attribute: true } + } + } + + async initialize () { + this.listenTo(this.model, 'change', () => this.requestUpdate()) + } + + render () { + return tplMucNoteOccupant(this, this.model) + } +} + +api.elements.define('livechat-converse-muc-note-occupant', MUCNoteOccupantView) diff --git a/conversejs/custom/plugins/notes/components/muc-notes-view.js b/conversejs/custom/plugins/notes/components/muc-notes-view.js index ef5c9900..f16656fb 100644 --- a/conversejs/custom/plugins/notes/components/muc-notes-view.js +++ b/conversejs/custom/plugins/notes/components/muc-notes-view.js @@ -14,7 +14,8 @@ export default class MUCNotesView extends DraggablesCustomElement { return { model: { type: Object, attribute: true }, create_note_error_message: { type: String, attribute: false }, - create_note_opened: { type: Boolean, attribute: false } + create_note_opened: { type: Boolean, attribute: false }, + create_note_for_occupant: { type: Object, attribute: false } } } @@ -41,9 +42,10 @@ export default class MUCNotesView extends DraggablesCustomElement { return tplMucNotes(this, this.model) } - async openCreateNoteForm (ev) { + async openCreateNoteForm (ev, occupant) { ev?.preventDefault?.() this.create_note_opened = true + this.create_note_for_occupant = occupant ?? undefined await this.updateComplete const textarea = this.querySelector('.notes-create-note textarea[name="description"]') if (textarea) { @@ -54,6 +56,7 @@ export default class MUCNotesView extends DraggablesCustomElement { closeCreateNoteForm (ev) { ev?.preventDefault?.() this.create_note_opened = false + this.create_note_for_occupant = undefined } async submitCreateNote (ev) { diff --git a/conversejs/custom/plugins/notes/index.js b/conversejs/custom/plugins/notes/index.js index a1bd5d66..860ec9eb 100644 --- a/conversejs/custom/plugins/notes/index.js +++ b/conversejs/custom/plugins/notes/index.js @@ -11,6 +11,7 @@ import { initOrDestroyChatRoomNotes, getHeadingButtons, getMessageActionButtons import './components/muc-note-app-view.js' import './components/muc-notes-view.js' import './components/muc-note-view.js' +import './components/muc-note-occupant-view.js' converse.plugins.add('livechat-converse-notes', { dependencies: ['converse-muc', 'converse-disco', 'converse-pubsub'], diff --git a/conversejs/custom/plugins/notes/styles/muc-note-occupant.scss b/conversejs/custom/plugins/notes/styles/muc-note-occupant.scss new file mode 100644 index 00000000..18f3819a --- /dev/null +++ b/conversejs/custom/plugins/notes/styles/muc-note-occupant.scss @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2024 John Livingston + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +.conversejs { + livechat-converse-muc-note-occupant { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: space-between; + padding: 0.25em; + + & > a { + display: flex; + flex-flow: row nowrap; + align-items: center; + + span { + font-weight: bold; + margin-left: 0.5em; + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + } + } + + & > ul { + list-style: none; + text-align: right; + } + } +} diff --git a/conversejs/custom/plugins/notes/templates/muc-note-occupant.js b/conversejs/custom/plugins/notes/templates/muc-note-occupant.js new file mode 100644 index 00000000..1ed19b9d --- /dev/null +++ b/conversejs/custom/plugins/notes/templates/muc-note-occupant.js @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { html } from 'lit' +import { api } from '@converse/headless' +import { getAuthorStyle } from '../../../../src/utils/color.js' +import { __ } from 'i18n' + +export function tplMucNoteOccupant (el, occupant) { + const authorStyle = getAuthorStyle(occupant) + const jid = occupant.get('jid') + const occupantId = occupant.get('occupant_id') + + return html` + { + api.modal.show('converse-muc-occupant-modal', { model: occupant }, ev) + }}> + + + ${occupant.getDisplayName()} + + ${ + el.full_display + ? html`
    + ${jid ? html`
  • ${jid}
  • ` : ''} + ${occupantId ? html`
  • ${occupantId}
  • ` : ''} +
` + : '' + } + ` +} diff --git a/conversejs/custom/plugins/notes/templates/muc-note.js b/conversejs/custom/plugins/notes/templates/muc-note.js index 0eebcd4b..c60e966a 100644 --- a/conversejs/custom/plugins/notes/templates/muc-note.js +++ b/conversejs/custom/plugins/notes/templates/muc-note.js @@ -50,12 +50,32 @@ function _tplNoteForm (note) { ` } -export function tplMucCreateNoteForm (notesEl) { +function _tplNoteOccupantFormFields (occupant) { + if (!occupant) { return '' } + return html` + + + + ` +} + +export function tplMucCreateNoteForm (notesEl, occupant) { const i18nOk = __('Ok') const i18nCancel = __('Cancel') return html`
+ ${ + occupant + ? html` + ${_tplNoteOccupantFormFields(occupant)} + + ` + : '' + } ${_tplNoteForm(undefined)}
diff --git a/conversejs/custom/plugins/notes/templates/muc-notes.js b/conversejs/custom/plugins/notes/templates/muc-notes.js index 8a0aa363..aa4832f8 100644 --- a/conversejs/custom/plugins/notes/templates/muc-notes.js +++ b/conversejs/custom/plugins/notes/templates/muc-notes.js @@ -14,7 +14,7 @@ export default function tplMucNotes (el, notes) { return html` ${ - el.create_note_opened ? tplMucCreateNoteForm(el) : tplCreateButton(el) + el.create_note_opened ? tplMucCreateNoteForm(el, el.create_note_for_occupant) : tplCreateButton(el) } ${ repeat(notes, (note) => note.get('id'), (note) => { diff --git a/conversejs/custom/plugins/notes/utils.js b/conversejs/custom/plugins/notes/utils.js index e06d4e93..7f9c7d50 100644 --- a/conversejs/custom/plugins/notes/utils.js +++ b/conversejs/custom/plugins/notes/utils.js @@ -48,23 +48,33 @@ export function getMessageActionButtons (messageActionsEl, buttons) { return buttons } - // TODO: button to create a note from a message. - // // eslint-disable-next-line no-undef - // const i18nCreate = __(LOC_task_create) + if (messageModel.occupant) { + // eslint-disable-next-line no-undef + const i18nCreate = __(LOC_moderator_note_create_for_participant) - // 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' - // }) + buttons.push({ + i18n_text: i18nCreate, + handler: async (ev) => { + ev.preventDefault() + const appElement = document.querySelector('livechat-converse-muc-note-app') + if (!appElement) { + throw new Error('Cant find Note App Element') + } + await appElement.showApp() + await appElement.updateComplete // waiting for the app to be open + + const notesElement = appElement.querySelector('livechat-converse-muc-notes') + if (!notesElement) { + throw new Error('Cant find Notes Element') + } + await notesElement.updateComplete + notesElement.openCreateNoteForm(undefined, messageModel.occupant) + }, + button_class: '', + icon_class: 'fa fa-note-sticky', + name: 'muc-note-create-for-occupant' + }) + } return buttons } diff --git a/conversejs/custom/shared/components/muc-app/index.js b/conversejs/custom/shared/components/muc-app/index.js index 40f13911..a532391a 100644 --- a/conversejs/custom/shared/components/muc-app/index.js +++ b/conversejs/custom/shared/components/muc-app/index.js @@ -76,6 +76,14 @@ export class MUCApp extends CustomElement { } } + showApp () { + if (!this.show) { return this.toggleApp() } + } + + hideApp () { + if (this.show) { return this.toggleApp() } + } + _closeOtherApps () { document.querySelectorAll('.livechat-converse-muc-app').forEach((el) => { if (el !== this && el.show) { diff --git a/conversejs/loc.keys.js b/conversejs/loc.keys.js index 9be7414d..70307fce 100644 --- a/conversejs/loc.keys.js +++ b/conversejs/loc.keys.js @@ -55,7 +55,8 @@ const locKeys = [ 'moderator_note_create', 'moderator_note_description', 'moderator_note_delete', - 'moderator_note_delete_confirm' + 'moderator_note_delete_confirm', + 'moderator_note_create_for_participant' ] module.exports = locKeys diff --git a/languages/en.yml b/languages/en.yml index 376a24b5..ab5b949c 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -600,3 +600,4 @@ moderator_note_create: 'Create a new note' moderator_note_description: 'Description' moderator_note_delete: 'Delete note' moderator_note_delete_confirm: 'Are you sure you want to delete this note?' +moderator_note_create_for_participant: 'Create a new note for this participant'