Skip to content

Commit 3e5414a

Browse files
committed
Add todo app
1 parent a352a32 commit 3e5414a

File tree

15 files changed

+173
-21
lines changed

15 files changed

+173
-21
lines changed

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import "./plugins/rosterview/index.js";
4242
import "./plugins/singleton/index.js";
4343
import "./plugins/dragresize/index.js"; // Allows chat boxes to be resized by dragging them
4444
import "./plugins/fullscreen/index.js";
45+
import "./plugins/todo/index.js";
4546
/* END: Removable components */
4647

4748
_converse.exports.CustomElement = CustomElement;

src/plugins/chatboxviews/index.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @license Mozilla Public License (MPLv2)
44
*/
55
import { html } from 'lit';
6-
import { _converse, api, converse } from '@converse/headless';
6+
import { _converse, api, constants, converse } from '@converse/headless';
77
import './view.js';
88
import ChatBoxViews from './container.js';
99
import { calculateViewportHeightUnit } from './utils.js';
@@ -32,18 +32,20 @@ converse.plugins.add('converse-chatboxviews', {
3232
class="converse-chatboxes row justify-content-start g-0 ${extra_classes.join(' ')}"
3333
></converse-chats>`;
3434
},
35+
renderControlbox: () => html`
36+
<converse-headlines-feeds-list class="controlbox-section"></converse-headlines-feeds-list>
37+
<div id="chatrooms" class="controlbox-section">
38+
<converse-rooms-list></converse-rooms-list>
39+
</div>
40+
${api.settings.get('authentication') === constants.ANONYMOUS
41+
? ''
42+
: html`<div id="converse-roster" class="controlbox-section">
43+
<converse-roster />
44+
</div>`}
45+
`,
3546
active: true,
3647
});
3748

38-
// TODO: move to own plugin
39-
api.apps.add({
40-
name: 'todo',
41-
render: () => {
42-
return html`<p>hello world: todo</p>`;
43-
},
44-
active: false,
45-
});
46-
4749
// TODO: move to own plugin
4850
api.apps.add({
4951
name: 'timetracker',

src/plugins/controlbox/templates/controlbox.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { html, nothing } from 'lit';
2-
import { _converse, api, converse, constants } from '@converse/headless';
2+
import { _converse, api, converse } from '@converse/headless';
33
import { getChatStyle } from 'shared/chat/utils.js';
44

55
const { Strophe } = converse.env;
6-
const { ANONYMOUS } = constants;
76

87
/**
98
* @param {import('../controlbox').default} el
@@ -35,17 +34,12 @@ function whenNotConnected(el) {
3534
*/
3635
export default (el) => {
3736
const style = getChatStyle(el.model);
37+
const { renderControlbox } = api.apps.getActive();
3838
return html`<div class="flyout box-flyout" style="${style || nothing}">
3939
${api.settings.get('view_mode') === 'overlayed' ? html`<converse-dragresize></converse-dragresize>` : ''}
4040
${el.model.get('connected')
4141
? html`<converse-user-profile></converse-user-profile>
42-
<div class="controlbox-pane">
43-
<converse-headlines-feeds-list class="controlbox-section"></converse-headlines-feeds-list>
44-
<div id="chatrooms" class="controlbox-section"><converse-rooms-list></converse-rooms-list></div>
45-
${api.settings.get('authentication') === ANONYMOUS
46-
? ''
47-
: html`<div id="converse-roster" class="controlbox-section"><converse-roster /></div>`}
48-
</div>`
42+
<div class="controlbox-pane">${renderControlbox()}</div>`
4943
: whenNotConnected(el)}
5044
</div>`;
5145
};

src/plugins/rootview/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { TemplateResult } from 'lit';
22

33
export type App = {
44
name: string;
5-
render: TemplateResult;
5+
render: () => TemplateResult;
6+
renderControlbox?: () => TemplateResult;
67
active: boolean;
78
};

src/plugins/todo/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import './view.js';
2+
import './lists.js';
3+
import './plugin.js';

src/plugins/todo/lists.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Model } from '@converse/skeletor';
2+
import { _converse, api, constants, u } from '@converse/headless';
3+
import { __ } from 'i18n';
4+
import { CustomElement } from 'shared/components/element.js';
5+
import tplTodoProjects from './templates/lists.js';
6+
7+
const { initStorage } = u;
8+
9+
export default class TodoLists extends CustomElement {
10+
render() {
11+
const bare_jid = _converse.session.get('bare_jid');
12+
const id = `converse.todo-lists-${bare_jid}`;
13+
this.model = new Model({ id });
14+
initStorage(this.model, id);
15+
this.model.fetch();
16+
17+
return tplTodoProjects(this);
18+
}
19+
20+
/** @param {Event} [ev] */
21+
toggleList(ev) {
22+
ev?.preventDefault?.();
23+
const list_el = this.querySelector('.open-rooms-list');
24+
if (this.model.get('toggle_state') === constants.CLOSED) {
25+
u.slideOut(list_el).then(() => this.model.save({ toggle_state: constants.OPENED }));
26+
} else {
27+
u.slideIn(list_el).then(() => this.model.save({ toggle_state: constants.CLOSED }));
28+
}
29+
}
30+
31+
getProjects() {
32+
return [];
33+
}
34+
}
35+
36+
api.elements.define('converse-todo-lists', TodoLists);

src/plugins/todo/plugin.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { html } from 'lit';
2+
import { _converse, api, converse } from '@converse/headless';
3+
4+
converse.plugins.add('converse-app-todo', {
5+
initialize() {
6+
api.apps.add({
7+
name: 'todo',
8+
render: () => {
9+
return html`<converse-app-todo></converse-app-todo>`;
10+
},
11+
renderControlbox: () => {
12+
return html`<converse-todo-lists></converse-todo-lists>`;
13+
},
14+
active: false,
15+
});
16+
},
17+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { html } from 'lit';
2+
import { constants } from '@converse/headless';
3+
import { __ } from 'i18n';
4+
5+
/**
6+
* @param {import('../lists.js').default} el
7+
*/
8+
export default (el) => {
9+
const projects = el.getProjects();
10+
const i18n_desc_rooms = __('Click to toggle the list of open projects');
11+
const i18n_heading_projects = __('PROJECTS');
12+
const is_closed = el.model.get('toggle_state') === constants.CLOSED;
13+
14+
const btns = [];
15+
16+
return html`<div class="d-flex controlbox-padded">
17+
<span class="w-100 controlbox-heading controlbox-heading--groupchats">
18+
<a
19+
class="list-toggle open-rooms-toggle"
20+
role="heading"
21+
aria-level="3"
22+
title="${i18n_desc_rooms}"
23+
@click=${(ev) => el.toggleList(ev)}
24+
>
25+
${i18n_heading_projects}
26+
${projects.length
27+
? html`<converse-icon
28+
class="fa ${is_closed ? 'fa-caret-right' : 'fa-caret-down'}"
29+
size="1em"
30+
color="var(--muc-color)"
31+
></converse-icon>`
32+
: ''}
33+
</a>
34+
</span>
35+
<converse-dropdown class="btn-group dropstart" .items=${btns}></converse-dropdown>
36+
</div>
37+
38+
<div class="list-container list-container--openrooms ${projects.length ? '' : 'hidden'}">
39+
<ul class="items-list rooms-list open-rooms-list ${is_closed ? 'collapsed' : ''}">
40+
${projects.map(() => html`<p>Here comes a project</p>`)}
41+
</ul>
42+
</div>`;
43+
};

src/plugins/todo/templates/todo.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { html, nothing } from 'lit';
2+
import { _converse, api, constants } from '@converse/headless';
3+
import { isMobileViewport } from 'shared/chat/utils';
4+
5+
const { CONTROLBOX_TYPE, CONNECTION_STATUS } = constants;
6+
7+
export default () => {
8+
const { chatboxes, connfeedback } = _converse.state;
9+
const view_mode = api.settings.get('view_mode');
10+
const is_overlayed = view_mode === 'overlayed';
11+
const is_mobile = isMobileViewport();
12+
const connection = api.connection.get();
13+
const logged_out = !connection?.connected || !connection?.authenticated || connection?.disconnecting;
14+
const connection_status = connfeedback.get('connection_status');
15+
const controlbox = chatboxes.find((m) => m.get('type') === CONTROLBOX_TYPE);
16+
const width = controlbox.get('width');
17+
const style = !is_mobile && is_overlayed && width ? `width: ${width}px` : nothing;
18+
const connecting = ['CONNECTED', 'CONNECTING', 'AUTHENTICATING', 'RECONNECTING'].includes(
19+
CONNECTION_STATUS[connection_status]
20+
);
21+
22+
return html`
23+
${!logged_out && is_overlayed
24+
? html`<converse-minimized-chats class="col-auto"></converse-minimized-chats>`
25+
: ''}
26+
${is_overlayed && controlbox.get('closed')
27+
? html`<converse-controlbox-toggle class="col-auto"></converse-controlbox-toggle>`
28+
: html`<converse-controlbox
29+
id="controlbox"
30+
class="col-auto chatbox ${logged_out && !connecting ? 'logged-out' : ''}"
31+
style="${style}"
32+
></converse-controlbox>`}
33+
`;
34+
};

src/plugins/todo/view.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { CustomElement } from 'shared/components/element.js';
2+
import { api } from '@converse/headless';
3+
import tplTodo from './templates/todo.js';
4+
5+
class TodoApp extends CustomElement {
6+
render() {
7+
return tplTodo();
8+
}
9+
}
10+
11+
api.elements.define('converse-app-todo', TodoApp);

0 commit comments

Comments
 (0)