Task lists WIP:
* task list template + form
This commit is contained in:
parent
d16bdd9a87
commit
9d5d59e9bc
@ -6,11 +6,15 @@ import { __ } from 'i18n'
|
|||||||
export default class MUCTaskListView extends CustomElement {
|
export default class MUCTaskListView extends CustomElement {
|
||||||
static get properties () {
|
static get properties () {
|
||||||
return {
|
return {
|
||||||
model: { type: Object, attribute: true }
|
model: { type: Object, attribute: true },
|
||||||
|
collapsed: { type: Boolean, attribute: false },
|
||||||
|
edit: { type: Boolean, attribute: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize () {
|
async initialize () {
|
||||||
|
this.collapsed = false
|
||||||
|
this.edit = false
|
||||||
if (!this.model) {
|
if (!this.model) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -22,6 +26,34 @@ export default class MUCTaskListView extends CustomElement {
|
|||||||
return tplMucTaskList(this, this.model)
|
return tplMucTaskList(this, this.model)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async saveTaskList (ev) {
|
||||||
|
ev?.preventDefault?.()
|
||||||
|
|
||||||
|
const name = ev.target.name.value.trim()
|
||||||
|
|
||||||
|
if ((name ?? '') === '') { return }
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.querySelectorAll('input[type=submit]').forEach(el => {
|
||||||
|
el.setAttribute('disabled', true)
|
||||||
|
el.classList.add('disabled')
|
||||||
|
})
|
||||||
|
|
||||||
|
const tasklist = this.model
|
||||||
|
tasklist.set('name', name)
|
||||||
|
await tasklist.saveItem()
|
||||||
|
|
||||||
|
this.edit = false
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
} finally {
|
||||||
|
this.querySelectorAll('input[type=submit]').forEach(el => {
|
||||||
|
el.removeAttribute('disabled')
|
||||||
|
el.classList.remove('disabled')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async deleteTaskList (ev) {
|
async deleteTaskList (ev) {
|
||||||
ev?.preventDefault?.()
|
ev?.preventDefault?.()
|
||||||
|
|
||||||
@ -41,6 +73,24 @@ export default class MUCTaskListView extends CustomElement {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleTasks () {
|
||||||
|
this.collapsed = !this.collapsed
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleEdit () {
|
||||||
|
this.edit = !this.edit
|
||||||
|
if (this.edit) {
|
||||||
|
await this.updateComplete
|
||||||
|
const input = this.querySelector('input[name="name"]')
|
||||||
|
if (input) {
|
||||||
|
input.focus()
|
||||||
|
// Placing cursor at the end:
|
||||||
|
input.selectionStart = input.value.length
|
||||||
|
input.selectionEnd = input.selectionStart
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.elements.define('livechat-converse-muc-task-list', MUCTaskListView)
|
api.elements.define('livechat-converse-muc-task-list', MUCTaskListView)
|
||||||
|
@ -3,6 +3,8 @@ import { api } from '@converse/headless/core'
|
|||||||
import tplMucTaskLists from './templates/muc-task-lists'
|
import tplMucTaskLists from './templates/muc-task-lists'
|
||||||
import { __ } from 'i18n'
|
import { __ } from 'i18n'
|
||||||
|
|
||||||
|
import './styles/muc-task-lists.scss'
|
||||||
|
|
||||||
export default class MUCTaskListsView extends CustomElement {
|
export default class MUCTaskListsView extends CustomElement {
|
||||||
static get properties () {
|
static get properties () {
|
||||||
return {
|
return {
|
||||||
|
33
conversejs/custom/plugins/tasks/styles/muc-task-lists.scss
Normal file
33
conversejs/custom/plugins/tasks/styles/muc-task-lists.scss
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
.conversejs {
|
||||||
|
livechat-converse-muc-task-lists {
|
||||||
|
padding: 1em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
livechat-converse-muc-task-list {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.task-list-description {
|
||||||
|
border: 1px solid var(--chatroom-head-bg-color);
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 0.25em;
|
||||||
|
column-gap: 0.25em;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-list-name {
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-list-tasks {
|
||||||
|
padding-left: 2em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,12 @@ class ChatRoomTaskList extends Model {
|
|||||||
}) ?? []
|
}) ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async saveItem () {
|
||||||
|
console.log('Saving task list ' + this.get('id') + '...')
|
||||||
|
await this.collection.chatroom.taskManager.saveItem(this, { name })
|
||||||
|
console.log('Task list ' + this.get('id') + ' created.')
|
||||||
|
}
|
||||||
|
|
||||||
async deleteItem () {
|
async deleteItem () {
|
||||||
return this.collection.chatroom.taskManager.deleteItem(this)
|
return this.collection.chatroom.taskManager.deleteItem(this)
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,52 @@ export default function tplMucTaskList (el, tasklist) {
|
|||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const i18nDelete = __(LOC_task_list_delete)
|
const i18nDelete = __(LOC_task_list_delete)
|
||||||
return html`
|
return html`
|
||||||
<div class="">
|
<div class="task-list-description">
|
||||||
Tasklist: ${tasklist.get('name')}
|
${el.collapsed
|
||||||
<a class="" title="${i18nDelete}"
|
? html`
|
||||||
@click=${el.deleteTaskList}
|
<button @click=${el.toggleTasks}>
|
||||||
>
|
<converse-icon
|
||||||
<converse-icon class="fa fa-trash-alt" size="1em"></converse-icon>
|
color="var(--muc-toolbar-btn-color)"
|
||||||
</a>
|
class="fa fa-angle-double-up"
|
||||||
|
size="1em"></converse-icon>
|
||||||
|
</button>`
|
||||||
|
: html`
|
||||||
|
<button @click=${el.toggleTasks}>
|
||||||
|
<converse-icon
|
||||||
|
color="var(--muc-toolbar-btn-color)"
|
||||||
|
class="fa fa-angle-double-down"
|
||||||
|
size="1em"></converse-icon>
|
||||||
|
</button>`
|
||||||
|
}
|
||||||
|
${!el.edit
|
||||||
|
? html`
|
||||||
|
<div class="task-list-name">
|
||||||
|
${tasklist.get('name')}
|
||||||
|
</div>
|
||||||
|
<a title="${__('Edit')}"
|
||||||
|
@click=${el.toggleEdit}
|
||||||
|
>
|
||||||
|
<converse-icon class="fa fa-edit" size="1em"></converse-icon>
|
||||||
|
</a>
|
||||||
|
<a title="${i18nDelete}"
|
||||||
|
@click=${el.deleteTaskList}
|
||||||
|
>
|
||||||
|
<converse-icon class="fa fa-trash-alt" size="1em"></converse-icon>
|
||||||
|
</a>`
|
||||||
|
: html`
|
||||||
|
<div class="task-list-name">
|
||||||
|
<form @submit=${el.saveTaskList}>
|
||||||
|
<input type="text" name="name" autofocus value=${tasklist.get('name')} />
|
||||||
|
<input type="submit" class="btn btn-primary" value="${__('Ok')}" />
|
||||||
|
<input type="reset" class="btn btn-secondary" value="${__('Cancel')}" @click=${el.toggleEdit} />
|
||||||
|
</form>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="task-list-tasks">
|
||||||
${
|
${el.collapsed
|
||||||
repeat(tasks, (task) => task.get('id'), (task) => {
|
? ''
|
||||||
|
: repeat(tasks, (task) => task.get('id'), (task) => {
|
||||||
return html`<livechat-converse-muc-task .model=${task}></livechat-converse-muc-task>`
|
return html`<livechat-converse-muc-task .model=${task}></livechat-converse-muc-task>`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,11 @@ export default function tplMucTaskLists (el, tasklists) {
|
|||||||
const i18nTaskListName = __(LOC_task_list_name)
|
const i18nTaskListName = __(LOC_task_list_name)
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="">
|
${
|
||||||
${
|
repeat(tasklists, (tasklist) => tasklist.get('id'), (tasklist) => {
|
||||||
repeat(tasklists, (tasklist) => tasklist.get('id'), (tasklist) => {
|
return html`<livechat-converse-muc-task-list .model=${tasklist}></livechat-converse-muc-task-list>`
|
||||||
return html`<livechat-converse-muc-task-list .model=${tasklist}></livechat-converse-muc-task-list>`
|
})
|
||||||
})
|
}
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<form class="converse-form" @submit=${el.submitCreateTaskList}>
|
<form class="converse-form" @submit=${el.submitCreateTaskList}>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>
|
<label>
|
||||||
|
@ -92,21 +92,31 @@ export class PubSubManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('Creating item...')
|
console.log('Creating item...')
|
||||||
const attributes = { xmlns: type.xmlns }
|
await this._save(type, data)
|
||||||
|
console.log(`Node ${this.node} created on ${this.roomJID}.`)
|
||||||
|
}
|
||||||
|
|
||||||
for (const attrName in type.attributes ?? []) {
|
async saveItem (item) {
|
||||||
if (!(attrName in data)) { continue }
|
const id = item.get('id')
|
||||||
attributes[attrName] = data[attrName]
|
if (!id) {
|
||||||
|
throw new Error('Can\'t delete an empty without ID')
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = $build('item').c(type.itemTag, attributes)
|
const type = this._typeFromCollection(item.collection)
|
||||||
|
if (!type) {
|
||||||
for (const fieldName in type.fields ?? []) {
|
throw new Error('Collection not found in manager')
|
||||||
if (!(fieldName in data)) { continue }
|
|
||||||
item.c(fieldName).t(data[fieldName]).up()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await api.pubsub.publish(this.roomJID, this.node, item)
|
const data = {}
|
||||||
|
for (const attr in (type.attributes ?? [])) {
|
||||||
|
data[attr] = item.get(attr)
|
||||||
|
}
|
||||||
|
for (const field in (type.fields ?? [])) {
|
||||||
|
data[field] = item.get(field)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Saving item...')
|
||||||
|
await this._save(type, data, id)
|
||||||
console.log(`Node ${this.node} created on ${this.roomJID}.`)
|
console.log(`Node ${this.node} created on ${this.roomJID}.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +145,29 @@ export class PubSubManager {
|
|||||||
console.log('Item deleted.')
|
console.log('Item deleted.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _save (type, data, id) {
|
||||||
|
const itemAttributes = {}
|
||||||
|
if (id) {
|
||||||
|
itemAttributes.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributes = { xmlns: type.xmlns }
|
||||||
|
|
||||||
|
for (const attrName in type.attributes ?? []) {
|
||||||
|
if (!(attrName in data)) { continue }
|
||||||
|
attributes[attrName] = data[attrName]
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = $build('item', itemAttributes).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)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribed to the pubsub node.
|
* Subscribed to the pubsub node.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user