Task lists WIP

This commit is contained in:
John Livingston 2024-04-30 18:30:44 +02:00
parent ca026c2e10
commit 22561b4daa
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
13 changed files with 205 additions and 10 deletions

View File

@ -1,7 +1,10 @@
import { _converse, converse } from '../../../src/headless/core.js'
import { ChatRoomTaskLists } from './task-lists.js'
import { ChatRoomTaskList } from './task-list.js'
import { ChatRoomTasks } from './tasks.js'
import { getHeadingButtons, initOrDestroyChatRoomTaskLists } from './utils.js'
import './muc-task-view.js' // FIXME: here or in another file?
import './muc-task-list-view.js' // FIXME: here or in another file?
import './muc-task-lists-view.js' // FIXME: here or in another file?
import './modals/muc-task-lists.js' // FIXME: here or in another file?
@ -11,6 +14,7 @@ converse.plugins.add('livechat-converse-tasks', {
initialize () {
_converse.ChatRoomTaskLists = ChatRoomTaskLists
_converse.ChatRoomTaskList = ChatRoomTaskList
_converse.ChatRoomTasks = ChatRoomTasks
_converse.api.listen.on('chatRoomInitialized', muc => {
muc.session.on('change:connection_status', _session => {

View File

@ -6,7 +6,7 @@ import { __ } from 'i18n'
export default class mucTaskListsModal extends BaseModal {
renderModal () {
const muc = this.model
return html`<livechat-converse-muc-task-lists jid="${muc.get('jid')}"></livechat-converse-muc-task-lists>`
return html`<livechat-converse-muc-task-lists .model=${muc.tasklists}></livechat-converse-muc-task-lists>`
}
getModalTitle () {

View File

@ -0,0 +1,25 @@
import { CustomElement } from 'shared/components/element.js'
import { api } from '@converse/headless/core'
import tplMucTaskList from './templates/muc-task-list'
export default class MUCTaskListView extends CustomElement {
static get properties () {
return {
model: { type: Object, attribute: true }
}
}
async initialize () {
if (!this.model) {
return
}
this.listenTo(this.model, 'change', () => this.requestUpdate())
}
render () {
return tplMucTaskList(this.model)
}
}
api.elements.define('livechat-converse-muc-task-list', MUCTaskListView)

View File

@ -1,23 +1,22 @@
import { CustomElement } from 'shared/components/element.js'
import { _converse, api } from '@converse/headless/core'
import { api } from '@converse/headless/core'
import tplMucTaskLists from './templates/muc-task-lists'
export default class MUCTaskListsView extends CustomElement {
static get properties () {
return {
jid: { type: String, attribute: true }
model: { type: Object, attribute: true }
}
}
async initialize () {
this.model = _converse.chatboxes.get(this.getAttribute('jid')).tasklists
if (!this.model) {
return
}
// Adding or removing a new task list: we must update.
this.listenTo(this.model, 'add', () => this.requestUpdate())
this.listenTo(this.model, 'change', () => this.requestUpdate())
this.listenTo(this.model, 'remove', () => this.requestUpdate())
}
render () {

View File

@ -0,0 +1,25 @@
import { CustomElement } from 'shared/components/element.js'
import { api } from '@converse/headless/core'
import tplMucTask from './templates/muc-task'
export default class MUCTaskView extends CustomElement {
static get properties () {
return {
model: { type: Object, attribute: true }
}
}
async initialize () {
if (!this.model) {
return
}
this.listenTo(this.model, 'change', () => this.requestUpdate())
}
render () {
return tplMucTask(this.model)
}
}
api.elements.define('livechat-converse-muc-task', MUCTaskView)

View File

@ -8,6 +8,13 @@ import { Model } from '@converse/skeletor/src/model.js'
*/
class ChatRoomTaskList extends Model {
idAttribute = 'id'
getTasks () {
const taskListId = this.get('id')
return this.collection?.chatroom?.tasks?.filter({
list: taskListId
}) ?? []
}
}
export {

View File

@ -13,6 +13,7 @@ class ChatRoomTaskLists extends Collection {
model = ChatRoomTaskList
initialize (models, options) {
this.model = ChatRoomTaskList // don't know why, must do it again here
super.initialize(arguments)
this.chatroom = options.chatroom
@ -32,6 +33,9 @@ class ChatRoomTaskLists extends Collection {
}
create (attrs, options) {
if (attrs instanceof ChatRoomTaskList) {
return super.create(attrs, options)
}
attrs.id ??= getUniqueId()
return super.create(attrs, options)
}
@ -47,7 +51,7 @@ class ChatRoomTaskLists extends Collection {
name: 'Task List 1'
},
{
// id: 'task-list-2',
id: 'task-list-2',
name: 'Task List 2'
}
]

View File

@ -0,0 +1,15 @@
import { Model } from '@converse/skeletor/src/model.js'
/**
* A chat room task.
* @class
* @namespace _converse.ChatRoomTask
* @memberof _converse
*/
class ChatRoomTask extends Model {
idAttribute = 'id'
}
export {
ChatRoomTask
}

View File

@ -0,0 +1,95 @@
import { Collection } from '@converse/skeletor/src/collection.js'
import { ChatRoomTask } from './task'
import { initStorage } from '@converse/headless/utils/storage.js'
import { getUniqueId } from '@converse/headless/utils/core.js'
/**
* A list of {@link _converse.ChatRoomTask} instances, representing all tasks associated to a MUC.
* @class
* @namespace _converse.ChatRoomTasks
* @memberOf _converse
*/
class ChatRoomTasks extends Collection {
model = ChatRoomTask
comparator = 'order'
initialize (models, options) {
this.model = ChatRoomTask // don't know why, must do it again here
super.initialize(arguments)
this.chatroom = options.chatroom
const id = `converse-livechat-tasks-${this.chatroom.get('jid')}`
initStorage(this, id, 'session')
this.on('change:order', () => this.sort())
this.fetchTasks().catch(console.error)
}
create (attrs, options) {
if (attrs instanceof ChatRoomTask) {
return super.create(attrs, options)
}
attrs.id ??= getUniqueId()
return super.create(attrs, options)
}
/**
* Requires Task lists from the server.
*/
async fetchTasks () {
// TODO: remove these test lines, and subscribe to pubsub.
const tasksData = [
{
id: 'task-1',
name: 'Task 1.1',
list: 'task-list-1',
order: 1,
done: false
},
{
id: 'task-2',
name: 'Task 1.2',
list: 'task-list-1',
order: 2,
done: true
},
{
id: 'task-3',
name: 'Task 2.1',
list: 'task-list-2',
order: 1,
done: false
}
]
for (const item of tasksData) {
let id = item.id
const task = id ? this.get(id) : undefined
if (task) {
task.save({
name: item.name,
list: item.list,
order: item.order,
done: item.done
})
return
}
id ??= getUniqueId()
this.create({
id,
name: item.name,
list: item.list,
order: item.order,
done: item.done
})
}
}
}
export {
ChatRoomTasks
}

View File

@ -1,7 +1,17 @@
import { html } from 'lit'
import { repeat } from 'lit/directives/repeat.js'
export default function tplMucTaskList (tasklist) {
return html`<div class="">
const tasks = tasklist.getTasks()
return html`
<div class="">
Tasklist: ${tasklist.get('name')}
</div>
<div class="">
${
repeat(tasks, (task) => task.get('id'), (task) => {
return html`<livechat-converse-muc-task .model=${task}></livechat-converse-muc-task>`
})
}
</div>`
}

View File

@ -1,4 +1,3 @@
import tplMucTaskList from './muc-task-list'
import { html } from 'lit'
import { repeat } from 'lit/directives/repeat.js'
import { __ } from 'i18n'
@ -37,7 +36,9 @@ export default function tplMucTaskLists (tasklists) {
</form>
<div class="">
${
repeat(tasklists, (tasklist) => tasklist.get('id'), (tasklist) => tplMucTaskList(tasklist))
repeat(tasklists, (tasklist) => tasklist.get('id'), (tasklist) => {
return html`<livechat-converse-muc-task-list .model=${tasklist}></livechat-converse-muc-task-list>`
})
}
</div>`
}

View File

@ -0,0 +1,8 @@
import { html } from 'lit'
export default function tplMucTask (task) {
return html`
<div class="">
Task: ${task.get('name')}
</div>`
}

View File

@ -37,6 +37,7 @@ function _initChatRoomTaskLists (mucModel) {
}
mucModel.tasklists = new _converse.ChatRoomTaskLists(undefined, { chatroom: mucModel })
mucModel.tasks = new _converse.ChatRoomTasks(undefined, { chatroom: mucModel })
}
function _destroyChatRoomTaskLists (mucModel) {
@ -44,6 +45,7 @@ function _destroyChatRoomTaskLists (mucModel) {
// mucModel.tasklists.unload() FIXME: add a method to unregister from the pubsub, and empty the tasklist.
mucModel.tasklists = undefined
mucModel.tasks = undefined
}
export function initOrDestroyChatRoomTaskLists (mucModel) {