From f70fc7b87ac04cd4c591e9f6816d84582194385e Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 12 Sep 2022 17:42:37 +0200 Subject: [PATCH 1/8] 94233: use actual CSS variables in theme --- .../admin-sidebar-section.component.spec.ts | 2 +- .../admin-sidebar.component.spec.ts | 2 +- .../admin-sidebar/admin-sidebar.component.ts | 4 +- ...le-admin-sidebar-section.component.spec.ts | 2 +- ...andable-admin-sidebar-section.component.ts | 4 +- src/app/app.component.spec.ts | 2 +- src/app/app.component.ts | 21 ++--- src/app/app.reducer.ts | 2 +- src/app/core/core.module.ts | 2 +- src/app/root/root.component.spec.ts | 2 +- src/app/root/root.component.ts | 6 +- src/app/shared/host-window.service.ts | 10 +-- src/app/shared/key-value-pair.model.ts | 4 + ...per.actions.ts => css-variable.actions.ts} | 0 ...per.reducer.ts => css-variable.reducer.ts} | 2 +- .../sass-helper/css-variable.service.spec.ts | 78 +++++++++++++++++++ .../sass-helper/css-variable.service.ts | 71 +++++++++++++++++ .../shared/sass-helper/css-variable.utils.ts | 46 +++++++++++ .../shared/sass-helper/sass-helper.service.ts | 30 ------- 19 files changed, 226 insertions(+), 64 deletions(-) create mode 100644 src/app/shared/key-value-pair.model.ts rename src/app/shared/sass-helper/{sass-helper.actions.ts => css-variable.actions.ts} (100%) rename src/app/shared/sass-helper/{sass-helper.reducer.ts => css-variable.reducer.ts} (85%) create mode 100644 src/app/shared/sass-helper/css-variable.service.spec.ts create mode 100644 src/app/shared/sass-helper/css-variable.service.ts create mode 100644 src/app/shared/sass-helper/css-variable.utils.ts delete mode 100644 src/app/shared/sass-helper/sass-helper.service.ts diff --git a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.spec.ts b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.spec.ts index 14d5d38199..1e28b62626 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.spec.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { MenuService } from '../../../shared/menu/menu.service'; import { MenuServiceStub } from '../../../shared/testing/menu-service.stub'; -import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service'; import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub'; import { Component } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts index 65026c1504..bcc40aae60 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -6,7 +6,7 @@ import { ScriptDataService } from '../../core/data/processes/script-data.service import { AdminSidebarComponent } from './admin-sidebar.component'; import { MenuService } from '../../shared/menu/menu.service'; import { MenuServiceStub } from '../../shared/testing/menu-service.stub'; -import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../../shared/sass-helper/css-variable.service'; import { CSSVariableServiceStub } from '../../shared/testing/css-variable-service.stub'; import { AuthServiceStub } from '../../shared/testing/auth-service.stub'; import { AuthService } from '../../core/auth/auth.service'; diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.ts index c81b2e6e93..777fc4a250 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.ts @@ -18,7 +18,7 @@ import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick import { TextMenuItemModel } from '../../shared/menu/menu-item/models/text.model'; import { MenuComponent } from '../../shared/menu/menu.component'; import { MenuService } from '../../shared/menu/menu.service'; -import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../../shared/sass-helper/css-variable.service'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../core/data/feature-authorization/feature-id'; import { Router, ActivatedRoute } from '@angular/router'; @@ -82,7 +82,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { ngOnInit(): void { this.createMenu(); super.ngOnInit(); - this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth'); + this.sidebarWidth = this.variableService.getVariable('--ds-sidebar-items-width'); this.authService.isAuthenticated() .subscribe((loggedIn: boolean) => { if (loggedIn) { diff --git a/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.spec.ts b/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.spec.ts index b1f3a63c06..0f0181c3d5 100644 --- a/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.spec.ts +++ b/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.spec.ts @@ -3,7 +3,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { ExpandableAdminSidebarSectionComponent } from './expandable-admin-sidebar-section.component'; import { MenuService } from '../../../shared/menu/menu.service'; import { MenuServiceStub } from '../../../shared/testing/menu-service.stub'; -import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service'; import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub'; import { of as observableOf } from 'rxjs'; import { Component } from '@angular/core'; diff --git a/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.ts b/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.ts index aaa6a85c51..59f07979bb 100644 --- a/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.ts +++ b/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.ts @@ -2,7 +2,7 @@ import { Component, Inject, Injector, OnInit } from '@angular/core'; import { rotate } from '../../../shared/animations/rotate'; import { AdminSidebarSectionComponent } from '../admin-sidebar-section/admin-sidebar-section.component'; import { slide } from '../../../shared/animations/slide'; -import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service'; import { bgColor } from '../../../shared/animations/bgColor'; import { MenuID } from '../../../shared/menu/initial-menus-state'; import { MenuService } from '../../../shared/menu/menu.service'; @@ -65,7 +65,7 @@ export class ExpandableAdminSidebarSectionComponent extends AdminSidebarSectionC */ ngOnInit(): void { super.ngOnInit(); - this.sidebarActiveBg = this.variableService.getVariable('adminSidebarActiveBg'); + this.sidebarActiveBg = this.variableService.getVariable('--ds-admin-sidebar-active-bg'); this.sidebarCollapsed = this.menuService.isMenuCollapsed(this.menuID); this.sidebarPreviewCollapsed = this.menuService.isMenuPreviewCollapsed(this.menuID); this.expanded = combineLatestObservable(this.active, this.sidebarCollapsed, this.sidebarPreviewCollapsed) diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index a892e34a5a..dcbf11525e 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -19,7 +19,7 @@ import { AngularticsProviderMock } from './shared/mocks/angulartics-provider.ser import { AuthServiceMock } from './shared/mocks/auth.service.mock'; import { AuthService } from './core/auth/auth.service'; import { MenuService } from './shared/menu/menu.service'; -import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from './shared/sass-helper/css-variable.service'; import { CSSVariableServiceStub } from './shared/testing/css-variable-service.stub'; import { MenuServiceStub } from './shared/testing/menu-service.stub'; import { HostWindowService } from './shared/host-window.service'; diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 669411d9aa..0c38d2bd64 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -31,7 +31,7 @@ import { HostWindowState } from './shared/search/host-window.reducer'; import { NativeWindowRef, NativeWindowService } from './core/services/window.service'; import { isAuthenticationBlocking } from './core/auth/selectors'; import { AuthService } from './core/auth/auth.service'; -import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from './shared/sass-helper/css-variable.service'; import { MenuService } from './shared/menu/menu.service'; import { HostWindowService } from './shared/host-window.service'; import { HeadTagConfig, ThemeConfig } from '../config/theme.model'; @@ -48,6 +48,7 @@ import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service'; import { IdleModalComponent } from './shared/idle-modal/idle-modal.component'; import { getDefaultThemeConfig } from '../config/config.util'; import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; +import { getCSSCustomPropIndex } from './shared/sass-helper/css-variable.utils'; @Component({ selector: 'ds-app', @@ -161,7 +162,6 @@ export class AppComponent implements OnInit, AfterViewInit { if (environment.debug) { console.info(environment); } - this.storeCSSVariables(); } ngOnInit() { @@ -181,18 +181,9 @@ export class AppComponent implements OnInit, AfterViewInit { } private storeCSSVariables() { - this.cssService.addCSSVariable('xlMin', '1200px'); - this.cssService.addCSSVariable('mdMin', '768px'); - this.cssService.addCSSVariable('lgMin', '576px'); - this.cssService.addCSSVariable('smMin', '0'); - this.cssService.addCSSVariable('adminSidebarActiveBg', '#0f1b28'); - this.cssService.addCSSVariable('sidebarItemsWidth', '250px'); - this.cssService.addCSSVariable('collapsedSidebarWidth', '53.234px'); - this.cssService.addCSSVariable('totalSidebarWidth', '303.234px'); - // const vars = variables.locals || {}; - // Object.keys(vars).forEach((name: string) => { - // this.cssService.addCSSVariable(name, vars[name]); - // }) + getCSSCustomPropIndex(this.document).forEach(([prop, val]) => { + this.cssService.addCSSVariable(prop, val); + }); } ngAfterViewInit() { @@ -282,6 +273,8 @@ export class AppComponent implements OnInit, AfterViewInit { } // the fact that this callback is used, proves we're on the browser. this.isThemeCSSLoading$.next(false); + + this.storeCSSVariables(); }; head.appendChild(link); } diff --git a/src/app/app.reducer.ts b/src/app/app.reducer.ts index 5bd4f745d9..23d38bae30 100644 --- a/src/app/app.reducer.ts +++ b/src/app/app.reducer.ts @@ -35,7 +35,7 @@ import { ObjectSelectionListState, objectSelectionReducer } from './shared/object-select/object-select.reducer'; -import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/sass-helper.reducer'; +import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/css-variable.reducer'; import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer'; import { diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 8d8a614a89..2a4c75545e 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -23,7 +23,7 @@ import { NotificationsService } from '../shared/notifications/notifications.serv import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service'; import { ObjectSelectService } from '../shared/object-select/object-select.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../shared/sass-helper/css-variable.service'; import { SidebarService } from '../shared/sidebar/sidebar.service'; import { UploaderService } from '../shared/uploader/uploader.service'; import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service'; diff --git a/src/app/root/root.component.spec.ts b/src/app/root/root.component.spec.ts index 81b22592d6..2d41b8b610 100644 --- a/src/app/root/root.component.spec.ts +++ b/src/app/root/root.component.spec.ts @@ -18,7 +18,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { RouterMock } from '../shared/mocks/router.mock'; import { MockActivatedRoute } from '../shared/mocks/active-router.mock'; import { MenuService } from '../shared/menu/menu.service'; -import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../shared/sass-helper/css-variable.service'; import { CSSVariableServiceStub } from '../shared/testing/css-variable-service.stub'; import { HostWindowService } from '../shared/host-window.service'; import { HostWindowServiceStub } from '../shared/testing/host-window-service.stub'; diff --git a/src/app/root/root.component.ts b/src/app/root/root.component.ts index dc44095573..8584af357e 100644 --- a/src/app/root/root.component.ts +++ b/src/app/root/root.component.ts @@ -11,7 +11,7 @@ import { MetadataService } from '../core/metadata/metadata.service'; import { HostWindowState } from '../shared/search/host-window.reducer'; import { NativeWindowRef, NativeWindowService } from '../core/services/window.service'; import { AuthService } from '../core/auth/auth.service'; -import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../shared/sass-helper/css-variable.service'; import { MenuService } from '../shared/menu/menu.service'; import { MenuID } from '../shared/menu/initial-menus-state'; import { HostWindowService } from '../shared/host-window.service'; @@ -65,8 +65,8 @@ export class RootComponent implements OnInit { ngOnInit() { this.sidebarVisible = this.menuService.isMenuVisible(MenuID.ADMIN); - this.collapsedSidebarWidth = this.cssService.getVariable('collapsedSidebarWidth'); - this.totalSidebarWidth = this.cssService.getVariable('totalSidebarWidth'); + this.collapsedSidebarWidth = this.cssService.getVariable('--ds-collapsed-sidebar-width'); + this.totalSidebarWidth = this.cssService.getVariable('--ds-total-sidebar-width'); const sidebarCollapsed = this.menuService.isMenuCollapsed(MenuID.ADMIN); this.slideSidebarOver = combineLatestObservable([sidebarCollapsed, this.windowService.isXsOrSm()]) diff --git a/src/app/shared/host-window.service.ts b/src/app/shared/host-window.service.ts index 443dd40b14..6d13d921e0 100644 --- a/src/app/shared/host-window.service.ts +++ b/src/app/shared/host-window.service.ts @@ -7,7 +7,7 @@ import { createSelector, select, Store } from '@ngrx/store'; import { hasValue } from './empty.util'; import { AppState } from '../app.reducer'; -import { CSSVariableService } from './sass-helper/sass-helper.service'; +import { CSSVariableService } from './sass-helper/css-variable.service'; export enum WidthCategory { XS, @@ -31,10 +31,10 @@ export class HostWindowService { /* See _exposed_variables.scss */ variableService.getAllVariables() .subscribe((variables) => { - this.breakPoints.XL_MIN = parseInt(variables.xlMin, 10); - this.breakPoints.LG_MIN = parseInt(variables.lgMin, 10); - this.breakPoints.MD_MIN = parseInt(variables.mdMin, 10); - this.breakPoints.SM_MIN = parseInt(variables.smMin, 10); + this.breakPoints.XL_MIN = parseInt(variables['--bs-xl-min'], 10); + this.breakPoints.LG_MIN = parseInt(variables['--bs-lg-min'], 10); + this.breakPoints.MD_MIN = parseInt(variables['--bs-md-min'], 10); + this.breakPoints.SM_MIN = parseInt(variables['--bs-sm-min'], 10); }); } diff --git a/src/app/shared/key-value-pair.model.ts b/src/app/shared/key-value-pair.model.ts new file mode 100644 index 0000000000..6fb63070ad --- /dev/null +++ b/src/app/shared/key-value-pair.model.ts @@ -0,0 +1,4 @@ +export interface KeyValuePair { + key: K; + value: V; +} diff --git a/src/app/shared/sass-helper/sass-helper.actions.ts b/src/app/shared/sass-helper/css-variable.actions.ts similarity index 100% rename from src/app/shared/sass-helper/sass-helper.actions.ts rename to src/app/shared/sass-helper/css-variable.actions.ts diff --git a/src/app/shared/sass-helper/sass-helper.reducer.ts b/src/app/shared/sass-helper/css-variable.reducer.ts similarity index 85% rename from src/app/shared/sass-helper/sass-helper.reducer.ts rename to src/app/shared/sass-helper/css-variable.reducer.ts index 6f080619fa..a196304c92 100644 --- a/src/app/shared/sass-helper/sass-helper.reducer.ts +++ b/src/app/shared/sass-helper/css-variable.reducer.ts @@ -1,4 +1,4 @@ -import { CSSVariableAction, CSSVariableActionTypes } from './sass-helper.actions'; +import { CSSVariableAction, CSSVariableActionTypes } from './css-variable.actions'; export interface CSSVariablesState { [name: string]: string; diff --git a/src/app/shared/sass-helper/css-variable.service.spec.ts b/src/app/shared/sass-helper/css-variable.service.spec.ts new file mode 100644 index 0000000000..4fd33591f5 --- /dev/null +++ b/src/app/shared/sass-helper/css-variable.service.spec.ts @@ -0,0 +1,78 @@ +import { TestBed } from '@angular/core/testing'; +import { CSSVariableService } from './css-variable.service'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { getTestScheduler } from 'jasmine-marbles'; +import { buildPaginatedList } from '../../core/data/paginated-list.model'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { KeyValuePair } from '../key-value-pair.model'; + +describe('CSSVariableService', () => { + let store: MockStore; + + let service: CSSVariableService; + let initialState; + const varKey1 = '--test-1'; + const varValue1 = 'test-value-1'; + const varKey2 = '--test-2'; + const varValue2 = 'test-value-2'; + const varKey3 = '--test-3'; + const varValue3 = 'test-value-3'; + const queryInAll = 'test'; + const queryFor3 = '3'; + + function init() { + initialState = { + ['cssVariables']: { + [varKey1]: varValue1, + [varKey2]: varValue2, + [varKey3]: varValue3, + } + }; + } + + beforeEach(() => { + init(); + TestBed.configureTestingModule({ + providers: [ + CSSVariableService, + provideMockStore({ initialState }), + ], + }); + service = TestBed.inject(CSSVariableService as any); + store = TestBed.inject(MockStore as any); + }); + + it('should create', () => { + expect(service).toBeTruthy(); + }); + + fdescribe('searchVariable', () => { + it('should return the right keys and variables in a paginated list for query that returns all 3 results', () => { + const currentPage = 1; + const pageSize = 5; + const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalPages: 1, totalElements: 3 }); + const page: KeyValuePair[] = [{ key: varKey1, value: varValue1 }, { key: varKey2, value: varValue2 }, { key: varKey3, value: varValue3 }]; + const result = buildPaginatedList(pageInfo, page); + getTestScheduler().expectObservable(service.searchVariable(queryInAll, { currentPage, pageSize } as any)).toBe('a', { a: result }); + }); + + it('should return the right keys and variables in a paginated list for query that returns only the 3rd results', () => { + const currentPage = 1; + const pageSize = 5; + const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalPages: 1, totalElements: 1 }); + const page: KeyValuePair[] = [{ key: varKey3, value: varValue3 }]; + const result = buildPaginatedList(pageInfo, page); + getTestScheduler().expectObservable(service.searchVariable(queryFor3, { currentPage, pageSize } as any)).toBe('a', { a: result }); + }); + + it('should return the right keys and variables in a paginated list that\'s not longer than the page size', () => { + const currentPage = 1; + const pageSize = 2; + const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalPages: 2, totalElements: 3 }); + const page: KeyValuePair[] = [{ key: varKey1, value: varValue1 }, { key: varKey2, value: varValue2 }]; + const result = buildPaginatedList(pageInfo, page); + getTestScheduler().expectObservable(service.searchVariable(queryInAll, { currentPage, pageSize } as any)).toBe('a', { a: result }); + }); + }); + +}); diff --git a/src/app/shared/sass-helper/css-variable.service.ts b/src/app/shared/sass-helper/css-variable.service.ts new file mode 100644 index 0000000000..3e0ed7f214 --- /dev/null +++ b/src/app/shared/sass-helper/css-variable.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@angular/core'; +import { AppState, keySelector } from '../../app.reducer'; +import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; +import { AddCSSVariableAction } from './css-variable.actions'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; +import { Observable } from 'rxjs'; +import { hasValue } from '../empty.util'; +import { KeyValuePair } from '../key-value-pair.model'; +import { PageInfo } from '../../core/shared/page-info.model'; + +@Injectable() +export class CSSVariableService { + constructor( + protected store: Store) { + } + + addCSSVariable(name: string, value: string) { + this.store.dispatch(new AddCSSVariableAction(name, value)); + } + + getVariable(name: string) { + return this.store.pipe(select(themeVariableByNameSelector(name))); + } + + getAllVariables() { + return this.store.pipe(select(themeVariablesSelector)); + } + + searchVariable(query: string, paginationOptions: PaginationComponentOptions): Observable>> { + return this.store.pipe(select(themePaginatedVariablesByQuery(query, paginationOptions))); + } +} + +const themeVariablesSelector = (state: AppState) => state.cssVariables; + +const themeVariableByNameSelector = (name: string): MemoizedSelector => { + return keySelector(name, themeVariablesSelector); +}; + +// Split this up into two memoized selectors so the query search gets cached separately from the pagination, +// since the entire list has to be retrieved every time anyway +const themePaginatedVariablesByQuery = (query: string, pagination: PaginationComponentOptions): MemoizedSelector>> => { + return createSelector(themeVariablesByQuery(query), (pairs) => { + if (hasValue(pairs)) { + const { currentPage, pageSize } = pagination; + const startIndex = (currentPage - 1) * pageSize; + const endIndex = startIndex + pageSize; + const pairsPage = pairs.slice(startIndex, endIndex); + const totalPages = Math.ceil(pairs.length / pageSize); + const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalElements: pairs.length, totalPages }); + return buildPaginatedList(pageInfo, pairsPage); + } else { + return undefined; + } + }); +}; + +const themeVariablesByQuery = (query: string): MemoizedSelector[]> => { + return createSelector(themeVariablesSelector, (state) => { + if (hasValue(state)) { + return Object.keys(state) + .filter((key: string) => key.includes(query)) + .map((key: string) => { + return { key, value: state[key] }; + }); + } else { + return undefined; + } + }); +}; diff --git a/src/app/shared/sass-helper/css-variable.utils.ts b/src/app/shared/sass-helper/css-variable.utils.ts new file mode 100644 index 0000000000..63a93b8bc4 --- /dev/null +++ b/src/app/shared/sass-helper/css-variable.utils.ts @@ -0,0 +1,46 @@ +// Uses code from https://css-tricks.com/how-to-get-all-custom-properties-on-a-page-in-javascript/ + +const isSameDomain = (styleSheet) => { + // Internal style blocks won't have an href value + if (!styleSheet.href) { + return true; + } + + return styleSheet.href.indexOf(window.location.origin) === 0; +}; + +/* + Determine if the given rule is a CSSStyleRule + See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule#Type_constants +*/ +const isStyleRule = (rule) => rule.type === 1; + +/** + * Get all custom properties on a page + * @return array + * ex; [["--color-accent", "#b9f500"], ["--color-text", "#252525"], ...] + */ +export const getCSSCustomPropIndex = (document: Document) => + // styleSheets is array-like, so we convert it to an array. + // Filter out any stylesheets not on this domain + [...document.styleSheets] + .filter(isSameDomain) + .reduce( + (finalArr, sheet) => + finalArr.concat( + // cssRules is array-like, so we convert it to an array + [...sheet.cssRules].filter(isStyleRule).reduce((propValArr, rule: any) => { + const props = [...rule.style] + .map((propName) => [ + propName.trim(), + rule.style.getPropertyValue(propName).trim() + ]) + // Discard any props that don't start with "--". Custom props are required to. + .filter(([propName]) => propName.indexOf('--') === 0); + + return [...propValArr, ...props]; + }, []) + ), + [] + ); + diff --git a/src/app/shared/sass-helper/sass-helper.service.ts b/src/app/shared/sass-helper/sass-helper.service.ts deleted file mode 100644 index 7cc83dab2d..0000000000 --- a/src/app/shared/sass-helper/sass-helper.service.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from '@angular/core'; -import { AppState, keySelector } from '../../app.reducer'; -import { MemoizedSelector, select, Store } from '@ngrx/store'; -import { AddCSSVariableAction } from './sass-helper.actions'; - -@Injectable() -export class CSSVariableService { - constructor( - protected store: Store) { - } - - addCSSVariable(name: string, value: string) { - this.store.dispatch(new AddCSSVariableAction(name, value)); - } - - getVariable(name: string) { - return this.store.pipe(select(themeVariableByNameSelector(name))); - } - - getAllVariables() { - return this.store.pipe(select(themeVariablesSelector)); - } - -} - -const themeVariablesSelector = (state: AppState) => state.cssVariables; - -const themeVariableByNameSelector = (name: string): MemoizedSelector => { - return keySelector(name, themeVariablesSelector); -}; From ac094aa623bfb1d83e540f82ff4a6487287cffd4 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 13 Sep 2022 12:22:55 +0200 Subject: [PATCH 2/8] 94233: added typedoc --- .../sass-helper/css-variable.reducer.ts | 8 ++++++-- .../sass-helper/css-variable.service.ts | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/app/shared/sass-helper/css-variable.reducer.ts b/src/app/shared/sass-helper/css-variable.reducer.ts index a196304c92..a2d150dabf 100644 --- a/src/app/shared/sass-helper/css-variable.reducer.ts +++ b/src/app/shared/sass-helper/css-variable.reducer.ts @@ -6,12 +6,16 @@ export interface CSSVariablesState { const initialState: CSSVariablesState = Object.create({}); +/** + * Reducer that handles the state of CSS variables in the store + * @param state The current state of the store + * @param action The action to apply onto the current state of the store + */ export function cssVariablesReducer(state = initialState, action: CSSVariableAction): CSSVariablesState { switch (action.type) { case CSSVariableActionTypes.ADD: { const variable = action.payload; - const t = Object.assign({}, state, { [variable.name]: variable.value }); - return t; + return Object.assign({}, state, { [variable.name]: variable.value }); } default: { return state; diff --git a/src/app/shared/sass-helper/css-variable.service.ts b/src/app/shared/sass-helper/css-variable.service.ts index 3e0ed7f214..bdcba8503e 100644 --- a/src/app/shared/sass-helper/css-variable.service.ts +++ b/src/app/shared/sass-helper/css-variable.service.ts @@ -9,24 +9,44 @@ import { hasValue } from '../empty.util'; import { KeyValuePair } from '../key-value-pair.model'; import { PageInfo } from '../../core/shared/page-info.model'; +/** + * This service deals with adding and retrieving CSS variables to and from the store + */ @Injectable() export class CSSVariableService { constructor( protected store: Store) { } + /** + * Adds a CSS variable to the store + * @param name The name/key of the CSS variable + * @param value The value of the CSS variable + */ addCSSVariable(name: string, value: string) { this.store.dispatch(new AddCSSVariableAction(name, value)); } + /** + * Returns the value of a specific CSS key + * @param name The name/key of the CSS value + */ getVariable(name: string) { return this.store.pipe(select(themeVariableByNameSelector(name))); } + /** + * Returns the CSSVariablesState of the store containing all variables + */ getAllVariables() { return this.store.pipe(select(themeVariablesSelector)); } + /** + * Method to find CSS variables by their partially supplying their key. Case sensitive. Returns a paginated list of KeyValuePairs with CSS variables that match the query. + * @param query The query to look for in the keys + * @param paginationOptions The pagination options for the requested page + */ searchVariable(query: string, paginationOptions: PaginationComponentOptions): Observable>> { return this.store.pipe(select(themePaginatedVariablesByQuery(query, paginationOptions))); } From 89ba24fc1c1df13cfecdf12ebe59883901980d28 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 16 Sep 2022 12:40:04 +0200 Subject: [PATCH 3/8] 94233: applied feedback for css variables --- src/app/app.component.ts | 6 +- .../sass-helper/css-variable.actions.ts | 20 +++++- .../sass-helper/css-variable.reducer.ts | 6 ++ .../sass-helper/css-variable.service.ts | 71 ++++++++++++++++++- .../shared/sass-helper/css-variable.utils.ts | 44 +----------- 5 files changed, 96 insertions(+), 51 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0c38d2bd64..32753ce74c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -48,7 +48,6 @@ import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service'; import { IdleModalComponent } from './shared/idle-modal/idle-modal.component'; import { getDefaultThemeConfig } from '../config/config.util'; import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; -import { getCSSCustomPropIndex } from './shared/sass-helper/css-variable.utils'; @Component({ selector: 'ds-app', @@ -181,9 +180,8 @@ export class AppComponent implements OnInit, AfterViewInit { } private storeCSSVariables() { - getCSSCustomPropIndex(this.document).forEach(([prop, val]) => { - this.cssService.addCSSVariable(prop, val); - }); + this.cssService.clearCSSVariables(); + this.cssService.addCSSVariables(this.cssService.getCSSVariablesFromStylesheets(this.document)); } ngAfterViewInit() { diff --git a/src/app/shared/sass-helper/css-variable.actions.ts b/src/app/shared/sass-helper/css-variable.actions.ts index 144904646e..93225f9426 100644 --- a/src/app/shared/sass-helper/css-variable.actions.ts +++ b/src/app/shared/sass-helper/css-variable.actions.ts @@ -1,5 +1,6 @@ import { Action } from '@ngrx/store'; import { type } from '../ngrx/type'; +import { KeyValuePair } from '../key-value-pair.model'; /** * For each action type in an action group, make a simple @@ -11,6 +12,8 @@ import { type } from '../ngrx/type'; */ export const CSSVariableActionTypes = { ADD: type('dspace/css-variables/ADD'), + ADD_ALL: type('dspace/css-variables/ADD_ALL'), + CLEAR: type('dspace/css-variables/CLEAR'), }; export class AddCSSVariableAction implements Action { @@ -24,5 +27,20 @@ export class AddCSSVariableAction implements Action { this.payload = {name, value}; } } +export class AddAllCSSVariablesAction implements Action { + type = CSSVariableActionTypes.ADD_ALL; + payload: KeyValuePair[]; -export type CSSVariableAction = AddCSSVariableAction; + constructor(variables: KeyValuePair[]) { + this.payload = variables; + } +} + +export class ClearCSSVariablesAction implements Action { + type = CSSVariableActionTypes.CLEAR; + + constructor() { + } +} + +export type CSSVariableAction = AddCSSVariableAction | AddAllCSSVariablesAction | ClearCSSVariablesAction; diff --git a/src/app/shared/sass-helper/css-variable.reducer.ts b/src/app/shared/sass-helper/css-variable.reducer.ts index a2d150dabf..405cbf5df4 100644 --- a/src/app/shared/sass-helper/css-variable.reducer.ts +++ b/src/app/shared/sass-helper/css-variable.reducer.ts @@ -1,4 +1,5 @@ import { CSSVariableAction, CSSVariableActionTypes } from './css-variable.actions'; +import { KeyValuePair } from '../key-value-pair.model'; export interface CSSVariablesState { [name: string]: string; @@ -16,6 +17,11 @@ export function cssVariablesReducer(state = initialState, action: CSSVariableAct case CSSVariableActionTypes.ADD: { const variable = action.payload; return Object.assign({}, state, { [variable.name]: variable.value }); + } case CSSVariableActionTypes.ADD_ALL: { + const variables = action.payload; + return Object.assign({}, state, ...variables.map(({ key, value }: KeyValuePair) => {return {[key]: value}})); + } case CSSVariableActionTypes.CLEAR: { + return initialState; } default: { return state; diff --git a/src/app/shared/sass-helper/css-variable.service.ts b/src/app/shared/sass-helper/css-variable.service.ts index bdcba8503e..9ba9dfca3c 100644 --- a/src/app/shared/sass-helper/css-variable.service.ts +++ b/src/app/shared/sass-helper/css-variable.service.ts @@ -1,19 +1,35 @@ import { Injectable } from '@angular/core'; import { AppState, keySelector } from '../../app.reducer'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; -import { AddCSSVariableAction } from './css-variable.actions'; +import { AddAllCSSVariablesAction, AddCSSVariableAction, ClearCSSVariablesAction } from './css-variable.actions'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; import { Observable } from 'rxjs'; import { hasValue } from '../empty.util'; import { KeyValuePair } from '../key-value-pair.model'; import { PageInfo } from '../../core/shared/page-info.model'; +import { CSSVariablesState } from './css-variable.reducer'; /** * This service deals with adding and retrieving CSS variables to and from the store */ @Injectable() export class CSSVariableService { + isSameDomain = (styleSheet) => { + // Internal style blocks won't have an href value + if (!styleSheet.href) { + return true; + } + + return styleSheet.href.indexOf(window.location.origin) === 0; + }; + + /* + Determine if the given rule is a CSSStyleRule + See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule#Type_constants + */ + isStyleRule = (rule) => rule.type === 1; + constructor( protected store: Store) { } @@ -27,18 +43,33 @@ export class CSSVariableService { this.store.dispatch(new AddCSSVariableAction(name, value)); } + /** + * Adds multiples CSS variables to the store + * @param variables The key-value pairs with the CSS variables to be added + */ + addCSSVariables(variables: KeyValuePair[]) { + this.store.dispatch(new AddAllCSSVariablesAction(variables)); + } + + /** + * Clears all CSS variables ƒrom the store + */ + clearCSSVariables() { + this.store.dispatch(new ClearCSSVariablesAction()); + } + /** * Returns the value of a specific CSS key * @param name The name/key of the CSS value */ - getVariable(name: string) { + getVariable(name: string): Observable { return this.store.pipe(select(themeVariableByNameSelector(name))); } /** * Returns the CSSVariablesState of the store containing all variables */ - getAllVariables() { + getAllVariables(): Observable { return this.store.pipe(select(themeVariablesSelector)); } @@ -50,6 +81,40 @@ export class CSSVariableService { searchVariable(query: string, paginationOptions: PaginationComponentOptions): Observable>> { return this.store.pipe(select(themePaginatedVariablesByQuery(query, paginationOptions))); } + + /** + * Get all custom properties on a page + * @return array> + * ex; [{key: "--color-accent", value: "#b9f500"}, {key: "--color-text", value: "#252525"}, ...] + */ + getCSSVariablesFromStylesheets(document: Document): KeyValuePair[] + { + // styleSheets is array-like, so we convert it to an array. + // Filter out any stylesheets not on this domain + return [...document.styleSheets] + .filter(this.isSameDomain) + .reduce( + (finalArr, sheet) => + finalArr.concat( + // cssRules is array-like, so we convert it to an array + [...sheet.cssRules].filter(this.isStyleRule).reduce((propValArr, rule: any) => { + const props = [...rule.style] + .map((propName) => { + return { + key: propName.trim(), + value: rule.style.getPropertyValue(propName).trim() + } as KeyValuePair; + } + ) + // Discard any props that don't start with "--". Custom props are required to. + .filter(({ key }: KeyValuePair) => key.indexOf('--') === 0); + + return [...propValArr, ...props]; + }, []) + ), + [] + ); + } } const themeVariablesSelector = (state: AppState) => state.cssVariables; diff --git a/src/app/shared/sass-helper/css-variable.utils.ts b/src/app/shared/sass-helper/css-variable.utils.ts index 63a93b8bc4..05e3074f98 100644 --- a/src/app/shared/sass-helper/css-variable.utils.ts +++ b/src/app/shared/sass-helper/css-variable.utils.ts @@ -1,46 +1,4 @@ // Uses code from https://css-tricks.com/how-to-get-all-custom-properties-on-a-page-in-javascript/ -const isSameDomain = (styleSheet) => { - // Internal style blocks won't have an href value - if (!styleSheet.href) { - return true; - } - - return styleSheet.href.indexOf(window.location.origin) === 0; -}; - -/* - Determine if the given rule is a CSSStyleRule - See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule#Type_constants -*/ -const isStyleRule = (rule) => rule.type === 1; - -/** - * Get all custom properties on a page - * @return array - * ex; [["--color-accent", "#b9f500"], ["--color-text", "#252525"], ...] - */ -export const getCSSCustomPropIndex = (document: Document) => - // styleSheets is array-like, so we convert it to an array. - // Filter out any stylesheets not on this domain - [...document.styleSheets] - .filter(isSameDomain) - .reduce( - (finalArr, sheet) => - finalArr.concat( - // cssRules is array-like, so we convert it to an array - [...sheet.cssRules].filter(isStyleRule).reduce((propValArr, rule: any) => { - const props = [...rule.style] - .map((propName) => [ - propName.trim(), - rule.style.getPropertyValue(propName).trim() - ]) - // Discard any props that don't start with "--". Custom props are required to. - .filter(([propName]) => propName.indexOf('--') === 0); - - return [...propValArr, ...props]; - }, []) - ), - [] - ); +import { KeyValuePair } from '../key-value-pair.model'; From ce67003f26478f2ef225c82e0466642454a0cd6d Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 16 Sep 2022 16:23:11 +0200 Subject: [PATCH 4/8] 94233: fixed tests after CSSVariableService changes --- src/app/shared/sass-helper/css-variable.service.spec.ts | 2 +- src/app/shared/testing/css-variable-service.stub.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/shared/sass-helper/css-variable.service.spec.ts b/src/app/shared/sass-helper/css-variable.service.spec.ts index 4fd33591f5..559384a5d7 100644 --- a/src/app/shared/sass-helper/css-variable.service.spec.ts +++ b/src/app/shared/sass-helper/css-variable.service.spec.ts @@ -46,7 +46,7 @@ describe('CSSVariableService', () => { expect(service).toBeTruthy(); }); - fdescribe('searchVariable', () => { + describe('searchVariable', () => { it('should return the right keys and variables in a paginated list for query that returns all 3 results', () => { const currentPage = 1; const pageSize = 5; diff --git a/src/app/shared/testing/css-variable-service.stub.ts b/src/app/shared/testing/css-variable-service.stub.ts index 6159d89655..f72e338455 100644 --- a/src/app/shared/testing/css-variable-service.stub.ts +++ b/src/app/shared/testing/css-variable-service.stub.ts @@ -1,10 +1,10 @@ import { Observable, of as observableOf } from 'rxjs'; const variables = { - smMin: '576px,', - mdMin: '768px,', - lgMin: '992px', - xlMin: '1200px', + '--bs-sm-min': '576px,', + '--bs-md-min': '768px,', + '--bs-lg-min': '992px', + '--bs-xl-min': '1200px', } as any; export class CSSVariableServiceStub { From d68f38e848ec06c02f4d9445fe1c9fdbea764fa8 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 22 Sep 2022 17:07:09 +0200 Subject: [PATCH 5/8] 94233: Fixed tests --- src/app/shared/sass-helper/css-variable.actions.ts | 4 +--- src/app/shared/sass-helper/css-variable.reducer.ts | 2 +- src/app/shared/sass-helper/css-variable.service.ts | 3 +-- src/app/shared/testing/css-variable-service.stub.ts | 13 +++++++++++++ src/modules/app/server-init.service.ts | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/app/shared/sass-helper/css-variable.actions.ts b/src/app/shared/sass-helper/css-variable.actions.ts index 93225f9426..2d58a2978b 100644 --- a/src/app/shared/sass-helper/css-variable.actions.ts +++ b/src/app/shared/sass-helper/css-variable.actions.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { Action } from '@ngrx/store'; import { type } from '../ngrx/type'; import { KeyValuePair } from '../key-value-pair.model'; @@ -38,9 +39,6 @@ export class AddAllCSSVariablesAction implements Action { export class ClearCSSVariablesAction implements Action { type = CSSVariableActionTypes.CLEAR; - - constructor() { - } } export type CSSVariableAction = AddCSSVariableAction | AddAllCSSVariablesAction | ClearCSSVariablesAction; diff --git a/src/app/shared/sass-helper/css-variable.reducer.ts b/src/app/shared/sass-helper/css-variable.reducer.ts index 405cbf5df4..449a936b4e 100644 --- a/src/app/shared/sass-helper/css-variable.reducer.ts +++ b/src/app/shared/sass-helper/css-variable.reducer.ts @@ -19,7 +19,7 @@ export function cssVariablesReducer(state = initialState, action: CSSVariableAct return Object.assign({}, state, { [variable.name]: variable.value }); } case CSSVariableActionTypes.ADD_ALL: { const variables = action.payload; - return Object.assign({}, state, ...variables.map(({ key, value }: KeyValuePair) => {return {[key]: value}})); + return Object.assign({}, state, ...variables.map(({ key, value }: KeyValuePair) => {return {[key]: value};})); } case CSSVariableActionTypes.CLEAR: { return initialState; } diff --git a/src/app/shared/sass-helper/css-variable.service.ts b/src/app/shared/sass-helper/css-variable.service.ts index 9ba9dfca3c..af40c634fd 100644 --- a/src/app/shared/sass-helper/css-variable.service.ts +++ b/src/app/shared/sass-helper/css-variable.service.ts @@ -87,8 +87,7 @@ export class CSSVariableService { * @return array> * ex; [{key: "--color-accent", value: "#b9f500"}, {key: "--color-text", value: "#252525"}, ...] */ - getCSSVariablesFromStylesheets(document: Document): KeyValuePair[] - { + getCSSVariablesFromStylesheets(document: Document): KeyValuePair[] { // styleSheets is array-like, so we convert it to an array. // Filter out any stylesheets not on this domain return [...document.styleSheets] diff --git a/src/app/shared/testing/css-variable-service.stub.ts b/src/app/shared/testing/css-variable-service.stub.ts index f72e338455..47be5c0ff4 100644 --- a/src/app/shared/testing/css-variable-service.stub.ts +++ b/src/app/shared/testing/css-variable-service.stub.ts @@ -1,4 +1,5 @@ import { Observable, of as observableOf } from 'rxjs'; +import { KeyValuePair } from '../key-value-pair.model'; const variables = { '--bs-sm-min': '576px,', @@ -19,4 +20,16 @@ export class CSSVariableServiceStub { addCSSVariable(name: string, value: string): void { /**/ } + + addCSSVariables(variables: KeyValuePair[]): void { + /**/ + } + + clearCSSVariables(): void { + /**/ + } + + getCSSVariablesFromStylesheets(document: Document): void { + /**/ + } } diff --git a/src/modules/app/server-init.service.ts b/src/modules/app/server-init.service.ts index e93c692cd7..9f6aa65921 100644 --- a/src/modules/app/server-init.service.ts +++ b/src/modules/app/server-init.service.ts @@ -18,7 +18,7 @@ import { LocaleService } from '../../app/core/locale/locale.service'; import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider'; import { MetadataService } from '../../app/core/metadata/metadata.service'; import { BreadcrumbsService } from '../../app/breadcrumbs/breadcrumbs.service'; -import { CSSVariableService } from '../../app/shared/sass-helper/sass-helper.service'; +import { CSSVariableService } from '../../sass-helper/css-variable.service'; import { ThemeService } from '../../app/shared/theme-support/theme.service'; import { take } from 'rxjs/operators'; From 97bceffb0272d095f1c1826b2daabca26034c4a4 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 22 Sep 2022 17:14:55 +0200 Subject: [PATCH 6/8] 94233: Fixed lint issue --- src/app/shared/testing/css-variable-service.stub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/testing/css-variable-service.stub.ts b/src/app/shared/testing/css-variable-service.stub.ts index 47be5c0ff4..2f5c647945 100644 --- a/src/app/shared/testing/css-variable-service.stub.ts +++ b/src/app/shared/testing/css-variable-service.stub.ts @@ -21,7 +21,7 @@ export class CSSVariableServiceStub { /**/ } - addCSSVariables(variables: KeyValuePair[]): void { + addCSSVariables(variablesToAdd: KeyValuePair[]): void { /**/ } From f7619249630f9df9bf5731eb7793ecbc27551d19 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 22 Sep 2022 17:16:35 +0200 Subject: [PATCH 7/8] 94233: removed empty file --- src/app/shared/sass-helper/css-variable.utils.ts | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/app/shared/sass-helper/css-variable.utils.ts diff --git a/src/app/shared/sass-helper/css-variable.utils.ts b/src/app/shared/sass-helper/css-variable.utils.ts deleted file mode 100644 index 05e3074f98..0000000000 --- a/src/app/shared/sass-helper/css-variable.utils.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Uses code from https://css-tricks.com/how-to-get-all-custom-properties-on-a-page-in-javascript/ - -import { KeyValuePair } from '../key-value-pair.model'; - From af982471953836051dd51fb391929f5b3f8c38a3 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Thu, 22 Sep 2022 18:18:42 +0200 Subject: [PATCH 8/8] add check to ensure document.styleSheets is defined --- src/app/core/core.module.ts | 2 - .../sass-helper/css-variable.service.ts | 58 ++++++++++--------- src/modules/app/server-init.service.ts | 2 - 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index f80a2a020e..90cefd54c7 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -23,7 +23,6 @@ import { NotificationsService } from '../shared/notifications/notifications.serv import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service'; import { ObjectSelectService } from '../shared/object-select/object-select.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { CSSVariableService } from '../shared/sass-helper/css-variable.service'; import { SidebarService } from '../shared/sidebar/sidebar.service'; import { UploaderService } from '../shared/uploader/uploader.service'; import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service'; @@ -257,7 +256,6 @@ const PROVIDERS = [ DefaultChangeAnalyzer, ArrayMoveChangeAnalyzer, ObjectSelectService, - CSSVariableService, MenuService, ObjectUpdatesService, SearchService, diff --git a/src/app/shared/sass-helper/css-variable.service.ts b/src/app/shared/sass-helper/css-variable.service.ts index af40c634fd..0190a05036 100644 --- a/src/app/shared/sass-helper/css-variable.service.ts +++ b/src/app/shared/sass-helper/css-variable.service.ts @@ -5,7 +5,7 @@ import { AddAllCSSVariablesAction, AddCSSVariableAction, ClearCSSVariablesAction import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; import { Observable } from 'rxjs'; -import { hasValue } from '../empty.util'; +import { hasValue, isNotEmpty } from '../empty.util'; import { KeyValuePair } from '../key-value-pair.model'; import { PageInfo } from '../../core/shared/page-info.model'; import { CSSVariablesState } from './css-variable.reducer'; @@ -13,7 +13,9 @@ import { CSSVariablesState } from './css-variable.reducer'; /** * This service deals with adding and retrieving CSS variables to and from the store */ -@Injectable() +@Injectable({ + providedIn: 'root' +}) export class CSSVariableService { isSameDomain = (styleSheet) => { // Internal style blocks won't have an href value @@ -88,31 +90,35 @@ export class CSSVariableService { * ex; [{key: "--color-accent", value: "#b9f500"}, {key: "--color-text", value: "#252525"}, ...] */ getCSSVariablesFromStylesheets(document: Document): KeyValuePair[] { - // styleSheets is array-like, so we convert it to an array. - // Filter out any stylesheets not on this domain - return [...document.styleSheets] - .filter(this.isSameDomain) - .reduce( - (finalArr, sheet) => - finalArr.concat( - // cssRules is array-like, so we convert it to an array - [...sheet.cssRules].filter(this.isStyleRule).reduce((propValArr, rule: any) => { - const props = [...rule.style] - .map((propName) => { - return { - key: propName.trim(), - value: rule.style.getPropertyValue(propName).trim() - } as KeyValuePair; - } - ) - // Discard any props that don't start with "--". Custom props are required to. - .filter(({ key }: KeyValuePair) => key.indexOf('--') === 0); + if (isNotEmpty(document.styleSheets)) { + // styleSheets is array-like, so we convert it to an array. + // Filter out any stylesheets not on this domain + return [...document.styleSheets] + .filter(this.isSameDomain) + .reduce( + (finalArr, sheet) => + finalArr.concat( + // cssRules is array-like, so we convert it to an array + [...sheet.cssRules].filter(this.isStyleRule).reduce((propValArr, rule: any) => { + const props = [...rule.style] + .map((propName) => { + return { + key: propName.trim(), + value: rule.style.getPropertyValue(propName).trim() + } as KeyValuePair; + } + ) + // Discard any props that don't start with "--". Custom props are required to. + .filter(({ key }: KeyValuePair) => key.indexOf('--') === 0); - return [...propValArr, ...props]; - }, []) - ), - [] - ); + return [...propValArr, ...props]; + }, []) + ), + [] + ); + } else { + return []; + } } } diff --git a/src/modules/app/server-init.service.ts b/src/modules/app/server-init.service.ts index 9f6aa65921..903bd91b7c 100644 --- a/src/modules/app/server-init.service.ts +++ b/src/modules/app/server-init.service.ts @@ -18,7 +18,6 @@ import { LocaleService } from '../../app/core/locale/locale.service'; import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider'; import { MetadataService } from '../../app/core/metadata/metadata.service'; import { BreadcrumbsService } from '../../app/breadcrumbs/breadcrumbs.service'; -import { CSSVariableService } from '../../sass-helper/css-variable.service'; import { ThemeService } from '../../app/shared/theme-support/theme.service'; import { take } from 'rxjs/operators'; @@ -37,7 +36,6 @@ export class ServerInitService extends InitService { protected angulartics2DSpace: Angulartics2DSpace, protected metadata: MetadataService, protected breadcrumbsService: BreadcrumbsService, - protected cssService: CSSVariableService, protected themeService: ThemeService, ) { super(