From 6b40ec0a11225fc4c2cc227f399edd3633eae44c Mon Sep 17 00:00:00 2001 From: tmont Date: Sun, 21 Feb 2021 11:52:43 -0800 Subject: [PATCH] persist checkbox state for apprentices and locations --- package-lock.json | 6 ++ package.json | 1 + scripts/client-deps.sh | 1 + web/static/js.cookie.js | 163 ++++++++++++++++++++++++++++++++++++++++ web/static/saga.js | 58 ++++++++++++-- web/views/master.pug | 1 + 6 files changed, 224 insertions(+), 6 deletions(-) create mode 100644 web/static/js.cookie.js diff --git a/package-lock.json b/package-lock.json index 608fcf9..9d4a42b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -449,6 +449,12 @@ "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", "dev": true }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", + "dev": true + }, "js-stringify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", diff --git a/package.json b/package.json index 0079a5d..bf7a28c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "bootstrap": "4.6.0", "bootstrap-icons": "1.3.0", "express": "4.17.1", + "js-cookie": "2.2.1", "jquery": "3.5.1", "node-dev": "6.2.0", "popper.js": "1.16.1", diff --git a/scripts/client-deps.sh b/scripts/client-deps.sh index 5242439..aab7baf 100755 --- a/scripts/client-deps.sh +++ b/scripts/client-deps.sh @@ -16,4 +16,5 @@ cp -r \ "${nodeDir}"/bootstrap-icons/font/fonts/ \ "${nodeDir}"/jquery/dist/jquery.js \ "${nodeDir}"/popper.js/dist/umd/popper.js \ + "${nodeDir}"/js-cookie/src/js.cookie.js \ "${targetDir}" diff --git a/web/static/js.cookie.js b/web/static/js.cookie.js new file mode 100644 index 0000000..80a7551 --- /dev/null +++ b/web/static/js.cookie.js @@ -0,0 +1,163 @@ +/*! + * JavaScript Cookie v2.2.1 + * https://github.com/js-cookie/js-cookie + * + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack + * Released under the MIT license + */ +;(function (factory) { + var registeredInModuleLoader; + if (typeof define === 'function' && define.amd) { + define(factory); + registeredInModuleLoader = true; + } + if (typeof exports === 'object') { + module.exports = factory(); + registeredInModuleLoader = true; + } + if (!registeredInModuleLoader) { + var OldCookies = window.Cookies; + var api = window.Cookies = factory(); + api.noConflict = function () { + window.Cookies = OldCookies; + return api; + }; + } +}(function () { + function extend () { + var i = 0; + var result = {}; + for (; i < arguments.length; i++) { + var attributes = arguments[ i ]; + for (var key in attributes) { + result[key] = attributes[key]; + } + } + return result; + } + + function decode (s) { + return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent); + } + + function init (converter) { + function api() {} + + function set (key, value, attributes) { + if (typeof document === 'undefined') { + return; + } + + attributes = extend({ + path: '/' + }, api.defaults, attributes); + + if (typeof attributes.expires === 'number') { + attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5); + } + + // We're using "expires" because "max-age" is not supported by IE + attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; + + try { + var result = JSON.stringify(value); + if (/^[\{\[]/.test(result)) { + value = result; + } + } catch (e) {} + + value = converter.write ? + converter.write(value, key) : + encodeURIComponent(String(value)) + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); + + key = encodeURIComponent(String(key)) + .replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent) + .replace(/[\(\)]/g, escape); + + var stringifiedAttributes = ''; + for (var attributeName in attributes) { + if (!attributes[attributeName]) { + continue; + } + stringifiedAttributes += '; ' + attributeName; + if (attributes[attributeName] === true) { + continue; + } + + // Considers RFC 6265 section 5.2: + // ... + // 3. If the remaining unparsed-attributes contains a %x3B (";") + // character: + // Consume the characters of the unparsed-attributes up to, + // not including, the first %x3B (";") character. + // ... + stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]; + } + + return (document.cookie = key + '=' + value + stringifiedAttributes); + } + + function get (key, json) { + if (typeof document === 'undefined') { + return; + } + + var jar = {}; + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. + var cookies = document.cookie ? document.cookie.split('; ') : []; + var i = 0; + + for (; i < cookies.length; i++) { + var parts = cookies[i].split('='); + var cookie = parts.slice(1).join('='); + + if (!json && cookie.charAt(0) === '"') { + cookie = cookie.slice(1, -1); + } + + try { + var name = decode(parts[0]); + cookie = (converter.read || converter)(cookie, name) || + decode(cookie); + + if (json) { + try { + cookie = JSON.parse(cookie); + } catch (e) {} + } + + jar[name] = cookie; + + if (key === name) { + break; + } + } catch (e) {} + } + + return key ? jar[key] : jar; + } + + api.set = set; + api.get = function (key) { + return get(key, false /* read as raw */); + }; + api.getJSON = function (key) { + return get(key, true /* read as json */); + }; + api.remove = function (key, attributes) { + set(key, '', extend(attributes, { + expires: -1 + })); + }; + + api.defaults = {}; + + api.withConverter = init; + + return api; + } + + return init(function () {}); +})); diff --git a/web/static/saga.js b/web/static/saga.js index fa3a5c3..68362b5 100644 --- a/web/static/saga.js +++ b/web/static/saga.js @@ -5,6 +5,7 @@ window.saga = { sortData: () => { + console.log('sorting data'); const qs = new URLSearchParams(window.location.search); const col = qs.get('col'); let dir = qs.get('dir'); @@ -91,19 +92,27 @@ }, filterApprentices: () => { - const apprentices = []; + if (!$apprenticeFilterForm.length) { + return; + } + + const checked = []; $apprenticeFilterForm.find('input[type="checkbox"]').toArray().map((input) => { if (input.checked) { - apprentices.push(input.name); + checked.push(input.name); } }); + window.Cookies.set('apprenticeFilter', checked.join(','), { + sameSite: 'strict', + }); + $table .find('tbody.data tr') .hide() .filter((i, row) => { - if (!apprentices.length) { + if (!checked.length) { return true; } @@ -111,22 +120,28 @@ if (!users.length) { return true; } - return apprentices.some((name) => users.includes(name)); + return checked.some((name) => users.includes(name)); }) .show(); }, filterLocations: () => { + if (!$locationFilterForm.length) { + return; + } + const checked = []; - console.log('filter locations'); $locationFilterForm.find('input[type="checkbox"]').toArray().map((input) => { if (input.checked) { - console.log('input checked'); checked.push(input.name); } }); + window.Cookies.set('locationFilter', checked.join(','), { + sameSite: 'strict', + }); + $table .find('tbody.data tr') .hide() @@ -145,12 +160,43 @@ }, }; + const checkLocations = () => { + if (!$locationFilterForm.length) { + return; + } + + try { + window.Cookies.get('locationFilter').split(',').forEach((location) => { + $locationFilterForm.find(`input[type="checkbox"][name="${location}"]`).prop('checked', true); + }); + } catch (e) {} + }; + + const checkApprentices = () => { + if (!$apprenticeFilterForm.length) { + return; + } + + try { + window.Cookies.get('apprenticeFilter').split(',').forEach((apprentice) => { + $apprenticeFilterForm.find(`input[type="checkbox"][name="${apprentice}"]`).prop('checked', true); + }); + } catch (e) {} + }; + + checkLocations(); + checkApprentices(); + window.saga.sortData(); window.saga.filterApprentices(); window.saga.filterLocations(); window.addEventListener('popstate', () => { + checkLocations(); + checkApprentices(); window.saga.sortData(); + window.saga.filterApprentices(); + window.saga.filterLocations(); }); $('.sortable-links a').click(function(e) { diff --git a/web/views/master.pug b/web/views/master.pug index 19f5492..3730ed2 100644 --- a/web/views/master.pug +++ b/web/views/master.pug @@ -53,4 +53,5 @@ html script(src="/static/jquery.js") script(src="/static/popper.js") script(src="/static/bootstrap.js") + script(src="/static/js.cookie.js") script(src="/static/saga.js")