From 1c7a493bd3cd5cc6eac4a357c061040f2f4a5810 Mon Sep 17 00:00:00 2001 From: Adam Plumer Date: Sat, 22 Jul 2017 01:35:54 -0400 Subject: [PATCH] Fixed nav-menu config to make it more dynamic, added manager view - Added manager view, initial verson of #29 - Updated travis to use npm 5.3.x - Updated material deps - Added route resolvers to properly configure nav-menu list - Added service worker update service - Fixed theme to keep up with latest material theme updates --- .travis.yml | 2 +- package-lock.json | 295 ++++++++++-------- package.json | 24 +- src/app/app-routing.module.ts | 32 +- src/app/app.module.ts | 27 +- src/app/home/home-menu.service.spec.ts | 15 + src/app/home/home-menu.service.ts | 90 ++++++ src/app/home/home.component.html | 53 ++-- src/app/home/home.component.ts | 51 ++- .../manage-course.component.html | 3 + .../manage-course.component.scss | 0 .../manage-course.component.spec.ts | 25 ++ .../manage-course/manage-course.component.ts | 15 + .../manage-dept/manage-dept.component.html | 3 + .../manage-dept/manage-dept.component.scss | 0 .../manage-dept/manage-dept.component.spec.ts | 25 ++ .../manage-dept/manage-dept.component.ts | 15 + .../manage-home/manage-home.component.html | 3 + .../manage-home/manage-home.component.scss | 0 .../manage-home/manage-home.component.spec.ts | 25 ++ .../manage-home/manage-home.component.ts | 15 + .../manage-material/manage-material.module.ts | 10 + src/app/manage/manage-routing.module.ts | 41 +++ src/app/manage/manage.module.ts | 17 + src/app/nav-menu/_nav-menu-theme.scss | 1 - src/app/nav-menu/nav-menu-header.html | 2 +- src/app/nav-menu/nav-menu.scss | 4 +- src/app/nav-menu/nav-menu.ts | 1 - src/app/shared/guards/auth.guard.ts | 22 ++ .../shared/resolvers/admin-resolver.spec.ts | 15 + src/app/shared/resolvers/admin-resolver.ts | 27 ++ src/app/shared/resolvers/courses-resolver.ts | 33 ++ src/app/shared/resolvers/grading-resolver.ts | 27 ++ src/app/shared/resolvers/landing-resolver.ts | 37 +++ src/app/shared/resolvers/manage-resolver.ts | 54 ++++ src/app/shared/services/auth.service.ts | 12 +- src/app/shared/services/user.service.ts | 10 + src/app/sw-updates/sw-updates.module.ts | 14 + src/app/sw-updates/sw-updates.service.spec.ts | 15 + src/app/sw-updates/sw-updates.service.ts | 53 ++++ src/assets/data.json | 13 + src/theme.scss | 2 + 42 files changed, 897 insertions(+), 231 deletions(-) create mode 100644 src/app/home/home-menu.service.spec.ts create mode 100644 src/app/home/home-menu.service.ts create mode 100644 src/app/manage/manage-course/manage-course.component.html create mode 100644 src/app/manage/manage-course/manage-course.component.scss create mode 100644 src/app/manage/manage-course/manage-course.component.spec.ts create mode 100644 src/app/manage/manage-course/manage-course.component.ts create mode 100644 src/app/manage/manage-dept/manage-dept.component.html create mode 100644 src/app/manage/manage-dept/manage-dept.component.scss create mode 100644 src/app/manage/manage-dept/manage-dept.component.spec.ts create mode 100644 src/app/manage/manage-dept/manage-dept.component.ts create mode 100644 src/app/manage/manage-home/manage-home.component.html create mode 100644 src/app/manage/manage-home/manage-home.component.scss create mode 100644 src/app/manage/manage-home/manage-home.component.spec.ts create mode 100644 src/app/manage/manage-home/manage-home.component.ts create mode 100644 src/app/manage/manage-material/manage-material.module.ts create mode 100644 src/app/manage/manage-routing.module.ts create mode 100644 src/app/manage/manage.module.ts create mode 100644 src/app/shared/resolvers/admin-resolver.spec.ts create mode 100644 src/app/shared/resolvers/admin-resolver.ts create mode 100644 src/app/shared/resolvers/courses-resolver.ts create mode 100644 src/app/shared/resolvers/grading-resolver.ts create mode 100644 src/app/shared/resolvers/landing-resolver.ts create mode 100644 src/app/shared/resolvers/manage-resolver.ts create mode 100644 src/app/sw-updates/sw-updates.module.ts create mode 100644 src/app/sw-updates/sw-updates.service.spec.ts create mode 100644 src/app/sw-updates/sw-updates.service.ts diff --git a/.travis.yml b/.travis.yml index 487bf8f..ce0d9db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ branches: - master - dev before_install: -- npm i -g npm@^5.0.1 +- npm i -g npm@~5.3.0 - npm install -g @angular/cli install: - npm install diff --git a/package-lock.json b/package-lock.json index 77f2a9c..253e138 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@angular/animations": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-4.3.0.tgz", - "integrity": "sha1-VvNLhGSTeSAqw1mSm4LrC5FenHI=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-4.3.1.tgz", + "integrity": "sha1-H34LuAPvwhxggkbmdlocZH89Gl8=", "requires": { "tslib": "1.7.1" } @@ -19,18 +19,18 @@ "dev": true }, "@angular/cdk": { - "version": "github:angular/cdk-builds#50f96d139cc3fb8d447ceddd00ff27469afc0864", + "version": "github:angular/cdk-builds#9078754833bedc013eea24e72c50af3ee64e81d5", "requires": { "tslib": "1.7.1" } }, "@angular/cli": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.2.1.tgz", - "integrity": "sha512-Y3AqcyvWcy9c4KuQAKHzXp2oO51bNY3o/90wfpcwct3Bt4znDMXuoQdgf+VhffcbIgc/b2yyPlOatXLRJ7531A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.2.3.tgz", + "integrity": "sha512-ajkUdF9MVAwSexv4dPm3EUTG1KEKMta646yYijvr6sR8x6ctIMfLJ5fSwpJIHD7KHEs6iqEdz6paAjxiOVQn/A==", "requires": { "@ngtools/json-schema": "1.1.0", - "@ngtools/webpack": "1.5.1", + "@ngtools/webpack": "1.5.2", "autoprefixer": "6.7.7", "chalk": "1.1.3", "common-tags": "1.4.0", @@ -55,6 +55,7 @@ "isbinaryfile": "3.0.2", "istanbul-instrumenter-loader": "2.0.0", "json-loader": "0.5.4", + "karma-source-map-support": "1.2.0", "less": "2.7.2", "less-loader": "4.0.5", "license-webpack-plugin": "0.4.3", @@ -70,7 +71,7 @@ "postcss-url": "5.1.2", "raw-loader": "0.5.1", "resolve": "1.3.3", - "rsvp": "3.6.1", + "rsvp": "3.6.2", "rxjs": "5.4.2", "sass-loader": "6.0.6", "script-loader": "0.7.0", @@ -88,66 +89,48 @@ "webpack-dev-middleware": "1.11.0", "webpack-dev-server": "2.4.5", "webpack-merge": "2.6.1", - "zone.js": "0.8.12" + "zone.js": "0.8.14" }, "dependencies": { "typescript": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.3.4.tgz", "integrity": "sha1-PTgyGCgjHkNPKHUUlZw3qCtin0I=" + }, + "zone.js": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.14.tgz", + "integrity": "sha1-DE2ySxeCMidMy0P3jJnbfzZCts8=" } } }, "@angular/common": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-4.3.0.tgz", - "integrity": "sha1-E6VKaSndUvlymxauRG+tWP4WMFM=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-4.3.1.tgz", + "integrity": "sha1-Jg9IenzcoybENr0+qVFceX3i/3I=", "requires": { "tslib": "1.7.1" } }, "@angular/compiler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-4.3.0.tgz", - "integrity": "sha1-VVA78nofBi9xuUlTk/MxGQOo/EM=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-4.3.1.tgz", + "integrity": "sha1-OiTUns8BrCtuB/Y+N4uP+OJX/gk=", "requires": { "tslib": "1.7.1" } }, "@angular/compiler-cli": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-4.3.0.tgz", - "integrity": "sha1-83WAlzD16IPP4hGumRIQ8csanx4=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-4.3.1.tgz", + "integrity": "sha1-ALQa+2+utK71YbhCeASsiICv9jw=", "dev": true, "requires": { - "@angular/tsc-wrapped": "4.3.0", + "@angular/tsc-wrapped": "4.3.1", "minimist": "1.2.0", "reflect-metadata": "0.1.10" }, "dependencies": { - "@angular/tsc-wrapped": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/tsc-wrapped/-/tsc-wrapped-4.3.0.tgz", - "integrity": "sha1-/i5TdrbirRsTnt3iOp27QpnfYmQ=", - "dev": true, - "requires": { - "tsickle": "0.21.6" - }, - "dependencies": { - "tsickle": { - "version": "0.21.6", - "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.21.6.tgz", - "integrity": "sha1-U7Abl5xcE/2xOvs/uVgXflmRWI0=", - "dev": true, - "requires": { - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "source-map": "0.5.6", - "source-map-support": "0.4.15" - } - } - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -157,9 +140,9 @@ } }, "@angular/core": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-4.3.0.tgz", - "integrity": "sha1-vSJJw94SJKfGU2xKunKNZWUykzQ=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-4.3.1.tgz", + "integrity": "sha1-qdCn1kS5YmBnQmm2iaBP7qYyqNM=", "requires": { "tslib": "1.7.1" } @@ -170,17 +153,17 @@ "integrity": "sha1-uc9XhlqTyhWP5W2FCVJCPySNEDs=" }, "@angular/forms": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-4.3.0.tgz", - "integrity": "sha1-fQx6hUc36aMKX9lmX41PVqG5G9g=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-4.3.1.tgz", + "integrity": "sha1-M5FNossUZDD/kBRx5oLHZlRiLf4=", "requires": { "tslib": "1.7.1" } }, "@angular/http": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-4.3.0.tgz", - "integrity": "sha1-37czEKhApq2AUKxR8OVcSYTbCSY=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-4.3.1.tgz", + "integrity": "sha1-5PZh90ZxHojsvqdqPJBbq/l9MVo=", "requires": { "tslib": "1.7.1" } @@ -192,31 +175,31 @@ "dev": true }, "@angular/material": { - "version": "github:angular/material2-builds#03dd33fbfdc7948c7da7d4676b0ed4ec7e081c47", + "version": "github:angular/material2-builds#e3b9ea96082b32a79dc409a51088239a9de7daa7", "requires": { "tslib": "1.7.1" } }, "@angular/platform-browser": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-4.3.0.tgz", - "integrity": "sha1-AjiUiRhRhcO+zwY1k0YQDlR5x+E=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-4.3.1.tgz", + "integrity": "sha1-23J7Bu7WS9pd7+xxgV2yak2i9pA=", "requires": { "tslib": "1.7.1" } }, "@angular/platform-browser-dynamic": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.3.0.tgz", - "integrity": "sha1-VR+xiFGyfujz5LDuJarRC9ezEuM=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.3.1.tgz", + "integrity": "sha1-hANNpgqC7zbn7/2ns63m5kWzMLM=", "requires": { "tslib": "1.7.1" } }, "@angular/platform-server": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-4.3.0.tgz", - "integrity": "sha1-U4f8hI0KdWV8Xtm3DhpX8FT7Jw8=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-4.3.1.tgz", + "integrity": "sha1-O5FfxAE8apR6jBR7TbAnmwJZNus=", "requires": { "parse5": "3.0.2", "tslib": "1.7.1", @@ -224,9 +207,9 @@ } }, "@angular/router": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-4.3.0.tgz", - "integrity": "sha1-cbQo8YXrkWGh3hTcGUkhndzf/a4=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-4.3.1.tgz", + "integrity": "sha1-UhnURSYVbYFgZYQRJ2EBZaAVtFA=", "requires": { "tslib": "1.7.1" } @@ -241,15 +224,24 @@ "jshashes": "1.0.6" } }, + "@angular/tsc-wrapped": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@angular/tsc-wrapped/-/tsc-wrapped-4.3.1.tgz", + "integrity": "sha1-9mFqTSo7vsHN7WZP0fUm7c6Z70E=", + "dev": true, + "requires": { + "tsickle": "0.21.6" + } + }, "@ngtools/json-schema": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.1.0.tgz", "integrity": "sha1-w6DFRNYjkqzCgTpCyKDcb1j4aSI=" }, "@ngtools/webpack": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.5.1.tgz", - "integrity": "sha512-zGe9JQ3nTpKd2EnYKvC4+zrf/aOLUr2ZhLmSv8bAWMPu59v7fqo3oFs4n3JAbu8albQJmiktGVeY7Y2fFEsS7A==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.5.2.tgz", + "integrity": "sha1-+t7wa6aprA2q+JHQE9rQMda/DCY=", "requires": { "enhanced-resolve": "3.3.0", "loader-utils": "1.1.0", @@ -585,7 +577,7 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000701", + "caniuse-db": "1.0.30000704", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "5.2.17", @@ -951,8 +943,8 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "requires": { - "caniuse-db": "1.0.30000701", - "electron-to-chromium": "1.3.15" + "caniuse-db": "1.0.30000704", + "electron-to-chromium": "1.3.16" } }, "buffer": { @@ -1022,15 +1014,15 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000701", + "caniuse-db": "1.0.30000704", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" } }, "caniuse-db": { - "version": "1.0.30000701", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000701.tgz", - "integrity": "sha1-LjKwaZO/Pb2QtD2T8E4m0Rr93Lo=" + "version": "1.0.30000704", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000704.tgz", + "integrity": "sha1-jFqm/tgFjmXHDywfXWP3CIZQcFw=" }, "caseless": { "version": "0.12.0", @@ -1218,20 +1210,20 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", "requires": { - "color-name": "1.1.2" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.2.tgz", - "integrity": "sha1-XIq3K2S9IhXWF66VWeuxSEdc+Y0=" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "requires": { - "color-name": "1.1.2" + "color-name": "1.1.3" } }, "colormin": { @@ -1417,9 +1409,9 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cosmiconfig": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.1.3.tgz", - "integrity": "sha1-lSdx6w3dwcs/ovb75RpSLpOz7go=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.1.tgz", + "integrity": "sha512-17m9pl5cD9jhPUHqaxSA4fyoiAQJUG7V3CQDxCF7gWzGYeUY0YEnLQdQyOEKjEPVv0yGbdCfdfJMq6SphRiRjw==", "requires": { "is-directory": "0.3.1", "js-yaml": "3.7.0", @@ -2140,9 +2132,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.15", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz", - "integrity": "sha1-CDl5NIkcvPrrvRi4KpW1pIETg2k=" + "version": "1.3.16", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.16.tgz", + "integrity": "sha1-0OAmc1dUdwkBrjAaIWZMukXZL30=" }, "elliptic": { "version": "6.4.0", @@ -2277,7 +2269,7 @@ "graceful-fs": "4.1.11", "memory-fs": "0.4.1", "object-assign": "4.1.1", - "tapable": "0.2.6" + "tapable": "0.2.7" } }, "ensure-posix-path": { @@ -2494,7 +2486,7 @@ "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", "requires": { "iconv-lite": "0.4.18", - "jschardet": "1.4.2", + "jschardet": "1.5.0", "tmp": "0.0.31" } }, @@ -2685,7 +2677,7 @@ "requires": { "graceful-fs": "4.1.11", "jsonfile": "3.0.1", - "universalify": "0.1.0" + "universalify": "0.1.1" } }, "fs.realpath": { @@ -3079,7 +3071,7 @@ "ncname": "1.0.0", "param-case": "2.1.1", "relateurl": "0.2.7", - "uglify-js": "3.0.24" + "uglify-js": "3.0.25" } }, "html-webpack-plugin": { @@ -3242,7 +3234,7 @@ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", "requires": { - "postcss": "6.0.6" + "postcss": "6.0.8" }, "dependencies": { "ansi-styles": { @@ -3269,9 +3261,9 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "postcss": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.6.tgz", - "integrity": "sha1-u6TVjohPx4yEDRU54Q7dqruPc70=", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", @@ -3373,7 +3365,7 @@ "run-async": "2.3.0", "rx-lite": "4.0.8", "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.0", + "string-width": "2.1.1", "strip-ansi": "4.0.0", "through": "2.3.8" }, @@ -3894,9 +3886,9 @@ "optional": true }, "jschardet": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz", - "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.0.tgz", + "integrity": "sha512-+Q8JsoEQbrdE+a/gg1F9XO92gcKXgpE5UACqr0sIubjDmBEkd+OOWPGzQeMrWSLxd73r4dHxBeRW7edHu5LmJQ==" }, "jsesc": { "version": "0.5.0", @@ -4075,6 +4067,14 @@ "karma-jasmine": "1.1.0" } }, + "karma-source-map-support": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.2.0.tgz", + "integrity": "sha1-G/gee7SwiWJ6s1LsQXnhF8QGpUA=", + "requires": { + "source-map-support": "0.4.15" + } + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -5105,7 +5105,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "requires": { - "cosmiconfig": "2.1.3", + "cosmiconfig": "2.2.1", "object-assign": "4.1.1", "postcss-load-options": "1.2.0", "postcss-load-plugins": "2.3.0" @@ -5116,7 +5116,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "requires": { - "cosmiconfig": "2.1.3", + "cosmiconfig": "2.2.1", "object-assign": "4.1.1" } }, @@ -5125,7 +5125,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "requires": { - "cosmiconfig": "2.1.3", + "cosmiconfig": "2.2.1", "object-assign": "4.1.1" } }, @@ -5221,7 +5221,7 @@ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", "requires": { - "postcss": "6.0.6" + "postcss": "6.0.8" }, "dependencies": { "ansi-styles": { @@ -5248,9 +5248,9 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "postcss": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.6.tgz", - "integrity": "sha1-u6TVjohPx4yEDRU54Q7dqruPc70=", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", @@ -5273,7 +5273,7 @@ "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", "requires": { "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.6" + "postcss": "6.0.8" }, "dependencies": { "ansi-styles": { @@ -5300,9 +5300,9 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "postcss": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.6.tgz", - "integrity": "sha1-u6TVjohPx4yEDRU54Q7dqruPc70=", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", @@ -5325,7 +5325,7 @@ "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", "requires": { "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.6" + "postcss": "6.0.8" }, "dependencies": { "ansi-styles": { @@ -5352,9 +5352,9 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "postcss": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.6.tgz", - "integrity": "sha1-u6TVjohPx4yEDRU54Q7dqruPc70=", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", @@ -5377,7 +5377,7 @@ "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", "requires": { "icss-replace-symbols": "1.1.0", - "postcss": "6.0.6" + "postcss": "6.0.8" }, "dependencies": { "ansi-styles": { @@ -5404,9 +5404,9 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "postcss": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.6.tgz", - "integrity": "sha1-u6TVjohPx4yEDRU54Q7dqruPc70=", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", @@ -6060,9 +6060,9 @@ } }, "rsvp": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.1.tgz", - "integrity": "sha1-NPSnrChZ97rMj0l4nFYE8eJq5wI=" + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==" }, "run-async": { "version": "2.3.0", @@ -6596,7 +6596,6 @@ "version": "0.4.15", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", - "dev": true, "requires": { "source-map": "0.5.6" } @@ -6722,9 +6721,9 @@ } }, "string-width": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz", - "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -6868,9 +6867,9 @@ "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" }, "tapable": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.6.tgz", - "integrity": "sha1-IGvo4YiGC1FEJTdebxrom/sB/Y0=" + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.7.tgz", + "integrity": "sha1-5GwNqsuyuKmLmwzqD0BSEFgX7Vw=" }, "tar": { "version": "2.2.1", @@ -7004,6 +7003,26 @@ } } }, + "tsickle": { + "version": "0.21.6", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.21.6.tgz", + "integrity": "sha1-U7Abl5xcE/2xOvs/uVgXflmRWI0=", + "dev": true, + "requires": { + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map": "0.5.6", + "source-map-support": "0.4.15" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "tslib": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz", @@ -7079,9 +7098,9 @@ "dev": true }, "uglify-js": { - "version": "3.0.24", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.24.tgz", - "integrity": "sha512-IZ7l7MU2j7LIuz6IAFWBOk1dbuQ0QVQsKLffpNPKXuL8NYcFBBQ5QkvMAtfL1+oaBW16344DY4sA26GI9cXzlA==", + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.25.tgz", + "integrity": "sha512-JO1XE0WZ9m6UpDkN7WCyPNAWI6EN3K0g40ekcoJKejViYmryJ0BaLxXjvra1IsAeIlJfq72scTbhl0jknsT2GA==", "requires": { "commander": "2.9.0", "source-map": "0.5.6" @@ -7118,9 +7137,9 @@ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" }, "universalify": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.0.tgz", - "integrity": "sha1-nrHEZR3rzGcMyU8adXYjMruWd3g=" + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, "unpipe": { "version": "1.0.0", @@ -7297,9 +7316,9 @@ } }, "watchpack": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.3.1.tgz", - "integrity": "sha1-fYaTkHsozmAT5/NhCqKhrPB9rYc=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", "requires": { "async": "2.5.0", "chokidar": "1.7.0", @@ -7393,9 +7412,9 @@ "node-libs-browser": "2.0.0", "source-map": "0.5.6", "supports-color": "3.2.3", - "tapable": "0.2.6", + "tapable": "0.2.7", "uglify-js": "2.8.29", - "watchpack": "1.3.1", + "watchpack": "1.4.0", "webpack-sources": "0.2.3", "yargs": "6.6.0" }, diff --git a/package.json b/package.json index 86945e3..dbbd1d8 100644 --- a/package.json +++ b/package.json @@ -12,20 +12,20 @@ }, "private": true, "dependencies": { - "@angular/animations": "^4.3.0", + "@angular/animations": "^4.3.1", "@angular/cdk": "github:angular/cdk-builds", - "@angular/cli": "^1.2.1", - "@angular/common": "^4.3.0", - "@angular/compiler": "^4.3.0", - "@angular/core": "^4.3.0", + "@angular/cli": "^1.2.3", + "@angular/common": "^4.3.1", + "@angular/compiler": "^4.3.1", + "@angular/core": "^4.3.1", "@angular/flex-layout": "^2.0.0-beta.8", - "@angular/forms": "^4.3.0", - "@angular/http": "^4.3.0", + "@angular/forms": "^4.3.1", + "@angular/http": "^4.3.1", "@angular/material": "github:angular/material2-builds", - "@angular/platform-browser": "^4.3.0", - "@angular/platform-browser-dynamic": "^4.3.0", - "@angular/platform-server": "^4.3.0", - "@angular/router": "^4.3.0", + "@angular/platform-browser": "^4.3.1", + "@angular/platform-browser-dynamic": "^4.3.1", + "@angular/platform-server": "^4.3.1", + "@angular/router": "^4.3.1", "@swimlane/ngx-charts": "^5.3.1", "core-js": "^2.4.1", "d3": "^4.9.1", @@ -36,7 +36,7 @@ }, "devDependencies": { "@angular/app-shell": "^0.1.0", - "@angular/compiler-cli": "^4.3.0", + "@angular/compiler-cli": "^4.3.1", "@angular/language-service": "^4.3.0", "@angular/service-worker": "^1.0.0-beta.16", "@types/jasmine": "~2.5.53", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 70a8b38..5e1c1b9 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,12 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import {HomeComponent} from './home/home.component'; -import {CanLoadAdmin, CanLoadCourses, CanLoadGrading} from './shared/guards/auth.guard'; +import {CanLoadAdmin, CanLoadCourses, CanLoadGrading, CanLoadManage} from './shared/guards/auth.guard'; +import {AdminResolver} from './shared/resolvers/admin-resolver'; +import {GradingResolver} from './shared/resolvers/grading-resolver'; +import {CoursesResolver} from './shared/resolvers/courses-resolver'; +import {LandingResolver} from './shared/resolvers/landing-resolver'; +import {ManageResolver} from './shared/resolvers/manage-resolver'; export const appRoutes: Routes = [ { @@ -9,16 +14,33 @@ export const appRoutes: Routes = [ component: HomeComponent, children: [ { - path: '', loadChildren: './landing/landing.module#LandingModule' + path: '', + loadChildren: './landing/landing.module#LandingModule', + resolve: {data: LandingResolver} }, { - path: 'courses', loadChildren: './courses/courses.module#CoursesModule', canLoad: [CanLoadCourses] + path: 'courses', + loadChildren: './courses/courses.module#CoursesModule', + canLoad: [CanLoadCourses], + resolve: {data: CoursesResolver} }, { - path: 'grading', loadChildren: './grading/grading.module#GradingModule', canLoad: [CanLoadGrading] + path: 'grading', + loadChildren: './grading/grading.module#GradingModule', + canLoad: [CanLoadGrading], + resolve: {data: GradingResolver} }, { - path: 'admin', loadChildren: './admin/admin.module#AdminModule', canLoad: [CanLoadAdmin] + path: 'admin', + loadChildren: './admin/admin.module#AdminModule', + canLoad: [CanLoadAdmin], + resolve: {data: AdminResolver} + }, + { + path: 'manage', + loadChildren: './manage/manage.module#ManageModule', + canLoad: [CanLoadManage], + resolve: {data: ManageResolver} }, { path: '**', redirectTo: '', pathMatch: 'full' diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1ef081d..f016141 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -10,13 +10,20 @@ import {FlexLayoutModule} from '@angular/flex-layout'; import 'hammerjs'; import 'd3'; import {AuthService} from './shared/services/auth.service'; -import {CanLoadAdmin, CanLoadCourses, CanLoadGrading} from './shared/guards/auth.guard'; +import {CanLoadAdmin, CanLoadCourses, CanLoadGrading, CanLoadManage} from './shared/guards/auth.guard'; import {HomeComponent, SigninDialogComponent} from './home/home.component'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {AppMaterialModule} from './app-material/app-material.module'; import {NavMenuModule} from './nav-menu/index'; import {SortByPipe} from './shared/pipes/sort-by.pipe'; import {SortPipe} from './shared/pipes/sort.pipe'; +import {SwUpdatesModule} from './sw-updates/sw-updates.module'; +import {HomeMenuService} from './home/home-menu.service'; +import {AdminResolver} from './shared/resolvers/admin-resolver'; +import {CoursesResolver} from './shared/resolvers/courses-resolver'; +import {GradingResolver} from './shared/resolvers/grading-resolver'; +import {LandingResolver} from './shared/resolvers/landing-resolver'; +import {ManageResolver} from './shared/resolvers/manage-resolver'; @NgModule({ declarations: [ @@ -34,9 +41,23 @@ import {SortPipe} from './shared/pipes/sort.pipe'; FlexLayoutModule, NavMenuModule, AppMaterialModule, - AppRoutingModule + AppRoutingModule, + SwUpdatesModule + ], + providers: [ + UserService, + AuthService, + CanLoadCourses, + CanLoadGrading, + CanLoadAdmin, + CanLoadManage, + HomeMenuService, + AdminResolver, + CoursesResolver, + GradingResolver, + LandingResolver, + ManageResolver, ], - providers: [UserService, AuthService, CanLoadCourses, CanLoadGrading, CanLoadAdmin], bootstrap: [AppComponent], entryComponents: [SigninDialogComponent] }) diff --git a/src/app/home/home-menu.service.spec.ts b/src/app/home/home-menu.service.spec.ts new file mode 100644 index 0000000..cdd8553 --- /dev/null +++ b/src/app/home/home-menu.service.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, inject } from '@angular/core/testing'; + +import { HomeMenuService } from './home-menu.service'; + +describe('HomeMenuService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [HomeMenuService] + }); + }); + + it('should be created', inject([HomeMenuService], (service: HomeMenuService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/home/home-menu.service.ts b/src/app/home/home-menu.service.ts new file mode 100644 index 0000000..203eba7 --- /dev/null +++ b/src/app/home/home-menu.service.ts @@ -0,0 +1,90 @@ +import { Injectable } from '@angular/core'; +import {Observable} from 'rxjs/Observable'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; + +@Injectable() +export class HomeMenuService { + + navs$: Observable; + + private _navs: BehaviorSubject = new BehaviorSubject([]); + + constructor() { + this.navs$ = this._navs.asObservable(); + } + + /** + * very opinionated constructor from course data to nav-menu data + * @param courses - a list of courses in course data format + * @param mode - the current nav mode or top-level nav name + * @param active - whether the course heading should be active or inactive + * @return the list of courses in nav-menu data format + */ + public constructCourses(courses, mode, active) { + + const home = c => { + return { + type: 'link', + label: 'Home', + link: '/' + mode + '/' + c + }; + }; + + const options = c => { + if (mode === 'admin') { + return [ + { + type: 'link', + label: 'Create New', + link: '/' + mode + '/' + c + '/create' + }, + { + type: 'link', + label: 'Gradebook', + link: '/' + mode + '/' + c + '/gradebook' + }, + { + type: 'link', + label: 'Calendar', + link: '/' + mode + '/' + c + '/calendar' + }, + { + type: 'link', + label: 'Graders', + link: '/' + mode + '/' + c + '/graders' + } + ]; + } + + return []; + }; + + const newCourses = courses.reduce((a, d) => { + return [...a, { + type: 'toggle', + label: d['name'], + children: [home(d['name']), ...d['assigns'].reduce((b, e) => { + return [...b, { + type: 'link', + label: e, + link: '/' + mode + '/' + d['name'] + '/' + e + }]; + }, []), ...options(d['name'])] + }]; + }, []); + + return { + type: 'header', + label: active ? 'Courses' : 'Inactive Courses', + children: newCourses + } + } + + /** + * set the nav menu courses with nav-menu data formatted array + * @param courses - a list of courses in nav-menu data format + */ + public setCourses(courses: any[]) { + this._navs.next(courses); + } +} diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 0813427..1f340b0 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -42,44 +42,27 @@ - - - - - Home - - - {{link}} - - - Create New - Gradebook - Calendar - Graders - - - - - - Home - - - {{link}} - + +
+ +
+ + {{link['label']}} + + {{child['label']}} +
+
+ + {{link['label']}} - - - Home - About - Help - + + {{link['label']}} + +
{{link.label}}
diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 2f5114b..2e2a61d 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -3,13 +3,14 @@ import {NavigationEnd, Router, RouterOutlet} from '@angular/router'; import {UserService} from '../shared/services/user.service'; import {Location} from '@angular/common'; import {AuthService} from '../shared/services/auth.service'; -import {Observable} from 'rxjs/Observable'; import {MdDialog, MdDialogRef} from '@angular/material'; import {environment} from '../../environments/environment'; import {NgForm} from '@angular/forms'; import {Subject} from 'rxjs/Subject'; import {takeUntil} from 'rxjs/operator/takeUntil'; import {group, query, transition, trigger, style, animate, animateChild} from '@angular/animations'; +import {SwUpdatesService} from '../sw-updates/sw-updates.service'; +import {HomeMenuService} from './home-menu.service'; @Component({ selector: 'vg-home', @@ -44,28 +45,25 @@ import {group, query, transition, trigger, style, animate, animateChild} from '@ }) export class HomeComponent implements OnInit, OnDestroy { - mode: string; - courses$: Observable; - inCourses$: Observable; + navs$ = this._homeService.navs$; + utln$ = this._userService.utln; + isSideBySide = true; activeLinkIndex = -1; adminTab = {route: '/admin', label: 'Admin', show: false}; graderTab = {route: '/grading', label: 'Grading', show: false}; gradesTab = {route: '/courses', label: 'Courses', show: false}; + manageTab = {route: '/manage', label: 'Manage', show: false}; navLinks = [ {route: '/', label: 'Home', show: true}, this.gradesTab, this.graderTab, - this.adminTab + this.adminTab, + this.manageTab ]; - utln$: Observable = this._userService.utln; - isSideBySide = true; - - private _grades: Observable; - private _grading: Observable; - private _admin: Observable; - private _inactive: Observable; + private _tabWidth = 160; + private _baseWidth = 220; private _sideBySideWidth = 875; private _isOpen = false; @@ -76,15 +74,13 @@ export class HomeComponent implements OnInit, OnDestroy { private _location: Location, private _userService: UserService, private _authService: AuthService, + private _homeService: HomeMenuService, + swUpdates: SwUpdatesService, public dialog: MdDialog ) { takeUntil.call(this._router.events .filter(event => event instanceof NavigationEnd), this._destroy) .subscribe((event) => this.changeTab()); - this._grading = this._userService.grading; - this._admin = this._userService.admin; - this._grades = this._userService.courses; - this._inactive = this._userService.inactive; } ngOnInit () { @@ -97,6 +93,9 @@ export class HomeComponent implements OnInit, OnDestroy { takeUntil.call(this._authService.isLoggedIn, this._destroy).subscribe(data => { this.navLinks[this.navLinks.indexOf(this.gradesTab)].show = data; }); + takeUntil.call(this._authService.isManager, this._destroy).subscribe(data => { + this.navLinks[this.navLinks.indexOf(this.manageTab)].show = data; + }); this.onResize(window.innerWidth); } @@ -113,7 +112,13 @@ export class HomeComponent implements OnInit, OnDestroy { @HostListener('window:resize', ['$event.target.innerWidth']) onResize(width) { - this.isSideBySide = width > this._sideBySideWidth; + const calcSize = () => { + return this.navLinks.reduce((a, d) => { + return a + (d.show ? this._tabWidth : 0); + }, 0) + this._baseWidth; + }; + + this.isSideBySide = width > Math.max(this._sideBySideWidth, calcSize()); } get isOpen() { @@ -138,18 +143,6 @@ export class HomeComponent implements OnInit, OnDestroy { const idx = this.navLinks.indexOf(this.navLinks.find(findTab)); this.activeLinkIndex = (idx === -1) ? 0 : idx; - this.mode = this.navLinks[this.activeLinkIndex].route; - this.inCourses$ = null; - if (this.mode === '/admin') { - this.courses$ = this._admin; - } else if (this.mode === '/grading') { - this.courses$ = this._grading; - } else if (this.mode === '/courses') { - this.courses$ = this._grades; - this.inCourses$ = this._inactive; - } else { - this.courses$ = null; - } } } diff --git a/src/app/manage/manage-course/manage-course.component.html b/src/app/manage/manage-course/manage-course.component.html new file mode 100644 index 0000000..89db0c4 --- /dev/null +++ b/src/app/manage/manage-course/manage-course.component.html @@ -0,0 +1,3 @@ +

+ manage-course works! +

diff --git a/src/app/manage/manage-course/manage-course.component.scss b/src/app/manage/manage-course/manage-course.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/manage/manage-course/manage-course.component.spec.ts b/src/app/manage/manage-course/manage-course.component.spec.ts new file mode 100644 index 0000000..b7861a6 --- /dev/null +++ b/src/app/manage/manage-course/manage-course.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageCourseComponent } from './manage-course.component'; + +describe('ManageCourseComponent', () => { + let component: ManageCourseComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ManageCourseComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageCourseComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/manage/manage-course/manage-course.component.ts b/src/app/manage/manage-course/manage-course.component.ts new file mode 100644 index 0000000..c834a1a --- /dev/null +++ b/src/app/manage/manage-course/manage-course.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'vg-manage-course', + templateUrl: './manage-course.component.html', + styleUrls: ['./manage-course.component.scss'] +}) +export class ManageCourseComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/manage/manage-dept/manage-dept.component.html b/src/app/manage/manage-dept/manage-dept.component.html new file mode 100644 index 0000000..1527253 --- /dev/null +++ b/src/app/manage/manage-dept/manage-dept.component.html @@ -0,0 +1,3 @@ +

+ manage-dept works! +

diff --git a/src/app/manage/manage-dept/manage-dept.component.scss b/src/app/manage/manage-dept/manage-dept.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/manage/manage-dept/manage-dept.component.spec.ts b/src/app/manage/manage-dept/manage-dept.component.spec.ts new file mode 100644 index 0000000..cafe951 --- /dev/null +++ b/src/app/manage/manage-dept/manage-dept.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageDeptComponent } from './manage-dept.component'; + +describe('ManageDeptComponent', () => { + let component: ManageDeptComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ManageDeptComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageDeptComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/manage/manage-dept/manage-dept.component.ts b/src/app/manage/manage-dept/manage-dept.component.ts new file mode 100644 index 0000000..b5e2923 --- /dev/null +++ b/src/app/manage/manage-dept/manage-dept.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'vg-manage-dept', + templateUrl: './manage-dept.component.html', + styleUrls: ['./manage-dept.component.scss'] +}) +export class ManageDeptComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/manage/manage-home/manage-home.component.html b/src/app/manage/manage-home/manage-home.component.html new file mode 100644 index 0000000..013fb4e --- /dev/null +++ b/src/app/manage/manage-home/manage-home.component.html @@ -0,0 +1,3 @@ +

+ manage-home works! +

diff --git a/src/app/manage/manage-home/manage-home.component.scss b/src/app/manage/manage-home/manage-home.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/manage/manage-home/manage-home.component.spec.ts b/src/app/manage/manage-home/manage-home.component.spec.ts new file mode 100644 index 0000000..266bff2 --- /dev/null +++ b/src/app/manage/manage-home/manage-home.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageHomeComponent } from './manage-home.component'; + +describe('ManageHomeComponent', () => { + let component: ManageHomeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ManageHomeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageHomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/manage/manage-home/manage-home.component.ts b/src/app/manage/manage-home/manage-home.component.ts new file mode 100644 index 0000000..819f6f7 --- /dev/null +++ b/src/app/manage/manage-home/manage-home.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'vg-manage-home', + templateUrl: './manage-home.component.html', + styleUrls: ['./manage-home.component.scss'] +}) +export class ManageHomeComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/manage/manage-material/manage-material.module.ts b/src/app/manage/manage-material/manage-material.module.ts new file mode 100644 index 0000000..39e035e --- /dev/null +++ b/src/app/manage/manage-material/manage-material.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +@NgModule({ + imports: [ + CommonModule + ], + declarations: [] +}) +export class ManageMaterialModule { } diff --git a/src/app/manage/manage-routing.module.ts b/src/app/manage/manage-routing.module.ts new file mode 100644 index 0000000..a47b1c0 --- /dev/null +++ b/src/app/manage/manage-routing.module.ts @@ -0,0 +1,41 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import {ManageHomeComponent} from './manage-home/manage-home.component'; +import {ManageCourseComponent} from './manage-course/manage-course.component'; +import {ManageDeptComponent} from './manage-dept/manage-dept.component'; + +export const manageRoutes: Routes = [ + { + path: '', + component: ManageHomeComponent, + data: { + depth: 1 + } + }, + { + path: ':dept', + component: ManageDeptComponent, + data: { + depth: 2 + } + } + , + { + path: ':dept/:id', + component: ManageCourseComponent, + data: { + depth: 3 + } + } +]; + +@NgModule({ + imports: [ + RouterModule.forChild(manageRoutes) + ], + exports: [ + RouterModule + ] +}) +export class ManageRoutingModule {} + diff --git a/src/app/manage/manage.module.ts b/src/app/manage/manage.module.ts new file mode 100644 index 0000000..ec7d19e --- /dev/null +++ b/src/app/manage/manage.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {ManageRoutingModule} from './manage-routing.module'; +import {ManageMaterialModule} from './manage-material/manage-material.module'; +import { ManageHomeComponent } from './manage-home/manage-home.component'; +import { ManageCourseComponent } from './manage-course/manage-course.component'; +import { ManageDeptComponent } from './manage-dept/manage-dept.component'; + +@NgModule({ + imports: [ + CommonModule, + ManageMaterialModule, + ManageRoutingModule + ], + declarations: [ManageHomeComponent, ManageCourseComponent, ManageDeptComponent] +}) +export class ManageModule { } diff --git a/src/app/nav-menu/_nav-menu-theme.scss b/src/app/nav-menu/_nav-menu-theme.scss index e758a61..8521499 100644 --- a/src/app/nav-menu/_nav-menu-theme.scss +++ b/src/app/nav-menu/_nav-menu-theme.scss @@ -14,7 +14,6 @@ $foreground: map-get($theme, foreground); .nav-menu { - //background: transparent; color: mat-color($foreground, text); &.mat-primary { diff --git a/src/app/nav-menu/nav-menu-header.html b/src/app/nav-menu/nav-menu-header.html index 700a595..2752b46 100644 --- a/src/app/nav-menu/nav-menu-header.html +++ b/src/app/nav-menu/nav-menu-header.html @@ -3,7 +3,7 @@ {{label}} + select="nav-menu-toggle, nav-menu-link, div"> diff --git a/src/app/nav-menu/nav-menu.scss b/src/app/nav-menu/nav-menu.scss index b135b05..25be0cd 100644 --- a/src/app/nav-menu/nav-menu.scss +++ b/src/app/nav-menu/nav-menu.scss @@ -1,6 +1,4 @@ -:host { - font-family: Roboto, "Helvetica Neue", sans-serif; -} +@import '~@angular/material/theming'; .md-visually-hidden { border: 0; diff --git a/src/app/nav-menu/nav-menu.ts b/src/app/nav-menu/nav-menu.ts index b482bc2..3a6c698 100644 --- a/src/app/nav-menu/nav-menu.ts +++ b/src/app/nav-menu/nav-menu.ts @@ -148,7 +148,6 @@ export class NavMenuHeaderComponent { host: { '[class.nav-menu]': 'true', '[class.site-sidenav]': 'true', - '[class.mat-elevation-z2]': 'true', '[attr.hide-print]': 'true' }, selector: 'nav-menu-container', diff --git a/src/app/shared/guards/auth.guard.ts b/src/app/shared/guards/auth.guard.ts index c0c17e1..27701f2 100644 --- a/src/app/shared/guards/auth.guard.ts +++ b/src/app/shared/guards/auth.guard.ts @@ -70,3 +70,25 @@ export class CanLoadAdmin implements CanLoad { })); } } + +@Injectable() +export class CanLoadManage implements CanLoad { + + constructor ( + private _router: Router, + private _authService: AuthService + ) { + } + + canLoad(route: Route): Observable | Promise | boolean { + + return first.call(map.call(this._authService.isManager, d => { + if (d) { + return true; + } else { + this._router.navigate(['/ausi']); + return false; + } + })); + } +} diff --git a/src/app/shared/resolvers/admin-resolver.spec.ts b/src/app/shared/resolvers/admin-resolver.spec.ts new file mode 100644 index 0000000..b4cff22 --- /dev/null +++ b/src/app/shared/resolvers/admin-resolver.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, async, inject } from '@angular/core/testing'; + +import { AdminResolver } from './admin-resolver'; + +describe('AdminResolveGuard', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AdminResolver] + }); + }); + + it('should ...', inject([AdminResolver], (guard: AdminResolver) => { + expect(guard).toBeTruthy(); + })); +}); diff --git a/src/app/shared/resolvers/admin-resolver.ts b/src/app/shared/resolvers/admin-resolver.ts new file mode 100644 index 0000000..17355ef --- /dev/null +++ b/src/app/shared/resolvers/admin-resolver.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import {ActivatedRouteSnapshot, Resolve} from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import {UserService} from '../services/user.service'; +import {HomeMenuService} from '../../home/home-menu.service'; + +@Injectable() +export class AdminResolver implements Resolve { + + private _courses = this._userService.admin; + + constructor( + private _userService: UserService, + private _homeService: HomeMenuService + ) { + } + + resolve(route: ActivatedRouteSnapshot) { + return new Observable(obs => { + this._courses.subscribe(data => { + this._homeService.setCourses([this._homeService.constructCourses(data, 'admin', true)]); + obs.next(true); + obs.complete(); + }); + }); + } +} diff --git a/src/app/shared/resolvers/courses-resolver.ts b/src/app/shared/resolvers/courses-resolver.ts new file mode 100644 index 0000000..16f113d --- /dev/null +++ b/src/app/shared/resolvers/courses-resolver.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import {ActivatedRouteSnapshot, Resolve} from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import {UserService} from '../services/user.service'; +import {HomeMenuService} from '../../home/home-menu.service'; + +@Injectable() +export class CoursesResolver implements Resolve { + + private _courses = this._userService.courses; + private _inCourses = this._userService.inactive; + + constructor( + private _userService: UserService, + private _homeService: HomeMenuService + ) { + } + + resolve(route: ActivatedRouteSnapshot) { + return new Observable(obs => { + this._courses + .subscribe(courses => { + this._inCourses + .subscribe(inactive => { + this._homeService.setCourses([this._homeService.constructCourses(courses, 'courses', true), + this._homeService.constructCourses(inactive, 'courses', false)]); + obs.next(true); + obs.complete(); + }) + }); + }); + } +} diff --git a/src/app/shared/resolvers/grading-resolver.ts b/src/app/shared/resolvers/grading-resolver.ts new file mode 100644 index 0000000..bd455ff --- /dev/null +++ b/src/app/shared/resolvers/grading-resolver.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import {ActivatedRouteSnapshot, Resolve} from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import {UserService} from '../services/user.service'; +import {HomeMenuService} from '../../home/home-menu.service'; + +@Injectable() +export class GradingResolver implements Resolve { + + private _courses = this._userService.grading; + + constructor( + private _userService: UserService, + private _homeService: HomeMenuService + ) { + } + + resolve(route: ActivatedRouteSnapshot) { + return new Observable(obs => { + this._courses.subscribe(data => { + this._homeService.setCourses([this._homeService.constructCourses(data, 'grading', true)]); + obs.next(true); + obs.complete(); + }); + }); + } +} diff --git a/src/app/shared/resolvers/landing-resolver.ts b/src/app/shared/resolvers/landing-resolver.ts new file mode 100644 index 0000000..f9fbe3f --- /dev/null +++ b/src/app/shared/resolvers/landing-resolver.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core'; +import {ActivatedRouteSnapshot, Resolve} from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import {HomeMenuService} from '../../home/home-menu.service'; + +@Injectable() +export class LandingResolver implements Resolve { + + private _landing = { + type: 'header', + label: 'Pages', + children: [ + { + type: 'link', + label: 'Home', + link: '/' + }, + { + type: 'link', + label: 'About', + link: '/about' + }, + { + type: 'link', + label: 'Help', + link: '/help' + } + ] + }; + + constructor(private _homeService: HomeMenuService) { } + + resolve(route: ActivatedRouteSnapshot) { + this._homeService.setCourses([this._landing]); + return Observable.of(true); + } +} diff --git a/src/app/shared/resolvers/manage-resolver.ts b/src/app/shared/resolvers/manage-resolver.ts new file mode 100644 index 0000000..46a2d91 --- /dev/null +++ b/src/app/shared/resolvers/manage-resolver.ts @@ -0,0 +1,54 @@ +import { Injectable } from '@angular/core'; +import {ActivatedRouteSnapshot, Resolve} from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import {UserService} from '../services/user.service'; +import {HomeMenuService} from '../../home/home-menu.service'; + +@Injectable() +export class ManageResolver implements Resolve { + + private _courses = this._userService.manage; + + private _home = c => { + return { + type: 'link', + label: 'Home', + link: '/manage/' + c + }; + }; + + constructor( + private _userService: UserService, + private _homeService: HomeMenuService + ) { + } + + resolve(route: ActivatedRouteSnapshot) { + return new Observable(obs => { + this._courses.subscribe(data => { + + const deps = { + type: 'header', + label: 'Departments', + children: data.reduce((a, d) => { + return [...a, { + type: 'toggle', + label: d['name'], + children: [this._home(d['name']), ...d['courses'].reduce((b, e) => { + return [...b, { + type: 'link', + label: e, + link: '/manage/' + d['name'] + '/' + e + }]; + }, [])] + }]; + }, []) + }; + + this._homeService.setCourses([deps]); + obs.next(true); + obs.complete(); + }); + }); + } +} diff --git a/src/app/shared/services/auth.service.ts b/src/app/shared/services/auth.service.ts index 491e8c8..604b64b 100644 --- a/src/app/shared/services/auth.service.ts +++ b/src/app/shared/services/auth.service.ts @@ -14,9 +14,11 @@ export class AuthService { private _loggedIn = new ReplaySubject(1); private _loggedIn$ = this._loggedIn.asObservable(); private _grader = new ReplaySubject(1); - private _grader$ = this._loggedIn.asObservable(); + private _grader$ = this._grader.asObservable(); private _admin = new ReplaySubject(1); - private _admin$ = this._loggedIn.asObservable(); + private _admin$ = this._admin.asObservable(); + private _manage = new ReplaySubject(1); + private _manage$ = this._manage.asObservable(); constructor( private _router: Router, @@ -39,6 +41,10 @@ export class AuthService { return this._grader$; } + get isManager(): Observable { + return this._manage$; + } + public login (username: string, password: string) { this._tempLogIn(); @@ -63,6 +69,7 @@ export class AuthService { this._loggedIn.next(true); this._grader.next(data['grading'].length !== 0); this._admin.next(data['admin'].length !== 0); + this._manage.next(data['manage']['privileges'].length !== 0); this.userService.populate(data, data['user']); obs.next(true); obs.complete(); @@ -71,6 +78,7 @@ export class AuthService { this._loggedIn.next(false); this._grader.next(false); this._admin.next(false); + this._manage.next(false); obs.next(false); obs.complete(); } diff --git a/src/app/shared/services/user.service.ts b/src/app/shared/services/user.service.ts index e76b5a8..362d2c3 100644 --- a/src/app/shared/services/user.service.ts +++ b/src/app/shared/services/user.service.ts @@ -10,12 +10,16 @@ export class UserService { admin: Observable; courses: Observable; inactive: Observable; + manage: Observable; + managePerms: Observable; private _utln: BehaviorSubject = new BehaviorSubject(''); private _grading: BehaviorSubject = new BehaviorSubject([]); private _admin: BehaviorSubject = new BehaviorSubject([]); private _courses: BehaviorSubject = new BehaviorSubject([]); private _inactive: BehaviorSubject = new BehaviorSubject([]); + private _manage: BehaviorSubject = new BehaviorSubject([]); + private _managePerms: BehaviorSubject = new BehaviorSubject([]); constructor() { this.utln = this._utln.asObservable(); @@ -23,6 +27,8 @@ export class UserService { this.admin = this._admin.asObservable(); this.courses = this._courses.asObservable(); this.inactive = this._inactive.asObservable(); + this.manage = this._manage.asObservable(); + this.managePerms = this._managePerms.asObservable(); } public populate (data, utln) { @@ -32,6 +38,8 @@ export class UserService { this._courses.next(data.courses); this._inactive.next(data.inactive); this._utln.next(data.user); + this._manage.next(data.manage.departments); + this._managePerms.next(data.manage.permissions); } } @@ -41,5 +49,7 @@ export class UserService { this._courses.next([]); this._inactive.next([]); this._utln.next(null); + this._manage.next([]); + this._managePerms.next([]); } } diff --git a/src/app/sw-updates/sw-updates.module.ts b/src/app/sw-updates/sw-updates.module.ts new file mode 100644 index 0000000..5670792 --- /dev/null +++ b/src/app/sw-updates/sw-updates.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SwUpdatesService} from './sw-updates.service'; +import {ServiceWorkerModule} from '@angular/service-worker'; + +@NgModule({ + imports: [ + CommonModule, + ServiceWorkerModule + ], + declarations: [], + providers: [SwUpdatesService] +}) +export class SwUpdatesModule { } diff --git a/src/app/sw-updates/sw-updates.service.spec.ts b/src/app/sw-updates/sw-updates.service.spec.ts new file mode 100644 index 0000000..c003407 --- /dev/null +++ b/src/app/sw-updates/sw-updates.service.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, inject } from '@angular/core/testing'; + +import { SwUpdatesService } from './sw-updates.service'; + +describe('SwUpdatesService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [SwUpdatesService] + }); + }); + + it('should be created', inject([SwUpdatesService], (service: SwUpdatesService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/sw-updates/sw-updates.service.ts b/src/app/sw-updates/sw-updates.service.ts new file mode 100644 index 0000000..4e3c893 --- /dev/null +++ b/src/app/sw-updates/sw-updates.service.ts @@ -0,0 +1,53 @@ +import {Injectable, OnDestroy} from '@angular/core'; +import {Subject} from 'rxjs/Subject'; +import {NgServiceWorker} from '@angular/service-worker'; +import {concat} from 'rxjs/operator/concat'; +import {Observable} from 'rxjs/Observable'; +import {debounceTime, RxChain, startWith, takeUntil} from '@angular/cdk'; + +/** + * credit to Angular Core team and their work on angular.io + */ +@Injectable() +export class SwUpdatesService implements OnDestroy { + + updateActivated; + + private _destroy = new Subject(); + private _checkInterval = 1000 * 60 * 60 * 6; // 6 hours + private _checkForUpdateSubj = new Subject(); + + constructor(private _sw: NgServiceWorker) { + RxChain.from(this._checkForUpdateSubj) + .call(takeUntil, this._destroy) + .call(debounceTime, this._checkInterval) + .call(startWith, null) + .subscribe(() => this._checkForUpdate()); + + this.updateActivated = takeUntil.call(this._sw.updates, this._destroy) + .filter(({type}) => type === 'activation') + .map(({version}) => version); + } + + ngOnDestroy() { + this._destroy.next(); + this._destroy.complete(); + } + + private _checkForUpdate() { + // Temp workaround for https://github.com/angular/mobile-toolkit/pull/137. + // TODO (): Remove once #137 is fixed. + concat.call(this._sw.checkForUpdate(), Observable.of(false)) + .take(1) + .subscribe(v => v ? this._activateUpdate() : this._scheduleCheckForUpdate()); + } + + private _activateUpdate() { + this._sw.activateUpdate(null) + .subscribe(() => this._scheduleCheckForUpdate()); + } + + private _scheduleCheckForUpdate() { + this._checkForUpdateSubj.next(); + } +} diff --git a/src/assets/data.json b/src/assets/data.json index d3d52ef..794f88f 100644 --- a/src/assets/data.json +++ b/src/assets/data.json @@ -39,5 +39,18 @@ "assigns": ["Final", "Midterm"] } ], + "manage": { + "departments": [ + { + "name": "COMP", + "courses": ["COMP15", "COMP20"] + }, + { + "name": "MATH", + "courses": ["MATH71", "MATH61"] + } + ], + "privileges": ["CREATE", "READ", "UPDATE", "DELETE"] + }, "user": "aplume01" } diff --git a/src/theme.scss b/src/theme.scss index 7e9a31d..23f0883 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -20,6 +20,7 @@ $background: ( selected-button: map_get($mat-grey, 300), selected-disabled-button: map_get($mat-grey, 400), disabled-button-toggle: map_get($mat-grey, 200), + unselected-chip: map_get($mat-grey, 300), ); $pdf-dark-background: ( @@ -35,6 +36,7 @@ $pdf-dark-background: ( selected-button: map_get($mat-grey, 900), selected-disabled-button: map_get($mat-blue-grey, 800), disabled-button-toggle: map_get($mat-grey, 1000), // there is no mat-blue-grey 1000 (grey-1000 == black) + unselected-chip: map_get($mat-blue-grey, 700), ); @function md-app-theme($primary, $accent, $warn, $background, $foreground) {