diff --git a/webui-src/app/boards/board.css b/webui-src/app/boards/board.css index 7977a29..a5ed606 100644 --- a/webui-src/app/boards/board.css +++ b/webui-src/app/boards/board.css @@ -1,9 +1,9 @@ .board-node-panel { - position: relative; - bottom: 200px; - margin-left: 200px; - animation: fadein 0.5s; - } + position: relative; + bottom: 200px; + margin-left: 200px; + animation: fadein 0.5s; +} /* subject */ table.boards th:nth-child(1) { @@ -28,7 +28,7 @@ table.boards tr.hidden{ display: none; } -#searchboard{ +#searchboard { position:relative; margin-left: 250px; } @@ -39,15 +39,16 @@ img.boardpic { width:150px; padding: 25px; } -#boarddetails{ +#boarddetails { position: relative; margin-left: 150px; + padding: 10px; } .p{ margin:0; } -#toggleunsub{ +#toggleunsub { position: relative; background: gray; } @@ -60,22 +61,23 @@ img.boardpic { .card { width: 150px; - height: 150px; + height: 200px; border: 2px solid gray; cursor: pointer; text-align: center; } -.card-img{ +.card-img { width: 120px; height: 120px; } -.card-title{ - position: absolute; +.card-title { + position: relative; bottom: 0px; + overflow: auto; } /* subject */ -table.comments th{ +table.comments th { height: 40px; } table.comments th:nth-child(1) { @@ -89,14 +91,29 @@ table.comments td:nth-child(1){ border-radius: 25px; } -table.comments tr{ +table.comments tr { height: 40px; } -#options{ +#options { width: 100px; text-align: center; font-size: medium; margin-left: 20px; height: 40px; +} + +#composepopup { + height: 80%; + width: 70%; + bottom: 50%; + right: 58%; +} + +#mtags { + width: 160px; + text-align: center; + font-size: medium; + margin-left: 10px; + height: 40px; } \ No newline at end of file diff --git a/webui-src/app/boards/board_view.js b/webui-src/app/boards/board_view.js index d723b1e..e0ccbf8 100644 --- a/webui-src/app/boards/board_view.js +++ b/webui-src/app/boards/board_view.js @@ -4,6 +4,159 @@ const util = require('boards/boards_util'); const Data = util.Data; const peopleUtil = require('people/people_util'); +const messageGroups = ['Public', 'Restricted Circle', 'Restricted Node Group']; +const messageGroupsCode = [util.PUBLIC, util.EXTERNAL, util.NODES_GROUP]; //rsgxscirles.h:50 + +function createboard() { + let title; + let body; + let identity; + let thumbnail; + let selectedGroup = messageGroups[0]; + let selectedGroupCode = messageGroupsCode[0]; + let selectedCircle; + let circles; + return { + oninit: async (vnode) => { + if (vnode.attrs.authorId) { + identity = vnode.attrs.authorId[0]; + } + + const res = await rs.rsJsonApiRequest('/rsgxscircles/getCirclesSummaries'); + if (res.body.retval) { + circles = res.body.circles; + selectedCircle = circles[0].mGroupName; + } + }, + view: (vnode) => + m('.widget', [ + m('h3', 'Create Board'), + m('hr'), + m('input[type=text][placeholder=Title]', { + style: { float: 'left' }, + oninput: (e) => (title = e.target.value), + }), + m('div', { style: { float: 'right', marginTop: '10px', marginBottom: '10px' } }, [ + m('label[for=thumbnail]', 'Thumbnail: '), + m('input[type=file][name=files][id=thumbnail][accept=image/*]', { + onchange: async (e) => { + let reader = new FileReader(); + reader.onloadend = function () { + thumbnail = reader.result.substring(reader.result.indexOf(',') + 1); + }; + reader.readAsDataURL(e.target.files[0]); + }, + }), + ]), + + m('div', { style: { float: 'right', marginTop: '10px', marginBottom: '10px' } }, [ + m('label[for=idtags]', 'Select identity: '), + m( + 'select[id=idtags]', + { + value: identity, + onchange: (e) => { + identity = vnode.attrs.authorId[e.target.selectedIndex]; + }, + }, + [ + vnode.attrs.authorId && + vnode.attrs.authorId.map((o) => + m( + 'option', + { value: o }, + rs.userList.userMap[o] + ? rs.userList.userMap[o].toLocaleString() + : 'No Signature' + ) + ), + ] + ), + ]), + m('div', { style: { float: 'left', marginTop: '10px', marginBottom: '10px' } }, [ + m('label[for=mtags]', 'Message Distribution: '), + m( + 'select[id=mtags]', + { + value: selectedGroup, + onchange: (e) => { + selectedGroup = messageGroups[e.target.selectedIndex]; + selectedGroupCode = messageGroupsCode[e.target.selectedIndex]; + util.popupmessage(m(createboard, { authorId: vnode.attrs.authorId })); + }, + }, + [messageGroups.map((group) => m('option', { value: group }, group))] + ), + ]), + circles && + m( + 'div', + { + style: { + float: 'left', + marginTop: '10px', + marginBottom: '10px', + display: selectedGroupCode === util.EXTERNAL ? 'block' : 'none', + }, + }, + [ + m('label[for=circlestag]', 'Circles: '), + m( + 'select[id=circlestag]', + { + value: selectedCircle, + onchange: (e) => { + selectedCircle = circles[e.target.selectedIndex]; + console.log(selectedCircle); + // selectedGroupCode = messageGroupsCode[e.target.selectedIndex]; + }, + }, + [ + circles.map((circle) => + m('option', { value: circle.mGroupName }, circle.mGroupName) + ), + ] + ), + ] + ), + m('textarea[rows=5][placeholder=Description]', { + style: { width: '100%', display: 'block' }, + oninput: (e) => (body = e.target.value), + value: body, + }), + m( + 'button', + { + onclick: async () => { + const res = await rs.rsJsonApiRequest('/rsposted/createBoardV2', { + name: title, + description: body, + thumbnail: { mData: { base64: thumbnail } }, + ...(Number(identity) !== 0 && { authorId: identity }), + circleType: selectedGroupCode, + ...(selectedGroupCode === util.EXTERNAL && + selectedCircle && { circleId: selectedCircle.mGroupId }), + }); + if (res.body.retval) { + util.updatedisplayboards(res.body.boardId); + m.redraw(); + } + res.body.retval === false + ? util.popupmessage([m('h3', 'Error'), m('hr'), m('p', res.body.errorMessage)]) + : util.popupmessage([ + m('h3', 'Success'), + m('hr'), + m('p', 'Board created successfully'), + ]); + }, + }, + 'Create' + ), + ]), + }; +} + + const BoardView = () => { let bname = ''; let bimage = ''; @@ -139,4 +292,5 @@ const BoardView = () => { module.exports = { BoardView, + createboard, }; diff --git a/webui-src/app/boards/boards.js b/webui-src/app/boards/boards.js index add63a1..8ec4464 100644 --- a/webui-src/app/boards/boards.js +++ b/webui-src/app/boards/boards.js @@ -3,6 +3,7 @@ const widget = require('widgets'); const rs = require('rswebui'); const util = require('boards/boards_util'); const viewUtil = require('boards/board_view'); +const peopleUtil = require('people/people_util'); const getBoards = { @@ -10,11 +11,15 @@ const getBoards = PopularBoards : [], SubscribedBoards : [], MyBoards : [], + OtherBoards : [], async load(){ const res = await rs.rsJsonApiRequest('/rsPosted/getBoardsSummaries'); const data = res.body; getBoards.All = data.groupInfo; getBoards.PopularBoards = getBoards.All; + getBoards.PopularBoards.sort((a, b) => b.mPop - a.mPop); + getBoards.OtherBoards = getBoards.PopularBoards.slice(5); + getBoards.PopularBoards = getBoards.PopularBoards.slice(0, 5); getBoards.SubscribedBoards = getBoards.All.filter( (board) => board.mSubscribeFlags === util.GROUP_SUBSCRIBE_SUBSCRIBED @@ -32,43 +37,62 @@ const sections = { OtherBoards: require('boards/other_boards') }; -const Layout = { - oninit : () => { - rs.setBackgroundTask(getBoards.load, 5000, () => { - }); - }, - // onupdate: getBoards.load, - view: (vnode) => - m('.tab-page', [ - Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') - ? '' - : Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') - ? m(util.SearchBar, { - category: 'posts', - boardId: vnode.attrs.pathInfo.mGroupId - }) - : m(util.SearchBar, { - category: 'boards' - }), - m(widget.Sidebar, { - tabs: Object.keys(sections), - baseRoute: '/boards/', - }), - m('.board-node-panel', - Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') - ? m(viewUtil.PostView, { - msgId: vnode.attrs.pathInfo.mMsgId, - boardId: vnode.attrs.pathInfo.mGroupId, - }) - : Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') - ? m(viewUtil.BoardView, { - id: vnode.attrs.pathInfo.mGroupId, - }) - : m(sections[vnode.attrs.pathInfo.tab], { - list: getBoards[vnode.attrs.pathInfo.tab], - }) - ), - ]), +const Layout = () => { + let ownId; + + return { + oninit: () => { + rs.setBackgroundTask(getBoards.load, 5000, () => { + // return m.route.get() === '/files/files'; + }); + peopleUtil.ownIds((data) => { + ownId = data; + for (let i = 0; i < ownId.length; i++) { + if (Number(ownId[i]) === 0) { + ownId.splice(i, 1); + } + } + ownId.unshift(0); + }); + }, + view: (vnode) => + m('.tab-page', [ + m(util.SearchBar, { + list: getBoards.All, + }), + m( + 'button', + { + style: {fontSize: '1.2em', width: '200px'}, + onclick: () => + ownId && util.popupmessage( + m(viewUtil.createboard, { + authorId: ownId, + }) + ), + }, + 'Create Board' + ), + m(widget.Sidebar, { + tabs: Object.keys(sections), + baseRoute: '/boards/', + }), + m('.board-node-panel', + Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') + ? m(viewUtil.PostView, { + msgId: vnode.attrs.pathInfo.mMsgId, + forumId: vnode.attrs.pathInfo.mGroupId, + }) + : Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') + ? m(viewUtil.BoardView, { + id: vnode.attrs.pathInfo.mGroupId, + }) + : m(sections[vnode.attrs.pathInfo.tab], { + list: getBoards[vnode.attrs.pathInfo.tab], + }) + ), + ]), + }; }; module.exports = { diff --git a/webui-src/app/boards/boards_util.js b/webui-src/app/boards/boards_util.js index 956530f..15c72eb 100644 --- a/webui-src/app/boards/boards_util.js +++ b/webui-src/app/boards/boards_util.js @@ -9,10 +9,15 @@ const GROUP_MY_BOARD = GROUP_SUBSCRIBE_ADMIN + GROUP_SUBSCRIBE_SUBSCRIBED + GROU const GXS_VOTE_DOWN = 0x0001; const GXS_VOTE_UP = 0x0002; +//rsgxscircles.h:50 +const PUBLIC = 1; /// Public distribution +const EXTERNAL = 2; /// Restricted to an external circle, based on GxsIds +const NODES_GROUP = 3; + const Data = { - DisplayBoards: {}, - Posts: {}, - Comments: {}, + DisplayBoards: {}, // boardID -> board info + Posts: {}, // boardID, PostID -> {post, isSearched} + Comments: {}, // threadID, msgID -> {Comment, showReplies} }; async function updateContent(content, boardid) { @@ -122,6 +127,24 @@ const BoardTable = () => { }; }; +function popupmessage(message) { + const container = document.getElementById('modal-container'); + container.style.display = 'block'; + m.render( + container, + m('.modal-content[id=composepopup]', [ + m( + 'button.red', + { + onclick: () => (container.style.display = 'none'), + }, + m('i.fas.fa-times') + ), + message, + ]) + ); +} + const SearchBar = () => { let searchString = ''; return { @@ -145,6 +168,7 @@ const SearchBar = () => { module.exports = { Data, SearchBar, + popupmessage, BoardSummary, DisplayBoardsFromList, updateDisplayBoards, @@ -156,4 +180,7 @@ module.exports = { GROUP_MY_BOARD, GXS_VOTE_DOWN, GXS_VOTE_UP, + PUBLIC, + EXTERNAL, + NODES_GROUP, }; diff --git a/webui-src/app/boards/other_boards.js b/webui-src/app/boards/other_boards.js index 5c813d4..c5fc7dd 100644 --- a/webui-src/app/boards/other_boards.js +++ b/webui-src/app/boards/other_boards.js @@ -1,11 +1,32 @@ const m = require('mithril'); +const util = require('boards/boards_util'); const Layout = () => { - return{ - view: () => [ - m('.widget', [m('h2', 'Other Boards'), m('hr'), ]) - ] - }; + return { + view: (v) => [ + m('.widget', [ + m('h3', 'Other Boards'), + m('hr'), + m( + util.BoardTable, + m('tbody', [ + v.attrs.list.map((board) => + m(util.BoardSummary, { + details: board, + category: 'OtherBoards', + }) + ), + v.attrs.list.map((board) => + m(util.DisplayBoardsFromList, { + id: board.mGroupId, + category: 'OtherBoards', + }) + ), + ]) + ), + ]), + ], + }; }; module.exports = Layout();