UNPKG

@cxco/ui-faq

Version:

FAQ Module using @cxco default packages

471 lines (406 loc) 15.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.actions = actions; var _index = require("../utils/index.js"); function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _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); } var debug = require('debug')('cxco:ui-faq.actions'); function actions(core) { /** * Checks current url with regex pattern to retrieve * Category and FAQ information * @param {string} urlQuestion */ function getURLParameters(urlQuestion) { var expression = (0, _index.urlRegexBuilder)(urlQuestion); var exp = new RegExp(expression, 'i'); var matches = window.location.hash.match(exp); /* regex matches: 0: full match 1: category crumbs 2: category name 3: faq id 4: faq */ if (matches !== null) { var ids = matches[1].split('-').map(function (i) { return Number(i); }); var faqId = isNaN(Number(matches[3])) ? undefined : Number(matches[3]); return { selectedCategories: ids, categoryName: matches[2], faqId: faqId, faq: matches[4] }; } return undefined; } /** * Shallow compare two objects via stringification. So property order matters. * @param {Object} obj1 * @param {Object} obj2 */ function shallowObjectEquals(obj1, obj2) { if (_typeof(obj1) !== _typeof(obj2)) { return false; } return JSON.stringify(Object.values(obj1)) === JSON.stringify(Object.values(obj2)); } return { /** * Initialize FAQ Module */ botReady: function botReady() { return function (state, actions) { debug('init Default FAQ Module'); }; }, onAnswer: function onAnswer(response) { return function (state, actions) { // category type response is triggered when the module loads. if (response.data.type === 'category') { var categories = response.data.result; actions.preLoadFaq(categories); return { categories: categories }; } // answer type is the FAQ output request if (response.data.type === 'answer') { var faqs = state.faqs.map(function (f) { if (f.id === response.metadata.id) { f.answer = response.data.answer; f.feedback = { interactionId: response.metadata.interactionId, shouldShowTextarea: false, message: state.feedback.intro }; } return f; }); var params = getURLParameters(state.urlQuestion); if (params) { (0, _index.scrollToEnd)(); } return { faqs: faqs }; } }; }, loadCategories: function loadCategories() { return function (state, actions) { var _core$config$classifi, _core$config; var classificationId = (_core$config$classifi = (_core$config = core.config) === null || _core$config === void 0 ? void 0 : _core$config.classificationId) !== null && _core$config$classifi !== void 0 ? _core$config$classifi : state.classificationId; var faqPayload = { data: { classificationId: classificationId }, metadata: { includeFaqs: true } }; core.getAllFaqs(faqPayload); }; }, /** * Updates URL hash * @param {{ selectedCategories: Array.<number>, categoryName: string, faqId: number, faq: string }} urlProperties */ updateUrlProperties: function updateUrlProperties(urlProperties) { return function (state, actions) { var selectedCategories = urlProperties.selectedCategories, categoryName = urlProperties.categoryName, faqId = urlProperties.faqId, faq = urlProperties.faq; // no category is selected if (selectedCategories && selectedCategories[0] === -1) { window.location.hash = ''; } else { var hash = state.urlQuestion.replace(/{categorycrumbs}/i, selectedCategories.filter(function (id) { return id > 0; }).join('-')).replace(/{categoryname}/i, categoryName).replace(/{faqid}/i, faqId || ''); hash = faq ? hash.replace(/{question}/i, faq) : hash.replace(/\/?{question}/i, ''); window.location.hash = hash; } return { urlProperties: urlProperties }; }; }, /** * checks if URL contains urlQuestion to pre-select elements **/ preLoadFaq: function preLoadFaq(categories) { return function (state, actions) { var params = getURLParameters(state.urlQuestion); var newState = {}; if (params && !shallowObjectEquals(newState.urlProperties, params)) { actions.updateUrlProperties(params); try { var selectedCategories = params.selectedCategories; var cat = (0, _index.getCategoryById)(selectedCategories[selectedCategories.length - 1], categories); if (cat.subCategories.length > 0) { selectedCategories = [].concat(_toConsumableArray(selectedCategories), [-1]); } newState.depth = selectedCategories.length - 1; newState.selectedCategories = selectedCategories; newState.catItem = cat; newState.faqs = newState.catItem.items.map(function (faq) { if (faq.id === params.faqId) { faq.isSelected = true; } faq.feedback = faq.feedback || {}; return faq; }); } catch (error) { debug(error); var _cat = (0, _index.prepareAndCategoriesByFaqId)(categories, params.faqId, ''); newState.selectedCategories = _cat.categoryCrumbs.split('-').map(function (n) { return Number(n); }); newState.depth = newState.selectedCategories.length - 1; newState.catItem = (0, _index.getCategoryById)(newState.selectedCategories[newState.depth], categories); newState.faqs = newState.catItem.items.map(function (faq) { if (faq.id === params.faqId) { faq.isSelected = true; } faq.feedback = faq.feedback || {}; return faq; }); } if (params.faqId) { actions.faqClick({ id: params.faqId, isPreloaded: true }); } } return newState; }; }, storeStateInStorage: function storeStateInStorage() { return function (state) { core.store(state, 'faq'); }; }, /** * When the user clicks a category could be toggling it on or off. * @param {Object} category */ categoryClick: function categoryClick(category) { return function (state, actions) { debug('category clicked', category); var selectedCategories = (0, _index.toggleCategory)(category, state.selectedCategories); if (state.updateUrl) { // when toggling off the clicked category isn't selected anymore. var isTogglingOff = !selectedCategories.some(function (c) { return c === category.id; }); var params = { selectedCategories: selectedCategories, categoryName: category.name, faqId: '', faq: '' }; if (isTogglingOff) { // remove any -1 in the list and get the last cat. var id = selectedCategories.filter(function (catId) { return catId !== -1; }).pop(); if (id) { // find the active cat var activeCat = (0, _index.getCategoryById)(id, state.categories); params.categoryName = activeCat.name; } else { // deselect all params.categoryName = ''; } } actions.updateUrlProperties(params); } actions.resetActiveFaqs(); // when deselected empty FAQ array return { selectedCategories: selectedCategories, faqs: category.isSelected ? [] : category.items, depth: category.depth, currentCategory: category.name }; }; }, /** * FAQ click action. Toggles the isSelected state and makes API call if needed. */ faqClick: function faqClick(faq) { return function (state, actions) { var id = faq.id, question = faq.question, answer = faq.answer, isPreloaded = faq.isPreloaded; debug('faq clicked', faq); if (!answer && id) { if (state.updateUrl) { var params = getURLParameters(state.urlQuestion); params.faqId = id; params.faq = question || params.faq; if (!shallowObjectEquals(state.urlProperties, params)) { actions.updateUrlProperties(params); } } // to avoid double request if (!state.faqs.some(function (f) { return f.id === id && f.isSelected && typeof answer !== 'undefined'; })) { core.faqAsk(faq.id); } } var faqs = state.faqs.map(function (f) { if (f.id === faq.id) { if (typeof f.isSelected === 'undefined') { f.isSelected = true; } else { if (isPreloaded) { f.isSelected = true; } else { f.isSelected = !f.isSelected; } } } if (typeof f.feedback === 'undefined') { f.feedback = {}; } return f; }); return { faqs: faqs }; }; }, handleClick: function handleClick(_ref) { var interactionId = _ref.interactionId, linkUrl = _ref.linkUrl, linkId = _ref.linkId; return function (state, actions) { core.sendLinkClick({ data: { interactionId: interactionId, linkUrl: linkUrl, linkId: linkId } }); }; }, setWidth: function setWidth(width) { return function (state, actions) { return { width: width }; }; }, setNodesInView: function setNodesInView(nodesInView) { return function (state, actions) { return { nodesInView: nodesInView }; }; }, resetActiveFaqs: function resetActiveFaqs() { return function (state) { var faqs = state.faqs.map(function (f) { return f.isSelected = false; }); return { faqs: faqs }; }; }, resize: function resize(elm) { return function (state, actions) { var fontSize = window.getComputedStyle(document.documentElement, null).fontSize; fontSize = parseFloat(fontSize) || 16; var appWidth = Math.ceil(elm.offsetWidth / fontSize); var minWidthArr = []; // maximum amount of breakpoints. var max = state.maxBreakpoints || 3; // amount of size increment in each "breakpoint". var step = 20; for (var i = 1; i <= max; i++) { var val = step * i; if (appWidth >= val) { minWidthArr.push("".concat(val, "rem")); } } actions.setWidth(minWidthArr.join(' ')); actions.setNodesInView(minWidthArr.length); (0, _index.scrollToEnd)(); }; }, hashChanged: function hashChanged() { return function (state, actions) { var params = getURLParameters(state.urlQuestion); if (params && typeof params.faq !== 'undefined') { actions.preLoadFaq(state.categories); } }; }, /** * Send Feedback or Show text area on negative feedback. * If score is negative but there is no comment then show the textarea. * Negative feedback is submitted once comment isn't empty. * @param {Object} faq */ feedbackClick: function feedbackClick(faq) { return function (state, actions) { var feedback = faq.feedback; var score = feedback.score, interactionId = feedback.interactionId, comment = feedback.comment, label = feedback.label; var hasComment = typeof comment !== 'undefined' && comment !== ''; var feedbackPayload = { data: { score: score, interactionId: interactionId, comment: comment, label: label } }; if (feedback.score > 0) { core.sendFeedback(feedbackPayload); var faqs = state.faqs.map(function (f) { if (f.id === faq.id) { f.feedback.shouldShowTextarea = false; f.feedback.message = state.feedback.thanks; f.feedback.sent = true; } return f; }); return { faqs: faqs }; } else { var _faqs = state.faqs.map(function (f) { if (f.id === faq.id) { f.feedback.shouldShowTextarea = !hasComment; if (hasComment) { f.feedback.message = state.feedback.thanks; f.feedback.sent = true; } } return f; }); if (hasComment) { core.sendFeedback(feedbackPayload); } return { faqs: _faqs }; } }; } }; }