aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/asset-manifest.json6
-rw-r--r--build/background.js356
-rw-r--r--build/index.html2
-rw-r--r--build/precache-manifest.9f3e92b5e4dff660087cc664d98afa28.js (renamed from build/precache-manifest.4b3348396592c5f2793c6b9bef079d99.js)42
-rw-r--r--build/service-worker.js2
-rw-r--r--build/static/js/main.0c8ec738.chunk.js2
-rw-r--r--build/static/js/main.0c8ec738.chunk.js.map1
-rw-r--r--build/static/js/main.9e0b7c77.chunk.js2
-rw-r--r--build/static/js/main.9e0b7c77.chunk.js.map1
-rw-r--r--package-lock.json589
-rw-r--r--package.json11
-rw-r--r--public/background.js3
-rw-r--r--scripts/build.js10
-rwxr-xr-xsrc/App.js115
-rw-r--r--src/PatternTable.js6
-rw-r--r--src/RegexField.js6
-rw-r--r--src/background.js58
-rw-r--r--src/gapi.js22
-rw-r--r--src/pattern.js4
19 files changed, 1139 insertions, 99 deletions
diff --git a/build/asset-manifest.json b/build/asset-manifest.json
index 4761af6..5bd4d82 100644
--- a/build/asset-manifest.json
+++ b/build/asset-manifest.json
@@ -1,6 +1,6 @@
{
- "main.js": "/static/js/main.0c8ec738.chunk.js",
- "main.js.map": "/static/js/main.0c8ec738.chunk.js.map",
+ "main.js": "/static/js/main.9e0b7c77.chunk.js",
+ "main.js.map": "/static/js/main.9e0b7c77.chunk.js.map",
"static/css/1.297ee474.chunk.css": "/static/css/1.297ee474.chunk.css",
"static/js/1.b5cbbf9b.chunk.js": "/static/js/1.b5cbbf9b.chunk.js",
"static/js/1.b5cbbf9b.chunk.js.map": "/static/js/1.b5cbbf9b.chunk.js.map",
@@ -9,6 +9,6 @@
"static/media/index.css": "/static/media/roboto-latin-900italic.bc833e72.woff",
"static/css/1.297ee474.chunk.css.map": "/static/css/1.297ee474.chunk.css.map",
"index.html": "/index.html",
- "precache-manifest.4b3348396592c5f2793c6b9bef079d99.js": "/precache-manifest.4b3348396592c5f2793c6b9bef079d99.js",
+ "precache-manifest.9f3e92b5e4dff660087cc664d98afa28.js": "/precache-manifest.9f3e92b5e4dff660087cc664d98afa28.js",
"service-worker.js": "/service-worker.js"
} \ No newline at end of file
diff --git a/build/background.js b/build/background.js
index 76043c6..ec5d6af 100644
--- a/build/background.js
+++ b/build/background.js
@@ -1,3 +1,355 @@
-chrome.browserAction.onClicked.addListener(function() {
- chrome.tabs.create({url: 'index.html'});
+(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+"use strict";
+
+var gapi = _interopRequireWildcard(require("./gapi"));
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+var patterns = [];
+var calendars = {};
+var calData = {};
+chrome.runtime.onConnect.addListener(function (port) {
+ console.assert(port.name == 'main');
+ port.onMessage.addListener(function (msg) {
+ console.log(msg);
+
+ if (msg.type == 0) {
+ patterns = msg.data;
+ } else if (msg.type == 1) {
+ port.postMessage({
+ id: msg.id,
+ type: 1,
+ data: patterns
+ });
+ } else if (msg.type == 2) {
+ calendars = msg.data;
+ } else if (msg.type == 3) {
+ port.postMessage({
+ id: msg.id,
+ type: 3,
+ data: calendars
+ });
+ } else if (msg.type == 4) {
+ calData[msg.data.id].getEvents(new Date(msg.data.start), new Date(msg.data.end)).catch(function (e) {
+ console.log("cannot load calendar ".concat(msg.data.id));
+ return [];
+ }).then(function (data) {
+ console.log(data);
+ var resp = {
+ id: msg.id,
+ type: 4,
+ data: data.map(function (e) {
+ return {
+ id: e.id,
+ start: e.start.getTime(),
+ end: e.end.getTime()
+ };
+ })
+ };
+ console.log(resp);
+ port.postMessage(resp);
+ });
+ } else if (msg.type == 5) {
+ calendars = msg.data;
+
+ for (var id in calendars) {
+ if (!calData.hasOwnProperty(id)) calData[id] = new gapi.GCalendar(id, calendars[id].summary);
+ }
+ } else {
+ console.error("unknown msg type");
+ }
+ });
});
+chrome.browserAction.onClicked.addListener(function () {
+ chrome.tabs.create({
+ url: 'index.html'
+ });
+});
+
+},{"./gapi":2}],2:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.getAuthToken = getAuthToken;
+exports.getCalendars = getCalendars;
+exports.getColors = getColors;
+exports.GCalendar = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+/* global chrome */
+var gapi_base = 'https://www.googleapis.com/calendar/v3';
+var GApiError = {
+ invalidSyncToken: 1,
+ otherError: 2
+};
+
+function to_params(dict) {
+ return Object.entries(dict).map(function (_ref) {
+ var _ref2 = _slicedToArray(_ref, 2),
+ k = _ref2[0],
+ v = _ref2[1];
+
+ return "".concat(encodeURIComponent(k), "=").concat(encodeURIComponent(v));
+ }).join('&');
+}
+
+function getAuthToken() {
+ return new Promise(function (resolver) {
+ return chrome.identity.getAuthToken({
+ interactive: true
+ }, function (token) {
+ return resolver(token);
+ });
+ });
+}
+
+function getCalendars(token) {
+ return fetch("".concat(gapi_base, "/users/me/calendarList?").concat(to_params({
+ access_token: token
+ })), {
+ method: 'GET',
+ async: true
+ }).then(function (response) {
+ return response.json();
+ }).then(function (data) {
+ return data.items;
+ });
+}
+
+function getColors(token) {
+ return fetch("".concat(gapi_base, "/colors?").concat(to_params({
+ access_token: token
+ })), {
+ method: 'GET',
+ async: true
+ }).then(function (response) {
+ return response.json();
+ });
+}
+
+function getEvent(calId, eventId, token) {
+ return fetch("".concat(gapi_base, "/calendars/").concat(calId, "/events/").concat(eventId, "?").concat(to_params({
+ access_token: token
+ })), {
+ method: 'GET',
+ async: true
+ }).then(function (response) {
+ return response.json();
+ });
+}
+
+function getEvents(calId, token, syncToken) {
+ var resultsPerRequest = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 100;
+ var results = [];
+
+ var singleFetch = function singleFetch(pageToken, syncToken) {
+ return fetch("".concat(gapi_base, "/calendars/").concat(calId, "/events?").concat(to_params({
+ access_token: token,
+ pageToken: pageToken,
+ syncToken: syncToken,
+ maxResults: resultsPerRequest
+ })), {
+ method: 'GET',
+ async: true
+ }).then(function (response) {
+ if (response.status === 200) return response.json();else if (response.status === 410) throw GApiError.invalidSyncToken;else throw GApiError.otherErrors;
+ }).then(function (data) {
+ results.push.apply(results, _toConsumableArray(data.items));
+
+ if (data.nextPageToken) {
+ return singleFetch(data.nextPageToken, '');
+ } else {
+ return {
+ nextSyncToken: data.nextSyncToken,
+ results: results
+ };
+ }
+ });
+ };
+
+ return singleFetch('', syncToken);
+}
+
+var GCalendar =
+/*#__PURE__*/
+function () {
+ function GCalendar(calId, name) {
+ _classCallCheck(this, GCalendar);
+
+ this.calId = calId;
+ this.name = name;
+ this.token = getAuthToken();
+ this.syncToken = '';
+ this.cache = {};
+ }
+
+ _createClass(GCalendar, [{
+ key: "getSlot",
+ value: function getSlot(k) {
+ if (!this.cache[k]) this.cache[k] = {};
+ return this.cache[k];
+ }
+ }, {
+ key: "addEvent",
+ value: function addEvent(e) {
+ var ks = GCalendar.dateToCacheKey(e.start);
+ var ke = GCalendar.dateToCacheKey(new Date(e.end.getTime() - 1));
+ if (ks === ke) this.getSlot(ks)[e.id] = {
+ start: e.start,
+ end: e.end,
+ id: e.id,
+ summary: e.summary
+ };else {
+ this.getSlot(ks)[e.id] = {
+ start: e.start,
+ end: GCalendar.slotEndDate(ks),
+ id: e.id,
+ summary: e.summary
+ };
+ this.getSlot(ke)[e.id] = {
+ start: GCalendar.slotStartDate(ke),
+ end: e.end,
+ id: e.id,
+ summary: e.summary
+ };
+
+ for (var k = ks + 1; k < ke; k++) {
+ this.getSlot(k)[e.id] = {
+ start: GCalendar.slotStartDate(k),
+ end: GCalendar.slotEndDate(k),
+ id: e.id,
+ summary: e.summary
+ };
+ }
+ }
+ }
+ }, {
+ key: "removeEvent",
+ value: function removeEvent(e) {
+ var ks = GCalendar.dateToCacheKey(e.start);
+ var ke = GCalendar.dateToCacheKey(new Date(e.end.getTime() - 1));
+
+ for (var k = ks; k <= ke; k++) {
+ delete this.getSlot(k)[e.id];
+ }
+ }
+ }, {
+ key: "getSlotEvents",
+ value: function getSlotEvents(k, start, end) {
+ var s = this.getSlot(k);
+ var results = [];
+
+ for (var id in s) {
+ if (!(s[id].start >= end || s[id].end <= start)) {
+ results.push({
+ id: id,
+ start: s[id].start < start ? start : s[id].start,
+ end: s[id].end > end ? end : s[id].end,
+ summary: s[id].summary
+ });
+ }
+ }
+
+ return results;
+ }
+ }, {
+ key: "getCachedEvents",
+ value: function getCachedEvents(start, end) {
+ var ks = GCalendar.dateToCacheKey(start);
+ var ke = GCalendar.dateToCacheKey(new Date(end.getTime() - 1));
+ var results = this.getSlotEvents(ks, start, end);
+
+ for (var k = ks + 1; k < ke; k++) {
+ var s = this.getSlot(k);
+
+ for (var id in s) {
+ results.push(s[id]);
+ }
+ }
+
+ if (ke > ks) results.push.apply(results, _toConsumableArray(this.getSlotEvents(ke, start, end)));
+ return results;
+ }
+ }, {
+ key: "sync",
+ value: function sync() {
+ var _this = this;
+
+ return this.token.then(function (token) {
+ return getEvents(_this.calId, token, _this.syncToken).then(function (r) {
+ _this.syncToken = r.nextSyncToken;
+ var pm_results = r.results.map(function (e) {
+ return e.start ? Promise.resolve(e) : getEvent(_this.calId, e.id, token);
+ });
+ return Promise.all(pm_results).then(function (results) {
+ return results.forEach(function (e) {
+ e.start = new Date(e.start.dateTime);
+ e.end = new Date(e.end.dateTime);
+ if (e.status === 'confirmed') _this.addEvent(e);else if (e.status === 'cancelled') _this.removeEvent(e);
+ });
+ });
+ });
+ }).catch(function (e) {
+ if (e === GApiError.invalidSyncToken) {
+ _this.syncToken = '';
+
+ _this.sync();
+ } else throw e;
+ });
+ }
+ }, {
+ key: "getEvents",
+ value: function getEvents(start, end) {
+ var _this2 = this;
+
+ return this.sync().then(function () {
+ return _this2.getCachedEvents(start, end);
+ });
+ }
+ }], [{
+ key: "dateToCacheKey",
+ value: function dateToCacheKey(date) {
+ return Math.floor(date / 8.64e7);
+ }
+ }, {
+ key: "slotStartDate",
+ value: function slotStartDate(k) {
+ return new Date(k * 8.64e7);
+ }
+ }, {
+ key: "slotEndDate",
+ value: function slotEndDate(k) {
+ return new Date((k + 1) * 8.64e7);
+ }
+ }]);
+
+ return GCalendar;
+}();
+
+exports.GCalendar = GCalendar;
+
+},{}]},{},[1])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvYmFja2dyb3VuZC5qcyIsInNyYy9nYXBpLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7QUNBQTs7OztBQUVBLElBQUksUUFBUSxHQUFHLEVBQWY7QUFDQSxJQUFJLFNBQVMsR0FBRyxFQUFoQjtBQUNBLElBQUksT0FBTyxHQUFHLEVBQWQ7QUFFQSxNQUFNLENBQUMsT0FBUCxDQUFlLFNBQWYsQ0FBeUIsV0FBekIsQ0FBcUMsVUFBUyxJQUFULEVBQWU7QUFDaEQsRUFBQSxPQUFPLENBQUMsTUFBUixDQUFlLElBQUksQ0FBQyxJQUFMLElBQWEsTUFBNUI7QUFDQSxFQUFBLElBQUksQ0FBQyxTQUFMLENBQWUsV0FBZixDQUEyQixVQUFTLEdBQVQsRUFBYztBQUNyQyxJQUFBLE9BQU8sQ0FBQyxHQUFSLENBQVksR0FBWjs7QUFDQSxRQUFJLEdBQUcsQ0FBQyxJQUFKLElBQVksQ0FBaEIsRUFBbUI7QUFDZixNQUFBLFFBQVEsR0FBRyxHQUFHLENBQUMsSUFBZjtBQUNILEtBRkQsTUFHSyxJQUFJLEdBQUcsQ0FBQyxJQUFKLElBQVksQ0FBaEIsRUFBbUI7QUFDcEIsTUFBQSxJQUFJLENBQUMsV0FBTCxDQUFpQjtBQUFFLFFBQUEsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFWO0FBQWMsUUFBQSxJQUFJLEVBQUUsQ0FBcEI7QUFBdUIsUUFBQSxJQUFJLEVBQUU7QUFBN0IsT0FBakI7QUFDSCxLQUZJLE1BR0EsSUFBSSxHQUFHLENBQUMsSUFBSixJQUFZLENBQWhCLEVBQW1CO0FBQ3BCLE1BQUEsU0FBUyxHQUFHLEdBQUcsQ0FBQyxJQUFoQjtBQUNILEtBRkksTUFHQSxJQUFJLEdBQUcsQ0FBQyxJQUFKLElBQVksQ0FBaEIsRUFBbUI7QUFDcEIsTUFBQSxJQUFJLENBQUMsV0FBTCxDQUFpQjtBQUFFLFFBQUEsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFWO0FBQWMsUUFBQSxJ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QUFDSDs7O2tDQVFvQixDLEVBQUc7QUFBRSxhQUFPLElBQUksSUFBSixDQUFTLENBQUMsR0FBRyxNQUFiLENBQVA7QUFBOEI7OztnQ0FDckMsQyxFQUFHO0FBQUUsYUFBTyxJQUFJLElBQUosQ0FBUyxDQUFDLENBQUMsR0FBRyxDQUFMLElBQVUsTUFBbkIsQ0FBUDtBQUFvQyIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsImltcG9ydCAqIGFzIGdhcGkgZnJvbSAnLi9nYXBpJztcblxubGV0IHBhdHRlcm5zID0gW107XG5sZXQgY2FsZW5kYXJzID0ge307XG5sZXQgY2FsRGF0YSA9IHt9O1xuXG5jaHJvbWUucnVudGltZS5vbkNvbm5lY3QuYWRkTGlzdGVuZXIoZnVuY3Rpb24ocG9ydCkge1xuICAgIGNvbnNvbGUuYXNzZXJ0KHBvcnQubmFtZSA9PSAnbWFpbicpO1xuICAgIHBvcnQub25NZXNzYWdlLmFkZExpc3RlbmVyKGZ1bmN0aW9uKG1zZykge1xuICAgICAgICBjb25zb2xlLmxvZyhtc2cpO1xuICAgICAgICBpZiAobXNnLnR5cGUgPT0gMCkge1xuICAgICAgICAgICAgcGF0dGVybnMgPSBtc2cuZGF0YTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChtc2cudHlwZSA9PSAxKSB7XG4gICAgICAgICAgICBwb3J0LnBvc3RNZXNzYWdlKHsgaWQ6IG1zZy5pZCwgdHlwZTogMSwgZGF0YTogcGF0dGVybnMgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobXNnLnR5cGUgPT0gMikge1xuICAgICAgICAgICAgY2FsZW5kYXJzID0gbXNnLmRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobXNnLnR5cGUgPT0gMykge1xuICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7IGlkOiBtc2cuaWQsIHR5cGU6IDMsIGRhdGE6IGNhbGVuZGFycyB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChtc2cudHlwZSA9PSA0KSB7XG4gICAgICAgICAgICBjYWxEYXRhW21zZy5kYXRhLmlkXS5nZXRFdmVudHMobmV3IERhdGUobXNnLmRhdGEuc3RhcnQpLCBuZXcgRGF0ZShtc2cuZGF0YS5lbmQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coYGNhbm5vdCBsb2FkIGNhbGVuZGFyICR7bXNnLmRhdGEuaWR9YCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC50aGVuKGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGRhdGEpO1xuICAgICAgICAgICAgICAgIGxldCByZXNwID0geyBpZDogbXNnLmlkLCB0eXBlOiA0LCBkYXRhOiBkYXRhLm1hcChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBlLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IGUuc3RhcnQuZ2V0VGltZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBlLmVuZC5nZXRUaW1lKClcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pfTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhyZXNwKTtcbiAgICAgICAgICAgICAgICBwb3J0LnBvc3RNZXNzYWdlKHJlc3ApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobXNnLnR5cGUgPT0gNSkge1xuICAgICAgICAgICAgY2FsZW5kYXJzID0gbXNnLmRhdGE7XG4gICAgICAgICAgICBmb3IgKGxldCBpZCBpbiBjYWxlbmRhcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNhbERhdGEuaGFzT3duUHJvcGVydHkoaWQpKVxuICAgICAgICAgICAgICAgICAgICBjYWxEYXRhW2lkXSA9IG5ldyBnYXBpLkdDYWxlbmRhcihpZCwgY2FsZW5kYXJzW2lkXS5zdW1tYXJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJ1bmtub3duIG1zZyB0eXBlXCIpO1xuICAgICAgICB9XG4gICAgfSk7XG59KTtcblxuY2hyb21lLmJyb3dzZXJBY3Rpb24ub25DbGlja2VkLmFkZExpc3RlbmVyKGZ1bmN0aW9uKCkge1xuICAgIGNocm9tZS50YWJzLmNyZWF0ZSh7dXJsOiAnaW5kZXguaHRtbCd9KTtcbn0pO1xuXG4iLCIvKiBnbG9iYWwgY2hyb21lICovXG5jb25zdCBnYXBpX2Jhc2UgPSAnaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vY2FsZW5kYXIvdjMnO1xuXG5jb25zdCBHQXBpRXJyb3IgPSB7XG4gICAgaW52YWxpZFN5bmNUb2tlbjogMSxcbiAgICBvdGhlckVycm9yOiAyLFxufTtcblxuZnVuY3Rpb24gdG9fcGFyYW1zKGRpY3QpIHtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMoZGljdCkubWFwKChbaywgdl0pID0+IGAke2VuY29kZVVSSUNvbXBvbmVudChrKX09JHtlbmNvZGVVUklDb21wb25lbnQodil9YCkuam9pbignJicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QXV0aFRva2VuKCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlciA9PlxuICAgICAgICBjaHJvbWUuaWRlbnRpdHkuZ2V0QXV0aFRva2VuKFxuICAgICAgICAgICAge2ludGVyYWN0aXZlOiB0cnVlfSwgdG9rZW4gPT4gcmVzb2x2ZXIodG9rZW4pKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDYWxlbmRhcnModG9rZW4pIHtcbiAgICByZXR1cm4gZmV0Y2goYCR7Z2FwaV9iYXNlfS91c2Vycy9tZS9jYWxlbmRhckxpc3Q/JHt0b19wYXJhbXMoe2FjY2Vzc190b2tlbjogdG9rZW59KX1gLFxuICAgICAgICAgICAgeyBtZXRob2Q6ICdHRVQnLCBhc3luYzogdHJ1ZSB9KVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiByZXNwb25zZS5qc29uKCkpXG4gICAgICAgIC50aGVuKGRhdGEgPT4gZGF0YS5pdGVtcyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb2xvcnModG9rZW4pIHtcbiAgICByZXR1cm4gZmV0Y2goYCR7Z2FwaV9iYXNlfS9jb2xvcnM/JHt0b19wYXJhbXMoe2FjY2Vzc190b2tlbjogdG9rZW59KX1gLFxuICAgICAgICB7IG1ldGhvZDogJ0dFVCcsIGFzeW5jOiB0cnVlIH0pXG4gICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHJlc3BvbnNlLmpzb24oKSk7XG59XG5cbmZ1bmN0aW9uIGdldEV2ZW50KGNhbElkLCBldmVudElkLCB0b2tlbikge1xuICAgIHJldHVybiBmZXRjaChgJHtnYXBpX2Jhc2V9L2NhbGVuZGFycy8ke2NhbElkfS9ldmVudHMvJHtldmVudElkfT8ke3RvX3BhcmFtcyh7YWNjZXNzX3Rva2VuOiB0b2tlbn0pfWAsXG4gICAgICAgIHsgbWV0aG9kOiAnR0VUJywgYXN5bmM6IHRydWUgfSlcbiAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4gcmVzcG9uc2UuanNvbigpKTtcbn1cblxuZnVuY3Rpb24gZ2V0RXZlbnRzKGNhbElkLCB0b2tlbiwgc3luY1Rva2VuLCByZXN1bHRzUGVyUmVxdWVzdD0xMDApIHtcbiAgICBsZXQgcmVzdWx0cyA9IFtdO1xuICAgIGNvbnN0IHNpbmdsZUZldGNoID0gKHBhZ2VUb2tlbiwgc3luY1Rva2VuKSA9PiBmZXRjaChgJHtnYXBpX2Jhc2V9L2NhbGVuZGFycy8ke2NhbElkfS9ldmVudHM/JHt0b19wYXJhbXMoe1xuICAgICAgICAgICAgYWNjZXNzX3Rva2VuOiB0b2tlbixcbiAgICAgICAgICAgIHBhZ2VUb2tlbixcbiAgICAgICAgICAgIHN5bmNUb2tlbixcbiAgICAgICAgICAgIG1heFJlc3VsdHM6IHJlc3VsdHNQZXJSZXF1ZXN0XG4gICAgICAgIH0pfWAsIHsgbWV0aG9kOiAnR0VUJywgYXN5bmM6IHRydWUgfSlcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAyMDApXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MTApXG4gICAgICAgICAgICAgICAgICAgIHRocm93IEdBcGlFcnJvci5pbnZhbGlkU3luY1Rva2VuO1xuICAgICAgICAgICAgICAgIGVsc2UgdGhyb3cgR0FwaUVycm9yLm90aGVyRXJyb3JzO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaCguLi5kYXRhLml0ZW1zKTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5uZXh0UGFnZVRva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzaW5nbGVGZXRjaChkYXRhLm5leHRQYWdlVG9rZW4sICcnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRTeW5jVG9rZW46IGRhdGEubmV4dFN5bmNUb2tlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHNcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcblxuICAgIHJldHVybiBzaW5nbGVGZXRjaCgnJywgc3luY1Rva2VuKTtcbn1cblxuZXhwb3J0IGNsYXNzIEdDYWxlbmRhciB7XG4gICAgY29uc3RydWN0b3IoY2FsSWQsIG5hbWUpIHtcbiAgICAgICAgdGhpcy5jYWxJZCA9IGNhbElkO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLnRva2VuID0gZ2V0QXV0aFRva2VuKCk7XG4gICAgICAgIHRoaXMuc3luY1Rva2VuID0gJyc7XG4gICAgICAgIHRoaXMuY2FjaGUgPSB7fTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZGF0ZVRvQ2FjaGVLZXkoZGF0ZSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihkYXRlIC8gOC42NGU3KTtcbiAgICB9XG5cbiAgICBnZXRTbG90KGspIHtcbiAgICAgICAgaWYgKCF0aGlzLmNhY2hlW2tdKVxuICAgICAgICAgICAgdGhpcy5jYWNoZVtrXSA9IHt9O1xuICAgICAgICByZXR1cm4gdGhpcy5jYWNoZVtrXTtcbiAgICB9XG5cbiAgICBzdGF0aWMgc2xvdFN0YXJ0RGF0ZShrKSB7IHJldHVybiBuZXcgRGF0ZShrICogOC42NGU3KTsgfVxuICAgIHN0YXRpYyBzbG90RW5kRGF0ZShrKSB7IHJldHVybiBuZXcgRGF0ZSgoayArIDEpICogOC42NGU3KTsgfVxuXG4gICAgYWRkRXZlbnQoZSkge1xuICAgICAgICBsZXQga3MgPSBHQ2FsZW5kYXIuZGF0ZVRvQ2FjaGVLZXkoZS5zdGFydCk7XG4gICAgICAgIGxldCBrZSA9IEdDYWxlbmRhci5kYXRlVG9DYWNoZUtleShuZXcgRGF0ZShlLmVuZC5nZXRUaW1lKCkgLSAxKSk7XG4gICAgICAgIGlmIChrcyA9PT0ga2UpXG4gICAgICAgICAgICB0aGlzLmdldFNsb3Qoa3MpW2UuaWRdID0ge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBlLnN0YXJ0LFxuICAgICAgICAgICAgICAgIGVuZDogZS5lbmQsXG4gICAgICAgICAgICAgICAgaWQ6IGUuaWQsXG4gICAgICAgICAgICAgICAgc3VtbWFyeTogZS5zdW1tYXJ5fTtcbiAgICAgICAgZWxzZVxuICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLmdldFNsb3Qoa3MpW2UuaWRdID0ge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBlLnN0YXJ0LFxuICAgICAgICAgICAgICAgIGVuZDogR0NhbGVuZGFyLnNsb3RFbmREYXRlKGtzKSxcbiAgICAgICAgICAgICAgICBpZDogZS5pZCxcbiAgICAgICAgICAgICAgICBzdW1tYXJ5OiBlLnN1bW1hcnl9O1xuICAgICAgICAgICAgdGhpcy5nZXRTbG90KGtlKVtlLmlkXSA9IHtcbiAgICAgICAgICAgICAgICBzdGFydDogR0NhbGVuZGFyLnNsb3RTdGFydERhdGUoa2UpLFxuICAgICAgICAgICAgICAgIGVuZDogZS5lbmQsXG4gICAgICAgICAgICAgICAgaWQ6IGUuaWQsXG4gICAgICAgICAgICAgICAgc3VtbWFyeTogZS5zdW1tYXJ5fTtcbiAgICAgICAgICAgIGZvciAobGV0IGsgPSBrcyArIDE7IGsgPCBrZTsgaysrKVxuICAgICAgICAgICAgICAgIHRoaXMuZ2V0U2xvdChrKVtlLmlkXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IEdDYWxlbmRhci5zbG90U3RhcnREYXRlKGspLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IEdDYWxlbmRhci5zbG90RW5kRGF0ZShrKSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6IGUuaWQsXG4gICAgICAgICAgICAgICAgICAgIHN1bW1hcnk6IGUuc3VtbWFyeX07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZW1vdmVFdmVudChlKSB7XG4gICAgICAgIGxldCBrcyA9IEdDYWxlbmRhci5kYXRlVG9DYWNoZUtleShlLnN0YXJ0KTtcbiAgICAgICAgbGV0IGtlID0gR0NhbGVuZGFyLmRhdGVUb0NhY2hlS2V5KG5ldyBEYXRlKGUuZW5kLmdldFRpbWUoKSAtIDEpKTtcbiAgICAgICAgZm9yIChsZXQgayA9IGtzOyBrIDw9IGtlOyBrKyspXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5nZXRTbG90KGspW2UuaWRdO1xuICAgIH1cblxuICAgIGdldFNsb3RFdmVudHMoaywgc3RhcnQsIGVuZCkge1xuICAgICAgICBsZXQgcyA9IHRoaXMuZ2V0U2xvdChrKTtcbiAgICAgICAgbGV0IHJlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaWQgaW4gcykge1xuICAgICAgICAgICAgaWYgKCEoc1tpZF0uc3RhcnQgPj0gZW5kIHx8IHNbaWRdLmVuZCA8PSBzdGFydCkpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBzW2lkXS5zdGFydCA8IHN0YXJ0ID8gc3RhcnQ6IHNbaWRdLnN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IHNbaWRdLmVuZCA+IGVuZCA/IGVuZDogc1tpZF0uZW5kLFxuICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5OiBzW2lkXS5zdW1tYXJ5XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgZ2V0Q2FjaGVkRXZlbnRzKHN0YXJ0LCBlbmQpIHtcbiAgICAgICAgbGV0IGtzID0gR0NhbGVuZGFyLmRhdGVUb0NhY2hlS2V5KHN0YXJ0KTtcbiAgICAgICAgbGV0IGtlID0gR0NhbGVuZGFyLmRhdGVUb0NhY2hlS2V5KG5ldyBEYXRlKGVuZC5nZXRUaW1lKCkgLSAxKSk7XG4gICAgICAgIGxldCByZXN1bHRzID0gdGhpcy5nZXRTbG90RXZlbnRzKGtzLCBzdGFydCwgZW5kKTtcbiAgICAgICAgZm9yIChsZXQgayA9IGtzICsgMTsgayA8IGtlOyBrKyspXG4gICAgICAgIHtcbiAgICAgICAgICAgIGxldCBzID0gdGhpcy5nZXRTbG90KGspO1xuICAgICAgICAgICAgZm9yIChsZXQgaWQgaW4gcylcbiAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goc1tpZF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZSA+IGtzKVxuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKC4uLnRoaXMuZ2V0U2xvdEV2ZW50cyhrZSwgc3RhcnQsIGVuZCkpO1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9XG5cbiAgICBzeW5jKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b2tlbi50aGVuKHRva2VuID0+IGdldEV2ZW50cyh0aGlzLmNhbElkLCB0b2tlbiwgdGhpcy5zeW5jVG9rZW4pLnRoZW4ociA9PiB7XG4gICAgICAgICAgICB0aGlzLnN5bmNUb2tlbiA9IHIubmV4dFN5bmNUb2tlbjtcbiAgICAgICAgICAgIGxldCBwbV9yZXN1bHRzID0gci5yZXN1bHRzLm1hcChlID0+IGUuc3RhcnQgPyBQcm9taXNlLnJlc29sdmUoZSkgOiBnZXRFdmVudCh0aGlzLmNhbElkLCBlLmlkLCB0b2tlbikpO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHBtX3Jlc3VsdHMpLnRoZW4ocmVzdWx0cyA9PiByZXN1bHRzLmZvckVhY2goZSA9PiB7XG4gICAgICAgICAgICAgICAgZS5zdGFydCA9IG5ldyBEYXRlKGUuc3RhcnQuZGF0ZVRpbWUpO1xuICAgICAgICAgICAgICAgIGUuZW5kID0gbmV3IERhdGUoZS5lbmQuZGF0ZVRpbWUpO1xuICAgICAgICAgICAgICAgIGlmIChlLnN0YXR1cyA9PT0gJ2NvbmZpcm1lZCcpXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRXZlbnQoZSk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS5zdGF0dXMgPT09ICdjYW5jZWxsZWQnKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50KGUpO1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9KSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICBpZiAoZSA9PT0gR0FwaUVycm9yLmludmFsaWRTeW5jVG9rZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN5bmNUb2tlbiA9ICcnO1xuICAgICAgICAgICAgICAgIHRoaXMuc3luYygpO1xuICAgICAgICAgICAgfSBlbHNlIHRocm93IGU7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGdldEV2ZW50cyhzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmMoKS50aGVuKCgpID0+IHRoaXMuZ2V0Q2FjaGVkRXZlbnRzKHN0YXJ0LCBlbmQpKTtcbiAgICB9XG59XG4iXX0=
diff --git a/build/index.html b/build/index.html
index 1880729..2edbc66 100644
--- a/build/index.html
+++ b/build/index.html
@@ -1 +1 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><link rel="stylesheet" href="/fonts/TypoPRO-FantasqueSansMono-Regular.css"/><title>Chromicle</title><link href="/static/css/1.297ee474.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={2:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/1.b5cbbf9b.chunk.js"></script><script src="/static/js/main.0c8ec738.chunk.js"></script></body></html> \ No newline at end of file
+<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><link rel="stylesheet" href="/fonts/TypoPRO-FantasqueSansMono-Regular.css"/><title>Chromicle</title><link href="/static/css/1.297ee474.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={2:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/1.b5cbbf9b.chunk.js"></script><script src="/static/js/main.9e0b7c77.chunk.js"></script></body></html> \ No newline at end of file
diff --git a/build/precache-manifest.4b3348396592c5f2793c6b9bef079d99.js b/build/precache-manifest.9f3e92b5e4dff660087cc664d98afa28.js
index 0c285f0..fc13304 100644
--- a/build/precache-manifest.4b3348396592c5f2793c6b9bef079d99.js
+++ b/build/precache-manifest.9f3e92b5e4dff660087cc664d98afa28.js
@@ -1,11 +1,11 @@
self.__precacheManifest = [
{
- "revision": "d8bcbe724fd6f4ba44d0ee6a2675890f",
- "url": "/static/media/roboto-latin-400italic.d8bcbe72.woff2"
+ "revision": "9680d5a0c32d2fd084e07bbc4c8b2923",
+ "url": "/static/media/roboto-latin-400italic.9680d5a0.woff"
},
{
- "revision": "0c8ec738cbc4afdfc52a",
- "url": "/static/js/main.0c8ec738.chunk.js"
+ "revision": "9e0b7c772ae44d9b0a03",
+ "url": "/static/js/main.9e0b7c77.chunk.js"
},
{
"revision": "bc833e725c137257c2c42a789845d82f",
@@ -28,16 +28,16 @@ self.__precacheManifest = [
"url": "/static/media/roboto-latin-100italic.d704bb3d.woff"
},
{
- "revision": "55536c8e9e9a532651e3cf374f290ea3",
- "url": "/static/media/roboto-latin-300.55536c8e.woff2"
+ "revision": "6232f43d15b0e7a0bf0fe82e295bdd06",
+ "url": "/static/media/roboto-latin-100italic.6232f43d.woff2"
},
{
"revision": "a1471d1d6431c893582a5f6a250db3f9",
"url": "/static/media/roboto-latin-300.a1471d1d.woff"
},
{
- "revision": "6232f43d15b0e7a0bf0fe82e295bdd06",
- "url": "/static/media/roboto-latin-100italic.6232f43d.woff2"
+ "revision": "55536c8e9e9a532651e3cf374f290ea3",
+ "url": "/static/media/roboto-latin-300.55536c8e.woff2"
},
{
"revision": "d69924b98acd849cdeba9fbff3f88ea6",
@@ -48,16 +48,20 @@ self.__precacheManifest = [
"url": "/static/media/roboto-latin-300italic.210a7c78.woff"
},
{
+ "revision": "5d4aeb4e5f5ef754e307d7ffaef688bd",
+ "url": "/static/media/roboto-latin-400.5d4aeb4e.woff2"
+ },
+ {
"revision": "bafb105baeb22d965c70fe52ba6b49d9",
"url": "/static/media/roboto-latin-400.bafb105b.woff"
},
{
- "revision": "9680d5a0c32d2fd084e07bbc4c8b2923",
- "url": "/static/media/roboto-latin-400italic.9680d5a0.woff"
+ "revision": "7b770d6c53423deb1a8e49d3c9175184",
+ "url": "/static/media/roboto-latin-900italic.7b770d6c.woff2"
},
{
- "revision": "8c2ade503b34e31430d6c98aa29a52a3",
- "url": "/static/media/roboto-latin-900.8c2ade50.woff"
+ "revision": "d8bcbe724fd6f4ba44d0ee6a2675890f",
+ "url": "/static/media/roboto-latin-400italic.d8bcbe72.woff2"
},
{
"revision": "285467176f7fe6bb6a9c6873b3dad2cc",
@@ -80,18 +84,14 @@ self.__precacheManifest = [
"url": "/static/media/roboto-latin-700.037d8304.woff2"
},
{
- "revision": "5d4aeb4e5f5ef754e307d7ffaef688bd",
- "url": "/static/media/roboto-latin-400.5d4aeb4e.woff2"
+ "revision": "cf6613d1adf490972c557a8e318e0868",
+ "url": "/static/media/roboto-latin-700.cf6613d1.woff"
},
{
"revision": "010c1aeee3c6d1cbb1d5761d80353823",
"url": "/static/media/roboto-latin-700italic.010c1aee.woff2"
},
{
- "revision": "cf6613d1adf490972c557a8e318e0868",
- "url": "/static/media/roboto-latin-700.cf6613d1.woff"
- },
- {
"revision": "846d1890aee87fde5d8ced8eba360c3a",
"url": "/static/media/roboto-latin-700italic.846d1890.woff"
},
@@ -100,8 +100,8 @@ self.__precacheManifest = [
"url": "/static/media/roboto-latin-900.19b7a0ad.woff2"
},
{
- "revision": "7b770d6c53423deb1a8e49d3c9175184",
- "url": "/static/media/roboto-latin-900italic.7b770d6c.woff2"
+ "revision": "8c2ade503b34e31430d6c98aa29a52a3",
+ "url": "/static/media/roboto-latin-900.8c2ade50.woff"
},
{
"revision": "b5cbbf9bff7bad31bf86",
@@ -112,7 +112,7 @@ self.__precacheManifest = [
"url": "/static/css/1.297ee474.chunk.css"
},
{
- "revision": "ae169eb6e1e22ab620835a8b332f1b63",
+ "revision": "aeb657f32a103bb2fa4e6ff7a484612c",
"url": "/index.html"
}
]; \ No newline at end of file
diff --git a/build/service-worker.js b/build/service-worker.js
index eee1ebb..7623ea8 100644
--- a/build/service-worker.js
+++ b/build/service-worker.js
@@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");
importScripts(
- "/precache-manifest.4b3348396592c5f2793c6b9bef079d99.js"
+ "/precache-manifest.9f3e92b5e4dff660087cc664d98afa28.js"
);
workbox.clientsClaim();
diff --git a/build/static/js/main.0c8ec738.chunk.js b/build/static/js/main.0c8ec738.chunk.js
deleted file mode 100644
index f55a1f0..0000000
--- a/build/static/js/main.0c8ec738.chunk.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(window.webpackJsonp=window.webpackJsonp||[]).push([[0],{308:function(e,t,a){e.exports=a(655)},655:function(e,t,a){"use strict";a.r(t);var n=a(1),r=a.n(n),c=a(28),o=a.n(c),i=a(137),l=a(101),s=a(39),u=a(45),h=a(78),d=a(74),m=a(79),p=(a(313),a(315),a(341),a(286)),f=a(31),v=a(99),g=a.n(v),y=a(306),E=a.n(y),w=a(305),b=a.n(w),P=a(173),x=a.n(P),k=a(81),S=a.n(k),T=a(177),C=a.n(T),D=a(93),O=a.n(D),j=a(103),R=a.n(j),N=a(40),B=a.n(N),G=a(307),I=a.n(G),W=a(174),K=a.n(W),A=function(e){return r.a.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 98.905998 93.557997",version:"1.1",style:e.style},r.a.createElement("g",{id:"g13",transform:"translate(-153.533,-203.047)"},r.a.createElement("g",{id:"g29"},r.a.createElement("g",{id:"g27"},r.a.createElement("polygon",{id:"polygon7",points:"252.439,241.924 234.556,288.703 185.103,296.605 153.533,257.728 171.416,210.949 220.869,203.047 ",style:{fill:"#ff8000"}}),r.a.createElement("g",{id:"g11",transform:"translate(167.24355,224.20734)"},r.a.createElement("text",{id:"text9",style:{fontStyle:"normal",fontVariant:"normal",fontWeight:"normal",fontStretch:"normal",fontSize:75,fontFamily:"TypoPRO Fantasque Sans Mono",fill:"#ffeade"},transform:"translate(0.586,49.072)"},"Cr"))))))},_="https://www.googleapis.com/calendar/v3",M={invalidSyncToken:1,otherError:2};function z(e){return Object.entries(e).map(function(e){var t=Object(i.a)(e,2),a=t[0],n=t[1];return"".concat(encodeURIComponent(a),"=").concat(encodeURIComponent(n))}).join("&")}function F(){return new Promise(function(e){return chrome.identity.getAuthToken({interactive:!0},function(t){return e(t)})})}function U(e){return fetch("".concat(_,"/users/me/calendarList?").concat(z({access_token:e})),{method:"GET",async:!0}).then(function(e){return e.json()}).then(function(e){return e.items})}function L(e){return fetch("".concat(_,"/colors?").concat(z({access_token:e})),{method:"GET",async:!0}).then(function(e){return e.json()})}var $=function(){function e(t,a){Object(s.a)(this,e),this.calId=t,this.name=a,this.token=F(),this.syncToken="",this.cache={}}return Object(u.a)(e,[{key:"getSlot",value:function(e){return this.cache[e]||(this.cache[e]={}),this.cache[e]}},{key:"addEvent",value:function(t){var a=e.dateToCacheKey(t.start),n=e.dateToCacheKey(new Date(t.end.getTime()-1));if(a===n)this.getSlot(a)[t.id]={start:t.start,end:t.end,id:t.id};else{this.getSlot(a)[t.id]={start:t.start,end:e.slotEndDate(a),id:t.id},this.getSlot(n)[t.id]={start:e.slotStartDate(n),end:t.end,id:t.id};for(var r=a+1;r<n;r++)this.getSlot(r)[t.id]={start:e.slotStartDate(r),end:e.slotEndDate(r),id:t.id}}}},{key:"removeEvent",value:function(t){for(var a=e.dateToCacheKey(t.start),n=e.dateToCacheKey(new Date(t.end.getTime()-1)),r=a;r<=n;r++)delete this.getSlot(r)[t.id]}},{key:"getSlotEvents",value:function(e,t,a){var n=this.getSlot(e),r=[];for(var c in n){if(!(n[c].start>=a||n[c].end<=t))(n[c].start<t?t:n[c].start)>(n[c].end>a?a:n[c].end)&&console.log(n[c],t,a),r.push({id:c,start:n[c].start<t?t:n[c].start,end:n[c].end>a?a:n[c].end})}return r}},{key:"getCachedEvents",value:function(t,a){for(var n=e.dateToCacheKey(t),r=e.dateToCacheKey(new Date(a.getTime()-1)),c=this.getSlotEvents(n,t,a),o=n+1;o<r;o++){var i=this.getSlot(o);for(var s in i)c.push(i[s])}return r>n&&c.push.apply(c,Object(l.a)(this.getSlotEvents(r,t,a))),c}},{key:"sync",value:function(){var e=this;return this.token.then(function(t){return function(e,t,a){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:100,r=[];return function a(c,o){return fetch("".concat(_,"/calendars/").concat(e,"/events?").concat(z({access_token:t,pageToken:c,syncToken:o,maxResults:n})),{method:"GET",async:!0}).then(function(e){if(200===e.status)return e.json();throw 410==e.status?M.invalidSyncToken:M.otherErrors}).then(function(e){return r.push.apply(r,Object(l.a)(e.items)),e.nextPageToken?a(e.nextPageToken,""):{nextSyncToken:e.nextSyncToken,results:r}})}("",a)}(e.calId,t,e.syncToken).then(function(a){e.syncToken=a.nextSyncToken;var n=a.results.map(function(a){return a.start?Promise.resolve(a):function(e,t,a){return fetch("".concat(_,"/calendars/").concat(e,"/events/").concat(t,"?").concat(z({access_token:a})),{method:"GET",async:!0}).then(function(e){return e.json()})}(e.calId,a.id,t)});return Promise.all(n).then(function(t){return t.forEach(function(t){t.start=new Date(t.start.dateTime),t.end=new Date(t.end.dateTime),"confirmed"===t.status?e.addEvent(t):"cancelled"===t.status&&e.removeEvent(t)})})})}).catch(function(t){if(t!=M.invalidSyncToken)throw t;e.syncToken="",e.sync()})}},{key:"getEvents",value:function(e,t){var a=this;return this.sync().then(function(){return a.getCachedEvents(e,t)})}}],[{key:"dateToCacheKey",value:function(e){return Math.floor(e/864e5)}},{key:"slotStartDate",value:function(e){return new Date(864e5*e)}},{key:"slotEndDate",value:function(e){return new Date(864e5*(e+1))}}]),e}(),H=function(){function e(t,a,n,r){Object(s.a)(this,e),this.id=t,this.isRegex=a,this.value=n,this.label=r}return Object(u.a)(e,[{key:"regex",get:function(){return new RegExp(this.isRegex?this.value:"^".concat(this.value,"$"))}},{key:"isEmpty",get:function(){return null===this.label}}]),e}();H.emptyPattern=function(){return new H(0,!0,"",null)},H.anyPattern=function(){return new H("any",!0,".*","Any")};var J=function e(t,a,n,r){Object(s.a)(this,e),this.name=t,this.idx=a,this.cal=n,this.event=r};J.defaultPatternEntry=function(e){return new J("",e,H.emptyPattern(),H.anyPattern())};var V=a(299),q=a.n(V),X=a(659),Y=a(657),Q=a(656),Z=a(554);function ee(e){var t=e.cx,a=e.cy,n=e.x,c=e.y,o=e.fill,i=e.name,l="middle",s=0,u=0;return n<t-2?(s=-5,l="end"):n>t+2&&(s=5,l="start"),c<a-2?u=-5:c>a+2&&(u=10),r.a.createElement("text",{x:n,y:c,dx:s,dy:u,fill:o,textAnchor:l},"".concat(i))}var te=Object(f.withStyles)(function(e){return{pieChart:{margin:"0 auto"}}})(function(e){return r.a.createElement(B.a,{container:!0,spacing:0},r.a.createElement(B.a,{item:!0,xs:12,lg:6},r.a.createElement("div",{className:e.classes.patternTableWrapper},r.a.createElement(X.a,{width:400,height:250,className:e.classes.pieChart},r.a.createElement(Y.a,{data:e.patternGraphData,dataKey:"value",cx:200,cy:125,outerRadius:60,fill:q.a[300],label:ee}),r.a.createElement(Q.a,{formatter:function(e){return"".concat(e.toFixed(2)," hr")}})))),r.a.createElement(B.a,{item:!0,xs:12,lg:6},r.a.createElement("div",{className:e.classes.patternTableWrapper},r.a.createElement(X.a,{width:400,height:250,className:e.classes.pieChart},r.a.createElement(Y.a,{data:e.calendarGraphData,dataKey:"value",cx:200,cy:125,innerRadius:40,outerRadius:70,fill:g.a[300],label:ee},e.calendarGraphData.map(function(e,t){return r.a.createElement(Z.a,{key:t,fill:e.color})})),r.a.createElement(Q.a,{formatter:function(e){return"".concat(e.toFixed(2)," hr")}})))))}),ae=a(136),ne=a.n(ae),re=a(301),ce=a.n(re),oe=a(303),ie=a.n(oe),le=a(140),se=a.n(le),ue=a(100),he=a.n(ue),de=a(302),me=a.n(de),pe=a(304),fe=a.n(pe),ve=a(300),ge=a.n(ve),ye=a(131),Ee=a.n(ye),we=a(172),be=a.n(we),Pe=function(e){function t(){return Object(s.a)(this,t),Object(h.a)(this,Object(d.a)(t).apply(this,arguments))}return Object(m.a)(t,e),Object(u.a)(t,[{key:"render",value:function(){var e=this,t=this.props.classes,a=[],n=this.props.options,c=new H.emptyPattern;for(var o in n[c.id]=c,n){var i=n[o].isEmpty?r.a.createElement("span",{style:{color:this.props.theme.palette.primary.dark}},"Custom"):n[o].label;a.push(r.a.createElement(be.a,{key:o,value:o},i))}var l=this.props.value.isRegex?t.fieldRegex:t.fieldNoRegex;return r.a.createElement(O.a,null,r.a.createElement("span",null,r.a.createElement(Ee.a,{value:this.props.value.id,onChange:function(t){var a;a=null==n[t.target.value].label?new H(0,!0,e.props.value.isRegex?e.props.value.value:"^".concat(e.props.value.value,"$"),null):n[t.target.value],e.props.onChange({target:{value:a}})},className:l},a),null==this.props.value.label&&r.a.createElement(ne.a,{value:this.props.value.value,onChange:function(t){return e.props.onChange({target:{value:new H(0,!0,t.target.value,null)}})}})))}}]),t}(r.a.Component),xe=Object(f.withStyles)(function(e){return{fieldNoRegex:{width:200},fieldRegex:{marginRight:"0.5em"}}})(Pe);var ke=a(139),Se=a.n(ke),Te=Object(f.createMuiTheme)({palette:{primary:{light:Se.a[300],main:Se.a[500],dark:Se.a[700],contrastText:"#fff"}},typography:{useNextVariants:!0}}),Ce=[{label:"Name",field:"name",elem:ne.a},{label:"Calendar",field:"cal",elem:Object(f.withTheme)(Te)(function(e){var t={};for(var a in e.cached.calendars)t[a]=new H(a,!1,e.cached.calendars[a].name,e.cached.calendars[a].name);return r.a.createElement(xe,{value:e.value,options:t,onChange:e.onChange,theme:e.theme})})},{label:"Event",field:"event",elem:Object(f.withTheme)(Te)(function(e){var t=H.anyPattern(),a={};return a[t.id]=t,r.a.createElement(xe,{value:e.value,options:a,onChange:e.onChange,theme:e.theme})})}],De=function(e){function t(){var e,a;Object(s.a)(this,t);for(var n=arguments.length,r=new Array(n),c=0;c<n;c++)r[c]=arguments[c];return(a=Object(h.a)(this,(e=Object(d.a)(t)).call.apply(e,[this].concat(r)))).state={page:0,rowsPerPage:5},a.handleChangePage=function(e,t){a.setState({page:t})},a.handleChangeRowsPerPage=function(e){a.setState({rowsPerPage:e.target.value})},a}return Object(m.a)(t,e),Object(u.a)(t,[{key:"render",value:function(){var e=this,t=this.props,a=t.classes,n=t.cached,c=t.patterns,o=this.state,i=o.rowsPerPage,l=o.page,s=i-Math.min(i,c.length-l*i),u=c.slice(l*i,(l+1)*i).map(function(t){return r.a.createElement(se.a,{onMouseOver:function(){return e.setState({activePattern:t.idx})},onMouseOut:function(){return e.setState({activePattern:null})}},Ce.map(function(a){var c=a.elem;return r.a.createElement(he.a,null,r.a.createElement(c,{value:t[a.field],cached:n,onChange:function(n){return e.props.onUpdatePattern(a.field,t.idx,n.target.value)}}))}),r.a.createElement("span",{className:e.state.activePattern===t.idx?a.deleteButtonShow:a.deleteButtonHide},r.a.createElement(ge.a,{className:a.deleteIcon,onClick:function(){return e.props.onRemovePattern(t.idx)}})))});return r.a.createElement("div",null,r.a.createElement("div",{className:a.patternTableWrapper},r.a.createElement(ce.a,{className:a.patternTable},r.a.createElement(me.a,null,r.a.createElement(se.a,null,Ce.map(function(e,t){return r.a.createElement(he.a,{key:t},e.label)}))),r.a.createElement(ie.a,null,u,s>0&&r.a.createElement(se.a,{style:{height:48*s}},r.a.createElement(he.a,{colSpan:Ce.length}))))),r.a.createElement(fe.a,{rowsPerPageOptions:[5,10,25],component:"div",count:c.length,rowsPerPage:i,page:l,backIconButtonProps:{"aria-label":"Previous Page"},nextIconButtonProps:{"aria-label":"Next Page"},onChangePage:this.handleChangePage,onChangeRowsPerPage:this.handleChangeRowsPerPage}))}}]),t}(r.a.Component),Oe=Object(f.withStyles)(function(e){return{deleteButtonShow:{position:"absolute",right:0,height:48},deleteButtonHide:{display:"none"},deleteIcon:{height:"100%",cursor:"pointer"},patternTableWrapper:{overflowX:"auto",overflowY:"hidden"},patternTable:{minWidth:600}}})(De),je=[{name:"Work",value:10,color:g.a[300]},{name:"Wasted",value:10,color:g.a[300]}];var Re=function(e){function t(){var e,a;Object(s.a)(this,t);for(var n=arguments.length,r=new Array(n),c=0;c<n;c++)r[c]=arguments[c];return(a=Object(h.a)(this,(e=Object(d.a)(t)).call.apply(e,[this].concat(r)))).state={patterns:[],timeRange:null,token:F(),patternGraphData:je,calendarGraphData:je,activePattern:null},a.cached={calendars:{}},a.updatePattern=function(e,t,n){var r=a.state.patterns;r[t][e]=n,a.setState({patterns:r})},a.removePattern=function(e){var t=a.state.patterns;t.splice(e,1);for(var n=0;n<t.length;n++)t[n].idx=n;a.setState({patterns:t})},a.newPattern=function(){for(var e=[J.defaultPatternEntry()].concat(Object(l.a)(a.state.patterns)),t=1;t<e.length;t++)e[t].idx=t;a.setState({patterns:e})},a.analyze=function(){if(a.state.startDate&&a.state.endDate){var e=a.state.startDate.startOf("day").toDate(),t=a.state.endDate.startOf("day").toDate();console.log(e,t);var n=[],r=function(r){n.push(a.cached.calendars[r].cal.getEvents(e,t).then(function(e){return{id:r,events:e}}).catch(function(e){return console.log("cannot load calendar ".concat(r)),{id:r,events:[]}}))};for(var c in a.cached.calendars)r(c);Promise.all(n).then(function(e){var t={},n={},r={};e.forEach(function(e){return t[e.id]=e.events});for(var c=0;c<a.state.patterns.length;c++)n[c]=0;var o=function(e){if(!t[e])return"continue";var c=function(e,t){return e.filter(function(e){return e.cal.regex.test(t)})}(a.state.patterns,a.cached.calendars[e].name);t[e].forEach(function(t){c.forEach(function(a){if(a.event.regex.test(t.summary)){r.hasOwnProperty(e)||(r[e]=0);var c=(t.end-t.start)/6e4;n[a.idx]+=c,r[e]+=c}})})};for(var i in a.cached.calendars)o(i);for(var l=[],s=[],u=0;u<a.state.patterns.length;u++)l.push({name:a.state.patterns[u].name,value:n[u]/60});for(var i in r)s.push({name:a.cached.calendars[i].name,value:r[i]/60,color:a.cached.calendars[i].color.background});a.setState({patternGraphData:l,calendarGraphData:s})})}else alert("Please choose a valid time range.")},a.loadPatterns=function(){var e=a.state.token,t=e.then(L).then(function(e){return e.calendar}),n=e.then(U);Promise.all([t,n]).then(function(e){var t=Object(i.a)(e,2),n=t[0],r=t[1];r.forEach(function(e){a.cached.calendars[e.id]={name:e.summary,color:n[e.colorId],cal:new $(e.id,e.summary)}}),a.setState({patterns:r.map(function(e,t){return new J(e.summary,t,new H(e.id,!1,e.summary,e.summary),H.anyPattern())})})})},a}return Object(m.a)(t,e),Object(u.a)(t,[{key:"render",value:function(){var e=this,t=this.props.classes;return r.a.createElement(f.MuiThemeProvider,{theme:Te},r.a.createElement("div",{className:t.root},r.a.createElement(b.a,{position:"absolute",className:t.appBar},r.a.createElement(x.a,{className:t.toolbar},r.a.createElement(S.a,{component:"h1",variant:"h6",color:"inherit",noWrap:!0,className:t.title},r.a.createElement(A,{style:{width:"2em",verticalAlign:"bottom",marginRight:"0.2em"}}),"Chromicle"))),r.a.createElement("main",{className:t.content},r.a.createElement("div",{className:t.appBarSpacer}),r.a.createElement(B.a,{container:!0,spacing:16},r.a.createElement(E.a,null),r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(O.a,{fullWidth:!0},r.a.createElement(R.a,null,r.a.createElement(S.a,{variant:"h6",component:"h1",gutterBottom:!0},"Event Patterns",r.a.createElement(K.a,{style:{marginBottom:"0.12em",marginLeft:"0.5em"},onClick:function(){return e.newPattern()}},r.a.createElement(I.a,null))),r.a.createElement(Oe,{patterns:this.state.patterns,cached:this.cached,onRemovePattern:this.removePattern,onUpdatePattern:this.updatePattern})),r.a.createElement(R.a,null,r.a.createElement(S.a,{variant:"h6",component:"h1",gutterBottom:!0},"Time Range"),r.a.createElement("div",{style:{textAlign:"center"}},r.a.createElement(p.DateRangePicker,{startDate:this.state.startDate,startDateId:"start_date_id",endDate:this.state.endDate,endDateId:"end_date_id",onDatesChange:function(t){var a=t.startDate,n=t.endDate;e.setState({startDate:a,endDate:n})},focusedInput:this.state.focusedInput,onFocusChange:function(t){return e.setState({focusedInput:t})},isOutsideRange:function(){return!1}}))),r.a.createElement("div",{className:t.buttonSpacer}),r.a.createElement(B.a,{container:!0,spacing:16},r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(R.a,null,r.a.createElement(C.a,{variant:"contained",color:"primary",onClick:this.loadPatterns},"Load"))),r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(R.a,null,r.a.createElement(C.a,{variant:"contained",color:"primary",onClick:this.analyze},"Analyze")))))),r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(S.a,{variant:"h6",component:"h1",gutterBottom:!0},"Graph"),r.a.createElement(te,{patternGraphData:this.state.patternGraphData,calendarGraphData:this.state.calendarGraphData}))))))}}]),t}(r.a.Component),Ne=Object(f.withStyles)(function(e){return{root:{display:"flex",height:"100vh"},appBar:{zIndex:e.zIndex.drawer+1,transition:e.transitions.create(["width","margin"],{easing:e.transitions.easing.sharp,duration:e.transitions.duration.leavingScreen})},title:{flexGrow:1},sectionTitle:{flex:"0 0 auto"},appBarSpacer:e.mixins.toolbar,content:{flexGrow:1,padding:3*e.spacing.unit,overflow:"auto"},buttonSpacer:{marginBottom:4*e.spacing.unit},fab:{margin:e.spacing.unit}}})(Re);Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));o.a.render(r.a.createElement(Ne,null),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then(function(e){e.unregister()})}},[[308,2,1]]]);
-//# sourceMappingURL=main.0c8ec738.chunk.js.map \ No newline at end of file
diff --git a/build/static/js/main.0c8ec738.chunk.js.map b/build/static/js/main.0c8ec738.chunk.js.map
deleted file mode 100644
index c60958e..0000000
--- a/build/static/js/main.0c8ec738.chunk.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["Logo.js","gapi.js","pattern.js","Chart.js","RegexField.js","theme.js","PatternTable.js","App.js","serviceWorker.js","index.js"],"names":["Logo","props","react_default","a","createElement","xmlns","viewBox","version","style","id","transform","points","fill","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontFamily","gapi_base","GApiError","invalidSyncToken","otherError","to_params","dict","Object","entries","map","_ref","_ref2","slicedToArray","k","v","concat","encodeURIComponent","join","getAuthToken","Promise","resolver","chrome","identity","interactive","token","getCalendars","fetch","access_token","method","async","then","response","json","data","items","getColors","GCalendar","calId","name","classCallCheck","this","syncToken","cache","createClass","key","value","e","ks","dateToCacheKey","start","ke","Date","end","getTime","getSlot","slotEndDate","slotStartDate","s","results","console","log","push","getSlotEvents","apply","toConsumableArray","_this","resultsPerRequest","arguments","length","undefined","singleFetch","pageToken","maxResults","status","otherErrors","nextPageToken","nextSyncToken","getEvents","r","pm_results","resolve","eventId","getEvent","all","forEach","dateTime","addEvent","removeEvent","catch","sync","_this2","getCachedEvents","date","Math","floor","Pattern","isRegex","label","get","RegExp","emptyPattern","anyPattern","PatternEntry","idx","calPattern","eventPattern","cal","event","defaultPatternEntry","customizedLabel","cx","cy","x","y","anchor","dx","dy","textAnchor","withStyles","theme","pieChart","margin","Grid_default","container","spacing","item","xs","lg","className","classes","patternTableWrapper","PieChart","width","height","Pie","patternGraphData","dataKey","outerRadius","deepOrange","Tooltip","formatter","toFixed","calendarGraphData","innerRadius","cyan","d","i","Cell","color","RegexField","pitems","options","p0","isEmpty","palette","primary","dark","MenuItem_default","fieldRegex","fieldNoRegex","FormControl_default","Select_default","onChange","target","TextField_default","React","Component","RegexFieldWithStyles","marginRight","createMuiTheme","light","orange","main","contrastText","typography","useNextVariants","patternHead","field","elem","TextField","withTheme","cached","calendars","any","PatternTable","state","page","rowsPerPage","handleChangePage","setState","handleChangeRowsPerPage","_this$props","patterns","_this$state","nDummy","min","rows","slice","p","TableRow_default","onMouseOver","activePattern","onMouseOut","CustomText","TableCell_default","onUpdatePattern","deleteButtonShow","deleteButtonHide","DeleteOutlined_default","deleteIcon","onClick","onRemovePattern","Table_default","patternTable","TableHead_default","TableBody_default","colSpan","TablePagination_default","rowsPerPageOptions","component","count","backIconButtonProps","aria-label","nextIconButtonProps","onChangePage","onChangeRowsPerPage","position","right","display","cursor","overflowX","overflowY","minWidth","default_chart_data","Dashboard","timeRange","gapi","updatePattern","removePattern","splice","newPattern","analyze","startDate","endDate","startOf","toDate","event_pms","_loop","events","all_events","cal_results","_loop2","calName","filter","regex","test","filterPatterns","summary","hasOwnProperty","duration","background","alert","loadPatterns","colors","calendar","cals","colorId","styles","root","AppBar_default","appBar","Toolbar_default","toolbar","Typography_default","variant","noWrap","title","verticalAlign","content","appBarSpacer","CssBaseline_default","md","fullWidth","FormGroup_default","gutterBottom","IconButton_default","marginBottom","marginLeft","AddCircle_default","src_PatternTable","textAlign","react_dates","startDateId","endDateId","onDatesChange","_ref3","focusedInput","onFocusChange","isOutsideRange","buttonSpacer","Button_default","Chart","zIndex","drawer","transition","transitions","create","easing","sharp","leavingScreen","flexGrow","sectionTitle","flex","mixins","padding","unit","overflow","fab","Boolean","window","location","hostname","match","ReactDOM","render","App","document","getElementById","navigator","serviceWorker","ready","registration","unregister"],"mappings":"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","file":"static/js/main.0c8ec738.chunk.js","sourcesContent":["import React from 'react';\nexport default (props) =>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 98.905998 93.557997\"\n version=\"1.1\"\n style={props.style}>\n <g id=\"g13\"\n transform=\"translate(-153.533,-203.047)\">\n <g id=\"g29\">\n <g\n id=\"g27\">\n <polygon\n id=\"polygon7\"\n points=\"252.439,241.924 234.556,288.703 185.103,296.605 153.533,257.728 171.416,210.949 220.869,203.047 \"\n style={{fill: '#ff8000'}} />\n <g\n id=\"g11\"\n transform=\"translate(167.24355,224.20734)\">\n <text\n id=\"text9\"\n style={{fontStyle:'normal',\n fontVariant:'normal',\n fontWeight:'normal',\n fontStretch:'normal',\n fontSize:75,\n fontFamily:'TypoPRO Fantasque Sans Mono',\n fill:'#ffeade'}}\n transform=\"translate(0.586,49.072)\">Cr</text>\n </g>\n </g>\n </g>\n </g>\n </svg>\n","/* global chrome */\nconst gapi_base = 'https://www.googleapis.com/calendar/v3';\n\nconst GApiError = {\n invalidSyncToken: 1,\n otherError: 2,\n};\n\nfunction to_params(dict) {\n return Object.entries(dict).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&');\n}\n\nexport function getAuthToken() {\n return new Promise(resolver =>\n chrome.identity.getAuthToken(\n {interactive: true}, token => resolver(token)));\n}\n\nexport function getCalendars(token) {\n return fetch(`${gapi_base}/users/me/calendarList?${to_params({access_token: token})}`,\n { method: 'GET', async: true })\n .then(response => response.json())\n .then(data => data.items);\n}\n\nexport function getColors(token) {\n return fetch(`${gapi_base}/colors?${to_params({access_token: token})}`,\n { method: 'GET', async: true })\n .then(response => response.json());\n}\n\nfunction getEvent(calId, eventId, token) {\n return fetch(`${gapi_base}/calendars/${calId}/events/${eventId}?${to_params({access_token: token})}`,\n { method: 'GET', async: true })\n .then(response => response.json());\n}\n\nfunction getEvents(calId, token, syncToken, resultsPerRequest=100) {\n let results = [];\n const singleFetch = (pageToken, syncToken) => fetch(`${gapi_base}/calendars/${calId}/events?${to_params({\n access_token: token,\n pageToken,\n syncToken,\n maxResults: resultsPerRequest\n })}`, { method: 'GET', async: true })\n .then(response => {\n if (response.status === 200)\n return response.json();\n else if (response.status == 410)\n throw GApiError.invalidSyncToken;\n else throw GApiError.otherErrors;\n })\n .then(data => {\n results.push(...data.items);\n if (data.nextPageToken) {\n return singleFetch(data.nextPageToken, '');\n } else {\n return ({\n nextSyncToken: data.nextSyncToken,\n results\n });\n }\n })\n\n return singleFetch('', syncToken);\n}\n\nexport class GCalendar {\n constructor(calId, name) {\n this.calId = calId;\n this.name = name;\n this.token = getAuthToken();\n this.syncToken = '';\n this.cache = {};\n }\n\n static dateToCacheKey(date) {\n return Math.floor(date / 8.64e7);\n }\n\n getSlot(k) {\n if (!this.cache[k])\n this.cache[k] = {};\n return this.cache[k];\n }\n\n static slotStartDate(k) { return new Date(k * 8.64e7); }\n static slotEndDate(k) { return new Date((k + 1) * 8.64e7); }\n\n addEvent(e) {\n let ks = GCalendar.dateToCacheKey(e.start);\n let ke = GCalendar.dateToCacheKey(new Date(e.end.getTime() - 1));\n if (ks === ke)\n this.getSlot(ks)[e.id] = {\n start: e.start,\n end: e.end,\n id: e.id };\n else\n {\n this.getSlot(ks)[e.id] = {\n start: e.start,\n end: GCalendar.slotEndDate(ks),\n id: e.id };\n this.getSlot(ke)[e.id] = {\n start: GCalendar.slotStartDate(ke),\n end: e.end,\n id: e.id };\n for (let k = ks + 1; k < ke; k++)\n this.getSlot(k)[e.id] = {\n start: GCalendar.slotStartDate(k),\n end: GCalendar.slotEndDate(k),\n id: e.id };\n }\n }\n\n removeEvent(e) {\n let ks = GCalendar.dateToCacheKey(e.start);\n let ke = GCalendar.dateToCacheKey(new Date(e.end.getTime() - 1));\n for (let k = ks; k <= ke; k++)\n delete this.getSlot(k)[e.id];\n }\n\n getSlotEvents(k, start, end) {\n let s = this.getSlot(k);\n let results = [];\n for (let id in s) {\n if (!(s[id].start >= end || s[id].end <= start))\n {\n let nstart = s[id].start < start ? start: s[id].start;\n let nend = s[id].end > end ? end: s[id].end;\n if (nstart > nend) console.log(s[id], start, end);\n results.push({\n id,\n start: s[id].start < start ? start: s[id].start,\n end: s[id].end > end ? end: s[id].end\n });\n }\n }\n return results;\n }\n\n getCachedEvents(start, end) {\n let ks = GCalendar.dateToCacheKey(start);\n let ke = GCalendar.dateToCacheKey(new Date(end.getTime() - 1));\n let results = this.getSlotEvents(ks, start, end);\n for (let k = ks + 1; k < ke; k++)\n {\n let s = this.getSlot(k);\n for (let id in s)\n results.push(s[id]);\n }\n if (ke > ks)\n results.push(...this.getSlotEvents(ke, start, end));\n return results;\n }\n\n sync() {\n return this.token.then(token => getEvents(this.calId, token, this.syncToken).then(r => {\n this.syncToken = r.nextSyncToken;\n let pm_results = r.results.map(e => e.start ? Promise.resolve(e) : getEvent(this.calId, e.id, token));\n return Promise.all(pm_results).then(results => results.forEach(e => {\n e.start = new Date(e.start.dateTime);\n e.end = new Date(e.end.dateTime);\n if (e.status === 'confirmed')\n this.addEvent(e);\n else if (e.status === 'cancelled')\n this.removeEvent(e);\n }));\n })).catch(e => {\n if (e == GApiError.invalidSyncToken) {\n this.syncToken = '';\n this.sync();\n } else throw e;\n });\n }\n\n getEvents(start, end) {\n return this.sync().then(() => this.getCachedEvents(start, end));\n }\n}\n","export class Pattern {\n constructor(id, isRegex, value, label) {\n this.id = id;\n this.isRegex = isRegex;\n this.value = value;\n this.label = label;\n }\n\n get regex() { return new RegExp(this.isRegex ? this.value : `^${this.value}$`); }\n get isEmpty() { return this.label === null; }\n static emptyPattern = () => new Pattern(0, true, '', null);\n static anyPattern = () => new Pattern('any', true, '.*', 'Any');\n}\n\nexport class PatternEntry {\n constructor(name, idx, calPattern, eventPattern) {\n this.name = name;\n this.idx = idx;\n this.cal = calPattern;\n this.event = eventPattern;\n }\n\n static defaultPatternEntry = (idx) => new PatternEntry('', idx, Pattern.emptyPattern(), Pattern.anyPattern());\n}\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles } from '@material-ui/core/styles';\nimport Grid from '@material-ui/core/Grid';\nimport deepOrange from '@material-ui/core/colors/deepOrange';\nimport cyan from '@material-ui/core/colors/cyan';\nimport { PieChart, Pie, Cell, Tooltip } from 'recharts';\n\nconst styles = theme => ({\n pieChart: {\n margin: '0 auto',\n }\n});\n\nfunction customizedLabel(props) {\n const {cx, cy, x, y, fill, name} = props;\n let anchor = \"middle\";\n const EPS = 2;\n let dx = 0;\n let dy = 0;\n if (x < cx - EPS) {\n dx = -5;\n anchor = \"end\"\n } else if (x > cx + EPS) {\n dx = 5;\n anchor = \"start\";\n }\n\n if (y < cy - EPS) {\n dy = -5;\n } else if (y > cy + EPS) {\n dy = 10;\n }\n\n return (<text x={x} y={y} dx={dx} dy={dy} fill={fill} textAnchor={anchor}>{`${name}`}</text>);\n}\n\nfunction ChromiclePieChart(props) {\n return (\n <Grid container spacing={0}>\n <Grid item xs={12} lg={6}>\n <div className={props.classes.patternTableWrapper}>\n <PieChart width={400} height={250} className={props.classes.pieChart}>\n <Pie data={props.patternGraphData}\n dataKey='value'\n cx={200}\n cy={125}\n outerRadius={60}\n fill={deepOrange[300]}\n label={customizedLabel}/>\n <Tooltip formatter={(value) => `${value.toFixed(2)} hr`}/>\n </PieChart>\n </div>\n </Grid>\n <Grid item xs={12} lg={6}>\n <div className={props.classes.patternTableWrapper}>\n <PieChart width={400} height={250} className={props.classes.pieChart}>\n <Pie data={props.calendarGraphData}\n dataKey='value'\n cx={200}\n cy={125}\n innerRadius={40}\n outerRadius={70}\n fill={cyan[300]}\n label={customizedLabel}>\n {props.calendarGraphData.map((d, i) => <Cell key={i} fill={d.color}/>)}\n </Pie>\n <Tooltip formatter={(value) => `${value.toFixed(2)} hr`}/>\n </PieChart>\n </div>\n </Grid>\n </Grid>);\n}\n\nChromiclePieChart.propTypes = {\n patternGraphData: PropTypes.array.isRequired,\n calendarGraphData: PropTypes.array.isRequired,\n};\n\nexport default withStyles(styles)(ChromiclePieChart);\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles } from '@material-ui/core/styles';\nimport Select from '@material-ui/core/Select';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport TextField from '@material-ui/core/TextField';\nimport FormControl from '@material-ui/core/FormControl';\nimport { Pattern } from './pattern';\n\nconst styles = theme => ({\n fieldNoRegex: {\n width: 200\n },\n fieldRegex: {\n marginRight: '0.5em'\n }\n});\n\nclass RegexField extends React.Component {\n render() {\n const { classes } = this.props;\n let items = [];\n var pitems = this.props.options;\n const p0 = new Pattern.emptyPattern();\n pitems[p0.id] = p0;\n for (let id in pitems)\n {\n const label = !pitems[id].isEmpty ? pitems[id].label :\n <span style={{color: this.props.theme.palette.primary.dark}}>Custom</span>;\n items.push(<MenuItem key={id} value={id}>{label}</MenuItem>);\n }\n const selectOnClick = event => {\n let value;\n if (pitems[event.target.value].label == null) {\n value = new Pattern(0, true,\n this.props.value.isRegex ?\n this.props.value.value :\n `^${this.props.value.value}$`, null);\n } else {\n value = pitems[event.target.value];\n }\n this.props.onChange({target: {value}});\n };\n\n const regexTextOnChange = event => this.props.onChange({\n target: { value: new Pattern(0, true, event.target.value, null)}});\n\n const className = this.props.value.isRegex ? classes.fieldRegex: classes.fieldNoRegex;\n return (\n <FormControl>\n <span>\n <Select\n value={this.props.value.id}\n onChange={selectOnClick}\n className={className}>{items}\n </Select>\n {this.props.value.label == null && (\n <TextField\n value={this.props.value.value}\n onChange={regexTextOnChange} />\n )}\n </span>\n </FormControl>);\n }\n}\n\nRegexField.propTypes = {\n classes: PropTypes.object.isRequired,\n};\n\nconst RegexFieldWithStyles = withStyles(styles)(RegexField);\n\nexport function CalendarField(props) {\n let options = {};\n for (let id in props.cached.calendars) {\n options[id] = new Pattern(id, false,\n props.cached.calendars[id].name,\n props.cached.calendars[id].name);\n }\n return (\n <RegexFieldWithStyles\n value={props.value}\n options={options}\n onChange={props.onChange}\n theme={props.theme} />);\n}\n\nexport function EventField(props) {\n let any = Pattern.anyPattern();\n let options = {};\n options[any.id] = any;\n return (\n <RegexFieldWithStyles\n value={props.value}\n options={options}\n onChange={props.onChange}\n theme={props.theme} />);\n}\n","import { createMuiTheme } from '@material-ui/core/styles';\nimport orange from '@material-ui/core/colors/orange';\n\nconst theme = createMuiTheme({\n palette: {\n primary: {\n light: orange[300],\n main: orange[500],\n dark: orange[700],\n contrastText: \"#fff\"\n }\n },\n typography: {\n useNextVariants: true,\n }\n});\n\nexport default theme;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles, withTheme } from '@material-ui/core/styles';\nimport TextField from '@material-ui/core/TextField';\nimport Table from '@material-ui/core/Table';\nimport TableBody from '@material-ui/core/TableBody';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableHead from '@material-ui/core/TableHead';\nimport TablePagination from '@material-ui/core/TablePagination';\nimport DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined';\nimport { CalendarField, EventField } from './RegexField';\nimport theme from './theme';\n\nconst styles = theme => ({\n deleteButtonShow: {\n position: 'absolute',\n right: 0,\n height: 48\n },\n deleteButtonHide: {\n display: 'none'\n },\n deleteIcon: {\n height: '100%',\n cursor: 'pointer'\n },\n patternTableWrapper: {\n overflowX: 'auto',\n overflowY: 'hidden'\n },\n patternTable: {\n minWidth: 600\n }\n});\n\nconst patternHead = [\n {label: \"Name\", field: \"name\", elem: TextField},\n {label: \"Calendar\", field: \"cal\", elem: withTheme(theme)(CalendarField)},\n {label: \"Event\", field: 'event', elem: withTheme(theme)(EventField)}];\n\nclass PatternTable extends React.Component {\n state = {\n page: 0,\n rowsPerPage: 5,\n };\n\n handleChangePage = (event, page) => {\n this.setState({ page });\n }\n\n handleChangeRowsPerPage = event => {\n this.setState({ rowsPerPage: event.target.value });\n }\n\n render() {\n const { classes, cached, patterns } = this.props;\n const { rowsPerPage, page } = this.state;\n const nDummy = rowsPerPage - Math.min(rowsPerPage, patterns.length - page * rowsPerPage);\n let rows = patterns.slice(page * rowsPerPage, (page + 1) * rowsPerPage).map(p => (\n <TableRow\n onMouseOver={() => this.setState({ activePattern: p.idx })}\n onMouseOut={() => this.setState({ activePattern: null })}>\n {\n patternHead.map(s => {\n const CustomText = s.elem;\n return (\n <TableCell>\n <CustomText\n value={p[s.field]}\n cached={cached}\n onChange={event => this.props.onUpdatePattern(s.field, p.idx, event.target.value)}/>\n </TableCell>)})\n }\n <span className={this.state.activePattern === p.idx ? classes.deleteButtonShow : classes.deleteButtonHide}>\n <DeleteOutlinedIcon\n className={classes.deleteIcon}\n onClick={() => this.props.onRemovePattern(p.idx)} />\n </span>\n </TableRow>));\n\n return (\n <div>\n <div className={classes.patternTableWrapper}>\n <Table className={classes.patternTable}>\n <TableHead>\n <TableRow>{patternHead.map((s, i) => (<TableCell key={i}>{s.label}</TableCell>))}</TableRow>\n </TableHead>\n <TableBody>\n {rows}\n {\n nDummy > 0 && (\n <TableRow style={{ height: 48 * nDummy }}>\n <TableCell colSpan={patternHead.length} />\n </TableRow>)\n }\n </TableBody>\n </Table>\n </div>\n <TablePagination\n rowsPerPageOptions={[5, 10, 25]}\n component=\"div\"\n count={patterns.length}\n rowsPerPage={rowsPerPage}\n page={page}\n backIconButtonProps={{'aria-label': 'Previous Page'}}\n nextIconButtonProps={{'aria-label': 'Next Page'}}\n onChangePage={this.handleChangePage}\n onChangeRowsPerPage={this.handleChangeRowsPerPage} />\n </div>);\n }\n}\n\n\nPatternTable.propTypes = {\n classes: PropTypes.object.isRequired,\n patterns: PropTypes.array.isRequired,\n cached: PropTypes.object.isRequired,\n onRemovePattern: PropTypes.func.isRequired,\n onUpdatePattern: PropTypes.func.isRequired,\n};\n\nexport default withStyles(styles)(PatternTable);\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport 'typeface-roboto';\nimport 'react-dates/initialize';\nimport 'react-dates/lib/css/_datepicker.css';\nimport { DateRangePicker } from 'react-dates';\nimport { withStyles } from '@material-ui/core/styles';\nimport { MuiThemeProvider } from '@material-ui/core/styles';\nimport cyan from '@material-ui/core/colors/cyan';\nimport CssBaseline from '@material-ui/core/CssBaseline';\nimport AppBar from '@material-ui/core/AppBar';\nimport Toolbar from '@material-ui/core/Toolbar';\nimport Typography from '@material-ui/core/Typography';\nimport Button from '@material-ui/core/Button';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport Grid from '@material-ui/core/Grid';\nimport AddCircleIcon from '@material-ui/icons/AddCircle';\nimport IconButton from '@material-ui/core/IconButton';\nimport Logo from './Logo';\nimport * as gapi from './gapi';\nimport { Pattern, PatternEntry } from './pattern';\nimport PieChart from './Chart';\nimport PatternTable from './PatternTable';\nimport theme from './theme';\n\nconst default_chart_data = [\n {name: 'Work', value: 10, color: cyan[300]},\n {name: 'Wasted', value: 10, color: cyan[300]}];\n\nfunction filterPatterns(patterns, calName) {\n return patterns.filter(p => {\n return p.cal.regex.test(calName);\n });\n}\n\nconst styles = theme => ({\n root: {\n display: 'flex',\n height: '100vh',\n },\n appBar: {\n zIndex: theme.zIndex.drawer + 1,\n transition: theme.transitions.create(['width', 'margin'], {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.leavingScreen,\n }),\n },\n title: {\n flexGrow: 1,\n },\n sectionTitle: {\n flex: '0 0 auto'\n },\n appBarSpacer: theme.mixins.toolbar,\n content: {\n flexGrow: 1,\n padding: theme.spacing.unit * 3,\n overflow: 'auto',\n },\n buttonSpacer: {\n marginBottom: theme.spacing.unit * 4,\n },\n fab: {\n margin: theme.spacing.unit,\n },\n});\n\nclass Dashboard extends React.Component {\n state = {\n patterns: [],\n timeRange: null,\n token: gapi.getAuthToken(),\n patternGraphData: default_chart_data,\n calendarGraphData: default_chart_data,\n activePattern: null\n };\n\n cached = {\n calendars: {}\n };\n\n updatePattern = (field, idx, value) => {\n let patterns = this.state.patterns;\n patterns[idx][field] = value;\n this.setState({ patterns });\n };\n\n removePattern = idx => {\n let patterns = this.state.patterns;\n patterns.splice(idx, 1);\n for (let i = 0; i < patterns.length; i++)\n patterns[i].idx = i;\n this.setState({ patterns });\n };\n\n newPattern = () => {\n let patterns = [PatternEntry.defaultPatternEntry(), ...this.state.patterns];\n for (let i = 1; i < patterns.length; i++)\n patterns[i].idx = i;\n this.setState({ patterns });\n };\n\n analyze = () => {\n if (!(this.state.startDate && this.state.endDate)) {\n alert(\"Please choose a valid time range.\");\n return;\n }\n let start = this.state.startDate.startOf('day').toDate();\n let end = this.state.endDate.startOf('day').toDate();\n console.log(start, end);\n let event_pms = [];\n for (let id in this.cached.calendars)\n event_pms.push(this.cached.calendars[id].cal.getEvents(start, end)\n .then(r => { return { id, events: r }; })\n .catch(e => {\n console.log(`cannot load calendar ${id}`);\n return { id, events: [] };\n }));\n\n Promise.all(event_pms).then(all_events => {\n let events = {};\n let results = {}; // pattern idx => time\n let cal_results = {}; // cal id => time\n all_events.forEach(e => events[e.id] = e.events);\n for (let i = 0; i < this.state.patterns.length; i++)\n results[i] = 0;\n for (let id in this.cached.calendars) {\n if (!events[id]) continue;\n let patterns = filterPatterns(this.state.patterns, this.cached.calendars[id].name);\n events[id].forEach(event => {\n patterns.forEach(p => {\n if (!p.event.regex.test(event.summary)) return;\n if (!cal_results.hasOwnProperty(id)) {\n cal_results[id] = 0;\n }\n let duration = (event.end - event.start) / 60000;\n results[p.idx] += duration;\n cal_results[id] += duration;\n });\n });\n }\n let patternGraphData = [];\n let calendarGraphData = [];\n for (let i = 0; i < this.state.patterns.length; i++) {\n patternGraphData.push({ name: this.state.patterns[i].name, value: results[i] / 60.0 });\n }\n for (let id in cal_results) {\n calendarGraphData.push({\n name: this.cached.calendars[id].name,\n value: (cal_results[id] / 60.0),\n color: this.cached.calendars[id].color.background});\n }\n //console.log(patternGraphData, calendarGraphData);\n this.setState({ patternGraphData, calendarGraphData });\n });\n };\n\n loadPatterns = () => {\n let token = this.state.token;\n let colors = token.then(gapi.getColors).then(color => {\n return color.calendar;\n });\n let cals = token.then(gapi.getCalendars);\n Promise.all([colors, cals]).then(([colors, items]) => {\n items.forEach(item => {\n this.cached.calendars[item.id] = {\n name: item.summary,\n color: colors[item.colorId],\n cal: new gapi.GCalendar(item.id, item.summary)\n };\n });\n this.setState({ patterns: items.map((item, idx) => {\n return new PatternEntry(item.summary, idx,\n new Pattern(item.id, false, item.summary, item.summary),\n Pattern.anyPattern());\n })});\n });\n };\n\n render() {\n const { classes } = this.props;\n\n return (\n <MuiThemeProvider theme={theme}>\n <div className={classes.root}>\n <AppBar\n position=\"absolute\"\n className={classes.appBar}>\n <Toolbar className={classes.toolbar}>\n <Typography component=\"h1\" variant=\"h6\" color=\"inherit\" noWrap className={classes.title}>\n <Logo style={{width: '2em', verticalAlign: 'bottom', marginRight: '0.2em'}}/>Chromicle\n </Typography>\n </Toolbar>\n </AppBar>\n <main className={classes.content}>\n <div className={classes.appBarSpacer} />\n <Grid container spacing={16}>\n <CssBaseline />\n <Grid item md={6} xs={12}>\n <FormControl fullWidth={true}>\n <FormGroup>\n <Typography variant=\"h6\" component=\"h1\" gutterBottom>\n Event Patterns\n <IconButton\n style={{marginBottom: '0.12em', marginLeft: '0.5em'}}\n onClick={() => this.newPattern()}><AddCircleIcon /></IconButton>\n </Typography>\n <PatternTable\n patterns={this.state.patterns}\n cached={this.cached}\n onRemovePattern={this.removePattern}\n onUpdatePattern={this.updatePattern} />\n </FormGroup>\n <FormGroup>\n <Typography variant=\"h6\" component=\"h1\" gutterBottom>\n Time Range\n </Typography>\n <div style={{textAlign: 'center'}}>\n <DateRangePicker\n startDate={this.state.startDate}\n startDateId=\"start_date_id\"\n endDate={this.state.endDate}\n endDateId=\"end_date_id\"\n onDatesChange={({ startDate, endDate }) => {\n this.setState({ startDate, endDate });\n }} \n focusedInput={this.state.focusedInput}\n onFocusChange={focusedInput => this.setState({ focusedInput })}\n isOutsideRange={() => false}/>\n </div>\n </FormGroup>\n <div className={classes.buttonSpacer} />\n <Grid container spacing={16}>\n <Grid item md={6} xs={12}>\n <FormGroup>\n <Button variant=\"contained\" color=\"primary\" onClick={this.loadPatterns}>Load</Button>\n </FormGroup>\n </Grid>\n <Grid item md={6} xs={12}>\n <FormGroup>\n <Button variant=\"contained\" color=\"primary\" onClick={this.analyze}>Analyze</Button>\n </FormGroup>\n </Grid>\n </Grid>\n </FormControl>\n </Grid>\n <Grid item md={6} xs={12}>\n <Typography variant=\"h6\" component=\"h1\" gutterBottom>\n Graph\n </Typography>\n <PieChart\n patternGraphData={this.state.patternGraphData}\n calendarGraphData={this.state.calendarGraphData}/>\n </Grid>\n </Grid>\n </main>\n </div>\n </MuiThemeProvider>);\n }\n}\n\nDashboard.propTypes = {\n classes: PropTypes.object.isRequired,\n};\n\nexport default withStyles(styles)(Dashboard);\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read http://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit http://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(<App />, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: http://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""} \ No newline at end of file
diff --git a/build/static/js/main.9e0b7c77.chunk.js b/build/static/js/main.9e0b7c77.chunk.js
new file mode 100644
index 0000000..bc640ed
--- /dev/null
+++ b/build/static/js/main.9e0b7c77.chunk.js
@@ -0,0 +1,2 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[0],{308:function(e,t,a){e.exports=a(655)},655:function(e,t,a){"use strict";a.r(t);var n=a(1),r=a.n(n),o=a(28),l=a.n(o),i=a(137),s=a(101),c=a(39),u=a(45),m=a(78),d=a(74),p=a(79),h=(a(313),a(315),a(341),a(286)),f=a(31),g=a(99),v=a.n(g),E=a(306),y=a.n(E),w=a(305),b=a.n(w),P=a(173),x=a.n(P),C=a(81),O=a.n(C),j=a(177),k=a.n(j),D=a(93),S=a.n(D),R=a(103),N=a.n(R),T=a(40),B=a.n(T),I=a(307),M=a.n(I),G=a(174),W=a.n(G),F=function(e){return r.a.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 98.905998 93.557997",version:"1.1",style:e.style},r.a.createElement("g",{id:"g13",transform:"translate(-153.533,-203.047)"},r.a.createElement("g",{id:"g29"},r.a.createElement("g",{id:"g27"},r.a.createElement("polygon",{id:"polygon7",points:"252.439,241.924 234.556,288.703 185.103,296.605 153.533,257.728 171.416,210.949 220.869,203.047 ",style:{fill:"#ff8000"}}),r.a.createElement("g",{id:"g11",transform:"translate(167.24355,224.20734)"},r.a.createElement("text",{id:"text9",style:{fontStyle:"normal",fontVariant:"normal",fontWeight:"normal",fontStretch:"normal",fontSize:75,fontFamily:"TypoPRO Fantasque Sans Mono",fill:"#ffeade"},transform:"translate(0.586,49.072)"},"Cr"))))))},A="https://www.googleapis.com/calendar/v3";function q(e){return Object.entries(e).map(function(e){var t=Object(i.a)(e,2),a=t[0],n=t[1];return"".concat(encodeURIComponent(a),"=").concat(encodeURIComponent(n))}).join("&")}function z(){return new Promise(function(e){return chrome.identity.getAuthToken({interactive:!0},function(t){return e(t)})})}function _(e){return fetch("".concat(A,"/users/me/calendarList?").concat(q({access_token:e})),{method:"GET",async:!0}).then(function(e){return e.json()}).then(function(e){return e.items})}function L(e){return fetch("".concat(A,"/colors?").concat(q({access_token:e})),{method:"GET",async:!0}).then(function(e){return e.json()})}var U=function(){function e(t,a,n,r){Object(c.a)(this,e),this.id=t,this.isRegex=a,this.value=n,this.label=r}return Object(u.a)(e,[{key:"regex",get:function(){return new RegExp(this.isRegex?this.value:"^".concat(this.value,"$"))}},{key:"isEmpty",get:function(){return null===this.label}}]),e}();U.emptyPattern=function(){return new U(0,!0,"",null)},U.anyPattern=function(){return new U("any",!0,".*","Any")},U.revive=function(e){return new U(e.id,e.isRegex,e.value,e.label)};var $=function e(t,a,n,r){Object(c.a)(this,e),this.name=t,this.idx=a,this.cal=n,this.event=r};$.defaultPatternEntry=function(e){return new $("",e,U.emptyPattern(),U.anyPattern())},$.revive=function(e){return new $(e.name,e.idx,U.revive(e.cal),U.revive(e.event))};var H=a(299),J=a.n(H),K=a(659),V=a(657),X=a(656),Y=a(554);function Q(e){var t=e.cx,a=e.cy,n=e.x,o=e.y,l=e.fill,i=e.name,s="middle",c=0,u=0;return n<t-2?(c=-5,s="end"):n>t+2&&(c=5,s="start"),o<a-2?u=-5:o>a+2&&(u=10),r.a.createElement("text",{x:n,y:o,dx:c,dy:u,fill:l,textAnchor:s},"".concat(i))}var Z=Object(f.withStyles)(function(e){return{pieChart:{margin:"0 auto"}}})(function(e){return r.a.createElement(B.a,{container:!0,spacing:0},r.a.createElement(B.a,{item:!0,xs:12,lg:6},r.a.createElement("div",{className:e.classes.patternTableWrapper},r.a.createElement(K.a,{width:400,height:250,className:e.classes.pieChart},r.a.createElement(V.a,{data:e.patternGraphData,dataKey:"value",cx:200,cy:125,outerRadius:60,fill:J.a[300],label:Q}),r.a.createElement(X.a,{formatter:function(e){return"".concat(e.toFixed(2)," hr")}})))),r.a.createElement(B.a,{item:!0,xs:12,lg:6},r.a.createElement("div",{className:e.classes.patternTableWrapper},r.a.createElement(K.a,{width:400,height:250,className:e.classes.pieChart},r.a.createElement(V.a,{data:e.calendarGraphData,dataKey:"value",cx:200,cy:125,innerRadius:40,outerRadius:70,fill:v.a[300],label:Q},e.calendarGraphData.map(function(e,t){return r.a.createElement(Y.a,{key:t,fill:e.color})})),r.a.createElement(X.a,{formatter:function(e){return"".concat(e.toFixed(2)," hr")}})))))}),ee=a(136),te=a.n(ee),ae=a(301),ne=a.n(ae),re=a(303),oe=a.n(re),le=a(140),ie=a.n(le),se=a(100),ce=a.n(se),ue=a(302),me=a.n(ue),de=a(304),pe=a.n(de),he=a(300),fe=a.n(he),ge=a(131),ve=a.n(ge),Ee=a(172),ye=a.n(Ee),we=function(e){function t(){return Object(c.a)(this,t),Object(m.a)(this,Object(d.a)(t).apply(this,arguments))}return Object(p.a)(t,e),Object(u.a)(t,[{key:"render",value:function(){var e=this,t=this.props.classes,a=[],n=this.props.options,o=new U.emptyPattern;for(var l in n[o.id]=o,n){var i=n[l].isEmpty?r.a.createElement("span",{style:{color:this.props.theme.palette.primary.dark}},"Custom"):n[l].label;a.push(r.a.createElement(ye.a,{key:l,value:l},i))}var s=this.props.value.isRegex?t.fieldRegex:t.fieldNoRegex;return r.a.createElement(S.a,null,r.a.createElement("span",null,r.a.createElement(ve.a,{value:this.props.value.id,onChange:function(t){var a;a=null==n[t.target.value].label?new U(0,!0,e.props.value.isRegex?e.props.value.value:"^".concat(e.props.value.value,"$"),null):n[t.target.value],e.props.onChange({target:{value:a}})},className:s},a),null==this.props.value.label&&r.a.createElement(te.a,{value:this.props.value.value,onChange:function(t){return e.props.onChange({target:{value:new U(0,!0,t.target.value,null)}})}})))}}]),t}(r.a.Component),be=Object(f.withStyles)(function(e){return{fieldNoRegex:{width:200},fieldRegex:{marginRight:"0.5em"}}})(we);var Pe=a(139),xe=a.n(Pe),Ce=Object(f.createMuiTheme)({palette:{primary:{light:xe.a[300],main:xe.a[500],dark:xe.a[700],contrastText:"#fff"}},typography:{useNextVariants:!0}}),Oe=[{label:"Name",field:"name",elem:te.a},{label:"Calendar",field:"cal",elem:Object(f.withTheme)(Ce)(function(e){var t={};for(var a in e.calendars)t[a]=new U(a,!1,e.calendars[a].name,e.calendars[a].name);return r.a.createElement(be,{value:e.value,options:t,onChange:e.onChange,theme:e.theme})})},{label:"Event",field:"event",elem:Object(f.withTheme)(Ce)(function(e){var t=U.anyPattern(),a={};return a[t.id]=t,r.a.createElement(be,{value:e.value,options:a,onChange:e.onChange,theme:e.theme})})}],je=function(e){function t(){var e,a;Object(c.a)(this,t);for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(a=Object(m.a)(this,(e=Object(d.a)(t)).call.apply(e,[this].concat(r)))).state={page:0,rowsPerPage:5},a.handleChangePage=function(e,t){a.setState({page:t})},a.handleChangeRowsPerPage=function(e){a.setState({rowsPerPage:e.target.value})},a}return Object(p.a)(t,e),Object(u.a)(t,[{key:"render",value:function(){var e=this,t=this.props,a=t.classes,n=t.calendars,o=t.patterns,l=this.state,i=l.rowsPerPage,s=l.page,c=i-Math.min(i,o.length-s*i),u=o.slice(s*i,(s+1)*i).map(function(t){return r.a.createElement(ie.a,{onMouseOver:function(){return e.setState({activePattern:t.idx})},onMouseOut:function(){return e.setState({activePattern:null})}},Oe.map(function(a){var o=a.elem;return r.a.createElement(ce.a,null,r.a.createElement(o,{value:t[a.field],calendars:n,onChange:function(n){return e.props.onUpdatePattern(a.field,t.idx,n.target.value)}}))}),r.a.createElement("span",{className:e.state.activePattern===t.idx?a.deleteButtonShow:a.deleteButtonHide},r.a.createElement(fe.a,{className:a.deleteIcon,onClick:function(){return e.props.onRemovePattern(t.idx)}})))});return r.a.createElement("div",null,r.a.createElement("div",{className:a.patternTableWrapper},r.a.createElement(ne.a,{className:a.patternTable},r.a.createElement(me.a,null,r.a.createElement(ie.a,null,Oe.map(function(e,t){return r.a.createElement(ce.a,{key:t},e.label)}))),r.a.createElement(oe.a,null,u,c>0&&r.a.createElement(ie.a,{style:{height:48*c}},r.a.createElement(ce.a,{colSpan:Oe.length}))))),r.a.createElement(pe.a,{rowsPerPageOptions:[5,10,25],component:"div",count:o.length,rowsPerPage:i,page:s,backIconButtonProps:{"aria-label":"Previous Page"},nextIconButtonProps:{"aria-label":"Next Page"},onChangePage:this.handleChangePage,onChangeRowsPerPage:this.handleChangeRowsPerPage}))}}]),t}(r.a.Component),ke=Object(f.withStyles)(function(e){return{deleteButtonShow:{position:"absolute",right:0,height:48},deleteButtonHide:{display:"none"},deleteIcon:{height:"100%",cursor:"pointer"},patternTableWrapper:{overflowX:"auto",overflowY:"hidden"},patternTable:{minWidth:600}}})(je),De=[{name:"Work",value:10,color:v.a[300]},{name:"Wasted",value:10,color:v.a[300]}];var Se=function(e){function t(e){var a;Object(c.a)(this,t),(a=Object(m.a)(this,Object(d.a)(t).call(this,e))).state={patterns:[],calendars:[],timeRange:null,token:z(),patternGraphData:De,calendarGraphData:De,activePattern:null},a.updatePattern=function(e,t,n){var r=a.state.patterns;r[t][e]=n,a.setState({patterns:r}),a.sendMsg({type:0,data:r})},a.removePattern=function(e){var t=a.state.patterns;t.splice(e,1);for(var n=0;n<t.length;n++)t[n].idx=n;a.setState({patterns:t}),a.sendMsg({type:0,data:t})},a.newPattern=function(){for(var e=[$.defaultPatternEntry(0)].concat(Object(s.a)(a.state.patterns)),t=1;t<e.length;t++)e[t].idx=t;a.setState({patterns:e}),a.sendMsg({type:0,data:e})},a.loadPatterns=function(e){a.setState({patterns:e}),a.sendMsg({type:0,data:e})},a.loadCalendars=function(e){a.setState({calendars:e}),a.sendMsg({type:5,data:e})},a.sendMsg=function(e){a.requestCallback.hasOwnProperty(e.type)||(a.requestCallback[e.type]={inFlight:{},ids:[],maxId:0});var t,n,r=a.requestCallback[e.type],o=new Promise(function(e){t=e});return n=r.ids.length>0?r.ids.pop():r.maxId++,r.inFlight[n]=t,e.id=n,a.port.postMessage(e),o},a.getCalEvents=function(e,t,n){return a.sendMsg({type:4,data:{id:e,start:t.getTime(),end:n.getTime()}}).then(function(e){return e.data.map(function(e){return{id:e.id,start:new Date(e.start),end:new Date(e.end)}})})},a.analyze=function(){if(a.state.startDate&&a.state.endDate){var e=a.state.startDate.startOf("day").toDate(),t=a.state.endDate.startOf("day").toDate(),n=[],r=a.state.calendars,o=function(r){n.push(a.getCalEvents(r,e,t).then(function(e){return{id:r,events:e}}))};for(var l in r)o(l);console.log(r),Promise.all(n).then(function(e){console.log(e);var t={},n={},o={};e.forEach(function(e){return t[e.id]=e.events});for(var l=0;l<a.state.patterns.length;l++)n[l]=0;var i=function(e){if(!t[e])return"continue";var l=function(e,t){return e.filter(function(e){return e.cal.regex.test(t)})}(a.state.patterns,r[e].name);t[e].forEach(function(t){l.forEach(function(a){if(a.event.regex.test(t.summary)){o.hasOwnProperty(e)||(o[e]=0);var r=(t.end-t.start)/6e4;n[a.idx]+=r,o[e]+=r}})})};for(var s in r)i(s);for(var c=[],u=[],m=0;m<a.state.patterns.length;m++)c.push({name:a.state.patterns[m].name,value:n[m]/60});for(var s in o)u.push({name:r[s].name,value:o[s]/60,color:r[s].color.background});console.log(c,u),a.setState({patternGraphData:c,calendarGraphData:u})})}else alert("Please choose a valid time range.")},a.load=function(){var e=a.state.token,t=e.then(L).then(function(e){return e.calendar}),n=e.then(_);Promise.all([t,n]).then(function(e){var t=Object(i.a)(e,2),n=t[0],r=t[1],o={};r.forEach(function(e){o[e.id]={name:e.summary,color:n[e.colorId]}}),a.loadCalendars(o),a.loadPatterns(r.map(function(e,t){return new $(e.summary,t,new U(e.id,!1,e.summary,e.summary),U.anyPattern())}))})};var n=chrome.runtime.connect({name:"main"});return n.onMessage.addListener(function(e){console.log(e);var t=function(e){return a.requestCallback[e]}(e.type),n=t.inFlight[e.id];console.assert(void 0!==n),t.ids.push(e.id),n(e)}),a.port=n,a.requestCallback={},a.sendMsg({type:1}).then(function(e){a.setState({patterns:e.data.map(function(e){return $.revive(e)})})}),a.sendMsg({type:3}).then(function(e){a.setState({calendars:e.data})}),a}return Object(p.a)(t,e),Object(u.a)(t,[{key:"render",value:function(){var e=this,t=this.props.classes;return r.a.createElement(f.MuiThemeProvider,{theme:Ce},r.a.createElement("div",{className:t.root},r.a.createElement(b.a,{position:"absolute",className:t.appBar},r.a.createElement(x.a,{className:t.toolbar},r.a.createElement(O.a,{component:"h1",variant:"h6",color:"inherit",noWrap:!0,className:t.title},r.a.createElement(F,{style:{width:"2em",verticalAlign:"bottom",marginRight:"0.2em"}}),"Chromicle"))),r.a.createElement("main",{className:t.content},r.a.createElement("div",{className:t.appBarSpacer}),r.a.createElement(B.a,{container:!0,spacing:16},r.a.createElement(y.a,null),r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(S.a,{fullWidth:!0},r.a.createElement(N.a,null,r.a.createElement(O.a,{variant:"h6",component:"h1",gutterBottom:!0},"Event Patterns",r.a.createElement(W.a,{style:{marginBottom:"0.12em",marginLeft:"0.5em"},onClick:function(){return e.newPattern()}},r.a.createElement(M.a,null))),r.a.createElement(ke,{patterns:this.state.patterns,calendars:this.state.calendars,onRemovePattern:this.removePattern,onUpdatePattern:this.updatePattern})),r.a.createElement(N.a,null,r.a.createElement(O.a,{variant:"h6",component:"h1",gutterBottom:!0},"Time Range"),r.a.createElement("div",{style:{textAlign:"center"}},r.a.createElement(h.DateRangePicker,{startDate:this.state.startDate,startDateId:"start_date_id",endDate:this.state.endDate,endDateId:"end_date_id",onDatesChange:function(t){var a=t.startDate,n=t.endDate;e.setState({startDate:a,endDate:n})},focusedInput:this.state.focusedInput,onFocusChange:function(t){return e.setState({focusedInput:t})},isOutsideRange:function(){return!1}}))),r.a.createElement("div",{className:t.buttonSpacer}),r.a.createElement(B.a,{container:!0,spacing:16},r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(N.a,null,r.a.createElement(k.a,{variant:"contained",color:"primary",onClick:this.load},"Load"))),r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(N.a,null,r.a.createElement(k.a,{variant:"contained",color:"primary",onClick:this.analyze},"Analyze")))))),r.a.createElement(B.a,{item:!0,md:6,xs:12},r.a.createElement(O.a,{variant:"h6",component:"h1",gutterBottom:!0},"Graph"),r.a.createElement(Z,{patternGraphData:this.state.patternGraphData,calendarGraphData:this.state.calendarGraphData}))))))}}]),t}(r.a.Component),Re=Object(f.withStyles)(function(e){return{root:{display:"flex",height:"100vh"},appBar:{zIndex:e.zIndex.drawer+1,transition:e.transitions.create(["width","margin"],{easing:e.transitions.easing.sharp,duration:e.transitions.duration.leavingScreen})},title:{flexGrow:1},sectionTitle:{flex:"0 0 auto"},appBarSpacer:e.mixins.toolbar,content:{flexGrow:1,padding:3*e.spacing.unit,overflow:"auto"},buttonSpacer:{marginBottom:4*e.spacing.unit},fab:{margin:e.spacing.unit}}})(Se);Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));l.a.render(r.a.createElement(Re,null),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then(function(e){e.unregister()})}},[[308,2,1]]]);
+//# sourceMappingURL=main.9e0b7c77.chunk.js.map \ No newline at end of file
diff --git a/build/static/js/main.9e0b7c77.chunk.js.map b/build/static/js/main.9e0b7c77.chunk.js.map
new file mode 100644
index 0000000..1cd76bc
--- /dev/null
+++ b/build/static/js/main.9e0b7c77.chunk.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["Logo.js","gapi.js","pattern.js","Chart.js","RegexField.js","theme.js","PatternTable.js","App.js","serviceWorker.js","index.js"],"names":["Logo","props","react_default","a","createElement","xmlns","viewBox","version","style","id","transform","points","fill","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontFamily","gapi_base","to_params","dict","Object","entries","map","_ref","_ref2","slicedToArray","k","v","concat","encodeURIComponent","join","getAuthToken","Promise","resolver","chrome","identity","interactive","token","getCalendars","fetch","access_token","method","async","then","response","json","data","items","getColors","Pattern","isRegex","value","label","classCallCheck","this","createClass","key","get","RegExp","emptyPattern","anyPattern","revive","obj","PatternEntry","name","idx","calPattern","eventPattern","cal","event","defaultPatternEntry","customizedLabel","cx","cy","x","y","anchor","dx","dy","textAnchor","withStyles","theme","pieChart","margin","Grid_default","container","spacing","item","xs","lg","className","classes","patternTableWrapper","PieChart","width","height","Pie","patternGraphData","dataKey","outerRadius","deepOrange","Tooltip","formatter","toFixed","calendarGraphData","innerRadius","cyan","d","i","Cell","color","RegexField","_this","pitems","options","p0","isEmpty","palette","primary","dark","push","MenuItem_default","fieldRegex","fieldNoRegex","FormControl_default","Select_default","onChange","target","TextField_default","React","Component","RegexFieldWithStyles","marginRight","createMuiTheme","light","orange","main","contrastText","typography","useNextVariants","patternHead","field","elem","TextField","withTheme","calendars","any","PatternTable","state","page","rowsPerPage","handleChangePage","setState","handleChangeRowsPerPage","_this2","_this$props","patterns","_this$state","nDummy","Math","min","length","rows","slice","p","TableRow_default","onMouseOver","activePattern","onMouseOut","s","CustomText","TableCell_default","onUpdatePattern","deleteButtonShow","deleteButtonHide","DeleteOutlined_default","deleteIcon","onClick","onRemovePattern","Table_default","patternTable","TableHead_default","TableBody_default","colSpan","TablePagination_default","rowsPerPageOptions","component","count","backIconButtonProps","aria-label","nextIconButtonProps","onChangePage","onChangeRowsPerPage","position","right","display","cursor","overflowX","overflowY","minWidth","default_chart_data","Dashboard","possibleConstructorReturn","getPrototypeOf","call","timeRange","gapi","updatePattern","sendMsg","type","removePattern","splice","newPattern","toConsumableArray","loadPatterns","loadCalendars","msg","requestCallback","hasOwnProperty","inFlight","ids","maxId","cb","t","pm","resolve","pop","port","postMessage","getCalEvents","start","end","getTime","e","Date","analyze","startDate","endDate","startOf","toDate","event_pms","cals","_loop","r","events","console","log","all","all_events","results","cal_results","forEach","_loop2","calName","filter","regex","test","filterPatterns","summary","duration","background","alert","load","colors","calendar","_ref3","colorId","runtime","connect","onMessage","addListener","getCallBack","assert","undefined","styles","root","AppBar_default","appBar","Toolbar_default","toolbar","Typography_default","variant","noWrap","title","verticalAlign","content","appBarSpacer","CssBaseline_default","md","fullWidth","FormGroup_default","gutterBottom","IconButton_default","marginBottom","marginLeft","AddCircle_default","src_PatternTable","textAlign","react_dates","startDateId","endDateId","onDatesChange","_ref4","focusedInput","onFocusChange","isOutsideRange","buttonSpacer","Button_default","Chart","zIndex","drawer","transition","transitions","create","easing","sharp","leavingScreen","flexGrow","sectionTitle","flex","mixins","padding","unit","overflow","fab","Boolean","window","location","hostname","match","ReactDOM","render","App","document","getElementById","navigator","serviceWorker","ready","registration","unregister"],"mappings":"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","file":"static/js/main.9e0b7c77.chunk.js","sourcesContent":["import React from 'react';\nexport default (props) =>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 98.905998 93.557997\"\n version=\"1.1\"\n style={props.style}>\n <g id=\"g13\"\n transform=\"translate(-153.533,-203.047)\">\n <g id=\"g29\">\n <g\n id=\"g27\">\n <polygon\n id=\"polygon7\"\n points=\"252.439,241.924 234.556,288.703 185.103,296.605 153.533,257.728 171.416,210.949 220.869,203.047 \"\n style={{fill: '#ff8000'}} />\n <g\n id=\"g11\"\n transform=\"translate(167.24355,224.20734)\">\n <text\n id=\"text9\"\n style={{fontStyle:'normal',\n fontVariant:'normal',\n fontWeight:'normal',\n fontStretch:'normal',\n fontSize:75,\n fontFamily:'TypoPRO Fantasque Sans Mono',\n fill:'#ffeade'}}\n transform=\"translate(0.586,49.072)\">Cr</text>\n </g>\n </g>\n </g>\n </g>\n </svg>\n","/* global chrome */\nconst gapi_base = 'https://www.googleapis.com/calendar/v3';\n\nconst GApiError = {\n invalidSyncToken: 1,\n otherError: 2,\n};\n\nfunction to_params(dict) {\n return Object.entries(dict).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&');\n}\n\nexport function getAuthToken() {\n return new Promise(resolver =>\n chrome.identity.getAuthToken(\n {interactive: true}, token => resolver(token)));\n}\n\nexport function getCalendars(token) {\n return fetch(`${gapi_base}/users/me/calendarList?${to_params({access_token: token})}`,\n { method: 'GET', async: true })\n .then(response => response.json())\n .then(data => data.items);\n}\n\nexport function getColors(token) {\n return fetch(`${gapi_base}/colors?${to_params({access_token: token})}`,\n { method: 'GET', async: true })\n .then(response => response.json());\n}\n\nfunction getEvent(calId, eventId, token) {\n return fetch(`${gapi_base}/calendars/${calId}/events/${eventId}?${to_params({access_token: token})}`,\n { method: 'GET', async: true })\n .then(response => response.json());\n}\n\nfunction getEvents(calId, token, syncToken, resultsPerRequest=100) {\n let results = [];\n const singleFetch = (pageToken, syncToken) => fetch(`${gapi_base}/calendars/${calId}/events?${to_params({\n access_token: token,\n pageToken,\n syncToken,\n maxResults: resultsPerRequest\n })}`, { method: 'GET', async: true })\n .then(response => {\n if (response.status === 200)\n return response.json();\n else if (response.status === 410)\n throw GApiError.invalidSyncToken;\n else throw GApiError.otherErrors;\n })\n .then(data => {\n results.push(...data.items);\n if (data.nextPageToken) {\n return singleFetch(data.nextPageToken, '');\n } else {\n return ({\n nextSyncToken: data.nextSyncToken,\n results\n });\n }\n })\n\n return singleFetch('', syncToken);\n}\n\nexport class GCalendar {\n constructor(calId, name) {\n this.calId = calId;\n this.name = name;\n this.token = getAuthToken();\n this.syncToken = '';\n this.cache = {};\n }\n\n static dateToCacheKey(date) {\n return Math.floor(date / 8.64e7);\n }\n\n getSlot(k) {\n if (!this.cache[k])\n this.cache[k] = {};\n return this.cache[k];\n }\n\n static slotStartDate(k) { return new Date(k * 8.64e7); }\n static slotEndDate(k) { return new Date((k + 1) * 8.64e7); }\n\n addEvent(e) {\n let ks = GCalendar.dateToCacheKey(e.start);\n let ke = GCalendar.dateToCacheKey(new Date(e.end.getTime() - 1));\n if (ks === ke)\n this.getSlot(ks)[e.id] = {\n start: e.start,\n end: e.end,\n id: e.id,\n summary: e.summary};\n else\n {\n this.getSlot(ks)[e.id] = {\n start: e.start,\n end: GCalendar.slotEndDate(ks),\n id: e.id,\n summary: e.summary};\n this.getSlot(ke)[e.id] = {\n start: GCalendar.slotStartDate(ke),\n end: e.end,\n id: e.id,\n summary: e.summary};\n for (let k = ks + 1; k < ke; k++)\n this.getSlot(k)[e.id] = {\n start: GCalendar.slotStartDate(k),\n end: GCalendar.slotEndDate(k),\n id: e.id,\n summary: e.summary};\n }\n }\n\n removeEvent(e) {\n let ks = GCalendar.dateToCacheKey(e.start);\n let ke = GCalendar.dateToCacheKey(new Date(e.end.getTime() - 1));\n for (let k = ks; k <= ke; k++)\n delete this.getSlot(k)[e.id];\n }\n\n getSlotEvents(k, start, end) {\n let s = this.getSlot(k);\n let results = [];\n for (let id in s) {\n if (!(s[id].start >= end || s[id].end <= start))\n {\n results.push({\n id,\n start: s[id].start < start ? start: s[id].start,\n end: s[id].end > end ? end: s[id].end,\n summary: s[id].summary\n });\n }\n }\n return results;\n }\n\n getCachedEvents(start, end) {\n let ks = GCalendar.dateToCacheKey(start);\n let ke = GCalendar.dateToCacheKey(new Date(end.getTime() - 1));\n let results = this.getSlotEvents(ks, start, end);\n for (let k = ks + 1; k < ke; k++)\n {\n let s = this.getSlot(k);\n for (let id in s)\n results.push(s[id]);\n }\n if (ke > ks)\n results.push(...this.getSlotEvents(ke, start, end));\n return results;\n }\n\n sync() {\n return this.token.then(token => getEvents(this.calId, token, this.syncToken).then(r => {\n this.syncToken = r.nextSyncToken;\n let pm_results = r.results.map(e => e.start ? Promise.resolve(e) : getEvent(this.calId, e.id, token));\n return Promise.all(pm_results).then(results => results.forEach(e => {\n e.start = new Date(e.start.dateTime);\n e.end = new Date(e.end.dateTime);\n if (e.status === 'confirmed')\n this.addEvent(e);\n else if (e.status === 'cancelled')\n this.removeEvent(e);\n }));\n })).catch(e => {\n if (e === GApiError.invalidSyncToken) {\n this.syncToken = '';\n this.sync();\n } else throw e;\n });\n }\n\n getEvents(start, end) {\n return this.sync().then(() => this.getCachedEvents(start, end));\n }\n}\n","export class Pattern {\n constructor(id, isRegex, value, label) {\n this.id = id;\n this.isRegex = isRegex;\n this.value = value;\n this.label = label;\n }\n\n get regex() { return new RegExp(this.isRegex ? this.value : `^${this.value}$`); }\n get isEmpty() { return this.label === null; }\n static emptyPattern = () => new Pattern(0, true, '', null);\n static anyPattern = () => new Pattern('any', true, '.*', 'Any');\n static revive = obj => new Pattern(obj.id, obj.isRegex, obj.value, obj.label);\n}\n\nexport class PatternEntry {\n constructor(name, idx, calPattern, eventPattern) {\n this.name = name;\n this.idx = idx;\n this.cal = calPattern;\n this.event = eventPattern;\n }\n\n static defaultPatternEntry = (idx) => new PatternEntry('', idx, Pattern.emptyPattern(), Pattern.anyPattern());\n static revive = obj => new PatternEntry(\n obj.name, obj.idx,\n Pattern.revive(obj.cal), Pattern.revive(obj.event));\n}\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles } from '@material-ui/core/styles';\nimport Grid from '@material-ui/core/Grid';\nimport deepOrange from '@material-ui/core/colors/deepOrange';\nimport cyan from '@material-ui/core/colors/cyan';\nimport { PieChart, Pie, Cell, Tooltip } from 'recharts';\n\nconst styles = theme => ({\n pieChart: {\n margin: '0 auto',\n }\n});\n\nfunction customizedLabel(props) {\n const {cx, cy, x, y, fill, name} = props;\n let anchor = \"middle\";\n const EPS = 2;\n let dx = 0;\n let dy = 0;\n if (x < cx - EPS) {\n dx = -5;\n anchor = \"end\"\n } else if (x > cx + EPS) {\n dx = 5;\n anchor = \"start\";\n }\n\n if (y < cy - EPS) {\n dy = -5;\n } else if (y > cy + EPS) {\n dy = 10;\n }\n\n return (<text x={x} y={y} dx={dx} dy={dy} fill={fill} textAnchor={anchor}>{`${name}`}</text>);\n}\n\nfunction ChromiclePieChart(props) {\n return (\n <Grid container spacing={0}>\n <Grid item xs={12} lg={6}>\n <div className={props.classes.patternTableWrapper}>\n <PieChart width={400} height={250} className={props.classes.pieChart}>\n <Pie data={props.patternGraphData}\n dataKey='value'\n cx={200}\n cy={125}\n outerRadius={60}\n fill={deepOrange[300]}\n label={customizedLabel}/>\n <Tooltip formatter={(value) => `${value.toFixed(2)} hr`}/>\n </PieChart>\n </div>\n </Grid>\n <Grid item xs={12} lg={6}>\n <div className={props.classes.patternTableWrapper}>\n <PieChart width={400} height={250} className={props.classes.pieChart}>\n <Pie data={props.calendarGraphData}\n dataKey='value'\n cx={200}\n cy={125}\n innerRadius={40}\n outerRadius={70}\n fill={cyan[300]}\n label={customizedLabel}>\n {props.calendarGraphData.map((d, i) => <Cell key={i} fill={d.color}/>)}\n </Pie>\n <Tooltip formatter={(value) => `${value.toFixed(2)} hr`}/>\n </PieChart>\n </div>\n </Grid>\n </Grid>);\n}\n\nChromiclePieChart.propTypes = {\n patternGraphData: PropTypes.array.isRequired,\n calendarGraphData: PropTypes.array.isRequired,\n};\n\nexport default withStyles(styles)(ChromiclePieChart);\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles } from '@material-ui/core/styles';\nimport Select from '@material-ui/core/Select';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport TextField from '@material-ui/core/TextField';\nimport FormControl from '@material-ui/core/FormControl';\nimport { Pattern } from './pattern';\n\nconst styles = theme => ({\n fieldNoRegex: {\n width: 200\n },\n fieldRegex: {\n marginRight: '0.5em'\n }\n});\n\nclass RegexField extends React.Component {\n render() {\n const { classes } = this.props;\n let items = [];\n var pitems = this.props.options;\n const p0 = new Pattern.emptyPattern();\n pitems[p0.id] = p0;\n for (let id in pitems)\n {\n const label = !pitems[id].isEmpty ? pitems[id].label :\n <span style={{color: this.props.theme.palette.primary.dark}}>Custom</span>;\n items.push(<MenuItem key={id} value={id}>{label}</MenuItem>);\n }\n const selectOnClick = event => {\n let value;\n if (pitems[event.target.value].label == null) {\n value = new Pattern(0, true,\n this.props.value.isRegex ?\n this.props.value.value :\n `^${this.props.value.value}$`, null);\n } else {\n value = pitems[event.target.value];\n }\n this.props.onChange({target: {value}});\n };\n\n const regexTextOnChange = event => this.props.onChange({\n target: { value: new Pattern(0, true, event.target.value, null)}});\n\n const className = this.props.value.isRegex ? classes.fieldRegex: classes.fieldNoRegex;\n return (\n <FormControl>\n <span>\n <Select\n value={this.props.value.id}\n onChange={selectOnClick}\n className={className}>{items}\n </Select>\n {this.props.value.label == null && (\n <TextField\n value={this.props.value.value}\n onChange={regexTextOnChange} />\n )}\n </span>\n </FormControl>);\n }\n}\n\nRegexField.propTypes = {\n classes: PropTypes.object.isRequired,\n};\n\nconst RegexFieldWithStyles = withStyles(styles)(RegexField);\n\nexport function CalendarField(props) {\n let options = {};\n for (let id in props.calendars) {\n options[id] = new Pattern(id, false,\n props.calendars[id].name,\n props.calendars[id].name);\n }\n return (\n <RegexFieldWithStyles\n value={props.value}\n options={options}\n onChange={props.onChange}\n theme={props.theme} />);\n}\n\nexport function EventField(props) {\n let any = Pattern.anyPattern();\n let options = {};\n options[any.id] = any;\n return (\n <RegexFieldWithStyles\n value={props.value}\n options={options}\n onChange={props.onChange}\n theme={props.theme} />);\n}\n","import { createMuiTheme } from '@material-ui/core/styles';\nimport orange from '@material-ui/core/colors/orange';\n\nconst theme = createMuiTheme({\n palette: {\n primary: {\n light: orange[300],\n main: orange[500],\n dark: orange[700],\n contrastText: \"#fff\"\n }\n },\n typography: {\n useNextVariants: true,\n }\n});\n\nexport default theme;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles, withTheme } from '@material-ui/core/styles';\nimport TextField from '@material-ui/core/TextField';\nimport Table from '@material-ui/core/Table';\nimport TableBody from '@material-ui/core/TableBody';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableHead from '@material-ui/core/TableHead';\nimport TablePagination from '@material-ui/core/TablePagination';\nimport DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined';\nimport { CalendarField, EventField } from './RegexField';\nimport theme from './theme';\n\nconst styles = theme => ({\n deleteButtonShow: {\n position: 'absolute',\n right: 0,\n height: 48\n },\n deleteButtonHide: {\n display: 'none'\n },\n deleteIcon: {\n height: '100%',\n cursor: 'pointer'\n },\n patternTableWrapper: {\n overflowX: 'auto',\n overflowY: 'hidden'\n },\n patternTable: {\n minWidth: 600\n }\n});\n\nconst patternHead = [\n {label: \"Name\", field: \"name\", elem: TextField},\n {label: \"Calendar\", field: \"cal\", elem: withTheme(theme)(CalendarField)},\n {label: \"Event\", field: 'event', elem: withTheme(theme)(EventField)}];\n\nclass PatternTable extends React.Component {\n state = {\n page: 0,\n rowsPerPage: 5,\n };\n\n handleChangePage = (event, page) => {\n this.setState({ page });\n }\n\n handleChangeRowsPerPage = event => {\n this.setState({ rowsPerPage: event.target.value });\n }\n\n render() {\n const { classes, calendars, patterns } = this.props;\n const { rowsPerPage, page } = this.state;\n const nDummy = rowsPerPage - Math.min(rowsPerPage, patterns.length - page * rowsPerPage);\n let rows = patterns.slice(page * rowsPerPage, (page + 1) * rowsPerPage).map(p => (\n <TableRow\n onMouseOver={() => this.setState({ activePattern: p.idx })}\n onMouseOut={() => this.setState({ activePattern: null })}>\n {\n patternHead.map(s => {\n const CustomText = s.elem;\n return (\n <TableCell>\n <CustomText\n value={p[s.field]}\n calendars={calendars}\n onChange={event => this.props.onUpdatePattern(s.field, p.idx, event.target.value)}/>\n </TableCell>)})\n }\n <span className={this.state.activePattern === p.idx ? classes.deleteButtonShow : classes.deleteButtonHide}>\n <DeleteOutlinedIcon\n className={classes.deleteIcon}\n onClick={() => this.props.onRemovePattern(p.idx)} />\n </span>\n </TableRow>));\n\n return (\n <div>\n <div className={classes.patternTableWrapper}>\n <Table className={classes.patternTable}>\n <TableHead>\n <TableRow>{patternHead.map((s, i) => (<TableCell key={i}>{s.label}</TableCell>))}</TableRow>\n </TableHead>\n <TableBody>\n {rows}\n {\n nDummy > 0 && (\n <TableRow style={{ height: 48 * nDummy }}>\n <TableCell colSpan={patternHead.length} />\n </TableRow>)\n }\n </TableBody>\n </Table>\n </div>\n <TablePagination\n rowsPerPageOptions={[5, 10, 25]}\n component=\"div\"\n count={patterns.length}\n rowsPerPage={rowsPerPage}\n page={page}\n backIconButtonProps={{'aria-label': 'Previous Page'}}\n nextIconButtonProps={{'aria-label': 'Next Page'}}\n onChangePage={this.handleChangePage}\n onChangeRowsPerPage={this.handleChangeRowsPerPage} />\n </div>);\n }\n}\n\n\nPatternTable.propTypes = {\n classes: PropTypes.object.isRequired,\n patterns: PropTypes.array.isRequired,\n calendars: PropTypes.object.isRequired,\n onRemovePattern: PropTypes.func.isRequired,\n onUpdatePattern: PropTypes.func.isRequired,\n};\n\nexport default withStyles(styles)(PatternTable);\n","/* global chrome */\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport 'typeface-roboto';\nimport 'react-dates/initialize';\nimport 'react-dates/lib/css/_datepicker.css';\nimport { DateRangePicker } from 'react-dates';\nimport { withStyles } from '@material-ui/core/styles';\nimport { MuiThemeProvider } from '@material-ui/core/styles';\nimport cyan from '@material-ui/core/colors/cyan';\nimport CssBaseline from '@material-ui/core/CssBaseline';\nimport AppBar from '@material-ui/core/AppBar';\nimport Toolbar from '@material-ui/core/Toolbar';\nimport Typography from '@material-ui/core/Typography';\nimport Button from '@material-ui/core/Button';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport Grid from '@material-ui/core/Grid';\nimport AddCircleIcon from '@material-ui/icons/AddCircle';\nimport IconButton from '@material-ui/core/IconButton';\nimport Logo from './Logo';\nimport * as gapi from './gapi';\nimport { Pattern, PatternEntry } from './pattern';\nimport PieChart from './Chart';\nimport PatternTable from './PatternTable';\nimport theme from './theme';\n\nconst default_chart_data = [\n {name: 'Work', value: 10, color: cyan[300]},\n {name: 'Wasted', value: 10, color: cyan[300]}];\n\nfunction filterPatterns(patterns, calName) {\n return patterns.filter(p => {\n return p.cal.regex.test(calName);\n });\n}\n\nconst styles = theme => ({\n root: {\n display: 'flex',\n height: '100vh',\n },\n appBar: {\n zIndex: theme.zIndex.drawer + 1,\n transition: theme.transitions.create(['width', 'margin'], {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.leavingScreen,\n }),\n },\n title: {\n flexGrow: 1,\n },\n sectionTitle: {\n flex: '0 0 auto'\n },\n appBarSpacer: theme.mixins.toolbar,\n content: {\n flexGrow: 1,\n padding: theme.spacing.unit * 3,\n overflow: 'auto',\n },\n buttonSpacer: {\n marginBottom: theme.spacing.unit * 4,\n },\n fab: {\n margin: theme.spacing.unit,\n },\n});\n\nclass Dashboard extends React.Component {\n state = {\n patterns: [],\n calendars: [],\n timeRange: null,\n token: gapi.getAuthToken(),\n patternGraphData: default_chart_data,\n calendarGraphData: default_chart_data,\n activePattern: null\n };\n\n constructor(props) {\n super(props);\n let port = chrome.runtime.connect({name: 'main'});\n const getCallBack = t => this.requestCallback[t];\n port.onMessage.addListener(function(msg) {\n console.log(msg);\n let t = getCallBack(msg.type);\n let e = t.inFlight[msg.id];\n console.assert(e !== undefined);\n t.ids.push(msg.id);\n e(msg);\n });\n this.port = port;\n this.requestCallback = {};\n this.sendMsg({ type: 1 }).then(msg => {\n this.setState({ patterns: msg.data.map(p => PatternEntry.revive(p)) });\n });\n this.sendMsg({ type: 3 }).then(msg => {\n this.setState({ calendars: msg.data });\n });\n }\n\n updatePattern = (field, idx, value) => {\n let patterns = this.state.patterns;\n patterns[idx][field] = value;\n this.setState({ patterns });\n this.sendMsg({ type: 0, data: patterns });\n };\n\n removePattern = idx => {\n let patterns = this.state.patterns;\n patterns.splice(idx, 1);\n for (let i = 0; i < patterns.length; i++)\n patterns[i].idx = i;\n this.setState({ patterns });\n this.sendMsg({ type: 0, data: patterns });\n };\n\n newPattern = () => {\n let patterns = [PatternEntry.defaultPatternEntry(0), ...this.state.patterns];\n for (let i = 1; i < patterns.length; i++)\n patterns[i].idx = i;\n this.setState({ patterns });\n this.sendMsg({ type: 0, data: patterns });\n };\n\n loadPatterns = patterns => {\n this.setState({ patterns });\n this.sendMsg({ type: 0, data: patterns });\n };\n\n loadCalendars = calendars => {\n this.setState({ calendars });\n this.sendMsg({ type: 5, data: calendars });\n };\n\n sendMsg = msg => {\n if (!this.requestCallback.hasOwnProperty(msg.type))\n this.requestCallback[msg.type] = {inFlight: {}, ids: [], maxId: 0};\n let t = this.requestCallback[msg.type];\n let cb;\n let pm = new Promise(resolve => { cb = resolve; });\n let id;\n if (t.ids.length > 0) {\n id = t.ids.pop();\n } else {\n id = t.maxId++;\n }\n t.inFlight[id] = cb;\n msg.id = id;\n this.port.postMessage(msg);\n return pm;\n }\n\n getCalEvents = (id, start, end) => {\n return this.sendMsg({ type: 4, data: { id,\n start: start.getTime(),\n end: end.getTime() } })\n .then(({ data }) => data.map(e => {\n return {\n id: e.id,\n start: new Date(e.start),\n end: new Date(e.end) }\n }));\n }\n\n analyze = () => {\n if (!(this.state.startDate && this.state.endDate)) {\n alert(\"Please choose a valid time range.\");\n return;\n }\n let start = this.state.startDate.startOf('day').toDate();\n let end = this.state.endDate.startOf('day').toDate();\n let event_pms = [];\n let cals = this.state.calendars;\n for (let id in cals)\n event_pms.push(this.getCalEvents(id, start, end)\n .then(r => { return { id, events: r }; }));\n console.log(cals);\n Promise.all(event_pms).then(all_events => {\n console.log(all_events);\n let events = {};\n let results = {}; // pattern idx => time\n let cal_results = {}; // cal id => time\n all_events.forEach(e => events[e.id] = e.events);\n for (let i = 0; i < this.state.patterns.length; i++)\n results[i] = 0;\n for (let id in cals) {\n if (!events[id]) continue;\n let patterns = filterPatterns(this.state.patterns, cals[id].name);\n events[id].forEach(event => {\n patterns.forEach(p => {\n if (!p.event.regex.test(event.summary)) return;\n if (!cal_results.hasOwnProperty(id)) {\n cal_results[id] = 0;\n }\n let duration = (event.end - event.start) / 60000;\n results[p.idx] += duration;\n cal_results[id] += duration;\n });\n });\n }\n let patternGraphData = [];\n let calendarGraphData = [];\n for (let i = 0; i < this.state.patterns.length; i++) {\n patternGraphData.push({ name: this.state.patterns[i].name, value: results[i] / 60.0 });\n }\n for (let id in cal_results) {\n calendarGraphData.push({\n name: cals[id].name,\n value: (cal_results[id] / 60.0),\n color: cals[id].color.background});\n }\n console.log(patternGraphData, calendarGraphData);\n this.setState({ patternGraphData, calendarGraphData });\n });\n };\n\n load = () => {\n let token = this.state.token;\n let colors = token.then(gapi.getColors).then(color => {\n return color.calendar;\n });\n let cals = token.then(gapi.getCalendars);\n Promise.all([colors, cals]).then(([colors, items]) => {\n var cals = {};\n items.forEach(item => {\n cals[item.id] = {\n name: item.summary,\n color: colors[item.colorId],\n //cal: new gapi.GCalendar(item.id, item.summary)\n }});\n this.loadCalendars(cals);\n this.loadPatterns(items.map((item, idx) => {\n return new PatternEntry(item.summary, idx,\n new Pattern(item.id, false, item.summary, item.summary),\n Pattern.anyPattern());\n }));\n });\n };\n\n render() {\n const { classes } = this.props;\n\n return (\n <MuiThemeProvider theme={theme}>\n <div className={classes.root}>\n <AppBar\n position=\"absolute\"\n className={classes.appBar}>\n <Toolbar className={classes.toolbar}>\n <Typography component=\"h1\" variant=\"h6\" color=\"inherit\" noWrap className={classes.title}>\n <Logo style={{width: '2em', verticalAlign: 'bottom', marginRight: '0.2em'}}/>Chromicle\n </Typography>\n </Toolbar>\n </AppBar>\n <main className={classes.content}>\n <div className={classes.appBarSpacer} />\n <Grid container spacing={16}>\n <CssBaseline />\n <Grid item md={6} xs={12}>\n <FormControl fullWidth={true}>\n <FormGroup>\n <Typography variant=\"h6\" component=\"h1\" gutterBottom>\n Event Patterns\n <IconButton\n style={{marginBottom: '0.12em', marginLeft: '0.5em'}}\n onClick={() => this.newPattern()}><AddCircleIcon /></IconButton>\n </Typography>\n <PatternTable\n patterns={this.state.patterns}\n calendars={this.state.calendars}\n onRemovePattern={this.removePattern}\n onUpdatePattern={this.updatePattern} />\n </FormGroup>\n <FormGroup>\n <Typography variant=\"h6\" component=\"h1\" gutterBottom>\n Time Range\n </Typography>\n <div style={{textAlign: 'center'}}>\n <DateRangePicker\n startDate={this.state.startDate}\n startDateId=\"start_date_id\"\n endDate={this.state.endDate}\n endDateId=\"end_date_id\"\n onDatesChange={({ startDate, endDate }) => {\n this.setState({ startDate, endDate });\n }} \n focusedInput={this.state.focusedInput}\n onFocusChange={focusedInput => this.setState({ focusedInput })}\n isOutsideRange={() => false}/>\n </div>\n </FormGroup>\n <div className={classes.buttonSpacer} />\n <Grid container spacing={16}>\n <Grid item md={6} xs={12}>\n <FormGroup>\n <Button variant=\"contained\" color=\"primary\" onClick={this.load}>Load</Button>\n </FormGroup>\n </Grid>\n <Grid item md={6} xs={12}>\n <FormGroup>\n <Button variant=\"contained\" color=\"primary\" onClick={this.analyze}>Analyze</Button>\n </FormGroup>\n </Grid>\n </Grid>\n </FormControl>\n </Grid>\n <Grid item md={6} xs={12}>\n <Typography variant=\"h6\" component=\"h1\" gutterBottom>\n Graph\n </Typography>\n <PieChart\n patternGraphData={this.state.patternGraphData}\n calendarGraphData={this.state.calendarGraphData}/>\n </Grid>\n </Grid>\n </main>\n </div>\n </MuiThemeProvider>);\n }\n}\n\nDashboard.propTypes = {\n classes: PropTypes.object.isRequired,\n};\n\nexport default withStyles(styles)(Dashboard);\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read http://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit http://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(<App />, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: http://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""} \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 91d6f99..fa313c7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1169,6 +1169,16 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz",
"integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g=="
},
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
"abab": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
@@ -1217,6 +1227,26 @@
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
"integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg=="
},
+ "acorn-node": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz",
+ "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==",
+ "dev": true,
+ "requires": {
+ "acorn": "^6.0.2",
+ "acorn-dynamic-import": "^4.0.0",
+ "acorn-walk": "^6.1.0",
+ "xtend": "^4.0.1"
+ },
+ "dependencies": {
+ "acorn-dynamic-import": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz",
+ "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==",
+ "dev": true
+ }
+ }
+ },
"acorn-walk": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz",
@@ -2346,6 +2376,12 @@
}
}
},
+ "babelify": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz",
+ "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==",
+ "dev": true
+ },
"babylon": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
@@ -2547,6 +2583,20 @@
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
},
+ "browser-pack": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
+ "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "combine-source-map": "~0.8.0",
+ "defined": "^1.0.0",
+ "safe-buffer": "^5.1.1",
+ "through2": "^2.0.0",
+ "umd": "^3.0.0"
+ }
+ },
"browser-process-hrtime": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
@@ -2567,6 +2617,116 @@
}
}
},
+ "browserify": {
+ "version": "16.2.3",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz",
+ "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^1.11.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "^5.0.2",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.0",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^2.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.0.0",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp": "^0.5.0",
+ "module-deps": "^6.0.0",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "~0.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^2.0.0",
+ "stream-http": "^2.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.10.1",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "dependencies": {
+ "buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+ "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "events": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz",
+ "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
+ "dev": true,
+ "requires": {
+ "process": "~0.11.0"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
+ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
+ "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==",
+ "dev": true
+ }
+ }
+ },
"browserify-aes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
@@ -2747,6 +2907,12 @@
"unset-value": "^1.0.0"
}
},
+ "cached-path-relative": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz",
+ "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==",
+ "dev": true
+ },
"call-me-maybe": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
@@ -3132,6 +3298,32 @@
"resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
"integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="
},
+ "combine-source-map": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz",
+ "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "~1.1.0",
+ "inline-source-map": "~0.6.0",
+ "lodash.memoize": "~3.0.3",
+ "source-map": "~0.5.3"
+ },
+ "dependencies": {
+ "convert-source-map": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
+ "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=",
+ "dev": true
+ },
+ "lodash.memoize": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
+ "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=",
+ "dev": true
+ }
+ }
+ },
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
@@ -4032,6 +4224,12 @@
}
}
},
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+ "dev": true
+ },
"del": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
@@ -4081,6 +4279,18 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
+ "deps-sort": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz",
+ "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "shasum": "^1.0.0",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0"
+ }
+ },
"des.js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
@@ -4137,6 +4347,17 @@
}
}
},
+ "detective": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz",
+ "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.6.1",
+ "defined": "^1.0.0",
+ "minimist": "^1.1.1"
+ }
+ },
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
@@ -4300,6 +4521,15 @@
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
},
+ "duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
"duplexify": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz",
@@ -5886,7 +6116,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -6251,7 +6482,8 @@
},
"safe-buffer": {
"version": "5.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -6299,6 +6531,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -6337,11 +6570,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
},
@@ -6365,6 +6600,12 @@
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
},
+ "get-assigned-identifiers": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
+ "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
+ "dev": true
+ },
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
@@ -6838,6 +7079,12 @@
"util.promisify": "1.0.0"
}
},
+ "htmlescape": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
+ "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=",
+ "dev": true
+ },
"htmlparser2": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
@@ -7338,6 +7585,15 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
+ "inline-source-map": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz",
+ "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.5.3"
+ }
+ },
"inquirer": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz",
@@ -7373,6 +7629,24 @@
}
}
},
+ "insert-module-globals": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz",
+ "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "acorn-node": "^1.5.2",
+ "combine-source-map": "^0.8.0",
+ "concat-stream": "^1.6.1",
+ "is-buffer": "^1.1.0",
+ "path-is-absolute": "^1.0.1",
+ "process": "~0.11.0",
+ "through2": "^2.0.0",
+ "undeclared-identifiers": "^1.1.2",
+ "xtend": "^4.0.0"
+ }
+ },
"internal-ip": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz",
@@ -8543,6 +8817,12 @@
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
},
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -8649,6 +8929,25 @@
"resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz",
"integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ=="
},
+ "labeled-stream-splicer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz",
+ "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "isarray": "^2.0.4",
+ "stream-splicer": "^2.0.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz",
+ "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==",
+ "dev": true
+ }
+ }
+ },
"last-call-webpack-plugin": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz",
@@ -9167,6 +9466,29 @@
}
}
},
+ "module-deps": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz",
+ "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "browser-resolve": "^1.7.0",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "~1.6.0",
+ "defined": "^1.0.0",
+ "detective": "^5.0.2",
+ "duplexer2": "^0.1.2",
+ "inherits": "^2.0.1",
+ "parents": "^1.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.4.0",
+ "stream-combiner2": "^1.1.1",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
@@ -9712,6 +10034,15 @@
"no-case": "^2.2.0"
}
},
+ "parents": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
+ "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=",
+ "dev": true,
+ "requires": {
+ "path-platform": "~0.11.15"
+ }
+ },
"parse-asn1": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz",
@@ -9800,6 +10131,12 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
+ "path-platform": {
+ "version": "0.11.15",
+ "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
+ "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=",
+ "dev": true
+ },
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
@@ -14038,6 +14375,15 @@
"global-cache": "^1.2.1"
}
},
+ "read-only-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
+ "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -14508,13 +14854,13 @@
}
},
"regexp-tree": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.0.tgz",
- "integrity": "sha512-rHQv+tzu+0l3KS/ERabas1yK49ahNVxuH40WcPg53CzP5p8TgmmyBgHELLyJcvjhTD0e5ahSY6C76LbEVtr7cg==",
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.1.tgz",
+ "integrity": "sha512-HwRjOquc9QOwKTgbxvZTcddS5mlNlwePMQ3NFL8broajMLD5CXDAqas8Y5yxJH5QtZp5iRor3YCILd5pz71Cgw==",
"requires": {
"cli-table3": "^0.5.0",
"colors": "^1.1.2",
- "yargs": "^10.0.3"
+ "yargs": "^12.0.5"
}
},
"regexpp": {
@@ -15409,6 +15755,27 @@
}
}
},
+ "shasum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
+ "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=",
+ "dev": true,
+ "requires": {
+ "json-stable-stringify": "~0.0.0",
+ "sha.js": "~2.4.4"
+ },
+ "dependencies": {
+ "json-stable-stringify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz",
+ "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=",
+ "dev": true,
+ "requires": {
+ "jsonify": "~0.0.0"
+ }
+ }
+ }
+ },
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@@ -15443,6 +15810,12 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
+ "simple-concat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
+ "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=",
+ "dev": true
+ },
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
@@ -15813,6 +16186,16 @@
"readable-stream": "^2.0.2"
}
},
+ "stream-combiner2": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+ "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=",
+ "dev": true,
+ "requires": {
+ "duplexer2": "~0.1.0",
+ "readable-stream": "^2.0.2"
+ }
+ },
"stream-each": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
@@ -15839,6 +16222,16 @@
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
},
+ "stream-splicer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz",
+ "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
"string-length": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
@@ -15995,6 +16388,15 @@
}
}
},
+ "subarg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
+ "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.1.0"
+ }
+ },
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -16041,6 +16443,15 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
"integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY="
},
+ "syntax-error": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz",
+ "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.2.0"
+ }
+ },
"table": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz",
@@ -16498,6 +16909,24 @@
}
}
},
+ "umd": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
+ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==",
+ "dev": true
+ },
+ "undeclared-identifiers": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz",
+ "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.3.0",
+ "get-assigned-identifiers": "^1.2.0",
+ "simple-concat": "^1.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
@@ -17754,30 +18183,150 @@
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
},
"yargs": {
- "version": "10.1.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz",
- "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==",
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
"requires": {
"cliui": "^4.0.0",
- "decamelize": "^1.1.1",
- "find-up": "^2.1.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
"get-caller-file": "^1.0.1",
- "os-locale": "^2.0.0",
+ "os-locale": "^3.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
- "y18n": "^3.2.1",
- "yargs-parser": "^8.1.0"
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "mem": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz",
+ "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==",
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^1.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "p-is-promise": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz",
+ "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg=="
+ },
+ "p-limit": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz",
+ "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
+ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ=="
+ }
}
},
"yargs-parser": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
- "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
"requires": {
- "camelcase": "^4.1.0"
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
+ "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA=="
+ }
}
}
}
diff --git a/package.json b/package.json
index 3e84f28..08faf82 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,9 @@
},
"scripts": {
"start": "react-scripts start",
- "build": "react-scripts build",
+ "build:ui": "react-scripts build",
+ "build:bg": "node scripts/build",
+ "build": "npm run build:ui && npm run build:bg",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
@@ -28,5 +30,10 @@
"not dead",
"not ie <= 11",
"not op_mini all"
- ]
+ ],
+ "devDependencies": {
+ "@babel/preset-env": "^7.3.1",
+ "babelify": "^10.0.0",
+ "browserify": "^16.2.3"
+ }
}
diff --git a/public/background.js b/public/background.js
deleted file mode 100644
index 76043c6..0000000
--- a/public/background.js
+++ /dev/null
@@ -1,3 +0,0 @@
-chrome.browserAction.onClicked.addListener(function() {
- chrome.tabs.create({url: 'index.html'});
-});
diff --git a/scripts/build.js b/scripts/build.js
new file mode 100644
index 0000000..75ff636
--- /dev/null
+++ b/scripts/build.js
@@ -0,0 +1,10 @@
+var fs = require("fs");
+var browserify = require("browserify");
+var babelify = require("babelify");
+
+browserify({ debug: true })
+ .transform(babelify.configure({ presets: ["@babel/preset-env"] }))
+ .require("./src/background.js", { entry: true })
+ .bundle()
+ .on("error", function (err) { console.log("Error: " + err.message); })
+ .pipe(fs.createWriteStream("./build/background.js"));
diff --git a/src/App.js b/src/App.js
index 0b0d6d5..efdb446 100755
--- a/src/App.js
+++ b/src/App.js
@@ -1,3 +1,4 @@
+/* global chrome */
import React from 'react';
import PropTypes from 'prop-types';
import 'typeface-roboto';
@@ -69,6 +70,7 @@ const styles = theme => ({
class Dashboard extends React.Component {
state = {
patterns: [],
+ calendars: [],
timeRange: null,
token: gapi.getAuthToken(),
patternGraphData: default_chart_data,
@@ -76,14 +78,33 @@ class Dashboard extends React.Component {
activePattern: null
};
- cached = {
- calendars: {}
- };
+ constructor(props) {
+ super(props);
+ let port = chrome.runtime.connect({name: 'main'});
+ const getCallBack = t => this.requestCallback[t];
+ port.onMessage.addListener(function(msg) {
+ console.log(msg);
+ let t = getCallBack(msg.type);
+ let e = t.inFlight[msg.id];
+ console.assert(e !== undefined);
+ t.ids.push(msg.id);
+ e(msg);
+ });
+ this.port = port;
+ this.requestCallback = {};
+ this.sendMsg({ type: 1 }).then(msg => {
+ this.setState({ patterns: msg.data.map(p => PatternEntry.revive(p)) });
+ });
+ this.sendMsg({ type: 3 }).then(msg => {
+ this.setState({ calendars: msg.data });
+ });
+ }
updatePattern = (field, idx, value) => {
let patterns = this.state.patterns;
patterns[idx][field] = value;
this.setState({ patterns });
+ this.sendMsg({ type: 0, data: patterns });
};
removePattern = idx => {
@@ -92,15 +113,57 @@ class Dashboard extends React.Component {
for (let i = 0; i < patterns.length; i++)
patterns[i].idx = i;
this.setState({ patterns });
+ this.sendMsg({ type: 0, data: patterns });
};
newPattern = () => {
- let patterns = [PatternEntry.defaultPatternEntry(), ...this.state.patterns];
+ let patterns = [PatternEntry.defaultPatternEntry(0), ...this.state.patterns];
for (let i = 1; i < patterns.length; i++)
patterns[i].idx = i;
this.setState({ patterns });
+ this.sendMsg({ type: 0, data: patterns });
+ };
+
+ loadPatterns = patterns => {
+ this.setState({ patterns });
+ this.sendMsg({ type: 0, data: patterns });
};
+ loadCalendars = calendars => {
+ this.setState({ calendars });
+ this.sendMsg({ type: 5, data: calendars });
+ };
+
+ sendMsg = msg => {
+ if (!this.requestCallback.hasOwnProperty(msg.type))
+ this.requestCallback[msg.type] = {inFlight: {}, ids: [], maxId: 0};
+ let t = this.requestCallback[msg.type];
+ let cb;
+ let pm = new Promise(resolve => { cb = resolve; });
+ let id;
+ if (t.ids.length > 0) {
+ id = t.ids.pop();
+ } else {
+ id = t.maxId++;
+ }
+ t.inFlight[id] = cb;
+ msg.id = id;
+ this.port.postMessage(msg);
+ return pm;
+ }
+
+ getCalEvents = (id, start, end) => {
+ return this.sendMsg({ type: 4, data: { id,
+ start: start.getTime(),
+ end: end.getTime() } })
+ .then(({ data }) => data.map(e => {
+ return {
+ id: e.id,
+ start: new Date(e.start),
+ end: new Date(e.end) }
+ }));
+ }
+
analyze = () => {
if (!(this.state.startDate && this.state.endDate)) {
alert("Please choose a valid time range.");
@@ -108,26 +171,23 @@ class Dashboard extends React.Component {
}
let start = this.state.startDate.startOf('day').toDate();
let end = this.state.endDate.startOf('day').toDate();
- console.log(start, end);
let event_pms = [];
- for (let id in this.cached.calendars)
- event_pms.push(this.cached.calendars[id].cal.getEvents(start, end)
- .then(r => { return { id, events: r }; })
- .catch(e => {
- console.log(`cannot load calendar ${id}`);
- return { id, events: [] };
- }));
-
+ let cals = this.state.calendars;
+ for (let id in cals)
+ event_pms.push(this.getCalEvents(id, start, end)
+ .then(r => { return { id, events: r }; }));
+ console.log(cals);
Promise.all(event_pms).then(all_events => {
+ console.log(all_events);
let events = {};
let results = {}; // pattern idx => time
let cal_results = {}; // cal id => time
all_events.forEach(e => events[e.id] = e.events);
for (let i = 0; i < this.state.patterns.length; i++)
results[i] = 0;
- for (let id in this.cached.calendars) {
+ for (let id in cals) {
if (!events[id]) continue;
- let patterns = filterPatterns(this.state.patterns, this.cached.calendars[id].name);
+ let patterns = filterPatterns(this.state.patterns, cals[id].name);
events[id].forEach(event => {
patterns.forEach(p => {
if (!p.event.regex.test(event.summary)) return;
@@ -147,34 +207,35 @@ class Dashboard extends React.Component {
}
for (let id in cal_results) {
calendarGraphData.push({
- name: this.cached.calendars[id].name,
+ name: cals[id].name,
value: (cal_results[id] / 60.0),
- color: this.cached.calendars[id].color.background});
+ color: cals[id].color.background});
}
- //console.log(patternGraphData, calendarGraphData);
+ console.log(patternGraphData, calendarGraphData);
this.setState({ patternGraphData, calendarGraphData });
});
};
- loadPatterns = () => {
+ load = () => {
let token = this.state.token;
let colors = token.then(gapi.getColors).then(color => {
return color.calendar;
});
let cals = token.then(gapi.getCalendars);
Promise.all([colors, cals]).then(([colors, items]) => {
+ var cals = {};
items.forEach(item => {
- this.cached.calendars[item.id] = {
+ cals[item.id] = {
name: item.summary,
color: colors[item.colorId],
- cal: new gapi.GCalendar(item.id, item.summary)
- };
- });
- this.setState({ patterns: items.map((item, idx) => {
+ //cal: new gapi.GCalendar(item.id, item.summary)
+ }});
+ this.loadCalendars(cals);
+ this.loadPatterns(items.map((item, idx) => {
return new PatternEntry(item.summary, idx,
new Pattern(item.id, false, item.summary, item.summary),
Pattern.anyPattern());
- })});
+ }));
});
};
@@ -208,7 +269,7 @@ class Dashboard extends React.Component {
</Typography>
<PatternTable
patterns={this.state.patterns}
- cached={this.cached}
+ calendars={this.state.calendars}
onRemovePattern={this.removePattern}
onUpdatePattern={this.updatePattern} />
</FormGroup>
@@ -234,7 +295,7 @@ class Dashboard extends React.Component {
<Grid container spacing={16}>
<Grid item md={6} xs={12}>
<FormGroup>
- <Button variant="contained" color="primary" onClick={this.loadPatterns}>Load</Button>
+ <Button variant="contained" color="primary" onClick={this.load}>Load</Button>
</FormGroup>
</Grid>
<Grid item md={6} xs={12}>
diff --git a/src/PatternTable.js b/src/PatternTable.js
index 19ac292..e579921 100644
--- a/src/PatternTable.js
+++ b/src/PatternTable.js
@@ -54,7 +54,7 @@ class PatternTable extends React.Component {
}
render() {
- const { classes, cached, patterns } = this.props;
+ const { classes, calendars, patterns } = this.props;
const { rowsPerPage, page } = this.state;
const nDummy = rowsPerPage - Math.min(rowsPerPage, patterns.length - page * rowsPerPage);
let rows = patterns.slice(page * rowsPerPage, (page + 1) * rowsPerPage).map(p => (
@@ -68,7 +68,7 @@ class PatternTable extends React.Component {
<TableCell>
<CustomText
value={p[s.field]}
- cached={cached}
+ calendars={calendars}
onChange={event => this.props.onUpdatePattern(s.field, p.idx, event.target.value)}/>
</TableCell>)})
}
@@ -115,7 +115,7 @@ class PatternTable extends React.Component {
PatternTable.propTypes = {
classes: PropTypes.object.isRequired,
patterns: PropTypes.array.isRequired,
- cached: PropTypes.object.isRequired,
+ calendars: PropTypes.object.isRequired,
onRemovePattern: PropTypes.func.isRequired,
onUpdatePattern: PropTypes.func.isRequired,
};
diff --git a/src/RegexField.js b/src/RegexField.js
index 926a3bc..d4080a1 100644
--- a/src/RegexField.js
+++ b/src/RegexField.js
@@ -72,10 +72,10 @@ const RegexFieldWithStyles = withStyles(styles)(RegexField);
export function CalendarField(props) {
let options = {};
- for (let id in props.cached.calendars) {
+ for (let id in props.calendars) {
options[id] = new Pattern(id, false,
- props.cached.calendars[id].name,
- props.cached.calendars[id].name);
+ props.calendars[id].name,
+ props.calendars[id].name);
}
return (
<RegexFieldWithStyles
diff --git a/src/background.js b/src/background.js
new file mode 100644
index 0000000..7bc0318
--- /dev/null
+++ b/src/background.js
@@ -0,0 +1,58 @@
+import * as gapi from './gapi';
+
+let patterns = [];
+let calendars = {};
+let calData = {};
+
+chrome.runtime.onConnect.addListener(function(port) {
+ console.assert(port.name == 'main');
+ port.onMessage.addListener(function(msg) {
+ console.log(msg);
+ if (msg.type == 0) {
+ patterns = msg.data;
+ }
+ else if (msg.type == 1) {
+ port.postMessage({ id: msg.id, type: 1, data: patterns });
+ }
+ else if (msg.type == 2) {
+ calendars = msg.data;
+ }
+ else if (msg.type == 3) {
+ port.postMessage({ id: msg.id, type: 3, data: calendars });
+ }
+ else if (msg.type == 4) {
+ calData[msg.data.id].getEvents(new Date(msg.data.start), new Date(msg.data.end))
+ .catch(e => {
+ console.log(`cannot load calendar ${msg.data.id}`);
+ return [];
+ })
+ .then(data => {
+ console.log(data);
+ let resp = { id: msg.id, type: 4, data: data.map(e => {
+ return {
+ id: e.id,
+ start: e.start.getTime(),
+ end: e.end.getTime()
+ }
+ })};
+ console.log(resp);
+ port.postMessage(resp);
+ });
+ }
+ else if (msg.type == 5) {
+ calendars = msg.data;
+ for (let id in calendars) {
+ if (!calData.hasOwnProperty(id))
+ calData[id] = new gapi.GCalendar(id, calendars[id].summary);
+ }
+ }
+ else {
+ console.error("unknown msg type");
+ }
+ });
+});
+
+chrome.browserAction.onClicked.addListener(function() {
+ chrome.tabs.create({url: 'index.html'});
+});
+
diff --git a/src/gapi.js b/src/gapi.js
index 34fc9e9..67884c9 100644
--- a/src/gapi.js
+++ b/src/gapi.js
@@ -46,7 +46,7 @@ function getEvents(calId, token, syncToken, resultsPerRequest=100) {
.then(response => {
if (response.status === 200)
return response.json();
- else if (response.status == 410)
+ else if (response.status === 410)
throw GApiError.invalidSyncToken;
else throw GApiError.otherErrors;
})
@@ -94,22 +94,26 @@ export class GCalendar {
this.getSlot(ks)[e.id] = {
start: e.start,
end: e.end,
- id: e.id };
+ id: e.id,
+ summary: e.summary};
else
{
this.getSlot(ks)[e.id] = {
start: e.start,
end: GCalendar.slotEndDate(ks),
- id: e.id };
+ id: e.id,
+ summary: e.summary};
this.getSlot(ke)[e.id] = {
start: GCalendar.slotStartDate(ke),
end: e.end,
- id: e.id };
+ id: e.id,
+ summary: e.summary};
for (let k = ks + 1; k < ke; k++)
this.getSlot(k)[e.id] = {
start: GCalendar.slotStartDate(k),
end: GCalendar.slotEndDate(k),
- id: e.id };
+ id: e.id,
+ summary: e.summary};
}
}
@@ -126,13 +130,11 @@ export class GCalendar {
for (let id in s) {
if (!(s[id].start >= end || s[id].end <= start))
{
- let nstart = s[id].start < start ? start: s[id].start;
- let nend = s[id].end > end ? end: s[id].end;
- if (nstart > nend) console.log(s[id], start, end);
results.push({
id,
start: s[id].start < start ? start: s[id].start,
- end: s[id].end > end ? end: s[id].end
+ end: s[id].end > end ? end: s[id].end,
+ summary: s[id].summary
});
}
}
@@ -167,7 +169,7 @@ export class GCalendar {
this.removeEvent(e);
}));
})).catch(e => {
- if (e == GApiError.invalidSyncToken) {
+ if (e === GApiError.invalidSyncToken) {
this.syncToken = '';
this.sync();
} else throw e;
diff --git a/src/pattern.js b/src/pattern.js
index ad94253..c7dafbd 100644
--- a/src/pattern.js
+++ b/src/pattern.js
@@ -10,6 +10,7 @@ export class Pattern {
get isEmpty() { return this.label === null; }
static emptyPattern = () => new Pattern(0, true, '', null);
static anyPattern = () => new Pattern('any', true, '.*', 'Any');
+ static revive = obj => new Pattern(obj.id, obj.isRegex, obj.value, obj.label);
}
export class PatternEntry {
@@ -21,4 +22,7 @@ export class PatternEntry {
}
static defaultPatternEntry = (idx) => new PatternEntry('', idx, Pattern.emptyPattern(), Pattern.anyPattern());
+ static revive = obj => new PatternEntry(
+ obj.name, obj.idx,
+ Pattern.revive(obj.cal), Pattern.revive(obj.event));
}