diff --git a/Dockerfile b/Dockerfile index 9f48afc71..ced8e4e65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,4 +20,13 @@ RUN chmod +x /usr/local/bin/docker-entrypoint ENTRYPOINT ["docker-entrypoint"] +RUN apk update; +RUN apk upgrade; + +RUN echo "" >> /usr/local/apache2/conf/httpd.conf +RUN echo "###SPECIFIC CUSTOMIZATIONS###" >> /usr/local/apache2/conf/httpd.conf +RUN echo "" >> /usr/local/apache2/conf/httpd.conf + +RUN printf ' \nOrder Allow,Deny \nAllow from all \nAllowOverride all \nHeader set Access-Control-Allow-Origin "*" \n' >> /usr/local/apache2/conf/httpd.conf + CMD ["httpd", "-D", "FOREGROUND"] diff --git a/defaults-ci-overrides.env b/defaults-ci-overrides.env new file mode 100644 index 000000000..187b67e6e --- /dev/null +++ b/defaults-ci-overrides.env @@ -0,0 +1,7 @@ +# +# This overrides file should contain only those value which need to be overriden +# in ./defaults.env when running a build for continuous integration. +# + +BASE_URL=https://tamulib.github.io/weaver-components/docs +ASSETS_URL=https://tamulib.github.io/weaver-components/docs/assets diff --git a/package.json b/package.json index a1e0e59c4..4cd847248 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "git", "url": "git+https://github.com/TAMULib/weaver-components.git" }, - "version": "1.3.0-rc3", + "version": "1.4.0", "private": false, "license": "MIT", "bin": { @@ -31,7 +31,7 @@ "build:static-setup": "node scripts/build-wvr-components-static.js", "build:static-docs": "npm run test:audit && npm run build:static-setup && npm run build:docs-usage && npm run build:docs-development", "build:static-reports": "npm run build:static-setup && npm run test:coverage", - "build:static-production": "npm run build:static && ls -A | grep -v static | xargs rimraf && mv static/weaver-components/* . && rimraf static", + "build:static-production": "npm run build:static && node scripts/build-wvr-components-configuration.js defaults-ci-overrides.env && ls -A | grep -v static | xargs rimraf && mv static/weaver-components/* . && rimraf static", "clean": "rimraf dist", "clean:static": "rimraf static", "lint": "ng lint", @@ -50,16 +50,16 @@ "test:ci": "npm run test:coverage && npm run test:audit" }, "dependencies": { - "@angular/animations": "^10.0.9", - "@angular/common": "^10.0.9", - "@angular/compiler": "^10.0.9", - "@angular/core": "^10.0.9", - "@angular/elements": "^10.0.9", - "@angular/forms": "^10.0.9", - "@angular/localize": "^10.0.9", - "@angular/platform-browser": "^10.0.9", - "@angular/platform-browser-dynamic": "^10.0.9", - "@angular/router": "^10.0.9", + "@angular/animations": "^10.0.12", + "@angular/common": "^10.0.12", + "@angular/compiler": "^10.0.12", + "@angular/core": "^10.0.12", + "@angular/elements": "^10.0.12", + "@angular/forms": "^10.0.12", + "@angular/localize": "^10.0.12", + "@angular/platform-browser": "^10.0.12", + "@angular/platform-browser-dynamic": "^10.0.12", + "@angular/router": "^10.0.12", "@ng-bootstrap/ng-bootstrap": "^7.0.0", "@types/json5": "0.0.30", "dotenv-override": "^5.0.1", @@ -76,18 +76,18 @@ "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.1000.5", - "@angular-devkit/build-ng-packagr": "~0.1000.5", - "@angular-devkit/schematics": "^10.0.5", - "@angular/cli": "^10.0.5", - "@angular/compiler-cli": "^10.0.9", - "@angular/language-service": "^10.0.9", + "@angular-devkit/build-angular": "~0.1000.7", + "@angular-devkit/build-ng-packagr": "~0.1000.7", + "@angular-devkit/schematics": "^10.0.7", + "@angular/cli": "^10.0.7", + "@angular/compiler-cli": "^10.0.12", + "@angular/language-service": "^10.0.12", "@compodoc/compodoc": "^1.1.11", - "@lhci/cli": "^0.4.4", + "@lhci/cli": "^0.5.0", "@pickra/copy-code-block": "^1.2.0", - "@types/jasmine": "~3.5.12", + "@types/jasmine": "~3.5.13", "@types/jasminewd2": "~2.0.8", - "@types/node": "^14.0.27", + "@types/node": "^14.6.0", "angular-tslint-rules": "^1.20.4", "chalk": "^4.1.0", "chrome-launcher": "^0.13.4", @@ -106,13 +106,13 @@ "karma-jasmine-html-reporter": "^1.5.4", "lighthouse": "^6.2.0", "lighthouse-badges": "^1.0.33", - "ng-packagr": "^10.0.3", + "ng-packagr": "^10.0.4", "protractor": "~7.0.0", "rimraf": "^3.0.2", "static-server": "^2.2.1", - "ts-loader": "^8.0.2", - "ts-node": "~8.10.2", + "ts-loader": "^8.0.3", + "ts-node": "~9.0.0", "tslint": "~6.1.3", - "typescript": "~3.9.7" + "typescript": "~3.9.4" } } diff --git a/projects/wvr-elements/package.json b/projects/wvr-elements/package.json index 4879d875d..f42c4a6da 100644 --- a/projects/wvr-elements/package.json +++ b/projects/wvr-elements/package.json @@ -1,6 +1,6 @@ { "name": "@wvr/elements", - "version": "1.3.0", + "version": "1.4.0", "description": "Collection of angular components for Weaver's Custom Web Component UI", "author": "Texas A&M University Libraries", "private": false, diff --git a/projects/wvr-elements/src/lib/core/icon.service.ts b/projects/wvr-elements/src/lib/core/icon.service.ts index d89fad207..749f8d49b 100644 --- a/projects/wvr-elements/src/lib/core/icon.service.ts +++ b/projects/wvr-elements/src/lib/core/icon.service.ts @@ -17,7 +17,6 @@ export class IconService { private readonly http: HttpClient, @Inject(APP_CONFIG) private readonly appConfig: AppConfig ) { - } registerIcons(icons: IconSet): void { diff --git a/projects/wvr-elements/src/lib/core/mobile.service.spec.ts b/projects/wvr-elements/src/lib/core/mobile.service.spec.ts new file mode 100644 index 000000000..a315b8161 --- /dev/null +++ b/projects/wvr-elements/src/lib/core/mobile.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { MobileService } from './mobile.service'; + +describe('MobileService', () => { + let service: MobileService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(MobileService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/projects/wvr-elements/src/lib/core/mobile.service.ts b/projects/wvr-elements/src/lib/core/mobile.service.ts new file mode 100644 index 000000000..2eabb2825 --- /dev/null +++ b/projects/wvr-elements/src/lib/core/mobile.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@angular/core'; +import { fromEvent, Observable } from 'rxjs'; +import { delay, map, throttleTime } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class MobileService { + + isMobileLayout: boolean; + + private readonly screenSizeChanged$: Observable; + + constructor() { + this.screenSizeChanged$ = fromEvent(window, 'resize') + .pipe(throttleTime(100)) + .pipe(map(this.checkScreenSize)); + + this.screenSizeChanged$.subscribe(iml => { + this.isMobileLayout = iml; + }); + + this.isMobileLayout = this.checkScreenSize(); + } + + private readonly checkScreenSize = () => window.innerWidth < 767; + +} diff --git a/projects/wvr-elements/src/lib/shared/utility/decorators.utilty.ts b/projects/wvr-elements/src/lib/shared/utility/decorators.utilty.ts new file mode 100644 index 000000000..34c446a27 --- /dev/null +++ b/projects/wvr-elements/src/lib/shared/utility/decorators.utilty.ts @@ -0,0 +1,20 @@ +// tslint:disable-next-line:only-arrow-functions +function debounce(delay = 300): MethodDecorator { + return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => { + const timeoutKey = Symbol(); + const original = descriptor.value; + // tslint:disable-next-line:typedef + descriptor.value = function(...args) { + // tslint:disable-next-line:no-invalid-this + clearTimeout(this[timeoutKey]); + // tslint:disable-next-line:no-invalid-this + this[timeoutKey] = setTimeout(() => original.apply(this, args), delay); + }; + + return descriptor; + }; +} + +export { + debounce +}; diff --git a/projects/wvr-elements/src/lib/shared/utility/index.ts b/projects/wvr-elements/src/lib/shared/utility/index.ts index c3b760301..693c2d7da 100644 --- a/projects/wvr-elements/src/lib/shared/utility/index.ts +++ b/projects/wvr-elements/src/lib/shared/utility/index.ts @@ -1,2 +1,2 @@ export { obtainConfigPath, weaverBootstrap } from './bootstrap.utility'; - +export { debounce } from './decorators.utilty'; diff --git a/projects/wvr-elements/src/lib/shared/wvr-base.component.ts b/projects/wvr-elements/src/lib/shared/wvr-base.component.ts index eb09e7456..c21c14f07 100644 --- a/projects/wvr-elements/src/lib/shared/wvr-base.component.ts +++ b/projects/wvr-elements/src/lib/shared/wvr-base.component.ts @@ -1,14 +1,18 @@ -import { AfterContentInit, Directive, ElementRef, EventEmitter, Injector, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { AfterContentInit, Directive, ElementRef, EventEmitter, HostBinding, Injector, Input, OnInit, Output, ViewChild } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import * as JSON5 from 'json5'; import { fromEvent, Observable } from 'rxjs'; import { debounceTime, map } from 'rxjs/operators'; import { WvrAnimationService } from '../core/wvr-animation.service'; +import { IconService } from '../core/icon.service'; +import { MobileService } from '../core/mobile.service'; @Directive() // tslint:disable-next-line:directive-class-suffix export abstract class WvrBaseComponent implements AfterContentInit, OnInit { + @HostBinding('class.wvr-bootstrap') wvrBootstrap = true; + private _animationSettings: any = {}; @Input() set animate(value: string) { this._animationSettings = JSON5.parse(value); @@ -27,6 +31,10 @@ export abstract class WvrBaseComponent implements AfterContentInit, OnInit { @ViewChild('animationRoot') animationRootElem: ElementRef; + get isMobileLayout(): boolean { + return this.mobileService.isMobileLayout; + } + get isMobileAgent(): boolean { const agent = navigator.userAgent || navigator.vendor || (window as any).opera; @@ -34,27 +42,27 @@ export abstract class WvrBaseComponent implements AfterContentInit, OnInit { return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(agent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(agent.substr(0, 4))); } - screenSizeChanged$: Observable; - - isMobileLayout = this.isMobileAgent; - protected readonly _animationService: WvrAnimationService; protected readonly _domSanitizer: DomSanitizer; protected readonly _eRef: ElementRef; + private readonly mobileService: MobileService; + + @HostBinding('class.wvr-hidden') private get _hiddenInMobile(): boolean { + return this.mobileService.isMobileLayout && this.hiddenInMobile; + } + + @Input() hiddenInMobile = false; + @Output() protected readonly animationEventTrigger = new EventEmitter(); constructor(injector: Injector) { - this._animationService = injector.get(WvrAnimationService); this._domSanitizer = injector.get(DomSanitizer); this._eRef = injector.get(ElementRef); - - this.screenSizeChanged$ = fromEvent(window, 'resize') - .pipe(debounceTime(50)) - .pipe(map(this.checkScreenSize)); + this.mobileService = injector.get(MobileService); } ngOnInit(): void { @@ -70,10 +78,6 @@ export abstract class WvrBaseComponent implements AfterContentInit, OnInit { } }); } - this.screenSizeChanged$.subscribe(iml => { - this.isMobileLayout = iml; - }); - this.isMobileLayout = this.checkScreenSize(); } ngAfterContentInit(): void { @@ -101,6 +105,4 @@ export abstract class WvrBaseComponent implements AfterContentInit, OnInit { this.triggerAnimations($event.type); } - private readonly checkScreenSize = () => document.body.offsetWidth < 767; - } diff --git a/projects/wvr-elements/src/lib/wvr-dropdown/wvr-dropdown.component.html b/projects/wvr-elements/src/lib/wvr-dropdown/wvr-dropdown.component.html index 02b50d0ef..943b7cbdb 100644 --- a/projects/wvr-elements/src/lib/wvr-dropdown/wvr-dropdown.component.html +++ b/projects/wvr-elements/src/lib/wvr-dropdown/wvr-dropdown.component.html @@ -1,5 +1,5 @@
-
+
-