Task lists WIP:

* front-end
This commit is contained in:
John Livingston 2024-05-06 15:57:42 +02:00
parent 9d5d59e9bc
commit 964b8854f6
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
11 changed files with 155 additions and 19 deletions

View File

@ -8,13 +8,15 @@ export default class MUCTaskListView extends CustomElement {
return {
model: { type: Object, attribute: true },
collapsed: { type: Boolean, attribute: false },
edit: { type: Boolean, attribute: false }
edit: { type: Boolean, attribute: false },
add_task_form_opened: { type: Boolean, attribute: false }
}
}
async initialize () {
this.collapsed = false
this.edit = false
this.add_task_form_opened = false
if (!this.model) {
return
}
@ -82,7 +84,7 @@ export default class MUCTaskListView extends CustomElement {
this.edit = !this.edit
if (this.edit) {
await this.updateComplete
const input = this.querySelector('input[name="name"]')
const input = this.querySelector('.task-list-name input[name="name"]')
if (input) {
input.focus()
// Placing cursor at the end:
@ -91,6 +93,46 @@ export default class MUCTaskListView extends CustomElement {
}
}
}
async openAddTaskForm () {
this.add_task_form_opened = true
await this.updateComplete
const input = this.querySelector('.task-list-add-task input[name="name"]')
if (input) {
input.focus()
}
}
closeAddTaskForm () {
this.add_task_form_opened = false
}
async submitAddTask (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')
})
await this.model.createTask({
name
})
this.closeAddTaskForm()
} catch (err) {
console.error(err)
} finally {
this.querySelectorAll('input[type=submit]').forEach(el => {
el.removeAttribute('disabled')
el.classList.remove('disabled')
})
}
}
}
api.elements.define('livechat-converse-muc-task-list', MUCTaskListView)

View File

@ -1,6 +1,6 @@
import { CustomElement } from 'shared/components/element.js'
import { api } from '@converse/headless/core'
import tplMucTask from './templates/muc-task'
import { tplMucTask } from './templates/muc-task'
export default class MUCTaskView extends CustomElement {
static get properties () {

View File

@ -16,12 +16,25 @@
column-gap: 0.25em;
width: 100%;
button {
.task-list-toggle-tasks,
.task-list-action {
border: 0;
padding-left: 0.25em;
padding-right: 0.25em;
}
.task-list-name {
flex-grow: 2;
form {
display: flex;
flex-flow: row nowrap;
column-gap: 0.25em;
input[type="text"] {
flex-grow: 2;
}
}
}
}
@ -29,5 +42,10 @@
padding-left: 2em;
width: 100%;
}
.task-list-add-task {
padding: 0.25em 0.25em 0.25em 2em;
width: 100%;
}
}
}

View File

@ -23,7 +23,27 @@ class ChatRoomTaskList extends Model {
}
async deleteItem () {
return this.collection.chatroom.taskManager.deleteItem(this)
const tasks = this.getTasks()
return this.collection.chatroom.taskManager.deleteItems([...tasks, this])
}
async createTask (data) {
// Cloning data to avoid side effects:
data = Object.assign({}, data)
const name = data?.name
if (!name) { throw new Error('Missing name') }
data.list = this.get('id')
if (!data.order) {
data.order = 1 + Math.max(...this.getTasks().map(t => t.get('order') ?? 0))
}
console.log('Creating task ' + name + '...')
const chatroom = this.collection.chatroom
const tasksCollection = chatroom.tasks
await chatroom.taskManager.createItem(tasksCollection, data)
console.log('Task list ' + name + ' created.')
}
}

View File

@ -1,23 +1,28 @@
import { html } from 'lit'
import { repeat } from 'lit/directives/repeat.js'
import { __ } from 'i18n'
import { tplMucAddTaskForm } from './muc-task'
export default function tplMucTaskList (el, tasklist) {
const tasks = tasklist.getTasks()
// eslint-disable-next-line no-undef
const i18nDelete = __(LOC_task_list_delete)
// eslint-disable-next-line no-undef
const i18nCreateTask = __(LOC_task_create)
// eslint-disable-next-line no-undef
const i18nTaskListName = __(LOC_task_list_name)
return html`
<div class="task-list-description">
${el.collapsed
? html`
<button @click=${el.toggleTasks}>
<button @click=${el.toggleTasks} class="task-list-toggle-tasks">
<converse-icon
color="var(--muc-toolbar-btn-color)"
class="fa fa-angle-double-up"
size="1em"></converse-icon>
</button>`
: html`
<button @click=${el.toggleTasks}>
<button @click=${el.toggleTasks} class="task-list-toggle-tasks">
<converse-icon
color="var(--muc-toolbar-btn-color)"
class="fa fa-angle-double-down"
@ -29,22 +34,31 @@ export default function tplMucTaskList (el, tasklist) {
<div class="task-list-name">
${tasklist.get('name')}
</div>
<a title="${__('Edit')}"
<button class="task-list-action" title="${i18nCreateTask}" @click=${el.openAddTaskForm}>
<converse-icon class="fa fa-plus" size="1em"></converse-icon>
</button>
<button class="task-list-action" title="${__('Edit')}"
@click=${el.toggleEdit}
>
<converse-icon class="fa fa-edit" size="1em"></converse-icon>
</a>
<a title="${i18nDelete}"
</button>
<button class="task-list-action" title="${i18nDelete}"
@click=${el.deleteTaskList}
>
<converse-icon class="fa fa-trash-alt" size="1em"></converse-icon>
</a>`
</button>`
: html`
<div class="task-list-name">
<form @submit=${el.saveTaskList}>
<input type="text" name="name" autofocus value=${tasklist.get('name')} />
<form @submit=${el.saveTaskList} class="converse-form">
<input type="text" name="name"
placeholder="${__(i18nTaskListName)}"
class="form-control"
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} />
<input type="button" class="btn btn-secondary button-cancel"
value="${__('Cancel')}" @click=${el.toggleEdit}
/>
</form>
</div>`
}
@ -56,5 +70,9 @@ export default function tplMucTaskList (el, tasklist) {
return html`<livechat-converse-muc-task .model=${task}></livechat-converse-muc-task>`
})
}
</div>`
</div>
${!el.add_task_form_opened
? ''
: tplMucAddTaskForm(el, tasklist)
}`
}

View File

@ -23,7 +23,7 @@ export default function tplMucTaskLists (el, tasklists) {
<div class="form-group">
<label>
${i18nCreateTaskList}
<input type="text" value="" name="name" placeholder="${i18nTaskListName}" />
<input type="text" value="" class="form-control" name="name" placeholder="${i18nTaskListName}" />
</label>
<input type="submit" value="${i18nAdd}" class="btn btn-primary" />
${!el.create_tasklist_error_message

View File

@ -1,6 +1,7 @@
import { html } from 'lit'
import { __ } from 'i18n'
export default function tplMucTask (task) {
export function tplMucTask (task) {
const done = task.get('done')
return html`
<div class="">
@ -15,3 +16,29 @@ export default function tplMucTask (task) {
${task.get('name')}
</div>`
}
export function tplMucAddTaskForm (tasklistEl, _tasklist) {
const i18nOk = __('Ok')
const i18nCancel = __('Cancel')
// eslint-disable-next-line no-undef
const i18nTaskName = __(LOC_task_name)
// eslint-disable-next-line no-undef
const i18nTaskDesc = __(LOC_task_description)
return html`
<form class="task-list-add-task converse-form" @submit=${tasklistEl.submitAddTask}>
<fieldset class="form-group">
<input type="text" name="name"
class="form-control" value=""
placeholder="${i18nTaskName}"
/>
<textarea class="form-control" name="description" placeholder="${i18nTaskDesc}"></textarea>
</fieldset>
<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=${tasklistEl.closeAddTaskForm}
/>
</fieldset>
</form>`
}

View File

@ -61,7 +61,8 @@ function _initChatRoomTaskLists (mucModel) {
xmlns: XMLNS_TASK,
collection: mucModel.tasks,
fields: {
name: String
name: String,
description: String
},
attributes: {
done: Boolean,

View File

@ -120,6 +120,10 @@ export class PubSubManager {
console.log(`Node ${this.node} created on ${this.roomJID}.`)
}
async deleteItems (items) {
await Promise.all[items.map(item => this.deleteItem(item))]
}
async deleteItem (item) {
const id = item.get('id')
if (!id) {

View File

@ -21,7 +21,10 @@ const locKeys = [
'task_list_create_error',
'task_list_name',
'task_list_delete',
'task_list_delete_confirm'
'task_list_delete_confirm',
'task_create',
'task_name',
'task_description'
]
module.exports = locKeys

View File

@ -441,3 +441,6 @@ task_list_create_error: 'Error when saving the task list'
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?'
task_create: 'Create a new task'
task_name: 'Task name'
task_description: 'Description'