{"version":3,"names":[],"mappings":"","sources":["all.js"],"sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.ibis = f()}})(function(){var define,module,exports;return (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\"],\n data: function data() {\n return {\n accessToken: \"42ac3-2bd67-852eb-05473\",\n state: {\n initialized: false,\n expanded: false,\n error: false,\n timeoutId: null\n },\n query: null,\n suggestedAddresses: [],\n address: {\n postalCode: \"\",\n streetAddress: \"\",\n city: \"\",\n region: \"\",\n country: \"\"\n }\n };\n },\n mounted: function mounted() {\n if (this.debug) console.log(\"MOUNTED ADDRESS INPUT\", JSON.stringify(this.address));\n this.prepopulateFields();\n if (this.debug) console.log(\"FOUND PREPOPULATED VALUES\", JSON.stringify(this.address));\n this.bindValidationCheck();\n this.state.initialized = true;\n },\n watch: {\n query: function query(e) {\n var _this2 = this;\n\n // When the query changes, set a timeout before making AJAX call, so we aren't spamming the endpoint as much\n clearTimeout(this.timeoutId);\n this.timeoutId = setTimeout(function () {\n _this2.findMatches();\n }, 500);\n }\n },\n methods: {\n selectSuggestedAddress: function selectSuggestedAddress(id, count) {\n if (count > 1) {\n // More than one possibility, refine list of suggestedAddresses\n this.findMatches(id);\n } else {\n // Only one possibility, retrieve the address\n this.retrieveAddress(id);\n }\n },\n findMatches: function findMatches() {\n var _this3 = this;\n\n var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n _axios.default.get(\"https://api.craftyclicks.co.uk/address/1.1/find\", {\n params: {\n key: this.accessToken,\n query: this.query,\n country: this.address.country,\n id: id\n }\n }).then(function (response) {\n if (_this3.debug) console.log(\"response\", response);\n _this3.suggestedAddresses = response.data.results;\n _this3.state.error = _this3.state.expanded = false;\n }).catch(function (error) {\n _this3.state.error = _this3.state.expanded = true;\n _this3.suggestedAddresses = [];\n });\n },\n retrieveAddress: function retrieveAddress(id) {\n var _this4 = this;\n\n _axios.default.get(\"https://api.craftyclicks.co.uk/address/1.1/retrieve\", {\n params: {\n key: this.accessToken,\n country: this.address.country,\n id: id\n }\n }).then(function (response) {\n if (_this4.debug) console.log(\"response\", response);\n var address = response.data.result;\n _this4.address.postalCode = address.postal_code;\n _this4.address.streetAddress = _this4.mergeStrings(\"\\n\", address.line_1, address.line_2, address.line_3, address.line_4, address.line_5);\n _this4.address.city = address.locality;\n _this4.address.region = address.province_name;\n _this4.state.error = false;\n _this4.state.expanded = true;\n _this4.suggestedAddresses = [];\n }).catch(function (error) {\n _this4.state.error = _this4.state.expanded = true;\n _this4.suggestedAddresses = [];\n });\n },\n prepopulateFields: function prepopulateFields() {\n this.address.country = $module.querySelector('[autocomplete=\"country\"]') ? $module.querySelector('[autocomplete=\"country\"]').value : \"\";\n this.address.postalCode = $module.querySelector('[autocomplete=\"postal-code\"]') ? $module.querySelector('[autocomplete=\"postal-code\"]').value : \"\";\n this.address.streetAddress = $module.querySelector('[autocomplete=\"street-address\"]') ? $module.querySelector('[autocomplete=\"street-address\"]').value : \"\";\n this.address.city = $module.querySelector('[autocomplete=\"address-level2\"]') ? $module.querySelector('[autocomplete=\"address-level2\"]').value : \"\";\n this.address.region = $module.querySelector('[autocomplete=\"address-level1\"]') ? $module.querySelector('[autocomplete=\"address-level1\"]').value : \"\";\n\n if (this.address.postalCode || this.address.streetAddress || this.address.city || this.address.region) {\n // If any are set, show the expanded state immediately\n this.state.expanded = true;\n }\n },\n mergeStrings: function mergeStrings(delimiter) {\n var parts = [];\n\n for (var _len = arguments.length, strings = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n strings[_key - 1] = arguments[_key];\n }\n\n strings.forEach(function (item) {\n if (item) {\n parts.push(item);\n }\n });\n return parts.join(delimiter);\n },\n bindValidationCheck: function bindValidationCheck() {\n var _this5 = this;\n\n if (!$form) {\n return;\n }\n\n $form.addEventListener(\"submit\", function () {\n var $inputs = $form.querySelectorAll(\"input, textarea, select\");\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = $inputs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var $input = _step.value;\n\n if (!$input.validity.valid) {\n _this5.state.expanded = true;\n break;\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n });\n }\n }\n });\n }\n }]);\n\n return AddressInput;\n}();\n\nexports.default = AddressInput;\n\n},{\"axios\":35,\"vue/dist/vue.js\":173}],2:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _chart = _interopRequireDefault(require(\"chart.js\"));\n\nvar _merge2 = _interopRequireDefault(require(\"lodash/merge\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar BarChart =\n/*#__PURE__*/\nfunction () {\n function BarChart($module) {\n var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, BarChart);\n\n this.$module = $module; // Global chart defaults\n\n _chart.default.defaults.font.family = \"Poppins, 'Poppins', Calibri, Helvetica, Geneva, Univers, Arial, sans-serif\"; // Bar chart config\n\n var defaultConfig = {\n responsive: true,\n maintainAspectRatio: false,\n scales: {\n y: {\n beginAtZero: true\n }\n },\n animation: {\n delay: 1000\n },\n plugins: {\n tooltip: {\n enabled: false\n },\n legend: {\n position: \"bottom\",\n align: \"start\",\n labels: {\n boxWidth: 12,\n boxHeight: 12\n }\n }\n }\n };\n this.settings = (0, _merge2.default)(defaultConfig, config); // Go\n\n this.chart = new _chart.default(this.$module, {\n type: \"bar\",\n data: {},\n options: this.settings\n });\n }\n\n _createClass(BarChart, [{\n key: \"updateChart\",\n value: function updateChart(data) {\n this.chart.data.labels = data.labels;\n this.chart.data.datasets = this.injectDataStyles(data.data);\n this.chart.update();\n }\n }, {\n key: \"injectDataStyles\",\n value: function injectDataStyles(data) {\n if (!data) return []; // Chart.js, for whatever reason, ties presentation data in with actual data.\n // It's very annoying.\n\n var colors = this.generateDataColors(data.length, 0, 54, 61, 25);\n\n for (var i = 0; i < data.length; i++) {\n data[i] = Object.assign({}, data[i], {\n backgroundColor: colors[i]\n });\n }\n\n return data;\n }\n }, {\n key: \"generateDataColors\",\n value: function generateDataColors(datasetCount, h, s, l1, l2) {\n var colorArray = [];\n var l = l1;\n var increment = (l1 - l2) / (datasetCount - 1);\n\n for (var i = 0; i < datasetCount; i++) {\n colorArray.push(\"hsl(\".concat(h, \", \").concat(s, \"%, \").concat(l, \"%)\"));\n l = l - increment;\n }\n\n return colorArray;\n }\n }, {\n key: \"debugTestData\",\n value: function debugTestData() {\n this.updateChart({\n labels: [\"Aug 2021\", \"Jul 2021\", \"Jun 2021\", \"May 2021\", \"Apr 2021\", \"Mar 2021\", \"Feb 2021\", \"Jan 2021\", \"Dec 2020\", \"Nov 2020\"],\n data: [{\n label: \"Unaware\",\n data: [97, 44, 15, 34, 13, 53, 71, 43, 45, 4]\n }, {\n label: \"Aware\",\n data: [57, 17, 21, 13, 35, 32, 86, 13, 68, 4]\n }, {\n label: \"Okay at\",\n data: [93, 11, 6, 71, 13, 1, 70, 86, 5, 99]\n }, {\n label: \"Pretty good\",\n data: [57, 87, 31, 15, 84, 5, 98, 43, 76, 23]\n }, {\n label: \"Experienced\",\n data: [41, 50, 86, 35, 100, 18, 78, 10, 36, 23]\n }]\n });\n }\n }]);\n\n return BarChart;\n}();\n\nexports.default = BarChart;\n\n},{\"chart.js\":64,\"lodash/merge\":160}],3:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _swiper = _interopRequireDefault(require(\"swiper\"));\n\nvar _tokensWeb = _interopRequireDefault(require(\"../../dist/tokens/tokens.web.json\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar BlogFeed = function BlogFeed($module) {\n _classCallCheck(this, BlogFeed);\n\n this.$module = $module;\n var flipBreakpoint = _tokensWeb.default.props[\"bp_mars\"].originalValue;\n var slc = \"ibis-blog-feed__slider\";\n this.$slider = $module.querySelector(\".\".concat(slc));\n this.swiper = new _swiper.default(this.$slider, {\n slidesPerView: 1,\n slidesPerGroup: 1,\n spaceBetween: 24,\n speed: 666,\n containerModifierClass: \"\".concat(slc, \"--\"),\n wrapperClass: \"\".concat(slc, \"-wrapper\"),\n slideClass: \"\".concat(slc, \"-slide\"),\n slideActiveClass: \"\".concat(slc, \"-slide--active\"),\n slideVisibleClass: \"\".concat(slc, \"-slide--visible\"),\n slideNextClass: \"\".concat(slc, \"-slide--next\"),\n slidePrevClass: \"\".concat(slc, \"-slide--prev\"),\n slideDuplicateClass: \"\".concat(slc, \"-slide--duplicate\"),\n slideDuplicateActiveClass: \"\".concat(slc, \"-slide--duplicate-active\"),\n slideDuplicateNextClass: \"\".concat(slc, \"-slide--duplicate-next\"),\n slideDuplicatePrevClass: \"\".concat(slc, \"-slide--duplicate-prev\"),\n navigation: {\n nextEl: \".\".concat(slc, \"-control--next\"),\n prevEl: \".\".concat(slc, \"-control--prev\"),\n disabledClass: \"\".concat(slc, \"-control--disabled\"),\n hiddenClass: \"\".concat(slc, \"-control--hidden\")\n },\n breakpoints: _defineProperty({}, parseInt(flipBreakpoint), {\n slidesPerView: 2,\n slidesPerGroup: 2\n }),\n a11y: {\n enabled: true,\n notificationClass: \"\".concat(slc, \"-status\")\n }\n });\n};\n\nexports.default = BlogFeed;\n\n},{\"../../dist/tokens/tokens.web.json\":33,\"swiper\":168}],4:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _axios = _interopRequireDefault(require(\"axios\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar Bookmark =\n/*#__PURE__*/\nfunction () {\n function Bookmark($module) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, Bookmark);\n\n this.$module = $module;\n this.$button = this.$module.querySelector(\".ibis-bookmark__button\");\n this.$buttonLabel = this.$button.querySelector(\".ibis-bookmark__label\"); // Config settings\n\n var defaultSettings = {\n addBookmarkCallback: function addBookmarkCallback() {},\n removeBookmarkCallback: function removeBookmarkCallback() {},\n buttonLabels: {\n initial: this.$buttonLabel.innerText.trim() || \"Add to Saved Content\",\n saving: this.$button.dataset.savingLabel || \"Saving...\",\n saved: this.$button.dataset.savedLabel || \"Added to Saved Content\",\n removing: this.$button.dataset.removingLabel || \"Removing...\"\n }\n };\n this.settings = Object.assign({}, defaultSettings, options); // Pre-flight check to see if we have everything we want\n\n if (!this.$module.dataset.endpointAdd || !this.$module.dataset.endpointRemove || !this.$module.dataset.endpointCheck) {\n console.error(\"Bookmark module is missing a required attribute. Must have `data-endpoint-add`, `data-endpoint-remove` and `data-endpoint-check`.\");\n return;\n } // More set up\n\n\n this.isSaved = false;\n this.formData = this.getFormData();\n this.$buttonLabel.innerText = this.settings.buttonLabels.initial; // Setup a11y\n\n this.$button.setAttribute(\"role\", \"status\");\n this.$button.setAttribute(\"aria-live\", \"status\"); // Run check to see if page is already bookmarked\n\n this.checkIfSaved(); // JS is available. Show the button.\n\n this.$module.removeAttribute(\"hidden\"); // The functionality\n\n this.bindControls();\n }\n\n _createClass(Bookmark, [{\n key: \"bindControls\",\n value: function bindControls() {\n var _this = this;\n\n this.$module.addEventListener(\"submit\", function (e) {\n e.preventDefault();\n\n if (_this.isSaved) {\n _this.removeBookmark();\n } else {\n _this.addBookmark();\n }\n });\n }\n }, {\n key: \"checkIfSaved\",\n value: function checkIfSaved() {\n var _this2 = this;\n\n if (window.DESIGN_SYSTEM) {\n this.isSaved = false;\n this.$button.disabled = false;\n this.$buttonLabel.innerText = this.settings.buttonLabels.initial;\n } else {\n _axios.default.get(this.$module.dataset.endpointCheck, {\n params: this.formData\n }).then(function (response) {\n // Response is boolean that says either \"true\" or \"false\"\n if (response.data) {\n _this2.isSaved = true;\n _this2.$button.disabled = false;\n _this2.$buttonLabel.innerText = _this2.settings.buttonLabels.saved;\n } else {\n _this2.isSaved = false;\n _this2.$button.disabled = false;\n _this2.$buttonLabel.innerText = _this2.settings.buttonLabels.initial;\n }\n }).catch(function (error) {\n _this2.isSaved = false;\n });\n }\n }\n }, {\n key: \"addBookmark\",\n value: function addBookmark() {\n var _this3 = this;\n\n this.$button.disabled = true;\n this.$buttonLabel.innerText = this.settings.buttonLabels.saving;\n\n if (window.DESIGN_SYSTEM) {\n this.$buttonLabel.innerText = this.settings.buttonLabels.saved;\n this.isSaved = true;\n this.settings.addBookmarkCallback();\n } else {\n _axios.default.post(this.$module.dataset.endpointAdd, {\n params: this.formData\n }).then(function (response) {\n _this3.$buttonLabel.innerText = _this3.settings.buttonLabels.saved;\n _this3.isSaved = true;\n\n _this3.settings.addBookmarkCallback(response.data);\n }).catch(function (error) {\n _this3.$buttonLabel.innerText = _this3.settings.buttonLabels.initial;\n }).then(function () {\n _this3.$button.disabled = false;\n });\n }\n }\n }, {\n key: \"removeBookmark\",\n value: function removeBookmark() {\n var _this4 = this;\n\n this.$button.disabled = true;\n this.$buttonLabel.innerText = this.settings.buttonLabels.removing;\n\n if (window.DESIGN_SYSTEM) {\n this.$buttonLabel.innerText = this.settings.buttonLabels.initial;\n this.isSaved = false;\n this.settings.removeBookmarkCallback();\n } else {\n _axios.default.post(this.$module.dataset.endpointRemove, {\n params: this.formData\n }).then(function (response) {\n _this4.$buttonLabel.innerText = _this4.settings.buttonLabels.initial;\n _this4.isSaved = false;\n\n _this4.settings.removeBookmarkCallback(response.data);\n }).catch(function (error) {\n _this4.$buttonLabel.innerText = _this4.settings.buttonLabels.saved;\n }).then(function () {\n _this4.$button.disabled = false;\n });\n }\n }\n }, {\n key: \"getFormData\",\n value: function getFormData() {\n // We use an object instead of FormData because Axios wants objects, dammit\n var returnObj = {};\n var formInputs = this.$module.querySelectorAll(\"[name]\");\n formInputs.forEach(function (input) {\n returnObj[input.name] = input.value;\n });\n return returnObj;\n }\n }]);\n\n return Bookmark;\n}();\n\nexports.default = Bookmark;\n\n},{\"axios\":35}],5:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar ButtonDropdown =\n/*#__PURE__*/\nfunction () {\n function ButtonDropdown($module) {\n var _this = this;\n\n _classCallCheck(this, ButtonDropdown);\n\n this.$module = $module;\n this.$button = $module.querySelector(\".ibis-button-dropdown__button\");\n this.$menu = $module.querySelector(\".ibis-button-dropdown__menu\");\n this.id = this.$button.id; // Set a11y attributes\n\n this.$menu.id = \"\".concat(this.id, \"-menu\");\n this.$menu.setAttribute(\"aria-controlledby\", this.id);\n this.$menu.setAttribute(\"hidden\", \"hidden\");\n this.$button.setAttribute(\"aria-controls\", this.$menu.id);\n this.$button.setAttribute(\"aria-expanded\", \"false\"); // Set action when user clicks button\n\n this.$button.bindClick = this.onClick.bind(this);\n this.$button.addEventListener(\"click\", this.$button.bindClick);\n this.$menu.addEventListener(\"click\", function (e) {\n return e.stopPropagation();\n });\n document.addEventListener(\"click\", function () {\n _this.close();\n });\n }\n\n _createClass(ButtonDropdown, [{\n key: \"onClick\",\n value: function onClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.toggle();\n }\n }, {\n key: \"toggle\",\n value: function toggle() {\n if (this.$button.ariaExpanded === \"true\") {\n // If open, close it\n this.close();\n } else {\n // If closed, open it\n this.open();\n }\n }\n }, {\n key: \"open\",\n value: function open() {\n this.$menu.removeAttribute(\"hidden\");\n this.$button.setAttribute(\"aria-expanded\", \"true\");\n }\n }, {\n key: \"close\",\n value: function close() {\n this.$menu.setAttribute(\"hidden\", \"hidden\");\n this.$button.setAttribute(\"aria-expanded\", \"false\");\n }\n }]);\n\n return ButtonDropdown;\n}();\n\nexports.default = ButtonDropdown;\n\n},{}],6:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _vue = _interopRequireDefault(require(\"vue/dist/vue.js\"));\n\nvar _vue2FlipCountdown = _interopRequireDefault(require(\"vue2-flip-countdown\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar CountdownClock =\n/*#__PURE__*/\nfunction () {\n function CountdownClock($module) {\n var _this = this;\n\n _classCallCheck(this, CountdownClock);\n\n this.$module = $module; // Create Countdown\n\n document.addEventListener(\"DOMContentLoaded\", function () {\n _this.initVue();\n });\n }\n\n _createClass(CountdownClock, [{\n key: \"initVue\",\n value: function initVue() {\n var $module = this.$module;\n new _vue.default({\n el: $module,\n components: {\n \"flip-countdown\": _vue2FlipCountdown.default\n }\n });\n }\n }]);\n\n return CountdownClock;\n}();\n\nexports.default = CountdownClock;\n\n},{\"vue/dist/vue.js\":173,\"vue2-flip-countdown\":172}],7:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _vue = _interopRequireDefault(require(\"vue/dist/vue.js\"));\n\nvar _axios = _interopRequireDefault(require(\"axios\"));\n\nvar _helper = _interopRequireDefault(require(\"../../src/js/global/helper\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar CPDApp = function CPDApp($module) {\n _classCallCheck(this, CPDApp);\n\n var noAjax = window.DESIGN_SYSTEM || false;\n new _vue.default({\n el: $module,\n delimiters: [\"<%\", \"%>\"],\n data: function data() {\n return {\n state: {\n initialized: false,\n isLoading: false,\n error: null\n },\n displayOptions: {\n sort: \"DateAddedDesc\",\n startDate: null,\n endDate: null,\n cpdTargetHours: 35\n },\n errorMessage: \"\",\n cpdGraph: {\n date: null,\n isWorking: false,\n error: null\n },\n goals: [],\n logs: []\n };\n },\n mounted: function mounted() {\n // Load saved data\n this.loadData();\n },\n methods: {\n resetDate: function resetDate() {\n this.displayOptions.endDate = null;\n this.displayOptions.startDate = null;\n },\n loadData: function loadData() {\n var _this = this;\n\n this.state.isLoading = true;\n this.state.error = null;\n\n if (noAjax) {\n // Dummy data\n this.cpdGraph.date = \"2021-08-09\";\n this.goals = this.addGoalStateProperties([{\n id: \"b683a8b2-7733-4eba-89af-0119aab4242a\",\n value: \"Increase diversity and inclusivity.\"\n }, {\n id: \"b450b1b7-3970-4f1f-984e-b2f1a61b7477\",\n value: \"Work out how Gantt charts work.\",\n deleted: true\n }, {\n id: \"80900d63-8a31-4041-8dad-e2e1d3b49f3f\",\n value: \"Work out what font to use on this sweet Powerpoint.\"\n }]);\n this.logs = this.addLogStateProperties([{\n id: \"d3f689d8-53e7-4280-bfc9-9dc3ba15b667\",\n value: {\n creationDate: \"2021-05-06T10:36:42Z\",\n title: \"First example log\",\n startDate: \"2021-05-06\",\n endDate: \"2021-05-08\",\n hours: 1,\n minutes: 0,\n duration: 60,\n selectedGoal: \"b683a8b2-7733-4eba-89af-0119aab4242a\",\n reflection: \"This was certainly a thing I did.\\nAnd I would do it again.\",\n complete: true\n }\n }, {\n id: \"b450b1b7-3970-4eee-984e-b2f1a61b7444\",\n value: {\n creationDate: \"2021-05-11T17:28:15Z\",\n title: \"Second example log\",\n startDate: \"2021-05-12\",\n endDate: null,\n hours: 2,\n minutes: 1,\n duration: 121,\n selectedGoal: \"b450b1b7-3970-4f1f-984e-b2f1a61b7477\",\n reflection: null,\n complete: false\n }\n }, {\n id: \"2ffcdb45-7679-45f9-970c-5de663657120\",\n value: {\n creationDate: \"2021-03-10T16:44:23Z\",\n title: \"An incomplete log\",\n startDate: \"2021-03-10\",\n endDate: \"2021-03-10\",\n hours: 8,\n minutes: 7,\n duration: 487,\n selectedGoal: \"b683a8b2-7733-4eba-89af-0119aab4242a\",\n reflection: null,\n complete: true\n }\n }]); // When loaded...\n\n this.state.isLoading = false;\n this.state.initialized = true;\n this.checkQueryStringParameters();\n } else {\n _axios.default.get($module.dataset.endpointLoad, {\n headers: {}\n }).then(function (response) {\n var data = response.data;\n _this.cpdGraph.date = data.cpdTargetDate;\n _this.goals = _this.addGoalStateProperties(data.goals);\n _this.logs = _this.addLogStateProperties(data.logs);\n\n _this.checkQueryStringParameters();\n }).catch(function (err) {\n _this.state.error = _this.handleAxiosError(err);\n }).then(function () {\n _this.state.isLoading = false;\n _this.state.initialized = true;\n });\n }\n },\n checkQueryStringParameters: function checkQueryStringParameters() {\n // Flags to see if we should be creating/editing a goal/log\n if (this.getQueryStringParameter(\"goal\") === \"new\") {\n this.addGoal();\n } else if (this.getQueryStringParameter(\"goal\") === \"last\") {\n this.focusGoal();\n } else if (this.getQueryStringParameter(\"goal\")) {\n this.focusGoal(this.getQueryStringParameter(\"goal\"));\n }\n\n if (this.getQueryStringParameter(\"log\") === \"new\") {\n this.addLog();\n } else if (this.getQueryStringParameter(\"log\")) {\n this.focusLog(this.getQueryStringParameter(\"log\"));\n }\n },\n getQueryStringParameter: function getQueryStringParameter(param) {\n var searchParams = new URLSearchParams(window.location.search);\n\n if (!searchParams.has(param)) {\n return false;\n }\n\n return searchParams.get(param) || true;\n },\n formatDate: function formatDate(isoDate) {\n return new Intl.DateTimeFormat(\"en-GB\", {\n day: \"numeric\",\n month: \"short\",\n year: \"numeric\"\n }).format(new Date(isoDate));\n },\n convertDurationToTime: function convertDurationToTime(duration) {\n return {\n hours: Math.floor(duration / 60),\n minutes: Math.round(duration % 60)\n };\n },\n convertDurationToTimeFormatted: function convertDurationToTimeFormatted(duration) {\n var d = this.convertDurationToTime(duration);\n return \"\".concat(d.hours, \":\").concat(String(d.minutes).padStart(2, \"0\"));\n },\n convertTimeToDuration: function convertTimeToDuration() {\n var hours = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;\n var minutes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n return Number(hours) * 60 + Number(minutes);\n },\n formatTime: function formatTime(hours, minutes) {\n var hoursLabel = hours || \"0\";\n var minutesLabel = String(minutes || \"0\").padStart(2, '0');\n return \"\".concat(hoursLabel, \":\").concat(minutesLabel);\n },\n handleAxiosError: function handleAxiosError(err) {\n if (err.response && err.response.data) {\n return err.response.data.error;\n }\n\n return err.message;\n },\n\n /**\n * CPD GRAPH METHODS\n */\n updateCPDTargetDate: function updateCPDTargetDate() {\n var _this2 = this;\n\n if (!this.cpdGraph.date) {\n return;\n }\n\n this.cpdGraph.isWorking = true;\n this.cpdGraph.error = null;\n\n if (noAjax) {\n this.cpdGraph.isWorking = false;\n } else {\n _axios.default.post($module.dataset.endpointSaveTarget, {\n params: {\n date: this.cpdGraph.date\n }\n }, {\n headers: {}\n }).then(function (response) {// Completed successfully. Do something?\n }).catch(function (err) {\n _this2.cpdGraph.error = _this2.handleAxiosError(err);\n }).then(function () {\n _this2.cpdGraph.isWorking = false;\n });\n }\n },\n\n /**\n * DEVELOPMENT GOAL HANDLING METHODS\n */\n addGoal: function addGoal() {\n this.goals.push({\n id: null,\n error: null,\n isEditing: true,\n isWorking: false,\n isRecentlySaved: false,\n value: \"\",\n oldValue: \"\"\n });\n this.focusGoal();\n },\n addGoalStateProperties: function addGoalStateProperties(arr) {\n arr.forEach(function (item) {\n Object.assign(item, {\n // id and value come from endpoint\n error: null,\n isEditing: false,\n isWorking: false,\n isRecentlySaved: false,\n oldValue: item.value\n });\n });\n return arr;\n },\n focusGoal: function focusGoal() {\n var _this3 = this;\n\n var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n _vue.default.nextTick().then(function () {\n // If there's nothing in $refs.goalInput yet, try again on the next tick\n if (!_this3.$refs.goalInput) {\n _this3.focusGoal(id);\n\n return;\n }\n\n var $input = null;\n\n if (id) {\n // If an ID is defined, look it up.\n // Annoyingly, we have to look through two indexes:\n // Data index includes deleted (really, hidden) goals.\n // Element index is only the ones visible on page.\n var dataIndex = _this3.goals.findIndex(function (x) {\n return x.id === Number(id);\n });\n\n var elemIndex = _this3.$refs.goalInput.findIndex(function (x) {\n return x.dataset.id === id;\n });\n\n $input = _this3.$refs.goalInput[elemIndex];\n\n _this3.editGoal(dataIndex);\n } else {\n // If no ID is defined, just grab the last one of each\n // NOTE: that this will not work as intended if the last goal input is hidden/deleted!\n $input = _this3.$refs.goalInput[_this3.$refs.goalInput.length - 1];\n\n _this3.editGoal(_this3.goals.length - 1);\n }\n\n $input.focus(); // Check for existence of `scrollIntoViewIfNeeded` before using\n // as not all browsers support this yet\n\n if (typeof $input.scrollIntoViewIfNeeded !== \"undefined\") {\n $input.scrollIntoViewIfNeeded();\n } else {\n $input.scrollIntoView();\n }\n });\n },\n cancelAddGoal: function cancelAddGoal(index) {\n this.goals.splice(index, 1);\n },\n editGoal: function editGoal(index) {\n this.goals[index].error = null;\n this.goals[index].isEditing = this.goals[index].oldValue !== this.goals[index].value;\n },\n cancelEditGoal: function cancelEditGoal(index) {\n this.goals[index].error = null;\n this.goals[index].isEditing = false;\n this.goals[index].value = this.goals[index].oldValue;\n },\n saveGoal: function saveGoal(index) {\n var _this4 = this;\n\n var thisGoal = this.goals[index];\n thisGoal.isWorking = true;\n thisGoal.error = null;\n var id = thisGoal.id;\n\n if (noAjax) {\n setTimeout(function () {\n thisGoal.id = \"placeholderId\";\n thisGoal.oldValue = thisGoal.value;\n thisGoal.isWorking = false;\n thisGoal.isEditing = false;\n thisGoal.isRecentlySaved = true;\n new window.ibis.Notification(\"Goal saved.\", {\n transitionInDuration: 300,\n duration: 5000,\n transitionOutDuration: 300\n });\n setTimeout(function () {\n thisGoal.isRecentlySaved = false;\n }, 2500);\n }, 1000);\n } else {\n _axios.default.post($module.dataset.endpointSaveGoal, {\n params: {\n id: id,\n data: JSON.stringify(thisGoal)\n }\n }, {\n headers: {}\n }).then(function (response) {\n thisGoal.id = response.data.id;\n thisGoal.oldValue = thisGoal.value;\n thisGoal.isRecentlySaved = true;\n\n if (response.data.successMessage) {\n new window.ibis.Notification(response.data.successMessage, {\n transitionInDuration: 300,\n duration: 5000,\n transitionOutDuration: 300\n });\n }\n\n setTimeout(function () {\n thisGoal.isRecentlySaved = false;\n }, 2500);\n thisGoal.isEditing = false;\n }).catch(function (err) {\n thisGoal.error = _this4.handleAxiosError(err);\n }).then(function () {\n thisGoal.isWorking = false;\n });\n }\n },\n deleteGoal: function deleteGoal(index) {\n var _this5 = this;\n\n var thisGoal = this.goals[index];\n\n if (!window.confirm(\"Delete goal \\\"\".concat(thisGoal.value, \"\\\"?\"))) {\n return;\n }\n\n thisGoal.isWorking = true;\n thisGoal.isEditing = false;\n var id = thisGoal.id;\n this.state.error = null;\n\n if (noAjax) {\n this.goals[index].deleted = true;\n thisGoal.isWorking = false;\n } else {\n _axios.default.post($module.dataset.endpointDeleteGoal, {\n params: {\n id: id\n }\n }, {\n headers: {}\n }).then(function (response) {\n _this5.goals[index].deleted = true;\n }).catch(function (err) {\n thisGoal.error = _this5.handleAxiosError(err);\n }).then(function () {\n thisGoal.isWorking = false;\n });\n }\n },\n\n /**\n * LOG ENTRY HANDLING METHODS\n */\n addLog: function addLog() {\n this.resetDate();\n\n var tempId = \"T-\" + _helper.default.generateGuid();\n\n this.logs.push({\n // This ID is temporary and is replaced when the log is saved\n id: tempId,\n error: null,\n hasTemporaryId: true,\n isOpen: true,\n isEditing: true,\n isWorking: false,\n isRecentlySaved: false,\n value: {\n creationDate: new Date().toISOString(),\n title: null,\n startDate: null,\n endDate: null,\n hours: null,\n minutes: null,\n duration: null,\n selectedGoal: null,\n reflection: null,\n complete: false\n },\n oldValue: {\n creationDate: new Date().toISOString(),\n title: null,\n startDate: null,\n endDate: null,\n hours: null,\n minutes: null,\n duration: null,\n selectedGoal: null,\n reflection: null,\n complete: false\n }\n });\n this.focusLog(tempId);\n },\n addLogStateProperties: function addLogStateProperties(arr) {\n arr.forEach(function (item) {\n Object.assign(item, {\n error: null,\n hasTemporaryId: false,\n isOpen: false,\n isEditing: false,\n isWorking: false,\n isRecentlySaved: false,\n oldValue: _objectSpread({}, item.value)\n });\n });\n return arr;\n },\n focusLog: function focusLog(id) {\n var _this6 = this;\n\n _vue.default.nextTick().then(function () {\n _this6.logs.find(function (x) {\n return x.id === id;\n }).isOpen = true;\n\n var $log = _this6.$refs.log.find(function (x) {\n return x.id === id;\n });\n\n if (typeof $log.scrollIntoViewIfNeeded !== \"undefined\") {\n $log.scrollIntoViewIfNeeded();\n } else {\n $log.scrollIntoView();\n }\n });\n },\n cancelAddLog: function cancelAddLog(id) {\n this.removeLogById(id);\n },\n editLog: function editLog(id) {\n var entry = this.getEditableEntryById(id);\n\n if (!entry) {\n return;\n }\n\n entry.isEditing = true;\n entry.oldValue = _objectSpread({}, entry.value);\n },\n reduceHoursToLength: function reduceHoursToLength(id, maxLength) {\n var log = this.getEntryById(id);\n var hours = log.value.hours;\n log.value.hours = this.reduceToLength(hours, maxLength);\n },\n reduceMinsToLength: function reduceMinsToLength(id, maxLength) {\n var log = this.getEntryById(id);\n var mins = log.value.minutes;\n log.value.minutes = this.reduceToLength(mins, maxLength);\n },\n reduceToLength: function reduceToLength(value, maxLength) {\n if (value.length <= maxLength) {\n return value;\n }\n\n return \"9\".padStart(maxLength, \"9\");\n },\n editLogNoValueOverride: function editLogNoValueOverride(id) {\n var entry = this.getEditableEntryById(id);\n\n if (!entry) {\n return;\n }\n\n entry.isEditing = true;\n },\n cancelEditLog: function cancelEditLog(id) {\n var entry = this.getEntryById(id);\n entry.isEditing = false;\n entry.value = entry.oldValue;\n },\n saveLog: function saveLog(id) {\n var _this7 = this;\n\n var thisLog = this.getEntryById(id);\n thisLog.isWorking = true;\n thisLog.error = null;\n thisLog.value.startDate = thisLog.value.startDate || null;\n thisLog.value.endDate = thisLog.value.endDate || null;\n\n if (noAjax) {\n setTimeout(function () {\n thisLog.id = \"placeholderId\";\n thisLog.oldValue = _objectSpread({}, thisLog.value);\n thisLog.isWorking = false;\n thisLog.isEditing = false;\n thisLog.isRecentlySaved = true;\n new window.ibis.Notification(\"Activity log saved.\", {\n transitionInDuration: 300,\n duration: 5000,\n transitionOutDuration: 300\n });\n setTimeout(function () {\n thisLog.isRecentlySaved = false;\n }, 2500);\n }, 1000);\n } else {\n _axios.default.post($module.dataset.endpointSaveLog, {\n params: {\n id: thisLog.hasTemporaryId ? null : thisLog.id,\n data: JSON.stringify(thisLog)\n }\n }, {\n headers: {}\n }).then(function (response) {\n thisLog.id = response.data.id;\n thisLog.hasTemporaryId = false;\n thisLog.oldValue = _objectSpread({}, thisLog.value);\n thisLog.isRecentlySaved = true;\n\n if (response.data.successMessage) {\n new window.ibis.Notification(response.data.successMessage, {\n transitionInDuration: 300,\n duration: 5000,\n transitionOutDuration: 300\n });\n }\n\n setTimeout(function () {\n thisLog.isRecentlySaved = false;\n }, 2500);\n thisLog.isEditing = false;\n }).catch(function (err) {\n thisLog.error = _this7.handleAxiosError(err);\n }).then(function () {\n thisLog.isWorking = false;\n });\n }\n },\n deleteLog: function deleteLog(id) {\n var _this8 = this;\n\n var thisLog = this.getEntryById(id);\n var confirmMessage = \"Delete log?\";\n\n if (thisLog.value.title) {\n confirmMessage = \"Delete log \\\"\".concat(thisLog.value.title, \"\\\"?\");\n }\n\n if (!window.confirm(confirmMessage)) {\n return;\n }\n\n thisLog.isWorking = true;\n this.state.error = null;\n\n if (noAjax) {\n this.removeLogById(id);\n thisLog.isWorking = false;\n } else {\n // TODO: AJAX request\n _axios.default.post($module.dataset.endpointDeleteLog, {\n params: {\n id: id\n }\n }, {\n headers: {}\n }).then(function (response) {\n _this8.removeLogById(id);\n }).catch(function (err) {\n thisLog.error = _this8.handleAxiosError(err);\n }).then(function () {\n thisLog.isWorking = false;\n });\n }\n },\n toggleLogState: function toggleLogState(e, index) {\n this.displayedLogs[index].isOpen = e.target.open;\n },\n updateLogDuration: function updateLogDuration(id) {\n var entry = this.getEntryById(id);\n entry.value.duration = this.getDuration(entry);\n },\n updateLogCompletion: function updateLogCompletion(event, id) {\n var thisLog = this.getEntryById(id); // If setting to false...\n // unpopulate the end date...\n // but only if the end date was autopopulated in the first place...\n // then just leave\n\n if (!event.target.checked) {\n if (thisLog.autopopulatedEndDate) {\n thisLog.value.endDate = \"\";\n }\n\n return;\n } // If setting to true, and the end date is empty, set it to today\n\n\n if (!thisLog.value.endDate) {\n thisLog.autopopulatedEndDate = true;\n thisLog.value.endDate = new Date().toISOString().substring(0, 10);\n }\n },\n getEditableEntryById: function getEditableEntryById(id) {\n var entry = this.getEntryById(id);\n return entry && !entry.isEditing ? entry : null;\n },\n getEntryById: function getEntryById(id) {\n var entry = this.logs.find(function (e) {\n return e.id === id;\n });\n\n if (!entry) {\n throw new Error(\"Unable to locate log entry with id \\\"\".concat(id, \"\\\"\"));\n }\n\n return entry;\n },\n removeLogById: function removeLogById(id) {\n var entryIndex = this.getEntryIndexById(id);\n this.logs.splice(entryIndex, 1);\n },\n getEntryIndexById: function getEntryIndexById(id) {\n var entryIndex = this.logs.findIndex(function (e) {\n return e.id === id;\n });\n\n if (entryIndex === -1) {\n throw new Error(\"Unable to locate log entry with id \\\"\".concat(id, \"\\\"\"));\n }\n\n return entryIndex;\n },\n\n /**\n * SORTING AND FILTERING FUNCTIONALITY\n */\n sortLogs: function sortLogs(arr) {\n var order = \"\";\n var property = null;\n var format = null;\n\n switch (this.displayOptions.sort) {\n case \"ActivityTitleDesc\":\n order = \"DESC\";\n property = \"oldValue.title\";\n break;\n\n case \"ActivityTitleAsc\":\n order = \"ASC\";\n property = \"oldValue.title\";\n break;\n\n case \"LengthDesc\":\n order = \"DESC\";\n property = \"oldValue.duration\";\n break;\n\n case \"LengthAsc\":\n order = \"ASC\";\n property = \"oldValue.duration\";\n break;\n\n case \"DateAddedAsc\":\n order = \"ASC\";\n property = \"oldValue.creationDate\";\n format = \"date\";\n break;\n\n case \"DateAddedDesc\":\n default:\n order = \"DESC\";\n property = \"oldValue.creationDate\";\n format = \"date\";\n break;\n }\n\n var sortFunction = function sortFunction(arr, prop, order) {\n // HT: https://stackoverflow.com/a/5073866\n prop = prop.split(\".\");\n var len = prop.length;\n arr.sort(function (a, b) {\n var i = 0;\n\n while (i < len) {\n a = a[prop[i]];\n b = b[prop[i]];\n i++;\n }\n\n if (format === \"date\") {\n a = new Date(a);\n b = new Date(b);\n } else if (typeof a === \"string\" && typeof b === \"string\") {\n a = a.toUpperCase();\n b = b.toUpperCase();\n } else if (typeof a === \"string\" && typeof b === \"string\") {\n a = a.toUpperCase();\n b = b.toUpperCase();\n }\n\n if (order === \"ASC\") {\n return a < b ? -1 : a > b ? 1 : 0;\n }\n\n return a > b ? -1 : a < b ? 1 : 0;\n });\n return arr;\n };\n\n return sortFunction(arr, property, order);\n },\n filterLogsByDate: function filterLogsByDate(arr) {\n var createDateWithNoTime = function createDateWithNoTime(dateValue) {\n var date = new Date(dateValue);\n return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));\n };\n\n var filterStartDate = this.displayOptions.startDate ? createDateWithNoTime(this.displayOptions.startDate) : null;\n var filterEndDate = this.displayOptions.endDate ? createDateWithNoTime(this.displayOptions.endDate) : null;\n\n if (!filterStartDate && !filterEndDate) {\n return arr;\n }\n\n return arr.filter(function (item) {\n var itemStartDate = item.oldValue.startDate ? createDateWithNoTime(item.oldValue.startDate) : null;\n var itemEndDate = item.oldValue.endDate ? createDateWithNoTime(item.oldValue.endDate) : null;\n\n if (!itemStartDate && !itemEndDate) {\n return false;\n }\n\n if (!itemStartDate) {\n itemStartDate = itemEndDate;\n } else if (!itemEndDate) {\n itemEndDate = itemStartDate;\n }\n\n if (filterStartDate && filterEndDate) {\n return (itemStartDate >= filterStartDate || itemEndDate >= filterStartDate) && (itemStartDate <= filterEndDate || itemEndDate <= filterEndDate);\n } else if (filterStartDate) {\n return itemStartDate >= filterStartDate || itemEndDate >= filterStartDate;\n } else {\n return itemStartDate <= filterEndDate || itemEndDate <= filterEndDate;\n }\n });\n },\n getDuration: function getDuration(logEntry) {\n var hours = logEntry.value.hours || 0;\n var minutes = logEntry.value.minutes || 0;\n return this.convertTimeToDuration(hours, minutes);\n }\n },\n computed: {\n cpdGraphValidLogs: function cpdGraphValidLogs() {\n if (!this.cpdGraph.date) {\n return [];\n }\n\n var rangeEnd = new Date(this.cpdGraph.date);\n var rangeStart = new Date(rangeEnd).setMonth(rangeEnd.getMonth() - 12); // -1 year\n\n return this.logs.filter(function (item) {\n // We only compare against the log's end date according to client spec,\n // But if there's no end date we assume it's the same as the start date\n var itemDate = new Date(item.value.endDate || item.value.startDate);\n return itemDate <= rangeEnd && itemDate > rangeStart;\n });\n },\n completeCPDHours: function completeCPDHours() {\n var _this9 = this;\n\n var total = this.cpdGraphValidLogs.reduce(function (accum, item) {\n if (item.value.complete === true) {\n return accum + _this9.getDuration(item);\n }\n\n return accum;\n }, 0);\n return total;\n },\n incompleteCPDHours: function incompleteCPDHours() {\n var _this10 = this;\n\n var total = this.cpdGraphValidLogs.reduce(function (accum, item) {\n if (item.value.complete === false) {\n return accum + _this10.getDuration(item);\n }\n\n return accum;\n }, 0);\n return total;\n },\n cpdHourTargetDate: function cpdHourTargetDate() {\n if (!this.cpdGraph.date) {\n return \"(no date set)\";\n }\n\n var date = new Date(this.cpdGraph.date);\n return new Intl.DateTimeFormat(\"en-GB\", {\n day: \"numeric\",\n month: \"short\",\n year: \"numeric\"\n }).format(date);\n },\n completeCPDHoursDonutRing: function completeCPDHoursDonutRing() {\n var percentFilled = this.completeCPDHours / 60 / this.displayOptions.cpdTargetHours * 100;\n return \"\".concat(percentFilled, \" \").concat(100 - percentFilled);\n },\n incompleteCPDHoursDonutRing: function incompleteCPDHoursDonutRing() {\n var percentFilled = this.incompleteCPDHours / 60 / this.displayOptions.cpdTargetHours * 100;\n return \"\".concat(percentFilled, \" \").concat(100 - percentFilled);\n },\n displayedLogs: function displayedLogs() {\n var logs = this.logs; // Filter by start/end dates\n\n logs = this.filterLogsByDate(logs); // Sort logs\n\n logs = this.sortLogs(logs);\n return logs;\n },\n logFilterStatus: function logFilterStatus() {\n var returnedString = \"\"; // Number of displayed logs\n\n returnedString += \"Showing \".concat(this.displayedLogs.length, \" \").concat(this.displayedLogs.length === 1 ? \"activity\" : \"activities\"); // Date filters\n\n if (this.displayOptions.startDate && this.displayOptions.endDate) {\n returnedString += \" from between \".concat(this.displayOptions.startDate, \" and \").concat(this.displayOptions.endDate, \"\");\n } else if (this.displayOptions.startDate) {\n returnedString += \" from \".concat(this.displayOptions.startDate, \"\");\n } else if (this.displayOptions.endDate) {\n returnedString += \" from before \".concat(this.displayOptions.endDate, \"\");\n }\n\n returnedString += \".\"; // Sort setting\n\n switch (this.displayOptions.sort) {\n case \"ActivityTitleDesc\":\n returnedString += \" Sorted by activity title (Z to A).\";\n break;\n\n case \"ActivityTitleAsc\":\n returnedString += \" Sorted by activity title (A to Z).\";\n break;\n\n case \"LengthDesc\":\n returnedString += \" Sorted by CPD hours (most to least).\";\n break;\n\n case \"LengthAsc\":\n returnedString += \" Sorted by CPD hours (least to most).\";\n break;\n\n case \"DateAddedAsc\":\n returnedString += \" Sorted by date added (oldest to newest).\";\n break;\n\n case \"DateAddedDesc\":\n default:\n returnedString += \" Sorted by date added (newest to oldest).\";\n break;\n }\n\n return returnedString;\n }\n }\n });\n};\n\nexports.default = CPDApp;\n\n},{\"../../src/js/global/helper\":177,\"axios\":35,\"vue/dist/vue.js\":173}],8:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _pikaday = _interopRequireDefault(require(\"pikaday\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar Datepicker =\n/*#__PURE__*/\nfunction () {\n function Datepicker($module) {\n var settings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, Datepicker);\n\n this.$module = $module;\n this.userConfig = settings;\n this.picker = null;\n this.initPicker();\n }\n\n _createClass(Datepicker, [{\n key: \"initPicker\",\n value: function initPicker() {\n var _this = this;\n\n // Convert field to `text` type (keeping it as `date` will mess stuff up)\n this.$module.setAttribute(\"type\", \"text\");\n this.$module.setAttribute(\"hidden\", \"hidden\"); // Create config\n\n var datepickerConfig = Object.assign({}, {\n format: \"YYYY-MM-DD\",\n firstDay: 1,\n showDaysInNextAndPreviousMonths: true,\n theme: \"ibis-datepicker\",\n i18n: {\n previousMonth: \"Previous month\",\n nextMonth: \"Next month\",\n months: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\n weekdays: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\n weekdaysShort: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"]\n },\n onSelect: function onSelect(date) {\n _this.$module.value = _this.picker.toString();\n\n _this.$module.dispatchEvent(new Event(\"change\"));\n }\n }, this.userConfig); // Init Pikaday\n\n this.picker = new _pikaday.default(datepickerConfig); // If a value is already set\n\n if (this.$module.value) {\n this.picker.setDate(this.$module.value);\n } // Conditional settings - Minimum date\n\n\n if (this.$module.getAttribute(\"min\")) {\n this.setMinDate(new Date(this.$module.getAttribute(\"min\")));\n } // Conditional settings - Max date\n\n\n if (this.$module.getAttribute(\"max\")) {\n this.setMaxDate(new Date(this.$module.getAttribute(\"max\")));\n } // Insert into DOM\n\n\n this.$module.parentNode.insertBefore(this.picker.el, this.$module.nextSibling);\n }\n }, {\n key: \"setMinDate\",\n value: function setMinDate(date) {\n this.picker.setMinDate(date);\n }\n }, {\n key: \"setMaxDate\",\n value: function setMaxDate(date) {\n this.picker.setMaxDate(date);\n }\n }]);\n\n return Datepicker;\n}();\n\nexports.default = Datepicker;\n\n},{\"pikaday\":165}],9:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar DetailsGroup =\n/*#__PURE__*/\nfunction () {\n function DetailsGroup($module) {\n var settings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, DetailsGroup);\n\n this.$container = $module;\n var defaultSettings = {\n forceSingle: false\n };\n this.settings = Object.assign({}, defaultSettings, settings);\n this.$allModules = $module.querySelectorAll(\".ibis-details\");\n this.create();\n }\n\n _createClass(DetailsGroup, [{\n key: \"create\",\n value: function create() {\n var _this = this;\n\n this.$allModules.forEach(function ($module) {\n if (_this.settings.forceSingle) {\n $module.bindToggle = _this.onSingleToggle.bind(_this);\n $module.addEventListener(\"toggle\", $module.bindToggle);\n }\n\n var $nextButton = $module.querySelector(\"[data-details-group-next]\");\n\n if ($nextButton) {\n $nextButton.bindNext = _this.onNextButton.bind(_this);\n $nextButton.addEventListener(\"click\", $nextButton.bindNext);\n }\n });\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n var _this2 = this;\n\n this.$allModules.forEach(function ($module) {\n if (_this2.settings.forceSingle) {\n $module.removeEventListener(\"toggle\", $module.bindToggle);\n }\n\n var $nextButton = $module.querySelector(\"[data-details-group-next]\");\n $nextButton.removeEventListener(\"click\", $nextButton.bindNext);\n });\n }\n }, {\n key: \"onSingleToggle\",\n value: function onSingleToggle(e) {\n if (!e.target.hasAttribute(\"open\")) {\n return;\n }\n\n var $openModules = Array.from(this.$container.querySelectorAll(\".ibis-details[open]\"));\n $openModules.forEach(function ($module) {\n if ($module === e.target) {\n return;\n }\n\n $module.removeAttribute(\"open\");\n });\n }\n }, {\n key: \"onNextButton\",\n value: function onNextButton(e) {\n var $parent = e.target.closest(\".ibis-details\");\n var $next = $parent.nextElementSibling;\n $parent.removeAttribute(\"open\");\n\n if ($next && $next.tagName === \"DETAILS\") {\n $next.setAttribute(\"open\", \"open\");\n }\n }\n }]);\n\n return DetailsGroup;\n}();\n\nexports.default = DetailsGroup;\n\n},{}],10:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _helper = _interopRequireDefault(require(\"../../src/js/global/helper\"));\n\nvar _dialogPolyfill = _interopRequireDefault(require(\"dialog-polyfill\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar Dialog =\n/*#__PURE__*/\nfunction () {\n function Dialog($module) {\n _classCallCheck(this, Dialog);\n\n this.$module = $module;\n\n _dialogPolyfill.default.registerDialog(this.$module);\n\n this.bindControls();\n }\n\n _createClass(Dialog, [{\n key: \"bindControls\",\n value: function bindControls() {\n var _this = this;\n\n // Close buttons within the nodal\n var $closeButtons = this.$module.querySelectorAll(\"[data-close]\");\n $closeButtons.forEach(function (button) {\n button.addEventListener(\"click\", function () {\n _this.$module.close();\n }, false);\n }); // Escape key\n\n var keyCodes = _helper.default.keyCodes();\n\n document.addEventListener(\"keyup\", function (e) {\n var key = e.which || e.keyCode;\n\n if (key === keyCodes.ESCAPE && _this.$module.open) {\n _this.$module.close();\n }\n }, false);\n }\n }]);\n\n return Dialog;\n}();\n\nexports.default = Dialog;\n\n},{\"../../src/js/global/helper\":177,\"dialog-polyfill\":65}],11:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar FileUpload =\n/*#__PURE__*/\nfunction () {\n function FileUpload($module) {\n _classCallCheck(this, FileUpload);\n\n this.$module = $module;\n this.initPreviewImage();\n }\n\n _createClass(FileUpload, [{\n key: \"initPreviewImage\",\n value: function initPreviewImage() {\n // Preflight: Is the data attribute set and populated?\n if (!this.$module.dataset.previewId) {\n return;\n } // Preflight: Does the target exist?\n\n\n var $target = document.getElementById(this.$module.dataset.previewId);\n\n if (!$target) {\n return;\n } // Preflight: Is the target an element?\n\n\n if ($target.tagName !== \"IMG\") {\n return;\n } // Preflight: Does the input have the `multiple` attribute?\n\n\n if (this.$module.getAttribute(\"multiple\") !== null) {\n return;\n } // Let us continue...\n\n\n var readURL = function readURL(input) {\n if (input.files && input.files[0]) {\n var reader = new FileReader();\n\n reader.onload = function (e) {\n $target.setAttribute(\"src\", e.target.result);\n };\n\n reader.readAsDataURL(input.files[0]);\n }\n };\n\n this.$module.addEventListener(\"change\", function () {\n readURL(this);\n });\n }\n }]);\n\n return FileUpload;\n}();\n\nexports.default = FileUpload;\n\n},{}],12:[function(require,module,exports){\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _umbrellajs = _interopRequireDefault(require(\"umbrellajs\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar Form =\n/*#__PURE__*/\nfunction () {\n // TODO: Show summary of errors at top of form.\n function Form(form) {\n _classCallCheck(this, Form);\n\n this.$form = (0, _umbrellajs.default)(form);\n this.debug = false; // Form validation — no not initialize if form has `novalidate`\n\n if (!form.noValidate) {\n this.initFormValidation();\n } // Form state checking\n\n\n if (this.debug) console.log(_typeof(form.dataset.doNotPromptUnload));\n\n if (typeof form.dataset.doNotPromptUnload === \"undefined\") {\n this.incompleteFormNavigationWarning();\n }\n }\n\n _createClass(Form, [{\n key: \"initFormValidation\",\n value: function initFormValidation() {\n // Track state\n this.formPassesValidation = false;\n this.clickedSubmitButton = false;\n this.formErrorList = []; // Add `novalidate` attribute to form so that the browser doesn't display\n // native errors, as we're handling those manually.\n\n this.$form.attr(\"novalidate\", \"novalidate\");\n if (this.debug) console.log(\"Added `novalidate` attribute to form.\", this.$form); // Bind validation events\n\n this.bindControls();\n }\n }, {\n key: \"bindControls\",\n value: function bindControls() {\n var _this = this;\n\n if (this.debug) console.log(\"Started bindControls.\"); // If the user clicked a submit button on the form, track which one it is.\n // There might be name/value information on it we don't want to lose.\n\n this.$form.on(\"click\", '[type=\"submit\"]', function (e) {\n _this.clickedSubmitButton = e.currentTarget;\n if (_this.debug) console.log(\"Populated clickedSubmitButton.\", _this.clickedSubmitButton);\n }); // Intercept form submit to perform validation\n\n this.$form.on(\"submit\", function (submitEvent) {\n if (!(submitEvent instanceof SubmitEvent)) {\n throw new TypeError('Event is not of type \"SubmitEvent\".');\n }\n\n if (submitEvent.submitter.formNoValidate) {\n if (_this.debug) {\n console.debug(\"Form submitted by clicking a button element with formNoValidate=true.\");\n }\n\n return;\n } else if (_this.debug) {\n console.debug(\"Form submitted wby clicking a button element with formNoValidate=false.\");\n }\n\n if (!_this.formPassesValidation) {\n // The form hasn't been validated or failed the last attempt to\n // validate it. Prevent submission while we check it out.\n submitEvent.preventDefault();\n\n _this.findErrors();\n }\n });\n if (this.debug) console.log(\"Completed bindControls.\");\n }\n }, {\n key: \"findErrors\",\n value: function findErrors() {\n var _this2 = this;\n\n if (this.debug) console.log(\"Looking for errors...\"); // Clear error list, as we're about to repopulate it.\n\n this.formErrorList = []; // Find and loop through all the inputs. This includes inputs that are\n // hidden (either of the `hidden` type, or just not visible on screen),\n // keep that in mind.\n\n var $inputs = this.$form.find(\"input, select, textarea, button\");\n $inputs.each(function (currentInput, i) {\n if (_this2.debug) console.dir(currentInput);\n\n if (!currentInput.validity.valid) {\n if (_this2.debug) console.log(\"NOT VALID\", currentInput.validity); // IE: Check if this input is inside of a