diff --git a/webui-src/app/mail/mail.css b/webui-src/app/mail/mail.css new file mode 100644 index 0000000..72e993e --- /dev/null +++ b/webui-src/app/mail/mail.css @@ -0,0 +1,42 @@ +table.mails th { +} +/* star */ +table.mails th:nth-child(1) { + width: 5%; +} +/* attachments */ +table.mails th:nth-child(2) { + width: 5%; +} +/* subject */ +table.mails th:nth-child(3) { + width: 50%; + text-align: start; +} +/* date */ +table.mails th:nth-child(4) { + width: 40%; + text-align: start; +} + +/* subject */ +table.mails td:nth-child(3) { + text-align: start; + /* Truncate text with '...' */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +/* date */ +table.mails td:nth-child(4) { + text-align: start; +} + +table.mails tr.unread { + color: black; + background-color: #eef3f6; +} + +iframe.msg { + border: 0; +} diff --git a/webui-src/app/mail/mail_inbox.js b/webui-src/app/mail/mail_inbox.js index 2418081..f7808bd 100644 --- a/webui-src/app/mail/mail_inbox.js +++ b/webui-src/app/mail/mail_inbox.js @@ -5,15 +5,17 @@ const util = require('mail_util'); const Layout = () => { return { - view: (vnode) => [ - m('.widget', m('table', [ - m('thead', m('tr', [ - m('th'), - ])), - m('tbody', [ - m('tr') - ]), - ])), + oninit: (v) => {}, + view: (v) => [ + m('.widget', [ + m('h3', 'Inbox'), + m('hr'), + m(util.Table, m('tbody', v.attrs.list.map( + (msg) => m(util.MessageSummary, { + details: msg, + }) + ))), + ]), ] }; }; diff --git a/webui-src/app/mail/mail_resolver.js b/webui-src/app/mail/mail_resolver.js index 59323c6..2562a8d 100644 --- a/webui-src/app/mail/mail_resolver.js +++ b/webui-src/app/mail/mail_resolver.js @@ -1,7 +1,35 @@ let m = require('mithril'); let rs = require('rswebui'); +let util = require('mail_util'); +const Messages = { + all: [], + inbox: [], + sentbox: [], + outbox: [], + draftbox: [], + load() { + rs.rsJsonApiRequest('/rsMsgs/getMessageSummaries', {}, + (data) => { + Messages.all = data.msgList + // RS_MSG_BOXMASK = 0x000f + // RS_MSG_INBOX + Messages.inbox = Messages.all.filter( + (msg) => (msg.msgflags & 0x000f) === 0); + // RS_MSG_SENTBOX + Messages.sentbox = Messages.all.filter( + (msg) => (msg.msgflags & 0x000f) === 1); + // RS_MSG_OUTBOX + Messages.outbox = Messages.all.filter( + (msg) => (msg.msgflags & 0x000f) === 3); + // RS_MSG_DRAFTBOX + Messages.draftbox = Messages.all.filter( + (msg) => (msg.msgflags & 0x000f) === 5); + }); + }, +} + let sections = { inbox: require('mail_inbox'), outbox: require('mail_outbox'), @@ -9,11 +37,10 @@ let sections = { const sidebar = () => { let active = 0; - const tabs = Object.keys(sections); return { - view: () => m('.sidebar', - tabs.map((panelName, index) => m('a', { - href: '/mail/' + panelName, + view: (v) => m('.sidebar', + v.attrs.tabs.map((panelName, index) => m('a', { + href: v.attrs.baseRoute + panelName, oncreate: m.route.link, class: index === active ? 'selected-sidebar-link' : '', @@ -27,16 +54,28 @@ const sidebar = () => { }; const Layout = { + oninit: Messages.load, view: vnode => m('.tab-page', [ - m(sidebar), + m(sidebar, { + tabs: Object.keys(sections), + baseRoute: '/mail/', + }), m('.node-panel', vnode.children), ]) }; module.exports = { - view: (vnode) => { - const tab = vnode.attrs.tab; - return m(Layout, m(sections[tab])); + view: (v) => { + const tab = v.attrs.tab; + // TODO: utilize multiple routing params + if(tab.startsWith('id=')) { + return m(Layout, m(util.MessageView, { + id: v.attrs.tab.slice(3) + })) + } + return m(Layout, m(sections[tab], { + list: Messages[tab], + })); }, }; diff --git a/webui-src/app/mail/mail_util.js b/webui-src/app/mail/mail_util.js index 0a7da50..81df861 100644 --- a/webui-src/app/mail/mail_util.js +++ b/webui-src/app/mail/mail_util.js @@ -1,4 +1,72 @@ const m = require('mithril'); const rs = require('rswebui'); +const people = require('people_util'); + + +const MessageSummary = () => { + let details = {}; + let files = []; + return { + oninit: (v) => rs.rsJsonApiRequest('/rsMsgs/getMessage', { + msgId: v.attrs.details.msgId, + }, (data) => { + details = data.msg; + files = details.files; + }), + view: (v) => m('tr.msgbody', { + key: details.msgId, + class: (details.msgflags & 0xf0) === 0x40 ? 'unread' : 'read', + onclick: () => m.route.set('/mail/id=' + v.attrs.details.msgId), + }, [ + // TODO: custom checkbox tag + m('td', m('i.fas.fa-star', { + class: (details.msgflags & 0xf00) === 0x200 ? 'starred' : 'unstarred' + })), + m('td', files.length), + m('td', details.title), + //m('td', details.rspeerid_srcId == 0 ? + // '[Notification]' : + // people.getInfo(details.rspeerid_srcId)), + m('td', new Date(details.ts * 1000).toLocaleString()), + ]), + }; +}; + +const MessageView = () => { + let details = {}; + return { + oninit: (v) => rs.rsJsonApiRequest('/rsMsgs/getMessage', { + msgId: v.attrs.id, + }, (data) => details = data.msg), + view: (v) => m('.widget.msgview', { + key: details.msgId, + }, [ + m('h3', details.title), + m('hr'), + m('p', m('iframe[width=100%][height=100%].msg', {src: 'data:text/html;charset=utf-8,'+details.msg})), + ]), + }; +}; + +const Table = () => { + return { + oninit: (v) => {}, + view: (v) => m('table.mails', [ + m('tr', [ + m('th', m('i.fas.fa-star')), + m('th', m('i.fas.fa-paperclip')), + m('th', 'Subject'), + //m('th', 'From'), + m('th', 'Date'), + ]), + v.children, + ]), + }; +}; + +module.exports = { + MessageSummary, + MessageView, + Table, +}; -module.exports = {}; diff --git a/webui-src/app/people/people_util.js b/webui-src/app/people/people_util.js new file mode 100644 index 0000000..ab16ea2 --- /dev/null +++ b/webui-src/app/people/people_util.js @@ -0,0 +1,25 @@ +let m = require('mithril'); +let rs = require('rswebui'); + + +function getInfo(id) { + let name = ''; + let imageURI = ''; + rs.rsJsonApiRequest('/rsIdentity/getIdentitiesInfo', { + id + }, function(data) { + console.log('data: ', data.idsInfo); + //name = data.details.mNickname + //imageURI = data.details.mAvatar.mData; + }); + //return m('.profile-detail', [ + //m('img[src=data:image/png;base64,' + imageURI + ']'), + // name//, + //]); + return 'name'; +} + +module.exports = { + getInfo +}; +