diff --git a/package.json b/package.json
index 2219058..cddc8d8 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,9 @@
"eslint-import-resolver-webpack": "^0.3.2",
"eslint-plugin-babel": "^3.2.0",
"eslint-plugin-import": "^1.7.0",
+ "exports-loader": "^0.6.3",
"file-loader": "^0.9.0",
+ "imports-loader": "^0.6.5",
"jsdoc": "^3.4.0",
"ts-loader": "^0.8.2",
"typedoc": "^0.4.4",
@@ -63,7 +65,8 @@
"fullcalendar": "^2.9.0",
"intl": "^1.2.4",
"moment": "^2.14.1",
- "validator": "^5.2.0"
+ "validator": "^5.2.0",
+ "whatwg-fetch": "^1.0.0"
},
"nbbpm": {
"compatibility": "^1.0.3"
diff --git a/public/calendar.less b/public/calendar.less
index 476c398..70a071b 100644
--- a/public/calendar.less
+++ b/public/calendar.less
@@ -1 +1,9 @@
@import (inline) '../node_modules/fullcalendar/dist/fullcalendar.css';
+
+.fc-event {
+ cursor: pointer;
+}
+
+#plugin-calendar-cal-event-display .plugin-calendar-event {
+ margin: -15px;
+}
diff --git a/public/languages/en_US/calendar.json b/public/languages/en_US/calendar.json
index 337e835..d1f5490 100644
--- a/public/languages/en_US/calendar.json
+++ b/public/languages/en_US/calendar.json
@@ -6,6 +6,7 @@
"edit_event": "Edit Event",
"event_starting": "Event starting %1: %2",
"now": "now",
+ "go_to_post": "Go to post",
"event_name": "Event name",
"all_day": "All day",
diff --git a/public/templates/calendar.tpl b/public/templates/calendar.tpl
index 2be5d2e..076dc5c 100644
--- a/public/templates/calendar.tpl
+++ b/public/templates/calendar.tpl
@@ -1,6 +1,32 @@
-
[[calendar:calendar]]
-
-
+
+
+
diff --git a/src/calendar/index.js b/src/calendar/index.js
index fde8603..114acb2 100644
--- a/src/calendar/index.js
+++ b/src/calendar/index.js
@@ -1,9 +1,7 @@
-/* global socket, $, config, app */
+/* global socket, $, config, app, RELATIVE_PATH, fetch */
import './vendor/fullcalendar';
-// TODO: centralized calendar interface
-
const convertToFC = event => {
const ev = {
id: event.pid,
@@ -17,6 +15,14 @@ const convertToFC = event => {
return ev;
};
+const toggle = e => {
+ const panel = $(e.target).closest('.panel');
+ const cont = panel.find('.panel-collapse');
+ const height = cont.children()[0].scrollHeight;
+ cont.css('height', `${height}px`);
+ panel.toggleClass('closed');
+};
+
const calendarOptions = {
editable: false,
header: {
@@ -38,35 +44,74 @@ const calendarOptions = {
});
},
eventClick: event => {
- // TODO: show modal on event click
+ const pid = event.id;
+ fetch(`${RELATIVE_PATH}/api/post/${pid}`)
+ .then(response => response.json())
+ .then(path => fetch(`${RELATIVE_PATH}/api${path}`))
+ .then(response => response.json())
+ .then(topic => topic.posts.find(post => parseInt(post.pid, 10) === pid).content)
+ .then(content => {
+ const $c = $(content);
+ let div = $c.filter('.plugin-calendar-event');
+ if (!div.length) {
+ div = $c.find('.plugin-calendar-event');
+ }
+ return div;
+ })
+ .then(div => {
+ const modal = $('#plugin-calendar-cal-event-display');
+ modal
+ .find('.modal-body')
+ .empty()
+ .append(div);
+ modal
+ .find('.modal-footer a.btn-primary')
+ .attr('href', `${RELATIVE_PATH}/post/${pid}`);
+ modal
+ .find('.modal-body .plugin-calendar-event-responses-lists .panel-heading a')
+ .on('click', toggle);
+ modal
+ .find('.plugin-calendar-event-responses-lists .panel-body')
+ .addClass('topic')
+ .find('ul')
+ .addClass('posts');
+ $(window).trigger('action:calendar.event.display', { pid, modal });
+ modal
+ .attr('data-pid', pid)
+ .modal('show');
+ });
},
};
/* eslint-disable */
-function shadeColor2(color, percent) {
- var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
- return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
-}
+// function shadeColor2(color, percent) {
+// var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
+// return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
+// }
/* eslint-enable */
const init = () => {
- socket.emit('plugins.calendar.getCategoryColors', (err, colors) => {
- if (err) {
- app.alertError(err);
- return;
- }
- let style = '';
- $(document.head).append(style);
- });
+ // socket.emit('plugins.calendar.getCategoryColors', (err, colors) => {
+ // if (err) {
+ // app.alertError(err);
+ // return;
+ // }
+ // let style = '';
+ // $(document.head).append(style);
+ // });
$('#calendar').fullCalendar(calendarOptions);
+
+ $(window).on('action:ajaxify.end', () => {
+ // TODO: automatically go to and open event when pid is in hash of url
+ });
};
$(document).ready(init);
diff --git a/src/client/responses.js b/src/client/responses.js
index 1b9001a..911a1ea 100644
--- a/src/client/responses.js
+++ b/src/client/responses.js
@@ -77,7 +77,7 @@ const initResponses = () => {
$(document.body).on('click', '.plugin-calendar-event-responses-user .btn', e => {
const button = $(e.target);
const value = button.data('value');
- const pid = button.closest('[component=post]').data('pid');
+ const pid = button.closest('[data-pid]').data('pid');
socket.emit('plugins.calendar.submitResponse', { pid, value }, err => {
if (err) {
@@ -99,7 +99,46 @@ const initResponses = () => {
}
};
- $(window).on('action:posts.loaded action:ajaxify.end action:posts.edited', checkPosts);
+ $(window).on('action:calendar.event.display', (e, { pid, modal }) => {
+ const buttonCont = modal.find('.plugin-calendar-event-responses-user');
+ socket.emit('plugins.calendar.getUserResponse', pid, (err, value) => {
+ const button = buttonCont.find(`[data-value=${value}]`);
+
+ button.siblings().removeClass('active');
+ button.addClass('active');
+ });
+
+ const $responses = modal.find('.plugin-calendar-event-responses-lists');
+ socket.emit('plugins.calendar.getResponses', pid, (err, responses) => {
+ if (err) {
+ app.alertError(err);
+ return;
+ }
+ if (!responses ||
+ !responses.yes ||
+ !responses.maybe ||
+ !responses.no) {
+ return;
+ }
+
+ const yess = $responses.find('.plugin-calendar-event-responses-list-yes');
+ const maybes = $responses.find('.plugin-calendar-event-responses-list-maybe');
+ const nos = $responses.find('.plugin-calendar-event-responses-list-no');
+
+ const yes = responses.yes.map(userTemplate);
+ const maybe = responses.maybe.map(userTemplate);
+ const no = responses.no.map(userTemplate);
+
+ yess.empty().append(yes.length ? yes : noYesResponses);
+ maybes.empty().append(maybe.length ? maybe : noMaybeResponses);
+ nos.empty().append(no.length ? no : noNoResponses);
+ });
+ });
+
+ $(window).on(
+ 'action:posts.loaded action:ajaxify.end action:posts.edited',
+ checkPosts
+ );
checkPosts(null, ajaxify.data);
$(document.body).on(
diff --git a/src/lib/controllers.js b/src/lib/controllers.js
index b711547..2d00ef7 100644
--- a/src/lib/controllers.js
+++ b/src/lib/controllers.js
@@ -1,4 +1,19 @@
+const privileges = require.main.require('./src/privileges');
+const categories = require.main.require('./src/categories');
+
// import { getEventsByDate, filterByPid, escapeEvent } from './event';
+import Promise from 'bluebird';
+const p = Promise.promisify;
+
+const getAllCategoryFields = p(categories.getAllCategoryFields);
+const filterCids = p(privileges.categories.filterCids);
+
+/* eslint-disable */
+function shadeColor2(color, percent) {
+ var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
+ return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
+}
+/* eslint-enable */
export default (router, middleware) => {
const renderAdmin = (req, res) => {
@@ -7,14 +22,14 @@ export default (router, middleware) => {
router.get('/admin/plugins/calendar', middleware.admin.buildHeader, renderAdmin);
router.get('/api/admin/plugins/calendar', renderAdmin);
- const renderPage = (req, res) => { // next
- // const cb = (err, data) => {
- // if (err) {
- // next(err);
- // return;
- // }
- // res.render('calendar', data);
- // };
+ const renderPage = (req, res, next) => {
+ const cb = (err, data) => {
+ if (err) {
+ next(err);
+ return;
+ }
+ res.render('calendar', data);
+ };
//
// const startDate = new Date();
// const endDate = new Date();
@@ -35,8 +50,26 @@ export default (router, middleware) => {
// };
// })(req.uid).asCallback(cb);
+ (async () => {
+ const cats = await getAllCategoryFields(['cid', 'bgColor']);
+ const filtered = await filterCids('read', cats.map(c => c.cid), req.uid);
+
+ const colors = cats.filter(c => filtered.includes(c.cid));
+
+ const style = colors.map(({ cid, bgColor }) =>
+ `.plugin-calendar-cal-event-category-${cid} {
+ background-color: ${bgColor};
+ border-color: ${shadeColor2(bgColor, -0.2)};
+ }`
+ );
+
+ return {
+ calendarEventsStyle: style.join('\n'),
+ title: '[[calendar:calendar]]',
+ };
+ })().asCallback(cb);
- res.render('calendar', {});
+ // res.render('calendar', {});
};
router.get('/calendar', middleware.buildHeader, renderPage);
diff --git a/src/lib/sockets.js b/src/lib/sockets.js
index 7ba575f..4294103 100644
--- a/src/lib/sockets.js
+++ b/src/lib/sockets.js
@@ -1,15 +1,8 @@
const privileges = require.main.require('./src/privileges');
const pluginSockets = require.main.require('./src/socket.io/plugins');
-const categories = require.main.require('./src/categories');
import { getAll as getAllResponses, submitResponse, getUserResponse } from './responses';
import { getEventsByDate, filterByPid, escapeEvent } from './event';
-import Promise from 'bluebird';
-
-const p = Promise.promisify;
-
-const getAllCategoryFields = p(categories.getAllCategoryFields);
-const filterCids = p(privileges.categories.filterCids);
const perm = 'plugin-calendar:event:post';
@@ -46,12 +39,12 @@ pluginSockets.calendar.getUserResponse = ({ uid }, pid, cb) => {
getUserResponse({ uid, pid }).asCallback(cb);
};
-pluginSockets.calendar.getCategoryColors = ({ uid }, cb) => (async () => {
- const cats = await getAllCategoryFields(['cid', 'bgColor']);
- const filtered = await filterCids('read', cats.map(c => c.cid), uid);
-
- return cats.filter(c => filtered.includes(c.cid));
-})().asCallback(cb);
+// pluginSockets.calendar.getCategoryColors = ({ uid }, cb) => (async () => {
+// const cats = await getAllCategoryFields(['cid', 'bgColor']);
+// const filtered = await filterCids('read', cats.map(c => c.cid), uid);
+//
+// return cats.filter(c => filtered.includes(c.cid));
+// })().asCallback(cb);
pluginSockets.calendar.getEventsByDate = ({ uid }, { startDate, endDate }, cb) =>
(async () => {
diff --git a/ts/index.js b/ts/index.js
new file mode 100644
index 0000000..b770a7d
--- /dev/null
+++ b/ts/index.js
@@ -0,0 +1 @@
+// TODO: convert to TypeScript?
diff --git a/webpack.config.js b/webpack.config.js
index dc5e3c2..78c8b11 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,4 +1,4 @@
-// const webpack = require('webpack');
+const webpack = require('webpack');
const path = require('path');
const nodeEnv = process.env.NODE_ENV || 'development';
@@ -54,26 +54,29 @@ module.exports = {
path.resolve('./src/client/vendor'),
],
},
- // plugins: [
- // // new webpack.optimize.CommonsChunkPlugin({
- // // name: 'vendor',
- // // minChunks: Infinity,
- // // filename: 'vendor.bundle.js',
- // // }),
- // new webpack.LoaderOptionsPlugin({
- // minimize: isProd,
- // debug: !isProd,
- // }),
- // isProd && new webpack.optimize.UglifyJsPlugin({
- // compress: {
- // warnings: false,
- // },
- // output: {
- // comments: false,
- // },
- // sourceMap: false,
- // }),
- // ],
+ plugins: [
+ // new webpack.optimize.CommonsChunkPlugin({
+ // name: 'vendor',
+ // minChunks: Infinity,
+ // filename: 'vendor.bundle.js',
+ // }),
+ // new webpack.LoaderOptionsPlugin({
+ // minimize: isProd,
+ // debug: !isProd,
+ // }),
+ // isProd && new webpack.optimize.UglifyJsPlugin({
+ // compress: {
+ // warnings: false,
+ // },
+ // output: {
+ // comments: false,
+ // },
+ // sourceMap: false,
+ // }),
+ new webpack.ProvidePlugin({
+ fetch: 'imports?this=>global!exports?global.fetch!whatwg-fetch',
+ }),
+ ],
};
// console.log(module.exports);