-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9ed20b4
commit a17a72d
Showing
12 changed files
with
398 additions
and
10 deletions.
There are no files selected for viewing
109 changes: 109 additions & 0 deletions
109
conversejs/custom/plugins/notes/components/muc-note-view.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> | ||
// | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
import { CustomElement } from 'shared/components/element.js' | ||
import { api } from '@converse/headless' | ||
import { tplMucNote } from '../templates/muc-note' | ||
import { __ } from 'i18n' | ||
|
||
import '../styles/muc-note.scss' | ||
|
||
export default class MUCNoteView extends CustomElement { | ||
static get properties () { | ||
return { | ||
model: { type: Object, attribute: true }, | ||
edit: { type: Boolean, attribute: false } | ||
} | ||
} | ||
|
||
async initialize () { | ||
this.edit = false | ||
if (!this.model) { | ||
return | ||
} | ||
|
||
this.listenTo(this.model, 'change', () => this.requestUpdate()) | ||
} | ||
|
||
render () { | ||
return tplMucNote(this, this.model) | ||
} | ||
|
||
shouldUpdate (changedProperties) { | ||
if (!super.shouldUpdate(...arguments)) { return false } | ||
// When a note is currently edited, and another users change the order, | ||
// it could refresh losing the current form. | ||
// To avoid this, we cancel update here. | ||
// Note: of course, if 'edit' is part of the edited properties, we must update anyway | ||
// (it means we just leaved the form) | ||
if (this.edit && !changedProperties.has('edit')) { | ||
console.info('Canceling an update on note, because it is currently edited', this) | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
async saveNote (ev) { | ||
ev?.preventDefault?.() | ||
|
||
const description = ev.target.description.value | ||
|
||
if ((description ?? '') === '') { return } | ||
|
||
try { | ||
this.querySelectorAll('input[type=submit]').forEach(el => { | ||
el.setAttribute('disabled', true) | ||
el.classList.add('disabled') | ||
}) | ||
|
||
const note = this.model | ||
note.set('description', description) | ||
await note.saveItem() | ||
|
||
this.edit = false | ||
this.requestUpdate() // In case we cancel another update in shouldUpdate | ||
} catch (err) { | ||
console.error(err) | ||
} finally { | ||
this.querySelectorAll('input[type=submit]').forEach(el => { | ||
el.removeAttribute('disabled') | ||
el.classList.remove('disabled') | ||
}) | ||
} | ||
} | ||
|
||
async deleteNote (ev) { | ||
ev?.preventDefault?.() | ||
|
||
// eslint-disable-next-line no-undef | ||
const i18nConfirmDelete = __(LOC_moderator_note_delete_confirm) | ||
|
||
const result = await api.confirm(i18nConfirmDelete) | ||
if (!result) { return } | ||
|
||
try { | ||
await this.model.deleteItem() | ||
} catch (err) { | ||
api.alert( | ||
'error', __('Error'), [__('Error')] | ||
) | ||
} | ||
} | ||
|
||
async toggleEdit () { | ||
this.edit = !this.edit | ||
if (this.edit) { | ||
await this.updateComplete | ||
const textarea = this.querySelector('textarea[name="description"]') | ||
if (textarea) { | ||
textarea.focus() | ||
// Placing cursor at the end: | ||
textarea.selectionStart = textarea.value.length | ||
textarea.selectionEnd = textarea.selectionStart | ||
} | ||
} | ||
} | ||
} | ||
|
||
api.elements.define('livechat-converse-muc-note', MUCNoteView) |
95 changes: 95 additions & 0 deletions
95
conversejs/custom/plugins/notes/components/muc-notes-view.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> | ||
// | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
import { CustomElement } from 'shared/components/element.js' | ||
import { api } from '@converse/headless' | ||
import tplMucNotes from '../templates/muc-notes' | ||
import { __ } from 'i18n' | ||
|
||
import '../styles/muc-notes.scss' | ||
|
||
export default class MUCNotesView extends CustomElement { | ||
currentDraggedNote = null | ||
|
||
static get properties () { | ||
return { | ||
model: { type: Object, attribute: true }, | ||
create_note_error_message: { type: String, attribute: false }, | ||
create_note_opened: { type: Boolean, attribute: false } | ||
} | ||
} | ||
|
||
async initialize () { | ||
this.create_note_error_message = '' | ||
|
||
if (!this.model) { | ||
return | ||
} | ||
|
||
// Adding or removing a new note: we must update. | ||
this.listenTo(this.model, 'add', () => this.requestUpdate()) | ||
this.listenTo(this.model, 'remove', () => this.requestUpdate()) | ||
this.listenTo(this.model, 'sort', () => this.requestUpdate()) | ||
|
||
// this._handleDragStartBinded = this._handleDragStart.bind(this) | ||
// this._handleDragOverBinded = this._handleDragOver.bind(this) | ||
// this._handleDragLeaveBinded = this._handleDragLeave.bind(this) | ||
// this._handleDragEndBinded = this._handleDragEnd.bind(this) | ||
// this._handleDropBinded = this._handleDrop.bind(this) | ||
} | ||
|
||
render () { | ||
return tplMucNotes(this, this.model) | ||
} | ||
|
||
async openCreateNoteForm (ev) { | ||
ev?.preventDefault?.() | ||
this.create_note_opened = true | ||
await this.updateComplete | ||
const textarea = this.querySelector('.notes-create-note textarea[name="description"]') | ||
if (textarea) { | ||
textarea.focus() | ||
} | ||
} | ||
|
||
closeCreateNoteForm (ev) { | ||
ev?.preventDefault?.() | ||
this.create_note_opened = false | ||
} | ||
|
||
async submitCreateNote (ev) { | ||
ev.preventDefault() | ||
|
||
const description = ev.target.description.value | ||
if (this.create_note_error_message) { | ||
this.create_note_error_message = '' | ||
} | ||
|
||
if ((description ?? '') === '') { return } | ||
|
||
try { | ||
this.querySelectorAll('input[type=submit]').forEach(el => { | ||
el.setAttribute('disabled', true) | ||
el.classList.add('disabled') | ||
}) | ||
|
||
await this.model.createNote({ | ||
description: description | ||
}) | ||
|
||
this.closeCreateNoteForm() | ||
} catch (err) { | ||
console.error(err) | ||
// eslint-disable-next-line no-undef | ||
this.create_note_error_message = __(LOC_moderator_notes_create_error) | ||
} finally { | ||
this.querySelectorAll('input[type=submit]').forEach(el => { | ||
el.removeAttribute('disabled') | ||
el.classList.remove('disabled') | ||
}) | ||
} | ||
} | ||
} | ||
|
||
api.elements.define('livechat-converse-muc-notes', MUCNotesView) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> | ||
* | ||
* SPDX-License-Identifier: AGPL-3.0-only | ||
*/ | ||
|
||
.conversejs { | ||
livechat-converse-muc-note { | ||
padding: 0; | ||
width: 100%; | ||
|
||
.note-line { | ||
border: 1px solid var(--chatroom-head-bg-color); | ||
border-radius: 4px; | ||
display: flex; | ||
flex-flow: row nowrap; | ||
justify-content: space-around; | ||
margin: 0.25em 0; | ||
padding: 0.25em; | ||
column-gap: 0.25em; | ||
width: 100%; | ||
|
||
.note-description { | ||
flex-grow: 2; | ||
white-space: pre-wrap; | ||
} | ||
|
||
.note-action { | ||
background: unset; | ||
border: 0; | ||
padding-left: 0.25em; | ||
padding-right: 0.25em; | ||
} | ||
|
||
form { | ||
width: 100%; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> | ||
* | ||
* SPDX-License-Identifier: AGPL-3.0-only | ||
*/ | ||
|
||
.conversejs { | ||
.notes-actions { | ||
display: flex; | ||
flex-flow: row nowrap; | ||
justify-content: right; | ||
width: 100%; | ||
} | ||
|
||
.notes-action { | ||
background: unset; | ||
border: 0; | ||
padding-left: 0.25em; | ||
padding-right: 0.25em; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> | ||
// | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
import { html } from 'lit' | ||
import { __ } from 'i18n' | ||
|
||
export function tplMucNote (el, note) { | ||
// eslint-disable-next-line no-undef | ||
const i18nDelete = __(LOC_moderator_note_delete) | ||
|
||
return !el.edit | ||
? html` | ||
<div draggable="true" class="note-line"> | ||
<div class="note-description">${note.get('description') ?? ''}</div> | ||
<button class="note-action" title="${__('Edit')}" | ||
@click=${el.toggleEdit} | ||
> | ||
<converse-icon class="fa fa-edit" size="1em"></converse-icon> | ||
</button> | ||
<button class="note-action" title="${i18nDelete}" | ||
@click=${el.deleteNote} | ||
> | ||
<converse-icon class="fa fa-trash-alt" size="1em"></converse-icon> | ||
</button> | ||
</div>` | ||
: html` | ||
<div class="note-line"> | ||
<form class="converse-form" @submit=${el.saveNote}> | ||
${_tplNoteForm(note)} | ||
<fieldset class="form-group"> | ||
<input type="submit" class="btn btn-primary" value="${__('Ok')}" /> | ||
<input type="button" class="btn btn-secondary button-cancel" | ||
value="${__('Cancel')}" @click=${el.toggleEdit} | ||
/> | ||
</fieldset> | ||
</form> | ||
</div>` | ||
} | ||
|
||
function _tplNoteForm (note) { | ||
// eslint-disable-next-line no-undef | ||
const i18nNoteDesc = __(LOC_moderator_note_description) | ||
|
||
return html`<fieldset class="form-group"> | ||
<textarea | ||
class="form-control" name="description" | ||
placeholder="${i18nNoteDesc}" | ||
>${note ? note.get('description') : ''}</textarea> | ||
</fieldset>` | ||
} | ||
|
||
export function tplMucCreateNoteForm (notesEl) { | ||
const i18nOk = __('Ok') | ||
const i18nCancel = __('Cancel') | ||
|
||
return html` | ||
<form class="notes-create-note converse-form" @submit=${notesEl.submitCreateNote}> | ||
${_tplNoteForm(undefined)} | ||
<fieldset class="form-group"> | ||
<input type="submit" class="btn btn-primary" value="${i18nOk}" /> | ||
<input type="button" class="btn btn-secondary button-cancel" | ||
value="${i18nCancel}" @click=${notesEl.closeCreateNoteForm} | ||
/> | ||
${!notesEl.create_note_error_message | ||
? '' | ||
: html`<div class="invalid-feedback d-block">${notesEl.create_note_error_message}</div>` | ||
} | ||
</fieldset> | ||
</form>` | ||
} |
Oops, something went wrong.