From e371412db48c600589800890477531706a6313bd Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 13 Dec 2019 15:04:52 +0100 Subject: [PATCH] fix(hide-columns): improve positioning BREAKING CHANGE: StorageManager version numbers --- frontend/src/app.js | 3 - .../lib/storage-manager/storage-manager.js | 53 +- frontend/src/polyfill.js | 4 + frontend/src/utils/async-table/async-table.js | 8 +- .../src/utils/hide-columns/hide-columns.js | 40 +- .../src/utils/hide-columns/hide-columns.scss | 73 ++- frontend/src/utils/show-hide/show-hide.js | 2 +- package-lock.json | 82 ++- package.json | 7 +- records.json | 544 ------------------ webpack.config.js | 26 +- 11 files changed, 199 insertions(+), 643 deletions(-) create mode 100644 frontend/src/polyfill.js delete mode 100644 records.json diff --git a/frontend/src/app.js b/frontend/src/app.js index acbc4702a..6aa438405 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -4,9 +4,6 @@ import { I18n } from './services/i18n/i18n'; import { UtilRegistry } from './services/util-registry/util-registry'; import { isValidUtility } from './core/utility'; -// load window.fetch polyfill -import 'whatwg-fetch'; - import './app.scss'; export class App { diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js index d2e407593..ec564c17a 100644 --- a/frontend/src/lib/storage-manager/storage-manager.js +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -1,3 +1,5 @@ +import * as semver from 'semver'; + export const LOCATION = { LOCAL: 'local', WINDOW: 'window', @@ -8,14 +10,19 @@ const LOCATION_SHADOWING = [ LOCATION.WINDOW, LOCATION.LOCAL ]; export class StorageManager { namespace; + version; _options; - constructor(namespace, options) { + constructor(namespace, version, options) { + this.namespace = namespace; + this.version = semver.valid(version); + if (!namespace) { throw new Error('Cannot setup StorageManager without namespace'); } - - this.namespace = namespace; + if (!this.version) { + throw new Error('Cannot setup StorageManager without valid semver version'); + } if (options !== undefined) { this._options = options; @@ -128,20 +135,41 @@ export class StorageManager { _getFromLocalStorage() { - const state = JSON.parse(window.localStorage.getItem(this.namespace)); - if (state === null) { - // remove item from localStorage if it stores an invalid value (cannot be parsed) + let state; + + try { + state = JSON.parse(window.localStorage.getItem(this.namespace)); + } catch { + state = null; + } + + if (state === null || !state.version || !semver.satisfies(this.version, `^${state.version}`)) { + // remove item from localStorage if it stores an invalid state this._clearLocalStorage(); return {}; } - return state; + + if ('state' in state) + return state.state; + else { + delete state.version; + return state; + } } - _saveToLocalStorage(value) { - if (!value) + _saveToLocalStorage(state) { + if (!state) return this._clearLocalStorage(); + + let versionedState; - window.localStorage.setItem(this.namespace, JSON.stringify(value)); + if ('version' in state || 'state' in state) { + versionedState = { version: this.version, state: state }; + } else { + versionedState = { version: this.version, ...state }; + } + + window.localStorage.setItem(this.namespace, JSON.stringify(versionedState)); } _clearLocalStorage() { @@ -156,10 +184,7 @@ export class StorageManager { if (!window.App.Storage) window.App.Storage = {}; - if (!window.App.Storage[this.namespace]) - return {}; - - return window.App.Storage[this.namespace]; + return window.App.Storage[this.namespace] || {}; } _saveToWindow(value) { diff --git a/frontend/src/polyfill.js b/frontend/src/polyfill.js new file mode 100644 index 000000000..27333c1a0 --- /dev/null +++ b/frontend/src/polyfill.js @@ -0,0 +1,4 @@ +import 'whatwg-fetch'; + +import { ResizeObserver as Polyfill } from '@juggle/resize-observer'; +window.ResizeObserver = window.ResizeObserver || Polyfill; diff --git a/frontend/src/utils/async-table/async-table.js b/frontend/src/utils/async-table/async-table.js index 3067e0f1f..80dadca3a 100644 --- a/frontend/src/utils/async-table/async-table.js +++ b/frontend/src/utils/async-table/async-table.js @@ -41,7 +41,7 @@ export class AsyncTable { }; _ignoreRequest = false; - _storageManager = new StorageManager(ASYNC_TABLE_LOCAL_STORAGE_KEY, { location: LOCATION.LOCAL }); + _storageManager = new StorageManager(ASYNC_TABLE_LOCAL_STORAGE_KEY, '1.0.0', { location: LOCATION.WINDOW }); constructor(element, app) { if (!element) { @@ -228,7 +228,7 @@ export class AsyncTable { const prefix = findCssIdPrefix(focusedInput.id); const focusId = focusedInput.id.replace(prefix, ''); callback = function(wrapper) { - const idPrefix = this._storageManager.load('cssIdPrefix', { location: LOCATION.WINDOW }); + const idPrefix = this._storageManager.load('cssIdPrefix'); const toBeFocused = wrapper.querySelector('#' + idPrefix + focusId); if (toBeFocused) { toBeFocused.focus(); @@ -349,9 +349,9 @@ export class AsyncTable { this._app.utilRegistry.setupAll(this._element); if (callback && typeof callback === 'function') { - this._storageManager.save('cssIdPrefix', response.idPrefix, { location: LOCATION.WINDOW }); + this._storageManager.save('cssIdPrefix', response.idPrefix); callback(this._element); - this._storageManager.remove('cssIdPrefix', { location: LOCATION.WINDOW }); + this._storageManager.remove('cssIdPrefix'); } }).catch((err) => console.error(err) ).finally(() => this._element.classList.remove(ASYNC_TABLE_LOADING_CLASS)); diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 420916f41..acedc2375 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -8,7 +8,6 @@ const TABLE_HEADER_IDENT = 'uw-hide-column-header'; const TABLE_UTILS_ATTR = 'table-utils'; const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`; -const TABLE_HIDER_CONTAINER_CLASS = 'table-hiders'; const TABLE_HIDER_CLASS = 'table-hider'; const TABLE_HIDER_VISIBLE_CLASS = 'table-hider--visible'; @@ -22,12 +21,13 @@ const CELL_ORIGINAL_COLSPAN = 'uw-hide-column-original-colspan'; }) export class HideColumns { - _storageManager = new StorageManager('HIDE_COLUMNS', { location: LOCATION.LOCAL }); + _storageManager = new StorageManager('HIDE_COLUMNS', '1.0.0', { location: LOCATION.LOCAL }); _element; _elementWrapper; _tableUtilContainer; - _tableHiderContainer; + + _autoHide; headerToHider = new Map(); hiderToHeader = new Map(); @@ -38,6 +38,8 @@ export class HideColumns { } constructor(element) { + this._autoHide = this._storageManager.load('autoHide', {}) || false; + if (!element) { throw new Error('Hide Columns utility cannot be setup without an element!'); } @@ -64,14 +66,6 @@ export class HideColumns { hideColumnsContainer.insertBefore(this._tableUtilContainer, tableContainer); } - // get or create table hider container before the table - this._tableHiderContainer = this._element.previousSibling; - if (!this._tableHiderContainer || !this._tableHiderContainer.classList.contains(TABLE_HIDER_CONTAINER_CLASS)) { - this._tableHiderContainer = document.createElement('div'); - this._tableHiderContainer.classList.add(TABLE_HIDER_CONTAINER_CLASS); - this._element.parentElement.insertBefore(this._tableHiderContainer, this._element); - } - this._element.querySelectorAll('th').forEach(th => this.setupHideButton(th)); } @@ -102,8 +96,9 @@ export class HideColumns { hider.addEventListener('click', (event) => { event.preventDefault(); + event.stopPropagation(); this.switchColumnDisplay(th, hider); - this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); + // this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); }); hider.addEventListener('mouseover', () => { @@ -119,8 +114,10 @@ export class HideColumns { this.updateHiderIcon(hider, currentlyHidden); }); + new ResizeObserver(() => { this.repositionHider(hider); }).observe(th); + // reposition hider on each window resize event - window.addEventListener('resize', () => this.repositionHider(hider)); + // window.addEventListener('resize', () => this.repositionHider(hider)); this.updateColumnDisplay(this.colIndex(th), preHidden); this.updateHider(hider, preHidden); @@ -130,8 +127,6 @@ export class HideColumns { } else { this.hideHiderBehindHeader(hider); } - - this._tableHiderContainer.children.forEach(hider => this.repositionHider(hider)); } switchColumnDisplay(th, hider) { @@ -146,7 +141,7 @@ export class HideColumns { this.updateHider(hider, hidden); // persist new hidden setting for column - if (hidden && this.isEmptyColumn(columnIndex)) { + if ((hidden && this.isEmptyColumn(columnIndex) && this._autoHide) || (!hidden && (!this.isEmptyColumn(columnIndex) || !this._autoHide))) { this._storageManager.remove(this.getStorageKey(th)); } else { this._storageManager.save(this.getStorageKey(th), hidden); @@ -202,8 +197,8 @@ export class HideColumns { } hideHiderBehindHeader(hider) { - if (!this._tableHiderContainer.contains(hider)) { - this._tableHiderContainer.appendChild(hider); + if (!this.hiderToHeader.get(hider).contains(hider)) { + this.hiderToHeader.get(hider).appendChild(hider); } this.repositionHider(hider); @@ -214,11 +209,10 @@ export class HideColumns { repositionHider(hider) { const thR = this.hiderToHeader.get(hider).getBoundingClientRect(), - hR = hider.getBoundingClientRect(), - pR = this._tableHiderContainer.getBoundingClientRect(); + hR = hider.getBoundingClientRect(); - hider.style.left = (thR.left + thR.width/2 - hR.width/2 - pR.left) + 'px'; - hider.style.top = (thR.top - pR.top + thR.height) + 'px'; + hider.style.left = (thR.width/2 - hR.width/2) + 'px'; + hider.style.top = thR.height + 'px'; } getStorageKey(th) { @@ -266,7 +260,7 @@ export class HideColumns { isHiddenColumn(th) { const hidden = this._storageManager.load(this.getStorageKey(th)), emptyColumn = this.isEmptyColumn(this.colIndex(th)); - return hidden === true || hidden === undefined && emptyColumn; + return hidden === true || hidden === undefined && emptyColumn && this._autoHide; } colSpan(cell) { diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index 77a73bee3..59aab069d 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -1,47 +1,38 @@ -.table-hiders { - position: relative; - max-height: 0px; +.table-hider { + background-color: #fff; + color: var(--color-link); + padding: 10px; + cursor: pointer; + box-shadow: 0 0 2px 0 rgba(0,0,0,0.6); + position: absolute; + overflow: hidden; + transition: transform .2s ease; + transform: scaleY(0); + transform-origin: top; - .table-hider { - background-color: #fff; - color: var(--color-link); - padding: 10px; - cursor: pointer; - box-shadow: 0 0 2px 0 rgba(0,0,0,0.6); - position: absolute; - overflow: hidden; - transition: transform .2s ease; - transform: scaleY(0); - transform-origin: top; - - &:hover { - background-color: var(--color-grey-light); - } - - .table-hider__label { - display: none; - } - - &.table-hider--visible { - transform: scaleY(.4); - transition: none; /* TODO find better way to prevent transition on icons */ - - .fas { - transform: scaleY(2.5); - } - - &:hover { - transform: scaleY(1); - - .fas { - transform: scaleY(1); - } - } - } + &:hover { + background-color: var(--color-grey-light); } - &+.table { - margin-top: 0px; + .table-hider__label { + display: none; + } + + &.table-hider--visible { + transform: scaleY(.4); + transition: none; /* TODO find better way to prevent transition on icons */ + + .fas { + transform: scaleY(2.5); + } + + &:hover { + transform: scaleY(1); + + .fas { + transform: scaleY(1); + } + } } } diff --git a/frontend/src/utils/show-hide/show-hide.js b/frontend/src/utils/show-hide/show-hide.js index c264f3af3..aa1f4f792 100644 --- a/frontend/src/utils/show-hide/show-hide.js +++ b/frontend/src/utils/show-hide/show-hide.js @@ -16,7 +16,7 @@ export class ShowHide { _showHideId; _element; - _storageManager = new StorageManager(SHOW_HIDE_LOCAL_STORAGE_KEY, { location: LOCATION.LOCAL }); + _storageManager = new StorageManager(SHOW_HIDE_LOCAL_STORAGE_KEY, '1.0.0', { location: LOCATION.LOCAL }); constructor(element) { if (!element) { diff --git a/package-lock.json b/package-lock.json index a03239ca5..a1bd61eda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -178,6 +178,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -1907,6 +1913,14 @@ "@babel/helper-plugin-utils": "^7.0.0", "resolve": "^1.8.1", "semver": "^5.5.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "@babel/plugin-transform-shorthand-properties": { @@ -2035,6 +2049,12 @@ "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -2541,6 +2561,11 @@ "integrity": "sha512-EKKR4p0higjsIPKjSSkGqtweUwo/GgR/zKL4rCwzF5Z/BZ/ebJZaS8ZjGE7YUNEN63SYk2WhpJVI+l9dwfU7RQ==", "dev": true }, + "@juggle/resize-observer": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-2.5.0.tgz", + "integrity": "sha512-Nmkeaj5LalJeciRVEqi9Uxi61r0LvGc2yhUCykhXuft9fMyb/6VkZbwJ+UmUl8bk2k6qhwd1qJw6S2YJ0joXlA==" + }, "@marionebl/sander": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/@marionebl/sander/-/sander-0.6.1.tgz", @@ -6277,6 +6302,14 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "crypto-browserify": { @@ -6989,6 +7022,12 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -8608,6 +8647,12 @@ "strip-indent": "^2.0.0" } }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -10348,6 +10393,14 @@ "requires": { "pify": "^4.0.1", "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "mamacro": { @@ -10941,6 +10994,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "normalize-path": { @@ -14352,6 +14413,12 @@ "os-tmpdir": "^1.0.0" } }, + "outdent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.7.0.tgz", + "integrity": "sha512-Ue462G+UIFoyQmOzapGIKWS3d/9NHeD/018WGEDZIhN2/VaQpVXbofMcZX0socv1fw4/tmEn7Vd3McOdPZfKzQ==", + "dev": true + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -15468,9 +15535,9 @@ } }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "semver-compare": { @@ -17555,6 +17622,15 @@ "tapable": "^1.0.0" } }, + "webpack-plugin-hash-output": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/webpack-plugin-hash-output/-/webpack-plugin-hash-output-3.2.1.tgz", + "integrity": "sha512-Iu4Sox3/bdiqd6TdYwZAExuH+XNbnJStPrwh6yhzOflwc/hZUP9MdiZDbFwTXrmm9ZwoXNUmvn7C0Qj4qRez2A==", + "dev": true, + "requires": { + "outdent": "^0.7.0" + } + }, "webpack-sources": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", diff --git a/package.json b/package.json index 1c4af85d9..3361f6443 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "author": "", "license": "ISC", "scripts": { - "start": "run-p frontend:build:watch yesod:start", + "start": "npm-run-all frontend:build --parallel \"frontend:build:watch\" \"yesod:start\"", "test": "run-s frontend:test yesod:test", "lint": "run-s frontend:lint yesod:lint", "build": "run-s frontend:build yesod:build", @@ -90,6 +90,7 @@ "null-loader": "^2.0.0", "postcss-loader": "^3.0.0", "sass-loader": "^7.3.1", + "semver": "^6.3.0", "standard-version": "^6.0.1", "style-loader": "^0.23.1", "terser-webpack-plugin": "^2.2.3", @@ -97,10 +98,12 @@ "typeface-source-sans-pro": "0.0.75", "webpack": "^4.41.2", "webpack-cli": "^3.3.10", - "webpack-manifest-plugin": "^2.2.0" + "webpack-manifest-plugin": "^2.2.0", + "webpack-plugin-hash-output": "^3.2.1" }, "dependencies": { "@babel/runtime": "^7.7.6", + "@juggle/resize-observer": "^2.5.0", "core-js": "^3.4.8", "moment": "^2.24.0", "npm": "^6.13.3", diff --git a/records.json b/records.json deleted file mode 100644 index c3e4f6812..000000000 --- a/records.json +++ /dev/null @@ -1,544 +0,0 @@ -{ - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/typeface-roboto/index.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/typeface-source-sans-pro/index.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/@fortawesome/fontawesome-pro/css/all.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/async-form/async-form.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/asidenav/asidenav.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/show-hide/show-hide.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/inputs/inputs.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/inputs/radio.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/form/form.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/alerts/alerts.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/tooltips/tooltips.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/course-teaser/course-teaser.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/modal/modal.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/navbar/navbar.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/async-table/async-table.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/async-table/async-table-filter.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/mass-input/mass-input.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/inputs/file-input.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/dist/cjs.js!frontend/src/utils/inputs/checkbox.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/postcss-loader/src/index.js!frontend/src/utils/form/datepicker.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - }, - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js??ref--5-2!node_modules/typeface-source-sans-pro/index.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js??ref--5-2!node_modules/typeface-roboto/index.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js??ref--5-2!node_modules/@fortawesome/fontawesome-pro/css/all.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/asidenav/asidenav.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/async-form/async-form.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/show-hide/show-hide.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/form/form.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/inputs/inputs.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/inputs/radio.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/tooltips/tooltips.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/course-teaser/course-teaser.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/modal/modal.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/async-table/async-table.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/async-table/async-table-filter.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/mass-input/mass-input.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/alerts/alerts.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/navbar/navbar.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js??ref--5-2!frontend/src/utils/form/datepicker.css": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/inputs/file-input.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/utils/inputs/checkbox.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ], - "mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/sass-loader/dist/cjs.js??ref--6-3!frontend/src/app.scss": [ - { - "modules": { - "byIdentifier": {}, - "usedIds": {} - }, - "chunks": { - "byName": {}, - "bySource": {}, - "usedIds": [] - } - } - ] -} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 3a93a5bbe..c16c23a9d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,9 +6,10 @@ const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const yaml = require('js-yaml'); +const HashOutput = require('webpack-plugin-hash-output'); -var webpackVersion = require('webpack/package.json').version.split('.').slice(0, 2).join('.'); - +const webpackVersion = require('webpack/package.json').version.split('.').slice(0, 2).join('.'); +const packageVersion = require('./package.json').version; module.exports = { module: { @@ -71,15 +72,21 @@ module.exports = { }, entry: { - main: path.resolve(__dirname, 'frontend/src', 'main.js') + main: [ path.resolve(__dirname, 'frontend/src', 'polyfill.js'), + path.resolve(__dirname, 'frontend/src', 'main.js') + ] }, plugins: [ + new HashOutput({ + validateOutput: true, + validateOutputRegex: /static\/wp-[^\/]\// + }), new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // all options are optional - filename: '[contenthash].css', - chunkFilename: '[contenthash].css', + filename: '[chunkhash].css', + chunkFilename: '[chunkhash].css', ignoreOrder: false, // Enable to remove warnings about conflicting order }), new webpack.NamedChunksPlugin((chunk) => { @@ -101,12 +108,15 @@ module.exports = { new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new CopyPlugin([ { from: 'assets/lmu/sigillum.svg', to: path.resolve(__dirname, 'static', 'img/lmu/sigillum.svg') }, - ]) + ]), + new webpack.DefinePlugin({ + VERSION: JSON.stringify(packageVersion) + }) ], output: { - chunkFilename: '[contenthash].js', - filename: '[contenthash].js', + chunkFilename: '[chunkhash].js', + filename: '[chunkhash].js', path: path.resolve(__dirname, 'static', `wp-${webpackVersion}`), publicPath: `/static/res/wp-${webpackVersion}/`, hashFunction: 'shake256',