From 00aac33199b4f3de133f778f37141eff0f167a4a Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Mon, 16 Dec 2019 14:25:10 +0100 Subject: [PATCH 01/46] refactor(fonts): include fontawesome as scss --- frontend/src/app.js | 5 +---- frontend/src/app.scss | 11 +++++++++++ records.json | 13 +++++++++++++ webpack.config.js | 6 ++++-- 4 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 frontend/src/app.scss diff --git a/frontend/src/app.js b/frontend/src/app.js index 88056f735..acbc4702a 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -7,10 +7,7 @@ import { isValidUtility } from './core/utility'; // load window.fetch polyfill import 'whatwg-fetch'; -import '@fortawesome/fontawesome-pro/css/all.css'; - -import 'typeface-roboto/index.css'; -import 'typeface-source-sans-pro/index.css'; +import './app.scss'; export class App { httpClient = new HttpClient(); diff --git a/frontend/src/app.scss b/frontend/src/app.scss new file mode 100644 index 000000000..5eeb75ecb --- /dev/null +++ b/frontend/src/app.scss @@ -0,0 +1,11 @@ +$fa-font-path: "~@fortawesome/fontawesome-pro/webfonts"; + +@import "@fortawesome/fontawesome-pro/scss/fontawesome.scss"; +@import "@fortawesome/fontawesome-pro/scss/solid.scss"; + + +$roboto: "Roboto"; +@import "~typeface-roboto/index.css"; + +$source-sans: "Source Sans Pro"; +@import "~typeface-source-sans-pro/index.css"; diff --git a/records.json b/records.json index c8c6aed06..c3e4f6812 100644 --- a/records.json +++ b/records.json @@ -527,5 +527,18 @@ "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 96b5db285..3a93a5bbe 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -52,7 +52,7 @@ module.exports = { use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true }}, { loader: 'postcss-loader', options: { sourceMap: true }}, - { loader: 'sass-loader', options: { sourceMap: true }} + { loader: 'sass-loader', options: { sourceMap: true, includePaths: [path.resolve(__dirname, 'node_modules')] }} ] }, { @@ -131,7 +131,9 @@ module.exports = { minChunks: 1, cacheGroups: { vendor: { - test: /[\\/]node_modules[\\/]/, + test(module, chunk) { + return module.context.match(/[\\/]node_modules[\\/]/); + }, name(module, chunks, cacheGroupKey) { const moduleFileName = module.identifier().split('/').reduceRight(item => item); const allChunksNames = chunks.map((item) => item.name).join('~'); From e27bebac59e42857b82e567f07576167bafcf8e3 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 16:26:29 +0100 Subject: [PATCH 02/46] feat(foundation): move stuff out of Foundation --- src/Foundation.hs | 76 +------------------------ src/Foundation/Routes.hs | 84 ++++++++++++++++++++++++++-- src/Foundation/Routes/Definitions.hs | 10 ++++ src/Handler/Utils/Routes.hs | 4 +- 4 files changed, 94 insertions(+), 80 deletions(-) create mode 100644 src/Foundation/Routes/Definitions.hs diff --git a/src/Foundation.hs b/src/Foundation.hs index 3014250a6..1e7d8db89 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -71,6 +71,7 @@ import Handler.Utils.SchoolLdap import Handler.Utils.ExamOffice.Exam import Handler.Utils.ExamOffice.Course import Handler.Utils.Profile +import Handler.Utils.Routes import Utils.Form import Utils.Sheet import Utils.SystemMessage @@ -96,86 +97,12 @@ import qualified Ldap.Client as Ldap import UnliftIO.Pool - --- This is where we define all of the routes in our application. For a full --- explanation of the syntax, please see: --- http://www.yesodweb.com/book/routing-and-handlers --- --- Note that this is really half the story; in Application.hs, mkYesodDispatch --- generates the rest of the code. Please see the following documentation --- for an explanation for this split: --- http://www.yesodweb.com/book/scaffolding-and-the-site-template#scaffolding-and-the-site-template_foundation_and_application_modules --- --- This function also generates the following type synonyms: --- type Handler x = HandlerT UniWorX IO x --- type Widget = WidgetT UniWorX IO () -mkYesodData "UniWorX" uniworxRoutes - -deriving instance Generic CourseR -deriving instance Generic SheetR -deriving instance Generic SubmissionR -deriving instance Generic MaterialR -deriving instance Generic TutorialR -deriving instance Generic ExamR -deriving instance Generic CourseApplicationR -deriving instance Generic AllocationR -deriving instance Generic SchoolR -deriving instance Generic ExamOfficeR -deriving instance Generic CourseNewsR -deriving instance Generic CourseEventR -deriving instance Generic (Route UniWorX) - -data RouteChildren -type instance Children RouteChildren a = ChildrenRouteChildren a -type family ChildrenRouteChildren a where - ChildrenRouteChildren (Route EmbeddedStatic) = '[] - ChildrenRouteChildren (Route Auth) = '[] - ChildrenRouteChildren UUID = '[] - ChildrenRouteChildren (Key a) = '[] - ChildrenRouteChildren (CI a) = '[] - - ChildrenRouteChildren a = Children ChGeneric a - -- | Convenient Type Synonyms: type DB = YesodDB UniWorX type Form x = Html -> MForm (HandlerFor UniWorX) (FormResult x, Widget) type MsgRenderer = MsgRendererS UniWorX -- see Utils type MailM a = MailT (HandlerFor UniWorX) a --- Pattern Synonyms for convenience -pattern CSheetR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> SheetR -> Route UniWorX -pattern CSheetR tid ssh csh shn ptn - = CourseR tid ssh csh (SheetR shn ptn) - -pattern CMaterialR :: TermId -> SchoolId -> CourseShorthand -> MaterialName -> MaterialR -> Route UniWorX -pattern CMaterialR tid ssh csh mnm ptn - = CourseR tid ssh csh (MaterialR mnm ptn) - -pattern CTutorialR :: TermId -> SchoolId -> CourseShorthand -> TutorialName -> TutorialR -> Route UniWorX -pattern CTutorialR tid ssh csh tnm ptn - = CourseR tid ssh csh (TutorialR tnm ptn) - -pattern CExamR :: TermId -> SchoolId -> CourseShorthand -> ExamName -> ExamR -> Route UniWorX -pattern CExamR tid ssh csh tnm ptn - = CourseR tid ssh csh (ExamR tnm ptn) - -pattern CSubmissionR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> CryptoFileNameSubmission -> SubmissionR -> Route UniWorX -pattern CSubmissionR tid ssh csh shn cid ptn - = CSheetR tid ssh csh shn (SubmissionR cid ptn) - -pattern CApplicationR :: TermId -> SchoolId -> CourseShorthand -> CryptoFileNameCourseApplication -> CourseApplicationR -> Route UniWorX -pattern CApplicationR tid ssh csh appId ptn - = CourseR tid ssh csh (CourseApplicationR appId ptn) - -pattern CNewsR :: TermId -> SchoolId -> CourseShorthand -> CryptoUUIDCourseNews -> CourseNewsR -> Route UniWorX -pattern CNewsR tid ssh csh nId ptn - = CourseR tid ssh csh (CourseNewsR nId ptn) - -pattern CEventR :: TermId -> SchoolId -> CourseShorthand -> CryptoUUIDCourseEvent -> CourseEventR -> Route UniWorX -pattern CEventR tid ssh csh nId ptn - = CourseR tid ssh csh (CourseEventR nId ptn) - - -- Requires `rendeRoute`, thus cannot currently be moved to Foundation.I18n instance RenderMessage UniWorX (UnsupportedAuthPredicate AuthTag (Route UniWorX)) where renderMessage f ls (UnsupportedAuthPredicate tag route) = mr . MsgUnsupportedAuthPredicate (mr tag) $ Text.intercalate "/" pieces @@ -1486,6 +1413,7 @@ siteLayout' headingOverride widget = do primaryLanguage <- unsafeHead . Text.splitOn "-" <$> selectLanguage appLanguages mcurrentRoute <- getCurrentRoute + let currentHandler = classifyHandler <$> mcurrentRoute -- Get the breadcrumbs, as defined in the YesodBreadcrumbs instance. let diff --git a/src/Foundation/Routes.hs b/src/Foundation/Routes.hs index 614bdea6d..0e83a0734 100644 --- a/src/Foundation/Routes.hs +++ b/src/Foundation/Routes.hs @@ -1,10 +1,84 @@ +{-# LANGUAGE UndecidableInstances #-} +{-# OPTIONS_GHC -fno-warn-orphans #-} + module Foundation.Routes - ( uniworxRoutes + ( module Foundation.Routes.Definitions + , module Foundation.Routes ) where -import ClassyPrelude.Yesod -import Yesod.Routes.TH.Types (ResourceTree) +import Import.NoFoundation +import Foundation.Type +import Foundation.Routes.Definitions -uniworxRoutes :: [ResourceTree String] -uniworxRoutes = $(parseRoutesFile "routes") +-- This is where we define all of the routes in our application. For a full +-- explanation of the syntax, please see: +-- http://www.yesodweb.com/book/routing-and-handlers +-- +-- Note that this is really half the story; in Application.hs, mkYesodDispatch +-- generates the rest of the code. Please see the following documentation +-- for an explanation for this split: +-- http://www.yesodweb.com/book/scaffolding-and-the-site-template#scaffolding-and-the-site-template_foundation_and_application_modules +-- +-- This function also generates the following type synonyms: +-- type Handler x = HandlerT UniWorX IO x +-- type Widget = WidgetT UniWorX IO () +mkYesodData "UniWorX" uniworxRoutes + +deriving instance Generic CourseR +deriving instance Generic SheetR +deriving instance Generic SubmissionR +deriving instance Generic MaterialR +deriving instance Generic TutorialR +deriving instance Generic ExamR +deriving instance Generic CourseApplicationR +deriving instance Generic AllocationR +deriving instance Generic SchoolR +deriving instance Generic ExamOfficeR +deriving instance Generic CourseNewsR +deriving instance Generic CourseEventR +deriving instance Generic (Route UniWorX) + +data RouteChildren +type instance Children RouteChildren a = ChildrenRouteChildren a +type family ChildrenRouteChildren a where + ChildrenRouteChildren (Route EmbeddedStatic) = '[] + ChildrenRouteChildren (Route Auth) = '[] + ChildrenRouteChildren UUID = '[] + ChildrenRouteChildren (Key a) = '[] + ChildrenRouteChildren (CI a) = '[] + + ChildrenRouteChildren a = Children ChGeneric a + +-- Pattern Synonyms for convenience +pattern CSheetR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> SheetR -> Route UniWorX +pattern CSheetR tid ssh csh shn ptn + = CourseR tid ssh csh (SheetR shn ptn) + +pattern CMaterialR :: TermId -> SchoolId -> CourseShorthand -> MaterialName -> MaterialR -> Route UniWorX +pattern CMaterialR tid ssh csh mnm ptn + = CourseR tid ssh csh (MaterialR mnm ptn) + +pattern CTutorialR :: TermId -> SchoolId -> CourseShorthand -> TutorialName -> TutorialR -> Route UniWorX +pattern CTutorialR tid ssh csh tnm ptn + = CourseR tid ssh csh (TutorialR tnm ptn) + +pattern CExamR :: TermId -> SchoolId -> CourseShorthand -> ExamName -> ExamR -> Route UniWorX +pattern CExamR tid ssh csh tnm ptn + = CourseR tid ssh csh (ExamR tnm ptn) + +pattern CSubmissionR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> CryptoFileNameSubmission -> SubmissionR -> Route UniWorX +pattern CSubmissionR tid ssh csh shn cid ptn + = CSheetR tid ssh csh shn (SubmissionR cid ptn) + +pattern CApplicationR :: TermId -> SchoolId -> CourseShorthand -> CryptoFileNameCourseApplication -> CourseApplicationR -> Route UniWorX +pattern CApplicationR tid ssh csh appId ptn + = CourseR tid ssh csh (CourseApplicationR appId ptn) + +pattern CNewsR :: TermId -> SchoolId -> CourseShorthand -> CryptoUUIDCourseNews -> CourseNewsR -> Route UniWorX +pattern CNewsR tid ssh csh nId ptn + = CourseR tid ssh csh (CourseNewsR nId ptn) + +pattern CEventR :: TermId -> SchoolId -> CourseShorthand -> CryptoUUIDCourseEvent -> CourseEventR -> Route UniWorX +pattern CEventR tid ssh csh nId ptn + = CourseR tid ssh csh (CourseEventR nId ptn) diff --git a/src/Foundation/Routes/Definitions.hs b/src/Foundation/Routes/Definitions.hs new file mode 100644 index 000000000..4908a25ee --- /dev/null +++ b/src/Foundation/Routes/Definitions.hs @@ -0,0 +1,10 @@ +module Foundation.Routes.Definitions + ( uniworxRoutes + ) where + +import ClassyPrelude.Yesod +import Yesod.Routes.TH.Types (ResourceTree) + + +uniworxRoutes :: [ResourceTree String] +uniworxRoutes = $(parseRoutesFile "routes") diff --git a/src/Handler/Utils/Routes.hs b/src/Handler/Utils/Routes.hs index 52a93dfed..345718bcb 100644 --- a/src/Handler/Utils/Routes.hs +++ b/src/Handler/Utils/Routes.hs @@ -2,7 +2,9 @@ module Handler.Utils.Routes ( classifyHandler ) where -import Import +import Import.NoFoundation +import Foundation.Routes +import Foundation.Type import Utils.TH.Routes From ba846be5aa99278ca00b64150165ccb825eb9ba0 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 16:28:15 +0100 Subject: [PATCH 03/46] feat(default-layout): save handler ident to main content --- templates/default-layout.hamlet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/default-layout.hamlet b/templates/default-layout.hamlet index cdcffaad5..22fe5fa2d 100644 --- a/templates/default-layout.hamlet +++ b/templates/default-layout.hamlet @@ -11,7 +11,7 @@ $if not isModal
-
+
$if not isModal From 169a4799b4996c9474ee492e79dcd0a5040af04e Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 16:31:39 +0100 Subject: [PATCH 04/46] feat(hide-columns): set attributes for hide-columns and extra-stuff div --- templates/course-participants.hamlet | 2 +- templates/table/colonnade.hamlet | 2 ++ templates/table/layout-wrapper.hamlet | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/course-participants.hamlet b/templates/course-participants.hamlet index 37f9960b9..ff5847746 100644 --- a/templates/course-participants.hamlet +++ b/templates/course-participants.hamlet @@ -4,4 +4,4 @@ $# $# participantTable : widget table ^{participantTable} -_{MsgCourseMembersCountOf (fromIntegral numParticipants) (courseCapacity course)}. \ No newline at end of file +_{MsgCourseMembersCountOf (fromIntegral numParticipants) (courseCapacity course)}. diff --git a/templates/table/colonnade.hamlet b/templates/table/colonnade.hamlet index c756229c5..f13131530 100644 --- a/templates/table/colonnade.hamlet +++ b/templates/table/colonnade.hamlet @@ -1,4 +1,6 @@ $newline never +
+ Table Utils:
$maybe wHeaders' <- wHeaders diff --git a/templates/table/layout-wrapper.hamlet b/templates/table/layout-wrapper.hamlet index 791ccd656..c67a6ca3d 100644 --- a/templates/table/layout-wrapper.hamlet +++ b/templates/table/layout-wrapper.hamlet @@ -1,3 +1,3 @@ $newline never -
+
^{table} From 10232401369fa18fd7866a584b4f6d3eb1380e5c Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 16:39:47 +0100 Subject: [PATCH 05/46] feat(storage-manager): add storage manager library --- .../lib/storage-manager/storage-manager.js | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 frontend/src/lib/storage-manager/storage-manager.js diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js new file mode 100644 index 000000000..0735286c1 --- /dev/null +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -0,0 +1,62 @@ +const LIFETIME = { + INFINITE: 'infinite', +}; + +export class StorageManager { + + namespace; + + constructor(namespace) { + if (!namespace) { + throw new Error('Cannot setup StorageManager without namespace'); + } + + this.namespace = namespace; + } + + toNamespace(key) { + return this.namespace + '--' + key; + } + + save(key, value, options) { + if (!key) { + throw new Error('StorageManager.save called with invalid key'); + } + + if (options && options.lifetime !== undefined && !Object.values(LIFETIME).includes(options.lifetime)) { + throw new Error('StorageManager.save called with unsupported lifetime option'); + } + + const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; + + switch (lifetime) { + case LIFETIME.INFINITE: + localStorage.setItem(this.toNamespace(key), JSON.stringify(value)); + break; + default: + console.error('StorageManager.save cannot save item with unsupported lifetime'); + } + } + + load(key, options) { + if (options && options.lifetime !== undefined && !Object.values(LIFETIME).includes(options.lifetime)) { + throw new Error('StorageManager.load called with unsupported lifetime option'); + } + + const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; + + switch (lifetime) { + case LIFETIME.INFINITE: { + const value = JSON.parse(localStorage.getItem(this.toNamespace(key))); + if (value === null) { + // remove item from localStorage if it stores an invalid value (cannot be parsed) + localStorage.removeItem(this.toNamespace(key)); + } + return value; + } + default: + console.error('StorageManager.load cannot load item with unsupported lifetime'); + } + } + +} From 111821dcad4d0ffde6dfebbb62fb21b9b76ab9c5 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 16:49:15 +0100 Subject: [PATCH 06/46] feat(hide-columns): first stub of hide-column util with manual styling --- .../src/utils/hide-columns/hide-columns.js | 149 ++++++++++++++++++ frontend/src/utils/utils.js | 2 + 2 files changed, 151 insertions(+) create mode 100644 frontend/src/utils/hide-columns/hide-columns.js diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js new file mode 100644 index 000000000..d4cbf234e --- /dev/null +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -0,0 +1,149 @@ +import { Utility } from '../../core/utility'; +import { StorageManager } from '../../lib/storage-manager/storage-manager'; + +const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; +const TABLE_HEADER_IDENT = 'hide-column-header'; + +const TABLE_UTILS_ATTR = 'table-utils'; +const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`; + + +const HIDER_TEXT_ATTR = 'header-text'; + +const HIDE_BUTTON_FADE_DELAY = 3000; + +@Utility({ + selector: `[${HIDE_COLUMNS_CONTAINER_IDENT}] table`, +}) +export class HideColumns { + + _storageManager = new StorageManager('uw-hide-columns'); + + _element; + _tableUtilContainer; + + constructor(element) { + if (!element) { + throw new Error('Hide Columns utility cannot be setup without an element!'); + } + + // do not provide hide-column ability in tables inside modals or async forms with response + if (element.closest('[uw-modal], .async-form__response')) { + return false; + } + + this._element = element; + + const hideColumnsContainer = this._element.closest(`[${HIDE_COLUMNS_CONTAINER_IDENT}]`); + if (!hideColumnsContainer) { + throw new Error('Hide Columns utility needs to be setup on a table inside a hide columns container!'); + } + + // get or create table utils container + this._tableUtilContainer = hideColumnsContainer.querySelector(TABLE_UTILS_CONTAINER_SELECTOR); + if (!this._tableUtilContainer) { + this._tableUtilContainer = document.createElement('div'); + this._tableUtilContainer.setAttribute(TABLE_UTILS_ATTR, ''); + const tableContainer = this._element.closest(`[${HIDE_COLUMNS_CONTAINER_IDENT}] > *`); + hideColumnsContainer.insertBefore(this._tableUtilContainer, tableContainer); + } + + this._element.querySelectorAll('th').forEach(th => { + const storageKey = this.getStorageKey(th); + const previouslyHidden = this._storageManager.load(storageKey); + this.setupHideButton(th, previouslyHidden); + }); + } + + setupHideButton(th, prevHidden) { + console.log('setupHideButton', th, prevHidden); + + const hider = document.createElement('button'); + hider.setAttribute(HIDER_TEXT_ATTR, th.innerText); + + hider.addEventListener('click', (event) => { + console.log('click', th.cellIndex, hider, th.innerText); + event.preventDefault(); + this.toggleColumnVisibility(th, hider); + }); + + // TODO fade in / fade out animation in css + th.addEventListener('mouseover', () => { + hider.style.display = ''; + }); + th.addEventListener('mouseout', () => { + setTimeout(() => { + if (hider.style.position === 'absolute') hider.style.display = 'none'; + }, HIDE_BUTTON_FADE_DELAY); + }); + + this.updateColumnDisplay(th.cellIndex, prevHidden); + this.updateHider(hider, prevHidden); + + this._tableUtilContainer.appendChild(hider); + } + + // TODO better name + toggleColumnVisibility(th, hider) { + const storageKey = this.getStorageKey(th); + + const hidden = !this._storageManager.load(storageKey); + + // hide/unhide column + this.updateColumnDisplay(th.cellIndex, hidden); + + // tweak hider button + this.updateHider(hider, hidden); + + // persist new hidden setting for column + this._storageManager.save(storageKey, hidden); + } + + // TODO better name + updateColumnDisplay(columnIndex, hidden) { + this._element.getElementsByTagName('tr').forEach(row => { + if (row.cells[columnIndex]) { + row.cells[columnIndex].style.display = hidden ? 'none' : ''; + } + }); + } + + // TODO better name + updateHider(hider, hidden) { + // TODO set css classes instead + if (hidden) { + hider.innerHTML = hider.getAttribute(HIDER_TEXT_ATTR); + hider.style.position = 'relative'; + } else { + hider.innerHTML = 'hide'; + hider.style.position = 'absolute'; + hider.style.display = 'none'; + } + } + + getStorageKey(th) { + // get handler name + const handlerIdent = document.querySelector('[uw-handler]').getAttribute('uw-handler'); + + // get hide-columns container ident (if not present, use table index in document as fallback) + let tIdent = th.getAttribute(TABLE_HEADER_IDENT); + if (!tIdent) { + const tablesInDocument = document.getElementsByTagName('TABLE'); + for (let i = 0; i < tablesInDocument.length; i++) { + if (tablesInDocument[i] === this._element) { + tIdent = i; + break; + } + } + } + + // check for unique table header ident from backend (if not present, use cell index as fallback) + let thIdent = th.getAttribute(TABLE_HEADER_IDENT); + if (!thIdent) { + thIdent = th.cellIndex; + } + + return `${handlerIdent}-${tIdent}-${thIdent}`; + } + +} diff --git a/frontend/src/utils/utils.js b/frontend/src/utils/utils.js index b539edb44..00f3e5ec0 100644 --- a/frontend/src/utils/utils.js +++ b/frontend/src/utils/utils.js @@ -11,6 +11,7 @@ import { Modal } from './modal/modal'; import { Tooltip } from './tooltips/tooltips'; import { CourseTeaser } from './course-teaser/course-teaser'; import { NavbarUtils } from './navbar/navbar'; +import { HideColumns } from './hide-columns/hide-columns'; export const Utils = [ Alerts, @@ -27,4 +28,5 @@ export const Utils = [ Tooltip, CourseTeaser, ...NavbarUtils, + HideColumns, ]; From 5cc88089b5e275bf37b64b95270991d3ef01fd04 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 16:51:44 +0100 Subject: [PATCH 07/46] chore(hide-columns): remove unnecessary console.logs --- frontend/src/utils/hide-columns/hide-columns.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index d4cbf234e..6e2836768 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -56,13 +56,10 @@ export class HideColumns { } setupHideButton(th, prevHidden) { - console.log('setupHideButton', th, prevHidden); - const hider = document.createElement('button'); hider.setAttribute(HIDER_TEXT_ATTR, th.innerText); hider.addEventListener('click', (event) => { - console.log('click', th.cellIndex, hider, th.innerText); event.preventDefault(); this.toggleColumnVisibility(th, hider); }); From d55d3ef4847f089970982e9554365f8699f2f9e6 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 17:00:38 +0100 Subject: [PATCH 08/46] feat(hide-columns): get table wrapper ident for storage ident --- frontend/src/utils/hide-columns/hide-columns.js | 4 +++- templates/table/layout-wrapper.hamlet | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 6e2836768..ea2da5195 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -20,6 +20,7 @@ export class HideColumns { _storageManager = new StorageManager('uw-hide-columns'); _element; + _elementWrapper; _tableUtilContainer; constructor(element) { @@ -38,6 +39,7 @@ export class HideColumns { if (!hideColumnsContainer) { throw new Error('Hide Columns utility needs to be setup on a table inside a hide columns container!'); } + this._elementWrapper = hideColumnsContainer; // get or create table utils container this._tableUtilContainer = hideColumnsContainer.querySelector(TABLE_UTILS_CONTAINER_SELECTOR); @@ -123,7 +125,7 @@ export class HideColumns { const handlerIdent = document.querySelector('[uw-handler]').getAttribute('uw-handler'); // get hide-columns container ident (if not present, use table index in document as fallback) - let tIdent = th.getAttribute(TABLE_HEADER_IDENT); + let tIdent = this._elementWrapper.getAttribute(HIDE_COLUMNS_CONTAINER_IDENT); if (!tIdent) { const tablesInDocument = document.getElementsByTagName('TABLE'); for (let i = 0; i < tablesInDocument.length; i++) { diff --git a/templates/table/layout-wrapper.hamlet b/templates/table/layout-wrapper.hamlet index c67a6ca3d..791694f14 100644 --- a/templates/table/layout-wrapper.hamlet +++ b/templates/table/layout-wrapper.hamlet @@ -1,3 +1,3 @@ $newline never -
+
^{table} From 610d13a7292f61e7892bc0f58a666011efbbbe71 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 17:15:59 +0100 Subject: [PATCH 09/46] feat(hide-columns): correct storage keys --- frontend/src/utils/hide-columns/hide-columns.js | 3 +-- templates/table/cell/header.hamlet | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index ea2da5195..744f2737f 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -2,12 +2,11 @@ import { Utility } from '../../core/utility'; import { StorageManager } from '../../lib/storage-manager/storage-manager'; const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; -const TABLE_HEADER_IDENT = 'hide-column-header'; +const TABLE_HEADER_IDENT = 'uw-hide-column-header'; const TABLE_UTILS_ATTR = 'table-utils'; const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`; - const HIDER_TEXT_ATTR = 'header-text'; const HIDE_BUTTON_FADE_DELAY = 3000; diff --git a/templates/table/cell/header.hamlet b/templates/table/cell/header.hamlet index ddea5960c..fca1c703c 100644 --- a/templates/table/cell/header.hamlet +++ b/templates/table/cell/header.hamlet @@ -1,5 +1,5 @@ $newline never -
+ $maybe flag <- sortableKey $case directions $of [SortAsc] From 42dd41f9d6109f891024c1f11cb637c246f8f315 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 17:53:03 +0100 Subject: [PATCH 10/46] refactor(storage-manager): namespace as key, values as object properties --- .../lib/storage-manager/storage-manager.js | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js index 0735286c1..cb82a0006 100644 --- a/frontend/src/lib/storage-manager/storage-manager.js +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -14,10 +14,6 @@ export class StorageManager { this.namespace = namespace; } - toNamespace(key) { - return this.namespace + '--' + key; - } - save(key, value, options) { if (!key) { throw new Error('StorageManager.save called with invalid key'); @@ -30,9 +26,10 @@ export class StorageManager { const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; switch (lifetime) { - case LIFETIME.INFINITE: - localStorage.setItem(this.toNamespace(key), JSON.stringify(value)); + case LIFETIME.INFINITE: { + this.saveToLocalStorage({ ...this.getFromLocalStorage(), [key]: value }); break; + } default: console.error('StorageManager.save cannot save item with unsupported lifetime'); } @@ -46,17 +43,29 @@ export class StorageManager { const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; switch (lifetime) { - case LIFETIME.INFINITE: { - const value = JSON.parse(localStorage.getItem(this.toNamespace(key))); - if (value === null) { - // remove item from localStorage if it stores an invalid value (cannot be parsed) - localStorage.removeItem(this.toNamespace(key)); - } - return value; - } + case LIFETIME.INFINITE: + return this.getFromLocalStorage()[key]; default: console.error('StorageManager.load cannot load item with unsupported lifetime'); } } + 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) + this.clearLocalStorage(); + return {}; + } + return state; + } + + saveToLocalStorage(value) { + window.localStorage.setItem(this.namespace, JSON.stringify(value)); + } + + clearLocalStorage() { + window.localStorage.removeItem(this.namespace); + } + } From bc023f5bfb55914af5bed9979e0f82b5757101c2 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 17:53:53 +0100 Subject: [PATCH 11/46] refactor(hide-columns): conform to LS naming scheme --- frontend/src/utils/hide-columns/hide-columns.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 744f2737f..33bf474b0 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -16,7 +16,7 @@ const HIDE_BUTTON_FADE_DELAY = 3000; }) export class HideColumns { - _storageManager = new StorageManager('uw-hide-columns'); + _storageManager = new StorageManager('HIDE_COLUMNS'); _element; _elementWrapper; @@ -141,7 +141,7 @@ export class HideColumns { thIdent = th.cellIndex; } - return `${handlerIdent}-${tIdent}-${thIdent}`; + return `${handlerIdent}__${tIdent}__${thIdent}`; } } From 68fc4e4c3a373d83b4557b8ae33f86c496c6933b Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 26 Nov 2019 18:10:11 +0100 Subject: [PATCH 12/46] refactor(hide-columns): minor renaming and preparation for css work --- frontend/src/utils/hide-columns/hide-columns.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 33bf474b0..6bc0bc8af 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -57,12 +57,12 @@ export class HideColumns { } setupHideButton(th, prevHidden) { - const hider = document.createElement('button'); + const hider = document.createElement('span'); hider.setAttribute(HIDER_TEXT_ATTR, th.innerText); hider.addEventListener('click', (event) => { event.preventDefault(); - this.toggleColumnVisibility(th, hider); + this.switchColumnDisplay(th, hider); }); // TODO fade in / fade out animation in css @@ -81,23 +81,18 @@ export class HideColumns { this._tableUtilContainer.appendChild(hider); } - // TODO better name - toggleColumnVisibility(th, hider) { + switchColumnDisplay(th, hider) { const storageKey = this.getStorageKey(th); const hidden = !this._storageManager.load(storageKey); - // hide/unhide column this.updateColumnDisplay(th.cellIndex, hidden); - - // tweak hider button this.updateHider(hider, hidden); // persist new hidden setting for column this._storageManager.save(storageKey, hidden); } - // TODO better name updateColumnDisplay(columnIndex, hidden) { this._element.getElementsByTagName('tr').forEach(row => { if (row.cells[columnIndex]) { @@ -106,7 +101,6 @@ export class HideColumns { }); } - // TODO better name updateHider(hider, hidden) { // TODO set css classes instead if (hidden) { From a9c17d75fe2ec2aef65e4150d8f080797433fe0d Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Wed, 27 Nov 2019 17:01:49 +0100 Subject: [PATCH 13/46] feat(hide-columns): styling stub with repositioning --- .../src/utils/hide-columns/hide-columns.js | 65 +++++++++++++++---- .../src/utils/hide-columns/hide-columns.scss | 53 +++++++++++++++ 2 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 frontend/src/utils/hide-columns/hide-columns.scss diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 6bc0bc8af..242c51095 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -1,5 +1,6 @@ import { Utility } from '../../core/utility'; import { StorageManager } from '../../lib/storage-manager/storage-manager'; +import './hide-columns.scss'; const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; const TABLE_HEADER_IDENT = 'uw-hide-column-header'; @@ -7,8 +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 HIDER_TEXT_ATTR = 'header-text'; - const HIDE_BUTTON_FADE_DELAY = 3000; @Utility({ @@ -22,6 +21,14 @@ export class HideColumns { _elementWrapper; _tableUtilContainer; + headerToHider = new Map(); + hiderToHeader = new Map(); + + addHeaderHider(th, hider) { + this.headerToHider.set(th, hider); + this.hiderToHeader.set(hider, th); + } + constructor(element) { if (!element) { throw new Error('Hide Columns utility cannot be setup without an element!'); @@ -58,7 +65,14 @@ export class HideColumns { setupHideButton(th, prevHidden) { const hider = document.createElement('span'); - hider.setAttribute(HIDER_TEXT_ATTR, th.innerText); + hider.classList.add('table-pill'); + const hiderIcon = document.createElement('i'); + hiderIcon.classList.add('fas', 'fa-fw'); + hider.appendChild(hiderIcon); + const hiderContent = document.createElement('span'); + hiderContent.classList.add('table-pill__content'); + hiderContent.innerHTML = th.innerText; + hider.appendChild(hiderContent); hider.addEventListener('click', (event) => { event.preventDefault(); @@ -67,17 +81,34 @@ export class HideColumns { // TODO fade in / fade out animation in css th.addEventListener('mouseover', () => { - hider.style.display = ''; + hider.classList.remove('table-pill--hidden'); + const posTH = th.getBoundingClientRect(); + const posH = hider.getBoundingClientRect(); + hider.style.left = (posTH.left + ((posTH.right-posTH.left)/2 - ((posH.right-posH.left)/2))) + 'px'; + hider.style.top = (posTH.top - 50) + 'px'; }); th.addEventListener('mouseout', () => { setTimeout(() => { - if (hider.style.position === 'absolute') hider.style.display = 'none'; + if (hider.classList.contains('table-pill--floating')) { + hider.classList.add('table-pill--hidden'); + } }, HIDE_BUTTON_FADE_DELAY); }); + hider.addEventListener('mouseover', () => { + const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); + this.updateHiderIcon(hider, !currentlyHidden); + }); + hider.addEventListener('mouseout', () => { + const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); + this.updateHiderIcon(hider, currentlyHidden); + }); + this.updateColumnDisplay(th.cellIndex, prevHidden); this.updateHider(hider, prevHidden); + this.addHeaderHider(th, hider); + this._tableUtilContainer.appendChild(hider); } @@ -95,22 +126,30 @@ export class HideColumns { updateColumnDisplay(columnIndex, hidden) { this._element.getElementsByTagName('tr').forEach(row => { - if (row.cells[columnIndex]) { - row.cells[columnIndex].style.display = hidden ? 'none' : ''; + const cell = row.cells[columnIndex]; + if (cell) { + if (hidden) { + cell.classList.add('hide-columns--hidden-cell'); + } else { + cell.classList.remove('hide-columns--hidden-cell'); + } } }); } updateHider(hider, hidden) { - // TODO set css classes instead if (hidden) { - hider.innerHTML = hider.getAttribute(HIDER_TEXT_ATTR); - hider.style.position = 'relative'; + hider.classList.remove('table-pill--hidden', 'table-pill--floating'); } else { - hider.innerHTML = 'hide'; - hider.style.position = 'absolute'; - hider.style.display = 'none'; + hider.classList.add('table-pill--hidden', 'table-pill--floating'); } + this.updateHiderIcon(hider, hidden); + } + + updateHiderIcon(hider, hidden) { + const hiderIcon = hider.getElementsByClassName('fas')[0]; + hiderIcon.classList.remove(hidden ? 'fa-eye' : 'fa-eye-slash'); + hiderIcon.classList.add(hidden ? 'fa-eye-slash' : 'fa-eye'); } getStorageKey(th) { diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss new file mode 100644 index 000000000..82a39d97c --- /dev/null +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -0,0 +1,53 @@ +[table-utils] { + margin-bottom: 20px; + line-height: 1.4; + max-width: 85vw; + + .table-pill { + background-color: var(--color-dark); + color: #fff; + padding-top: 10px; + padding-bottom: 10px; + padding-right: 10px; + padding-left: 10px; + border-radius: 20px 20px 20px 20px / 50% 50% 50% 50%; + margin-right: 20px; + cursor: pointer; + + .table-pill__content { + font-size: 16px; + font-weight: bold; + margin-left: 5px; + } + } + .table-pill.table-pill--hidden { + animation: fadeout 2s ease-in alternate infinite; + display: none; + } + .table-pill.table-pill--floating { + position: fixed; + .table-pill__content { display: none; } + } + + .table-pill.table-pill--hide { + padding-left: 10px; + } + + .table-pill--unhide { + padding-left: 10px; + } + +} + +.hide-columns--hidden-cell { + display: none; +} + +@keyframes fadeout { + from: { opacity: 1; } + to: { opacity: 0; display: none; } +} +@keyframes fadein { + from: { opacity: 0; } + to: { opacity: 1; } +} From e655bc6e700f1b9668633f6beaef7acf8db484f0 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Thu, 28 Nov 2019 12:33:44 +0100 Subject: [PATCH 14/46] feat(hide-columns): more (broken) styling; move hider elements in DOM --- .../src/utils/hide-columns/hide-columns.js | 82 ++++++++++++++----- .../src/utils/hide-columns/hide-columns.scss | 44 +++++----- 2 files changed, 85 insertions(+), 41 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 242c51095..0b2ee8c50 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -8,7 +8,13 @@ const TABLE_HEADER_IDENT = 'uw-hide-column-header'; const TABLE_UTILS_ATTR = 'table-utils'; const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`; -const HIDE_BUTTON_FADE_DELAY = 3000; +const TABLE_HIDER_CONTAINER_CLASS = 'table-hiders'; + +const HIDER_HIDE_CLASS = 'table-pill--hide'; +const HIDER_HIDDEN_CLASS = 'table-pill--hidden'; +const HIDER_FLOATING_CLASS = 'table-pill--floating'; + +const CELL_HIDDEN_CLASS = 'hide-columns--hidden-cell'; @Utility({ selector: `[${HIDE_COLUMNS_CONTAINER_IDENT}] table`, @@ -20,6 +26,7 @@ export class HideColumns { _element; _elementWrapper; _tableUtilContainer; + _tableHiderContainer; headerToHider = new Map(); hiderToHeader = new Map(); @@ -56,6 +63,14 @@ 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 => { const storageKey = this.getStorageKey(th); const previouslyHidden = this._storageManager.load(storageKey); @@ -63,17 +78,42 @@ export class HideColumns { }); } + hideHiderBehindHeader(hider) { + const th = this.hiderToHeader.get(hider); + // move hider right before table (inside any scrolltable element) + this._tableHiderContainer.appendChild(hider); + // reposition hider + const posTH = th.getBoundingClientRect(); + const posH = hider.getBoundingClientRect(); + // TODO move to aux function + let p = { + top: posTH.top, + left: posTH.left, + width: th.offsetWidth || 0, + height: th.offsetHeight || 0, + }; + const hiderCompStyle = window.getComputedStyle(hider); + const x = parseInt(hiderCompStyle.marginLeft) + parseInt(hiderCompStyle.marginRight); + const y = parseInt(hiderCompStyle.marginTop) + parseInt(hiderCompStyle.marginBottom); + const posHParent = hider.parentElement.getBoundingClientRect(); + p.top += -posHParent.top + hider.parentElement.scrollTop + hider.parentElement.offsetTop; + p.left += -posHParent.left - hider.parentElement.scrollLeft + hider.parentElement.offsetLeft; + hider.style.left = (p.left + (p.width/2) - (posH.width/2 + x)) + 'px'; + hider.style.top = (p.top - (hider.offsetHeight + y)) + 'px'; + } + setupHideButton(th, prevHidden) { const hider = document.createElement('span'); - hider.classList.add('table-pill'); const hiderIcon = document.createElement('i'); hiderIcon.classList.add('fas', 'fa-fw'); hider.appendChild(hiderIcon); const hiderContent = document.createElement('span'); - hiderContent.classList.add('table-pill__content'); + hiderContent.classList.add('table-hider__label'); hiderContent.innerHTML = th.innerText; hider.appendChild(hiderContent); + this.addHeaderHider(th, hider); + hider.addEventListener('click', (event) => { event.preventDefault(); this.switchColumnDisplay(th, hider); @@ -81,18 +121,13 @@ export class HideColumns { // TODO fade in / fade out animation in css th.addEventListener('mouseover', () => { - hider.classList.remove('table-pill--hidden'); - const posTH = th.getBoundingClientRect(); - const posH = hider.getBoundingClientRect(); - hider.style.left = (posTH.left + ((posTH.right-posTH.left)/2 - ((posH.right-posH.left)/2))) + 'px'; - hider.style.top = (posTH.top - 50) + 'px'; + // hider.classList.remove(HIDER_HIDDEN_CLASS); }); - th.addEventListener('mouseout', () => { - setTimeout(() => { - if (hider.classList.contains('table-pill--floating')) { - hider.classList.add('table-pill--hidden'); - } - }, HIDE_BUTTON_FADE_DELAY); + th.addEventListener('mouseout', (event) => { + console.log('th mouseout', event); + if (hider.classList.contains(HIDER_FLOATING_CLASS)) { + hider.classList.add(HIDER_HIDE_CLASS); + } }); hider.addEventListener('mouseover', () => { @@ -107,9 +142,12 @@ export class HideColumns { this.updateColumnDisplay(th.cellIndex, prevHidden); this.updateHider(hider, prevHidden); - this.addHeaderHider(th, hider); + if (prevHidden) { + this._tableUtilContainer.appendChild(hider); + } else { + this.hideHiderBehindHeader(hider); + } - this._tableUtilContainer.appendChild(hider); } switchColumnDisplay(th, hider) { @@ -129,9 +167,9 @@ export class HideColumns { const cell = row.cells[columnIndex]; if (cell) { if (hidden) { - cell.classList.add('hide-columns--hidden-cell'); + cell.classList.add(CELL_HIDDEN_CLASS); } else { - cell.classList.remove('hide-columns--hidden-cell'); + cell.classList.remove(CELL_HIDDEN_CLASS); } } }); @@ -139,9 +177,13 @@ export class HideColumns { updateHider(hider, hidden) { if (hidden) { - hider.classList.remove('table-pill--hidden', 'table-pill--floating'); + this._tableUtilContainer.appendChild(hider); + hider.classList.remove(HIDER_HIDDEN_CLASS, HIDER_FLOATING_CLASS, 'table-hider'); + hider.classList.add('table-pill'); } else { - hider.classList.add('table-pill--hidden', 'table-pill--floating'); + + hider.classList.remove('table-pill'); + hider.classList.add(HIDER_HIDDEN_CLASS, HIDER_FLOATING_CLASS, 'table-hider'); } this.updateHiderIcon(hider, hidden); } diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index 82a39d97c..a6066283d 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -2,6 +2,21 @@ margin-bottom: 20px; line-height: 1.4; max-width: 85vw; +} + + .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); + margin: 10px 10px 0 0; + position: absolute; + + .table-hider__label { + display: none; + } + } .table-pill { background-color: var(--color-dark); @@ -14,40 +29,27 @@ margin-right: 20px; cursor: pointer; - .table-pill__content { + .table-hider__label { font-size: 16px; font-weight: bold; margin-left: 5px; } } - .table-pill.table-pill--hidden { - animation: fadeout 2s ease-in alternate infinite; - display: none; - } - .table-pill.table-pill--floating { - position: fixed; - .table-pill__content { display: none; } - } - .table-pill.table-pill--hide { - padding-left: 10px; + /* -webkit-animation: fadeout 0.5s linear forwards; */ + /* animation: fadeout 0.5s linear forwards; */ + /* animation-delay: 2s; */ } - .table-pill--unhide { - padding-left: 10px; - } - -} - .hide-columns--hidden-cell { display: none; } @keyframes fadeout { - from: { opacity: 1; } - to: { opacity: 0; display: none; } + 0% { opacity: 1; } + 100% { opacity: 0; } } @keyframes fadein { - from: { opacity: 0; } - to: { opacity: 1; } + 0% { opacity: 0; } + 100% { opacity: 1; } } From 761c6d39a82a57e4bdddd193d25be459b12ca1f7 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Thu, 28 Nov 2019 13:14:34 +0100 Subject: [PATCH 15/46] feat(hide-columns): better positioning of hiders --- .../src/utils/hide-columns/hide-columns.js | 23 ++++--------------- .../src/utils/hide-columns/hide-columns.scss | 16 ++++++++----- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 0b2ee8c50..0cf01df51 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -79,27 +79,14 @@ export class HideColumns { } hideHiderBehindHeader(hider) { - const th = this.hiderToHeader.get(hider); // move hider right before table (inside any scrolltable element) this._tableHiderContainer.appendChild(hider); // reposition hider - const posTH = th.getBoundingClientRect(); - const posH = hider.getBoundingClientRect(); - // TODO move to aux function - let p = { - top: posTH.top, - left: posTH.left, - width: th.offsetWidth || 0, - height: th.offsetHeight || 0, - }; - const hiderCompStyle = window.getComputedStyle(hider); - const x = parseInt(hiderCompStyle.marginLeft) + parseInt(hiderCompStyle.marginRight); - const y = parseInt(hiderCompStyle.marginTop) + parseInt(hiderCompStyle.marginBottom); - const posHParent = hider.parentElement.getBoundingClientRect(); - p.top += -posHParent.top + hider.parentElement.scrollTop + hider.parentElement.offsetTop; - p.left += -posHParent.left - hider.parentElement.scrollLeft + hider.parentElement.offsetLeft; - hider.style.left = (p.left + (p.width/2) - (posH.width/2 + x)) + 'px'; - hider.style.top = (p.top - (hider.offsetHeight + y)) + 'px'; + const thR = this.hiderToHeader.get(hider).getBoundingClientRect(); + const hR = hider.getBoundingClientRect(); + const pR = this._tableHiderContainer.getBoundingClientRect(); + hider.style.left = (thR.left + thR.width/2 - hR.width/2 - pR.left) + 'px'; + hider.style.top = (thR.top - pR.top + 5) + 'px'; } setupHideButton(th, prevHidden) { diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index a6066283d..a2e9ed957 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -1,8 +1,6 @@ -[table-utils] { - margin-bottom: 20px; - line-height: 1.4; - max-width: 85vw; -} +.table-hiders { + position: relative; + max-height: 0px; .table-hider { background-color: #fff; @@ -10,13 +8,18 @@ padding: 10px; cursor: pointer; box-shadow: 0 0 2px 0 rgba(0,0,0,0.6); - margin: 10px 10px 0 0; position: absolute; .table-hider__label { display: none; } } +} + +[table-utils] { + margin-bottom: 20px; + line-height: 1.4; + max-width: 85vw; .table-pill { background-color: var(--color-dark); @@ -40,6 +43,7 @@ /* animation: fadeout 0.5s linear forwards; */ /* animation-delay: 2s; */ } +} .hide-columns--hidden-cell { display: none; From 49087027b250a8ce1212d508e1c9028f5122a09e Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Thu, 28 Nov 2019 15:44:53 +0100 Subject: [PATCH 16/46] feat(hide-columns): more styling --- .../src/utils/hide-columns/hide-columns.js | 28 ++++++++++--------- .../src/utils/hide-columns/hide-columns.scss | 15 +++++++++- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 0cf01df51..976c24622 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -9,10 +9,9 @@ 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 HIDER_HIDE_CLASS = 'table-pill--hide'; -const HIDER_HIDDEN_CLASS = 'table-pill--hidden'; -const HIDER_FLOATING_CLASS = 'table-pill--floating'; +const HIDER_POPUP_CLASS = 'table-hider--visible'; const CELL_HIDDEN_CLASS = 'hide-columns--hidden-cell'; @@ -86,7 +85,7 @@ export class HideColumns { const hR = hider.getBoundingClientRect(); const pR = this._tableHiderContainer.getBoundingClientRect(); hider.style.left = (thR.left + thR.width/2 - hR.width/2 - pR.left) + 'px'; - hider.style.top = (thR.top - pR.top + 5) + 'px'; + hider.style.top = (thR.top - pR.top + 5 +50) + 'px'; } setupHideButton(th, prevHidden) { @@ -106,22 +105,24 @@ export class HideColumns { this.switchColumnDisplay(th, hider); }); - // TODO fade in / fade out animation in css th.addEventListener('mouseover', () => { - // hider.classList.remove(HIDER_HIDDEN_CLASS); + hider.classList.add(HIDER_POPUP_CLASS); }); - th.addEventListener('mouseout', (event) => { - console.log('th mouseout', event); - if (hider.classList.contains(HIDER_FLOATING_CLASS)) { - hider.classList.add(HIDER_HIDE_CLASS); + th.addEventListener('mouseout', () => { + if (hider.classList.contains(TABLE_HIDER_CLASS)) { + hider.classList.remove(HIDER_POPUP_CLASS); } }); hider.addEventListener('mouseover', () => { + hider.classList.add(HIDER_POPUP_CLASS); const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); this.updateHiderIcon(hider, !currentlyHidden); }); hider.addEventListener('mouseout', () => { + if (hider.classList.contains(TABLE_HIDER_CLASS)) { + hider.classList.remove(HIDER_POPUP_CLASS); + } const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); this.updateHiderIcon(hider, currentlyHidden); }); @@ -165,12 +166,13 @@ export class HideColumns { updateHider(hider, hidden) { if (hidden) { this._tableUtilContainer.appendChild(hider); - hider.classList.remove(HIDER_HIDDEN_CLASS, HIDER_FLOATING_CLASS, 'table-hider'); + hider.classList.remove(TABLE_HIDER_CLASS); hider.classList.add('table-pill'); } else { - + this.hideHiderBehindHeader(hider); + this._tableHiderContainer.appendChild(hider); hider.classList.remove('table-pill'); - hider.classList.add(HIDER_HIDDEN_CLASS, HIDER_FLOATING_CLASS, 'table-hider'); + hider.classList.add(TABLE_HIDER_CLASS); } this.updateHiderIcon(hider, hidden); } diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index a2e9ed957..070ff88d7 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -5,14 +5,27 @@ .table-hider { background-color: #fff; color: var(--color-link); - padding: 10px; + padding: 0 10px; + height: 0; cursor: pointer; box-shadow: 0 0 2px 0 rgba(0,0,0,0.6); position: absolute; + overflow: hidden; + transition: .3s; + + &:hover { + background-color: var(--color-grey-light); + } .table-hider__label { display: none; } + + &.table-hider--visible { + display: flex; + padding: 10px; + height: auto; + } } } From 9e449ddaed31aba904d7a6bbd367cc256180d237 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Thu, 28 Nov 2019 15:45:36 +0100 Subject: [PATCH 17/46] fix(hide-columns): remove debug text from template --- templates/table/colonnade.hamlet | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/table/colonnade.hamlet b/templates/table/colonnade.hamlet index f13131530..081195f60 100644 --- a/templates/table/colonnade.hamlet +++ b/templates/table/colonnade.hamlet @@ -1,6 +1,5 @@ $newline never
- Table Utils:
$maybe wHeaders' <- wHeaders From 506f94e5d4afd2e2a955dab654f9a566a4152728 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Fri, 29 Nov 2019 14:24:58 +0100 Subject: [PATCH 18/46] feat(hide-columns): fadein transformation --- .../src/utils/hide-columns/hide-columns.js | 1 + .../src/utils/hide-columns/hide-columns.scss | 26 +++++++------------ 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 976c24622..e8c826408 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -103,6 +103,7 @@ export class HideColumns { hider.addEventListener('click', (event) => { event.preventDefault(); this.switchColumnDisplay(th, hider); + this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); }); th.addEventListener('mouseover', () => { diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index 070ff88d7..484e02b49 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -5,13 +5,15 @@ .table-hider { background-color: #fff; color: var(--color-link); - padding: 0 10px; - height: 0; + padding: 10px; cursor: pointer; box-shadow: 0 0 2px 0 rgba(0,0,0,0.6); position: absolute; overflow: hidden; - transition: .3s; + + transition: transform .2s ease 1s; + transform: scaleY(0); + transform-origin: top; &:hover { background-color: var(--color-grey-light); @@ -22,25 +24,20 @@ } &.table-hider--visible { - display: flex; - padding: 10px; - height: auto; + transform: scaleY(1); } } } [table-utils] { - margin-bottom: 20px; - line-height: 1.4; max-width: 85vw; + margin-bottom: 20px; + min-height: 0; .table-pill { background-color: var(--color-dark); color: #fff; - padding-top: 10px; - padding-bottom: 10px; - padding-right: 10px; - padding-left: 10px; + padding: 10px; border-radius: 20px 20px 20px 20px / 50% 50% 50% 50%; margin-right: 20px; cursor: pointer; @@ -51,11 +48,6 @@ margin-left: 5px; } } - .table-pill.table-pill--hide { - /* -webkit-animation: fadeout 0.5s linear forwards; */ - /* animation: fadeout 0.5s linear forwards; */ - /* animation-delay: 2s; */ - } } .hide-columns--hidden-cell { From 8e03a68e6d974b8b4157864fc93bf0ec5e984feb Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Fri, 29 Nov 2019 14:41:23 +0100 Subject: [PATCH 19/46] style(hide-columns): no table margin-top with table-hider sibling above --- frontend/src/utils/hide-columns/hide-columns.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index 484e02b49..5899dd08d 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -27,6 +27,10 @@ transform: scaleY(1); } } + + &+.table { + margin-top: 0px; + } } [table-utils] { From 9d8ca38f2e7016b753d7951a12b4b10ac3089c9f Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Fri, 29 Nov 2019 15:06:28 +0100 Subject: [PATCH 20/46] fix(hide-columns): fix repositioning of table hiders onclick --- frontend/src/utils/hide-columns/hide-columns.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index e8c826408..fd3c94d32 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -78,9 +78,9 @@ export class HideColumns { } hideHiderBehindHeader(hider) { - // move hider right before table (inside any scrolltable element) - this._tableHiderContainer.appendChild(hider); - // reposition hider + if (!this._tableHiderContainer.contains(hider)) { + this._tableHiderContainer.appendChild(hider); + } const thR = this.hiderToHeader.get(hider).getBoundingClientRect(); const hR = hider.getBoundingClientRect(); const pR = this._tableHiderContainer.getBoundingClientRect(); @@ -103,7 +103,11 @@ export class HideColumns { hider.addEventListener('click', (event) => { event.preventDefault(); this.switchColumnDisplay(th, hider); - this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); + + // recompute position for every table hider + this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => { + this.hideHiderBehindHeader(hider); + }); }); th.addEventListener('mouseover', () => { From c2eb9fbc171a08c37a31bcaff3447824f0ab8ebf Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Fri, 29 Nov 2019 16:51:33 +0100 Subject: [PATCH 21/46] style(hide-columns): fix line-breaking of table pills --- frontend/src/utils/hide-columns/hide-columns.scss | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index 5899dd08d..394078c1c 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -35,15 +35,18 @@ [table-utils] { max-width: 85vw; - margin-bottom: 20px; + margin-bottom: 10px; min-height: 0; + line-height: 1.4; .table-pill { background-color: var(--color-dark); + float: left; color: #fff; padding: 10px; border-radius: 20px 20px 20px 20px / 50% 50% 50% 50%; margin-right: 20px; + margin-bottom: 10px; cursor: pointer; .table-hider__label { @@ -52,6 +55,12 @@ margin-left: 5px; } } + + &:after { + content: ""; + display: block; + clear: both; + } } .hide-columns--hidden-cell { From 364991c42bbb82301dd71cee8823d061f92da1ad Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Fri, 29 Nov 2019 17:18:28 +0100 Subject: [PATCH 22/46] fix(hide-columns): correctly hide hiders of previously hidden columns --- frontend/src/utils/hide-columns/hide-columns.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index fd3c94d32..a6743bd8b 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -86,6 +86,9 @@ export class HideColumns { const pR = this._tableHiderContainer.getBoundingClientRect(); hider.style.left = (thR.left + thR.width/2 - hR.width/2 - pR.left) + 'px'; hider.style.top = (thR.top - pR.top + 5 +50) + 'px'; + + // remove visible class if necessary + hider.classList.remove('table-hider--visible'); } setupHideButton(th, prevHidden) { @@ -105,9 +108,7 @@ export class HideColumns { this.switchColumnDisplay(th, hider); // recompute position for every table hider - this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => { - this.hideHiderBehindHeader(hider); - }); + this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); }); th.addEventListener('mouseover', () => { From 3fbb4db962c6493a1da2c243850d65e4f735ab4b Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Fri, 29 Nov 2019 17:52:32 +0100 Subject: [PATCH 23/46] fix(hide-columns): fix vertical positioning of hider and minor refactor --- .../src/utils/hide-columns/hide-columns.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index a6743bd8b..33de28005 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -10,8 +10,9 @@ 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'; -const HIDER_POPUP_CLASS = 'table-hider--visible'; +const TABLE_PILL_CLASS = 'table-pill'; const CELL_HIDDEN_CLASS = 'hide-columns--hidden-cell'; @@ -85,10 +86,10 @@ export class HideColumns { const hR = hider.getBoundingClientRect(); const pR = this._tableHiderContainer.getBoundingClientRect(); hider.style.left = (thR.left + thR.width/2 - hR.width/2 - pR.left) + 'px'; - hider.style.top = (thR.top - pR.top + 5 +50) + 'px'; + hider.style.top = (thR.top - pR.top + thR.height) + 'px'; // remove visible class if necessary - hider.classList.remove('table-hider--visible'); + hider.classList.remove(TABLE_HIDER_VISIBLE_CLASS); } setupHideButton(th, prevHidden) { @@ -112,22 +113,22 @@ export class HideColumns { }); th.addEventListener('mouseover', () => { - hider.classList.add(HIDER_POPUP_CLASS); + hider.classList.add(TABLE_HIDER_VISIBLE_CLASS); }); th.addEventListener('mouseout', () => { if (hider.classList.contains(TABLE_HIDER_CLASS)) { - hider.classList.remove(HIDER_POPUP_CLASS); + hider.classList.remove(TABLE_HIDER_VISIBLE_CLASS); } }); hider.addEventListener('mouseover', () => { - hider.classList.add(HIDER_POPUP_CLASS); + hider.classList.add(TABLE_HIDER_VISIBLE_CLASS); const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); this.updateHiderIcon(hider, !currentlyHidden); }); hider.addEventListener('mouseout', () => { if (hider.classList.contains(TABLE_HIDER_CLASS)) { - hider.classList.remove(HIDER_POPUP_CLASS); + hider.classList.remove(TABLE_HIDER_VISIBLE_CLASS); } const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); this.updateHiderIcon(hider, currentlyHidden); @@ -173,11 +174,11 @@ export class HideColumns { if (hidden) { this._tableUtilContainer.appendChild(hider); hider.classList.remove(TABLE_HIDER_CLASS); - hider.classList.add('table-pill'); + hider.classList.add(TABLE_PILL_CLASS); } else { this.hideHiderBehindHeader(hider); this._tableHiderContainer.appendChild(hider); - hider.classList.remove('table-pill'); + hider.classList.remove(TABLE_PILL_CLASS); hider.classList.add(TABLE_HIDER_CLASS); } this.updateHiderIcon(hider, hidden); From d1232ce72d45ddcabe14f9770a0f8117d8efe74d Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Mon, 2 Dec 2019 11:19:50 +0100 Subject: [PATCH 24/46] feat(hide-columns): hide empty columns per default --- .../src/utils/hide-columns/hide-columns.js | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 33de28005..f8d2cd755 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -5,6 +5,8 @@ import './hide-columns.scss'; const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; const TABLE_HEADER_IDENT = 'uw-hide-column-header'; +const ASYNC_TABLE_IDENT = 'uw-async-table'; + const TABLE_UTILS_ATTR = 'table-utils'; const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`; @@ -158,6 +160,8 @@ export class HideColumns { } updateColumnDisplay(columnIndex, hidden) { + let isColumnWithContent = false; + this._element.getElementsByTagName('tr').forEach(row => { const cell = row.cells[columnIndex]; if (cell) { @@ -165,9 +169,26 @@ export class HideColumns { cell.classList.add(CELL_HIDDEN_CLASS); } else { cell.classList.remove(CELL_HIDDEN_CLASS); + + // determine if this cell has content + if (cell.nodeName === 'TD') { + let cellHasContent = false; + if (this._elementWrapper.hasAttribute(ASYNC_TABLE_IDENT)) { + cell.children.forEach(child => { + cellHasContent = cellHasContent || !isEmptyElement(child); + }); + } else { + cellHasContent = !isEmptyElement(cell); + } + isColumnWithContent = isColumnWithContent || cellHasContent; + } } } }); + + if (!hidden && !isColumnWithContent) { + this.updateColumnDisplay(columnIndex, true); + } } updateHider(hider, hidden) { @@ -216,3 +237,12 @@ export class HideColumns { } } + +function isEmptyElement(element) { + for (let child of element.childNodes) { + if (child.nodeName !== '#comment') + return false; + } + return true; +} + From 047c0a5787657be7f810b20599bb1015a99b4e9b Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Mon, 2 Dec 2019 18:19:50 +0100 Subject: [PATCH 25/46] feat(hide-columns): refactor and auto-hide empty columns --- .../src/utils/hide-columns/hide-columns.js | 136 ++++++++++-------- .../src/utils/hide-columns/hide-columns.scss | 26 ++-- stack.yaml.lock | 43 +++++- templates/default-layout.lucius | 8 +- 4 files changed, 135 insertions(+), 78 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index f8d2cd755..c8599e17e 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -73,32 +73,18 @@ export class HideColumns { this._element.parentElement.insertBefore(this._tableHiderContainer, this._element); } - this._element.querySelectorAll('th').forEach(th => { - const storageKey = this.getStorageKey(th); - const previouslyHidden = this._storageManager.load(storageKey); - this.setupHideButton(th, previouslyHidden); - }); + this._element.querySelectorAll('th').forEach(th => this.setupHideButton(th)); } - hideHiderBehindHeader(hider) { - if (!this._tableHiderContainer.contains(hider)) { - this._tableHiderContainer.appendChild(hider); - } - const thR = this.hiderToHeader.get(hider).getBoundingClientRect(); - const hR = hider.getBoundingClientRect(); - const pR = this._tableHiderContainer.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'; + setupHideButton(th) { + const preHidden = this.isHiddenColumn(th); - // remove visible class if necessary - hider.classList.remove(TABLE_HIDER_VISIBLE_CLASS); - } - - setupHideButton(th, prevHidden) { const hider = document.createElement('span'); + const hiderIcon = document.createElement('i'); hiderIcon.classList.add('fas', 'fa-fw'); hider.appendChild(hiderIcon); + const hiderContent = document.createElement('span'); hiderContent.classList.add('table-hider__label'); hiderContent.innerHTML = th.innerText; @@ -106,14 +92,6 @@ export class HideColumns { this.addHeaderHider(th, hider); - hider.addEventListener('click', (event) => { - event.preventDefault(); - this.switchColumnDisplay(th, hider); - - // recompute position for every table hider - this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); - }); - th.addEventListener('mouseover', () => { hider.classList.add(TABLE_HIDER_VISIBLE_CLASS); }); @@ -123,45 +101,51 @@ export class HideColumns { } }); + hider.addEventListener('click', (event) => { + event.preventDefault(); + this.switchColumnDisplay(th, hider); + this._tableHiderContainer.getElementsByClassName(TABLE_HIDER_CLASS).forEach(hider => this.hideHiderBehindHeader(hider)); + }); + hider.addEventListener('mouseover', () => { hider.classList.add(TABLE_HIDER_VISIBLE_CLASS); - const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); + const currentlyHidden = this.isHiddenColumn(th); this.updateHiderIcon(hider, !currentlyHidden); }); hider.addEventListener('mouseout', () => { if (hider.classList.contains(TABLE_HIDER_CLASS)) { hider.classList.remove(TABLE_HIDER_VISIBLE_CLASS); } - const currentlyHidden = this._storageManager.load(this.getStorageKey(th)); + const currentlyHidden = this.isHiddenColumn(th); this.updateHiderIcon(hider, currentlyHidden); }); - this.updateColumnDisplay(th.cellIndex, prevHidden); - this.updateHider(hider, prevHidden); + // reposition hider on each window resize event + window.addEventListener('resize', () => this.repositionHider(hider)); - if (prevHidden) { + if (preHidden) { this._tableUtilContainer.appendChild(hider); } else { this.hideHiderBehindHeader(hider); } + this.updateColumnDisplay(th.cellIndex, preHidden); + this.updateHider(hider, preHidden); + + this._tableHiderContainer.children.forEach(hider => this.repositionHider(hider)); } switchColumnDisplay(th, hider) { - const storageKey = this.getStorageKey(th); - - const hidden = !this._storageManager.load(storageKey); + const hidden = !this.isHiddenColumn(th); this.updateColumnDisplay(th.cellIndex, hidden); this.updateHider(hider, hidden); // persist new hidden setting for column - this._storageManager.save(storageKey, hidden); + this._storageManager.save(this.getStorageKey(th), hidden); } updateColumnDisplay(columnIndex, hidden) { - let isColumnWithContent = false; - this._element.getElementsByTagName('tr').forEach(row => { const cell = row.cells[columnIndex]; if (cell) { @@ -169,46 +153,49 @@ export class HideColumns { cell.classList.add(CELL_HIDDEN_CLASS); } else { cell.classList.remove(CELL_HIDDEN_CLASS); - - // determine if this cell has content - if (cell.nodeName === 'TD') { - let cellHasContent = false; - if (this._elementWrapper.hasAttribute(ASYNC_TABLE_IDENT)) { - cell.children.forEach(child => { - cellHasContent = cellHasContent || !isEmptyElement(child); - }); - } else { - cellHasContent = !isEmptyElement(cell); - } - isColumnWithContent = isColumnWithContent || cellHasContent; - } } } }); - - if (!hidden && !isColumnWithContent) { - this.updateColumnDisplay(columnIndex, true); - } } updateHider(hider, hidden) { if (hidden) { - this._tableUtilContainer.appendChild(hider); hider.classList.remove(TABLE_HIDER_CLASS); hider.classList.add(TABLE_PILL_CLASS); + this._tableUtilContainer.appendChild(hider); } else { - this.hideHiderBehindHeader(hider); - this._tableHiderContainer.appendChild(hider); hider.classList.remove(TABLE_PILL_CLASS); hider.classList.add(TABLE_HIDER_CLASS); + this.hideHiderBehindHeader(hider); } this.updateHiderIcon(hider, hidden); } updateHiderIcon(hider, hidden) { - const hiderIcon = hider.getElementsByClassName('fas')[0]; - hiderIcon.classList.remove(hidden ? 'fa-eye' : 'fa-eye-slash'); - hiderIcon.classList.add(hidden ? 'fa-eye-slash' : 'fa-eye'); + hider.getElementsByClassName('fas').forEach(hiderIcon => { + hiderIcon.classList.remove(hidden ? 'fa-eye' : 'fa-eye-slash'); + hiderIcon.classList.add(hidden ? 'fa-eye-slash' : 'fa-eye'); + }); + } + + hideHiderBehindHeader(hider) { + if (!this._tableHiderContainer.contains(hider)) { + this._tableHiderContainer.appendChild(hider); + } + + this.repositionHider(hider); + + // remove visible class if necessary + hider.classList.remove(TABLE_HIDER_VISIBLE_CLASS); + } + + repositionHider(hider) { + const thR = this.hiderToHeader.get(hider).getBoundingClientRect(), + hR = hider.getBoundingClientRect(), + pR = this._tableHiderContainer.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'; } getStorageKey(th) { @@ -236,6 +223,33 @@ export class HideColumns { return `${handlerIdent}__${tIdent}__${thIdent}`; } + isEmptyColumn(columnIndex) { + for (let row of this._element.getElementsByTagName('TR')) { + if (row.children.length <= columnIndex) { + throw new Error('Invalid column index for table'); + } + + const cell = row.children[columnIndex]; + if (cell.tagName === 'TH') + continue; + if (this._element.closest(`[${ASYNC_TABLE_IDENT}]`)) { + for (let child of cell.children) { + if (!isEmptyElement(child)) + return false; + } + return true; + } else { + return isEmptyElement(cell); + } + } + } + + isHiddenColumn(th) { + const hidden = this._storageManager.load(this.getStorageKey(th)), + emptyColumn = this.isEmptyColumn(th.cellIndex); + return hidden === true || hidden === undefined && emptyColumn; + } + } function isEmptyElement(element) { diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index 394078c1c..d3df5addc 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -11,7 +11,7 @@ position: absolute; overflow: hidden; - transition: transform .2s ease 1s; + /* transition: transform .2s ease; */ transform: scaleY(0); transform-origin: top; @@ -24,7 +24,20 @@ } &.table-hider--visible { - transform: scaleY(1); + 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); + } + } } } @@ -66,12 +79,3 @@ .hide-columns--hidden-cell { display: none; } - -@keyframes fadeout { - 0% { opacity: 1; } - 100% { opacity: 0; } -} -@keyframes fadein { - 0% { opacity: 0; } - 100% { opacity: 1; } -} diff --git a/stack.yaml.lock b/stack.yaml.lock index 3758cb266..3a7017a21 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -138,12 +138,33 @@ packages: original: hackage: HaXml-1.25.5 - completed: - hackage: esqueleto-3.0.0@sha256:efd84fd11ceaf0ae4e1b0c6236122b1f213c2c6f2f4f58e30f03eddc2ec3f423,5248 + hackage: persistent-2.10.4@sha256:16c4c0823dd5e16bac4d607895ab0f4febd0626c020e5755ed1a52bf04068148,4738 pantry-tree: - size: 1127 - sha256: 74e43834d5cc468acc3cb6e8a81567ebfbb5350a3e07ae01dd7f30d6255274a1 + size: 2094 + sha256: b40d1783b539ddbbceaa827bf286d0b3bfcf76ca19e604c9d510b2a64008714e original: - hackage: esqueleto-3.0.0 + hackage: persistent-2.10.4 +- completed: + hackage: persistent-postgresql-2.10.1@sha256:ea53a0f1f4223b4884b5e19511325367879560d2432a02a976aa4da57c5fb760,2871 + pantry-tree: + size: 740 + sha256: 3cdbc757b1cebb65542fb919369be238b3f120adc45f023084a8b64c214d9675 + original: + hackage: persistent-postgresql-2.10.1 +- completed: + hackage: persistent-template-2.7.3@sha256:ac3e5e8c48e968b927bbf4e97162c52e7e417d69b05efeb1c581d7c682e043d2,2703 + pantry-tree: + size: 560 + sha256: fdfb2a721eb9c9831d7381d36bc52de0808a008ed3d553b6490080f337249684 + original: + hackage: persistent-template-2.7.3 +- completed: + hackage: esqueleto-3.2.3@sha256:5e1e0a8600e2744127ef4bb5956fa84ae6bc1fc337c7b8726fabb7ca53e2d9b3,5466 + pantry-tree: + size: 1461 + sha256: f6215274a43addd339f8bc89f1ca0e8fdfb08180b13d779ae8f7e360acc4c473 + original: + hackage: esqueleto-3.2.3 - completed: hackage: HaskellNet-SSL-0.3.4.1@sha256:3ca14dd69460a380cf69aed40654fb10c4c03e344632b6a9986568c87feda157,1843 pantry-tree: @@ -242,6 +263,20 @@ packages: sha256: 9ed161eadfda5b1eb36cfcf077146f7b66db1da69f1041fc720aea287ec021b0 original: hackage: generic-lens-1.2.0.0 +- completed: + hackage: prometheus-metrics-ghc-1.0.0@sha256:0f4ecbefa810bd847e66c498ab3387bf21e426525a7c9a94841973c582719ba3,1231 + pantry-tree: + size: 293 + sha256: 8a6d6ef3235ab980e867f64b712b5d38f1a84c3ac4920f5b4c3b3e63bcdf6ec9 + original: + hackage: prometheus-metrics-ghc-1.0.0 +- completed: + hackage: wai-middleware-prometheus-1.0.0@sha256:1625792914fb2139f005685be8ce519111451cfb854816e430fbf54af46238b4,1314 + pantry-tree: + size: 307 + sha256: 6d64803c639ed4c7204ea6fab0536b97d3ee16cdecb9b4a883cd8e56d3c61402 + original: + hackage: wai-middleware-prometheus-1.0.0 snapshots: - completed: size: 498180 diff --git a/templates/default-layout.lucius b/templates/default-layout.lucius index 11355082b..0f09cb225 100644 --- a/templates/default-layout.lucius +++ b/templates/default-layout.lucius @@ -329,8 +329,12 @@ input[type="button"].btn-info:hover, width: 100%; } -.table:only-child { - margin: 0; +.table:first-child { + margin-top: 0; +} + +.table:last-child { + margin-bottom: 0; } .table--striped { From 827cecda8f4244861f05ec988c00929591c94bec Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Mon, 2 Dec 2019 18:27:14 +0100 Subject: [PATCH 26/46] fix(hide-columns): fix crash if no row is present --- frontend/src/utils/hide-columns/hide-columns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index c8599e17e..766277170 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -226,7 +226,7 @@ export class HideColumns { isEmptyColumn(columnIndex) { for (let row of this._element.getElementsByTagName('TR')) { if (row.children.length <= columnIndex) { - throw new Error('Invalid column index for table'); + return; } const cell = row.children[columnIndex]; From ff366a785b9991f21806f2d54f4c99170ce1cf38 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Mon, 2 Dec 2019 19:35:03 +0100 Subject: [PATCH 27/46] style(hide-columns): hide hiders on setup --- frontend/src/utils/hide-columns/hide-columns.js | 6 +++--- frontend/src/utils/hide-columns/hide-columns.scss | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 766277170..1901130c6 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -123,15 +123,15 @@ export class HideColumns { // reposition hider on each window resize event window.addEventListener('resize', () => this.repositionHider(hider)); + this.updateColumnDisplay(th.cellIndex, preHidden); + this.updateHider(hider, preHidden); + if (preHidden) { this._tableUtilContainer.appendChild(hider); } else { this.hideHiderBehindHeader(hider); } - this.updateColumnDisplay(th.cellIndex, preHidden); - this.updateHider(hider, preHidden); - this._tableHiderContainer.children.forEach(hider => this.repositionHider(hider)); } diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss index d3df5addc..77a73bee3 100644 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ b/frontend/src/utils/hide-columns/hide-columns.scss @@ -10,8 +10,7 @@ box-shadow: 0 0 2px 0 rgba(0,0,0,0.6); position: absolute; overflow: hidden; - - /* transition: transform .2s ease; */ + transition: transform .2s ease; transform: scaleY(0); transform-origin: top; @@ -57,7 +56,7 @@ float: left; color: #fff; padding: 10px; - border-radius: 20px 20px 20px 20px / 50% 50% 50% 50%; + border-radius: 20px / 50%; margin-right: 20px; margin-bottom: 10px; cursor: pointer; From 615555eb597bf4a87b83020275cce7f30495d0ac Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Mon, 2 Dec 2019 19:44:15 +0100 Subject: [PATCH 28/46] fix(hide-columns): check for content div in isEmptyColumn --- frontend/src/utils/hide-columns/hide-columns.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index 1901130c6..e10627a71 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -5,8 +5,6 @@ import './hide-columns.scss'; const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; const TABLE_HEADER_IDENT = 'uw-hide-column-header'; -const ASYNC_TABLE_IDENT = 'uw-async-table'; - const TABLE_UTILS_ATTR = 'table-utils'; const TABLE_UTILS_CONTAINER_SELECTOR = `[${TABLE_UTILS_ATTR}]`; @@ -232,7 +230,7 @@ export class HideColumns { const cell = row.children[columnIndex]; if (cell.tagName === 'TH') continue; - if (this._element.closest(`[${ASYNC_TABLE_IDENT}]`)) { + if (cell.querySelector('.table__td-content')) { for (let child of cell.children) { if (!isEmptyElement(child)) return false; From 0798d6870e7b4dfd0baf23940fe5d87b9c2d444c Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Dec 2019 15:58:09 +0100 Subject: [PATCH 29/46] feat(hide-columns): support colspan & don't persist autohide --- .../lib/storage-manager/storage-manager.js | 21 ++++- .../src/utils/hide-columns/hide-columns.js | 88 +++++++++++++++---- 2 files changed, 93 insertions(+), 16 deletions(-) diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js index cb82a0006..8297627fa 100644 --- a/frontend/src/lib/storage-manager/storage-manager.js +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -50,6 +50,26 @@ export class StorageManager { } } + remove(key, options) { + if (options && options.lifetime !== undefined && !Object.values(LIFETIME).includes(options.lifetime)) { + throw new Error('StorageManager.load called with unsupported lifetime option'); + } + + const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; + + switch (lifetime) { + case LIFETIME.INFINITE: { + var val = this.getFromLocalStorage(); + + delete val[key]; + + return this.saveToLocalStorage(val); + } + default: + console.error('StorageManager.load cannot load item with unsupported lifetime'); + } + } + getFromLocalStorage() { const state = JSON.parse(window.localStorage.getItem(this.namespace)); if (state === null) { @@ -67,5 +87,4 @@ export class StorageManager { clearLocalStorage() { window.localStorage.removeItem(this.namespace); } - } diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index e10627a71..c4a1f6f0f 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -15,6 +15,7 @@ const TABLE_HIDER_VISIBLE_CLASS = 'table-hider--visible'; const TABLE_PILL_CLASS = 'table-pill'; const CELL_HIDDEN_CLASS = 'hide-columns--hidden-cell'; +const CELL_ORIGINAL_COLSPAN = 'uw-hide-column-original-colspan'; @Utility({ selector: `[${HIDE_COLUMNS_CONTAINER_IDENT}] table`, @@ -121,7 +122,7 @@ export class HideColumns { // reposition hider on each window resize event window.addEventListener('resize', () => this.repositionHider(hider)); - this.updateColumnDisplay(th.cellIndex, preHidden); + this.updateColumnDisplay(this.colIndex(th), preHidden); this.updateHider(hider, preHidden); if (preHidden) { @@ -135,22 +136,46 @@ export class HideColumns { switchColumnDisplay(th, hider) { const hidden = !this.isHiddenColumn(th); + const originalColspan = Math.max(1, th.getAttribute(CELL_ORIGINAL_COLSPAN)) || 1; + const colspan = Math.max(1, th.colSpan) || 1; + const columnIndex = this.colIndex(th); - this.updateColumnDisplay(th.cellIndex, hidden); + for (var i = 0; i < Math.max(colspan, originalColspan); i++) { + this.updateColumnDisplay(columnIndex + i, hidden); + } this.updateHider(hider, hidden); // persist new hidden setting for column - this._storageManager.save(this.getStorageKey(th), hidden); + if (hidden && this.isEmptyColumn(columnIndex)) { + this._storageManager.remove(this.getStorageKey(th)); + } else { + this._storageManager.save(this.getStorageKey(th), hidden); + } } updateColumnDisplay(columnIndex, hidden) { this._element.getElementsByTagName('tr').forEach(row => { - const cell = row.cells[columnIndex]; + const cell = this.getCol(row, columnIndex); + if (cell) { + const originalColspan = cell.getAttribute(CELL_ORIGINAL_COLSPAN); + const colspan = Math.max(1, cell.colSpan) || 1; + if (hidden) { - cell.classList.add(CELL_HIDDEN_CLASS); + if (colspan > 1) { + if (!originalColspan) { + cell.setAttribute(CELL_ORIGINAL_COLSPAN, colspan); + } + cell.colSpan--; + } else { + cell.classList.add(CELL_HIDDEN_CLASS); + } } else { - cell.classList.remove(CELL_HIDDEN_CLASS); + if (cell.classList.contains(CELL_HIDDEN_CLASS)) { + cell.classList.remove(CELL_HIDDEN_CLASS); + } else if (originalColspan && colspan < originalColspan) { + cell.colSpan++; + } } } }); @@ -215,20 +240,16 @@ export class HideColumns { // check for unique table header ident from backend (if not present, use cell index as fallback) let thIdent = th.getAttribute(TABLE_HEADER_IDENT); if (!thIdent) { - thIdent = th.cellIndex; + thIdent = this.colIndex(th); } return `${handlerIdent}__${tIdent}__${thIdent}`; } isEmptyColumn(columnIndex) { - for (let row of this._element.getElementsByTagName('TR')) { - if (row.children.length <= columnIndex) { - return; - } - - const cell = row.children[columnIndex]; - if (cell.tagName === 'TH') + for (let row of this._element.getElementsByTagName('tr')) { + const cell = this.getCol(row, columnIndex); + if (cell.matches('th')) continue; if (cell.querySelector('.table__td-content')) { for (let child of cell.children) { @@ -244,10 +265,47 @@ export class HideColumns { isHiddenColumn(th) { const hidden = this._storageManager.load(this.getStorageKey(th)), - emptyColumn = this.isEmptyColumn(th.cellIndex); + emptyColumn = this.isEmptyColumn(this.colIndex(th)); return hidden === true || hidden === undefined && emptyColumn; } + colSpan(cell) { + if (!cell) + return 1; + + const originalColspan = cell.getAttribute(CELL_ORIGINAL_COLSPAN); + const colspan = Math.max(1, cell.colSpan) || 1; + + return originalColspan ? Math.max(colspan, originalColspan) : colspan; + } + + colIndex(cell) { + if (!cell) + return 0; + + const rowParent = cell.closest('tr'); + + if (!rowParent) + return 0; + + var i = 0; + for (const sibling of Array.from(rowParent.cells).slice(0, cell.cellIndex)) { + i += this.colSpan(sibling); + } + + return i; + } + + getCol(row, columnIndex) { + var c = 0; + + for (const cell of row.cells) { + c += cell ? this.colSpan(cell) : 1; + + if (columnIndex < c) + return cell; + } + } } function isEmptyElement(element) { From 80ff4ac2a734bf295a026aa68d5d881da9cca3bd Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Dec 2019 17:02:32 +0100 Subject: [PATCH 30/46] feat(storage-manager): location hierarchy --- .../lib/storage-manager/storage-manager.js | 174 +++++++++++++----- .../src/utils/hide-columns/hide-columns.js | 4 +- 2 files changed, 134 insertions(+), 44 deletions(-) diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js index 8297627fa..a5e3e0e8f 100644 --- a/frontend/src/lib/storage-manager/storage-manager.js +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -1,90 +1,180 @@ -const LIFETIME = { - INFINITE: 'infinite', +export const LOCATION = { + LOCAL: 'local', + WINDOW: 'window', }; +const LOCATION_SHADOWING = [ LOCATION.WINDOW, LOCATION.LOCAL ]; + export class StorageManager { namespace; + _options; - constructor(namespace) { + constructor(namespace, options) { if (!namespace) { throw new Error('Cannot setup StorageManager without namespace'); } this.namespace = namespace; + + if (options !== undefined) { + this._options = options; + } } - save(key, value, options) { + save(key, value, options=this._options) { if (!key) { throw new Error('StorageManager.save called with invalid key'); } - if (options && options.lifetime !== undefined && !Object.values(LIFETIME).includes(options.lifetime)) { - throw new Error('StorageManager.save called with unsupported lifetime option'); + if (options && options.location !== undefined && !Object.values(LOCATION).includes(options.location)) { + throw new Error('StorageManager.save called with unsupported location option'); } - const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; + const location = options && options.location !== undefined ? options.location : LOCATION_SHADOWING[0]; - switch (lifetime) { - case LIFETIME.INFINITE: { - this.saveToLocalStorage({ ...this.getFromLocalStorage(), [key]: value }); + switch (location) { + case LOCATION.LOCAL: { + this._saveToLocalStorage({ ...this._getFromLocalStorage(), [key]: value }); + break; + } + case LOCATION.WINDOW: { + this._saveToWindow({ ...this._getFromLocalStorage(), [key]: value }); break; } default: - console.error('StorageManager.save cannot save item with unsupported lifetime'); + console.error('StorageManager.save cannot save item with unsupported location'); } } - load(key, options) { - if (options && options.lifetime !== undefined && !Object.values(LIFETIME).includes(options.lifetime)) { - throw new Error('StorageManager.load called with unsupported lifetime option'); + load(key, options=this._options) { + if (options && options.location !== undefined && !Object.values(LOCATION).includes(options.location)) { + throw new Error('StorageManager.load called with unsupported location option'); } - const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; + let locations = options && options.location !== undefined ? [options.location] : LOCATION_SHADOWING; - switch (lifetime) { - case LIFETIME.INFINITE: - return this.getFromLocalStorage()[key]; - default: - console.error('StorageManager.load cannot load item with unsupported lifetime'); - } - } - - remove(key, options) { - if (options && options.lifetime !== undefined && !Object.values(LIFETIME).includes(options.lifetime)) { - throw new Error('StorageManager.load called with unsupported lifetime option'); - } - - const lifetime = options && options.lifetime !== undefined ? options.lifetime : LIFETIME.INFINITE; - - switch (lifetime) { - case LIFETIME.INFINITE: { - var val = this.getFromLocalStorage(); - - delete val[key]; + while (locations.length > 0) { + const location = locations.shift(); + let val; - return this.saveToLocalStorage(val); + switch (location) { + case LOCATION.LOCAL: { + val = this._getFromLocalStorage()[key]; + break; + } + case LOCATION.WINDOW: { + val = this._getFromWindow()[key]; + break; + } + default: + console.error('StorageManager.load cannot load item with unsupported location'); + } + + if (val !== undefined || locations.length === 0) { + return val; } - default: - console.error('StorageManager.load cannot load item with unsupported lifetime'); } } - getFromLocalStorage() { + remove(key, options=this._options) { + if (options && options.location !== undefined && !Object.values(LOCATION).includes(options.location)) { + throw new Error('StorageManager.load called with unsupported location option'); + } + + const locations = options && options.location !== undefined ? [options.location] : LOCATION_SHADOWING; + + for (const location of locations) { + switch (location) { + case LOCATION.LOCAL: { + let val = this._getFromLocalStorage(); + + delete val[key]; + + return this._saveToLocalStorage(val); + } + case LOCATION.WINDOW: { + let val = this._getFromWindow(); + + delete val[key]; + + return this._saveToWindow(val); + } + default: + console.error('StorageManager.load cannot load item with unsupported location'); + } + } + } + + clear(options) { + if (options && options.location !== undefined && !Object.values(LOCATION).includes(options.location)) { + throw new Error('StorageManager.clear called with unsupported location option'); + } + + const locations = options && options.location !== undefined ? [options.location] : LOCATION_SHADOWING; + + for (const location of locations) { + switch (location) { + case LOCATION.LOCAL: + return this._clearLocalStorage(); + case LOCATION.WINDOW: + return this._clearWindow(); + default: + console.error('StorageManager.clear cannot clear with unsupported location'); + } + } + + } + + + _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) - this.clearLocalStorage(); + this._clearLocalStorage(); return {}; } return state; } - saveToLocalStorage(value) { + _saveToLocalStorage(value) { window.localStorage.setItem(this.namespace, JSON.stringify(value)); } - clearLocalStorage() { + _clearLocalStorage() { window.localStorage.removeItem(this.namespace); } + + + _getFromWindow() { + if (!window || !window.App) + return {}; + + if (!window.App.Storage) + window.App.Storage = {}; + + if (!window.App.Storage[this.namespace]) + return {}; + + return window.App.Storage[this.namespace]; + } + + _saveToWindow(value) { + if (!window || !window.App) { + throw new Error('StorageManager._saveToWindow called when window.App is not available'); + } + + if (!window.App.Storage) + window.App.Storage = {}; + + window.App.Storage[this.namespace] = value; + } + + _clearWindow() { + if (!window || !window.App) { + throw new Error('StorageManager._saveToWindow called when window.App is not available'); + } + + delete window.App.Storage[this.namespace]; + } } diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index c4a1f6f0f..420916f41 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import { StorageManager } from '../../lib/storage-manager/storage-manager'; +import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager'; import './hide-columns.scss'; const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; @@ -22,7 +22,7 @@ const CELL_ORIGINAL_COLSPAN = 'uw-hide-column-original-colspan'; }) export class HideColumns { - _storageManager = new StorageManager('HIDE_COLUMNS'); + _storageManager = new StorageManager('HIDE_COLUMNS', { location: LOCATION.LOCAL }); _element; _elementWrapper; From 33d9bacc8aa3e412e88251a76a389d19fd148210 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Dec 2019 17:22:09 +0100 Subject: [PATCH 31/46] fix(allocation-list): fix sorting --- src/Handler/Allocation/List.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Handler/Allocation/List.hs b/src/Handler/Allocation/List.hs index 9d52233ed..558d4c889 100644 --- a/src/Handler/Allocation/List.hs +++ b/src/Handler/Allocation/List.hs @@ -89,7 +89,7 @@ getAllocationListR = do dbtSorting = mconcat [ sortTerm $ queryAllocation . to (E.^. AllocationTerm) - , sortSchool $ queryAllocation . to (E.^. AllocationSchool) + , sortSchoolShort $ queryAllocation . to (E.^. AllocationSchool) , sortAllocationName $ queryAllocation . to (E.^. AllocationName) , singletonMap "available" . SortColumn $ view queryAvailable , if From 0b56ecc6ec50a110b6307045d3028e3bdcde7bd0 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Dec 2019 17:24:05 +0100 Subject: [PATCH 32/46] refactor(async-table): migrate to StorageManager --- .../lib/storage-manager/storage-manager.js | 10 +++- frontend/src/utils/async-table/async-table.js | 47 +++++++------------ 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js index a5e3e0e8f..d2e407593 100644 --- a/frontend/src/lib/storage-manager/storage-manager.js +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -138,6 +138,9 @@ export class StorageManager { } _saveToLocalStorage(value) { + if (!value) + return this._clearLocalStorage(); + window.localStorage.setItem(this.namespace, JSON.stringify(value)); } @@ -164,6 +167,9 @@ export class StorageManager { throw new Error('StorageManager._saveToWindow called when window.App is not available'); } + if (!value) + return this._clearWindow(); + if (!window.App.Storage) window.App.Storage = {}; @@ -175,6 +181,8 @@ export class StorageManager { throw new Error('StorageManager._saveToWindow called when window.App is not available'); } - delete window.App.Storage[this.namespace]; + if (window.App.Storage) { + delete window.App.Storage[this.namespace]; + } } } diff --git a/frontend/src/utils/async-table/async-table.js b/frontend/src/utils/async-table/async-table.js index b8330aa4b..3067e0f1f 100644 --- a/frontend/src/utils/async-table/async-table.js +++ b/frontend/src/utils/async-table/async-table.js @@ -1,4 +1,5 @@ import { Utility } from '../../core/utility'; +import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager'; import { Datepicker } from '../form/datepicker'; import { HttpClient } from '../../services/http-client/http-client'; import * as debounce from 'lodash.debounce'; @@ -40,6 +41,8 @@ export class AsyncTable { }; _ignoreRequest = false; + _storageManager = new StorageManager(ASYNC_TABLE_LOCAL_STORAGE_KEY, { location: LOCATION.LOCAL }); + constructor(element, app) { if (!element) { throw new Error('Async Table utility cannot be setup without an element!'); @@ -81,10 +84,10 @@ export class AsyncTable { this._setupPageSizeSelect(); this._setupTableFilter(); - this._processLocalStorage(); + this._processStorage(); // clear currentTableUrl from previous requests - setLocalStorageParameter('currentTableUrl', null); + this._storageManager.remove('currentTableUrl'); // mark initialized this._element.classList.add(ASYNC_TABLE_INITIALIZED_CLASS); @@ -100,7 +103,7 @@ export class AsyncTable { this._ths.forEach((th) => { th.clickHandler = (event) => { - setLocalStorageParameter('horizPos', (this._scrollTable || {}).scrollLeft); + this._storageManager.save('horizPos', (this._scrollTable || {}).scrollLeft); this._linkClickHandler(event); }; th.element.addEventListener('click', th.clickHandler); @@ -122,7 +125,7 @@ export class AsyncTable { left: this._scrollTable.offsetLeft || 0, behavior: 'smooth', }; - setLocalStorageParameter('scrollTo', scrollTo); + this._storageManager.save('scrollTo', scrollTo); } this._linkClickHandler(event); }; @@ -225,7 +228,7 @@ export class AsyncTable { const prefix = findCssIdPrefix(focusedInput.id); const focusId = focusedInput.id.replace(prefix, ''); callback = function(wrapper) { - const idPrefix = getLocalStorageParameter('cssIdPrefix'); + const idPrefix = this._storageManager.load('cssIdPrefix', { location: LOCATION.WINDOW }); const toBeFocused = wrapper.querySelector('#' + idPrefix + focusId); if (toBeFocused) { toBeFocused.focus(); @@ -238,7 +241,7 @@ export class AsyncTable { } _serializeTableFilterToURL(tableFilterForm) { - const url = new URL(getLocalStorageParameter('currentTableUrl') || window.location.href); + const url = new URL(this._storageManager.load('currentTableUrl') || window.location.href); // create new FormData and format any date values const formData = Datepicker.unformatAll(this._massInputForm, new FormData(tableFilterForm)); @@ -254,18 +257,18 @@ export class AsyncTable { return url; } - _processLocalStorage() { - const scrollTo = getLocalStorageParameter('scrollTo'); + _processStorage() { + const scrollTo = this._storageManager.load('scrollTo'); if (scrollTo && this._scrollTable) { window.scrollTo(scrollTo); } - setLocalStorageParameter('scrollTo', null); + this._storageManager.remove('scrollTo'); - const horizPos = getLocalStorageParameter('horizPos'); + const horizPos = this._storageManager.load('horizPos'); if (horizPos && this._scrollTable) { this._scrollTable.scrollLeft = horizPos; } - setLocalStorageParameter('horizPos', null); + this._storageManager.remove('horizPos'); } _removeListeners() { @@ -300,7 +303,7 @@ export class AsyncTable { } _changePagesizeHandler = () => { - const url = new URL(getLocalStorageParameter('currentTableUrl') || window.location.href); + const url = new URL(this._storageManager.load('currentTableUrl') || window.location.href); // create new FormData and format any date values const formData = Datepicker.unformatAll(this._pagesizeForm, new FormData(this._pagesizeForm)); @@ -336,7 +339,7 @@ export class AsyncTable { return false; } - setLocalStorageParameter('currentTableUrl', url.href); + this._storageManager.save('currentTableUrl', url.href); // reset table this._removeListeners(); this._element.classList.remove(ASYNC_TABLE_INITIALIZED_CLASS); @@ -346,9 +349,9 @@ export class AsyncTable { this._app.utilRegistry.setupAll(this._element); if (callback && typeof callback === 'function') { - setLocalStorageParameter('cssIdPrefix', response.idPrefix); + this._storageManager.save('cssIdPrefix', response.idPrefix, { location: LOCATION.WINDOW }); callback(this._element); - setLocalStorageParameter('cssIdPrefix', ''); + this._storageManager.remove('cssIdPrefix', { location: LOCATION.WINDOW }); } }).catch((err) => console.error(err) ).finally(() => this._element.classList.remove(ASYNC_TABLE_LOADING_CLASS)); @@ -365,17 +368,3 @@ function findCssIdPrefix(id) { } return ''; } - -function setLocalStorageParameter(key, value) { - const currentLSState = JSON.parse(window.localStorage.getItem(ASYNC_TABLE_LOCAL_STORAGE_KEY)) || {}; - if (value !== null) { - currentLSState[key] = value; - } else { - delete currentLSState[key]; - } - window.localStorage.setItem(ASYNC_TABLE_LOCAL_STORAGE_KEY, JSON.stringify(currentLSState)); -} -function getLocalStorageParameter(key) { - const currentLSState = JSON.parse(window.localStorage.getItem(ASYNC_TABLE_LOCAL_STORAGE_KEY)) || {}; - return currentLSState[key]; -} From 9eff3cfa10806f90d655fb32f72116e30020afab Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Dec 2019 17:32:41 +0100 Subject: [PATCH 33/46] fix(allocation-list): fix default sorting --- src/Handler/Allocation/List.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Handler/Allocation/List.hs b/src/Handler/Allocation/List.hs index 558d4c889..081734394 100644 --- a/src/Handler/Allocation/List.hs +++ b/src/Handler/Allocation/List.hs @@ -124,7 +124,7 @@ getAllocationListR = do psValidator :: PSValidator _ _ psValidator = def - & defaultSorting [SortDescBy "term", SortAscBy "school", SortAscBy "allocation"] + & defaultSorting [SortDescBy "term", SortAscBy "school-short", SortAscBy "allocation"] table <- runDB $ dbTableWidget' psValidator DBTable{..} From 4af776fff141c0961a5f0b59e042747193f2e3df Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Dec 2019 17:32:56 +0100 Subject: [PATCH 34/46] refactor(show-hide): migrate to StorageManager --- frontend/src/utils/show-hide/show-hide.js | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/frontend/src/utils/show-hide/show-hide.js b/frontend/src/utils/show-hide/show-hide.js index 0780a465d..c264f3af3 100644 --- a/frontend/src/utils/show-hide/show-hide.js +++ b/frontend/src/utils/show-hide/show-hide.js @@ -1,4 +1,5 @@ import { Utility } from '../../core/utility'; +import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager'; import './show-hide.scss'; const SHOW_HIDE_LOCAL_STORAGE_KEY = 'SHOW_HIDE'; @@ -15,6 +16,8 @@ export class ShowHide { _showHideId; _element; + _storageManager = new StorageManager(SHOW_HIDE_LOCAL_STORAGE_KEY, { location: LOCATION.LOCAL }); + constructor(element) { if (!element) { throw new Error('ShowHide utility cannot be setup without an element!'); @@ -41,9 +44,9 @@ export class ShowHide { } if (this._showHideId) { - let localStorageCollapsed = this._getLocalStorage()[this._showHideId]; - if (typeof localStorageCollapsed !== 'undefined') { - collapsed = localStorageCollapsed; + let storageCollapsed = this._storageManager.load(this._showHideId); + if (typeof storageCollapsed !== 'undefined') { + collapsed = storageCollapsed; } } this._element.parentElement.classList.toggle(SHOW_HIDE_COLLAPSED_CLASS, collapsed); @@ -70,18 +73,7 @@ export class ShowHide { const newState = this._element.parentElement.classList.toggle(SHOW_HIDE_COLLAPSED_CLASS); if (this._showHideId) { - this._setLocalStorage(this._showHideId, newState); + this._storageManager.save(this._showHideId, newState); } } - - // maybe move these to a LocalStorageHelper? - _setLocalStorage(id, state) { - const lsData = this._getLocalStorage(); - lsData[id] = state; - window.localStorage.setItem(SHOW_HIDE_LOCAL_STORAGE_KEY, JSON.stringify(lsData)); - } - - _getLocalStorage() { - return JSON.parse(window.localStorage.getItem(SHOW_HIDE_LOCAL_STORAGE_KEY)) || {}; - } } From e371412db48c600589800890477531706a6313bd Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 13 Dec 2019 15:04:52 +0100 Subject: [PATCH 35/46] 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', From cb75f4e4f1de5695aa8c8c8d2ac24c9d0f5134ad Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Mon, 16 Dec 2019 14:41:56 +0100 Subject: [PATCH 36/46] chore(frontend-tests): fix environment specifications --- frontend/src/app.spec.js | 32 +++++++++---------- .../lib/storage-manager/storage-manager.js | 32 ++++++++++++------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/frontend/src/app.spec.js b/frontend/src/app.spec.js index 247be9f00..e682f0e28 100644 --- a/frontend/src/app.spec.js +++ b/frontend/src/app.spec.js @@ -1,3 +1,5 @@ +/* eslint-env node */ + import { App } from './app'; import { Utility } from './core/utility'; @@ -13,52 +15,50 @@ const TEST_UTILS = [ ]; describe('App', () => { - let app; - beforeEach(() => { - app = new App(); + global.App = new App(); }); it('should create', () => { - expect(app).toBeTruthy(); + expect(global.App).toBeTruthy(); }); it('should setup all utlites when page is done loading', () => { - spyOn(app.utilRegistry, 'setupAll'); + spyOn(global.App.utilRegistry, 'setupAll'); document.dispatchEvent(new Event('DOMContentLoaded')); - expect(app.utilRegistry.setupAll).toHaveBeenCalled(); + expect(global.App.utilRegistry.setupAll).toHaveBeenCalled(); }); describe('provides services', () => { it('HttpClient as httpClient', () => { - expect(app.httpClient).toBeTruthy(); + expect(global.App.httpClient).toBeTruthy(); }); it('HtmlHelpers as htmlHelpers', () => { - expect(app.htmlHelpers).toBeTruthy(); + expect(global.App.htmlHelpers).toBeTruthy(); }); it('I18n as i18n', () => { - expect(app.i18n).toBeTruthy(); + expect(global.App.i18n).toBeTruthy(); }); it('UtilRegistry as utilRegistry', () => { - expect(app.utilRegistry).toBeTruthy(); + expect(global.App.utilRegistry).toBeTruthy(); }); }); describe('registerUtilities()', () => { it('should register the given utilities', () => { - spyOn(app.utilRegistry, 'register'); - app.registerUtilities(TEST_UTILS); - expect(app.utilRegistry.register.calls.count()).toBe(TEST_UTILS.length); - expect(app.utilRegistry.register.calls.argsFor(0)).toEqual([TEST_UTILS[0]]); - expect(app.utilRegistry.register.calls.argsFor(1)).toEqual([TEST_UTILS[1]]); + spyOn(global.App.utilRegistry, 'register'); + global.App.registerUtilities(TEST_UTILS); + expect(global.App.utilRegistry.register.calls.count()).toBe(TEST_UTILS.length); + expect(global.App.utilRegistry.register.calls.argsFor(0)).toEqual([TEST_UTILS[0]]); + expect(global.App.utilRegistry.register.calls.argsFor(1)).toEqual([TEST_UTILS[1]]); }); it('should throw an error if not passed an array of utilities', () => { expect(() => { - app.registerUtilities({}); + global.App.registerUtilities({}); }).toThrow(); }); }); diff --git a/frontend/src/lib/storage-manager/storage-manager.js b/frontend/src/lib/storage-manager/storage-manager.js index ec564c17a..9b6202329 100644 --- a/frontend/src/lib/storage-manager/storage-manager.js +++ b/frontend/src/lib/storage-manager/storage-manager.js @@ -1,3 +1,5 @@ +/* global global:writable */ + import * as semver from 'semver'; export const LOCATION = { @@ -12,6 +14,7 @@ export class StorageManager { namespace; version; _options; + _global; constructor(namespace, version, options) { this.namespace = namespace; @@ -27,6 +30,13 @@ export class StorageManager { if (options !== undefined) { this._options = options; } + + if (global !== undefined) + this._global = global; + else if (window !== undefined) + this._global = window; + else + throw new Error('Cannot setup StorageManager without window or global'); } save(key, value, options=this._options) { @@ -178,36 +188,36 @@ export class StorageManager { _getFromWindow() { - if (!window || !window.App) + if (!this._global || !this._global.App) return {}; - if (!window.App.Storage) - window.App.Storage = {}; + if (!this._global.App.Storage) + this._global.App.Storage = {}; - return window.App.Storage[this.namespace] || {}; + return this._global.App.Storage[this.namespace] || {}; } _saveToWindow(value) { - if (!window || !window.App) { + if (!this._global || !this._global.App) { throw new Error('StorageManager._saveToWindow called when window.App is not available'); } if (!value) return this._clearWindow(); - if (!window.App.Storage) - window.App.Storage = {}; + if (!this._global.App.Storage) + this._global.App.Storage = {}; - window.App.Storage[this.namespace] = value; + this._global.App.Storage[this.namespace] = value; } _clearWindow() { - if (!window || !window.App) { + if (!this._global || !this._global.App) { throw new Error('StorageManager._saveToWindow called when window.App is not available'); } - if (window.App.Storage) { - delete window.App.Storage[this.namespace]; + if (this._global.App.Storage) { + delete this._global.App.Storage[this.namespace]; } } } From 3077e51d70da4cd08783f2ed418f61a85293af62 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 17 Dec 2019 14:41:20 +0100 Subject: [PATCH 37/46] refactor(css): move all css to frontend/src --- frontend/src/_common.scss | 8 + frontend/src/app.scss | 1520 +++++++++++++++- frontend/src/utils/alerts/alerts.scss | 12 +- frontend/src/utils/modal/modal.scss | 6 +- frontend/src/utils/show-hide/show-hide.scss | 2 +- package-lock.json | 1543 ++++++++--------- package.json | 6 +- records.json | 509 ++++++ shell.nix | 4 +- templates/adminFeatures.cassius | 3 - templates/allocation/show.lucius | 104 -- templates/correction-user.cassius | 3 - templates/course.lucius | 42 - templates/course/applications-list.lucius | 4 - templates/csv-import-confirmation.lucius | 52 - templates/default-layout.lucius | 790 --------- templates/exam-show.cassius | 6 - templates/glossary.cassius | 14 - templates/table/colonnade.lucius | 40 - templates/table/course/colonnade.lucius | 45 - templates/table/csv-transcode.lucius | 8 - templates/table/layout-filter-default.lucius | 7 - templates/table/layout.lucius | 61 - templates/versionHistory.lucius | 11 - .../widgets/breadcrumbs/breadcrumbs.lucius | 62 - .../communication/recipientLayout.lucius | 65 - templates/widgets/csvRendered.lucius | 3 - .../delete-confirmation.lucius | 5 - templates/widgets/fields/funcField.hamlet | 2 +- templates/widgets/fields/funcField.lucius | 4 - templates/widgets/footer/footer.lucius | 24 - templates/widgets/gradingKey.cassius | 3 - templates/widgets/massinput/massinput.lucius | 8 - templates/widgets/multiFileField.lucius | 11 - .../widgets/pageaction/pageaction.lucius | 82 - .../widgets/permutation/permutation.lucius | 3 - webpack.config.js | 15 +- 37 files changed, 2795 insertions(+), 2292 deletions(-) create mode 100644 frontend/src/_common.scss create mode 100644 records.json delete mode 100644 templates/adminFeatures.cassius delete mode 100644 templates/allocation/show.lucius delete mode 100644 templates/correction-user.cassius delete mode 100644 templates/course.lucius delete mode 100644 templates/course/applications-list.lucius delete mode 100644 templates/csv-import-confirmation.lucius delete mode 100644 templates/default-layout.lucius delete mode 100644 templates/exam-show.cassius delete mode 100644 templates/glossary.cassius delete mode 100644 templates/table/colonnade.lucius delete mode 100644 templates/table/course/colonnade.lucius delete mode 100644 templates/table/csv-transcode.lucius delete mode 100644 templates/table/layout-filter-default.lucius delete mode 100644 templates/table/layout.lucius delete mode 100644 templates/versionHistory.lucius delete mode 100644 templates/widgets/breadcrumbs/breadcrumbs.lucius delete mode 100644 templates/widgets/communication/recipientLayout.lucius delete mode 100644 templates/widgets/csvRendered.lucius delete mode 100644 templates/widgets/delete-confirmation/delete-confirmation.lucius delete mode 100644 templates/widgets/fields/funcField.lucius delete mode 100644 templates/widgets/footer/footer.lucius delete mode 100644 templates/widgets/gradingKey.cassius delete mode 100644 templates/widgets/massinput/massinput.lucius delete mode 100644 templates/widgets/multiFileField.lucius delete mode 100644 templates/widgets/pageaction/pageaction.lucius delete mode 100644 templates/widgets/permutation/permutation.lucius diff --git a/frontend/src/_common.scss b/frontend/src/_common.scss new file mode 100644 index 000000000..d0652e036 --- /dev/null +++ b/frontend/src/_common.scss @@ -0,0 +1,8 @@ +@use "~@fortawesome/fontawesome-pro/scss/fontawesome" with ( + $fa-font-path: "~@fortawesome/fontawesome-pro/webfonts" +); +@forward "~@fortawesome/fontawesome-pro/scss/fontawesome"; +@use "~@fortawesome/fontawesome-pro/scss/solid"; + +@use "~typeface-roboto" as roboto; +@use "~typeface-source-sans-pro" as source-sans-pro; diff --git a/frontend/src/app.scss b/frontend/src/app.scss index 5eeb75ecb..fd0d6f93c 100644 --- a/frontend/src/app.scss +++ b/frontend/src/app.scss @@ -1,11 +1,1517 @@ -$fa-font-path: "~@fortawesome/fontawesome-pro/webfonts"; +@use "common" as *; -@import "@fortawesome/fontawesome-pro/scss/fontawesome.scss"; -@import "@fortawesome/fontawesome-pro/scss/solid.scss"; +:root { + /* THEME INDEPENDENT COLORS */ + --color-error: #8c0707; + --color-error-dark: #500303; + --color-warning: #fc9900; + --color-warning-dark: #c27400; + --color-success: #23d160; + --color-success-dark: #1ca64c; + --color-info: #c4c4c4; + --color-info-dark: #919191; + --color-lightblack: #1A2A36; + --color-lightwhite: #fcfffa; + --color-grey: #B1B5C0; + --color-grey-light: #efefef; + --color-grey-lighter: #f5f5f5; + --color-grey-medium: #9A989E; + --color-font: #34303a; + --color-fontsec: #5b5861; -$roboto: "Roboto"; -@import "~typeface-roboto/index.css"; + /* FONTS */ + --font-base: "Source Sans Pro", "Trebuchet MS", sans-serif; + --font-logo: "Roboto", var(--font-base); -$source-sans: "Source Sans Pro"; -@import "~typeface-source-sans-pro/index.css"; + /* DIMENSIONS */ + --header-height: 100px; + --header-height-collapsed: 60px; + + --asidenav-width-xl: 250px; + --asidenav-width-lg: 20%; + --asidenav-width-md: 60px; +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; + -webkit-font-smoothing: antialiased; +} + +body { + background-color: white; + color: var(--color-font); + font-family: var(--font-base); + font-weight: 400; + font-size: 16px; + overflow-y: scroll; +} + +/* THEMES */ + +body { + /* DEFAULT LMU THEME */ + --color-lmu-green: #0a9342; + --color-primary: var(--color-lmu-green); + --color-light: #31cc72; + --color-lighter: #35db7a; + --color-dark: #087536; + --color-darker: #075728; + --color-link: var(--color-font); + --color-link-hover: var(--color-font); + --color-lmu-box-border: var(--color-lightwhite); + + &.theme--lavender { + --color-primary: #584c9c; + --color-light: #5969b5; + --color-lighter: #5f7dc2; + --color-dark: #4c4279; + --color-darker: #3c2765; + --color-link: var(--color-dark); + --color-link-hover: var(--color-darker); + } + + &.theme--neutral-blue { + --color-primary: #3E606F; + --color-light: rgb(189, 201, 219); + --color-lighter: rgb(145, 159, 170); + --color-dark: rgb(42, 74, 88); + --color-darker: #193441; + } + + &.theme--aberdeen-reds { + --color-primary: #820333; + --color-light: #C9283E; + --color-lighter: #F0433A; + --color-dark: #540032; + --color-darker: #2E112D; + } + + &.theme--moss-green { + --color-primary: #5C996B; + --color-light: #7ACC8F; + --color-lighter: #99FFB2; + --color-dark: #3D6647; + --color-darker: #1F3324; + } + + &.theme--sky-love { + --color-primary: #87ABE5; + --color-light: #A0C6F2; + --color-lighter: #BAE2FF; + --color-dark: #7A95DE; + --color-darker: #6B7BC9; + --color-link: var(--color-lightblack); + --color-link-hover: var(--color-darker); + } +} + +/* END THEMES */ + +.emph { + font-style: italic; +} + +a, +a:visited { + text-decoration: none; + font-weight: 600; + transition: color .2s ease, background-color .2s ease; +} + +a { + color: var(--color-link); +} + +a:hover { + color: var(--color-link-hover); +} + + +ul { + margin-left: 20px; +} + +h1, h2, h3, .div-h3 , h4, h5 { + font-weight: 600; +} +h1 { + font-size: 32px; + margin-bottom: 10px; +} +h2 { + font-size: 24px; + margin: 10px 0; + + &:first-child { + margin-top: 0; + } +} +h3, .div-h3 { + font-size: 20px; + margin: 10px 0; + + &:first-child { + margin-top: 0; + } +} +h4 { + font-size: 16px; + margin: 0; +} + +@media (max-width: 768px) { + + h1 { + font-size: 24px; + } + + h2 { + font-size: 20px; + } + + h3, .div-h3 { + font-size: 16px; + } +} + +/* LAYOUT */ +.main { + position: relative; +} + +.main__content { + position: relative; + background-color: white; + transition: padding-left .2s ease-out; + margin-top: var(--header-height-collapsed); + margin-left: 0; + + > .container { + margin: 20px 0; + } +} + +.main__content, .modal__content { + a { + text-decoration: underline; + } + + p, form, .div-p { + margin: 0.5rem 0; + + &:last-child { + margin: 0.5rem 0 0; + + &:first-child { + margin: 0; + } + } + } +} + +@media (min-width: 426px) { + .main__content { + margin-left: var(--asidenav-width-md, 50px); + } +} + +@media (min-width: 769px) { + .main__content { + margin-left: var(--asidenav-width-lg, 20%); + margin-top: var(--header-height); + } +} + +@media (min-width: 1200px) { + .main__content { + margin-left: var(--asidenav-width-xl, 250px); + } +} + +.main__content-body { + padding: 13px; +} + +@media (min-width: 426px) { + .main__content-body { + padding: 13px 20px; + } +} + +@media (min-width: 769px) { + .main__content-body { + padding: 20px 40px; + } +} + +.pseudo-focus { + outline: 5px auto var(--color-light); + outline: 5px auto -webkit-focus-ring-color; +} + +/* CONTAINER */ +.container { + + + .container { + margin-top: 20px; + } +} + +/* GENERAL BUTTON STYLES */ +input[type="submit"], +input[type="button"], +button, +.btn { + outline: 0; + border: 0; + box-shadow: 0; + background-color: var(--color-dark); + color: white; + padding: 10px 17px; + min-width: 100px; + transition: all .1s; + font-size: 16px; + cursor: pointer; + display: inline-block; + text-decoration: none; + + a:hover { + color: white; + } + + &:focus { + border-color: #3273dc; + box-shadow: 0 0 0 0.25rem rgba(50,115,220,.25); + outline: 0; + } +} + +input[type="submit"][disabled], +input[type="button"][disabled], +button[disabled], +.btn[disabled] { + opacity: 0.3; + background-color: var(--color-grey); + cursor: default; +} + +input[type="submit"]:not([disabled]):hover, +input[type="button"]:not([disabled]):hover, +button:not([disabled]):hover, +.btn:not([disabled]):hover { + background-color: var(--color-light); + color: white; +} + +.btn-primary { + background-color: var(--color-primary); +} + +.btn-info { + background-color: var(--color-info) +} + +.btn--small { + padding: 4px 7px; + background-color: var(--color-darker); +} + +input[type="submit"].btn-info:hover, +input[type="button"].btn-info:hover, +.btn-info:hover { + background-color: var(--color-grey) +} + +/* GENERAL TABLE STYLES */ +.table { + margin: 21px 0; + width: 100%; +} + +.table:first-child { + margin-top: 0; +} + +.table:last-child { + margin-bottom: 0; +} + +.table--striped { + + .table__row:not(.no-stripe):not(.table__row--sum):nth-child(even) { + background-color: rgba(0, 0, 0, 0.03); + } +} + +.table--hover { + + .table__row:not(.no-hover):not(.table__row--sum):not(.table__row--head):not(.table__row--foot):hover { + background-color: rgba(0, 0, 0, 0.07); + } +} + +.table__row--sum td.table__td::before { + content: 'Σ'; + font-weight: bold; + margin-right: .25em; +} + +/* SCROLLTABLE */ +.scrolltable { + overflow: auto; +} + +.scrolltable--bordered { + box-shadow: 0 0 1px 1px var(--color-grey-light); +} + +@media (max-width: 425px) { + + .scrolltable { + margin-left: -10px; + padding-left: 10px; + margin-right: -10px; + padding-right: 10px; + } +} + +/* TABLE DESIGN */ +.table__td, .table__th { + padding-top: 14px; + padding-bottom: 10px; + padding-left: 10px; + padding-right: 10px; + max-width: 300px; +} + +.table__td { + font-size: 16px; + color: var(--color-font); + line-height: 1.4; + vertical-align: top; +} + +.table__td--automatic { + font-style: oblique; + color: var(--color-fontsec); +} + +.table__td--overriden { + font-weight: bold; +} + +.table__th { + background-color: var(--color-dark); + position: relative; + font-size: 16px; + color: white; + line-height: 1.4; + padding-top: 10px; + padding-bottom: 10px; + font-weight: bold; + text-align: left; + + a { + color: white; + text-decoration: none; + font-weight: bold; + + &:hover { + color: inherit; + } + + &::before { + @extend .fas; + content: fa-content($fa-var-link); + margin-right: 0.25em; + } + } +} + +@media (max-width: 1200px) { + + .table th { + padding: 4px 6px; + } +} + +.table__td-content { + max-height: 200px; + overflow-y: auto; +} + +.table__th-link { + font-weight: bold; + + &::before { + display: none; + } +} + +.table--vertical { + + th { + background-color: transparent; + color: var(--color-font); + width: 170px; + text-align: right; + padding-right: 15px; + font-weight: 400; + } + + td { + font-weight: 600; + color: var(--color-font); + } +} + +.table--condensed { + margin: 0; + + .table__th, + .table__td { + padding: 4px 8px; + } +} + +/* UNORDERED LIST */ +.list-ul__item { + // padding: 4px 0; + line-height: 25px; +} + +/* LIST MODIFIERS */ +.list--iconless { + list-style-type: none; + margin-left: 0; +} + +.list--inline { + ul { + display: inline-block; + margin-left: 0; + + li { + display: inline-block; + } + } +} + +ul.list--inline { + + display: inline-block; + margin-left: 0; + + li { + display: inline-block; + } +} + +.list--comma-separated li { + &::after { + content: ', '; + white-space: pre; + } + + &:last-of-type::after { + content: none; + } +} + +.list--space-separated li { + &::after { + content: ' '; + white-space: pre; + } + + &:last-of-type::after { + content: none; + } +} + +.list--icon-width li { + width: 1rem; + height: 1rem; +} + +/* DEFINITION LIST */ +.deflist { + display: grid; + grid-template-columns: 100%; +} +.deflist__dt, +.deflist__dd { + padding: 2px 0; +} + +.deflist__dt { + font-weight: 600; +} + +.deflist__dd { + font-size: 18px; + margin-bottom: 10px; + + > p, > .div-p { + margin-top: 0; + } +} + +@media (min-width: 768px) { + + .deflist { + grid-template-columns: fit-content(25vw) 1fr; + + .deflist { + margin-top: -10px; + margin-right: -15px; + + .deflist__dd { + padding-right: 15px; + } + } + } + + .deflist__dt, + .deflist__dd { + padding: 12px 0; + margin: 0; + font-size: 16px; + + &:last-of-type { + border: 0; + } + } + + .deflist__dt { + padding-right: 50px; + } + + .deflist__dd { + padding-right: 15px; + } +} + +section { + padding-bottom: 30px; + border-bottom: 1px solid #d3d3d3; + + + section { + margin-top: 20px; + } + + &:last-child { + border-bottom: none; + padding-bottom: 0px; + } +} + +.pseudonym { + font-family: monospace; +} + +.headline-one { + margin-bottom: 10px; +} + +/* Notification style used as requested by @hamanf in #298, but class was not globally available. Copied from dead-code. For @hamanf to clean up: */ + +.notification { + position: relative; + border-radius: 3px; + padding: 10px 20px 20px; + margin: 40px auto; + box-shadow: 0 0 4px 2px inset currentColor; + padding-left: 100px; + min-height: 100px; + max-width: 700px; + font-weight: 600; + vertical-align: center; + display: grid; + grid-column: 2; + + &::before { + @extend .fas; + position: absolute; + display: flex; + left: 0; + top: 0; + height: 100%; + width: 100px; + font-size: 50px; + align-items: center; + justify-content: center; + } + + .notification__content { + grid-column: 1; + align-self: center; + + color: var(--color-font); + } + + &.notification--broad { + max-width: none; + } +} + +.form-section-notification { + display: grid; + grid-template-columns: 1fr 3fr; + grid-gap: 5px; + + fieldset { + display: grid; + grid-template-columns: 1fr 3fr; + grid-gap: 5px; + grid-column: 1/3; + } + + .notification { + margin: 0; + } + + + .form-group, + .form-section-legend, + .form-section-notification { + margin-top: 11px; + } + + + .form-section-title { + margin-top: 40px; + } +} + +@media (max-width: 768px) { + .form-section-notification { + grid-template-columns: 1fr; + margin-top: 17px; + + fieldset { + grid-template-columns: 1fr; + grid-column: 1/2; + } + } + + .notification { + grid-column: 1; + + max-width: none; + + padding-left: 40px; + + &::before { + height: auto; + width: 45px; + font-size: 40px; + top: 15px; + } + } +} + +.notification-error { + color: var(--color-error) ; +} + +.notification-warning { + color: var(--color-warning) ; +} + +.notification-info { + color: var(--color-lightblack) ; +} + +.notification-success { + color: var(--color-warning) ; +} + + + + +/* + "Heated" element. + Set custom property "--hotness" to a value from 0 to 1 to turn + the element's background to a color on a gradient from green to red. + + TBD: + - move to a proper place + - think about font-weight... + + Example: +
Lorem ipsum +*/ + +.heated { + --hotness: 0; + --red: calc(var(--hotness) * 200); + --green: calc(255 - calc(var(--hotness) * 255)); + --opacity: calc(calc(var(--red) / 600) + 0.1); + + font-weight: var(--weight, 600); + background-color: rgba(var(--red), var(--green), 0, var(--opacity)); +} + + +.uuid { + font-family: monospace; +} + + +.form--inline { + display: inline-block; +} + + +.ribbon { + position: fixed; + top: calc(40px + var(--header-height)); + transition: all .2s cubic-bezier(0.03, 0.43, 0.58, 1); + right: -63px; + transform: rotate(45deg); + width: 250px; + background: var(--color-error); + text-align: center; + color: var(--color-lightwhite); + font-weight: 600; + font-size: 1.25rem; + line-height: 2em; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.4); + z-index: 19; + pointer-events: none; +} + +@media (max-width: 768px) { + .ribbon { + top: calc(20px + var(--header-height-collapsed)); + right: -83px; + transform: rotate(45deg) scale(0.6); + } +} + +#admin-studyterms { + select, option, input { + min-width: 50px; + } +} + +.allocation__label, .allocation__explanation { + color: var(--color-fontsec); + font-style: italic; +} + +.allocation__state { + color: var(--color-font); + font-weight: 600; + font-style: normal; +} + +.allocation__courses { + margin: 20px 0 0 40px; +} + +.allocation-course { + display: grid; + grid-template-columns: minmax(105px, 1fr) 9fr; + grid-template-areas: + 'name name ' + '. registered ' + 'prio-label prio ' + 'instr-label instr ' + 'form-label form '; + + grid-gap: 5px 7px; + margin: 12px 0; + padding: 0 10px 12px 7px; + + border-left: 1px solid var(--color-grey); + + /* &:last-child { + * padding: 12px 10px 0 10px; + * } + * + * & + .allocation-course { + * border-top: 1px solid var(--color-grey); + * } + */ + + &:nth-child(2n) { + background-color: rgba(0, 0, 0, 0.015); + } + + .allocation-course__registered { + grid-area: registered; + } + + .allocation-course__priority { + grid-area: prio; + } + .allocation-course__priority-label { + grid-area: prio-label; + justify-self: end; + align-self: center; + text-align: right; + } + + .allocation-course__name { + grid-area: name; + + align-self: center; + + font-size: 1.2rem; + } + + .allocation-course__instructions { + grid-area: instr; + } + .allocation-course__instructions-label { + grid-area: instr-label; + justify-self: end; + text-align: right; + } + + .allocation-course__application { + grid-area: form; + } + .allocation-course__application-label { + grid-area: form-label; + justify-self: end; + text-align: right; + padding-top: 6px; + } +} + +@media (max-width: 426px) { + .allocation-course { + grid-template-columns: 1fr; + grid-template-areas: + 'name ' + 'registered ' + 'prio-label ' + 'prio ' + 'instr-label' + 'instr ' + 'form-label ' + 'form '; + } + + .allocation-course__application-label { + padding-top: 0; + } +} + + +.comment { + white-space: pre-wrap; + font-family: monospace; +} + +th { + vertical-align: top; + text-align: left; +} + +th, td { + padding-bottom: 7px; +} + +.course-news { + max-height: 50vh; + overflow: auto; + + .course-news-item { + padding: 12px 0; + border-bottom: 1px solid #d3d3d3; + + &:last-child { + padding-bottom: 0; + border-bottom: none; + } + + &:first-child { + padding-top: 0; + } + + .course-news-item__last-edit { + color: var(--color-fontsec); + font-style: italic; + } + + .course-news-item__title .modal__trigger-label { + font-style: normal; + } + + .course-news-item__summary .modal__trigger-label { + font-weight: normal; + font-style: normal; + color: var(--color-font); + } + } +} + + +.bound_explanation { + color: var(--color-fontsec); + font-style: italic; +} + + +.action { + max-width: 800px; + padding: 3px 0; + + &:not(:last-child) { + margin-bottom: 7px; + } + + &:not(:first-child) { + margin-top: 7px; + } +} + +.action__options { + max-height: 450px; + overflow-y: auto; +} + +.action__option { + display: flex; + + &:not(:last-child) { + margin-bottom: 10px; + } +} + +.action__label, +.action__option-label { + margin-left: 15px; + vertical-align: top; +} + +.action__fieldset { + margin: 7px 0 5px 9px; + padding: 5px 0 10px; + border-left: 1px solid #bcbcbc; + padding-left: 16px; + position: relative; +} + +.action__toggle-all { + display: flex; + border-bottom: 1px solid #bcbcbc; + padding-bottom: 8px; + margin-bottom: 8px; +} + +.action__checked-counter { + position: absolute; + right: 5px; + top: 5px; +} + + +.occurrence--not-registered, .no-bonus { + text-decoration: line-through; +} + +.result { + font-size: 3rem; + margin: 30px 30px 0 !important; +} + + +.glossary { + dt, .dt { + font-weight: 600; + } + + &.sec { + font-style: italic; + font-size: 0.9rem; + font-weight: 600; + color: var(--color-fontsec); + } + dd, .dd { + margin-left: 12px; + } + + dd + dt, .dd + dt, dd + .dt, .dd + .dt { + margin-top: 17px; + } +} + + +/* SORTABLE TABLE-HEADERS*/ +.table__th.sortable { + position: relative; + padding-right: 24px; + cursor: pointer; +} + +.table__th.sortable::after, +.table__th.sortable::before { + content: ''; + position: absolute; + top: 50%; + right: 4px; + width: 0; + height: 0; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 8px solid rgba(255, 255, 255, 0.4); +} + +.table__th.sortable::before { + /* magic numbers to move arrow back in the right position after flipping it. + this allows us to use the same border for the up and the down arrow */ + transform: translateY(150%) scale(1, -1); + transform-origin: top; +} + +.table__th.sortable::after { + transform: translateY(-150%); +} + +.table__th.sortable:hover::before, +.table__th.sortable:hover::after { + border-bottom-color: rgba(255, 255, 255, 0.7); +} + +.table__th.sorted-asc::before, +.table__th.sorted-desc::after { + border-bottom-color: white !important; +} + + +:root { + --color-grey-light: #efefef; + --color-grey-lighter: #f5f5f5; + --color-fontsec: #5b5861; + --course-bg-color: var(--color-grey-lighter); + --course-expanded-bg-color: var(--color-grey-light); +} + +.scrolltable { + box-shadow: none!important; +} + +.course-header::after, +.course-header::before { + content: ''; + position: absolute; + right: 10px; + top: 20px; + width: 0; + height: 0; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 8px solid rgba(255, 255, 255, 0.4); +} + +.course-header::before { + /* magic numbers to move arrow back in the right position after flipping it. + this allows us to use the same border for the up and the down arrow */ + transform: translateY(150%) scale(1, -1); + transform-origin: top; +} + +.course-header::after { + transform: translateY(-150%); +} + +.course-header:hover::before, +.course-header:hover::after { + border-bottom-color: rgba(255, 255, 255, 0.7); +} + +.sorted-asc::before, +.sorted-desc::after { + border-bottom-color: white !important; +} + +.csv-export { + margin-bottom: 13px; + +} + +.csv-import { + margin-bottom: 13px; +} + + +.table-filter { + margin-bottom: 13px; +} + +.table-filter__toggle { + padding: 3px 7px; +} + + +/* TABLE HEADER */ +.table-header { + display: flex; + flex-flow: row-reverse; + justify-content: space-between; + margin-bottom: 15px; +} + +/* TABLE FOOTER */ +.table-footer { + display: flex; + flex-flow: row-reverse; + justify-content: space-between; + margin-top: 15px; +} + +/* PAGINATION */ +.pagination { + margin-top: 20px; + overflow: auto; + + .pages { + text-align: center; + white-space: nowrap; + margin: 0; + + .page-link { + margin-top: 7px; + display: inline-block; + background-color: var(--color-grey-medium); + + + .page-link { + margin-left: 7px; + } + + a { + color: var(--color-lightwhite); + padding: 7px 13px; + display: inline-block; + text-decoration: none; + } + + &:not(.current):hover { + background-color: var(--color-primary); + + a { + color: var(--color-lightwhite); + } + } + + &.current { + pointer-events: none; + background-color: var(--color-dark); + + a { + pointer-events: none; + } + } + } + } +} + + +#changelog { + font-size: 14px; + white-space: pre-wrap; + font-family: monospace; +} + +#gitrev { + font-size: 12px; + white-space: pre-wrap; + font-family: monospace; +} + + +.breadcrumbs__container { + position: relative; + color: var(--color-lightwhite); + padding: 4px 13px; + background-color: var(--color-dark); + line-height: 30px; +} + +@media (min-width: 426px) { + .breadcrumbs__container { + padding: 7px 20px; + } +} + +@media (min-width: 769px) { + .breadcrumbs__container { + padding: 7px 40px; + } +} + +.breadcrumbs__link { + color: var(--color-lightwhite); + + &:hover { + color: var(--color-white); + } +} + +.breadcrumbs__item { + padding-right: 14px; + position: relative; + line-height: 28px; + opacity: 0.8; + z-index: 1; + margin-right: 10px; + + &:hover { + opacity: 1; + } + + &::after { + content: ''; + position: absolute; + top: 11px; + right: 0; + width: 7px; + height: 7px; + border-style: solid; + border-width: 0; + border-bottom-width: 1px; + border-right-width: 1px; + border-color: var(--color-white); + transform: rotate(-45deg); + z-index: 10; + } +} + +.breadcrumbs__last-item { + line-height: 28px; + vertical-align: bottom; + font-weight: 600; +} + + +.recipient-category { + max-width: 400px; + padding: 3px 0; + + &:not(:last-child) { + margin-bottom: 7px; + } + + &:not(:first-child) { + margin-top: 7px; + } +} + +.recipient-category__options { + max-height: 150px; + overflow-y: auto; +} + +.recipient-category__option { + display: flex; + + &:not(:last-child) { + margin-bottom: 10px; + } +} + +.recipient-category__label, +.recipient-category__option-label { + margin-left: 15px; + vertical-align: top; +} + +.recipient-category__fieldset { + margin: 7px 0 5px 9px; + padding: 5px 0 10px; + border-left: 1px solid #bcbcbc; + padding-left: 16px; + position: relative; +} + +.recipient-category__option-add { + display: flex; + + .btn-mass-input-add { + margin-left: 10px; + padding: 10px 0; + } +} + +.recipient-category__options + .recipient-category__option-add { + margin-top: 10px; +} + +.recipient-category__toggle-all { + display: flex; + border-bottom: 1px solid #bcbcbc; + padding-bottom: 8px; + margin-bottom: 8px; +} + +.recipient-category__checked-counter { + position: absolute; + right: 5px; + top: 5px; +} + + +.table__td--csv, .table__th--csv { + font-family: monospace; +} + + +.confirmationText { + white-space: pre-wrap; + font-size: 14px; + font-family: monospace; +} + + +.func-field__wrapper { + max-height: 75vh; + overflow: auto; +} + + +.footer { + text-align: center; + padding: 20px; + position: relative; + margin: 40px 0; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 10%; + width: 80%; + height: 2px; + background-color: var(--color-grey-light); + } +} + +.footer-links * { + margin-right: 0.5em; + + &:last { + margin-right: 0; + } +} + + +.table--grading-key { + th, td { + padding: 3px; + } +} + +.btn.btn-mass-input-delete, +.btn.btn-mass-input-add { + background-color: #999; + min-width: 50px; + padding: 5px 15px; + font-weight: 700; + font-size: 1.3rem; +} + + +.file-input__unpack { + font-size: .9rem; + display: flex; + align-items: center; + margin-top: 10px; + + .checkbox { + display: inline-block; + margin-left: 7px; + } +} + + +.pagenav { + display: flex; + align-items: flex-start; + padding-bottom: 15px; + margin-bottom: 20px; + border-bottom: 1px solid #eee; +} + +.pagenav__list-item { + flex: 1; + position: relative; + display: inline-flex; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6); + margin: 10px 10px 0 0; +} + +.pagenav__link-wrapper { + flex: 1; + padding: 10px 10px 12px; + text-decoration: none !important; + + &:hover { + background-color: var(--color-grey-light); + } +} + +@media (max-width: 1024px) { + + .pagenav { + flex-direction: column; + } +} + +@media (min-width: 1025px) { + .pagenav-secondary { + position: relative; + overflow: visible; + padding-top: 10px; + + &::after { + content: '\2026'; + display: inline-block; + padding: 10px 10px 12px; + width: 40px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6); + box-sizing: border-box; + text-align: center; + transition: box-shadow 0.2s ease; + } + + &:hover { + &::after { + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.8); + } + + .pagenav-secondary__list { + display: block; + } + } + } + + .pagenav-secondary__list { + position: absolute; + display: none; + right: 0; + top: 50px; + width: 250px; + background-color: white; + box-shadow: 0 0 6px 3px var(--color-grey-light); + z-index: 18; + } + + .pagenav__list-item--secondary { + display: flex; + box-shadow: none; + margin: 0; + + &:hover { + background-color: var(--color-grey-light); + } + } +} + + +##{theId} { + list-style-type: none; +} diff --git a/frontend/src/utils/alerts/alerts.scss b/frontend/src/utils/alerts/alerts.scss index aa2f6acdc..ee800d40a 100644 --- a/frontend/src/utils/alerts/alerts.scss +++ b/frontend/src/utils/alerts/alerts.scss @@ -1,3 +1,5 @@ +@use "../../common" as *; + .alerts { position: fixed; bottom: 0; @@ -18,9 +20,9 @@ cursor: pointer; &::before { - content: '\f077'; + @extend .fas; + content: fa-content($fa-var-chevron-up); position: absolute; - font-family: 'Font Awesome 5 Free'; left: 50%; top: 0; height: 30px; @@ -132,9 +134,7 @@ z-index: 40; &::before { - /* content: var(--alert-icon, var(--alert-icon-default, '\f05a')); */ position: absolute; - /* font-family: 'Font Awesome 5 Free'; */ font-size: 24px; top: 50%; left: 50%; @@ -170,9 +170,9 @@ } &::before { - content: '\f00d'; + @extend .fas; + content: fa-content($fa-var-times); position: absolute; - font-family: 'Font Awesome 5 Free'; top: 50%; left: 50%; display: flex; diff --git a/frontend/src/utils/modal/modal.scss b/frontend/src/utils/modal/modal.scss index e9cd70494..446863f03 100644 --- a/frontend/src/utils/modal/modal.scss +++ b/frontend/src/utils/modal/modal.scss @@ -1,3 +1,5 @@ +@use "../../common" as *; + .modals-wrapper { position: fixed; left: 0; @@ -106,8 +108,8 @@ div.modal__trigger { z-index: 20; &::before { - content: '\f00d'; - font-family: 'Font Awesome 5 Free'; + @extend .fas; + content: fa-content($fa-var-times); color: white; } } diff --git a/frontend/src/utils/show-hide/show-hide.scss b/frontend/src/utils/show-hide/show-hide.scss index 04143d0ae..f557248fb 100644 --- a/frontend/src/utils/show-hide/show-hide.scss +++ b/frontend/src/utils/show-hide/show-hide.scss @@ -43,7 +43,7 @@ $show-hide-toggle-size: 6px; transform: translateY(-50%) rotate(135deg); } - :not(.show-hide__toggle) { + & > :not(.show-hide__toggle) { display: block; height: 0; margin: 0; diff --git a/package-lock.json b/package-lock.json index a1bd61eda..00d481b46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2555,6 +2555,12 @@ } } }, + "@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", + "dev": true + }, "@fortawesome/fontawesome-pro": { "version": "5.12.0", "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-pro/-/5.12.0/fontawesome-pro-5.12.0.tgz", @@ -2901,12 +2907,6 @@ "through": ">=2.2.7 <3" } }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -2929,6 +2929,51 @@ "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, + "adjust-sourcemap-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz", + "integrity": "sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA==", + "dev": true, + "requires": { + "assert": "1.4.1", + "camelcase": "5.0.0", + "loader-utils": "1.2.3", + "object-path": "0.11.4", + "regex-parser": "2.2.10" + }, + "dependencies": { + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -2977,12 +3022,6 @@ "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", @@ -3043,16 +3082,6 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -3062,6 +3091,12 @@ "sprintf-js": "~1.0.2" } }, + "arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", + "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=", + "dev": true + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -3143,15 +3178,6 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -3190,12 +3216,6 @@ } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -3223,24 +3243,12 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true - }, "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -3296,18 +3304,6 @@ } } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", - "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", - "dev": true - }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -4153,15 +4149,6 @@ "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "better-assert": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", @@ -4189,15 +4176,6 @@ "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", "dev": true }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, "bluebird": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", @@ -4574,12 +4552,6 @@ "integrity": "sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4787,49 +4759,6 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - } - } - }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -4878,15 +4807,6 @@ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", @@ -4927,6 +4847,15 @@ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", "dev": true }, + "compose-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", + "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", + "dev": true, + "requires": { + "arity-n": "^1.0.4" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4963,12 +4892,6 @@ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", "dev": true }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -6331,6 +6254,64 @@ "randomfill": "^1.0.3" } }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, "css-loader": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", @@ -6350,6 +6331,21 @@ "schema-utils": "^1.0.0" } }, + "css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==", + "dev": true + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -6395,15 +6391,6 @@ "number-is-nan": "^1.0.0" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "date-fns": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", @@ -6537,18 +6524,6 @@ } } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -6687,16 +6662,6 @@ "stream-shift": "^1.0.0" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -7295,12 +7260,6 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -7470,6 +7429,12 @@ "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -7518,23 +7483,6 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -8155,18 +8103,6 @@ } } }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -8190,59 +8126,6 @@ "simple-git": "^1.85.0" } }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, "get-own-enumerable-property-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", @@ -8283,15 +8166,6 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "git-raw-commits": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-1.3.6.tgz", @@ -8788,17 +8662,6 @@ } } }, - "globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } - }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", @@ -8825,22 +8688,6 @@ } } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -8894,12 +8741,6 @@ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -9012,17 +8853,6 @@ "requires-port": "^1.0.0" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -9194,12 +9024,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", - "dev": true - }, "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", @@ -9299,12 +9123,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -9567,12 +9385,6 @@ "text-extensions": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -9618,12 +9430,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "jasmine-core": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz", @@ -9651,12 +9457,6 @@ } } }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", - "dev": true - }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -9679,12 +9479,6 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -9697,12 +9491,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -9759,18 +9547,6 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "karma": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/karma/-/karma-4.4.1.tgz", @@ -9994,15 +9770,6 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -10772,7 +10539,8 @@ "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -10823,34 +10591,6 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -10907,83 +10647,6 @@ } } }, - "node-sass": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.0.tgz", - "integrity": "sha512-W1XBrvoJ1dy7VsvTAS5q1V45lREbTlZQqFbiHb3R3OTTCma0XBtuG6xZ6Z4506nR4lmHPTqVRwxT6KgtWC97CA==", - "dev": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "^2.2.4", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -11029,9 +10692,9 @@ } }, "npm": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.3.tgz", - "integrity": "sha512-j1miGFbOTg03eKeBBevFgDtb2EeUc99uxsEMEDmUmwDV2o9FVpXzdRgMhinpAFusY8TSZQuQHpYpTIwKvHijdQ==", + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.4.tgz", + "integrity": "sha512-vTcUL4SCg3AzwInWTbqg1OIaOXlzKSS8Mb8kc5avwrJpcvevDA5J9BhYSuei+fNs3pwOp4lzA5x2FVDXACvoXA==", "requires": { "JSONStream": "^1.3.5", "abbrev": "~1.1.1", @@ -11039,7 +10702,7 @@ "ansistyles": "~0.1.3", "aproba": "^2.0.0", "archy": "~1.0.0", - "bin-links": "^1.1.5", + "bin-links": "^1.1.6", "bluebird": "^3.5.5", "byte-size": "^5.0.1", "cacache": "^12.0.3", @@ -11060,7 +10723,7 @@ "find-npm-prefix": "^1.0.2", "fs-vacuum": "~1.2.10", "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.2.1", + "gentle-fs": "^2.3.0", "glob": "^7.1.4", "graceful-fs": "^4.2.3", "has-unicode": "~2.0.1", @@ -11298,12 +10961,12 @@ } }, "bin-links": { - "version": "1.1.5", + "version": "1.1.6", "bundled": true, "requires": { "bluebird": "^3.5.3", "cmd-shim": "^3.0.0", - "gentle-fs": "^2.0.1", + "gentle-fs": "^2.3.0", "graceful-fs": "^4.1.15", "npm-normalize-package-bin": "^1.0.0", "write-file-atomic": "^2.3.0" @@ -12054,11 +11717,12 @@ "bundled": true }, "gentle-fs": { - "version": "2.2.1", + "version": "2.3.0", "bundled": true, "requires": { "aproba": "^1.1.2", "chownr": "^1.1.2", + "cmd-shim": "^3.0.3", "fs-vacuum": "^1.2.10", "graceful-fs": "^4.1.11", "iferr": "^0.1.5", @@ -14180,18 +13844,6 @@ "which": "^1.2.10" } }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, "null-check": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", @@ -14220,12 +13872,6 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -14275,6 +13921,12 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -14388,31 +14040,12 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "outdent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.7.0.tgz", @@ -14633,12 +14266,6 @@ "sha.js": "^2.4.8" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, "picomatch": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", @@ -14724,30 +14351,301 @@ } } }, - "postcss-load-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", - "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "postcss-attribute-case-insensitive": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz", + "integrity": "sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A==", "dev": true, "requires": { - "cosmiconfig": "^4.0.0", - "import-cwd": "^2.0.0" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0" }, "dependencies": { - "cosmiconfig": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", - "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0", - "require-from-string": "^2.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } }, + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "dev": true, + "requires": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "dev": true, + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + }, + "dependencies": { + "postcss": { + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.25.tgz", + "integrity": "sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "dev": true, + "requires": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-font-variant": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz", + "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-initial": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", + "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", + "dev": true, + "requires": { + "lodash.template": "^4.5.0", + "postcss": "^7.0.2" + }, + "dependencies": { + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + } + } + }, + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", + "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, "postcss-loader": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", @@ -14760,6 +14658,24 @@ "schema-utils": "^1.0.0" } }, + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, "postcss-modules-extract-imports": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", @@ -14800,6 +14716,174 @@ "postcss": "^7.0.6" } }, + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "dev": true, + "requires": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.25.tgz", + "integrity": "sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "postcss-selector-not": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz", + "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, "postcss-selector-parser": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", @@ -14817,6 +14901,17 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -14877,12 +14972,6 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, - "psl": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", - "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==", - "dev": true - }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -15174,6 +15263,12 @@ "safe-regex": "^1.1.0" } }, + "regex-parser": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.10.tgz", + "integrity": "sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==", + "dev": true + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -15244,60 +15339,12 @@ "is-finite": "^1.0.0" } }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -15374,6 +15421,61 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "resolve-url-loader": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz", + "integrity": "sha512-K1N5xUjj7v0l2j/3Sgs5b8CjrrgtC70SmdCuZiJ8tSyb5J+uk3FoeZ4b7yTnH6j7ngI+Bc5bldHJIa8hYdu2gQ==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "2.0.0", + "camelcase": "5.3.1", + "compose-function": "3.0.3", + "convert-source-map": "1.7.0", + "es6-iterator": "2.0.3", + "loader-utils": "1.2.3", + "postcss": "7.0.21", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "postcss": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -15390,6 +15492,30 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "requires": { + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + } + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, "rfdc": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", @@ -15469,16 +15595,13 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "sass": { + "version": "1.23.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.23.7.tgz", + "integrity": "sha512-cYgc0fanwIpi0rXisGxl+/wadVQ/HX3RhpdRcjLdj2o2ye/sxUTpAxIhbmJy3PLQgRFbf6Pn8Jsrta2vdXcoOQ==", "dev": true, "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" + "chokidar": ">=2.0.0 <4.0.0" } }, "sass-loader": { @@ -15513,27 +15636,6 @@ "ajv-keywords": "^3.1.0" } }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -16007,23 +16109,6 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -16303,15 +16388,6 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -16585,17 +16661,6 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, "terser": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz", @@ -16880,24 +16945,6 @@ "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", "dev": true }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -16916,15 +16963,6 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - } - }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -16937,21 +16975,6 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -17241,17 +17264,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -17663,21 +17675,6 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -17758,84 +17755,12 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index 3361f6443..58d79f396 100644 --- a/package.json +++ b/package.json @@ -85,10 +85,12 @@ "lint-staged": "^8.2.1", "lodash.debounce": "^4.0.8", "mini-css-extract-plugin": "^0.8.0", - "node-sass": "^4.13.0", "npm-run-all": "^4.1.5", "null-loader": "^2.0.0", "postcss-loader": "^3.0.0", + "postcss-preset-env": "^6.7.0", + "resolve-url-loader": "^3.1.1", + "sass": "^1.23.7", "sass-loader": "^7.3.1", "semver": "^6.3.0", "standard-version": "^6.0.1", @@ -106,7 +108,7 @@ "@juggle/resize-observer": "^2.5.0", "core-js": "^3.4.8", "moment": "^2.24.0", - "npm": "^6.13.3", + "npm": "^6.13.4", "tail.datetime": "git+https://github.com/uni2work/tail.DateTime.git#master", "whatwg-fetch": "^3.0.0" } diff --git a/records.json b/records.json new file mode 100644 index 000000000..70313cfe0 --- /dev/null +++ b/records.json @@ -0,0 +1,509 @@ +{ + "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": [] + } + } + ], + "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/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/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-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/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/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/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/hide-columns/hide-columns.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--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/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/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/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--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": [] + } + } + ], + "modules": { + "byIdentifier": { + "multi frontend/src/polyfill.js frontend/src/main.js": 0 + }, + "usedIds": { + "0": 0 + } + }, + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/app.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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/hide-columns/hide-columns.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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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--6-1!node_modules/postcss-loader/src/index.js??ref--6-2!node_modules/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!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--5-1!node_modules/postcss-loader/src/index.js??ref--5-2!node_modules/resolve-url-loader/index.js??ref--5-3!frontend/src/utils/form/datepicker.css": [ + { + "modules": { + "byIdentifier": {}, + "usedIds": {} + }, + "chunks": { + "byName": {}, + "bySource": {}, + "usedIds": [] + } + } + ] +} \ No newline at end of file diff --git a/shell.nix b/shell.nix index 1a285b264..ce4fd9035 100644 --- a/shell.nix +++ b/shell.nix @@ -19,10 +19,12 @@ let ''; override = oldAttrs: { - nativeBuildInputs = oldAttrs.nativeBuildInputs ++ (with pkgs; [ nodejs-12_x postgresql openldap ]) ++ (with haskellPackages; [ stack yesod-bin hlint cabal-install ]); + nativeBuildInputs = oldAttrs.nativeBuildInputs ++ (with pkgs; [ nodejs-12_x postgresql openldap google-chrome ]) ++ (with haskellPackages; [ stack yesod-bin hlint cabal-install ]); shellHook = '' export PROMPT_INFO="${oldAttrs.name}" + export CHROME_BIN=$(which google-chrome-stable) + if [[ -z "$PGHOST" ]]; then set -xe diff --git a/templates/adminFeatures.cassius b/templates/adminFeatures.cassius deleted file mode 100644 index cc48016f1..000000000 --- a/templates/adminFeatures.cassius +++ /dev/null @@ -1,3 +0,0 @@ -#admin-studyterms - select, option, input - min-width: 50px \ No newline at end of file diff --git a/templates/allocation/show.lucius b/templates/allocation/show.lucius deleted file mode 100644 index 5302b59a4..000000000 --- a/templates/allocation/show.lucius +++ /dev/null @@ -1,104 +0,0 @@ -.allocation__label, .allocation__explanation { - color: var(--color-fontsec); - font-style: italic; -} - -.allocation__state { - color: var(--color-font); - font-weight: 600; - font-style: normal; -} - -.allocation__courses { - margin: 20px 0 0 40px; -} - -.allocation-course { - display: grid; - grid-template-columns: minmax(105px, 1fr) 9fr; - grid-template-areas: - 'name name ' - '. registered ' - 'prio-label prio ' - 'instr-label instr ' - 'form-label form '; - - grid-gap: 5px 7px; - margin: 12px 0; - padding: 0 10px 12px 7px; - - border-left: 1px solid var(--color-grey); - - /* &:last-child { - * padding: 12px 10px 0 10px; - * } - * - * & + .allocation-course { - * border-top: 1px solid var(--color-grey); - * } - */ - - &:nth-child(2n) { - background-color: rgba(0, 0, 0, 0.015); - } - - .allocation-course__registered { - grid-area: registered; - } - - .allocation-course__priority { - grid-area: prio; - } - .allocation-course__priority-label { - grid-area: prio-label; - justify-self: end; - align-self: center; - text-align: right; - } - - .allocation-course__name { - grid-area: name; - - align-self: center; - - font-size: 1.2rem; - } - - .allocation-course__instructions { - grid-area: instr; - } - .allocation-course__instructions-label { - grid-area: instr-label; - justify-self: end; - text-align: right; - } - - .allocation-course__application { - grid-area: form; - } - .allocation-course__application-label { - grid-area: form-label; - justify-self: end; - text-align: right; - padding-top: 6px; - } -} - -@media (max-width: 426px) { - .allocation-course { - grid-template-columns: 1fr; - grid-template-areas: - 'name ' - 'registered ' - 'prio-label ' - 'prio ' - 'instr-label' - 'instr ' - 'form-label ' - 'form '; - } - - .allocation-course__application-label { - padding-top: 0; - } -} diff --git a/templates/correction-user.cassius b/templates/correction-user.cassius deleted file mode 100644 index 2b7b13b7a..000000000 --- a/templates/correction-user.cassius +++ /dev/null @@ -1,3 +0,0 @@ -.comment - white-space: pre-wrap - font-family: monospace \ No newline at end of file diff --git a/templates/course.lucius b/templates/course.lucius deleted file mode 100644 index c28d8cf60..000000000 --- a/templates/course.lucius +++ /dev/null @@ -1,42 +0,0 @@ -th { - vertical-align: top; - text-align: left; -} - -th, td { - padding-bottom: 7px; -} - -.course-news { - max-height: 50vh; - overflow: auto; - - .course-news-item { - padding: 12px 0; - border-bottom: 1px solid #d3d3d3; - - &:last-child { - padding-bottom: 0; - border-bottom: none; - } - - &:first-child { - padding-top: 0; - } - - .course-news-item__last-edit { - color: var(--color-fontsec); - font-style: italic; - } - - .course-news-item__title .modal__trigger-label { - font-style: normal; - } - - .course-news-item__summary .modal__trigger-label { - font-weight: normal; - font-style: normal; - color: var(--color-font); - } - } -} diff --git a/templates/course/applications-list.lucius b/templates/course/applications-list.lucius deleted file mode 100644 index 55579838c..000000000 --- a/templates/course/applications-list.lucius +++ /dev/null @@ -1,4 +0,0 @@ -.bound_explanation { - color: var(--color-fontsec); - font-style: italic; -} diff --git a/templates/csv-import-confirmation.lucius b/templates/csv-import-confirmation.lucius deleted file mode 100644 index 2569e0836..000000000 --- a/templates/csv-import-confirmation.lucius +++ /dev/null @@ -1,52 +0,0 @@ -.action { - max-width: 800px; - padding: 3px 0; - - &:not(:last-child) { - margin-bottom: 7px; - } - - &:not(:first-child) { - margin-top: 7px; - } -} - -.action__options { - max-height: 450px; - overflow-y: auto; -} - -.action__option { - display: flex; - - &:not(:last-child) { - margin-bottom: 10px; - } -} - -.action__label, -.action__option-label { - margin-left: 15px; - vertical-align: top; -} - -.action__fieldset { - margin: 7px 0 5px 9px; - padding: 5px 0 10px; - border-left: 1px solid #bcbcbc; - padding-left: 16px; - position: relative; -} - -.action__toggle-all { - display: flex; - border-bottom: 1px solid #bcbcbc; - padding-bottom: 8px; - margin-bottom: 8px; -} - -.action__checked-counter { - position: absolute; - right: 5px; - top: 5px; -} diff --git a/templates/default-layout.lucius b/templates/default-layout.lucius deleted file mode 100644 index 0f09cb225..000000000 --- a/templates/default-layout.lucius +++ /dev/null @@ -1,790 +0,0 @@ -:root { - /* THEME INDEPENDENT COLORS */ - --color-error: #8c0707; - --color-error-dark: #500303; - --color-warning: #fc9900; - --color-warning-dark: #c27400; - --color-success: #23d160; - --color-success-dark: #1ca64c; - --color-info: #c4c4c4; - --color-info-dark: #919191; - --color-lightblack: #1A2A36; - --color-lightwhite: #fcfffa; - --color-grey: #B1B5C0; - --color-grey-light: #efefef; - --color-grey-lighter: #f5f5f5; - --color-grey-medium: #9A989E; - --color-font: #34303a; - --color-fontsec: #5b5861; - - - /* FONTS */ - --font-base: "Source Sans Pro", "Trebuchet MS", sans-serif; - --font-logo: "Roboto", var(--font-base); - - /* DIMENSIONS */ - --header-height: 100px; - --header-height-collapsed: 60px; - - --asidenav-width-xl: 250px; - --asidenav-width-lg: 20%; - --asidenav-width-md: 60px; -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; - -webkit-font-smoothing: antialiased; -} - -body { - background-color: white; - color: var(--color-font); - font-family: var(--font-base); - font-weight: 400; - font-size: 16px; - overflow-y: scroll; -} - -/* THEMES */ - -body { - /* DEFAULT LMU THEME */ - --color-lmu-green: #0a9342; - --color-primary: var(--color-lmu-green); - --color-light: #31cc72; - --color-lighter: #35db7a; - --color-dark: #087536; - --color-darker: #075728; - --color-link: var(--color-font); - --color-link-hover: var(--color-font); - --color-lmu-box-border: var(--color-lightwhite); - - &.theme--lavender { - --color-primary: #584c9c; - --color-light: #5969b5; - --color-lighter: #5f7dc2; - --color-dark: #4c4279; - --color-darker: #3c2765; - --color-link: var(--color-dark); - --color-link-hover: var(--color-darker); - } - - &.theme--neutral-blue { - --color-primary: #3E606F; - --color-light: rgb(189, 201, 219); - --color-lighter: rgb(145, 159, 170); - --color-dark: rgb(42, 74, 88); - --color-darker: #193441; - } - - &.theme--aberdeen-reds { - --color-primary: #820333; - --color-light: #C9283E; - --color-lighter: #F0433A; - --color-dark: #540032; - --color-darker: #2E112D; - } - - &.theme--moss-green { - --color-primary: #5C996B; - --color-light: #7ACC8F; - --color-lighter: #99FFB2; - --color-dark: #3D6647; - --color-darker: #1F3324; - } - - &.theme--sky-love { - --color-primary: #87ABE5; - --color-light: #A0C6F2; - --color-lighter: #BAE2FF; - --color-dark: #7A95DE; - --color-darker: #6B7BC9; - --color-link: var(--color-lightblack); - --color-link-hover: var(--color-darker); - } -} - -/* END THEMES */ - -.emph { - font-style: italic; -} - -a, -a:visited { - text-decoration: none; - font-weight: 600; - transition: color .2s ease, background-color .2s ease; -} - -a { - color: var(--color-link); -} - -a:hover { - color: var(--color-link-hover); -} - - -ul { - margin-left: 20px; -} - -h1, h2, h3, .div-h3 , h4, h5 { - font-weight: 600; -} -h1 { - font-size: 32px; - margin-bottom: 10px; -} -h2 { - font-size: 24px; - margin: 10px 0; - - &:first-child { - margin-top: 0; - } -} -h3, .div-h3 { - font-size: 20px; - margin: 10px 0; - - &:first-child { - margin-top: 0; - } -} -h4 { - font-size: 16px; - margin: 0; -} - -@media (max-width: 768px) { - - h1 { - font-size: 24px; - } - - h2 { - font-size: 20px; - } - - h3, .div-h3 { - font-size: 16px; - } -} - -/* LAYOUT */ -.main { - position: relative; -} - -.main__content { - position: relative; - background-color: white; - transition: padding-left .2s ease-out; - margin-top: var(--header-height-collapsed); - margin-left: 0; - - > .container { - margin: 20px 0; - } -} - -.main__content, .modal__content { - a { - text-decoration: underline; - } - - p, form, .div-p { - margin: 0.5rem 0; - - &:last-child { - margin: 0.5rem 0 0; - - &:first-child { - margin: 0; - } - } - } -} - -@media (min-width: 426px) { - .main__content { - margin-left: var(--asidenav-width-md, 50px); - } -} - -@media (min-width: 769px) { - .main__content { - margin-left: var(--asidenav-width-lg, 20%); - margin-top: var(--header-height); - } -} - -@media (min-width: 1200px) { - .main__content { - margin-left: var(--asidenav-width-xl, 250px); - } -} - -.main__content-body { - padding: 13px; -} - -@media (min-width: 426px) { - .main__content-body { - padding: 13px 20px; - } -} - -@media (min-width: 769px) { - .main__content-body { - padding: 20px 40px; - } -} - -.pseudo-focus { - outline: 5px auto var(--color-light); - outline: 5px auto -webkit-focus-ring-color; -} - -/* CONTAINER */ -.container { - - + .container { - margin-top: 20px; - } -} - -/* GENERAL BUTTON STYLES */ -input[type="submit"], -input[type="button"], -button, -.btn { - outline: 0; - border: 0; - box-shadow: 0; - background-color: var(--color-dark); - color: white; - padding: 10px 17px; - min-width: 100px; - transition: all .1s; - font-size: 16px; - cursor: pointer; - display: inline-block; - text-decoration: none; - - a:hover { - color: white; - } - - &:focus { - border-color: #3273dc; - box-shadow: 0 0 0 0.25rem rgba(50,115,220,.25); - outline: 0; - } -} - -input[type="submit"][disabled], -input[type="button"][disabled], -button[disabled], -.btn[disabled] { - opacity: 0.3; - background-color: var(--color-grey); - cursor: default; -} - -input[type="submit"]:not([disabled]):hover, -input[type="button"]:not([disabled]):hover, -button:not([disabled]):hover, -.btn:not([disabled]):hover { - background-color: var(--color-light); - color: white; -} - -.btn-primary { - background-color: var(--color-primary); -} - -.btn-info { - background-color: var(--color-info) -} - -.btn--small { - padding: 4px 7px; - background-color: var(--color-darker); -} - -input[type="submit"].btn-info:hover, -input[type="button"].btn-info:hover, -.btn-info:hover { - background-color: var(--color-grey) -} - -/* GENERAL TABLE STYLES */ -.table { - margin: 21px 0; - width: 100%; -} - -.table:first-child { - margin-top: 0; -} - -.table:last-child { - margin-bottom: 0; -} - -.table--striped { - - .table__row:not(.no-stripe):not(.table__row--sum):nth-child(even) { - background-color: rgba(0, 0, 0, 0.03); - } -} - -.table--hover { - - .table__row:not(.no-hover):not(.table__row--sum):not(.table__row--head):not(.table__row--foot):hover { - background-color: rgba(0, 0, 0, 0.07); - } -} - -.table__row--sum td.table__td::before { - content: 'Σ'; - font-weight: bold; - margin-right: .25em; -} - -/* SCROLLTABLE */ -.scrolltable { - overflow: auto; -} - -.scrolltable--bordered { - box-shadow: 0 0 1px 1px var(--color-grey-light); -} - -@media (max-width: 425px) { - - .scrolltable { - margin-left: -10px; - padding-left: 10px; - margin-right: -10px; - padding-right: 10px; - } -} - -/* TABLE DESIGN */ -.table__td, .table__th { - padding-top: 14px; - padding-bottom: 10px; - padding-left: 10px; - padding-right: 10px; - max-width: 300px; -} - -.table__td { - font-size: 16px; - color: var(--color-font); - line-height: 1.4; - vertical-align: top; -} - -.table__td--automatic { - font-style: oblique; - color: var(--color-fontsec); -} - -.table__td--overriden { - font-weight: bold; -} - -.table__th { - background-color: var(--color-dark); - position: relative; - font-size: 16px; - color: white; - line-height: 1.4; - padding-top: 10px; - padding-bottom: 10px; - font-weight: bold; - text-align: left; - - a { - color: white; - text-decoration: none; - font-weight: bold; - - &:hover { - color: inherit; - } - - &::before { - content: "\f0c1"; - font-family: "Font Awesome 5 Free"; - font-weight: 900; - margin-right: 0.25em; - } - } -} - -@media (max-width: 1200px) { - - .table th { - padding: 4px 6px; - } -} - -.table__td-content { - max-height: 200px; - overflow-y: auto; -} - -.table__th-link { - font-weight: bold; - - &::before { - display: none; - } -} - -.table--vertical { - - th { - background-color: transparent; - color: var(--color-font); - width: 170px; - text-align: right; - padding-right: 15px; - font-weight: 400; - } - - td { - font-weight: 600; - color: var(--color-font); - } -} - -.table--condensed { - margin: 0; - - .table__th, - .table__td { - padding: 4px 8px; - } -} - -/* UNORDERED LIST */ -.list-ul__item { - // padding: 4px 0; - line-height: 25px; -} - -/* LIST MODIFIERS */ -.list--iconless { - list-style-type: none; - margin-left: 0; -} - -.list--inline { - ul { - display: inline-block; - margin-left: 0; - - li { - display: inline-block; - } - } -} - -ul.list--inline { - - display: inline-block; - margin-left: 0; - - li { - display: inline-block; - } -} - -.list--comma-separated li { - &::after { - content: ', '; - white-space: pre; - } - - &:last-of-type::after { - content: none; - } -} - -.list--space-separated li { - &::after { - content: ' '; - white-space: pre; - } - - &:last-of-type::after { - content: none; - } -} - -.list--icon-width li { - width: 1rem; - height: 1rem; -} - -/* DEFINITION LIST */ -.deflist { - display: grid; - grid-template-columns: 100%; -} -.deflist__dt, -.deflist__dd { - padding: 2px 0; -} - -.deflist__dt { - font-weight: 600; -} - -.deflist__dd { - font-size: 18px; - margin-bottom: 10px; - - > p, > .div-p { - margin-top: 0; - } -} - -@media (min-width: 768px) { - - .deflist { - grid-template-columns: fit-content(25vw) 1fr; - - .deflist { - margin-top: -10px; - margin-right: -15px; - - .deflist__dd { - padding-right: 15px; - } - } - } - - .deflist__dt, - .deflist__dd { - padding: 12px 0; - margin: 0; - font-size: 16px; - - &:last-of-type { - border: 0; - } - } - - .deflist__dt { - padding-right: 50px; - } - - .deflist__dd { - padding-right: 15px; - } -} - -section { - padding-bottom: 30px; - border-bottom: 1px solid #d3d3d3; - - + section { - margin-top: 20px; - } - - &:last-child { - border-bottom: none; - padding-bottom: 0px; - } -} - -.pseudonym { - font-family: monospace; -} - -.headline-one { - margin-bottom: 10px; -} - -/* Notification style used as requested by @hamanf in #298, but class was not globally available. Copied from dead-code. For @hamanf to clean up: */ - -.notification { - position: relative; - border-radius: 3px; - padding: 10px 20px 20px; - margin: 40px auto; - box-shadow: 0 0 4px 2px inset currentColor; - padding-left: 100px; - min-height: 100px; - max-width: 700px; - font-weight: 600; - vertical-align: center; - display: grid; - grid-column: 2; - - &::before { - font-family: "Font Awesome 5 Free"; - font-weight: 600; - position: absolute; - display: flex; - left: 0; - top: 0; - height: 100%; - width: 100px; - font-size: 50px; - align-items: center; - justify-content: center; - } - - .notification__content { - grid-column: 1; - align-self: center; - - color: var(--color-font); - } - - &.notification--broad { - max-width: none; - } -} - -.form-section-notification { - display: grid; - grid-template-columns: 1fr 3fr; - grid-gap: 5px; - - fieldset { - display: grid; - grid-template-columns: 1fr 3fr; - grid-gap: 5px; - grid-column: 1/3; - } - - .notification { - margin: 0; - } - - + .form-group, + .form-section-legend, + .form-section-notification { - margin-top: 11px; - } - - + .form-section-title { - margin-top: 40px; - } -} - -@media (max-width: 768px) { - .form-section-notification { - grid-template-columns: 1fr; - margin-top: 17px; - - fieldset { - grid-template-columns: 1fr; - grid-column: 1/2; - } - } - - .notification { - grid-column: 1; - - max-width: none; - - padding-left: 40px; - - &::before { - height: auto; - width: 45px; - font-size: 40px; - top: 15px; - } - } -} - -.notification-error { - color: var(--color-error) ; -} - -.notification-warning { - color: var(--color-warning) ; -} - -.notification-info { - color: var(--color-lightblack) ; -} - -.notification-success { - color: var(--color-warning) ; -} - - - - -/* - "Heated" element. - Set custom property "--hotness" to a value from 0 to 1 to turn - the element's background to a color on a gradient from green to red. - - TBD: - - move to a proper place - - think about font-weight... - - Example: -
Lorem ipsum -*/ - -.heated { - --hotness: 0; - --red: calc(var(--hotness) * 200); - --green: calc(255 - calc(var(--hotness) * 255)); - --opacity: calc(calc(var(--red) / 600) + 0.1); - - font-weight: var(--weight, 600); - background-color: rgba(var(--red), var(--green), 0, var(--opacity)); -} - - -.uuid { - font-family: monospace; -} - - -.form--inline { - display: inline-block; -} - - -.ribbon { - position: fixed; - top: calc(40px + var(--header-height)); - transition: all .2s cubic-bezier(0.03, 0.43, 0.58, 1); - right: -63px; - transform: rotate(45deg); - width: 250px; - background: var(--color-error); - text-align: center; - color: var(--color-lightwhite); - font-weight: 600; - font-size: 1.25rem; - line-height: 2em; - box-shadow: 0 0 3px rgba(0, 0, 0, 0.4); - z-index: 19; - pointer-events: none; -} - -@media (max-width: 768px) { - .ribbon { - top: calc(20px + var(--header-height-collapsed)); - right: -83px; - transform: rotate(45deg) scale(0.6); - } -} diff --git a/templates/exam-show.cassius b/templates/exam-show.cassius deleted file mode 100644 index 4588a6011..000000000 --- a/templates/exam-show.cassius +++ /dev/null @@ -1,6 +0,0 @@ -.occurrence--not-registered, .no-bonus - text-decoration: line-through - -.result - font-size: 3rem - margin: 30px 30px 0 !important diff --git a/templates/glossary.cassius b/templates/glossary.cassius deleted file mode 100644 index 8a6bc42cf..000000000 --- a/templates/glossary.cassius +++ /dev/null @@ -1,14 +0,0 @@ -.glossary - dt, .dt - font-weight: 600 - - &.sec - font-style: italic - font-size: 0.9rem - font-weight: 600 - color: var(--color-fontsec) - dd, .dd - margin-left: 12px - - dd + dt, .dd + dt, dd + .dt, .dd + .dt - margin-top: 17px diff --git a/templates/table/colonnade.lucius b/templates/table/colonnade.lucius deleted file mode 100644 index 918770d3e..000000000 --- a/templates/table/colonnade.lucius +++ /dev/null @@ -1,40 +0,0 @@ -/* SORTABLE TABLE-HEADERS*/ -.table__th.sortable { - position: relative; - padding-right: 24px; - cursor: pointer; -} - -.table__th.sortable::after, -.table__th.sortable::before { - content: ''; - position: absolute; - top: 50%; - right: 4px; - width: 0; - height: 0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - border-bottom: 8px solid rgba(255, 255, 255, 0.4); -} - -.table__th.sortable::before { - /* magic numbers to move arrow back in the right position after flipping it. - this allows us to use the same border for the up and the down arrow */ - transform: translateY(150%) scale(1, -1); - transform-origin: top; -} - -.table__th.sortable::after { - transform: translateY(-150%); -} - -.table__th.sortable:hover::before, -.table__th.sortable:hover::after { - border-bottom-color: rgba(255, 255, 255, 0.7); -} - -.table__th.sorted-asc::before, -.table__th.sorted-desc::after { - border-bottom-color: white !important; -} diff --git a/templates/table/course/colonnade.lucius b/templates/table/course/colonnade.lucius deleted file mode 100644 index 9590c7329..000000000 --- a/templates/table/course/colonnade.lucius +++ /dev/null @@ -1,45 +0,0 @@ -:root { - --color-grey-light: #efefef; - --color-grey-lighter: #f5f5f5; - --color-fontsec: #5b5861; - --course-bg-color: var(--color-grey-lighter); - --course-expanded-bg-color: var(--color-grey-light); -} - -.scrolltable { - box-shadow: none!important; -} - -.course-header::after, -.course-header::before { - content: ''; - position: absolute; - right: 10px; - top: 20px; - width: 0; - height: 0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - border-bottom: 8px solid rgba(255, 255, 255, 0.4); -} - -.course-header::before { - /* magic numbers to move arrow back in the right position after flipping it. - this allows us to use the same border for the up and the down arrow */ - transform: translateY(150%) scale(1, -1); - transform-origin: top; -} - -.course-header::after { - transform: translateY(-150%); -} - -.course-header:hover::before, -.course-header:hover::after { - border-bottom-color: rgba(255, 255, 255, 0.7); -} - -.sorted-asc::before, -.sorted-desc::after { - border-bottom-color: white !important; -} \ No newline at end of file diff --git a/templates/table/csv-transcode.lucius b/templates/table/csv-transcode.lucius deleted file mode 100644 index bcf12df47..000000000 --- a/templates/table/csv-transcode.lucius +++ /dev/null @@ -1,8 +0,0 @@ -.csv-export { - margin-bottom: 13px; - -} - -.csv-import { - margin-bottom: 13px; -} diff --git a/templates/table/layout-filter-default.lucius b/templates/table/layout-filter-default.lucius deleted file mode 100644 index 7c1d3ab14..000000000 --- a/templates/table/layout-filter-default.lucius +++ /dev/null @@ -1,7 +0,0 @@ -.table-filter { - margin-bottom: 13px; -} - -.table-filter__toggle { - padding: 3px 7px; -} diff --git a/templates/table/layout.lucius b/templates/table/layout.lucius deleted file mode 100644 index 943edbc15..000000000 --- a/templates/table/layout.lucius +++ /dev/null @@ -1,61 +0,0 @@ -/* TABLE HEADER */ -.table-header { - display: flex; - flex-flow: row-reverse; - justify-content: space-between; - margin-bottom: 15px; -} - -/* TABLE FOOTER */ -.table-footer { - display: flex; - flex-flow: row-reverse; - justify-content: space-between; - margin-top: 15px; -} - -/* PAGINATION */ -.pagination { - margin-top: 20px; - overflow: auto; - - .pages { - text-align: center; - white-space: nowrap; - margin: 0; - - .page-link { - margin-top: 7px; - display: inline-block; - background-color: var(--color-grey-medium); - - + .page-link { - margin-left: 7px; - } - - a { - color: var(--color-lightwhite); - padding: 7px 13px; - display: inline-block; - text-decoration: none; - } - - &:not(.current):hover { - background-color: var(--color-primary); - - a { - color: var(--color-lightwhite); - } - } - - &.current { - pointer-events: none; - background-color: var(--color-dark); - - a { - pointer-events: none; - } - } - } - } -} diff --git a/templates/versionHistory.lucius b/templates/versionHistory.lucius deleted file mode 100644 index 60203fcc4..000000000 --- a/templates/versionHistory.lucius +++ /dev/null @@ -1,11 +0,0 @@ -#changelog { - font-size: 14px; - white-space: pre-wrap; - font-family: monospace; -} - -#gitrev { - font-size: 12px; - white-space: pre-wrap; - font-family: monospace; -} diff --git a/templates/widgets/breadcrumbs/breadcrumbs.lucius b/templates/widgets/breadcrumbs/breadcrumbs.lucius deleted file mode 100644 index ca5dfd56c..000000000 --- a/templates/widgets/breadcrumbs/breadcrumbs.lucius +++ /dev/null @@ -1,62 +0,0 @@ -.breadcrumbs__container { - position: relative; - color: var(--color-lightwhite); - padding: 4px 13px; - background-color: var(--color-dark); - line-height: 30px; -} - -@media (min-width: 426px) { - .breadcrumbs__container { - padding: 7px 20px; - } -} - -@media (min-width: 769px) { - .breadcrumbs__container { - padding: 7px 40px; - } -} - -.breadcrumbs__link { - color: var(--color-lightwhite); - - &:hover { - color: var(--color-white); - } -} - -.breadcrumbs__item { - padding-right: 14px; - position: relative; - line-height: 28px; - opacity: 0.8; - z-index: 1; - margin-right: 10px; - - &:hover { - opacity: 1; - } - - &::after { - content: ''; - position: absolute; - top: 11px; - right: 0; - width: 7px; - height: 7px; - border-style: solid; - border-width: 0; - border-bottom-width: 1px; - border-right-width: 1px; - border-color: var(--color-white); - transform: rotate(-45deg); - z-index: 10; - } -} - -.breadcrumbs__last-item { - line-height: 28px; - vertical-align: bottom; - font-weight: 600; -} diff --git a/templates/widgets/communication/recipientLayout.lucius b/templates/widgets/communication/recipientLayout.lucius deleted file mode 100644 index aa4cb072d..000000000 --- a/templates/widgets/communication/recipientLayout.lucius +++ /dev/null @@ -1,65 +0,0 @@ -.recipient-category { - max-width: 400px; - padding: 3px 0; - - &:not(:last-child) { - margin-bottom: 7px; - } - - &:not(:first-child) { - margin-top: 7px; - } -} - -.recipient-category__options { - max-height: 150px; - overflow-y: auto; -} - -.recipient-category__option { - display: flex; - - &:not(:last-child) { - margin-bottom: 10px; - } -} - -.recipient-category__label, -.recipient-category__option-label { - margin-left: 15px; - vertical-align: top; -} - -.recipient-category__fieldset { - margin: 7px 0 5px 9px; - padding: 5px 0 10px; - border-left: 1px solid #bcbcbc; - padding-left: 16px; - position: relative; -} - -.recipient-category__option-add { - display: flex; - - .btn-mass-input-add { - margin-left: 10px; - padding: 10px 0; - } -} - -.recipient-category__options + .recipient-category__option-add { - margin-top: 10px; -} - -.recipient-category__toggle-all { - display: flex; - border-bottom: 1px solid #bcbcbc; - padding-bottom: 8px; - margin-bottom: 8px; -} - -.recipient-category__checked-counter { - position: absolute; - right: 5px; - top: 5px; -} diff --git a/templates/widgets/csvRendered.lucius b/templates/widgets/csvRendered.lucius deleted file mode 100644 index 1187b7160..000000000 --- a/templates/widgets/csvRendered.lucius +++ /dev/null @@ -1,3 +0,0 @@ -.table__td--csv, .table__th--csv { - font-family: monospace; -} diff --git a/templates/widgets/delete-confirmation/delete-confirmation.lucius b/templates/widgets/delete-confirmation/delete-confirmation.lucius deleted file mode 100644 index daf5e5d29..000000000 --- a/templates/widgets/delete-confirmation/delete-confirmation.lucius +++ /dev/null @@ -1,5 +0,0 @@ -.confirmationText { - white-space: pre-wrap; - font-size: 14px; - font-family: monospace; -} diff --git a/templates/widgets/fields/funcField.hamlet b/templates/widgets/fields/funcField.hamlet index 167bf5a9b..18b76ac44 100644 --- a/templates/widgets/fields/funcField.hamlet +++ b/templates/widgets/fields/funcField.hamlet @@ -1,3 +1,3 @@ $newline never -
"-wrapper"}> +
^{formView} diff --git a/templates/widgets/fields/funcField.lucius b/templates/widgets/fields/funcField.lucius deleted file mode 100644 index 37a4c1a9c..000000000 --- a/templates/widgets/fields/funcField.lucius +++ /dev/null @@ -1,4 +0,0 @@ -##{fvId <> "-wrapper"} { - max-height: 75vh; - overflow: auto; -} diff --git a/templates/widgets/footer/footer.lucius b/templates/widgets/footer/footer.lucius deleted file mode 100644 index 26c2ae10f..000000000 --- a/templates/widgets/footer/footer.lucius +++ /dev/null @@ -1,24 +0,0 @@ -.footer { - text-align: center; - padding: 20px; - position: relative; - margin: 40px 0; - - &::before { - content: ''; - position: absolute; - top: 0; - left: 10%; - width: 80%; - height: 2px; - background-color: var(--color-grey-light); - } -} - -.footer-links * { - margin-right: 0.5em; - - &:last { - margin-right: 0; - } -} diff --git a/templates/widgets/gradingKey.cassius b/templates/widgets/gradingKey.cassius deleted file mode 100644 index 396f41818..000000000 --- a/templates/widgets/gradingKey.cassius +++ /dev/null @@ -1,3 +0,0 @@ -.table--grading-key - th, td - padding: 3px; \ No newline at end of file diff --git a/templates/widgets/massinput/massinput.lucius b/templates/widgets/massinput/massinput.lucius deleted file mode 100644 index 6af5274b0..000000000 --- a/templates/widgets/massinput/massinput.lucius +++ /dev/null @@ -1,8 +0,0 @@ -.btn.btn-mass-input-delete, -.btn.btn-mass-input-add { - background-color: #999; - min-width: 50px; - padding: 5px 15px; - font-weight: 700; - font-size: 1.3rem; -} diff --git a/templates/widgets/multiFileField.lucius b/templates/widgets/multiFileField.lucius deleted file mode 100644 index 7c2d489a5..000000000 --- a/templates/widgets/multiFileField.lucius +++ /dev/null @@ -1,11 +0,0 @@ -.file-input__unpack { - font-size: .9rem; - display: flex; - align-items: center; - margin-top: 10px; - - .checkbox { - display: inline-block; - margin-left: 7px; - } -} diff --git a/templates/widgets/pageaction/pageaction.lucius b/templates/widgets/pageaction/pageaction.lucius deleted file mode 100644 index 95accefba..000000000 --- a/templates/widgets/pageaction/pageaction.lucius +++ /dev/null @@ -1,82 +0,0 @@ -.pagenav { - display: flex; - align-items: flex-start; - padding-bottom: 15px; - margin-bottom: 20px; - border-bottom: 1px solid #eee; -} - -.pagenav__list-item { - flex: 1; - position: relative; - display: inline-flex; - box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6); - margin: 10px 10px 0 0; -} - -.pagenav__link-wrapper { - flex: 1; - padding: 10px 10px 12px; - text-decoration: none !important; - - &:hover { - background-color: var(--color-grey-light); - } -} - -@media (max-width: 1024px) { - - .pagenav { - flex-direction: column; - } -} - -@media (min-width: 1025px) { - .pagenav-secondary { - position: relative; - overflow: visible; - padding-top: 10px; - - &::after { - content: '\2026'; - display: inline-block; - padding: 10px 10px 12px; - width: 40px; - box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6); - box-sizing: border-box; - text-align: center; - transition: box-shadow 0.2s ease; - } - - &:hover { - &::after { - box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.8); - } - - .pagenav-secondary__list { - display: block; - } - } - } - - .pagenav-secondary__list { - position: absolute; - display: none; - right: 0; - top: 50px; - width: 250px; - background-color: white; - box-shadow: 0 0 6px 3px var(--color-grey-light); - z-index: 18; - } - - .pagenav__list-item--secondary { - display: flex; - box-shadow: none; - margin: 0; - - &:hover { - background-color: var(--color-grey-light); - } - } -} diff --git a/templates/widgets/permutation/permutation.lucius b/templates/widgets/permutation/permutation.lucius deleted file mode 100644 index 0ae9d74e5..000000000 --- a/templates/widgets/permutation/permutation.lucius +++ /dev/null @@ -1,3 +0,0 @@ -##{theId} { - list-style-type: none; -} diff --git a/webpack.config.js b/webpack.config.js index c16c23a9d..376cc0b24 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,7 @@ const CopyPlugin = require('copy-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const yaml = require('js-yaml'); const HashOutput = require('webpack-plugin-hash-output'); +const postcssPresetEnv = require('postcss-preset-env'); const webpackVersion = require('webpack/package.json').version.split('.').slice(0, 2).join('.'); const packageVersion = require('./package.json').version; @@ -45,15 +46,23 @@ module.exports = { test: /\.css$/i, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true }}, - { loader: 'postcss-loader', options: { sourceMap: true }} + { loader: 'postcss-loader', options: { + sourceMap: true, + plugins: () => [ postcssPresetEnv ] + }}, + { loader: 'resolve-url-loader', options: { sourceMap: true }} ] }, { test: /\.scss$/i, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true }}, - { loader: 'postcss-loader', options: { sourceMap: true }}, - { loader: 'sass-loader', options: { sourceMap: true, includePaths: [path.resolve(__dirname, 'node_modules')] }} + { loader: 'postcss-loader', options: { + sourceMap: true, + plugins: () => [ postcssPresetEnv ] + }}, + { loader: 'resolve-url-loader', options: { sourceMap: true }}, + { loader: 'sass-loader', options: { implementation: require('sass'), sourceMap: true }} ] }, { From 33bd21f45a228aa4d0c1773e7846964de73d2de3 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 17 Dec 2019 14:53:06 +0100 Subject: [PATCH 38/46] chore: move dependencies to GitLab Fixes #552 --- package-lock.json | 4 ++-- package.json | 2 +- stack.yaml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00d481b46..e1895328f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16652,8 +16652,8 @@ } }, "tail.datetime": { - "version": "git+https://github.com/uni2work/tail.DateTime.git#57e4feb2d6a53c7e1d3630a2da7eb9a213fa288d", - "from": "git+https://github.com/uni2work/tail.DateTime.git#master" + "version": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#ef1237569ff22667acb64a9dfd64682ee55817eb", + "from": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#master" }, "tapable": { "version": "1.1.3", diff --git a/package.json b/package.json index 58d79f396..b4bbf8ab7 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "core-js": "^3.4.8", "moment": "^2.24.0", "npm": "^6.13.4", - "tail.datetime": "git+https://github.com/uni2work/tail.DateTime.git#master", + "tail.datetime": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#master", "whatwg-fetch": "^3.0.0" } } diff --git a/stack.yaml b/stack.yaml index a1cd45876..0d3e7a7cf 100644 --- a/stack.yaml +++ b/stack.yaml @@ -11,11 +11,11 @@ packages: - . extra-deps: - - git: https://github.com/uni2work/encoding.git + - git: git@gitlab2.rz.ifi.lmu.de:/uni2work/encoding.git commit: 67bb87ceff53f0178c988dd4e15eeb2daee92b84 - - git: https://github.com/uni2work/memcached-binary.git + - git: git@gitlab2.rz.ifi.lmu.de:uni2work/memcached-binary.git commit: b5461747e7be226d3b67daebc3c9aefe8a4490ad - - git: https://github.com/uni2work/conduit-resumablesink.git + - git: git@gitlab2.rz.ifi.lmu.de:uni2work/conduit-resumablesink.git commit: cbea6159c2975d42f948525e03e12fc390da53c5 - zip-stream-0.2.0.1 From a4cd1f586a467863cefb3e787307dd666acffa4d Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 17 Dec 2019 14:53:31 +0100 Subject: [PATCH 39/46] chore: remove outdated .dir-locals.el --- .dir-locals.el | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .dir-locals.el diff --git a/.dir-locals.el b/.dir-locals.el deleted file mode 100644 index a44395f88..000000000 --- a/.dir-locals.el +++ /dev/null @@ -1,4 +0,0 @@ -((haskell-mode . ((haskell-indent-spaces . 4) - (haskell-process-use-ghci . t))) - (hamlet-mode . ((hamlet/basic-offset . 4) - (haskell-process-use-ghci . t)))) From b66809a352864427366c8452bd8452ebba16deee Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 11:47:25 +0100 Subject: [PATCH 40/46] refactor: convert to sass & minify output css --- frontend/src/_common.sass | 9 + frontend/src/_common.scss | 8 - frontend/src/app.js | 2 +- frontend/src/app.sass | 1191 +++++++++++++ frontend/src/app.scss | 1517 ----------------- frontend/src/utils/alerts/alerts.js | 2 +- frontend/src/utils/alerts/alerts.sass | 186 ++ frontend/src/utils/alerts/alerts.scss | 221 --- frontend/src/utils/asidenav/asidenav.js | 2 +- frontend/src/utils/asidenav/asidenav.sass | 330 ++++ frontend/src/utils/asidenav/asidenav.scss | 406 ----- frontend/src/utils/async-form/async-form.js | 2 +- frontend/src/utils/async-form/async-form.sass | 71 + frontend/src/utils/async-form/async-form.scss | 78 - .../utils/async-table/async-table-filter.sass | 4 + .../utils/async-table/async-table-filter.scss | 5 - frontend/src/utils/async-table/async-table.js | 4 +- .../src/utils/async-table/async-table.sass | 4 + .../src/utils/async-table/async-table.scss | 5 - .../src/utils/course-teaser/course-teaser.js | 2 +- .../utils/course-teaser/course-teaser.sass | 246 +++ .../utils/course-teaser/course-teaser.scss | 317 ---- frontend/src/utils/form/form.js | 2 +- frontend/src/utils/form/form.sass | 35 + frontend/src/utils/form/form.scss | 45 - .../src/utils/hide-columns/hide-columns.js | 2 +- .../src/utils/hide-columns/hide-columns.sass | 61 + .../src/utils/hide-columns/hide-columns.scss | 71 - frontend/src/utils/inputs/checkbox.js | 2 +- frontend/src/utils/inputs/checkbox.sass | 71 + frontend/src/utils/inputs/checkbox.scss | 83 - frontend/src/utils/inputs/file-input.js | 2 +- frontend/src/utils/inputs/file-input.sass | 2 + frontend/src/utils/inputs/file-input.scss | 3 - frontend/src/utils/inputs/inputs.js | 4 +- frontend/src/utils/inputs/inputs.sass | 211 +++ frontend/src/utils/inputs/inputs.scss | 253 --- frontend/src/utils/inputs/radio.sass | 55 + frontend/src/utils/inputs/radio.scss | 66 - frontend/src/utils/mass-input/mass-input.js | 2 +- frontend/src/utils/mass-input/mass-input.sass | 14 + frontend/src/utils/mass-input/mass-input.scss | 18 - frontend/src/utils/modal/modal.js | 2 +- frontend/src/utils/modal/modal.sass | 103 ++ frontend/src/utils/modal/modal.scss | 120 -- frontend/src/utils/navbar/navbar.js | 2 +- frontend/src/utils/navbar/navbar.sass | 228 +++ frontend/src/utils/navbar/navbar.scss | 305 ---- frontend/src/utils/show-hide/show-hide.js | 2 +- frontend/src/utils/show-hide/show-hide.sass | 44 + frontend/src/utils/show-hide/show-hide.scss | 54 - frontend/src/utils/tabber/tabber.js | 2 +- frontend/src/utils/tabber/tabber.sass | 35 + frontend/src/utils/tabber/tabber.scss | 39 - frontend/src/utils/tooltips/tooltips.js | 2 +- frontend/src/utils/tooltips/tooltips.sass | 92 + frontend/src/utils/tooltips/tooltips.scss | 109 -- package-lock.json | 983 +++++++++++ package.json | 1 + records.json | 234 +++ webpack.config.js | 10 +- 61 files changed, 4238 insertions(+), 3743 deletions(-) create mode 100644 frontend/src/_common.sass delete mode 100644 frontend/src/_common.scss create mode 100644 frontend/src/app.sass delete mode 100644 frontend/src/app.scss create mode 100644 frontend/src/utils/alerts/alerts.sass delete mode 100644 frontend/src/utils/alerts/alerts.scss create mode 100644 frontend/src/utils/asidenav/asidenav.sass delete mode 100644 frontend/src/utils/asidenav/asidenav.scss create mode 100644 frontend/src/utils/async-form/async-form.sass delete mode 100644 frontend/src/utils/async-form/async-form.scss create mode 100644 frontend/src/utils/async-table/async-table-filter.sass delete mode 100644 frontend/src/utils/async-table/async-table-filter.scss create mode 100644 frontend/src/utils/async-table/async-table.sass delete mode 100644 frontend/src/utils/async-table/async-table.scss create mode 100644 frontend/src/utils/course-teaser/course-teaser.sass delete mode 100644 frontend/src/utils/course-teaser/course-teaser.scss create mode 100644 frontend/src/utils/form/form.sass delete mode 100644 frontend/src/utils/form/form.scss create mode 100644 frontend/src/utils/hide-columns/hide-columns.sass delete mode 100644 frontend/src/utils/hide-columns/hide-columns.scss create mode 100644 frontend/src/utils/inputs/checkbox.sass delete mode 100644 frontend/src/utils/inputs/checkbox.scss create mode 100644 frontend/src/utils/inputs/file-input.sass delete mode 100644 frontend/src/utils/inputs/file-input.scss create mode 100644 frontend/src/utils/inputs/inputs.sass delete mode 100644 frontend/src/utils/inputs/inputs.scss create mode 100644 frontend/src/utils/inputs/radio.sass delete mode 100644 frontend/src/utils/inputs/radio.scss create mode 100644 frontend/src/utils/mass-input/mass-input.sass delete mode 100644 frontend/src/utils/mass-input/mass-input.scss create mode 100644 frontend/src/utils/modal/modal.sass delete mode 100644 frontend/src/utils/modal/modal.scss create mode 100644 frontend/src/utils/navbar/navbar.sass delete mode 100644 frontend/src/utils/navbar/navbar.scss create mode 100644 frontend/src/utils/show-hide/show-hide.sass delete mode 100644 frontend/src/utils/show-hide/show-hide.scss create mode 100644 frontend/src/utils/tabber/tabber.sass delete mode 100644 frontend/src/utils/tabber/tabber.scss create mode 100644 frontend/src/utils/tooltips/tooltips.sass delete mode 100644 frontend/src/utils/tooltips/tooltips.scss diff --git a/frontend/src/_common.sass b/frontend/src/_common.sass new file mode 100644 index 000000000..cf4fab2cf --- /dev/null +++ b/frontend/src/_common.sass @@ -0,0 +1,9 @@ +@use "~@fortawesome/fontawesome-pro/scss/fontawesome" with ( $fa-font-path: "~@fortawesome/fontawesome-pro/webfonts" ) + +@forward "~@fortawesome/fontawesome-pro/scss/fontawesome" + +@use "~@fortawesome/fontawesome-pro/scss/solid" + +@use "~typeface-roboto" as roboto + +@use "~typeface-source-sans-pro" as source-sans-pro diff --git a/frontend/src/_common.scss b/frontend/src/_common.scss deleted file mode 100644 index d0652e036..000000000 --- a/frontend/src/_common.scss +++ /dev/null @@ -1,8 +0,0 @@ -@use "~@fortawesome/fontawesome-pro/scss/fontawesome" with ( - $fa-font-path: "~@fortawesome/fontawesome-pro/webfonts" -); -@forward "~@fortawesome/fontawesome-pro/scss/fontawesome"; -@use "~@fortawesome/fontawesome-pro/scss/solid"; - -@use "~typeface-roboto" as roboto; -@use "~typeface-source-sans-pro" as source-sans-pro; diff --git a/frontend/src/app.js b/frontend/src/app.js index 6aa438405..8b26b08a2 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -4,7 +4,7 @@ import { I18n } from './services/i18n/i18n'; import { UtilRegistry } from './services/util-registry/util-registry'; import { isValidUtility } from './core/utility'; -import './app.scss'; +import './app.sass'; export class App { httpClient = new HttpClient(); diff --git a/frontend/src/app.sass b/frontend/src/app.sass new file mode 100644 index 000000000..14460cf2a --- /dev/null +++ b/frontend/src/app.sass @@ -0,0 +1,1191 @@ +@use "common" as * + +\:root + // THEME INDEPENDENT COLORS + --color-error: #8c0707 + --color-error-dark: #500303 + --color-warning: #fc9900 + --color-warning-dark: #c27400 + --color-success: #23d160 + --color-success-dark: #1ca64c + --color-info: #c4c4c4 + --color-info-dark: #919191 + --color-lightblack: #1A2A36 + --color-lightwhite: #fcfffa + --color-grey: #B1B5C0 + --color-grey-light: #efefef + --color-grey-lighter: #f5f5f5 + --color-grey-medium: #9A989E + --color-font: #34303a + --color-fontsec: #5b5861 + + // FONTS + --font-base: "Source Sans Pro", "Trebuchet MS", sans-serif + --font-logo: "Roboto", var(--font-base) + + // DIMENSIONS + --header-height: 100px + --header-height-collapsed: 60px + --asidenav-width-xl: 250px + --asidenav-width-lg: 20% + --asidenav-width-md: 60px + +* + box-sizing: border-box + padding: 0 + margin: 0 + -webkit-font-smoothing: antialiased + +body + background-color: white + color: var(--color-font) + font-family: var(--font-base) + font-weight: 400 + font-size: 16px + overflow-y: scroll + +// THEMES + +body + // DEFAULT LMU THEME + --color-lmu-green: #0a9342 + --color-primary: var(--color-lmu-green) + --color-light: #31cc72 + --color-lighter: #35db7a + --color-dark: #087536 + --color-darker: #075728 + --color-link: var(--color-font) + --color-link-hover: var(--color-font) + --color-lmu-box-border: var(--color-lightwhite) + + &.theme--lavender + --color-primary: #584c9c + --color-light: #5969b5 + --color-lighter: #5f7dc2 + --color-dark: #4c4279 + --color-darker: #3c2765 + --color-link: var(--color-dark) + --color-link-hover: var(--color-darker) + + &.theme--neutral-blue + --color-primary: #3E606F + --color-light: rgb(189, 201, 219) + --color-lighter: rgb(145, 159, 170) + --color-dark: rgb(42, 74, 88) + --color-darker: #193441 + + &.theme--aberdeen-reds + --color-primary: #820333 + --color-light: #C9283E + --color-lighter: #F0433A + --color-dark: #540032 + --color-darker: #2E112D + + &.theme--moss-green + --color-primary: #5C996B + --color-light: #7ACC8F + --color-lighter: #99FFB2 + --color-dark: #3D6647 + --color-darker: #1F3324 + + &.theme--sky-love + --color-primary: #87ABE5 + --color-light: #A0C6F2 + --color-lighter: #BAE2FF + --color-dark: #7A95DE + --color-darker: #6B7BC9 + --color-link: var(--color-lightblack) + --color-link-hover: var(--color-darker) + +// END THEMES + +.emph + font-style: italic + +a, +a:visited + text-decoration: none + font-weight: 600 + transition: color .2s ease, background-color .2s ease + +a + color: var(--color-link) + +a:hover + color: var(--color-link-hover) + +ul + margin-left: 20px + +h1, h2, h3, .div-h3, h4, h5 + font-weight: 600 + +h1 + font-size: 32px + margin-bottom: 10px + +h2 + font-size: 24px + margin: 10px 0 + + &:first-child + margin-top: 0 + +h3, .div-h3 + font-size: 20px + margin: 10px 0 + + &:first-child + margin-top: 0 + +h4 + font-size: 16px + margin: 0 + +@media (max-width: 768px) + h1 + font-size: 24px + + h2 + font-size: 20px + + h3, .div-h3 + font-size: 16px + +// LAYOUT +.main + position: relative + +.main__content + position: relative + background-color: white + transition: padding-left .2s ease-out + margin-top: var(--header-height-collapsed) + margin-left: 0 + + > .container + margin: 20px 0 + +.main__content, .modal__content + a + text-decoration: underline + + p, form, .div-p + margin: 0.5rem 0 + + &:last-child + margin: 0.5rem 0 0 + + &:first-child + margin: 0 + +@media (min-width: 426px) + .main__content + margin-left: var(--asidenav-width-md, 50px) + +@media (min-width: 769px) + .main__content + margin-left: var(--asidenav-width-lg, 20%) + margin-top: var(--header-height) + +@media (min-width: 1200px) + .main__content + margin-left: var(--asidenav-width-xl, 250px) + +.main__content-body + padding: 13px + +@media (min-width: 426px) + .main__content-body + padding: 13px 20px + +@media (min-width: 769px) + .main__content-body + padding: 20px 40px + +.pseudo-focus + outline: 5px auto var(--color-light) + outline: 5px auto -webkit-focus-ring-color + +// CONTAINER +.container + + .container + margin-top: 20px + +// GENERAL BUTTON STYLES +input[type="submit"], +input[type="button"], +button, +.btn + outline: 0 + border: 0 + box-shadow: 0 + background-color: var(--color-dark) + color: white + padding: 10px 17px + min-width: 100px + transition: all .1s + font-size: 16px + cursor: pointer + display: inline-block + text-decoration: none + + a:hover + color: white + + &:focus + border-color: #3273dc + box-shadow: 0 0 0 0.25rem rgba(50, 115, 220, 0.25) + outline: 0 + +input[type="submit"][disabled], +input[type="button"][disabled], +button[disabled], +.btn[disabled] + opacity: 0.3 + background-color: var(--color-grey) + cursor: default + +input[type="submit"]:not([disabled]):hover, +input[type="button"]:not([disabled]):hover, +button:not([disabled]):hover, +.btn:not([disabled]):hover + background-color: var(--color-light) + color: white + +.btn-primary + background-color: var(--color-primary) + +.btn-info + background-color: var(--color-info) + +.btn--small + padding: 4px 7px + background-color: var(--color-darker) + +input[type="submit"].btn-info:hover, +input[type="button"].btn-info:hover, +.btn-info:hover + background-color: var(--color-grey) + +// GENERAL TABLE STYLES +.table + margin: 21px 0 + width: 100% + +.table:first-child + margin-top: 0 + +.table:last-child + margin-bottom: 0 + +.table--striped + .table__row:not(.no-stripe):not(.table__row--sum):nth-child(even) + background-color: rgba(0, 0, 0, 0.03) + +.table--hover + .table__row:not(.no-hover):not(.table__row--sum):not(.table__row--head):not(.table__row--foot):hover + background-color: rgba(0, 0, 0, 0.07) + +.table__row--sum td.table__td::before + content: 'Σ' + font-weight: bold + margin-right: .25em + +// SCROLLTABLE +.scrolltable + overflow: auto + +.scrolltable--bordered + box-shadow: 0 0 1px 1px var(--color-grey-light) + +@media (max-width: 425px) + .scrolltable + margin-left: -10px + padding-left: 10px + margin-right: -10px + padding-right: 10px + +// TABLE DESIGN +.table__td, .table__th + padding-top: 14px + padding-bottom: 10px + padding-left: 10px + padding-right: 10px + max-width: 300px + +.table__td + font-size: 16px + color: var(--color-font) + line-height: 1.4 + vertical-align: top + +.table__td--automatic + font-style: oblique + color: var(--color-fontsec) + +.table__td--overriden + font-weight: bold + +.table__th + background-color: var(--color-dark) + position: relative + font-size: 16px + color: white + line-height: 1.4 + padding-top: 10px + padding-bottom: 10px + font-weight: bold + text-align: left + + a + color: white + text-decoration: none + font-weight: bold + + &:hover + color: inherit + + &::before + @extend .fas + + content: fa-content($fa-var-link) + margin-right: 0.25em + +@media (max-width: 1200px) + .table th + padding: 4px 6px + +.table__td-content + max-height: 200px + overflow-y: auto + +.table__th-link + font-weight: bold + + &::before + display: none + +.table--vertical + th + background-color: transparent + color: var(--color-font) + width: 170px + text-align: right + padding-right: 15px + font-weight: 400 + + td + font-weight: 600 + color: var(--color-font) + +.table--condensed + margin: 0 + + .table__th, + .table__td + padding: 4px 8px + +// UNORDERED LIST +.list-ul__item + // padding: 4px 0; + line-height: 25px + +// LIST MODIFIERS +.list--iconless + list-style-type: none + margin-left: 0 + +.list--inline + ul + display: inline-block + margin-left: 0 + + li + display: inline-block + +ul.list--inline + display: inline-block + margin-left: 0 + + li + display: inline-block + +.list--comma-separated li + &::after + content: ', ' + white-space: pre + + &:last-of-type::after + content: none + +.list--space-separated li + &::after + content: ' ' + white-space: pre + + &:last-of-type::after + content: none + +.list--icon-width li + width: 1rem + height: 1rem + +// DEFINITION LIST +.deflist + display: grid + grid-template-columns: 100% + +.deflist__dt, +.deflist__dd + padding: 2px 0 + +.deflist__dt + font-weight: 600 + +.deflist__dd + font-size: 18px + margin-bottom: 10px + + > p, > .div-p + margin-top: 0 + +@media (min-width: 768px) + .deflist + grid-template-columns: fit-content(25vw) 1fr + + .deflist + margin-top: -10px + margin-right: -15px + + .deflist__dd + padding-right: 15px + + .deflist__dt, + .deflist__dd + padding: 12px 0 + margin: 0 + font-size: 16px + + &:last-of-type + border: 0 + + .deflist__dt + padding-right: 50px + + .deflist__dd + padding-right: 15px + +section + padding-bottom: 30px + border-bottom: 1px solid #d3d3d3 + + + section + margin-top: 20px + + &:last-child + border-bottom: none + padding-bottom: 0px + +.pseudonym + font-family: monospace + +.headline-one + margin-bottom: 10px + +// Notification style used as requested by @hamanf in #298, but class was not globally available. Copied from dead-code. For @hamanf to clean up: + +.notification + position: relative + border-radius: 3px + padding: 10px 20px 20px + margin: 40px auto + box-shadow: 0 0 4px 2px inset currentColor + padding-left: 100px + min-height: 100px + max-width: 700px + font-weight: 600 + vertical-align: center + display: grid + grid-column: 2 + + &::before + @extend .fas + + position: absolute + display: flex + left: 0 + top: 0 + height: 100% + width: 100px + font-size: 50px + align-items: center + justify-content: center + + .notification__content + grid-column: 1 + align-self: center + color: var(--color-font) + + &.notification--broad + max-width: none + +.form-section-notification + display: grid + grid-template-columns: 1fr 3fr + grid-gap: 5px + + fieldset + display: grid + grid-template-columns: 1fr 3fr + grid-gap: 5px + grid-column: 1/3 + + .notification + margin: 0 + + + .form-group, + .form-section-legend, + .form-section-notification + margin-top: 11px + + + .form-section-title + margin-top: 40px + +@media (max-width: 768px) + .form-section-notification + grid-template-columns: 1fr + margin-top: 17px + + fieldset + grid-template-columns: 1fr + grid-column: 1/2 + + .notification + grid-column: 1 + max-width: none + padding-left: 40px + + &::before + height: auto + width: 45px + font-size: 40px + top: 15px + +.notification-error + color: var(--color-error) + +.notification-warning + color: var(--color-warning) + +.notification-info + color: var(--color-lightblack) + +.notification-success + color: var(--color-warning) + +// "Heated" element. + Set custom property "--hotness" to a value from 0 to 1 to turn + the element's background to a color on a gradient from green to red. + + TBD: + - move to a proper place + - think about font-weight... + + Example: +
Lorem ipsum + +.heated + --hotness: 0 + --red: calc(var(--hotness) * 200) + --green: calc(255 - calc(var(--hotness) * 255)) + --opacity: calc(calc(var(--red) / 600) + 0.1) + font-weight: var(--weight, 600) + background-color: rgba(var(--red), var(--green), 0, var(--opacity)) + +.uuid + font-family: monospace + +.form--inline + display: inline-block + +.ribbon + position: fixed + top: calc(40px + var(--header-height)) + transition: all 0.2s cubic-bezier(0.03, 0.43, 0.58, 1) + right: -63px + transform: rotate(45deg) + width: 250px + background: var(--color-error) + text-align: center + color: var(--color-lightwhite) + font-weight: 600 + font-size: 1.25rem + line-height: 2em + box-shadow: 0 0 3px rgba(0, 0, 0, 0.4) + z-index: 19 + pointer-events: none + +@media (max-width: 768px) + .ribbon + top: calc(20px + var(--header-height-collapsed)) + right: -83px + transform: rotate(45deg) scale(0.6) + +#admin-studyterms + select, option, input + min-width: 50px + +.allocation__label, .allocation__explanation + color: var(--color-fontsec) + font-style: italic + +.allocation__state + color: var(--color-font) + font-weight: 600 + font-style: normal + +.allocation__courses + margin: 20px 0 0 40px + +.allocation-course + display: grid + grid-template-columns: minmax(105px, 1fr) 9fr + grid-template-areas: 'name name ' '. registered ' 'prio-label prio ' 'instr-label instr ' 'form-label form ' + grid-gap: 5px 7px + margin: 12px 0 + padding: 0 10px 12px 7px + border-left: 1px solid var(--color-grey) + + // &:last-child { + padding: 12px 10px 0 10px; + } + + & + .allocation-course { + border-top: 1px solid var(--color-grey); + } + + &:nth-child(2n) + background-color: rgba(0, 0, 0, 0.015) + + .allocation-course__registered + grid-area: registered + + .allocation-course__priority + grid-area: prio + + .allocation-course__priority-label + grid-area: prio-label + justify-self: end + align-self: center + text-align: right + + .allocation-course__name + grid-area: name + align-self: center + font-size: 1.2rem + + .allocation-course__instructions + grid-area: instr + + .allocation-course__instructions-label + grid-area: instr-label + justify-self: end + text-align: right + + .allocation-course__application + grid-area: form + + .allocation-course__application-label + grid-area: form-label + justify-self: end + text-align: right + padding-top: 6px + +@media (max-width: 426px) + .allocation-course + grid-template-columns: 1fr + grid-template-areas: 'name ' 'registered ' 'prio-label ' 'prio ' 'instr-label' 'instr ' 'form-label ' 'form ' + + .allocation-course__application-label + padding-top: 0 + +.comment + white-space: pre-wrap + font-family: monospace + +th + vertical-align: top + text-align: left + +th, td + padding-bottom: 7px + +.course-news + max-height: 50vh + overflow: auto + + .course-news-item + padding: 12px 0 + border-bottom: 1px solid #d3d3d3 + + &:last-child + padding-bottom: 0 + border-bottom: none + + &:first-child + padding-top: 0 + + .course-news-item__last-edit + color: var(--color-fontsec) + font-style: italic + + .course-news-item__title .modal__trigger-label + font-style: normal + + .course-news-item__summary .modal__trigger-label + font-weight: normal + font-style: normal + color: var(--color-font) + +.bound_explanation + color: var(--color-fontsec) + font-style: italic + +.action + max-width: 800px + padding: 3px 0 + + &:not(:last-child) + margin-bottom: 7px + + &:not(:first-child) + margin-top: 7px + +.action__options + max-height: 450px + overflow-y: auto + +.action__option + display: flex + + &:not(:last-child) + margin-bottom: 10px + +.action__label, +.action__option-label + margin-left: 15px + vertical-align: top + +.action__fieldset + margin: 7px 0 5px 9px + padding: 5px 0 10px + border-left: 1px solid #bcbcbc + padding-left: 16px + position: relative + +.action__toggle-all + display: flex + border-bottom: 1px solid #bcbcbc + padding-bottom: 8px + margin-bottom: 8px + +.action__checked-counter + position: absolute + right: 5px + top: 5px + +.occurrence--not-registered, .no-bonus + text-decoration: line-through + +.result + font-size: 3rem + margin: 30px 30px 0 !important + +.glossary + dt, .dt + font-weight: 600 + + &.sec + font-style: italic + font-size: 0.9rem + font-weight: 600 + color: var(--color-fontsec) + + dd, .dd + margin-left: 12px + + dd + dt, .dd + dt, dd + .dt, .dd + .dt + margin-top: 17px + +// SORTABLE TABLE-HEADERS +.table__th.sortable + position: relative + padding-right: 24px + cursor: pointer + +.table__th.sortable::after, +.table__th.sortable::before + content: '' + position: absolute + top: 50% + right: 4px + width: 0 + height: 0 + border-left: 8px solid transparent + border-right: 8px solid transparent + border-bottom: 8px solid rgba(255, 255, 255, 0.4) + +.table__th.sortable::before + // magic numbers to move arrow back in the right position after flipping it. + this allows us to use the same border for the up and the down arrow + transform: translateY(150%) scale(1, -1) + transform-origin: top + +.table__th.sortable::after + transform: translateY(-150%) + +.table__th.sortable:hover::before, +.table__th.sortable:hover::after + border-bottom-color: rgba(255, 255, 255, 0.7) + +.table__th.sorted-asc::before, +.table__th.sorted-desc::after + border-bottom-color: white !important + +\:root + --color-grey-light: #efefef + --color-grey-lighter: #f5f5f5 + --color-fontsec: #5b5861 + --course-bg-color: var(--color-grey-lighter) + --course-expanded-bg-color: var(--color-grey-light) + +.scrolltable + box-shadow: none !important + +.course-header::after, +.course-header::before + content: '' + position: absolute + right: 10px + top: 20px + width: 0 + height: 0 + border-left: 8px solid transparent + border-right: 8px solid transparent + border-bottom: 8px solid rgba(255, 255, 255, 0.4) + +.course-header::before + // magic numbers to move arrow back in the right position after flipping it. + this allows us to use the same border for the up and the down arrow + transform: translateY(150%) scale(1, -1) + transform-origin: top + +.course-header::after + transform: translateY(-150%) + +.course-header:hover::before, +.course-header:hover::after + border-bottom-color: rgba(255, 255, 255, 0.7) + +.sorted-asc::before, +.sorted-desc::after + border-bottom-color: white !important + +.csv-export + margin-bottom: 13px + +.csv-import + margin-bottom: 13px + +.table-filter + margin-bottom: 13px + +.table-filter__toggle + padding: 3px 7px + +// TABLE HEADER +.table-header + display: flex + flex-flow: row-reverse + justify-content: space-between + margin-bottom: 15px + +// TABLE FOOTER +.table-footer + display: flex + flex-flow: row-reverse + justify-content: space-between + margin-top: 15px + +// PAGINATION +.pagination + margin-top: 20px + overflow: auto + + .pages + text-align: center + white-space: nowrap + margin: 0 + + .page-link + margin-top: 7px + display: inline-block + background-color: var(--color-grey-medium) + + + .page-link + margin-left: 7px + + a + color: var(--color-lightwhite) + padding: 7px 13px + display: inline-block + text-decoration: none + + &:not(.current):hover + background-color: var(--color-primary) + + a + color: var(--color-lightwhite) + + &.current + pointer-events: none + background-color: var(--color-dark) + + a + pointer-events: none + +#changelog + font-size: 14px + white-space: pre-wrap + font-family: monospace + +#gitrev + font-size: 12px + white-space: pre-wrap + font-family: monospace + +.breadcrumbs__container + position: relative + color: var(--color-lightwhite) + padding: 4px 13px + background-color: var(--color-dark) + line-height: 30px + +@media (min-width: 426px) + .breadcrumbs__container + padding: 7px 20px + +@media (min-width: 769px) + .breadcrumbs__container + padding: 7px 40px + +.breadcrumbs__link + color: var(--color-lightwhite) + + &:hover + color: var(--color-white) + +.breadcrumbs__item + padding-right: 14px + position: relative + line-height: 28px + opacity: 0.8 + z-index: 1 + margin-right: 10px + + &:hover + opacity: 1 + + &::after + content: '' + position: absolute + top: 11px + right: 0 + width: 7px + height: 7px + border-style: solid + border-width: 0 + border-bottom-width: 1px + border-right-width: 1px + border-color: var(--color-white) + transform: rotate(-45deg) + z-index: 10 + +.breadcrumbs__last-item + line-height: 28px + vertical-align: bottom + font-weight: 600 + +.recipient-category + max-width: 400px + padding: 3px 0 + + &:not(:last-child) + margin-bottom: 7px + + &:not(:first-child) + margin-top: 7px + +.recipient-category__options + max-height: 150px + overflow-y: auto + +.recipient-category__option + display: flex + + &:not(:last-child) + margin-bottom: 10px + +.recipient-category__label, +.recipient-category__option-label + margin-left: 15px + vertical-align: top + +.recipient-category__fieldset + margin: 7px 0 5px 9px + padding: 5px 0 10px + border-left: 1px solid #bcbcbc + padding-left: 16px + position: relative + +.recipient-category__option-add + display: flex + + .btn-mass-input-add + margin-left: 10px + padding: 10px 0 + +.recipient-category__options + .recipient-category__option-add + margin-top: 10px + +.recipient-category__toggle-all + display: flex + border-bottom: 1px solid #bcbcbc + padding-bottom: 8px + margin-bottom: 8px + +.recipient-category__checked-counter + position: absolute + right: 5px + top: 5px + +.table__td--csv, .table__th--csv + font-family: monospace + +.confirmationText + white-space: pre-wrap + font-size: 14px + font-family: monospace + +.func-field__wrapper + max-height: 75vh + overflow: auto + +.footer + text-align: center + padding: 20px + position: relative + margin: 40px 0 + + &::before + content: '' + position: absolute + top: 0 + left: 10% + width: 80% + height: 2px + background-color: var(--color-grey-light) + +.footer-links * + margin-right: 0.5em + + &:last + margin-right: 0 + +.table--grading-key + th, td + padding: 3px + +.btn.btn-mass-input-delete, +.btn.btn-mass-input-add + background-color: #999 + min-width: 50px + padding: 5px 15px + font-weight: 700 + font-size: 1.3rem + +.file-input__unpack + font-size: .9rem + display: flex + align-items: center + margin-top: 10px + + .checkbox + display: inline-block + margin-left: 7px + +.pagenav + display: flex + align-items: flex-start + padding-bottom: 15px + margin-bottom: 20px + border-bottom: 1px solid #eee + +.pagenav__list-item + flex: 1 + position: relative + display: inline-flex + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6) + margin: 10px 10px 0 0 + +.pagenav__link-wrapper + flex: 1 + padding: 10px 10px 12px + text-decoration: none !important + + &:hover + background-color: var(--color-grey-light) + +@media (max-width: 1024px) + .pagenav + flex-direction: column + +@media (min-width: 1025px) + .pagenav-secondary + position: relative + overflow: visible + padding-top: 10px + + &::after + content: '\2026' + display: inline-block + padding: 10px 10px 12px + width: 40px + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6) + box-sizing: border-box + text-align: center + transition: box-shadow 0.2s ease + + &:hover + &::after + box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.8) + + .pagenav-secondary__list + display: block + + .pagenav-secondary__list + position: absolute + display: none + right: 0 + top: 50px + width: 250px + background-color: white + box-shadow: 0 0 6px 3px var(--color-grey-light) + z-index: 18 + + .pagenav__list-item--secondary + display: flex + box-shadow: none + margin: 0 + + &:hover + background-color: var(--color-grey-light) diff --git a/frontend/src/app.scss b/frontend/src/app.scss deleted file mode 100644 index fd0d6f93c..000000000 --- a/frontend/src/app.scss +++ /dev/null @@ -1,1517 +0,0 @@ -@use "common" as *; - -:root { - /* THEME INDEPENDENT COLORS */ - --color-error: #8c0707; - --color-error-dark: #500303; - --color-warning: #fc9900; - --color-warning-dark: #c27400; - --color-success: #23d160; - --color-success-dark: #1ca64c; - --color-info: #c4c4c4; - --color-info-dark: #919191; - --color-lightblack: #1A2A36; - --color-lightwhite: #fcfffa; - --color-grey: #B1B5C0; - --color-grey-light: #efefef; - --color-grey-lighter: #f5f5f5; - --color-grey-medium: #9A989E; - --color-font: #34303a; - --color-fontsec: #5b5861; - - - /* FONTS */ - --font-base: "Source Sans Pro", "Trebuchet MS", sans-serif; - --font-logo: "Roboto", var(--font-base); - - /* DIMENSIONS */ - --header-height: 100px; - --header-height-collapsed: 60px; - - --asidenav-width-xl: 250px; - --asidenav-width-lg: 20%; - --asidenav-width-md: 60px; -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; - -webkit-font-smoothing: antialiased; -} - -body { - background-color: white; - color: var(--color-font); - font-family: var(--font-base); - font-weight: 400; - font-size: 16px; - overflow-y: scroll; -} - -/* THEMES */ - -body { - /* DEFAULT LMU THEME */ - --color-lmu-green: #0a9342; - --color-primary: var(--color-lmu-green); - --color-light: #31cc72; - --color-lighter: #35db7a; - --color-dark: #087536; - --color-darker: #075728; - --color-link: var(--color-font); - --color-link-hover: var(--color-font); - --color-lmu-box-border: var(--color-lightwhite); - - &.theme--lavender { - --color-primary: #584c9c; - --color-light: #5969b5; - --color-lighter: #5f7dc2; - --color-dark: #4c4279; - --color-darker: #3c2765; - --color-link: var(--color-dark); - --color-link-hover: var(--color-darker); - } - - &.theme--neutral-blue { - --color-primary: #3E606F; - --color-light: rgb(189, 201, 219); - --color-lighter: rgb(145, 159, 170); - --color-dark: rgb(42, 74, 88); - --color-darker: #193441; - } - - &.theme--aberdeen-reds { - --color-primary: #820333; - --color-light: #C9283E; - --color-lighter: #F0433A; - --color-dark: #540032; - --color-darker: #2E112D; - } - - &.theme--moss-green { - --color-primary: #5C996B; - --color-light: #7ACC8F; - --color-lighter: #99FFB2; - --color-dark: #3D6647; - --color-darker: #1F3324; - } - - &.theme--sky-love { - --color-primary: #87ABE5; - --color-light: #A0C6F2; - --color-lighter: #BAE2FF; - --color-dark: #7A95DE; - --color-darker: #6B7BC9; - --color-link: var(--color-lightblack); - --color-link-hover: var(--color-darker); - } -} - -/* END THEMES */ - -.emph { - font-style: italic; -} - -a, -a:visited { - text-decoration: none; - font-weight: 600; - transition: color .2s ease, background-color .2s ease; -} - -a { - color: var(--color-link); -} - -a:hover { - color: var(--color-link-hover); -} - - -ul { - margin-left: 20px; -} - -h1, h2, h3, .div-h3 , h4, h5 { - font-weight: 600; -} -h1 { - font-size: 32px; - margin-bottom: 10px; -} -h2 { - font-size: 24px; - margin: 10px 0; - - &:first-child { - margin-top: 0; - } -} -h3, .div-h3 { - font-size: 20px; - margin: 10px 0; - - &:first-child { - margin-top: 0; - } -} -h4 { - font-size: 16px; - margin: 0; -} - -@media (max-width: 768px) { - - h1 { - font-size: 24px; - } - - h2 { - font-size: 20px; - } - - h3, .div-h3 { - font-size: 16px; - } -} - -/* LAYOUT */ -.main { - position: relative; -} - -.main__content { - position: relative; - background-color: white; - transition: padding-left .2s ease-out; - margin-top: var(--header-height-collapsed); - margin-left: 0; - - > .container { - margin: 20px 0; - } -} - -.main__content, .modal__content { - a { - text-decoration: underline; - } - - p, form, .div-p { - margin: 0.5rem 0; - - &:last-child { - margin: 0.5rem 0 0; - - &:first-child { - margin: 0; - } - } - } -} - -@media (min-width: 426px) { - .main__content { - margin-left: var(--asidenav-width-md, 50px); - } -} - -@media (min-width: 769px) { - .main__content { - margin-left: var(--asidenav-width-lg, 20%); - margin-top: var(--header-height); - } -} - -@media (min-width: 1200px) { - .main__content { - margin-left: var(--asidenav-width-xl, 250px); - } -} - -.main__content-body { - padding: 13px; -} - -@media (min-width: 426px) { - .main__content-body { - padding: 13px 20px; - } -} - -@media (min-width: 769px) { - .main__content-body { - padding: 20px 40px; - } -} - -.pseudo-focus { - outline: 5px auto var(--color-light); - outline: 5px auto -webkit-focus-ring-color; -} - -/* CONTAINER */ -.container { - - + .container { - margin-top: 20px; - } -} - -/* GENERAL BUTTON STYLES */ -input[type="submit"], -input[type="button"], -button, -.btn { - outline: 0; - border: 0; - box-shadow: 0; - background-color: var(--color-dark); - color: white; - padding: 10px 17px; - min-width: 100px; - transition: all .1s; - font-size: 16px; - cursor: pointer; - display: inline-block; - text-decoration: none; - - a:hover { - color: white; - } - - &:focus { - border-color: #3273dc; - box-shadow: 0 0 0 0.25rem rgba(50,115,220,.25); - outline: 0; - } -} - -input[type="submit"][disabled], -input[type="button"][disabled], -button[disabled], -.btn[disabled] { - opacity: 0.3; - background-color: var(--color-grey); - cursor: default; -} - -input[type="submit"]:not([disabled]):hover, -input[type="button"]:not([disabled]):hover, -button:not([disabled]):hover, -.btn:not([disabled]):hover { - background-color: var(--color-light); - color: white; -} - -.btn-primary { - background-color: var(--color-primary); -} - -.btn-info { - background-color: var(--color-info) -} - -.btn--small { - padding: 4px 7px; - background-color: var(--color-darker); -} - -input[type="submit"].btn-info:hover, -input[type="button"].btn-info:hover, -.btn-info:hover { - background-color: var(--color-grey) -} - -/* GENERAL TABLE STYLES */ -.table { - margin: 21px 0; - width: 100%; -} - -.table:first-child { - margin-top: 0; -} - -.table:last-child { - margin-bottom: 0; -} - -.table--striped { - - .table__row:not(.no-stripe):not(.table__row--sum):nth-child(even) { - background-color: rgba(0, 0, 0, 0.03); - } -} - -.table--hover { - - .table__row:not(.no-hover):not(.table__row--sum):not(.table__row--head):not(.table__row--foot):hover { - background-color: rgba(0, 0, 0, 0.07); - } -} - -.table__row--sum td.table__td::before { - content: 'Σ'; - font-weight: bold; - margin-right: .25em; -} - -/* SCROLLTABLE */ -.scrolltable { - overflow: auto; -} - -.scrolltable--bordered { - box-shadow: 0 0 1px 1px var(--color-grey-light); -} - -@media (max-width: 425px) { - - .scrolltable { - margin-left: -10px; - padding-left: 10px; - margin-right: -10px; - padding-right: 10px; - } -} - -/* TABLE DESIGN */ -.table__td, .table__th { - padding-top: 14px; - padding-bottom: 10px; - padding-left: 10px; - padding-right: 10px; - max-width: 300px; -} - -.table__td { - font-size: 16px; - color: var(--color-font); - line-height: 1.4; - vertical-align: top; -} - -.table__td--automatic { - font-style: oblique; - color: var(--color-fontsec); -} - -.table__td--overriden { - font-weight: bold; -} - -.table__th { - background-color: var(--color-dark); - position: relative; - font-size: 16px; - color: white; - line-height: 1.4; - padding-top: 10px; - padding-bottom: 10px; - font-weight: bold; - text-align: left; - - a { - color: white; - text-decoration: none; - font-weight: bold; - - &:hover { - color: inherit; - } - - &::before { - @extend .fas; - content: fa-content($fa-var-link); - margin-right: 0.25em; - } - } -} - -@media (max-width: 1200px) { - - .table th { - padding: 4px 6px; - } -} - -.table__td-content { - max-height: 200px; - overflow-y: auto; -} - -.table__th-link { - font-weight: bold; - - &::before { - display: none; - } -} - -.table--vertical { - - th { - background-color: transparent; - color: var(--color-font); - width: 170px; - text-align: right; - padding-right: 15px; - font-weight: 400; - } - - td { - font-weight: 600; - color: var(--color-font); - } -} - -.table--condensed { - margin: 0; - - .table__th, - .table__td { - padding: 4px 8px; - } -} - -/* UNORDERED LIST */ -.list-ul__item { - // padding: 4px 0; - line-height: 25px; -} - -/* LIST MODIFIERS */ -.list--iconless { - list-style-type: none; - margin-left: 0; -} - -.list--inline { - ul { - display: inline-block; - margin-left: 0; - - li { - display: inline-block; - } - } -} - -ul.list--inline { - - display: inline-block; - margin-left: 0; - - li { - display: inline-block; - } -} - -.list--comma-separated li { - &::after { - content: ', '; - white-space: pre; - } - - &:last-of-type::after { - content: none; - } -} - -.list--space-separated li { - &::after { - content: ' '; - white-space: pre; - } - - &:last-of-type::after { - content: none; - } -} - -.list--icon-width li { - width: 1rem; - height: 1rem; -} - -/* DEFINITION LIST */ -.deflist { - display: grid; - grid-template-columns: 100%; -} -.deflist__dt, -.deflist__dd { - padding: 2px 0; -} - -.deflist__dt { - font-weight: 600; -} - -.deflist__dd { - font-size: 18px; - margin-bottom: 10px; - - > p, > .div-p { - margin-top: 0; - } -} - -@media (min-width: 768px) { - - .deflist { - grid-template-columns: fit-content(25vw) 1fr; - - .deflist { - margin-top: -10px; - margin-right: -15px; - - .deflist__dd { - padding-right: 15px; - } - } - } - - .deflist__dt, - .deflist__dd { - padding: 12px 0; - margin: 0; - font-size: 16px; - - &:last-of-type { - border: 0; - } - } - - .deflist__dt { - padding-right: 50px; - } - - .deflist__dd { - padding-right: 15px; - } -} - -section { - padding-bottom: 30px; - border-bottom: 1px solid #d3d3d3; - - + section { - margin-top: 20px; - } - - &:last-child { - border-bottom: none; - padding-bottom: 0px; - } -} - -.pseudonym { - font-family: monospace; -} - -.headline-one { - margin-bottom: 10px; -} - -/* Notification style used as requested by @hamanf in #298, but class was not globally available. Copied from dead-code. For @hamanf to clean up: */ - -.notification { - position: relative; - border-radius: 3px; - padding: 10px 20px 20px; - margin: 40px auto; - box-shadow: 0 0 4px 2px inset currentColor; - padding-left: 100px; - min-height: 100px; - max-width: 700px; - font-weight: 600; - vertical-align: center; - display: grid; - grid-column: 2; - - &::before { - @extend .fas; - position: absolute; - display: flex; - left: 0; - top: 0; - height: 100%; - width: 100px; - font-size: 50px; - align-items: center; - justify-content: center; - } - - .notification__content { - grid-column: 1; - align-self: center; - - color: var(--color-font); - } - - &.notification--broad { - max-width: none; - } -} - -.form-section-notification { - display: grid; - grid-template-columns: 1fr 3fr; - grid-gap: 5px; - - fieldset { - display: grid; - grid-template-columns: 1fr 3fr; - grid-gap: 5px; - grid-column: 1/3; - } - - .notification { - margin: 0; - } - - + .form-group, + .form-section-legend, + .form-section-notification { - margin-top: 11px; - } - - + .form-section-title { - margin-top: 40px; - } -} - -@media (max-width: 768px) { - .form-section-notification { - grid-template-columns: 1fr; - margin-top: 17px; - - fieldset { - grid-template-columns: 1fr; - grid-column: 1/2; - } - } - - .notification { - grid-column: 1; - - max-width: none; - - padding-left: 40px; - - &::before { - height: auto; - width: 45px; - font-size: 40px; - top: 15px; - } - } -} - -.notification-error { - color: var(--color-error) ; -} - -.notification-warning { - color: var(--color-warning) ; -} - -.notification-info { - color: var(--color-lightblack) ; -} - -.notification-success { - color: var(--color-warning) ; -} - - - - -/* - "Heated" element. - Set custom property "--hotness" to a value from 0 to 1 to turn - the element's background to a color on a gradient from green to red. - - TBD: - - move to a proper place - - think about font-weight... - - Example: -
Lorem ipsum -*/ - -.heated { - --hotness: 0; - --red: calc(var(--hotness) * 200); - --green: calc(255 - calc(var(--hotness) * 255)); - --opacity: calc(calc(var(--red) / 600) + 0.1); - - font-weight: var(--weight, 600); - background-color: rgba(var(--red), var(--green), 0, var(--opacity)); -} - - -.uuid { - font-family: monospace; -} - - -.form--inline { - display: inline-block; -} - - -.ribbon { - position: fixed; - top: calc(40px + var(--header-height)); - transition: all .2s cubic-bezier(0.03, 0.43, 0.58, 1); - right: -63px; - transform: rotate(45deg); - width: 250px; - background: var(--color-error); - text-align: center; - color: var(--color-lightwhite); - font-weight: 600; - font-size: 1.25rem; - line-height: 2em; - box-shadow: 0 0 3px rgba(0, 0, 0, 0.4); - z-index: 19; - pointer-events: none; -} - -@media (max-width: 768px) { - .ribbon { - top: calc(20px + var(--header-height-collapsed)); - right: -83px; - transform: rotate(45deg) scale(0.6); - } -} - -#admin-studyterms { - select, option, input { - min-width: 50px; - } -} - -.allocation__label, .allocation__explanation { - color: var(--color-fontsec); - font-style: italic; -} - -.allocation__state { - color: var(--color-font); - font-weight: 600; - font-style: normal; -} - -.allocation__courses { - margin: 20px 0 0 40px; -} - -.allocation-course { - display: grid; - grid-template-columns: minmax(105px, 1fr) 9fr; - grid-template-areas: - 'name name ' - '. registered ' - 'prio-label prio ' - 'instr-label instr ' - 'form-label form '; - - grid-gap: 5px 7px; - margin: 12px 0; - padding: 0 10px 12px 7px; - - border-left: 1px solid var(--color-grey); - - /* &:last-child { - * padding: 12px 10px 0 10px; - * } - * - * & + .allocation-course { - * border-top: 1px solid var(--color-grey); - * } - */ - - &:nth-child(2n) { - background-color: rgba(0, 0, 0, 0.015); - } - - .allocation-course__registered { - grid-area: registered; - } - - .allocation-course__priority { - grid-area: prio; - } - .allocation-course__priority-label { - grid-area: prio-label; - justify-self: end; - align-self: center; - text-align: right; - } - - .allocation-course__name { - grid-area: name; - - align-self: center; - - font-size: 1.2rem; - } - - .allocation-course__instructions { - grid-area: instr; - } - .allocation-course__instructions-label { - grid-area: instr-label; - justify-self: end; - text-align: right; - } - - .allocation-course__application { - grid-area: form; - } - .allocation-course__application-label { - grid-area: form-label; - justify-self: end; - text-align: right; - padding-top: 6px; - } -} - -@media (max-width: 426px) { - .allocation-course { - grid-template-columns: 1fr; - grid-template-areas: - 'name ' - 'registered ' - 'prio-label ' - 'prio ' - 'instr-label' - 'instr ' - 'form-label ' - 'form '; - } - - .allocation-course__application-label { - padding-top: 0; - } -} - - -.comment { - white-space: pre-wrap; - font-family: monospace; -} - -th { - vertical-align: top; - text-align: left; -} - -th, td { - padding-bottom: 7px; -} - -.course-news { - max-height: 50vh; - overflow: auto; - - .course-news-item { - padding: 12px 0; - border-bottom: 1px solid #d3d3d3; - - &:last-child { - padding-bottom: 0; - border-bottom: none; - } - - &:first-child { - padding-top: 0; - } - - .course-news-item__last-edit { - color: var(--color-fontsec); - font-style: italic; - } - - .course-news-item__title .modal__trigger-label { - font-style: normal; - } - - .course-news-item__summary .modal__trigger-label { - font-weight: normal; - font-style: normal; - color: var(--color-font); - } - } -} - - -.bound_explanation { - color: var(--color-fontsec); - font-style: italic; -} - - -.action { - max-width: 800px; - padding: 3px 0; - - &:not(:last-child) { - margin-bottom: 7px; - } - - &:not(:first-child) { - margin-top: 7px; - } -} - -.action__options { - max-height: 450px; - overflow-y: auto; -} - -.action__option { - display: flex; - - &:not(:last-child) { - margin-bottom: 10px; - } -} - -.action__label, -.action__option-label { - margin-left: 15px; - vertical-align: top; -} - -.action__fieldset { - margin: 7px 0 5px 9px; - padding: 5px 0 10px; - border-left: 1px solid #bcbcbc; - padding-left: 16px; - position: relative; -} - -.action__toggle-all { - display: flex; - border-bottom: 1px solid #bcbcbc; - padding-bottom: 8px; - margin-bottom: 8px; -} - -.action__checked-counter { - position: absolute; - right: 5px; - top: 5px; -} - - -.occurrence--not-registered, .no-bonus { - text-decoration: line-through; -} - -.result { - font-size: 3rem; - margin: 30px 30px 0 !important; -} - - -.glossary { - dt, .dt { - font-weight: 600; - } - - &.sec { - font-style: italic; - font-size: 0.9rem; - font-weight: 600; - color: var(--color-fontsec); - } - dd, .dd { - margin-left: 12px; - } - - dd + dt, .dd + dt, dd + .dt, .dd + .dt { - margin-top: 17px; - } -} - - -/* SORTABLE TABLE-HEADERS*/ -.table__th.sortable { - position: relative; - padding-right: 24px; - cursor: pointer; -} - -.table__th.sortable::after, -.table__th.sortable::before { - content: ''; - position: absolute; - top: 50%; - right: 4px; - width: 0; - height: 0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - border-bottom: 8px solid rgba(255, 255, 255, 0.4); -} - -.table__th.sortable::before { - /* magic numbers to move arrow back in the right position after flipping it. - this allows us to use the same border for the up and the down arrow */ - transform: translateY(150%) scale(1, -1); - transform-origin: top; -} - -.table__th.sortable::after { - transform: translateY(-150%); -} - -.table__th.sortable:hover::before, -.table__th.sortable:hover::after { - border-bottom-color: rgba(255, 255, 255, 0.7); -} - -.table__th.sorted-asc::before, -.table__th.sorted-desc::after { - border-bottom-color: white !important; -} - - -:root { - --color-grey-light: #efefef; - --color-grey-lighter: #f5f5f5; - --color-fontsec: #5b5861; - --course-bg-color: var(--color-grey-lighter); - --course-expanded-bg-color: var(--color-grey-light); -} - -.scrolltable { - box-shadow: none!important; -} - -.course-header::after, -.course-header::before { - content: ''; - position: absolute; - right: 10px; - top: 20px; - width: 0; - height: 0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - border-bottom: 8px solid rgba(255, 255, 255, 0.4); -} - -.course-header::before { - /* magic numbers to move arrow back in the right position after flipping it. - this allows us to use the same border for the up and the down arrow */ - transform: translateY(150%) scale(1, -1); - transform-origin: top; -} - -.course-header::after { - transform: translateY(-150%); -} - -.course-header:hover::before, -.course-header:hover::after { - border-bottom-color: rgba(255, 255, 255, 0.7); -} - -.sorted-asc::before, -.sorted-desc::after { - border-bottom-color: white !important; -} - -.csv-export { - margin-bottom: 13px; - -} - -.csv-import { - margin-bottom: 13px; -} - - -.table-filter { - margin-bottom: 13px; -} - -.table-filter__toggle { - padding: 3px 7px; -} - - -/* TABLE HEADER */ -.table-header { - display: flex; - flex-flow: row-reverse; - justify-content: space-between; - margin-bottom: 15px; -} - -/* TABLE FOOTER */ -.table-footer { - display: flex; - flex-flow: row-reverse; - justify-content: space-between; - margin-top: 15px; -} - -/* PAGINATION */ -.pagination { - margin-top: 20px; - overflow: auto; - - .pages { - text-align: center; - white-space: nowrap; - margin: 0; - - .page-link { - margin-top: 7px; - display: inline-block; - background-color: var(--color-grey-medium); - - + .page-link { - margin-left: 7px; - } - - a { - color: var(--color-lightwhite); - padding: 7px 13px; - display: inline-block; - text-decoration: none; - } - - &:not(.current):hover { - background-color: var(--color-primary); - - a { - color: var(--color-lightwhite); - } - } - - &.current { - pointer-events: none; - background-color: var(--color-dark); - - a { - pointer-events: none; - } - } - } - } -} - - -#changelog { - font-size: 14px; - white-space: pre-wrap; - font-family: monospace; -} - -#gitrev { - font-size: 12px; - white-space: pre-wrap; - font-family: monospace; -} - - -.breadcrumbs__container { - position: relative; - color: var(--color-lightwhite); - padding: 4px 13px; - background-color: var(--color-dark); - line-height: 30px; -} - -@media (min-width: 426px) { - .breadcrumbs__container { - padding: 7px 20px; - } -} - -@media (min-width: 769px) { - .breadcrumbs__container { - padding: 7px 40px; - } -} - -.breadcrumbs__link { - color: var(--color-lightwhite); - - &:hover { - color: var(--color-white); - } -} - -.breadcrumbs__item { - padding-right: 14px; - position: relative; - line-height: 28px; - opacity: 0.8; - z-index: 1; - margin-right: 10px; - - &:hover { - opacity: 1; - } - - &::after { - content: ''; - position: absolute; - top: 11px; - right: 0; - width: 7px; - height: 7px; - border-style: solid; - border-width: 0; - border-bottom-width: 1px; - border-right-width: 1px; - border-color: var(--color-white); - transform: rotate(-45deg); - z-index: 10; - } -} - -.breadcrumbs__last-item { - line-height: 28px; - vertical-align: bottom; - font-weight: 600; -} - - -.recipient-category { - max-width: 400px; - padding: 3px 0; - - &:not(:last-child) { - margin-bottom: 7px; - } - - &:not(:first-child) { - margin-top: 7px; - } -} - -.recipient-category__options { - max-height: 150px; - overflow-y: auto; -} - -.recipient-category__option { - display: flex; - - &:not(:last-child) { - margin-bottom: 10px; - } -} - -.recipient-category__label, -.recipient-category__option-label { - margin-left: 15px; - vertical-align: top; -} - -.recipient-category__fieldset { - margin: 7px 0 5px 9px; - padding: 5px 0 10px; - border-left: 1px solid #bcbcbc; - padding-left: 16px; - position: relative; -} - -.recipient-category__option-add { - display: flex; - - .btn-mass-input-add { - margin-left: 10px; - padding: 10px 0; - } -} - -.recipient-category__options + .recipient-category__option-add { - margin-top: 10px; -} - -.recipient-category__toggle-all { - display: flex; - border-bottom: 1px solid #bcbcbc; - padding-bottom: 8px; - margin-bottom: 8px; -} - -.recipient-category__checked-counter { - position: absolute; - right: 5px; - top: 5px; -} - - -.table__td--csv, .table__th--csv { - font-family: monospace; -} - - -.confirmationText { - white-space: pre-wrap; - font-size: 14px; - font-family: monospace; -} - - -.func-field__wrapper { - max-height: 75vh; - overflow: auto; -} - - -.footer { - text-align: center; - padding: 20px; - position: relative; - margin: 40px 0; - - &::before { - content: ''; - position: absolute; - top: 0; - left: 10%; - width: 80%; - height: 2px; - background-color: var(--color-grey-light); - } -} - -.footer-links * { - margin-right: 0.5em; - - &:last { - margin-right: 0; - } -} - - -.table--grading-key { - th, td { - padding: 3px; - } -} - -.btn.btn-mass-input-delete, -.btn.btn-mass-input-add { - background-color: #999; - min-width: 50px; - padding: 5px 15px; - font-weight: 700; - font-size: 1.3rem; -} - - -.file-input__unpack { - font-size: .9rem; - display: flex; - align-items: center; - margin-top: 10px; - - .checkbox { - display: inline-block; - margin-left: 7px; - } -} - - -.pagenav { - display: flex; - align-items: flex-start; - padding-bottom: 15px; - margin-bottom: 20px; - border-bottom: 1px solid #eee; -} - -.pagenav__list-item { - flex: 1; - position: relative; - display: inline-flex; - box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6); - margin: 10px 10px 0 0; -} - -.pagenav__link-wrapper { - flex: 1; - padding: 10px 10px 12px; - text-decoration: none !important; - - &:hover { - background-color: var(--color-grey-light); - } -} - -@media (max-width: 1024px) { - - .pagenav { - flex-direction: column; - } -} - -@media (min-width: 1025px) { - .pagenav-secondary { - position: relative; - overflow: visible; - padding-top: 10px; - - &::after { - content: '\2026'; - display: inline-block; - padding: 10px 10px 12px; - width: 40px; - box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.6); - box-sizing: border-box; - text-align: center; - transition: box-shadow 0.2s ease; - } - - &:hover { - &::after { - box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.8); - } - - .pagenav-secondary__list { - display: block; - } - } - } - - .pagenav-secondary__list { - position: absolute; - display: none; - right: 0; - top: 50px; - width: 250px; - background-color: white; - box-shadow: 0 0 6px 3px var(--color-grey-light); - z-index: 18; - } - - .pagenav__list-item--secondary { - display: flex; - box-shadow: none; - margin: 0; - - &:hover { - background-color: var(--color-grey-light); - } - } -} - - -##{theId} { - list-style-type: none; -} diff --git a/frontend/src/utils/alerts/alerts.js b/frontend/src/utils/alerts/alerts.js index 3c4eba683..6c4a41a40 100644 --- a/frontend/src/utils/alerts/alerts.js +++ b/frontend/src/utils/alerts/alerts.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './alerts.scss'; +import './alerts.sass'; const ALERTS_INITIALIZED_CLASS = 'alerts--initialized'; const ALERTS_ELEVATED_CLASS = 'alerts--elevated'; diff --git a/frontend/src/utils/alerts/alerts.sass b/frontend/src/utils/alerts/alerts.sass new file mode 100644 index 000000000..340b85f01 --- /dev/null +++ b/frontend/src/utils/alerts/alerts.sass @@ -0,0 +1,186 @@ +@use "../../common" as * + +.alerts + position: fixed + bottom: 0 + right: 5% + z-index: 20 + text-align: right + display: flex + flex-direction: column + +.alerts__toggler + width: 40px + height: 40px + position: absolute + top: 400px + left: 50% + transform: translateX(-50%) + cursor: pointer + + &::before + @extend .fas + + content: fa-content($fa-var-chevron-up) + position: absolute + left: 50% + top: 0 + height: 30px + display: flex + align-items: center + justify-content: center + width: 30px + color: var(--color-grey) + font-size: 30px + transform: translateX(-50%) + + &:hover::before + color: var(--color-grey-medium) + +.alerts--elevated + z-index: 1000 + +.alerts__toggler--visible + top: -40px + opacity: 1 + transition: top 0.5s cubic-bezier(0.73, 1.25, 0.61, 1), opacity 0.5s cubic-bezier(0.73, 1.25, 0.61, 1) + +@media (max-width: 425px) + .alerts + left: 5% + +.alert + position: relative + display: block + background-color: var(--color-lightblack) + font-size: 1rem + color: var(--color-lightwhite) + z-index: 0 + padding: 0 50px + padding-right: 60px + animation: slide-in-alert .2s ease-out forwards + margin-bottom: 10px + transition: margin-bottom .2s ease-out + +.alert a + color: var(--color-lightwhite) + + &:hover + color: var(--color-grey) + +@keyframes slide-in-alert + from + transform: translateY(120%) + + to + transform: translateY(0) + +@keyframes slide-out-alert + from + transform: translateY(0) + max-height: 200px + + to + transform: translateY(250%) + opacity: 0 + max-height: 0 + overflow: hidden + +@media (min-width: 425px) + .alert + max-width: 400px + +.alert--invisible + animation: slide-out-alert .2s ease-out forwards + margin-bottom: 0 + +.alert__content + padding: 8px 0 + min-height: 40px + position: relative + display: flex + font-weight: 600 + align-items: center + text-align: left + +.alert__icon + text-align: right + position: absolute + left: 0px + top: 0 + width: 50px + height: 100% + z-index: 40 + + &::before + position: absolute + font-size: 24px + top: 50% + left: 50% + display: flex + align-items: center + justify-content: center + transform: translate(-50%, -50%) + border-radius: 50% + width: 30px + height: 30px + +.alert__closer + cursor: pointer + text-align: right + position: absolute + right: 0px + top: 0 + width: 60px + height: 100% + transition: all .3s ease + z-index: 40 + + &:hover + transform: scale(1.05, 1.05) + + &::before + box-shadow: 0 0 4px white + background-color: rgba(255, 255, 255, 0.1) + color: white + + &::before + @extend .fas + + content: fa-content($fa-var-times) + position: absolute + top: 50% + left: 50% + display: flex + align-items: center + justify-content: center + transform: translate(-50%, -50%) + border-radius: 50% + width: 30px + height: 30px + transition: all .15s ease + +@media (max-width: 768px) + .alert__closer + width: 40px + +.alert-success + background-color: var(--color-success) + + // .alert__icon::before { + // --alert-icon-default: '\f058'; + // } + +.alert-warning + background-color: var(--color-warning) + + // .alert__icon::before { + // --alert-icon-default: '\f06a'; + // } + +.alert-error + background-color: var(--color-error) + + // .alert__icon::before { + // --alert-icon-default: '\f071'; + // } diff --git a/frontend/src/utils/alerts/alerts.scss b/frontend/src/utils/alerts/alerts.scss deleted file mode 100644 index ee800d40a..000000000 --- a/frontend/src/utils/alerts/alerts.scss +++ /dev/null @@ -1,221 +0,0 @@ -@use "../../common" as *; - -.alerts { - position: fixed; - bottom: 0; - right: 5%; - z-index: 20; - text-align: right; - display: flex; - flex-direction: column; -} - -.alerts__toggler { - width: 40px; - height: 40px; - position: absolute; - top: 400px; - left: 50%; - transform: translateX(-50%); - cursor: pointer; - - &::before { - @extend .fas; - content: fa-content($fa-var-chevron-up); - position: absolute; - left: 50%; - top: 0; - height: 30px; - display: flex; - align-items: center; - justify-content: center; - width: 30px; - color: var(--color-grey); - font-size: 30px; - transform: translateX(-50%); - } - - &:hover::before { - color: var(--color-grey-medium); - } -} - -.alerts--elevated { - z-index: 1000; -} - -.alerts__toggler--visible { - top: -40px; - opacity: 1; - transition: top .5s cubic-bezier(0.73, 1.25, 0.61, 1), - opacity .5s cubic-bezier(0.73, 1.25, 0.61, 1); -} - -@media (max-width: 425px) { - - .alerts { - left: 5%; - } -} - -.alert { - position: relative; - display: block; - background-color: var(--color-lightblack); - font-size: 1rem; - color: var(--color-lightwhite); - z-index: 0; - padding: 0 50px; - padding-right: 60px; - animation: slide-in-alert .2s ease-out forwards; - margin-bottom: 10px; - transition: margin-bottom .2s ease-out; -} - -.alert a { - color: var(--color-lightwhite); - - &:hover { - color: var(--color-grey); - } -} - -@keyframes slide-in-alert { - from { - transform: translateY(120%); - } - to { - transform: translateY(0); - } -} - -@keyframes slide-out-alert { - from { - transform: translateY(0); - max-height: 200px; - } - to { - transform: translateY(250%); - opacity: 0; - max-height: 0; - overflow: hidden; - } -} - -@media (min-width: 425px) { - - .alert { - max-width: 400px; - } -} - -.alert--invisible { - animation: slide-out-alert .2s ease-out forwards; - margin-bottom: 0; -} - -.alert__content { - padding: 8px 0; - min-height: 40px; - position: relative; - display: flex; - font-weight: 600; - align-items: center; - text-align: left; -} - -.alert__icon { - text-align: right; - position: absolute; - left: 0px; - top: 0; - width: 50px; - height: 100%; - z-index: 40; - - &::before { - position: absolute; - font-size: 24px; - top: 50%; - left: 50%; - display: flex; - align-items: center; - justify-content: center; - transform: translate(-50%, -50%); - border-radius: 50%; - width: 30px; - height: 30px; - } -} - -.alert__closer { - cursor: pointer; - text-align: right; - position: absolute; - right: 0px; - top: 0; - width: 60px; - height: 100%; - transition: all .3s ease; - z-index: 40; - - &:hover { - transform: scale(1.05, 1.05); - - &::before { - box-shadow: 0 0 4px white; - background-color: rgba(255, 255, 255, 0.1); - color: white; - } - } - - &::before { - @extend .fas; - content: fa-content($fa-var-times); - position: absolute; - top: 50%; - left: 50%; - display: flex; - align-items: center; - justify-content: center; - transform: translate(-50%, -50%); - border-radius: 50%; - width: 30px; - height: 30px; - transition: all .15s ease; - } -} - -@media (max-width: 768px) { - - .alert__closer { - width: 40px; - } -} - -.alert-success { - background-color: var(--color-success); - - /* .alert__icon::before { - * --alert-icon-default: '\f058'; - * } - */ -} - -.alert-warning { - background-color: var(--color-warning); - - /* .alert__icon::before { - * --alert-icon-default: '\f06a'; - * } - */ -} - -.alert-error { - background-color: var(--color-error); - - /* .alert__icon::before { - * --alert-icon-default: '\f071'; - * } - */ -} diff --git a/frontend/src/utils/asidenav/asidenav.js b/frontend/src/utils/asidenav/asidenav.js index 2964e1617..6bf425ffa 100644 --- a/frontend/src/utils/asidenav/asidenav.js +++ b/frontend/src/utils/asidenav/asidenav.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './asidenav.scss'; +import './asidenav.sass'; const FAVORITES_BTN_CLASS = 'navbar__list-item--favorite'; const FAVORITES_BTN_ACTIVE_CLASS = 'navbar__list-item--active'; diff --git a/frontend/src/utils/asidenav/asidenav.sass b/frontend/src/utils/asidenav/asidenav.sass new file mode 100644 index 000000000..b9beb15b4 --- /dev/null +++ b/frontend/src/utils/asidenav/asidenav.sass @@ -0,0 +1,330 @@ +.main__aside + position: fixed + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3) + z-index: 1 + top: 0 + left: 0 + width: var(--asidenav-width-lg, 20%) + height: 100% + flex: 0 0 0 + flex-basis: var(--asidenav-width-lg, 20%) + transition: all .2s ease-out + + &::before + position: absolute + z-index: -1 + left: 0 + top: 0 + width: 100% + height: 100% + background-color: var(--color-dark) + opacity: 0.05 + + &::after + content: '' + position: absolute + z-index: -2 + left: 0 + top: 0 + width: 100% + height: 100% + background-color: var(--color-grey-light) + +@media (max-width: 425px) + .main__aside + position: fixed + top: var(--header-height-collapsed) + left: 0 + right: 0 + bottom: 0 + height: 100% !important + width: 100% + z-index: 5 + overflow: hidden + transform: translateX(-110%) + transition: transform .2s ease-out + + &.main__aside--expanded + transform: translateX(0%) + + .asidenav__box-subtitle + display: inherit + + .asidenav__box-title + font-size: 18px + padding-left: 10px + + .asidenav__box-subtitle + display: none + +@media (min-width: 1200px) + .main__aside + width: var(--asidenav-width-xl, 250px) + +.asidenav + color: var(--color-font) + min-height: calc(100% - var(--header-height)) + height: 400px + overflow-y: auto + overflow-x: hidden + + &::-webkit-scrollbar + width: 0 + +.asidenav__box + transition: opacity .2s ease + + + .asidenav__box + margin-top: 10px + +.asidenav__box-title + padding: 7px 13px + margin-top: 30px + background-color: transparent + transition: all .2s ease + padding: 10px 13px + margin: 0 + border-bottom: 1px solid var(--color-grey) + + .asidenav-term-identifier--long + display: inherit + + .asidenav-term-identifier--short + display: none + +.asidenav__box-subtitle + color: var(--color-fontsec) + font-size: 0.9rem + font-weight: 600 + padding: 0 13px + margin: 3px 0 + +// LOGO + +.asidenav__logo + height: var(--header-height) + display: flex + align-items: center + +@media (max-width: 768px) + .asidenav__logo + display: none + +.asidenav__logo-link + flex: 1 + top: 10px + left: 20px + height: 80px + padding: 0 20px + display: flex + flex-basis: var(--asidenav-width-xl, 250px) + font-size: 16px + align-items: center + color: var(--color-dark) + transform-origin: left + + &:hover + color: var(--color-primary) + +.asidenav__logo-lmu + width: 80px + height: 100% + +.asidenav__logo-uni2work + display: flex + align-items: flex-end + min-width: 70px + margin-left: 12px + text-transform: uppercase + width: 100% + height: 100% + padding: 2px 4px + border: 1px solid currentColor + letter-spacing: 2px + background-color: white + transition: background-color .3s ease + +@media (max-width: 1199px) + .asidenav__logo-link + flex-basis: var(--asidenav-width-lg, 20%) + font-size: 16px + + .asidenav__logo-lmu + display: none + + .asidenav__logo-uni2work + margin-left: 0 + +// SEAL + +.asidenav__sigillum + position: absolute + bottom: -40px + right: 25px + opacity: 0.1 + + > img + width: 350px + +@media (max-width: 768px) + .asidenav__sigillum + right: auto + left: 50% + transform: translateX(-50%) + +// LIST-ITEM + +.asidenav__list-item + color: var(--color-font) + display: flex + flex-direction: column + justify-content: flex-start + align-items: center + + &:not(.asidenav__list-item--active):hover + background-color: var(--color-lightwhite) + + > .asidenav__link-wrapper + color: var(--color-font) + + &:hover + .asidenav__link-shorthand + // transform: scale(1.05, 1.0); + // transform-origin: right; + text-shadow: none + + .asidenav__nested-list-wrapper + display: block + +// small list-item-padding for medium to large screens +@media (min-width: 769px) + .asidenav__list-item + padding-left: 10px + +.asidenav__list-item--active + background-color: var(--color-lightwhite) + + .asidenav__link-wrapper + color: var(--color-link) + + .asidenav__link-shorthand + transform: scale(1.05, 1) + transform-origin: right + text-shadow: none + +.asidenav__link-wrapper + position: relative + display: flex + flex: 1 + align-items: center + padding: 8px 3px + justify-content: flex-start + color: var(--color-font) + width: 100% + z-index: 1 + +.asidenav__link-shorthand + display: none + +.asidenav__link-label + line-height: 1 + +// hover sub-menus +.asidenav__nested-list-wrapper + position: absolute + z-index: 10 + display: none + color: var(--color-font) + background-color: var(--color-grey-light) + box-shadow: 1px 1px 1px 0px var(--color-grey) + +.asidenav__nested-list + min-width: 200px + +@media (max-width: 425px) + .asidenav__list-item + padding-left: 10px + + .asidenav__nested-list + display: none + +.asidenav__nested-list-item + position: relative + + &:hover + background-color: var(--color-lightwhite) + + .asidenav__link-wrapper + padding-left: 13px + padding-right: 13px + transition: all .2s ease + color: var(--color-font) + +// TABLET +@media (min-width: 426px) and (max-width: 768px) + .main__aside + width: var(--asidenav-width-md, 50px) + flex-basis: var(--asidenav-width-md, 50px) + overflow: hidden + min-height: calc(100% - var(--header-height-collapsed)) + top: var(--header-height-collapsed) + + .asidenav__box-title + width: var(--asidenav-width-md, 50px) + font-size: 18px + text-align: center + padding: 10px 1px + word-break: break-all + background-color: var(--color-dark) + color: var(--color-lightwhite) + + &:hover + background-color: var(--color-darker) + + &::before + display: none + + .asidenav-term-identifier--long + display: none + + .asidenav-term-identifier--short + display: inherit + + .asidenav__box-subtitle + padding: 0 3px + font-size: 0.85rem + + .asidenav__link-shorthand + display: flex + position: static + height: 50px + width: var(--asidenav-width-md, 50px) + text-align: center + opacity: 1 + font-size: 15px + line-height: 1em + margin-right: 13px + flex-shrink: 0 + padding: 1px + outline: 1px solid white + word-break: break-all + align-items: center + justify-content: center + + .asidenav__list-item + padding-left: 0 + + + .asidenav__list-item + margin: 0 + + .asidenav__link-wrapper + color: var(--color-font) + padding: 0 + + .asidenav__nested-list, + .asidenav__link-label + display: none + + .asidenav__list-item--active + .asidenav__link-wrapper + background-color: var(--color-lightwhite) diff --git a/frontend/src/utils/asidenav/asidenav.scss b/frontend/src/utils/asidenav/asidenav.scss deleted file mode 100644 index 477292d38..000000000 --- a/frontend/src/utils/asidenav/asidenav.scss +++ /dev/null @@ -1,406 +0,0 @@ -.main__aside { - position: fixed; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - z-index: 1; - top: 0; - left: 0; - width: var(--asidenav-width-lg, 20%); - height: 100%; - flex: 0 0 0; - flex-basis: var(--asidenav-width-lg, 20%); - transition: all .2s ease-out; - - &::before { - position: absolute; - z-index: -1; - left: 0; - top: 0; - width: 100%; - height: 100%; - background-color: var(--color-dark); - opacity: 0.05; - } - - &::after { - content: ''; - position: absolute; - z-index: -2; - left: 0; - top: 0; - width: 100%; - height: 100%; - background-color: var(--color-grey-light); - } -} - -@media (max-width: 425px) { - - .main__aside { - position: fixed; - top: var(--header-height-collapsed); - left: 0; - right: 0; - bottom: 0; - height: 100% !important; - width: 100%; - z-index: 5; - overflow: hidden; - transform: translateX(-110%); - transition: transform .2s ease-out; - - &.main__aside--expanded { - transform: translateX(0%); - - .asidenav__box-subtitle { - display: inherit; - } - } - - .asidenav__box-title { - font-size: 18px; - padding-left: 10px; - } - - .asidenav__box-subtitle { - display: none; - } - } -} - -@media (min-width: 1200px) { - .main__aside { - width: var(--asidenav-width-xl, 250px) - } -} - -.asidenav { - color: var(--color-font); - min-height: calc(100% - var(--header-height)); - height: 400px; - overflow-y: auto; - overflow-x: hidden; - - &::-webkit-scrollbar { - width: 0; - } -} - -.asidenav__box { - transition: opacity .2s ease; - - + .asidenav__box { - margin-top: 10px; - } -} - -.asidenav__box-title { - padding: 7px 13px; - margin-top: 30px; - background-color: transparent; - transition: all .2s ease; - padding: 10px 13px; - margin: 0; - border-bottom: 1px solid var(--color-grey); - - .asidenav-term-identifier--long { - display: inherit; - } - .asidenav-term-identifier--short { - display: none; - } -} - -.asidenav__box-subtitle { - color: var(--color-fontsec); - font-size: 0.9rem; - font-weight: 600; - padding: 0 13px; - margin: 3px 0; -} - -/* LOGO */ - -.asidenav__logo { - height: var(--header-height); - display: flex; - align-items: center; -} - -@media (max-width: 768px) { - - .asidenav__logo { - display: none; - } -} - -.asidenav__logo-link { - flex: 1; - top: 10px; - left: 20px; - height: 80px; - padding: 0 20px; - display: flex; - flex-basis: var(--asidenav-width-xl, 250px); - font-size: 16px; - align-items: center; - color: var(--color-dark); - transform-origin: left; - - &:hover { - color: var(--color-primary); - } -} - -.asidenav__logo-lmu { - width: 80px; - height: 100%; -} - -.asidenav__logo-uni2work { - display: flex; - align-items: flex-end; - min-width: 70px; - margin-left: 12px; - text-transform: uppercase; - width: 100%; - height: 100%; - padding: 2px 4px; - border: 1px solid currentColor; - letter-spacing: 2px; - background-color: white; - transition: background-color .3s ease; -} - -@media (max-width: 1199px) { - - .asidenav__logo-link { - flex-basis: var(--asidenav-width-lg, 20%); - font-size: 16px; - } - - .asidenav__logo-lmu { - display: none; - } - - .asidenav__logo-uni2work { - margin-left: 0; - } -} - -/* SEAL */ - -.asidenav__sigillum { - position: absolute; - bottom: -40px; - right: 25px; - opacity: 0.1; - - > img { - width: 350px; - } -} - -@media (max-width: 768px) { - .asidenav__sigillum { - right: auto; - left: 50%; - transform: translateX(-50%); - } -} - -/* LIST-ITEM */ - -.asidenav__list-item { - color: var(--color-font); - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - - &:not(.asidenav__list-item--active):hover { - background-color: var(--color-lightwhite); - - > .asidenav__link-wrapper { - color: var(--color-font); - } - } - - &:hover { - - .asidenav__link-shorthand { - /* transform: scale(1.05, 1.0); - * transform-origin: right; - */ - text-shadow: none; - } - - .asidenav__nested-list-wrapper { - display: block; - } - } -} - -/* small list-item-padding for medium to large screens */ -@media (min-width: 769px) { - .asidenav__list-item { - padding-left: 10px; - } -} - -.asidenav__list-item--active { - background-color: var(--color-lightwhite); - - .asidenav__link-wrapper { - color: var(--color-link); - } - - .asidenav__link-shorthand { - transform: scale(1.05, 1.0); - transform-origin: right; - text-shadow: none; - } -} - -.asidenav__link-wrapper { - position: relative; - display: flex; - flex: 1; - align-items: center; - padding: 8px 3px; - justify-content: flex-start; - color: var(--color-font); - width: 100%; - z-index: 1; -} - -.asidenav__link-shorthand { - display: none; -} - -.asidenav__link-label { - line-height: 1; -} - -/* hover sub-menus */ -.asidenav__nested-list-wrapper { - position: absolute; - z-index: 10; - display: none; - color: var(--color-font); - background-color: var(--color-grey-light); - box-shadow: 1px 1px 1px 0px var(--color-grey); -} - -.asidenav__nested-list { - min-width: 200px; -} - -@media (max-width: 425px) { - .asidenav__list-item { - padding-left: 10px; - } - - .asidenav__nested-list { - display: none; - } -} - -.asidenav__nested-list-item { - position: relative; - - &:hover { - background-color: var(--color-lightwhite); - } - - .asidenav__link-wrapper { - padding-left: 13px; - padding-right: 13px; - transition: all .2s ease; - color: var(--color-font); - } -} - -/* TABLET */ -@media (min-width: 426px) and (max-width: 768px) { - - .main__aside { - width: var(--asidenav-width-md, 50px); - flex-basis: var(--asidenav-width-md, 50px); - overflow: hidden; - min-height: calc(100% - var(--header-height-collapsed)); - top: var(--header-height-collapsed); - - .asidenav__box-title { - width: var(--asidenav-width-md, 50px); - font-size: 18px; - text-align: center; - padding: 10px 1px; - word-break: break-all; - background-color: var(--color-dark); - color: var(--color-lightwhite); - - &:hover { - background-color: var(--color-darker); - } - - &::before { - display: none; - } - - .asidenav-term-identifier--long { - display: none; - } - .asidenav-term-identifier--short { - display: inherit; - } - } - - .asidenav__box-subtitle { - padding: 0 3px; - font-size: 0.85rem; - } - - .asidenav__link-shorthand { - display: flex; - position: static; - height: 50px; - width: var(--asidenav-width-md, 50px); - text-align: center; - opacity: 1; - font-size: 15px; - line-height: 1em; - margin-right: 13px; - flex-shrink: 0; - padding: 1px; - outline: 1px solid white; - word-break: break-all; - align-items: center; - justify-content: center; - } - - .asidenav__list-item { - padding-left: 0; - - + .asidenav__list-item { - margin: 0; - } - } - - .asidenav__link-wrapper { - color: var(--color-font); - padding: 0; - } - - .asidenav__nested-list, - .asidenav__link-label { - display: none; - } - - .asidenav__list-item--active { - - .asidenav__link-wrapper { - background-color: var(--color-lightwhite); - } - } - } -} diff --git a/frontend/src/utils/async-form/async-form.js b/frontend/src/utils/async-form/async-form.js index f366f9eae..6c0da95c0 100644 --- a/frontend/src/utils/async-form/async-form.js +++ b/frontend/src/utils/async-form/async-form.js @@ -1,6 +1,6 @@ import { Utility } from '../../core/utility'; import { Datepicker } from '../form/datepicker'; -import './async-form.scss'; +import './async-form.sass'; const ASYNC_FORM_INITIALIZED_CLASS = 'check-all--initialized'; const ASYNC_FORM_RESPONSE_CLASS = 'async-form__response'; diff --git a/frontend/src/utils/async-form/async-form.sass b/frontend/src/utils/async-form/async-form.sass new file mode 100644 index 000000000..c4e54719d --- /dev/null +++ b/frontend/src/utils/async-form/async-form.sass @@ -0,0 +1,71 @@ +.async-form__response + margin: 20px 0 + position: relative + width: 100% + font-size: 18px + text-align: center + padding-top: 60px + +.async-form__response::before, +.async-form__response::after + position: absolute + top: 0px + left: 50% + display: block + +.async-form__response--success::before + content: '' + width: 17px + height: 28px + border: solid #069e04 + border-width: 0 5px 5px 0 + transform: translateX(-50%) rotate(45deg) + +.async-form__response--info::before + content: '' + width: 5px + height: 30px + top: 10px + background-color: #777 + transform: translateX(-50%) + +.async-form__response--info::after + content: '' + width: 5px + height: 5px + background-color: #777 + transform: translateX(-50%) + +.async-form__response--warning::before + content: '' + width: 5px + height: 30px + background-color: rgb(255, 187, 0) + transform: translateX(-50%) + +.async-form__response--warning::after + content: '' + width: 5px + height: 5px + top: 35px + background-color: rgb(255, 187, 0) + transform: translateX(-50%) + +.async-form__response--error::before + content: '' + width: 5px + height: 40px + background-color: #940d0d + transform: translateX(-50%) rotate(-45deg) + +.async-form__response--error::after + content: '' + width: 5px + height: 40px + background-color: #940d0d + transform: translateX(-50%) rotate(45deg) + +.async-form--loading + opacity: 0.1 + transition: opacity 800ms ease-out + pointer-events: none diff --git a/frontend/src/utils/async-form/async-form.scss b/frontend/src/utils/async-form/async-form.scss deleted file mode 100644 index bd5a97a41..000000000 --- a/frontend/src/utils/async-form/async-form.scss +++ /dev/null @@ -1,78 +0,0 @@ -.async-form__response { - margin: 20px 0; - position: relative; - width: 100%; - font-size: 18px; - text-align: center; - padding-top: 60px; -} - -.async-form__response::before, -.async-form__response::after { - position: absolute; - top: 0px; - left: 50%; - display: block; -} - -.async-form__response--success::before { - content: ''; - width: 17px; - height: 28px; - border: solid #069e04; - border-width: 0 5px 5px 0; - transform: translateX(-50%) rotate(45deg); -} - -.async-form__response--info::before { - content: ''; - width: 5px; - height: 30px; - top: 10px; - background-color: #777; - transform: translateX(-50%); -} -.async-form__response--info::after { - content: ''; - width: 5px; - height: 5px; - background-color: #777; - transform: translateX(-50%); -} - -.async-form__response--warning::before { - content: ''; - width: 5px; - height: 30px; - background-color: rgb(255, 187, 0); - transform: translateX(-50%); -} -.async-form__response--warning::after { - content: ''; - width: 5px; - height: 5px; - top: 35px; - background-color: rgb(255, 187, 0); - transform: translateX(-50%); -} - -.async-form__response--error::before { - content: ''; - width: 5px; - height: 40px; - background-color: #940d0d; - transform: translateX(-50%) rotate(-45deg); -} -.async-form__response--error::after { - content: ''; - width: 5px; - height: 40px; - background-color: #940d0d; - transform: translateX(-50%) rotate(45deg); -} - -.async-form--loading { - opacity: 0.1; - transition: opacity 800ms ease-out; - pointer-events: none; -} diff --git a/frontend/src/utils/async-table/async-table-filter.sass b/frontend/src/utils/async-table/async-table-filter.sass new file mode 100644 index 000000000..2108e9066 --- /dev/null +++ b/frontend/src/utils/async-table/async-table-filter.sass @@ -0,0 +1,4 @@ +.async-table-filter--loading + opacity: 0.7 + pointer-events: none + transition: opacity 400ms ease-out diff --git a/frontend/src/utils/async-table/async-table-filter.scss b/frontend/src/utils/async-table/async-table-filter.scss deleted file mode 100644 index 794240f3f..000000000 --- a/frontend/src/utils/async-table/async-table-filter.scss +++ /dev/null @@ -1,5 +0,0 @@ -.async-table-filter--loading { - opacity: 0.7; - pointer-events: none; - transition: opacity 400ms ease-out; -} diff --git a/frontend/src/utils/async-table/async-table.js b/frontend/src/utils/async-table/async-table.js index 80dadca3a..f2d1248ab 100644 --- a/frontend/src/utils/async-table/async-table.js +++ b/frontend/src/utils/async-table/async-table.js @@ -3,8 +3,8 @@ import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-mana import { Datepicker } from '../form/datepicker'; import { HttpClient } from '../../services/http-client/http-client'; import * as debounce from 'lodash.debounce'; -import './async-table-filter.scss'; -import './async-table.scss'; +import './async-table-filter.sass'; +import './async-table.sass'; const INPUT_DEBOUNCE = 600; const HEADER_HEIGHT = 80; diff --git a/frontend/src/utils/async-table/async-table.sass b/frontend/src/utils/async-table/async-table.sass new file mode 100644 index 000000000..3b885cdbe --- /dev/null +++ b/frontend/src/utils/async-table/async-table.sass @@ -0,0 +1,4 @@ +.async-table--loading + opacity: 0.7 + pointer-events: none + transition: opacity 400ms ease-out diff --git a/frontend/src/utils/async-table/async-table.scss b/frontend/src/utils/async-table/async-table.scss deleted file mode 100644 index 9766daa84..000000000 --- a/frontend/src/utils/async-table/async-table.scss +++ /dev/null @@ -1,5 +0,0 @@ -.async-table--loading { - opacity: 0.7; - pointer-events: none; - transition: opacity 400ms ease-out; -} diff --git a/frontend/src/utils/course-teaser/course-teaser.js b/frontend/src/utils/course-teaser/course-teaser.js index 7f8c32630..889e7937a 100644 --- a/frontend/src/utils/course-teaser/course-teaser.js +++ b/frontend/src/utils/course-teaser/course-teaser.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './course-teaser.scss'; +import './course-teaser.sass'; var COURSE_TEASER_INITIALIZED_CLASS = 'course-teaser--initialized'; diff --git a/frontend/src/utils/course-teaser/course-teaser.sass b/frontend/src/utils/course-teaser/course-teaser.sass new file mode 100644 index 000000000..56831de4f --- /dev/null +++ b/frontend/src/utils/course-teaser/course-teaser.sass @@ -0,0 +1,246 @@ +[uw-course-teaser] + --course-border-color: var(--color-grey) + --course-padding-hori: 10px + --course-padding-vert: 12px + display: grid + position: relative + grid-gap: 5px 7px + grid-template-columns: 130px 30px 1fr 60px + grid-template-areas: 'shrthnd . title chevron' 'shrthnd smstr school chevron' '. . rgstrd . ' 'tutor tutor name . ' 'duedate duedate date . ' 'dscrptn dscrptn dscrptn dscrptn' + padding: var(--course-padding-vert) var(--course-padding-hori) + transition: background-color .1s ease-out + cursor: pointer + + &:hover + background-color: var(--course-bg-color) + + + [uw-course-teaser] + border-top: 1px solid var(--course-border-color) + + @media (max-width: 768px) + grid-template-columns: 140px 1fr 30px + grid-template-areas: 'shrthnd title chevron' 'shrthnd title . ' 'smstr school school ' '. rgstrd rgstrd ' 'tutor name name ' 'duedate date date ' 'dscrptn dscrptn dscrptn' + + @media (max-width: 426px) + grid-template-columns: 1fr + grid-template-areas: 'shrthnd' 'title' 'smstr' 'school' 'rgstrd' 'tutor' 'name' 'duedate' 'date' 'dscrptnlbl' 'dscrptn' 'chevron' + +.course-teaser__not-expandable + cursor: initial + +// chevron +.course-teaser__chevron + position: relative + padding: 10px + grid-area: chevron + justify-self: center + align-self: center + width: 100% + height: 100% + cursor: pointer + + &::before + content: '' + position: absolute + display: block + margin-top: -7.35px + margin-left: -7.35px + + // visually centered + border-width: 0 3px 3px 0 + width: 8px + height: 8px + top: 50% + left: 50% + border-color: var(--color-fontsec) + border-style: solid + transform: rotate(135deg) + transform-origin: 7.25px 7.25px + + // rotate about visual center + transition: all .2s ease-out + + &:hover::before + transform: scale(1.4) rotate(45deg) + + @media (max-width: 768px) + justify-self: end + width: auto + + &::before + position: initial + + @media (max-width: 426px) + &::before + transform: rotate(45deg) + margin-left: -7.35px + + &:hover::before + transform: scale(1.4) rotate(45deg) + +// semester +.course-teaser__semester + grid-area: smstr + justify-self: end + + a + color: var(--color-fontsec) + + @media (max-width: 768px) + justify-self: initial + +// shorthand +.course-teaser__shorthand + position: relative + grid-area: shrthnd + font-size: 2rem + line-height: 1.25 + min-height: calc(2rem * 1.25) + + > a + position: absolute + height: 100% + width: 100% + overflow: hidden + text-overflow: ellipsis + white-space: nowrap + word-break: break-any + text-decoration: none !important + + // sry. + font-weight: 600 + color: var(--color-grey-medium) + + // @media (max-width: 768px) { + position: initial; + } + +// title +.course-teaser__title + grid-area: title + font-size: 1.2rem + align-self: baseline + +// registration +.course-teaser__registration + grid-area: rgstrd + color: var(--color-fontsec) + font-weight: bold + +// school +.course-teaser__school + grid-area: school + + a + color: var(--color-fontsec) + +// duedate +.course-teaser__duedate + grid-area: date + +// lecturer +.course-teaser__lecturer + grid-area: name + +// description +.course-teaser__description + grid-area: dscrptn + max-height: 75vh + overflow: auto + +// show description only as dots (overflow text-overflow) and only show when expanded. No "hidden fiddling" + +// labels +.course-teaser__lecturer-label + grid-area: tutor + +.course-teaser__duedate-label + grid-area: duedate + +.course-teaser__description-label + grid-area: dscrptnlbl + +.course-teaser__lecturer-label, +.course-teaser__description-label, +.course-teaser__duedate-label + justify-self: end + color: var(--color-fontsec) + font-style: italic + + @media (max-width: 768px) + justify-self: initial + + @media (max-width: 426px) + margin-top: 7px + font-weight: bold + font-style: initial + +// hidden in closed state +.course-teaser__description, +.course-teaser__description-label + display: none + +// expanded courses +.course-teaser__expanded + cursor: initial + + .course-teaser__chevron + &::before + transform: rotate(45deg) + + &:hover::before + transform: scale(1.4) rotate(135deg) + + @media (max-width: 426px) + &::before + transform: rotate(225deg) + + &:hover::before + transform: scale(1.4) rotate(225deg) + + .course-teaser__school-label, + .course-teaser__school, + .course-teaser__duedate-label, + .course-teaser__duedate, + .course-teaser__description + display: block + + @media (max-width: 426px) + .course-teaser__description-label + display: block + +// course teaser: header styling +.course-teaser-header + padding-top: 10px + padding-bottom: 20px + line-height: 1.4 + max-width: 85vw + + .course-header + float: left + background-color: var(--color-dark) + position: relative + font-size: 16px + color: #fff + padding-top: 10px + padding-bottom: 10px + padding-left: 10px + padding-right: 35px + margin-bottom: 10px + font-weight: bold + text-align: left + border-radius: 20px 20px 20px 20px / 50% 50% 50% 50% + margin-right: 30px + + .course-header-link + color: white + font-weight: bold + text-decoration: none + + &:hover + color: inherit + +.course-teaser-header:after + content: "" + display: table + clear: both diff --git a/frontend/src/utils/course-teaser/course-teaser.scss b/frontend/src/utils/course-teaser/course-teaser.scss deleted file mode 100644 index 68576fb1e..000000000 --- a/frontend/src/utils/course-teaser/course-teaser.scss +++ /dev/null @@ -1,317 +0,0 @@ -[uw-course-teaser] { - --course-border-color: var(--color-grey); - --course-padding-hori: 10px; - --course-padding-vert: 12px; - - display: grid; - position: relative; - grid-gap: 5px 7px; - grid-template-columns: 130px 30px 1fr 60px; - grid-template-areas: - 'shrthnd . title chevron' - 'shrthnd smstr school chevron' - '. . rgstrd . ' - 'tutor tutor name . ' - 'duedate duedate date . ' - 'dscrptn dscrptn dscrptn dscrptn'; - padding: var(--course-padding-vert) var(--course-padding-hori); - transition: background-color .1s ease-out; - cursor: pointer; - - &:hover { - background-color: var(--course-bg-color); - } - - + [uw-course-teaser] { - border-top: 1px solid var(--course-border-color); - } - - @media (max-width: 768px) { - grid-template-columns: 140px 1fr 30px; - grid-template-areas: - 'shrthnd title chevron' - 'shrthnd title . ' - 'smstr school school ' - '. rgstrd rgstrd ' - 'tutor name name ' - 'duedate date date ' - 'dscrptn dscrptn dscrptn'; - } - - @media (max-width: 426px) { - grid-template-columns: 1fr; - grid-template-areas: - 'shrthnd' - 'title' - 'smstr' - 'school' - 'rgstrd' - 'tutor' - 'name' - 'duedate' - 'date' - 'dscrptnlbl' - 'dscrptn' - 'chevron'; - } -} - -.course-teaser__not-expandable { - cursor: initial; -} - -/* chevron */ -.course-teaser__chevron { - position: relative; - padding: 10px; - grid-area: chevron; - justify-self: center; - align-self: center; - width: 100%; - height: 100%; - cursor: pointer; - - &::before { - content: ''; - position: absolute; - display: block; - margin-top: -7.35px; - margin-left: -7.35px; /* visually centered */ - border-width: 0 3px 3px 0; - width: 8px; - height: 8px; - top: 50%; - left: 50%; - border-color: var(--color-fontsec); - border-style: solid; - transform: rotate(135deg); - transform-origin: 7.25px 7.25px; /* rotate about visual center */ - transition: all .2s ease-out; - } - - &:hover::before { - transform: scale(1.4) rotate(45deg); - } - - @media (max-width: 768px) { - justify-self: end; - width: auto; - - &::before { - position: initial; - } - } - - @media (max-width: 426px) { - &::before { - transform: rotate(45deg); - margin-left: -7.35px; - } - - &:hover::before { - transform: scale(1.4) rotate(45deg); - } - } -} - -/* semester */ -.course-teaser__semester { - grid-area: smstr; - justify-self: end; - a { - color: var(--color-fontsec); - } - - @media (max-width: 768px) { - justify-self: initial; - } -} - -/* shorthand */ -.course-teaser__shorthand { - position: relative; - grid-area: shrthnd; - font-size: 2rem; - line-height: 1.25; - min-height: calc(2rem * 1.25); - - > a { - position: absolute; - height: 100%; - width: 100%; - overflow: hidden; - - text-overflow: ellipsis; - white-space: nowrap; - word-break: break-any; - - text-decoration: none !important; /* sry. */ - font-weight: 600; - color: var(--color-grey-medium); - } - - /* @media (max-width: 768px) { - * position: initial; - * } - */ -} - -/* title */ -.course-teaser__title { - grid-area: title; - font-size: 1.2rem; - align-self: baseline; -} - - /* registration */ -.course-teaser__registration { - grid-area: rgstrd; - color: var(--color-fontsec); - font-weight: bold; -} - -/* school */ -.course-teaser__school { - grid-area: school; - a { - color: var(--color-fontsec); - } -} - -/* duedate */ -.course-teaser__duedate { - grid-area: date; -} - -/* lecturer */ -.course-teaser__lecturer { - grid-area: name; -} - -/* description */ -.course-teaser__description { - grid-area: dscrptn; - max-height: 75vh; - overflow: auto; -} - -/* show description only as dots (overflow text-overflow) and only show when expanded. No "hidden fiddling" */ - -/* labels */ -.course-teaser__lecturer-label { - grid-area: tutor; -} - -.course-teaser__duedate-label { - grid-area: duedate; -} - -.course-teaser__description-label { - grid-area: dscrptnlbl; -} - -.course-teaser__lecturer-label, -.course-teaser__description-label, -.course-teaser__duedate-label { - justify-self: end; - color: var(--color-fontsec); - font-style: italic; - - @media (max-width: 768px) { - justify-self: initial; - } - - @media (max-width: 426px) { - margin-top: 7px; - font-weight: bold; - font-style: initial; - } -} - -/* hidden in closed state */ -.course-teaser__description, -.course-teaser__description-label { - display: none; -} - -/* expanded courses */ -.course-teaser__expanded { - cursor: initial; - - .course-teaser__chevron { - &::before { - transform: rotate(45deg); - } - - &:hover::before { - transform: scale(1.4) rotate(135deg); - } - - @media (max-width: 426px) { - &::before { - transform: rotate(225deg); - } - - &:hover::before { - transform: scale(1.4) rotate(225deg); - } - } - } - - .course-teaser__school-label, - .course-teaser__school, - .course-teaser__duedate-label, - .course-teaser__duedate, - .course-teaser__description { - display: block; - } - - @media (max-width: 426px) { - .course-teaser__description-label { - display: block; - } - } -} - -/* -course teaser: header styling -*/ -.course-teaser-header { - padding-top: 10px; - padding-bottom: 20px; - line-height: 1.4; - max-width: 85vw; - - .course-header { - float: left; - background-color: var(--color-dark); - position: relative; - font-size: 16px; - color: #fff; - padding-top: 10px; - padding-bottom: 10px; - padding-left: 10px; - padding-right: 35px; - margin-bottom: 10px; - font-weight: bold; - text-align: left; - border-radius: 20px 20px 20px 20px / 50% 50% 50% 50%; - margin-right: 30px; - - .course-header-link { - color: white; - font-weight: bold; - text-decoration: none; - - &:hover { - color: inherit; - } - } - } -} - -.course-teaser-header:after { - content: ""; - display: table; - clear: both; -} diff --git a/frontend/src/utils/form/form.js b/frontend/src/utils/form/form.js index 1e8fb6d3a..6d30a501b 100644 --- a/frontend/src/utils/form/form.js +++ b/frontend/src/utils/form/form.js @@ -1,4 +1,4 @@ -import './form.scss'; +import './form.sass'; import { AutoSubmitButton } from './auto-submit-button'; import { AutoSubmitInput } from './auto-submit-input'; import { Datepicker } from './datepicker'; diff --git a/frontend/src/utils/form/form.sass b/frontend/src/utils/form/form.sass new file mode 100644 index 000000000..675deabd9 --- /dev/null +++ b/frontend/src/utils/form/form.sass @@ -0,0 +1,35 @@ +fieldset + border: 0 + margin: 0 + padding: 0 + + legend + display: none + +@media (min-width: 769px) + .form-group__input + grid-column: 2 + +[uw-auto-submit-button][type='submit'] + animation: fade-in 500ms ease-in-out backwards + animation-delay: 500ms + +@keyframes fade-in + from + opacity: 0 + +.hidden + visibility: hidden !important + height: 0 !important + width: 0 !important + opacity: 0 !important + margin: 0 !important + padding: 0 !important + min-width: 0 !important + +.select--pagesize + width: 5em + min-width: 75px + +.label-pagesize + margin-right: 13px diff --git a/frontend/src/utils/form/form.scss b/frontend/src/utils/form/form.scss deleted file mode 100644 index 6ec870f9e..000000000 --- a/frontend/src/utils/form/form.scss +++ /dev/null @@ -1,45 +0,0 @@ -fieldset { - border: 0; - margin: 0; - padding: 0; - - legend { - display: none; - } -} - -@media (min-width: 769px) { - .form-group__input { - grid-column: 2; - } -} - -[uw-auto-submit-button][type='submit'] { - animation: fade-in 500ms ease-in-out backwards; - animation-delay: 500ms; -} - -@keyframes fade-in { - from { - opacity: 0; - } -} - -.hidden { - visibility: hidden !important; - height: 0 !important; - width: 0 !important; - opacity: 0 !important; - margin: 0 !important; - padding: 0 !important; - min-width: 0 !important; -} - -.select--pagesize { - width: 5em; - min-width: 75px; -} - -.label-pagesize { - margin-right: 13px; -} diff --git a/frontend/src/utils/hide-columns/hide-columns.js b/frontend/src/utils/hide-columns/hide-columns.js index acedc2375..712de7d68 100644 --- a/frontend/src/utils/hide-columns/hide-columns.js +++ b/frontend/src/utils/hide-columns/hide-columns.js @@ -1,6 +1,6 @@ import { Utility } from '../../core/utility'; import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager'; -import './hide-columns.scss'; +import './hide-columns.sass'; const HIDE_COLUMNS_CONTAINER_IDENT = 'uw-hide-columns'; const TABLE_HEADER_IDENT = 'uw-hide-column-header'; diff --git a/frontend/src/utils/hide-columns/hide-columns.sass b/frontend/src/utils/hide-columns/hide-columns.sass new file mode 100644 index 000000000..e257b7045 --- /dev/null +++ b/frontend/src/utils/hide-columns/hide-columns.sass @@ -0,0 +1,61 @@ +.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(0.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) + +[table-utils] + max-width: 85vw + margin-bottom: 10px + min-height: 0 + line-height: 1.4 + + .table-pill + background-color: var(--color-dark) + float: left + color: #fff + padding: 10px + border-radius: 20px / 50% + margin-right: 20px + margin-bottom: 10px + cursor: pointer + + .table-hider__label + font-size: 16px + font-weight: bold + margin-left: 5px + + &:after + content: "" + display: block + clear: both + +.hide-columns--hidden-cell + display: none diff --git a/frontend/src/utils/hide-columns/hide-columns.scss b/frontend/src/utils/hide-columns/hide-columns.scss deleted file mode 100644 index 59aab069d..000000000 --- a/frontend/src/utils/hide-columns/hide-columns.scss +++ /dev/null @@ -1,71 +0,0 @@ -.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); - } - } - } -} - -[table-utils] { - max-width: 85vw; - margin-bottom: 10px; - min-height: 0; - line-height: 1.4; - - .table-pill { - background-color: var(--color-dark); - float: left; - color: #fff; - padding: 10px; - border-radius: 20px / 50%; - margin-right: 20px; - margin-bottom: 10px; - cursor: pointer; - - .table-hider__label { - font-size: 16px; - font-weight: bold; - margin-left: 5px; - } - } - - &:after { - content: ""; - display: block; - clear: both; - } -} - -.hide-columns--hidden-cell { - display: none; -} diff --git a/frontend/src/utils/inputs/checkbox.js b/frontend/src/utils/inputs/checkbox.js index 6f52ea3ae..1cf408ba8 100644 --- a/frontend/src/utils/inputs/checkbox.js +++ b/frontend/src/utils/inputs/checkbox.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './checkbox.scss'; +import './checkbox.sass'; var CHECKBOX_CLASS = 'checkbox'; var CHECKBOX_INITIALIZED_CLASS = 'checkbox--initialized'; diff --git a/frontend/src/utils/inputs/checkbox.sass b/frontend/src/utils/inputs/checkbox.sass new file mode 100644 index 000000000..ce15110ae --- /dev/null +++ b/frontend/src/utils/inputs/checkbox.sass @@ -0,0 +1,71 @@ +// CUSTOM CHECKBOXES +// Completely replaces legacy checkbox +.checkbox [type='checkbox'], #lang-checkbox + position: fixed + top: -1px + left: -1px + width: 1px + height: 1px + overflow: hidden + display: none + +.checkbox + position: relative + display: inline-block + + label + display: block + height: 20px + width: 20px + background-color: #f3f3f3 + box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05) + border: 2px solid var(--color-primary) + border-radius: 4px + color: white + cursor: pointer + + label::before, + label::after + position: absolute + display: block + top: 12px + left: 8px + height: 2px + width: 8px + background-color: var(--color-font) + + \:checked + label + background-color: var(--color-primary) + + [type='checkbox']:focus + label + border-color: #3273dc + box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25) + outline: 0 + + \:checked + label::before, + :checked + label::after + content: '' + + \:checked + label::before + background-color: white + transform: rotate(45deg) + left: 2px + top: 11px + + \:checked + label::after + background-color: white + transform: rotate(-45deg) + top: 9px + width: 12px + left: 7px + + [disabled] + label + pointer-events: none + border: none + opacity: 0.6 + filter: grayscale(1) + +// special treatment for checkboxes in table headers +th .checkbox + margin-right: 7px + vertical-align: bottom diff --git a/frontend/src/utils/inputs/checkbox.scss b/frontend/src/utils/inputs/checkbox.scss deleted file mode 100644 index 817aa5f3a..000000000 --- a/frontend/src/utils/inputs/checkbox.scss +++ /dev/null @@ -1,83 +0,0 @@ - -/* CUSTOM CHECKBOXES */ -/* Completely replaces legacy checkbox */ -.checkbox [type='checkbox'], #lang-checkbox { - position: fixed; - top: -1px; - left: -1px; - width: 1px; - height: 1px; - overflow: hidden; - display: none; -} - -.checkbox { - position: relative; - display: inline-block; - - label { - display: block; - height: 20px; - width: 20px; - background-color: #f3f3f3; - box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05); - border: 2px solid var(--color-primary); - border-radius: 4px; - color: white; - cursor: pointer; - } - - label::before, - label::after { - position: absolute; - display: block; - top: 12px; - left: 8px; - height: 2px; - width: 8px; - background-color: var(--color-font); - } - - :checked + label { - background-color: var(--color-primary); - } - - [type='checkbox']:focus + label { - border-color: #3273dc; - box-shadow: 0 0 0 0.125em rgba(50,115,220,.25); - outline: 0; - } - - :checked + label::before, - :checked + label::after { - content: ''; - } - - :checked + label::before { - background-color: white; - transform: rotate(45deg); - left: 2px; - top: 11px; - } - - :checked + label::after { - background-color: white; - transform: rotate(-45deg); - top: 9px; - width: 12px; - left: 7px; - } - - [disabled] + label { - pointer-events: none; - border: none; - opacity: 0.6; - filter: grayscale(1); - } -} - -/* special treatment for checkboxes in table headers */ -th .checkbox { - margin-right: 7px; - vertical-align: bottom; -} diff --git a/frontend/src/utils/inputs/file-input.js b/frontend/src/utils/inputs/file-input.js index 568e1baf4..e84d2ce26 100644 --- a/frontend/src/utils/inputs/file-input.js +++ b/frontend/src/utils/inputs/file-input.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './file-input.scss'; +import './file-input.sass'; const FILE_INPUT_CLASS = 'file-input'; const FILE_INPUT_INITIALIZED_CLASS = 'file-input--initialized'; diff --git a/frontend/src/utils/inputs/file-input.sass b/frontend/src/utils/inputs/file-input.sass new file mode 100644 index 000000000..576aad0b5 --- /dev/null +++ b/frontend/src/utils/inputs/file-input.sass @@ -0,0 +1,2 @@ +.file-input__list:empty + display: none diff --git a/frontend/src/utils/inputs/file-input.scss b/frontend/src/utils/inputs/file-input.scss deleted file mode 100644 index 7bf23248d..000000000 --- a/frontend/src/utils/inputs/file-input.scss +++ /dev/null @@ -1,3 +0,0 @@ -.file-input__list:empty { - display: none; -} diff --git a/frontend/src/utils/inputs/inputs.js b/frontend/src/utils/inputs/inputs.js index abda566a5..1909d964a 100644 --- a/frontend/src/utils/inputs/inputs.js +++ b/frontend/src/utils/inputs/inputs.js @@ -1,8 +1,8 @@ import { Checkbox } from './checkbox'; import { FileInput } from './file-input'; -import './inputs.scss'; -import './radio.scss'; +import './inputs.sass'; +import './radio.sass'; export const InputUtils = [ Checkbox, diff --git a/frontend/src/utils/inputs/inputs.sass b/frontend/src/utils/inputs/inputs.sass new file mode 100644 index 000000000..ec9581ff7 --- /dev/null +++ b/frontend/src/utils/inputs/inputs.sass @@ -0,0 +1,211 @@ +// GENERAL STYLES FOR FORMS + +// FORM GROUPS +.form-section-title + color: var(--color-fontsec) + margin: 0 + + + .form-group + margin-top: 11px + +.form-group + position: relative + display: flex + display: grid + grid-template-columns: 1fr 3fr + grid-gap: 5px + justify-content: flex-start + align-items: flex-start + + + .form-group, + .form-section-legend, + .form-section-notification + margin-top: 11px + + + .form-section-title + margin-top: 40px + +.form-section-legend + color: var(--color-fontsec) + margin: 7px 0 + +.form-group__hint, .form-section-title__hint + color: var(--color-fontsec) + font-size: 0.9rem + font-weight: 600 + +.form-section-title__hint + margin-top: 7px + + + .form-group + margin-top: 11px + +.form-group-label + font-weight: 600 + padding-top: 6px + +.form-group-label__hint + margin-top: 7px + color: var(--color-fontsec) + font-size: 0.9rem + +.form-group--required .form-group-label__caption::after, .form-group__required-marker::before + content: ' *' + color: var(--color-error) + font-weight: 600 + +.form-group--submit .form-group__input + grid-column: 2 + +@media (max-width: 768px) + .form-group--submit .form-group__input + grid-column: 1 + +.form-group--has-error + background-color: rgba(255, 0, 0, 0.1) + + input, textarea + border-color: var(--color-error) !important + + .form-error + display: block + +.form-error + display: none + +@media (max-width: 768px) + .form-group + grid-template-columns: 1fr + align-items: baseline + margin-top: 17px + flex-direction: column + +// TEXT INPUTS +input[type='text'], +input[type='search'], +input[type='password'], +input[type='url'], +input[type='number'], +input[type='email'], +input[type*='date'], +input[type*='time'], +select + // from bulma.css + color: #363636 + border-color: #dbdbdb + background-color: #f3f3f3 + box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05) + width: 100% + max-width: 600px + align-items: center + border: 1px solid transparent + border-radius: 4px + font-size: 1rem + font-family: var(--font-base) + line-height: 1.5 + padding: 4px 13px + +input[type='number'] + width: 100px + +input[type*='date'], +input[type*='time'], +.flatpickr-input[type='text'] + width: 50% + width: 250px + +// BUTTON STYLE SEE default-layout.lucius + +// TEXTAREAS +textarea + width: 100% + height: 170px + max-width: 600px + line-height: 1.5 + color: #363636 + background-color: #f3f3f3 + padding: 4px 13px + font-size: 1rem + font-family: var(--font-base) + appearance: none + border: 1px solid #dbdbdb + border-radius: 2px + box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05) + vertical-align: top + +// SHARED STATE RELATED STYLES + +input, +select, +textarea + &:focus + border-color: #3273dc + box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25) + outline: 0 + + &[disabled] + background-color: #f3f3f3 + color: #7a7a7a + box-shadow: none + border-color: #dbdbdb + + &[readonly] + background-color: #f5f5f5 + border-color: #dbdbdb + +// OPTIONS + +select[size="1"], select:not([size]) + appearance: menulist + +select, +option + font-size: 1rem + line-height: 1.5 + padding: 4px 13px + border: 1px solid #dbdbdb + border-radius: 2px + outline: 0 + color: #363636 + min-width: 250px + width: auto + background-color: #f3f3f3 + box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05) + +@media (max-width: 425px) + select, option + width: 100% + +// FILE INPUT +.file-input + display: none + +.file-input__label + cursor: pointer + display: inline-block + background-color: var(--color-primary) + color: white + padding: 10px 17px + border-radius: 3px + +.file-input__info + font-size: .9rem + font-style: italic + margin: 10px 0 + color: var(--color-fontsec) + +.file-input__list + margin-left: 40px + margin-top: 10px + font-weight: 600 + +// PREVIOUSLY UPLOADED FILES + +.file-uploads-label + margin-bottom: 10px + +.file-container + display: flex + align-items: center + margin-bottom: 10px + + .checkbox + margin-left: 12px diff --git a/frontend/src/utils/inputs/inputs.scss b/frontend/src/utils/inputs/inputs.scss deleted file mode 100644 index f19a17bda..000000000 --- a/frontend/src/utils/inputs/inputs.scss +++ /dev/null @@ -1,253 +0,0 @@ -/* GENERAL STYLES FOR FORMS */ - -/* FORM GROUPS */ -.form-section-title { - color: var(--color-fontsec); - margin: 0; - - + .form-group { - margin-top: 11px; - } -} - -.form-group { - position: relative; - display: flex; - display: grid; - grid-template-columns: 1fr 3fr; - grid-gap: 5px; - justify-content: flex-start; - align-items: flex-start; - - + .form-group, + .form-section-legend, + .form-section-notification { - margin-top: 11px; - } - - + .form-section-title { - margin-top: 40px; - } -} - -.form-section-legend { - color: var(--color-fontsec); - margin: 7px 0; -} - -.form-group__hint, .form-section-title__hint { - color: var(--color-fontsec); - font-size: 0.9rem; - font-weight: 600; -} - -.form-section-title__hint { - margin-top: 7px; - - + .form-group { - margin-top: 11px; - } -} - -.form-group-label { - font-weight: 600; - padding-top: 6px; -} - -.form-group-label__hint { - margin-top: 7px; - color: var(--color-fontsec); - font-size: 0.9rem; -} - -.form-group--required .form-group-label__caption::after, .form-group__required-marker::before { - content: ' *'; - color: var(--color-error); - font-weight: 600; -} - -.form-group--submit .form-group__input { - grid-column: 2; -} - -@media (max-width: 768px) { - .form-group--submit .form-group__input { - grid-column: 1; - } -} - -.form-group--has-error { - background-color: rgba(255, 0, 0, 0.1); - - input, textarea { - border-color: var(--color-error) !important; - } - - .form-error { - display: block; - } -} - -.form-error { - display: none; -} - -@media (max-width: 768px) { - .form-group { - grid-template-columns: 1fr; - align-items: baseline; - margin-top: 17px; - flex-direction: column; - } -} - -/* TEXT INPUTS */ -input[type='text'], -input[type='search'], -input[type='password'], -input[type='url'], -input[type='number'], -input[type='email'], -input[type*='date'], -input[type*='time'], -select { - /* from bulma.css */ - color: #363636; - border-color: #dbdbdb; - background-color: #f3f3f3; - box-shadow: inset 0 1px 2px 1px rgba(50,50,50,.05); - - width: 100%; - max-width: 600px; - align-items: center; - border: 1px solid transparent; - border-radius: 4px; - font-size: 1rem; - font-family: var(--font-base); - line-height: 1.5; - padding: 4px 13px; -} - -input[type='number'] { - width: 100px; -} - -input[type*='date'], -input[type*='time'], -.flatpickr-input[type='text'] { - width: 50%; - width: 250px; -} - -/* BUTTON STYLE SEE default-layout.lucius */ - -/* TEXTAREAS */ -textarea { - width: 100%; - height: 170px; - max-width: 600px; - line-height: 1.5; - color: #363636; - background-color: #f3f3f3; - padding: 4px 13px; - font-size: 1rem; - font-family: var(--font-base); - appearance: none; - border: 1px solid #dbdbdb; - border-radius: 2px; - box-shadow: inset 0 1px 2px 1px rgba(50,50,50,.05); - vertical-align: top; -} - -/* SHARED STATE RELATED STYLES */ - -input, -select, -textarea { - &:focus { - border-color: #3273dc; - box-shadow: 0 0 0 0.125em rgba(50,115,220,.25); - outline: 0; - } - - &[disabled] { - background-color: #f3f3f3; - color: #7a7a7a; - box-shadow: none; - border-color: #dbdbdb; - } - - &[readonly] { - background-color: #f5f5f5; - border-color: #dbdbdb; - } -} - -/* OPTIONS */ - -select[size = "1"], select:not([size]) { - appearance: menulist; -} - -select, -option { - font-size: 1rem; - line-height: 1.5; - padding: 4px 13px; - border: 1px solid #dbdbdb; - border-radius: 2px; - outline: 0; - color: #363636; - min-width: 250px; - width: auto; - background-color: #f3f3f3; - box-shadow: inset 0 1px 2px 1px rgba(50,50,50,.05); -} - -@media (max-width: 425px) { - - select, option { - width: 100%; - } -} - -/* FILE INPUT */ -.file-input { - display: none; -} - -.file-input__label { - cursor: pointer; - display: inline-block; - background-color: var(--color-primary); - color: white; - padding: 10px 17px; - border-radius: 3px; -} - -.file-input__info { - font-size: .9rem; - font-style: italic; - margin: 10px 0; - color: var(--color-fontsec); -} - -.file-input__list { - margin-left: 40px; - margin-top: 10px; - font-weight: 600; -} - -/* PREVIOUSLY UPLOADED FILES */ - -.file-uploads-label { - margin-bottom: 10px; -} - -.file-container { - display: flex; - align-items: center; - margin-bottom: 10px; - - .checkbox { - margin-left: 12px; - } -} diff --git a/frontend/src/utils/inputs/radio.sass b/frontend/src/utils/inputs/radio.sass new file mode 100644 index 000000000..367a05702 --- /dev/null +++ b/frontend/src/utils/inputs/radio.sass @@ -0,0 +1,55 @@ +// CUSTOM RADIO BOXES +// Completely replaces native radiobox + +.radio-group + display: flex + +.radio + position: relative + display: inline-block + + [type='radio'] + position: fixed + top: -1px + left: -1px + width: 1px + height: 1px + overflow: hidden + + label + display: block + height: 34px + min-width: 42px + line-height: 34px + text-align: center + padding: 0 13px + background-color: #f3f3f3 + box-shadow: inset 2px 1px 2px 1px rgba(50, 50, 50, 0.05) + color: var(--color-font) + cursor: pointer + + \:checked + label + background-color: var(--color-primary) + color: var(--color-lightwhite) + box-shadow: inset -2px -1px 2px 1px rgba(255, 255, 255, 0.15) + + \:focus + label + border-color: #3273dc + box-shadow: 0 0 0.125em 0 rgba(50, 115, 220, 0.8) + outline: 0 + + [disabled] + label + pointer-events: none + border: none + opacity: 0.6 + filter: grayscale(1) + +.radio:first-child + label + border-top-left-radius: 4px + border-bottom-left-radius: 4px + +.radio:last-child + label + border-top-right-radius: 4px + border-bottom-right-radius: 4px diff --git a/frontend/src/utils/inputs/radio.scss b/frontend/src/utils/inputs/radio.scss deleted file mode 100644 index 8e36edbda..000000000 --- a/frontend/src/utils/inputs/radio.scss +++ /dev/null @@ -1,66 +0,0 @@ -/* CUSTOM RADIO BOXES */ -/* Completely replaces native radiobox */ - -.radio-group { - display: flex; -} - -.radio { - position: relative; - display: inline-block; - - [type='radio'] { - position: fixed; - top: -1px; - left: -1px; - width: 1px; - height: 1px; - overflow: hidden; - } - - label { - display: block; - height: 34px; - min-width: 42px; - line-height: 34px; - text-align: center; - padding: 0 13px; - background-color: #f3f3f3; - box-shadow: inset 2px 1px 2px 1px rgba(50, 50, 50, 0.05); - color: var(--color-font); - cursor: pointer; - } - - :checked + label { - background-color: var(--color-primary); - color: var(--color-lightwhite); - box-shadow: inset -2px -1px 2px 1px rgba(255, 255, 255, 0.15); - } - - :focus + label { - border-color: #3273dc; - box-shadow: 0 0 0.125em 0 rgba(50,115,220,0.8); - outline: 0; - } - - [disabled] + label { - pointer-events: none; - border: none; - opacity: 0.6; - filter: grayscale(1); - } -} - -.radio:first-child { - label { - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - } -} - -.radio:last-child { - label { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - } -} diff --git a/frontend/src/utils/mass-input/mass-input.js b/frontend/src/utils/mass-input/mass-input.js index f6c8357b2..403c626ac 100644 --- a/frontend/src/utils/mass-input/mass-input.js +++ b/frontend/src/utils/mass-input/mass-input.js @@ -1,6 +1,6 @@ import { Utility } from '../../core/utility'; import { Datepicker } from '../form/datepicker'; -import './mass-input.scss'; +import './mass-input.sass'; const MASS_INPUT_CELL_SELECTOR = '.massinput__cell'; const MASS_INPUT_ADD_CELL_SELECTOR = '.massinput__cell--add'; diff --git a/frontend/src/utils/mass-input/mass-input.sass b/frontend/src/utils/mass-input/mass-input.sass new file mode 100644 index 000000000..89bdf08c9 --- /dev/null +++ b/frontend/src/utils/mass-input/mass-input.sass @@ -0,0 +1,14 @@ +.massinput-list__wrapper, .massinput-list__cell + display: grid + grid: auto / auto 50px + max-width: 600px + grid-gap: 7px + +.massinput-list__field + grid-column: 1 + +.massinput-list__add, .massinput-list__delete + grid-column: 2 + +.massinput-list__cell + grid-column: 1 / 3 diff --git a/frontend/src/utils/mass-input/mass-input.scss b/frontend/src/utils/mass-input/mass-input.scss deleted file mode 100644 index d8f006d36..000000000 --- a/frontend/src/utils/mass-input/mass-input.scss +++ /dev/null @@ -1,18 +0,0 @@ -.massinput-list__wrapper, .massinput-list__cell { - display: grid; - grid: auto / auto 50px; - max-width: 600px; - grid-gap: 7px; -} - -.massinput-list__field { - grid-column: 1; -} - -.massinput-list__add, .massinput-list__delete { - grid-column: 2; -} - -.massinput-list__cell { - grid-column: 1 / 3; -} diff --git a/frontend/src/utils/modal/modal.js b/frontend/src/utils/modal/modal.js index 3958d6c2c..52a9a2b99 100644 --- a/frontend/src/utils/modal/modal.js +++ b/frontend/src/utils/modal/modal.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './modal.scss'; +import './modal.sass'; const MODAL_HEADERS = { 'Is-Modal': 'True', diff --git a/frontend/src/utils/modal/modal.sass b/frontend/src/utils/modal/modal.sass new file mode 100644 index 000000000..4a2b69459 --- /dev/null +++ b/frontend/src/utils/modal/modal.sass @@ -0,0 +1,103 @@ +@use "../../common" as * + +.modals-wrapper + position: fixed + left: 0 + top: 0 + width: 100% + height: 100% + z-index: -1 + display: flex + align-items: center + justify-content: center + + &.modals-wrapper--open + z-index: 200 + width: 100% + height: 100% + +.modal + position: relative + display: none + background-color: rgba(255, 255, 255, 1) + min-width: 60vw + max-width: 70vw + min-height: 100px + max-height: calc(100vh - 30px) + border-radius: 2px + z-index: -1 + color: var(--color-font) + overflow: auto + overscroll-behavior: contain + pointer-events: none + opacity: 0 + + &.modal--open + display: flex + opacity: 1 + pointer-events: auto + z-index: 200 + transition: opacity .2s .1s ease-in-out, transform .3s ease-in-out + +@media (max-width: 1024px) + .modal + min-width: 80vw + +@media (max-width: 768px) + .modal + min-width: 90vw + +@media (max-width: 425px) + .modal + min-width: calc(100vw - 20px) + +.modal__overlay + position: fixed + left: 0 + top: 0 + height: 100% + width: 100% + background-color: transparent + z-index: -1 + transition: all .2s ease + display: none + + &.modal__overlay--open + display: block + z-index: 199 + opacity: 1 + background-color: rgba(0, 0, 0, 0.4) + +.modal__trigger + cursor: pointer + +div.modal__trigger + display: inline-block + +.modal__trigger-label + font-style: italic + text-decoration: underline + +.modal__closer + position: absolute + top: 20px + right: 20px + display: flex + align-items: center + justify-content: center + width: 30px + height: 30px + background-color: var(--color-darker) + border-radius: 2px + cursor: pointer + z-index: 20 + + &::before + @extend .fas + + content: fa-content($fa-var-times) + color: white + +.modal__content + margin: 20px 40px + width: 100% diff --git a/frontend/src/utils/modal/modal.scss b/frontend/src/utils/modal/modal.scss deleted file mode 100644 index 446863f03..000000000 --- a/frontend/src/utils/modal/modal.scss +++ /dev/null @@ -1,120 +0,0 @@ -@use "../../common" as *; - -.modals-wrapper { - position: fixed; - left: 0; - top: 0; - width: 100%; - height: 100%; - z-index: -1; - display: flex; - align-items: center; - justify-content: center; - - &.modals-wrapper--open { - z-index: 200; - width: 100%; - height: 100%; - } -} - -.modal { - position: relative; - display: none; - background-color: rgba(255, 255, 255, 1); - min-width: 60vw; - max-width: 70vw; - min-height: 100px; - max-height: calc(100vh - 30px); - border-radius: 2px; - z-index: -1; - color: var(--color-font); - overflow: auto; - overscroll-behavior: contain; - pointer-events: none; - opacity: 0; - - &.modal--open { - display: flex; - opacity: 1; - pointer-events: auto; - z-index: 200; - transition: - opacity .2s .1s ease-in-out, - transform .3s ease-in-out; - } -} - -@media (max-width: 1024px) { - .modal { - min-width: 80vw; - } -} -@media (max-width: 768px) { - .modal { - min-width: 90vw; - } -} -@media (max-width: 425px) { - .modal { - min-width: calc(100vw - 20px); - } -} - -.modal__overlay { - position: fixed; - left: 0; - top: 0; - height: 100%; - width: 100%; - background-color: transparent; - z-index: -1; - transition: all .2s ease; - display: none; - - &.modal__overlay--open { - display: block; - z-index: 199; - opacity: 1; - background-color: rgba(0, 0, 0, 0.4); - } -} - -.modal__trigger { - cursor: pointer; -} - -div.modal__trigger { - display: inline-block; -} - -.modal__trigger-label { - font-style: italic; - text-decoration: underline; -} - -.modal__closer { - position: absolute; - top: 20px; - right: 20px; - display: flex; - align-items: center; - justify-content: center; - width: 30px; - height: 30px; - background-color: var(--color-darker); - border-radius: 2px; - cursor: pointer; - z-index: 20; - - &::before { - @extend .fas; - content: fa-content($fa-var-times); - color: white; - } -} - -.modal__content { - margin: 20px 40px; - width: 100%; -} diff --git a/frontend/src/utils/navbar/navbar.js b/frontend/src/utils/navbar/navbar.js index 95af958f4..0bb6fb029 100644 --- a/frontend/src/utils/navbar/navbar.js +++ b/frontend/src/utils/navbar/navbar.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './navbar.scss'; +import './navbar.sass'; export const LANGUAGE_SELECT_UTIL_SELECTOR = '[uw-language-select]'; diff --git a/frontend/src/utils/navbar/navbar.sass b/frontend/src/utils/navbar/navbar.sass new file mode 100644 index 000000000..05e3e23ab --- /dev/null +++ b/frontend/src/utils/navbar/navbar.sass @@ -0,0 +1,228 @@ +.navbar-container + position: relative + +.navbar-shadow + position: fixed + right: 0 + top: 0 + height: var(--header-height-collapsed) + width: 20px + z-index: 50 + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.4), transparent) + transition: height 0.2s cubic-bezier(0.03, 0.43, 0.58, 1) + +@media (min-width: 768px) + .navbar-shadow + height: var(--header-height) + +@media (min-width: 1025px) + .navbar-shadow + display: none + +.navbar + position: fixed + display: flex + flex-direction: row + align-items: center + justify-content: flex-start + right: 0 + top: 0 + left: var(--asidenav-width-xl) + height: var(--header-height) + background-color: var(--color-primary) + color: white + z-index: 20 + box-shadow: 0 0 4px rgba(0, 0, 0, 0.2) + overflow: auto + transition: all 0.2s cubic-bezier(0.03, 0.43, 0.58, 1) + +@media (max-width: 1199px) + .navbar + left: var(--asidenav-width-lg) + +@media (max-width: 768px) + .navbar + left: 0 + +// links +.navbar__link-wrapper + display: flex + flex-direction: column + justify-content: flex-end + align-items: center + height: 80px + min-width: 90px + color: var(--color-lightwhite) + transition: height 0.2s cubic-bezier(0.03, 0.43, 0.58, 1) + overflow: hidden + cursor: pointer + +.navbar__link-icon + opacity: 0.7 + transition: opacity 0.2s ease + margin-bottom: 7px + +.navbar__link-label + transition: opacity .2s ease + padding: 2px 4px + text-transform: uppercase + font-weight: 600 + +@media (min-width: 769px) + .navbar__link-wrapper + border: 1px solid rgba(255, 255, 255, 0.7) + +@media (max-width: 768px) + .navbar__link-wrapper + box-shadow: none + min-width: 0 + align-items: center + justify-content: center + + .navbar__link-label + padding: 0 7px + + .navbar__link-icon + transform: scale(0.65) + margin-bottom: 0 + +// navbar list +.navbar__list + white-space: nowrap + + + .navbar__list + margin-left: 12px + +@media (min-width: 769px) + .navbar__list:last-of-type + padding-right: 40px + +@media (max-width: 768px) + .navbar__list + + .navbar__list + margin-left: 0 + padding-right: 40px + +// list item +.navbar__list-item + position: relative + transition: background-color .1s ease + + &:not(.navbar__list-item--favorite) + .navbar__list-item--lang-wrapper + margin-left: 12px + + &:not(.navbar__list-item--favorite) + .navbar__list-item + margin-left: 12px + +@media (max-width: 500px) + .navbar__list-item + min-width: 60px + + &:not(.navbar__list-item--favorite) + .navbar__list-item + margin-left: 0 + + &:not(.navbar__list-item--favorite) + .navbar__list-item--lang-wrapper + margin-left: 0 + +.navbar__list-left + flex: 5 + padding-left: 40px + +@media (max-width: 768px) + .navbar__list-left + padding-left: 0 + +// "Favorites" list item, only visible on small screens and logged in +.navbar__list-item + &.navbar__list-item--favorite + display: none + +.navbar__list-item--favorite + display: none + background-color: var(--color-primary) + +.logged-in + .navbar__list + li.navbar__list-item--favorite, + .navbar__list-item--favorite + display: inline-block + +@media (min-width: 426px) + .logged-in + .navbar__list + .navbar__list-item--favorite + display: none !important + +.navbar__list-item--active + background-color: var(--color-lightwhite) + color: var(--color-dark) + + .navbar__link-wrapper + color: var(--color-dark) + +.navbar__list-item--active .navbar__link-wrapper + color: var(--color-dark) + +.navbar .navbar__list-item:not(.navbar__list-item--active):not(.navbar__list-item--favorite):hover .navbar__link-wrapper, #lang-checkbox:checked ~ * .navbar__link-wrapper + background-color: var(--color-dark) + color: var(--color-lightwhite) + + .navbar__link-icon + opacity: 1 + +// sticky state +.navbar--sticky + height: var(--header-height-collapsed) + z-index: 100 + + .navbar__link-wrapper + height: var(--header-height-collapsed) + +.navbar__pushdown + height: var(--header-height) + transition: height 0.2s cubic-bezier(0.03, 0.43, 0.58, 1) + +.navbar--sticky + .navbar__pushdown + display: block + height: var(--header-height-collapsed) + +@media (max-width: 768px) + .navbar, + .navbar__pushdown + height: var(--header-height-collapsed) + + .navbar__link-wrapper + height: var(--header-height-collapsed) + +@media (max-height: 500px) + .navbar, + .navbar__pushdown + height: var(--header-height-collapsed) + + .navbar__link-wrapper + height: var(--header-height-collapsed) + +#lang-dropdown + display: none + position: fixed + top: var(--header-height) + right: 0 + min-width: 200px + z-index: 10 + background-color: white + border-radius: 2px + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3) + + select + display: block + + button + display: block + width: 100% + +#lang-checkbox:checked ~ #lang-dropdown + display: block + +@media (max-width: 768px) + #lang-dropdown + top: var(--header-height-collapsed) diff --git a/frontend/src/utils/navbar/navbar.scss b/frontend/src/utils/navbar/navbar.scss deleted file mode 100644 index 888d8d5cb..000000000 --- a/frontend/src/utils/navbar/navbar.scss +++ /dev/null @@ -1,305 +0,0 @@ -.navbar-container { - position: relative; -} - -.navbar-shadow { - position: fixed; - right: 0; - top: 0; - height: var(--header-height-collapsed); - width: 20px; - z-index: 50; - background-image: linear-gradient(to left, rgba(0, 0, 0, 0.4), transparent); - transition: height .2s cubic-bezier(0.03, 0.43, 0.58, 1); -} - -@media (min-width: 768px) { - - .navbar-shadow { - height: var(--header-height); - } -} - -@media (min-width: 1025px) { - - .navbar-shadow { - display: none; - } -} - -.navbar { - position: fixed; - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-start; - right: 0; - top: 0; - left: var(--asidenav-width-xl); - height: var(--header-height); - background-color: var(--color-primary); - color: white; - z-index: 20; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.2); - overflow: auto; - transition: all .2s cubic-bezier(0.03, 0.43, 0.58, 1); -} - -@media (max-width: 1199px) { - .navbar { - left: var(--asidenav-width-lg); - } -} - -@media (max-width: 768px) { - .navbar { - left: 0; - } -} - -/* links */ -.navbar__link-wrapper { - display: flex; - flex-direction: column; - justify-content: flex-end; - align-items: center; - height: 80px; - min-width: 90px; - color: var(--color-lightwhite); - transition: height .2s cubic-bezier(0.03, 0.43, 0.58, 1); - overflow: hidden; - cursor: pointer; -} - -.navbar__link-icon { - opacity: 0.7; - transition: opacity 0.2s ease; - margin-bottom: 7px; -} - -.navbar__link-label { - transition: opacity .2s ease; - padding: 2px 4px; - text-transform: uppercase; - font-weight: 600; -} - -@media (min-width: 769px) { - - .navbar__link-wrapper { - border: 1px solid rgba(255, 255, 255, 0.7); - } -} - -@media (max-width: 768px) { - - .navbar__link-wrapper { - box-shadow: none; - min-width: 0; - align-items: center; - justify-content: center; - } - - .navbar__link-label { - padding: 0 7px; - } - - .navbar__link-icon { - transform: scale(0.65); - margin-bottom: 0; - } -} - -/* navbar list */ -.navbar__list { - white-space: nowrap; - - + .navbar__list { - margin-left: 12px; - } -} - -@media (min-width: 769px) { - - .navbar__list:last-of-type { - padding-right: 40px; - } -} - -@media (max-width: 768px) { - - .navbar__list { - + .navbar__list { - margin-left: 0; - padding-right: 40px; - } - } -} - -/* list item */ -.navbar__list-item { - position: relative; - transition: background-color .1s ease; - &:not(.navbar__list-item--favorite) + .navbar__list-item--lang-wrapper { - margin-left: 12px; - } - &:not(.navbar__list-item--favorite) + .navbar__list-item { - margin-left: 12px; - } -} - -@media (max-width: 500px) { - - .navbar__list-item { - min-width: 60px; - - &:not(.navbar__list-item--favorite) + .navbar__list-item { - margin-left: 0; - } - &:not(.navbar__list-item--favorite) + .navbar__list-item--lang-wrapper { - margin-left: 0; - } - } -} - -.navbar__list-left { - flex: 5; - padding-left: 40px; -} - -@media (max-width: 768px) { - - .navbar__list-left { - padding-left: 0; - } -} - -/* "Favorites" list item, only visible on small screens and logged in */ -.navbar__list-item { - &.navbar__list-item--favorite { - display: none; - } -} -.navbar__list-item--favorite { - display: none; - background-color: var(--color-primary); -} - -.logged-in { - .navbar__list { - li.navbar__list-item--favorite, - .navbar__list-item--favorite { - display: inline-block; - } - } -} - -@media (min-width: 426px) { - - .logged-in { - .navbar__list { - .navbar__list-item--favorite { - display: none !important; - } - } - } -} - -.navbar__list-item--active { - background-color: var(--color-lightwhite); - color: var(--color-dark); - - .navbar__link-wrapper { - color: var(--color-dark); - } -} - -.navbar__list-item--active .navbar__link-wrapper { - color: var(--color-dark); -} - -.navbar .navbar__list-item:not(.navbar__list-item--active):not(.navbar__list-item--favorite):hover .navbar__link-wrapper, #lang-checkbox:checked ~ * .navbar__link-wrapper { - background-color: var(--color-dark); - color: var(--color-lightwhite); - - .navbar__link-icon { - opacity: 1; - } -} - -/* sticky state */ -.navbar--sticky { - height: var(--header-height-collapsed); - z-index: 100; - - .navbar__link-wrapper { - height: var(--header-height-collapsed); - } -} - -.navbar__pushdown { - height: var(--header-height); - transition: height .2s cubic-bezier(0.03, 0.43, 0.58, 1); -} - -.navbar--sticky + .navbar__pushdown { - display: block; - height: var(--header-height-collapsed); -} - -@media (max-width: 768px) { - - .navbar, - .navbar__pushdown { - height: var(--header-height-collapsed); - } - - .navbar__link-wrapper { - height: var(--header-height-collapsed); - } -} - -@media (max-height: 500px) { - - .navbar, - .navbar__pushdown { - height: var(--header-height-collapsed); - } - - .navbar__link-wrapper { - height: var(--header-height-collapsed); - } -} - - -#lang-dropdown { - display: none; - - position: fixed; - top: var(--header-height); - right: 0; - min-width: 200px; - z-index: 10; - background-color: white; - border-radius: 2px; - box-shadow: 0 0 10px rgba(0,0,0,0.3); - - select { - display: block; - } - - button { - display: block; - width: 100%; - } -} - -#lang-checkbox:checked ~ #lang-dropdown { - display: block; -} - -@media (max-width: 768px) { - #lang-dropdown { - top: var(--header-height-collapsed); - } -} diff --git a/frontend/src/utils/show-hide/show-hide.js b/frontend/src/utils/show-hide/show-hide.js index aa1f4f792..4da5f8c06 100644 --- a/frontend/src/utils/show-hide/show-hide.js +++ b/frontend/src/utils/show-hide/show-hide.js @@ -1,6 +1,6 @@ import { Utility } from '../../core/utility'; import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager'; -import './show-hide.scss'; +import './show-hide.sass'; const SHOW_HIDE_LOCAL_STORAGE_KEY = 'SHOW_HIDE'; const SHOW_HIDE_INITIALIZED_CLASS = 'show-hide--initialized'; diff --git a/frontend/src/utils/show-hide/show-hide.sass b/frontend/src/utils/show-hide/show-hide.sass new file mode 100644 index 000000000..cb5c922f2 --- /dev/null +++ b/frontend/src/utils/show-hide/show-hide.sass @@ -0,0 +1,44 @@ +$show-hide-toggle-size: 6px + +.show-hide__toggle + position: relative + cursor: pointer + + &:hover + background-color: var(--color-grey-lighter) + cursor: pointer + +.show-hide__toggle::before + content: '' + position: absolute + width: $show-hide-toggle-size + height: $show-hide-toggle-size + left: -15px + top: 50% + color: var(--color-primary) + border-right: 2px solid currentColor + border-top: 2px solid currentColor + transition: transform .2s ease + transform: translateY(-50%) rotate(-45deg) + + @media (max-width: 768px) + left: auto + right: 20px + color: var(--color-font) + +.show-hide__toggle--right::before + left: auto + right: 20px + color: var(--color-font) + +.show-hide--collapsed + .show-hide__toggle::before + transform: translateY(-50%) rotate(135deg) + + & > :not(.show-hide__toggle) + display: block + height: 0 + margin: 0 + padding: 0 + max-height: 0 + overflow-y: hidden diff --git a/frontend/src/utils/show-hide/show-hide.scss b/frontend/src/utils/show-hide/show-hide.scss deleted file mode 100644 index f557248fb..000000000 --- a/frontend/src/utils/show-hide/show-hide.scss +++ /dev/null @@ -1,54 +0,0 @@ -$show-hide-toggle-size: 6px; - -.show-hide__toggle { - - position: relative; - cursor: pointer; - - &:hover { - background-color: var(--color-grey-lighter); - cursor: pointer; - } -} - -.show-hide__toggle::before { - content: ''; - position: absolute; - width: $show-hide-toggle-size; - height: $show-hide-toggle-size; - left: -15px; - top: 50%; - color: var(--color-primary); - border-right: 2px solid currentColor; - border-top: 2px solid currentColor; - transition: transform .2s ease; - transform: translateY(-50%) rotate(-45deg); - - @media (max-width: 768px) { - left: auto; - right: 20px; - color: var(--color-font); - } -} - -.show-hide__toggle--right::before { - left: auto; - right: 20px; - color: var(--color-font); -} - -.show-hide--collapsed { - - .show-hide__toggle::before { - transform: translateY(-50%) rotate(135deg); - } - - & > :not(.show-hide__toggle) { - display: block; - height: 0; - margin: 0; - padding: 0; - max-height: 0; - overflow-y: hidden; - } -} diff --git a/frontend/src/utils/tabber/tabber.js b/frontend/src/utils/tabber/tabber.js index c44caa44b..39ed37576 100644 --- a/frontend/src/utils/tabber/tabber.js +++ b/frontend/src/utils/tabber/tabber.js @@ -1,4 +1,4 @@ -import './tabber.scss'; +import './tabber.sass'; (function($) { diff --git a/frontend/src/utils/tabber/tabber.sass b/frontend/src/utils/tabber/tabber.sass new file mode 100644 index 000000000..eea4355fd --- /dev/null +++ b/frontend/src/utils/tabber/tabber.sass @@ -0,0 +1,35 @@ +.tab-group + border-top: 2px solid #dcdcdc + padding-top: 30px + +.tab-group-openers + display: flex + justify-content: stretch + line-height: 40px + font-size: 14px + margin-bottom: 40px + +.tab-opener + display: inline-block + flex: 1 + text-align: center + padding: 0 13px + margin: 0 2px + background-color: var(--color-dark) + color: white + font-size: 16px + text-transform: uppercase + font-weight: 600 + transition: all .1s ease + border-bottom: 5px solid rgba(100, 100, 100, 0.2) + +.tab-opener:not(.tab-visible):hover + cursor: pointer + background-color: transparent + color: rgb(52, 48, 58) + border-bottom-color: grey + +.tab-opener.tab-visible + background-color: transparent + color: rgb(52, 48, 58) + border-bottom-color: var(--color-primary) diff --git a/frontend/src/utils/tabber/tabber.scss b/frontend/src/utils/tabber/tabber.scss deleted file mode 100644 index d135a5f27..000000000 --- a/frontend/src/utils/tabber/tabber.scss +++ /dev/null @@ -1,39 +0,0 @@ -.tab-group { - border-top: 2px solid #dcdcdc; - padding-top: 30px; -} - -.tab-group-openers { - display: flex; - justify-content: stretch; - line-height: 40px; - font-size: 14px; - margin-bottom: 40px; -} - -.tab-opener { - display: inline-block; - flex: 1; - text-align: center; - padding: 0 13px; - margin: 0 2px; - background-color: var(--color-dark); - color: white; - font-size: 16px; - text-transform: uppercase; - font-weight: 600; - transition: all .1s ease; - border-bottom: 5px solid rgba(100, 100, 100, 0.2); -} -.tab-opener:not(.tab-visible):hover { - cursor: pointer; - background-color: transparent; - color: rgb(52, 48, 58); - border-bottom-color: grey; -} - -.tab-opener.tab-visible { - background-color: transparent; - color: rgb(52, 48, 58); - border-bottom-color: var(--color-primary); -} diff --git a/frontend/src/utils/tooltips/tooltips.js b/frontend/src/utils/tooltips/tooltips.js index b773eef39..c4813957e 100644 --- a/frontend/src/utils/tooltips/tooltips.js +++ b/frontend/src/utils/tooltips/tooltips.js @@ -1,5 +1,5 @@ import { Utility } from '../../core/utility'; -import './tooltips.scss'; +import './tooltips.sass'; // empty 'shell' to be able to load styles @Utility({ diff --git a/frontend/src/utils/tooltips/tooltips.sass b/frontend/src/utils/tooltips/tooltips.sass new file mode 100644 index 000000000..dc3861fee --- /dev/null +++ b/frontend/src/utils/tooltips/tooltips.sass @@ -0,0 +1,92 @@ +.tooltip + position: relative + display: inline-block + vertical-align: middle + + &:hover .tooltip__content + display: inline-block + +.tooltip__handle + color: var(--color-light) + height: 1.5rem + line-height: 1.5rem + font-size: 1.2rem + display: inline-block + text-align: center + margin: 0 10px + cursor: default + position: relative + + &::before + position: absolute + top: 0 + left: 0 + top: 50% + left: 50% + transform: translate(-50%, -50%) + font-size: 15px + + &.tooltip__handle.urgency__success + color: var(--color-success) + + &.tooltip__handle.urgency__warning + color: var(--color-warning) + + &.tooltip__handle.urgency__error + color: var(--color-error) + + &:hover + color: var(--color-dark) + + &.tooltip__handle.urgency__success + color: var(--color-success-dark) + + &.tooltip__handle.urgency__warning + color: var(--color-warning-dark) + + &.tooltip__handle.urgency__error + color: var(--color-error-dark) + +.tooltip.tooltip__inline + .tooltip__handle + height: 1.0rem + line-height: 1.0rem + font-size: 1.0rem + +.tooltip__content + position: absolute + display: none + top: -10px + transform: translateY(-100%) + left: 3px + width: 275px + z-index: 10 + background-color: #fafafa + border-radius: 4px + padding: 13px 17px + box-shadow: 0 0 20px 4px rgba(0, 0, 0, 0.1) + + &::after + content: '' + width: 16px + height: 16px + background-color: #fafafa + transform: rotate(45deg) + position: absolute + left: 10px + bottom: -8px + +@media (max-width: 768px) + .tooltip + display: block + margin-top: 10px + + .tooltip__content + left: 3px + right: 3px + width: auto + +// fix font color when used in tableheaders +th .tooltip__content + color: var(--color-font) + font-weight: normal diff --git a/frontend/src/utils/tooltips/tooltips.scss b/frontend/src/utils/tooltips/tooltips.scss deleted file mode 100644 index 845c33310..000000000 --- a/frontend/src/utils/tooltips/tooltips.scss +++ /dev/null @@ -1,109 +0,0 @@ -.tooltip { - position: relative; - display: inline-block; - vertical-align: middle; - - &:hover .tooltip__content { - display: inline-block; - } -} - -.tooltip__handle { - color: var(--color-light); - height: 1.5rem; - line-height: 1.5rem; - font-size: 1.2rem; - display: inline-block; - text-align: center; - margin: 0 10px; - cursor: default; - position: relative; - - &::before { - position: absolute; - top: 0; - left: 0; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - font-size: 15px; - } - - &.tooltip__handle.urgency__success { - color: var(--color-success); - } - &.tooltip__handle.urgency__warning { - color: var(--color-warning); - } - &.tooltip__handle.urgency__error { - color: var(--color-error); - } - - &:hover { - color: var(--color-dark); - - &.tooltip__handle.urgency__success { - color: var(--color-success-dark); - } - &.tooltip__handle.urgency__warning { - color: var(--color-warning-dark); - } - &.tooltip__handle.urgency__error { - color: var(--color-error-dark); - } - } -} - -.tooltip.tooltip__inline { - .tooltip__handle { - height: 1.0rem; - line-height: 1.0rem; - font-size: 1.0rem; - } -} - -.tooltip__content { - position: absolute; - display: none; - top: -10px; - transform: translateY(-100%); - left: 3px; - width: 275px; - z-index: 10; - background-color: #fafafa; - border-radius: 4px; - padding: 13px 17px; - box-shadow: 0 0 20px 4px rgba(0, 0, 0, 0.1); - - &::after { - content: ''; - width: 16px; - height: 16px; - background-color: #fafafa; - transform: rotate(45deg); - position: absolute; - left: 10px; - bottom: -8px; - } -} - -@media (max-width: 768px) { - - .tooltip { - display: block; - margin-top: 10px; - - .tooltip__content { - left: 3px; - right: 3px; - width: auto; - } - } -} - - -/* fix font color when used in tableheaders */ -th .tooltip__content { - color: var(--color-font); - font-weight: normal; -} diff --git a/package-lock.json b/package-lock.json index e1895328f..76cf43601 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2633,6 +2633,12 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", + "dev": true + }, "@types/semver": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.2.tgz", @@ -3022,6 +3028,12 @@ "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", @@ -4206,6 +4218,12 @@ "type-is": "~1.6.17" } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4546,6 +4564,18 @@ } } }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, "caniuse-lite": { "version": "1.0.30001015", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz", @@ -4770,6 +4800,17 @@ "shallow-clone": "^3.0.0" } }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -4786,6 +4827,16 @@ "object-visit": "^1.0.0" } }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -4801,6 +4852,16 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -6283,6 +6344,22 @@ "postcss": "^7.0.5" } }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, "css-has-pseudo": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", @@ -6340,6 +6417,54 @@ "postcss": "^7.0.5" } }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-unit-converter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", + "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", + "dev": true + }, + "css-what": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", + "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==", + "dev": true + }, "cssdb": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", @@ -6352,6 +6477,92 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz", + "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.37" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -6625,12 +6836,46 @@ "void-elements": "^2.0.0" } }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + } + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, "dot-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", @@ -6825,6 +7070,12 @@ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -8793,6 +9044,12 @@ "minimalistic-assert": "^1.0.1" } }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -8829,6 +9086,24 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -9123,6 +9398,12 @@ "loose-envify": "^1.0.0" } }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -9179,6 +9460,20 @@ "ci-info": "^2.0.0" } }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -9361,12 +9656,27 @@ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", @@ -9770,6 +10080,16 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -10044,6 +10364,12 @@ "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -10063,6 +10389,12 @@ "lodash._reinterpolate": "~3.0.0" } }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -10226,6 +10558,12 @@ "safe-buffer": "^5.1.2" } }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -13844,6 +14182,15 @@ "which": "^1.2.10" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, "null-check": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", @@ -13915,6 +14262,12 @@ } } }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -13960,6 +14313,54 @@ "has": "^1.0.3" } }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -13969,6 +14370,56 @@ "isobject": "^3.0.1" } }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -14014,6 +14465,16 @@ } } }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", + "dev": true, + "requires": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + } + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -14380,6 +14841,37 @@ } } }, + "postcss-calc": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", + "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "dev": true, + "requires": { + "css-unit-converter": "^1.1.1", + "postcss": "^7.0.5", + "postcss-selector-parser": "^5.0.0-rc.4", + "postcss-value-parser": "^3.3.1" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, "postcss-color-functional-notation": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", @@ -14432,6 +14924,29 @@ "postcss-values-parser": "^2.0.0" } }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, "postcss-custom-media": { "version": "7.0.8", "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", @@ -14537,6 +15052,42 @@ } } }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, "postcss-double-position-gradients": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", @@ -14676,6 +15227,124 @@ "postcss": "^7.0.2" } }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, "postcss-modules-extract-imports": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", @@ -14725,6 +15394,124 @@ "postcss": "^7.0.2" } }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, "postcss-overflow-shorthand": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", @@ -14855,6 +15642,30 @@ } } }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, "postcss-replace-overflow-wrap": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", @@ -14895,6 +15706,29 @@ "uniq": "^1.0.1" } }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, "postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", @@ -15522,6 +16356,18 @@ "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", "dev": true }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -15625,6 +16471,12 @@ } } }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -15767,6 +16619,23 @@ } } }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -16118,6 +16987,12 @@ "figgy-pudding": "^3.5.1" } }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, "staged-git-files": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", @@ -16507,6 +17382,26 @@ "function-bind": "^1.0.2" } }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -16590,6 +17485,39 @@ "schema-utils": "^1.0.0" } }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -16599,6 +17527,27 @@ "has-flag": "^3.0.0" } }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -16864,6 +17813,12 @@ "setimmediate": "^1.0.4" } }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -17090,6 +18045,12 @@ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -17120,6 +18081,12 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -17236,6 +18203,16 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -17264,6 +18241,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "vendors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", + "integrity": "sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==", + "dev": true + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/package.json b/package.json index b4bbf8ab7..a5108f480 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "mini-css-extract-plugin": "^0.8.0", "npm-run-all": "^4.1.5", "null-loader": "^2.0.0", + "optimize-css-assets-webpack-plugin": "^5.0.3", "postcss-loader": "^3.0.0", "postcss-preset-env": "^6.7.0", "resolve-url-loader": "^3.1.1", diff --git a/records.json b/records.json index 70313cfe0..0e3c24f99 100644 --- a/records.json +++ b/records.json @@ -505,5 +505,239 @@ "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/app.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/async-form/async-form.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/alerts/alerts.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/asidenav/asidenav.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/form/form.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/hide-columns/hide-columns.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/navbar/navbar.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/course-teaser/course-teaser.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/modal/modal.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/tooltips/tooltips.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/mass-input/mass-input.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/inputs/radio.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/inputs/inputs.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/show-hide/show-hide.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/async-table/async-table.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/async-table/async-table-filter.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/inputs/file-input.sass": [ + { + "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/resolve-url-loader/index.js??ref--6-3!node_modules/sass-loader/dist/cjs.js??ref--6-4!frontend/src/utils/inputs/checkbox.sass": [ + { + "modules": { + "byIdentifier": {}, + "usedIds": {} + }, + "chunks": { + "byName": {}, + "bySource": {}, + "usedIds": [] + } + } ] } \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 376cc0b24..7faa15e17 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,7 @@ const webpack = require('webpack'); const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const ManifestPlugin = require('webpack-manifest-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin'); @@ -54,7 +55,7 @@ module.exports = { ] }, { - test: /\.scss$/i, + test: /\.s(c|a)ss$/i, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true }}, { loader: 'postcss-loader', options: { @@ -139,6 +140,13 @@ module.exports = { cache: true, parallel: true, sourceMap: true + }), + new OptimizeCSSAssetsPlugin({ + cssProcessorOptions: { + map: { + inline: false + } + } }) ], runtimeChunk: 'single', From bda32446e74e740ac6c01fd1463421c7d58d5f9d Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 15:32:43 +0100 Subject: [PATCH 41/46] chore(gitlab-ci): ssh key management --- .gitlab-ci.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 49a0ee85c..9546408ae 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,6 +33,11 @@ npm install: - n stable - npm install -g npm - hash -r + - apt-get install openssh-client -y + - install -m 0700 -d ~/.ssh + - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - eval $(ssh-agent -s) + - for keyVar in "${!SSH_PRIVATE_KEY_NPM_*}"; do install -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - node_modules/ @@ -78,6 +83,11 @@ yesod:build:dev: - apt-get update -y - apt-get install -y --no-install-recommends locales-all - ln -s $(which g++-7) $(dirname $(which g++-7))/g++ + - 'which ssh-agent || apt-get install openssh-client -y' + - install -m 0700 -d ~/.ssh + - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - eval $(ssh-agent -s) + - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - bin/ @@ -101,6 +111,11 @@ yesod:build: - apt-get update -y - apt-get install -y --no-install-recommends locales-all - ln -s $(which g++-7) $(dirname $(which g++-7))/g++ + - apt-get install -y --no-install-recommends openssh-client + - install -m 0700 -d ~/.ssh + - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - eval $(ssh-agent -s) + - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - bin/ @@ -227,7 +242,8 @@ deploy:uniworx3: - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - install -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/id + - eval $(ssh-agent -s) + - install -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/uniworx3; ssh-add ~/.ssh/uniworx3 dependencies: - yesod:build From 7e8d22def9bf157e4620bbdb3f811271b19e1e36 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 15:59:17 +0100 Subject: [PATCH 42/46] chore(gitlab-ci): prevent directory/target-file confusion --- .gitlab-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9546408ae..0b026483a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,9 +35,9 @@ npm install: - hash -r - apt-get install openssh-client -y - install -m 0700 -d ~/.ssh - - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - for keyVar in "${!SSH_PRIVATE_KEY_NPM_*}"; do install -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in "${!SSH_PRIVATE_KEY_NPM_*}"; do install -T -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - node_modules/ @@ -85,9 +85,9 @@ yesod:build:dev: - ln -s $(which g++-7) $(dirname $(which g++-7))/g++ - 'which ssh-agent || apt-get install openssh-client -y' - install -m 0700 -d ~/.ssh - - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -T -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - bin/ @@ -113,9 +113,9 @@ yesod:build: - ln -s $(which g++-7) $(dirname $(which g++-7))/g++ - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -T -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - bin/ @@ -241,9 +241,9 @@ deploy:uniworx3: - apt-get update -y - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - - install -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - install -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/uniworx3; ssh-add ~/.ssh/uniworx3 + - install -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3; ssh-add ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3 dependencies: - yesod:build From a4a23be381a38c50456cb7e339e56464a226663f Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 16:20:47 +0100 Subject: [PATCH 43/46] chore(gitlab-ci): fix quoting --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0b026483a..096842acb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ npm install: - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - for keyVar in "${!SSH_PRIVATE_KEY_NPM_*}"; do install -T -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in ${!SSH_PRIVATE_KEY_NPM_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - node_modules/ @@ -87,7 +87,7 @@ yesod:build:dev: - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -T -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - bin/ @@ -115,7 +115,7 @@ yesod:build: - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - eval $(ssh-agent -s) - - for keyVar in "${!SSH_PRIVATE_KEY_STACK_*}"; do install -T -m 0400 "${!keyVar}" ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done artifacts: paths: - bin/ From 40babb3f5987a6c6e5fc54fc57803a1e1768e68c Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 16:39:06 +0100 Subject: [PATCH 44/46] chore: fix stack.yaml link to encoding --- stack.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.yaml b/stack.yaml index 0d3e7a7cf..2764abce4 100644 --- a/stack.yaml +++ b/stack.yaml @@ -11,7 +11,7 @@ packages: - . extra-deps: - - git: git@gitlab2.rz.ifi.lmu.de:/uni2work/encoding.git + - git: git@gitlab2.rz.ifi.lmu.de:uni2work/encoding.git commit: 67bb87ceff53f0178c988dd4e15eeb2daee92b84 - git: git@gitlab2.rz.ifi.lmu.de:uni2work/memcached-binary.git commit: b5461747e7be226d3b67daebc3c9aefe8a4490ad From 58fca2297bb276ea8592cbbaecc062e91f691b50 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 17:05:26 +0100 Subject: [PATCH 45/46] chore(gitlab-ci): don't use ssh-agent --- .gitlab-ci.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 096842acb..e163d26ae 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,8 +36,7 @@ npm install: - apt-get install openssh-client -y - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - eval $(ssh-agent -s) - - for keyVar in ${!SSH_PRIVATE_KEY_NPM_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in ${!SSH_PRIVATE_KEY_NPM_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> .ssh/config; done artifacts: paths: - node_modules/ @@ -86,8 +85,7 @@ yesod:build:dev: - 'which ssh-agent || apt-get install openssh-client -y' - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - eval $(ssh-agent -s) - - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> .ssh/config; done artifacts: paths: - bin/ @@ -114,8 +112,7 @@ yesod:build: - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - eval $(ssh-agent -s) - - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; ssh-add ~/.ssh/${keyVar}; done + - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> .ssh/config; done artifacts: paths: - bin/ @@ -242,8 +239,7 @@ deploy:uniworx3: - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - eval $(ssh-agent -s) - - install -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3; ssh-add ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3 + - install -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3; echo "IdentityFile ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3" >> .ssh/config; dependencies: - yesod:build From 4dc73ccf7c43dd26d0ea1cbf8ff3c3af04e45e1b Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 18 Dec 2019 17:08:36 +0100 Subject: [PATCH 46/46] chore(gitlab-ci): fix path to ssh config --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e163d26ae..009c1c0b4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,7 +36,7 @@ npm install: - apt-get install openssh-client -y - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - for keyVar in ${!SSH_PRIVATE_KEY_NPM_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> .ssh/config; done + - for keyVar in ${!SSH_PRIVATE_KEY_NPM_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> ~/.ssh/config; done artifacts: paths: - node_modules/ @@ -85,7 +85,7 @@ yesod:build:dev: - 'which ssh-agent || apt-get install openssh-client -y' - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> .ssh/config; done + - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> ~/.ssh/config; done artifacts: paths: - bin/ @@ -112,7 +112,7 @@ yesod:build: - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> .ssh/config; done + - for keyVar in ${!SSH_PRIVATE_KEY_STACK_*}; do install -T -m 0400 ${!keyVar} ~/.ssh/${keyVar}; echo "IdentityFile ~/.ssh/${keyVar}" >> ~/.ssh/config; done artifacts: paths: - bin/ @@ -239,7 +239,7 @@ deploy:uniworx3: - apt-get install -y --no-install-recommends openssh-client - install -m 0700 -d ~/.ssh - install -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - install -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3; echo "IdentityFile ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3" >> .ssh/config; + - install -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3; echo "IdentityFile ~/.ssh/SSH_PRIVATE_KEY_UNIWORX3" >> ~/.ssh/config; dependencies: - yesod:build