├── .browserslistrc ├── .coveralls.yml ├── .github └── PULL_REQUEST_TEMPATE.md ├── .gitignore ├── .huskyrc.js ├── .prettierignore ├── .travis.yml ├── LICENSE ├── README.md ├── angular.json ├── build.conf.js ├── commitlint.config.js ├── docs ├── CHANGELOG.md ├── RELEASE.md ├── SSOINFO.md └── assets │ └── sso_architecture.png ├── gulpfile.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── prettier.config.js ├── protractor.conf.js ├── proxy.conf.js ├── public └── .npmignore ├── scripts ├── build-release ├── bump-version.js ├── ci │ └── travis-script.sh ├── finish-release ├── nightly-publish ├── npm-publish ├── start-release └── version-placeholders.js ├── src ├── assets │ └── i18n │ │ └── en.json ├── docs-ui │ ├── app │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.routes.ts │ │ ├── covalent-components │ │ │ ├── covalent-components.component.html │ │ │ ├── covalent-components.component.scss │ │ │ └── covalent-components.component.ts │ │ ├── demos │ │ │ ├── demos.component.html │ │ │ ├── demos.component.scss │ │ │ └── demos.component.ts │ │ ├── icons-demo │ │ │ ├── icons-demo.component.html │ │ │ ├── icons-demo.component.scss │ │ │ └── icons-demo.component.ts │ │ ├── index.ts │ │ ├── main │ │ │ ├── main.component.html │ │ │ ├── main.component.scss │ │ │ └── main.component.ts │ │ ├── mat-components │ │ │ ├── mat-components.component.html │ │ │ ├── mat-components.component.scss │ │ │ └── mat-components.component.ts │ │ └── typography │ │ │ ├── typography.component.html │ │ │ ├── typography.component.scss │ │ │ └── typography.component.ts │ ├── config │ │ └── translate.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── index.html │ ├── main.ts │ ├── styles.scss │ ├── test.ts │ ├── tsconfig.app.json │ └── tsconfig.spec.json ├── lib │ ├── _theming.scss │ ├── access │ │ ├── access.module.ts │ │ ├── guards │ │ │ ├── block-root-access.guard.ts │ │ │ └── block-user-access.guard.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── public_api.ts │ ├── app-switcher │ │ ├── _app-switcher-theme.scss │ │ ├── app-switcher-menu │ │ │ ├── app-switcher-menu.component.html │ │ │ ├── app-switcher-menu.component.scss │ │ │ ├── app-switcher-menu.component.spec.ts │ │ │ └── app-switcher-menu.component.ts │ │ ├── app-switcher.component.html │ │ ├── app-switcher.component.scss │ │ ├── app-switcher.component.spec.ts │ │ ├── app-switcher.component.ts │ │ ├── app-switcher.module.ts │ │ ├── index.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ └── services │ │ │ └── products.service.ts │ ├── app │ │ ├── app.module.ts │ │ ├── app.service.spec.ts │ │ ├── app.service.ts │ │ ├── index.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── tags.service.spec.ts │ │ └── tags.service.ts │ ├── assets │ │ ├── assets.module.ts │ │ ├── assets.service.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── public_api.ts │ ├── audit │ │ ├── audit.module.ts │ │ ├── audit.service.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── public_api.ts │ ├── auth │ │ ├── auth.module.ts │ │ ├── config │ │ │ ├── vantageLoginProxyConfig.d.ts │ │ │ └── vantageLoginProxyConfig.js │ │ ├── guards │ │ │ └── authentication.guard.ts │ │ ├── index.ts │ │ ├── interceptors │ │ │ └── authentication.interceptor.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── session │ │ │ └── session.service.ts │ │ └── token │ │ │ └── token.service.ts │ ├── common │ │ ├── index.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ └── tokens.ts │ ├── index.ts │ ├── ng-package-common.js │ ├── ng-package.js │ ├── notification │ │ ├── index.ts │ │ ├── notification.module.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ └── smtp │ │ │ └── smtp.service.ts │ ├── package.json │ ├── sqle │ │ ├── connection.service.ts │ │ ├── credentials-dialog │ │ │ ├── credentials-dialog.component.html │ │ │ ├── credentials-dialog.component.scss │ │ │ ├── credentials-dialog.component.spec.ts │ │ │ └── credentials-dialog.component.ts │ │ ├── dictionary.service.ts │ │ ├── index.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── query.service.ts │ │ ├── spooled-query.service.ts │ │ └── sqle.module.ts │ ├── system │ │ ├── index.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── system.module.ts │ │ ├── system.service.spec.ts │ │ └── system.service.ts │ ├── test.ts │ ├── testing │ │ ├── cypress │ │ │ ├── index.ts │ │ │ ├── mock │ │ │ │ ├── README.md │ │ │ │ └── mockutility.ts │ │ │ ├── package.json │ │ │ └── utility │ │ │ │ ├── README.md │ │ │ │ └── utility.ts │ │ ├── index.ts │ │ └── public_api.ts │ ├── theme │ │ ├── README.md │ │ ├── _all-theme.scss │ │ ├── _default-variables.scss │ │ ├── _mixins.scss │ │ ├── _overrides.scss │ │ ├── _palette.scss │ │ ├── _theme.scss │ │ ├── icons │ │ │ ├── teradata-icons.svg │ │ │ └── teradata-logo.svg │ │ ├── index.ts │ │ ├── long-form-content │ │ │ └── _small-scale.scss │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── theme.module.ts │ │ ├── theme.service.spec.ts │ │ ├── theme.service.ts │ │ └── utilities │ │ │ └── icons.ts │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── user-profile │ │ ├── index.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── user-profile.component.html │ │ ├── user-profile.component.scss │ │ ├── user-profile.component.ts │ │ └── user-profile.module.ts │ ├── user │ │ ├── group │ │ │ └── group.service.ts │ │ ├── index.ts │ │ ├── ldap │ │ │ └── ldap.service.ts │ │ ├── package.json │ │ ├── public_api.ts │ │ ├── user.module.ts │ │ └── user │ │ │ └── user.service.ts │ └── utilities │ │ ├── index.ts │ │ ├── package.json │ │ ├── pre-loader │ │ ├── README.md │ │ ├── index.js │ │ ├── index.ts │ │ ├── pre-loader.html │ │ ├── pre-loader.scss │ │ └── pre-loader.ts │ │ ├── public_api.ts │ │ └── user-feedback │ │ ├── error │ │ └── error.service.ts │ │ ├── index.ts │ │ ├── toast │ │ └── toast.service.ts │ │ └── user-feedback.module.ts ├── polyfills.ts ├── theme.scss └── typings.d.ts ├── stylelint.config.js ├── tsconfig.json └── tslint.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-10 12 | IE 11 -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: dnS8M6Sk7IctRs0Hfty90EIdoHSuYrzAl 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | ### What's included? 5 | 6 | - One 7 | - Two 8 | - Three 9 | 10 | #### Test Steps 11 | 12 | - [ ] `npm ci` 13 | - [ ] In `proxy.conf.js` file, change serverUrl to `https://appcenter.ux.ac.uda.io` 14 | - [ ] `npm run serve` 15 | - [ ] then this 16 | - [ ] finally this 17 | 18 | #### General Tests for Every PR 19 | 20 | - [ ] `npm run serve:prod` still works. 21 | - [ ] `npm run tslint` passes. 22 | - [ ] `npm run stylelint` passes. 23 | - [ ] `npm test` passes and code coverage is not lower. 24 | - [ ] `npm run build:lib` still works. 25 | 26 | ##### Screenshots or link to StackBlitz/Plunker 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /deploy 6 | /tmp 7 | 8 | # dependencies 9 | node_modules 10 | /bower_components 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage/* 31 | /libpeerconnection.log 32 | npm-debug.log 33 | testem.log 34 | /typings 35 | /.vagrant 36 | 37 | # e2e 38 | /e2e/*.js 39 | /e2e/*.map 40 | 41 | #System Files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /.huskyrc.js: -------------------------------------------------------------------------------- 1 | const { covalentHooks, generateHuskyConfig } = require('./node_modules/@covalent/coding-standards/husky/husky.js'); 2 | const huskyHooks = generateHuskyConfig(covalentHooks()); 3 | module.exports = huskyHooks; 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | yarn.lock 4 | /bin 5 | /deploy 6 | /**/dist 7 | /coverage 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: required 3 | dist: trusty 4 | 5 | node_js: 6 | - '10.15.3' 7 | branches: 8 | only: 9 | - master 10 | - develop 11 | addons: 12 | firefox: latest 13 | before_script: 14 | - export CHROME_BIN=chromium-browser 15 | - export DISPLAY=:99.0 16 | - sh -e /etc/init.d/xvfb start 17 | jobs: 18 | include: 19 | - env: 'MODE=lint' 20 | - env: 'MODE=aot' 21 | - env: 'MODE=release' 22 | - env: 'MODE=unit-test' 23 | - env: 'MODE=audit' 24 | install: 25 | - npm ci 26 | script: 27 | - ./scripts/ci/travis-script.sh 28 | cache: 29 | directories: 30 | - ./node_modules/ 31 | after_success: 32 | - test $MODE == "release" && test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "develop" && npm run publish:nightly 33 | notifications: 34 | slack: 35 | secure: pkXQL5AZiSBh1yWjilrcA7KbcJjC4xxjhd0SAwogJCQgyEf/i8/CfR1ZXiZYsIBJT6HTI7UMdJzwP6TiY/zih6Mq8PqUg38NUsvGyznILkbksMQJieWrg1r+1ideplPJFX7qdXwrOcxvSVoEFIGha26X0Fglq3kXSBHpPR9U0lDCoUxLUO35txQ/iji85Na4hjQnmtBEQkqaJogA0hRdcSLIKxwScgSrb4UU2PXEaIS9Zpr2SOG/RTOMkrrSMOD7bgocZbhAbk3c5shPZNj51gpEN+692Qxp4kQ/nfT10Hu5ATLaFCM5v04+w0D3ZJLA46LpU47qP0ALy6O9d16pGUcxJGbWaMZpV53vV9jIl9y2ahaqN1h1J9BcLIOzJvaQy92km8F7a3l7cN8gWSUZjs5Hd+gPFQH9Flcydmq26e8Maa1tQDF5R3GIdaCw4qkuJYbl4ToE59wtiPQ6M7xVKqNK4Qypu1YNsKOoLG/tZRFvp4771vgWcR5Lu/DqJJ9SAB0jsdrOXpe+0DmdrLBwhoZv2D9FTce+clDHIJ7ObPEc/UKw8rtWAA5iCPCEJ0sPl+WZwOS3ZFp4QmMC+5mzffMUiX6HBnzxiyOZvYGJD/jTy1yA1Cmt4RJYrOPM73csI1ELs5tj4tvqBNJQ8daIenfkg7u42IJfByDGIsJz8to= 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2019 by Teradata. All rights reserved. http://teradata.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Vantage UI Platform 2 | 3 | [![Build Status](https://travis-ci.org/Teradata/vantage-ui-platform.svg?branch=develop)](https://travis-ci.org/Teradata/vantage-ui-platform) 4 | [![npm](https://img.shields.io/npm/v/%40vantage/ui-platform.svg)](https://www.npmjs.com/package/@td-vantage/ui-platform) 5 | [![npm](https://img.shields.io/npm/v/%40vantage/ui-platform/next.svg)](https://www.npmjs.com/package/@td-vantage/ui-platform/v/next) 6 | 7 | [![Coverage Status](https://coveralls.io/repos/github/Teradata/vantage-ui-platform/badge.svg)](https://coveralls.io/github/Teradata/vantage-ui-platform) 8 | [![npm](https://img.shields.io/npm/l/@td-vantage/ui-platform.svg)](LICENSE) 9 | 10 | ### Components, Utilities and Services for all Teradata Angular UIs 11 | 12 | ## Information 13 | 14 | ### Setup 15 | 16 | - Ensure you have **Node 10.15.3** (on a Mac use Homebrew and `brew install node@10.15.3`) 17 | - Ensure you have **NPM 6+** installed. 18 | - Install Docker Engine: [https://docs.docker.com/engine/installation/](https://docs.docker.com/engine/installation/) 19 | - Install Angular CLI `npm i -g @angular/cli` 20 | - Install Typescript `npm i -g typescript` 21 | - Install TSLint `npm i -g tslint` 22 | - Install Protractor for e2e testing `npm i -g protractor` 23 | - Install Node packages `npm install` 24 | 25 | ### Development 26 | 27 | 1. Update the `serverUrl` variable in the `proxy.conf.js` to point to your vantage environment. 28 | 29 | 2. Run local webserver `npm run serve` 30 | 31 | 3. In Chrome go to [http://localhost:4200](http://localhost:4200) 32 | 33 | ## Build and publish 34 | 35 | - Build the source code 36 | 37 | `npm run build:lib` 38 | 39 | - Publish to npm 40 | 41 | `npm run publish:npm` 42 | 43 | ## Usage Notes 44 | 45 | ### Single Sign-On 46 | 47 | click here for information about [SSO](./docs/SSOINFO.md) 48 | 49 | ### Http 50 | 51 | - HTTP in the ui-platform uses Covalent Http 52 | - See more information here: [https://teradata.github.io/covalent/#/components/http](https://teradata.github.io/covalent/#/components/http) 53 | - An es7 polyfill will be required in the Angular Application 54 | - Create a file named `src/polyfills.ts` 55 | - In that file add the following import: 56 | 57 | ``` 58 | import 'core-js/es7/reflect'; 59 | ``` 60 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "docs-ui": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "style": "scss" 11 | } 12 | }, 13 | "root": "", 14 | "sourceRoot": "src", 15 | "architect": { 16 | "build": { 17 | "builder": "@angular-builders/custom-webpack:browser", 18 | "options": { 19 | "indexTransform": "./src/lib/utilities/pre-loader/", 20 | "outputPath": "dist", 21 | "index": "src/docs-ui/index.html", 22 | "main": "src/docs-ui/main.ts", 23 | "tsConfig": "src/docs-ui/tsconfig.app.json", 24 | "polyfills": "src/polyfills.ts", 25 | "aot": false, 26 | "assets": [ 27 | "src/assets", 28 | { 29 | "glob": "*", 30 | "input": "src/lib/theme/icons/", 31 | "output": "/assets/icons/" 32 | }, 33 | { 34 | "glob": "favicon.ico", 35 | "input": "src/docs-ui/", 36 | "output": "/" 37 | } 38 | ], 39 | "styles": ["src/theme.scss", "src/docs-ui/styles.scss"], 40 | "scripts": ["node_modules/hammerjs/hammer.min.js"] 41 | }, 42 | "configurations": { 43 | "production": { 44 | "optimization": true, 45 | "outputHashing": "all", 46 | "sourceMap": false, 47 | "extractCss": true, 48 | "namedChunks": false, 49 | "aot": true, 50 | "extractLicenses": true, 51 | "vendorChunk": false, 52 | "buildOptimizer": true, 53 | "fileReplacements": [ 54 | { 55 | "replace": "src/docs-ui/environments/environment.ts", 56 | "with": "src/docs-ui/environments/environment.prod.ts" 57 | } 58 | ], 59 | "budgets": [ 60 | { 61 | "type": "initial", 62 | "maximumWarning": "2mb", 63 | "maximumError": "5mb" 64 | } 65 | ] 66 | } 67 | } 68 | }, 69 | "serve": { 70 | "builder": "@angular-builders/custom-webpack:dev-server", 71 | "options": { 72 | "browserTarget": "docs-ui:build", 73 | "proxyConfig": "./proxy.conf.js" 74 | }, 75 | "configurations": { 76 | "production": { 77 | "browserTarget": "docs-ui:build:production", 78 | "proxyConfig": "./proxy.conf.js" 79 | } 80 | } 81 | }, 82 | "extract-i18n": { 83 | "builder": "@angular-devkit/build-angular:extract-i18n", 84 | "options": { 85 | "browserTarget": "docs-ui:build" 86 | } 87 | }, 88 | "test": { 89 | "builder": "@angular-devkit/build-angular:karma", 90 | "options": { 91 | "main": "src/docs-ui/test.ts", 92 | "karmaConfig": "./karma.conf.js", 93 | "polyfills": "src/polyfills.ts", 94 | "tsConfig": "src/docs-ui/tsconfig.spec.json", 95 | "scripts": ["node_modules/hammerjs/hammer.min.js"], 96 | "styles": ["src/theme.scss", "src/docs-ui/styles.scss"], 97 | "assets": [ 98 | "src/assets", 99 | { 100 | "glob": "favicon.ico", 101 | "input": "src/docs-ui/", 102 | "output": "/" 103 | } 104 | ] 105 | } 106 | }, 107 | "lint": { 108 | "builder": "@angular-devkit/build-angular:tslint", 109 | "options": { 110 | "tsConfig": ["src/docs-ui/tsconfig.app.json", "src/docs-ui/tsconfig.spec.json"], 111 | "exclude": ["**/node_modules/**"] 112 | } 113 | }, 114 | "e2e": { 115 | "builder": "@angular-devkit/build-angular:protractor", 116 | "options": { 117 | "protractorConfig": "e2e/protractor.conf.js", 118 | "devServerTarget": "docs-ui:serve" 119 | }, 120 | "configurations": { 121 | "production": { 122 | "devServerTarget": "docs-ui:serve:production" 123 | } 124 | } 125 | } 126 | } 127 | }, 128 | "ui-platform": { 129 | "root": "", 130 | "sourceRoot": "src", 131 | "projectType": "library", 132 | "prefix": "lib", 133 | "architect": { 134 | "build": { 135 | "builder": "@angular-devkit/build-ng-packagr:build", 136 | "options": { 137 | "tsConfig": "src/lib/tsconfig.lib.json", 138 | "project": "src/lib/ng-package.js" 139 | } 140 | }, 141 | "test": { 142 | "builder": "@angular-devkit/build-angular:karma", 143 | "options": { 144 | "main": "src/lib/test.ts", 145 | "karmaConfig": "./karma.conf.js", 146 | "polyfills": "src/polyfills.ts", 147 | "tsConfig": "src/lib/tsconfig.spec.json", 148 | "scripts": ["node_modules/hammerjs/hammer.min.js"], 149 | "styles": ["src/theme.scss"], 150 | "assets": ["src/assets"] 151 | } 152 | } 153 | } 154 | } 155 | }, 156 | "defaultProject": "docs-ui", 157 | "schematics": { 158 | "@schematics/angular:component": { 159 | "prefix": "app", 160 | "styleext": "scss" 161 | }, 162 | "@schematics/angular:directive": { 163 | "prefix": "app" 164 | } 165 | }, 166 | "cli": { 167 | "analytics": false 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /build.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | deployed: 'deploy/ui-platform/', 5 | angularVersion: '9.0.0', 6 | materialVersion: '9.0.0', 7 | covalentVersion: '3.0.0', 8 | translateVersion: '12.0.0', 9 | }; 10 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | var defaultConfig = require('./node_modules/@covalent/coding-standards/commitlint/commitlint.config.js'); 2 | module.exports = defaultConfig; 3 | -------------------------------------------------------------------------------- /docs/RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Guide for the Platform 2 | 3 | ## Release 4 | 5 | - [Pre Release Checklist](#pre-release-checklist) 6 | - [Start Release](#start-release) 7 | - [Finish Release](#finish-release) 8 | - [Publish Release](#publish-release) 9 | 10 | #### Pre Release Checklist 11 | 12 | 1. Make sure the `build.conf.js` points to the correct versions. 13 | 2. `ng serve --prod` works fine. 14 | 3. `npm run build:lib` works fine. 15 | 16 | #### Start Release 17 | 18 | Execute `npm run release:start -- [version]` to start the automatic release process. The steps executed are: 19 | 20 | 1. Checks out the `master` branch and pulls the latest. 21 | 2. Checks out the `develop` branch. 22 | 3. Executes a typescript linting test. 23 | 4. Executes a sass linting test. 24 | 5. Executes unit tests. 25 | 6. Executes a build release test. 26 | 7. Bumps its version to [version] release 27 | 8. Executes `npm run generate:changelog` to generate a draft of the changelog with the commits that happened between the last tagged release and the last commit. NOTE: It need to be double checked and modified as needed. 28 | 29 | #### Finish Release 30 | 31 | Execute `npm run release:finish -- [version]` to finish the release process. The steps executed are: 32 | 33 | 1. Adds and commits all changes (changelog changes, bump, etc etc). 34 | 2. Creates new `[version]` tag 35 | 3. Pushes commit and new tag into the repository (`develop`). 36 | 4. Rebases `master` with `develop` and pushes changes to repository. 37 | 5. Returns to `develop` branch. 38 | 39 | #### Publish Release 40 | 41 | ##### Stable Release 42 | 43 | Execute `npm run publish:npm` from develop branch to start the automatic publishing process. The steps executed are: 44 | 45 | 1. Executes `npm run build:lib` process. 46 | 2. Executes `bash scripts/npm-publish` process. 47 | 48 | ##### Beta/RC Release 49 | 50 | Execute `npm run publish:npm -- next` to publish a beta/RC Release. 51 | -------------------------------------------------------------------------------- /docs/SSOINFO.md: -------------------------------------------------------------------------------- 1 | ## SSO Information 2 | 3 | ### Architecture 4 | 5 | - SSO in Vantage is provided by Vantage Services and the API Gateway 6 | - The Specification used is the OpenID Connect Authorization Code Flow 7 | - There are two ways to integrate with SSO 8 | - Integrate following the flow detailed here: 9 | - Specification: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth 10 | - Utilize the `@td-vantage/ui-platform` module in your Angular/Covalent application 11 | - Utilizes the API Gateway and Vantage User Service to handle the OpenID Connect flow 12 | - No Tokens are stored in the browser (better security) 13 | - Handles CSRF checking 14 | - Easy integration 15 | 16 | SSO Architecture 17 | 18 | --- 19 | 20 | ### Usage 21 | 22 | 1. Update proxy.conf.js file to include the `VantageLoginProxyConfig` from `@td-vantage/ui-platform` and replace the `serverUrl` with Vantage Base URL: 23 | 24 | e.g. 25 | 26 | ```js 27 | const vantageLoginProxyConfig = require('@td-vantage/ui-platform/auth/config/vantageLoginProxyConfig'); 28 | 29 | /* * * * * * * * * * * */ 30 | /* Edit these variables to point to your */ 31 | /* Vantage and local development environments */ 32 | /* * * * * * * * * * * */ 33 | 34 | const serverUrl = 'https://vantage.url.io'; // REPLACE WITH VANTAGE BASE URL 35 | const localUrl = 'localhost:4200'; 36 | const localProto = 'http'; // http or https 37 | 38 | /* * * * * * * * * * * */ 39 | /* This section contains the routes proxied through */ 40 | /* your local development environment and the Vantage deployment */ 41 | /* * * * * * * * * * * */ 42 | 43 | const PROXY_CONFIG = { 44 | ...vantageLoginProxyConfig({ serverUrl, localUrl, localProto }), 45 | '/api': { 46 | target: serverUrl, 47 | secure: false, 48 | changeOrigin: true, 49 | }, 50 | }; 51 | 52 | module.exports = PROXY_CONFIG; 53 | ``` 54 | 55 | 2. Import required dependencies in app.module.ts or desired NgModule. 56 | 57 | ```ts 58 | import { VantageAuthenticationModule, VantageAuthenticationInterceptor } from '@td-vantage/ui-platform/auth'; 59 | import { VantageUserModule } from '@td-vantage/ui-platform/user'; 60 | ``` 61 | 62 | 3. Below the last import statement in the same app.module.ts file, declare interceptor providers 63 | 64 | ```ts 65 | const httpInterceptorProviders: Type[] = [VantageAuthenticationInterceptor]; 66 | ``` 67 | 68 | 4. Provide modules, interceptors, and services in app.module.ts to NgModule 69 | 70 | ```ts 71 | @NgModule({ 72 | declarations: [], 73 | imports: [ 74 | //Import Modules 75 | VantageUserModule, 76 | VantageAuthenticationModule, 77 | 78 | //Declare interceptor 79 | CovalentHttpModule.forRoot({ 80 | interceptors: [{ 81 | interceptor: VantageAuthenticationInterceptor, paths: ['**'], 82 | }], 83 | }), 84 | 85 | ], 86 | providers: [ 87 | // Declare service providers 88 | httpInterceptorProviders, 89 | ], 90 | ``` 91 | 92 | 5. Protect your routes in app.routes.ts with TdAuthenticationModule 93 | 94 | ```ts 95 | import { VantageAuthenticationGuard } from '@td-vantage/ui-platform/auth'; 96 | 97 | const routes: Routes = [ 98 | // In root path provide guard to canActivate 99 | { 100 | path: '', 101 | component: MyComponent, 102 | canActivate: [VantageAuthenticationGuard], 103 | children: [ 104 | ... 105 | ], 106 | }, 107 | { path: '**', redirectTo: '/' }, 108 | ]; 109 | ``` 110 | 111 | ### Note 112 | 113 | If you are deploying outside the Vantage environment, there is a known issue with redirecting back to the previous page upon login. In your `default.conf`, add: 114 | 115 | ``` 116 | location ~ .*/start-login { 117 | proxy_pass APPCENTERBASEURL; 118 | proxy_set_header X-Orig-Host TARGETHOSTNAME:TARGETPORT; 119 | proxy_set_header X-Orig-Proto http; 120 | proxy_redirect off; 121 | rewrite ^/start-login(.*)$ /$1 break; 122 | } 123 | ``` 124 | 125 | where `TARGETHOSTNAME` is the application URL and `TARGETPORT` is the port. 126 | -------------------------------------------------------------------------------- /docs/assets/sso_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/docs/assets/sso_architecture.png -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('require-dir')('./scripts'); 4 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | basePath: '.', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('karma-spec-reporter'), 14 | require('@angular-devkit/build-angular/plugins/karma'), 15 | ], 16 | client: { 17 | clearContext: false, // leave Jasmine Spec Runner output visible in browser 18 | }, 19 | customLaunchers: { 20 | ChromeCustom: { 21 | base: 'ChromeHeadless', 22 | flags: ['--no-sandbox'], 23 | }, 24 | }, 25 | files: [ 26 | { pattern: './node_modules/hammerjs/hammer.min.js' }, 27 | { pattern: './src/lib/theme/icons' }, 28 | { pattern: './node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: true }, 29 | ], 30 | client: { 31 | clearContext: false, // leave Jasmine Spec Runner output visible in browser 32 | }, 33 | preprocessors: {}, 34 | mime: { 35 | 'text/x-typescript': ['ts', 'tsx'], 36 | }, 37 | coverageIstanbulReporter: { 38 | dir: require('path').join(__dirname, 'coverage'), 39 | reports: ['html', 'lcovonly', 'cobertura'], 40 | reports: ['html', 'lcovonly', 'text-summary'], 41 | fixWebpackSourcePaths: true, 42 | }, 43 | angularCli: { 44 | environment: 'dev', 45 | }, 46 | reporters: config.angularCli && config.angularCli.codeCoverage ? ['spec', 'coverage-istanbul'] : ['spec', 'kjhtml'], 47 | port: 9876, 48 | colors: true, 49 | logLevel: config.LOG_INFO, 50 | autoWatch: true, 51 | browsers: ['ChromeCustom'], 52 | singleRun: false, 53 | browserNoActivityTimeout: 90000, 54 | browserDisconnectTolerance: 10, 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@td-vantage/ui-platform", 3 | "version": "1.0.0-beta.5", 4 | "description": "Teradata Vantage Angular Platform for easy integration and usage", 5 | "keywords": [ 6 | "teradata", 7 | "vantage", 8 | "platform", 9 | "ui", 10 | "sso", 11 | "services" 12 | ], 13 | "scripts": { 14 | "serve": "./node_modules/.bin/ng serve", 15 | "serve:prod": "node --max_old_space_size=8192 ./node_modules/.bin/ng serve --aot --prod --source-map=false --optimization --proxy-config proxy.conf.js", 16 | "build:docs": "node --max_old_space_size=5048 ./node_modules/@angular/cli/bin/ng build --aot --prod --source-map=false --optimization", 17 | "lint": "npm run tslint && npm run stylelint", 18 | "tslint": "ng lint --format codeFrame --fix", 19 | "stylelint": "./node_modules/.bin/stylelint 'src/**/*.scss' '!**/assets/**' --config stylelint.config.js --syntax scss", 20 | "webdriver-update": "bash ./node_modules/.bin/webdriver-manager update", 21 | "test": "ng test ui-platform --code-coverage --source-map=false --watch=false", 22 | "coveralls": "cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js", 23 | "build:lib": "bash scripts/build-release && gulp version-placeholder", 24 | "release:start": "bash scripts/start-release", 25 | "release:finish": "bash scripts/finish-release", 26 | "generate:changelog": "./node_modules/.bin/conventional-changelog -i docs/CHANGELOG.md -s -p angular", 27 | "publish:npm": "npm run build:lib && bash scripts/npm-publish", 28 | "publish:nightly": "npm run build:lib && bash scripts/nightly-publish", 29 | "bump:version": "gulp bump-version --ver", 30 | "prettier": "./node_modules/.bin/prettier --write './**/*.{ts,js,json,css,scss,html,yml,md}'", 31 | "prettier:check": "./node_modules/.bin/prettier --check './**/*.{ts,js,json,css,scss,html,yml,md}'" 32 | }, 33 | "engines": { 34 | "node": ">=10.15.3", 35 | "npm": ">=6" 36 | }, 37 | "repository": { 38 | "type": "git", 39 | "url": "https://github.com/Teradata/vantage-ui-platform" 40 | }, 41 | "bugs": { 42 | "url": "https://github.com/Teradata/vantage-ui-platform/issues" 43 | }, 44 | "license": "MIT", 45 | "author": "Teradata UI Team", 46 | "dependencies": { 47 | "@angular/animations": "^9.0.0", 48 | "@angular/cdk": "^9.0.0", 49 | "@angular/common": "^9.0.0", 50 | "@angular/compiler": "^9.0.0", 51 | "@angular/core": "^9.0.0", 52 | "@angular/forms": "^9.0.0", 53 | "@angular/material": "^9.0.0", 54 | "@angular/platform-browser": "^9.0.0", 55 | "@angular/platform-browser-dynamic": "^9.0.0", 56 | "@angular/platform-server": "^9.0.0", 57 | "@angular/router": "^9.0.0", 58 | "@covalent/core": "git+https://github.com/Teradata/covalent-nightly.git", 59 | "@covalent/echarts": "3.0.0-beta.3", 60 | "@covalent/flavored-markdown": "3.1.0-beta.1", 61 | "@covalent/highlight": "3.0.0-beta.3", 62 | "@covalent/http": "3.0.0-beta.3", 63 | "@covalent/markdown": "^3.0.1", 64 | "@covalent/markdown-navigator": "git+https://github.com/Teradata/covalent-markdown-navigator-nightly.git", 65 | "@ngx-translate/core": "12.0.0", 66 | "@ngx-translate/http-loader": "4.0.0", 67 | "core-js": "^2.5.4", 68 | "cypress": "^4.12.0", 69 | "echarts": "4.2.1", 70 | "hammerjs": "^2.0.8", 71 | "moment": "^2.17.1", 72 | "rxjs": "^6.5.4", 73 | "sass": "^1.25.0", 74 | "tslib": "^1.10.0", 75 | "web-animations-js": "2.3.2", 76 | "zone.js": "^0.10.2" 77 | }, 78 | "devDependencies": { 79 | "@angular-builders/custom-webpack": "8.4.1", 80 | "@angular-devkit/build-angular": "^0.901.12", 81 | "@angular-devkit/build-ng-packagr": "^0.900.0", 82 | "@angular-devkit/core": "^9.0.0", 83 | "@angular-devkit/schematics": "^9.0.0", 84 | "@angular/cli": "^9.0.0", 85 | "@angular/compiler-cli": "^9.0.0", 86 | "@covalent/coding-standards": "git+https://github.com/Teradata/covalent-coding-standards-nightly.git", 87 | "@types/hammerjs": "^2.0.30", 88 | "@types/jasmine": "~3.5.0", 89 | "@types/jasminewd2": "~2.0.3", 90 | "@types/node": "^12.7.2", 91 | "autoprefixer": "9.6.5", 92 | "conventional-changelog-cli": "^2.0.34", 93 | "coveralls": "^3.0.3", 94 | "glob": "^6.0.4", 95 | "gulp": "4.0.2", 96 | "gulp-bump": "3.1.3", 97 | "gulp-hub": "4.2.0", 98 | "jasmine-core": "^3.5.0", 99 | "karma": "^5.0.8", 100 | "karma-chrome-launcher": "^2.2.0", 101 | "karma-coverage-istanbul-reporter": "^2.1.1", 102 | "karma-jasmine": "^2.0.1", 103 | "karma-jasmine-html-reporter": "^1.5.1", 104 | "karma-spec-reporter": "0.0.32", 105 | "ng-packagr": "^9.0.0", 106 | "protractor": "^7.0.0", 107 | "require-dir": "0.3.2", 108 | "semver": "5.2.0", 109 | "ts-node": "~7.0.0", 110 | "tsickle": "0.35.0", 111 | "typescript": "~3.7.5" 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | var defaultConfig = require('./node_modules/@covalent/coding-standards/prettier/prettier.config.js'); 2 | module.exports = defaultConfig; 3 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | /*global jasmine */ 5 | var SpecReporter = require('jasmine-spec-reporter'); 6 | 7 | exports.config = { 8 | allScriptsTimeout: 11000, 9 | specs: ['./e2e/**/*.e2e-spec.ts'], 10 | capabilities: { 11 | browserName: 'chrome', 12 | }, 13 | directConnect: true, 14 | baseUrl: 'http://localhost:4200/', 15 | framework: 'jasmine', 16 | jasmineNodeOpts: { 17 | showColors: true, 18 | defaultTimeoutInterval: 30000, 19 | print: function() {}, 20 | }, 21 | useAllAngular2AppRoots: true, 22 | beforeLaunch: function() { 23 | require('ts-node').register({ 24 | project: 'e2e', 25 | }); 26 | }, 27 | onPrepare: function() { 28 | jasmine.getEnv().addReporter(new SpecReporter()); 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /proxy.conf.js: -------------------------------------------------------------------------------- 1 | const vantageLoginProxyConfig = require('./src/lib/auth/config/vantageLoginProxyConfig'); 2 | 3 | /* * * * * * * * * * * */ 4 | /* Edit these variables to point to your */ 5 | /* Vantage and local development environments */ 6 | /* * * * * * * * * * * */ 7 | 8 | const serverUrl = 'https://vantage.url.io'; // REPLACE WITH VANTAGE BASE URL 9 | const localUrl = 'localhost:4200'; 10 | const localProto = 'http'; // http or https 11 | 12 | /* * * * * * * * * * * */ 13 | /* This section contains the routes proxied through */ 14 | /* your local development environment and the Vantage deployment */ 15 | /* * * * * * * * * * * */ 16 | 17 | const PROXY_CONFIG = { 18 | ...vantageLoginProxyConfig({ serverUrl, localUrl, localProto }), 19 | '/api': { 20 | target: serverUrl, 21 | secure: false, 22 | changeOrigin: true, 23 | }, 24 | '/ui-assets': { 25 | target: serverUrl, 26 | secure: false, 27 | changeOrigin: true, 28 | }, 29 | }; 30 | 31 | module.exports = PROXY_CONFIG; 32 | -------------------------------------------------------------------------------- /public/.npmignore: -------------------------------------------------------------------------------- 1 | # compiled aot output 2 | *.ngsummary.json 3 | *.ngfactory.ts 4 | *.shim.ngstyle.ts -------------------------------------------------------------------------------- /scripts/build-release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | echo 'Clean up' 5 | rm -rf ./deploy 6 | 7 | ./node_modules/.bin/ng build ui-platform 8 | 9 | rm -rf src/lib/node_modules 10 | 11 | # Adding config file to ui-platform 12 | cp -R ./src/lib/auth/config ./deploy/ui-platform/auth/ 13 | 14 | # Adding theming file to ui-platform 15 | cp ./src/lib/app-switcher/_*.scss ./deploy/ui-platform/app-switcher/ 16 | 17 | cp ./src/lib/theme/*.scss ./deploy/ui-platform/theme/ 18 | cp ./src/lib/_theming.scss ./deploy/ui-platform/ 19 | 20 | mkdir -p ./deploy/ui-platform/theme/long-form-content/ && cp -R ./src/lib/theme/long-form-content ./deploy/ui-platform/theme/ 21 | 22 | # Add pre-loader files 23 | mkdir -p ./deploy/ui-platform/utilities/pre-loader && cp -R ./src/lib/utilities/pre-loader ./deploy/ui-platform/utilities 24 | rm ./deploy/ui-platform/utilities/pre-loader/index.ts 25 | rm ./deploy/ui-platform/utilities/pre-loader/pre-loader.ts 26 | 27 | mkdir -p ./deploy/ui-platform/theme/icons && cp -R ./src/lib/theme/icons ./deploy/ui-platform/theme/ 28 | 29 | echo 'Build Complete' 30 | -------------------------------------------------------------------------------- /scripts/bump-version.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var bump = require('gulp-bump'); 5 | var semver = require('semver'); 6 | 7 | var minimist = require('minimist'); 8 | 9 | var knownOptions = { 10 | string: 'ver', 11 | }; 12 | 13 | var options = minimist(process.argv.slice(2), knownOptions); 14 | 15 | gulp.task('bump-version', function() { 16 | if (!options.ver) { 17 | throw '--ver is required'; 18 | } 19 | if (!semver.valid(options.ver)) { 20 | throw '--ver selected as input is not supported.'; 21 | } 22 | return gulp 23 | .src('package.json') 24 | .pipe(bump({ version: options.ver })) 25 | .pipe(gulp.dest('.')); 26 | }); 27 | -------------------------------------------------------------------------------- /scripts/ci/travis-script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script that runs in every Travis CI container. 4 | # Responsible for testing the project in different Travis jobs of the current build stage. 5 | 6 | # The script should immediately exit if any command in the script fails. 7 | set -e 8 | 9 | # Go to project directory 10 | cd $(dirname $0)/../.. 11 | 12 | if [[ -z "$TRAVIS" ]]; then 13 | echo "This script can only run inside of Travis build jobs." 14 | exit 1 15 | fi 16 | 17 | echo "" 18 | echo "Building sources and running tests. Running mode: ${MODE}" 19 | echo "" 20 | 21 | # Get commit diff 22 | if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then 23 | fileDiff=$(git diff --name-only $TRAVIS_COMMIT_RANGE) 24 | else 25 | fileDiff=$(git diff --name-only $TRAVIS_BRANCH...HEAD) 26 | fi 27 | 28 | # Check if tests can be skipped 29 | if [[ ${fileDiff} =~ ^(.*\.md\s*)*$ ]]; then 30 | echo "Skipping tests since only markdown files changed." 31 | exit 0 32 | fi 33 | 34 | if [ "${MODE}" = "lint" ]; then 35 | npm run lint 36 | elif [ "${MODE}" = "aot" ]; then 37 | npm run build:docs 38 | elif [ "${MODE}" = "release" ]; then 39 | npm run build:lib 40 | elif [ "${MODE}" = "unit-test" ]; then 41 | npm run test 42 | elif [ "${MODE}" = "audit" ]; then 43 | npm audit --production --audit-level=high 44 | fi 45 | 46 | # Upload coverage results if those are present. 47 | if [ -f coverage/lcov.info ]; then 48 | npm run coveralls 49 | fi -------------------------------------------------------------------------------- /scripts/finish-release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | version=$1 3 | 4 | set -e 5 | 6 | echo "Create commit for bump and changelog" 7 | git add -A . 8 | 9 | git commit -a -m "feat(): generate changelog and bump to version v$version" 10 | 11 | echo "Create tag" 12 | git tag -a v$version 13 | 14 | echo "Pushed tag to main repo" 15 | git push --tags 16 | 17 | echo "Pushing changes into develop" 18 | git push origin develop 19 | 20 | echo "Rebasing and pushing changes into master" 21 | git checkout master 22 | git rebase develop 23 | git push origin master 24 | 25 | echo "Return to develop branch" 26 | git checkout develop -------------------------------------------------------------------------------- /scripts/nightly-publish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit -o nounset 4 | 5 | package="ui-platform" 6 | buildDir="deploy/ui-platform" 7 | 8 | commitSha=$(git rev-parse --short HEAD) 9 | commitAuthorName=$(git --no-pager show -s --format='%an' HEAD) 10 | commitAuthorEmail=$(git --no-pager show -s --format='%ae' HEAD) 11 | commitMessage=$(git log --oneline -n 1) 12 | 13 | repoName="ui-platform-nightly" 14 | repoUrl="https://github.com/Teradata/vantage-ui-platform-nightly.git" 15 | repoDir="deploy/$repoName" 16 | 17 | echo "Start up" 18 | rm -rf $repoDir 19 | 20 | echo "Cloning $repoUrl into $repoDir" 21 | git clone $repoUrl $repoDir 22 | 23 | echo "Cleaning nightly repo and moving release files into it" 24 | rm -rf $repoDir/* 25 | cp -rf $buildDir/* $repoDir 26 | cd $repoDir 27 | 28 | # Prepare Git for pushing the artifacts to the repository. 29 | 30 | git config user.name "$commitAuthorName" 31 | git config user.email "$commitAuthorEmail" 32 | git config credential.helper "store --file=.git/credentials" 33 | 34 | echo "https://${UI_PLATFORM_NIGHTLY_TOKEN}:@github.com" > .git/credentials 35 | 36 | if [ -n "$(git status --porcelain)" ]; then 37 | git add -A 38 | git commit -m "$commitMessage" 39 | git tag "$commitSha" 40 | git push origin master --tags 41 | echo "Finished publishing nightly build for ${package}" 42 | else 43 | echo "No changes to commit for ${package}"; 44 | fi 45 | -------------------------------------------------------------------------------- /scripts/npm-publish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | scope=@td-vantage 3 | tag=latest 4 | 5 | [[ $1 = 'next' ]] && tag=next || tag=latest 6 | 7 | #login into private registry 8 | npm login --scope=$scope 9 | 10 | for package in ./deploy/* 11 | do 12 | if [ -d ${package} ] 13 | then 14 | npm publish ${package} --access=public --tag=$tag 15 | fi 16 | done 17 | 18 | #logout when finished 19 | npm logout 20 | echo "Published successfully [scope: $scope]. Use 'npm install [package-name]' in the project you want to use it." 21 | -------------------------------------------------------------------------------- /scripts/start-release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | version=$1 3 | 4 | set -e 5 | 6 | echo "Started release v$version" 7 | 8 | echo "Making sure master is up to date" 9 | git checkout master 10 | 11 | git pull origin master 12 | 13 | echo "Checking out develop branch" 14 | git checkout develop 15 | 16 | echo "Execute tslint test" 17 | npm run tslint 18 | 19 | echo "Execute stylelint test" 20 | npm run stylelint 21 | 22 | echo "Execute unit tests" 23 | npm run test 24 | 25 | echo "Execute release build test" 26 | npm run build:lib 27 | rm -rf deploy 28 | 29 | echo "Bump to version v$version" 30 | gulp bump-version --ver $version 31 | 32 | echo "Generate changelog" 33 | npm run generate:changelog -------------------------------------------------------------------------------- /scripts/version-placeholders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var platform = require('os').platform; 4 | var readFileSync = require('fs').readFileSync; 5 | var writeFileSync = require('fs').writeFileSync; 6 | var spawnSync = require('child_process').spawnSync; 7 | var gulp = require('gulp'); 8 | const buildConfig = require('../build.conf'); 9 | const packageJson = require('../package.json'); 10 | 11 | gulp.task('version-placeholder', function(cb) { 12 | replaceVersionPlaceholders(buildConfig.deployed, packageJson.version); 13 | cb(); 14 | }); 15 | 16 | /** Variable that is set to the string for version placeholders. */ 17 | const versionPlaceholderText = '0.0.0-PLATFORM'; 18 | const covalentVersionPlaceholderText = '0.0.0-COVALENT'; 19 | const ngVersionPlaceholderText = '0.0.0-NG'; 20 | const materialVersionPlaceholderText = '0.0.0-MATERIAL'; 21 | const translateVersionPlaceholderText = '0.0.0-TRANSLATE'; 22 | 23 | /** RegExp that matches version placeholders inside of a file. */ 24 | const versionPlaceholderRegex = new RegExp(versionPlaceholderText, 'g'); 25 | const covalentVersionPlaceholderRegex = new RegExp(covalentVersionPlaceholderText, 'g'); 26 | const ngVersionPlaceholderRegex = new RegExp(ngVersionPlaceholderText, 'g'); 27 | const materialVersionPlaceholderRegex = new RegExp(materialVersionPlaceholderText, 'g'); 28 | const translateVersionPlaceholderRegex = new RegExp(translateVersionPlaceholderText, 'g'); 29 | 30 | /** 31 | * Walks through every file in a directory and replaces the version placeholders 32 | */ 33 | function replaceVersionPlaceholders(packageDir, projectVersion) { 34 | // Resolve files that contain version placeholders using Grep or Findstr since those are 35 | // extremely fast and also have a very simple usage. 36 | const files = findFilesWithPlaceholders(packageDir); 37 | 38 | // Walk through every file that contains version placeholders and replace those with the current 39 | // version of the root package.json file. 40 | files.forEach((filePath) => { 41 | const fileContent = readFileSync(filePath, 'utf-8') 42 | .replace(ngVersionPlaceholderRegex, buildConfig.angularVersion) 43 | .replace(materialVersionPlaceholderRegex, buildConfig.materialVersion) 44 | .replace(covalentVersionPlaceholderRegex, buildConfig.covalentVersion) 45 | .replace(translateVersionPlaceholderRegex, buildConfig.translateVersion) 46 | .replace(versionPlaceholderRegex, projectVersion); 47 | 48 | writeFileSync(filePath, fileContent); 49 | }); 50 | } 51 | 52 | /** Finds all files in the specified package dir where version placeholders are included. */ 53 | function findFilesWithPlaceholders(packageDir) { 54 | const findCommand = buildPlaceholderFindCommand(packageDir); 55 | return spawnSync(findCommand.binary, findCommand.args) 56 | .stdout.toString() 57 | .split(/[\n\r]/) 58 | .filter(String); 59 | } 60 | 61 | /** Builds the command that will be executed to find all files containing version placeholders. */ 62 | function buildPlaceholderFindCommand(packageDir) { 63 | if (platform() === 'win32') { 64 | return { 65 | binary: 'findstr', 66 | args: [ 67 | '/msi', 68 | `${translateVersionPlaceholderText} ${materialVersionPlaceholderText} ${ngVersionPlaceholderText} ${versionPlaceholderText} ${covalentVersionPlaceholderText}`, 69 | `${packageDir}\\*`, 70 | ], 71 | }; 72 | } else { 73 | return { 74 | binary: 'grep', 75 | args: [ 76 | '-ril', 77 | `${translateVersionPlaceholderText}\\|${materialVersionPlaceholderText}\\|${ngVersionPlaceholderText}\\|${versionPlaceholderText} ${covalentVersionPlaceholderText}`, 78 | packageDir, 79 | ], 80 | }; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "APP_TITLE": "Kitchen Sync", 3 | "THERE_WAS_A_PROBLEM": "There was a problem", 4 | "CLOSE": "Close", 5 | "SPOOLED_QUERY_COULD_NOT_BE_DELETED": "Spooled query could not be deleted", 6 | "APP_SWITCHER": { 7 | "HEADER": "Vantage applications", 8 | "OTHER_PRODUCTS": "Other products", 9 | "EXPLORE_MORE": "Explore more products" 10 | }, 11 | "USER_PROFILE": { 12 | "TOOLTIP": "Account", 13 | "DARK_MODE": "Dark mode", 14 | "LIGHT_MODE": "Light mode", 15 | "SIGN_OUT": "Sign out" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/docs-ui/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 12 | 13 | 14 | 15 | 16 | GITHUB 17 | 18 |
19 | 20 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /src/docs-ui/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/docs-ui/app/app.component.scss -------------------------------------------------------------------------------- /src/docs-ui/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { DomSanitizer } from '@angular/platform-browser'; 3 | import { MatIconRegistry } from '@angular/material/icon'; 4 | import { IVantageAppSwitcherItem } from '@td-vantage/ui-platform/app-switcher'; 5 | import { VantageThemeService, VantageTheme } from '../../lib/theme/theme.service'; 6 | 7 | @Component({ 8 | selector: 'td-app', 9 | templateUrl: './app.component.html', 10 | styleUrls: ['./app.component.scss'], 11 | }) 12 | export class AppComponent { 13 | products: IVantageAppSwitcherItem[] = [ 14 | { 15 | text: 'Vantage Launcher', 16 | href: 'https://www.teradata.com', 17 | svgIcon: 'td-logo:logo-mark', 18 | divider: true, 19 | }, 20 | { 21 | text: 'Editor', 22 | href: 'https://www.teradata.com', 23 | icon: 'settings', 24 | }, 25 | { 26 | text: 'Analyst', 27 | href: 'https://www.teradata.com', 28 | icon: 'settings', 29 | }, 30 | { 31 | text: 'App Center', 32 | href: 'https://www.teradata.com', 33 | newTab: false, 34 | }, 35 | 36 | { 37 | text: 'Console', 38 | href: 'https://www.teradata.com', 39 | icon: 'settings', 40 | newTab: true, 41 | }, 42 | ]; 43 | 44 | otherProducts: IVantageAppSwitcherItem[] = [ 45 | { 46 | text: 'Jupyter', 47 | href: 'https://www.teradata.com', 48 | icon: 'settings', 49 | newTab: true, 50 | }, 51 | { 52 | text: 'Something else', 53 | href: 'https://www.teradata.com', 54 | icon: 'settings', 55 | }, 56 | { 57 | text: 'Another thing', 58 | href: 'https://www.teradata.com', 59 | icon: 'settings', 60 | newTab: false, 61 | }, 62 | ]; 63 | 64 | exploreMoreLink: string = 'https://www.teradata.com/products'; 65 | 66 | constructor( 67 | private _iconRegistry: MatIconRegistry, 68 | private _domSanitizer: DomSanitizer, 69 | public _themeService: VantageThemeService, 70 | ) { 71 | // Register Covalent Icons 72 | this._iconRegistry.registerFontClassAlias('covalent', 'covalent-icons'); 73 | 74 | // Register Teradata icons 75 | this._iconRegistry.addSvgIconSetInNamespace( 76 | 'td-icons', 77 | this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/teradata-icons.svg'), 78 | ); 79 | 80 | // Register Teradata icons 81 | this._iconRegistry.addSvgIconSetInNamespace( 82 | 'td-logo', 83 | this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/teradata-logo.svg'), 84 | ); 85 | } 86 | 87 | toggleTheme($event: Event): void { 88 | this._themeService.toggleTheme(); 89 | } 90 | 91 | _blockEvent(event: Event): void { 92 | event.preventDefault(); 93 | event.stopPropagation(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/docs-ui/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes, RouterModule } from '@angular/router'; 2 | 3 | import { MainComponent } from './main/main.component'; 4 | 5 | import { VantageAuthenticationGuard } from '@td-vantage/ui-platform/auth'; 6 | import { VantageBlockRootAccessGuard, VantageBlockUserAccessGuard } from '@td-vantage/ui-platform/access'; 7 | import { TypographyComponent } from './typography/typography.component'; 8 | import { MatComponentsComponent } from './mat-components/mat-components.component'; 9 | import { DemosComponent } from './demos/demos.component'; 10 | import { CovalentComponentsComponent } from './covalent-components/covalent-components.component'; 11 | import { IconsDemoComponent } from './icons-demo/icons-demo.component'; 12 | 13 | const routes: Routes = [ 14 | { 15 | path: '', 16 | component: MainComponent, 17 | children: [ 18 | { path: '', redirectTo: 'mat-components', pathMatch: 'full' }, 19 | { path: 'demos', component: DemosComponent }, 20 | { path: 'mat-components', component: MatComponentsComponent }, 21 | { path: 'typography', component: TypographyComponent }, 22 | { path: 'icons', component: IconsDemoComponent }, 23 | { path: 'covalent-components', component: CovalentComponentsComponent }, 24 | ], 25 | }, 26 | { path: 'login', component: MainComponent, canActivate: [VantageAuthenticationGuard] }, 27 | { path: 'block-root', component: MainComponent, canActivate: [VantageBlockRootAccessGuard] }, 28 | { path: 'block-user', component: MainComponent, canActivate: [VantageBlockUserAccessGuard] }, 29 | { path: '**', redirectTo: '/' }, 30 | ]; 31 | 32 | export const appRoutingProviders: any[] = []; 33 | 34 | export const appRoutes: any = RouterModule.forRoot(routes); 35 | -------------------------------------------------------------------------------- /src/docs-ui/app/covalent-components/covalent-components.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | Home 5 | 6 | Breadcrumb 1 7 | 8 | 9 | Breadcrumb 2 10 | 11 | Manage List 12 | 13 |
14 | 15 |
16 |
17 | -------------------------------------------------------------------------------- /src/docs-ui/app/covalent-components/covalent-components.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/docs-ui/app/covalent-components/covalent-components.component.scss -------------------------------------------------------------------------------- /src/docs-ui/app/covalent-components/covalent-components.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-covalent-components', 5 | templateUrl: './covalent-components.component.html', 6 | styleUrls: ['./covalent-components.component.scss'], 7 | }) 8 | export class CovalentComponentsComponent {} 9 | -------------------------------------------------------------------------------- /src/docs-ui/app/demos/demos.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Theme Service

3 |
Active theme: {{ _themeService.activeTheme$ | async }}
4 |
Dark theme is active: {{ _themeService.darkTheme$ | async }}
5 |
Light theme is active: {{ _themeService.lightTheme$ | async }}
6 |
7 | Theme map: {{ _themeService.map({ 'dark-theme': 'hacker vibes 👩‍💻', 'light-theme': 'miami vibes 🏖️' }) | async }} 8 |
9 |
10 | 11 |
12 |

SQLE Module

13 |

Credentials Dialog

14 |

Note: Navigate to `/login` to trigger the auth flow

15 |
16 | 17 | Basic Auth 18 | 19 |
20 | 23 |

Current connection:

24 |

{{ connectionService.currentConnection$ | async | json }}

25 |

Connections:

26 |

{{ connectionService.connections$ | async | json }}

27 | 34 |
35 | 36 |
37 |

Assets Module

38 |

Help JSON

39 | 42 |

Help Contents:

43 | 44 |
45 | 46 |
47 |

Utilities Module

48 |

Error Dialog

49 | 52 | 55 |
56 | -------------------------------------------------------------------------------- /src/docs-ui/app/demos/demos.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/docs-ui/app/demos/demos.component.scss -------------------------------------------------------------------------------- /src/docs-ui/app/demos/demos.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { MatDialog, MatDialogRef } from '@angular/material/dialog'; 3 | import { VantageThemeService } from '@td-vantage/ui-platform/theme'; 4 | import { VantageCredentialsDialogComponent, VantageConnectionService } from '@td-vantage/ui-platform/sqle'; 5 | import { VantageErrorService } from '@td-vantage/ui-platform/utilities'; 6 | import { Subject } from 'rxjs'; 7 | import { takeUntil } from 'rxjs/operators'; 8 | import { VantageAssetsService, IHelpAssets } from '@td-vantage/ui-platform/assets'; 9 | 10 | @Component({ 11 | selector: 'app-demos', 12 | templateUrl: './demos.component.html', 13 | styleUrls: ['./demos.component.scss'], 14 | }) 15 | export class DemosComponent implements OnInit, OnDestroy { 16 | private unsubscribe: Subject = new Subject(); 17 | 18 | helpJSON: IHelpAssets; 19 | 20 | constructor( 21 | public _themeService: VantageThemeService, 22 | private _dialog: MatDialog, 23 | private _errorService: VantageErrorService, 24 | public connectionService: VantageConnectionService, 25 | public assetsService: VantageAssetsService, 26 | ) {} 27 | 28 | ngOnInit(): void { 29 | // tslint:disable:no-console 30 | this._themeService 31 | .map({ 'dark-theme': 'dark-logo', 'light-theme': 'light-logo' }) 32 | .pipe(takeUntil(this.unsubscribe)) 33 | .subscribe(console.log); 34 | this._themeService 35 | .map({ 'dark-theme': 'vision', 'light-theme': 2020 }) 36 | .pipe(takeUntil(this.unsubscribe)) 37 | .subscribe(console.log); 38 | this._themeService 39 | .map({ 'dark-theme': 'dark-logo' }, 'fallback') 40 | .pipe(takeUntil(this.unsubscribe)) 41 | .subscribe(console.log); 42 | this._themeService.darkTheme$.pipe(takeUntil(this.unsubscribe)).subscribe(console.log); 43 | this._themeService.lightTheme$.pipe(takeUntil(this.unsubscribe)).subscribe(console.log); 44 | this._themeService.activeTheme$.pipe(takeUntil(this.unsubscribe)).subscribe(console.log); 45 | // tslint:enable:no-console 46 | } 47 | 48 | ngOnDestroy(): void { 49 | this.unsubscribe.next(); 50 | this.unsubscribe.complete(); 51 | } 52 | 53 | connect(basicAuthEnabled: boolean = false): void { 54 | const dialog: MatDialogRef = this._dialog.open( 55 | VantageCredentialsDialogComponent, 56 | { 57 | width: '500px', 58 | }, 59 | ); 60 | dialog.componentInstance.basicAuthEnabled = basicAuthEnabled; 61 | } 62 | 63 | openErrorDialog(error?: number): void { 64 | this._errorService.open({ 65 | message: 'This is an error dialog', 66 | error, 67 | }); 68 | } 69 | 70 | getHelpJSON(): void { 71 | this.assetsService.getHelpJSON().subscribe((helpJSON: IHelpAssets) => { 72 | this.helpJSON = helpJSON; 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/docs-ui/app/icons-demo/icons-demo.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 9 | 10 |
11 |

Teradata icons

12 | 13 |
14 | 15 |
16 | 17 |
{{ icon }}
18 |
19 |
20 |
21 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /src/docs-ui/app/icons-demo/icons-demo.component.scss: -------------------------------------------------------------------------------- 1 | .example-logo .mat-icon { 2 | margin-right: 16px; 3 | margin-bottom: 16px; 4 | } 5 | -------------------------------------------------------------------------------- /src/docs-ui/app/icons-demo/icons-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { TdIcon, TD_ICONS } from '../../../lib/theme/utilities/icons'; 3 | 4 | @Component({ 5 | selector: 'app-icons-demo', 6 | templateUrl: './icons-demo.component.html', 7 | styleUrls: ['./icons-demo.component.scss'], 8 | }) 9 | export class IconsDemoComponent { 10 | icons: TdIcon[] = TD_ICONS; 11 | } 12 | -------------------------------------------------------------------------------- /src/docs-ui/app/index.ts: -------------------------------------------------------------------------------- 1 | export { AppModule } from './app.module'; 2 | -------------------------------------------------------------------------------- /src/docs-ui/app/main/main.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | Second toolbar row 4 |
5 | 6 |
7 |
8 |
9 | 14 | Dark mode 15 | 16 | 17 | 29 |
30 | 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /src/docs-ui/app/main/main.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/docs-ui/app/main/main.component.scss -------------------------------------------------------------------------------- /src/docs-ui/app/main/main.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { MatDialog } from '@angular/material/dialog'; 3 | import { MatSnackBar } from '@angular/material/snack-bar'; 4 | import { VantageThemeService } from '@td-vantage/ui-platform/theme'; 5 | 6 | @Component({ 7 | selector: 'td-main', 8 | templateUrl: './main.component.html', 9 | styleUrls: ['./main.component.scss'], 10 | }) 11 | export class MainComponent { 12 | navLinks: any = [ 13 | { 14 | name: 'Material Components', 15 | route: '/mat-components', 16 | }, 17 | { 18 | name: 'Typography', 19 | route: '/typography', 20 | }, 21 | { 22 | name: 'Teradata Icons', 23 | route: '/icons', 24 | }, 25 | { 26 | name: 'Demos', 27 | route: '/demos', 28 | }, 29 | { 30 | name: 'Covalent', 31 | route: '/covalent-components', 32 | }, 33 | ]; 34 | 35 | constructor(private _dialog: MatDialog, private _snackbar: MatSnackBar, public _themeService: VantageThemeService) {} 36 | } 37 | -------------------------------------------------------------------------------- /src/docs-ui/app/mat-components/mat-components.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/docs-ui/app/mat-components/mat-components.component.scss -------------------------------------------------------------------------------- /src/docs-ui/app/mat-components/mat-components.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { MatDialog, MatDialogRef } from '@angular/material/dialog'; 3 | import { MatSnackBar } from '@angular/material/snack-bar'; 4 | 5 | @Component({ 6 | selector: 'app-mat-components', 7 | templateUrl: './mat-components.component.html', 8 | styleUrls: ['./mat-components.component.scss'], 9 | }) 10 | export class MatComponentsComponent { 11 | lastDialogResult: string; 12 | mode: string; 13 | value: number; 14 | 15 | foods: any[] = [ 16 | { name: 'Pizza', rating: 'Excellent' }, 17 | { name: 'Burritos', rating: 'Great' }, 18 | { name: 'French fries', rating: 'Pretty good' }, 19 | ]; 20 | 21 | public selectedValue: string; 22 | 23 | public games: any[] = [ 24 | { value: 'rts-0', viewValue: 'Starcraft' }, 25 | { value: 'rpg-1', viewValue: "Baldur's Gate" }, 26 | { value: 'fps-2', viewValue: 'Doom' }, 27 | ]; 28 | 29 | public progress: number = 0; 30 | public slider: any = { 31 | autoTicks: false, 32 | disabled: false, 33 | invert: false, 34 | max: 100, 35 | min: 0, 36 | showTicks: false, 37 | step: 1, 38 | thumbLabel: false, 39 | value: 0, 40 | vertical: false, 41 | tickInterval: 1, 42 | checked: true, 43 | }; 44 | public tiles: any = [ 45 | { text: 'One', cols: 3, rows: 1, color: 'lightblue' }, 46 | { text: 'Two', cols: 1, rows: 2, color: 'lightgreen' }, 47 | { text: 'Three', cols: 1, rows: 1, color: 'lightpink' }, 48 | { text: 'Four', cols: 2, rows: 1, color: '#DDBDF1' }, 49 | ]; 50 | 51 | public color: string; 52 | 53 | public availableColors: any[] = [ 54 | { name: 'none', color: '' }, 55 | { name: 'Primary', color: 'primary' }, 56 | { name: 'Accent', color: 'accent' }, 57 | { name: 'Warn', color: 'warn' }, 58 | ]; 59 | 60 | constructor(private _dialog: MatDialog, private _snackbar: MatSnackBar) { 61 | // Update the value for the progress-bar on an interval. 62 | setInterval(() => { 63 | this.progress = (this.progress + Math.floor(Math.random() * 4) + 1) % 100; 64 | }, 200); 65 | } 66 | 67 | openDialog(): void { 68 | const dialogRef: any = this._dialog.open(DialogContentComponent); 69 | 70 | dialogRef.afterClosed().subscribe((result: any) => { 71 | this.lastDialogResult = result; 72 | }); 73 | } 74 | 75 | showSnackbar(): void { 76 | this._snackbar.open('YUM SNACKS', 'CHEW'); 77 | } 78 | get tickInterval(): number | 'auto' { 79 | return this.slider.showTicks ? (this.slider.autoTicks ? 'auto' : this.slider.tickInterval) : undefined; 80 | } 81 | set tickInterval(v: number | 'auto') { 82 | this.slider.tickInterval = Number(v); 83 | } 84 | } 85 | 86 | @Component({ 87 | template: ` 88 |

This is a dialog

89 |
90 | 91 | 95 | 96 |
97 |
98 | 99 |
100 | `, 101 | }) 102 | export class DialogContentComponent { 103 | constructor(public dialogRef: MatDialogRef) {} 104 | } 105 | -------------------------------------------------------------------------------- /src/docs-ui/app/typography/typography.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Display-4
4 |
Display-3
5 |
Display-2
6 |
Display-1
7 |
Headline
8 |
Title
9 |
10 |
11 |
Subheading-2
12 |
Subheading-1
13 |

Body-2

14 |

Body-1

15 |

Caption

16 |

Overline

17 | 18 | 19 | 20 |   21 | 22 |
23 |
24 |
25 |
26 |

Long Form Content - Small Scale

27 | 28 | 29 | 30 |
31 |
32 | -------------------------------------------------------------------------------- /src/docs-ui/app/typography/typography.component.scss: -------------------------------------------------------------------------------- 1 | .types { 2 | display: grid; 3 | grid-template-areas: 'left right'; 4 | 5 | .headers { 6 | grid-area: left; 7 | } 8 | 9 | .bodies { 10 | grid-area: right; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/docs-ui/app/typography/typography.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { IMarkdownNavigatorItem } from '@covalent/markdown-navigator'; 3 | @Component({ 4 | selector: 'app-typography', 5 | templateUrl: './typography.component.html', 6 | styleUrls: ['./typography.component.scss'], 7 | }) 8 | export class TypographyComponent { 9 | items: IMarkdownNavigatorItem[] = [ 10 | { 11 | title: 'Covalent', 12 | description: 'Terdata UI Platform', 13 | icon: 'whatshot', 14 | url: 'https://raw.githubusercontent.com/ngx-translate/core/master/README.md', 15 | }, 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /src/docs-ui/config/translate.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | 3 | import { TranslateService, TranslateLoader } from '@ngx-translate/core'; 4 | import { TranslateHttpLoader } from '@ngx-translate/http-loader'; 5 | 6 | export const TRANSLATE_STORAGE_KEY: string = 'ngx-translate-lang'; 7 | export const SUPPORTED_LANGS: string[] = ['en']; 8 | /** 9 | * Utility method to get selected language from sessionStorage or browser 10 | */ 11 | export function getSelectedLanguage(translateService: TranslateService): string { 12 | const storedLanguage: string = sessionStorage.getItem(TRANSLATE_STORAGE_KEY); 13 | // Check if the language has been stored else if the language wasnt stored, then use browser default if supported 14 | if (storedLanguage && translateService.getLangs().indexOf(storedLanguage) > -1) { 15 | return storedLanguage; 16 | } else if (translateService.getLangs().indexOf(translateService.getBrowserLang()) > -1) { 17 | return translateService.getBrowserLang(); 18 | } 19 | // If everything fails, then use default lang 20 | return translateService.getDefaultLang(); 21 | } 22 | 23 | export function getSelectedLocale(translateService: TranslateService): string { 24 | return translateService.getBrowserCultureLang(); 25 | } 26 | 27 | /** 28 | * Create custom TranslateLoader since we have a diff dir structure for our json files 29 | */ 30 | export function createTranslateLoader(httpClient: HttpClient): TranslateLoader { 31 | return new TranslateHttpLoader(httpClient, 'assets/i18n/', '.json'); 32 | } 33 | -------------------------------------------------------------------------------- /src/docs-ui/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment: { production: boolean } = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /src/docs-ui/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment: { production: boolean } = { 7 | production: false, 8 | }; 9 | -------------------------------------------------------------------------------- /src/docs-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vantage UI Platform 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/docs-ui/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { environment } from './environments/environment'; 4 | import { AppModule } from './app/'; 5 | 6 | if (environment.production) { 7 | enableProdMode(); 8 | } 9 | 10 | platformBrowserDynamic().bootstrapModule(AppModule); 11 | -------------------------------------------------------------------------------- /src/docs-ui/styles.scss: -------------------------------------------------------------------------------- 1 | .light-theme .mat-drawer-container { 2 | background-color: white; 3 | } 4 | 5 | .app-content { 6 | padding: 5px; 7 | } 8 | 9 | .app-content mat-card { 10 | margin: 5px; 11 | } 12 | 13 | .app-sidenav { 14 | min-width: 200px; 15 | } 16 | 17 | .app-content mat-checkbox { 18 | margin: 10px; 19 | } 20 | 21 | .app-toolbar-filler { 22 | flex: 1 1 auto; 23 | } 24 | 25 | .app-fab { 26 | position: fixed !important; 27 | bottom: 20px; 28 | right: 20px; 29 | } 30 | 31 | .app-spinner { 32 | height: 30px; 33 | width: 30px; 34 | display: inline-block; 35 | } 36 | 37 | .app-input-icon { 38 | font-size: 16px; 39 | padding: 0 5px; 40 | } 41 | 42 | .app-menu-button { 43 | padding: 0; 44 | min-width: 50px; 45 | } 46 | .app-button { 47 | margin: 5px; 48 | } 49 | 50 | .app-list { 51 | border: 1px solid rgba(0, 0, 0, 0.12); 52 | } 53 | 54 | .app-progress { 55 | margin: 5px; 56 | } 57 | 58 | .example-section { 59 | display: flex; 60 | align-content: center; 61 | align-items: center; 62 | flex-wrap: wrap; 63 | } 64 | 65 | .example-margin { 66 | margin: 10px; 67 | } 68 | 69 | .mat-slider-horizontal { 70 | width: 300px; 71 | } 72 | 73 | .mat-slider-vertical { 74 | height: 300px; 75 | } 76 | 77 | mat-chip { 78 | max-width: 200px; 79 | } 80 | 81 | .app-sidebar-button { 82 | width: inherit; 83 | } 84 | 85 | .example-spacer { 86 | flex: 1 1 auto; 87 | } 88 | 89 | .example-h4 { 90 | letter-spacing: 1px; 91 | font-weight: 200; 92 | font-size: 14px; 93 | } 94 | 95 | .example-card { 96 | max-width: 400px; 97 | } 98 | 99 | .example-header-image { 100 | background-image: url('https://material.angular.io/assets/img/examples/shiba1.jpg'); 101 | background-size: cover; 102 | } 103 | -------------------------------------------------------------------------------- /src/docs-ui/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | 7 | declare const require: any; 8 | 9 | // First, initialize the Angular testing environment. 10 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 11 | // Then we find all the tests. 12 | const context: any = require.context('./', true, /\.spec\.ts$/); 13 | // And load the modules. 14 | context.keys().map(context); 15 | -------------------------------------------------------------------------------- /src/docs-ui/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "../../out-tsc/app", 6 | "types": ["hammerjs"], 7 | "paths": { 8 | "@td-vantage/ui-platform": ["../lib"], 9 | "@td-vantage/ui-platform/*": ["../lib/*"] 10 | } 11 | }, 12 | "files": ["../polyfills.ts", "../typings.d.ts", "main.ts"], 13 | "exclude": ["test.ts", "**/*.spec.*"] 14 | } 15 | -------------------------------------------------------------------------------- /src/docs-ui/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "../../out-tsc/spec", 6 | "lib": ["es6", "dom"], 7 | "module": "commonjs", 8 | "types": ["jasmine", "hammerjs", "node"] 9 | }, 10 | "include": ["../polyfills.ts", "test.ts", "**/*.spec.*"] 11 | } 12 | -------------------------------------------------------------------------------- /src/lib/_theming.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * All theme 3 | */ 4 | @import './theme/all-theme'; 5 | -------------------------------------------------------------------------------- /src/lib/access/access.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VantageBlockRootAccessGuard } from './guards/block-root-access.guard'; 5 | import { VantageBlockUserAccessGuard } from './guards/block-user-access.guard'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule], 9 | providers: [VantageBlockRootAccessGuard, VantageBlockUserAccessGuard], 10 | }) 11 | export class VantageAccessModule {} 12 | -------------------------------------------------------------------------------- /src/lib/access/guards/block-root-access.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 3 | import { Observable, of } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | import { VantageSessionService, VantageAuthenticationGuard } from '@td-vantage/ui-platform/auth'; 7 | 8 | /** 9 | * Guard that checks if the user is root (`admin` flag `true`) 10 | * to block access into a particular route. 11 | * If `admin` flag is `true`, then we redirect to `/` 12 | */ 13 | @Injectable() 14 | export class VantageBlockRootAccessGuard implements CanActivate { 15 | constructor(private _authGuard: VantageAuthenticationGuard, private _sessionService: VantageSessionService) {} 16 | 17 | canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { 18 | // pipe through the VantageAuthentication guard to be able to chain guards 19 | return this._authGuard.canActivate(next, state).pipe( 20 | map(() => { 21 | if (this._sessionService.user.admin) { 22 | location.replace('/'); 23 | return false; 24 | } 25 | return true; 26 | }), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/lib/access/guards/block-user-access.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 3 | import { Observable, of } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | import { VantageSessionService, VantageAuthenticationGuard } from '@td-vantage/ui-platform/auth'; 7 | 8 | /** 9 | * Guard that checks if the user is a normal user (`admin` flag `false`) 10 | * to block access into a particular route. 11 | * If `admin` flag is `false`, then we redirect to `/` 12 | */ 13 | @Injectable() 14 | export class VantageBlockUserAccessGuard implements CanActivate { 15 | constructor(private _authGuard: VantageAuthenticationGuard, private _sessionService: VantageSessionService) {} 16 | 17 | canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { 18 | // pipe through the VantageAuthentication guard to be able to chain guards 19 | return this._authGuard.canActivate(next, state).pipe( 20 | map(() => { 21 | if (!this._sessionService.user.admin) { 22 | location.replace('/'); 23 | return false; 24 | } 25 | return true; 26 | }), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/lib/access/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/access/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/access/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './guards/block-root-access.guard'; 2 | export * from './guards/block-user-access.guard'; 3 | export * from './access.module'; 4 | -------------------------------------------------------------------------------- /src/lib/app-switcher/_app-switcher-theme.scss: -------------------------------------------------------------------------------- 1 | @mixin vui-app-switcher-theme($theme, $config: null) { 2 | @include vantage-app-switcher-typography($config); 3 | @include vantage-app-switcher-theme($theme); 4 | } 5 | 6 | @mixin vantage-app-switcher-typography($config: null) { 7 | @if $fontConfig == null { 8 | $fontConfig: td-typography-config(); 9 | } 10 | 11 | vui-app-switcher-menu { 12 | .other-products-header { 13 | @include mat-typography-level-to-styles($fontConfig, caption); 14 | } 15 | } 16 | } 17 | 18 | @mixin vantage-app-switcher-theme($theme) { 19 | $foreground: map-get($theme, foreground); 20 | $text: map-get($foreground, text); 21 | $secondary-text: map-get($foreground, secondary-text); 22 | 23 | .app-switcher-header-title { 24 | color: $text; 25 | } 26 | .other-products-header { 27 | color: $secondary-text; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher-menu/app-switcher-menu.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
{{ 'APP_SWITCHER.HEADER' | translate }}
6 |
7 | 8 | 9 | 10 | 17 | 23 | 24 | {{ product.icon || 'apps' }} 25 | 26 | {{ product.text }} 27 | launch 28 | 29 | 30 | 36 | 37 | {{ product.icon || 'apps' }} 38 | 39 | {{ product.text }} 40 | 41 | 42 | 43 | 44 | 45 | 54 | 60 | 61 | {{ 'APP_SWITCHER.OTHER_PRODUCTS' | translate }} 62 | 63 | 64 | 65 | 66 | 73 | {{ other.text }} 74 | launch 75 | 76 | 77 | {{ other.text }} 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | {{ 'APP_SWITCHER.EXPLORE_MORE' | translate }} 86 | 87 | 88 |
89 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher-menu/app-switcher-menu.component.scss: -------------------------------------------------------------------------------- 1 | .app-switcher-menu { 2 | min-width: 256px; 3 | 4 | .app-switcher-header[td-menu-header] { 5 | padding: 24px 0; 6 | .mat-icon[svgicon='td-logo:logo-wordmark'] { 7 | height: 24px; 8 | width: auto; 9 | margin-bottom: 12px; 10 | } 11 | } 12 | .app-switcher-list-item { 13 | .mat-icon::ng-deep > svg { 14 | height: 40px; 15 | width: 40px; 16 | } 17 | } 18 | 19 | .other-products { 20 | box-shadow: none; 21 | margin: 8px 0; 22 | 23 | .other-products-header { 24 | padding: 0 16px; 25 | } 26 | 27 | ::ng-deep .mat-expansion-panel-body { 28 | padding: 0; 29 | } 30 | } 31 | 32 | .new-tab { 33 | ::ng-deep .mat-list-item-content { 34 | padding-right: 12px; 35 | } 36 | } 37 | 38 | .explore-more { 39 | margin: 6px 8px; 40 | } 41 | ::ng-deep .td-menu-content + .mat-divider { 42 | display: none; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher-menu/app-switcher-menu.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { HttpClientTestingModule } from '@angular/common/http/testing'; 3 | import { DomSanitizer } from '@angular/platform-browser'; 4 | import { MatDividerModule } from '@angular/material/divider'; 5 | import { MatMenuModule } from '@angular/material/menu'; 6 | import { MatIconModule, MatIconRegistry } from '@angular/material/icon'; 7 | import { MatButtonModule } from '@angular/material/button'; 8 | import { TranslateModule } from '@ngx-translate/core'; 9 | import { MatListModule } from '@angular/material/list'; 10 | import { CovalentMenuModule } from '@covalent/core/menu'; 11 | 12 | import { VantageThemeModule } from '../../theme/theme.module'; 13 | 14 | import { VantageAppSwitcherMenuComponent } from './app-switcher-menu.component'; 15 | 16 | describe('VantageAppSwitcherMenuComponent', () => { 17 | let component: VantageAppSwitcherMenuComponent; 18 | let fixture: ComponentFixture; 19 | 20 | beforeEach(async(() => { 21 | TestBed.configureTestingModule({ 22 | declarations: [VantageAppSwitcherMenuComponent], 23 | imports: [ 24 | HttpClientTestingModule, 25 | MatMenuModule, 26 | MatIconModule, 27 | MatButtonModule, 28 | MatDividerModule, 29 | MatListModule, 30 | CovalentMenuModule, 31 | TranslateModule.forRoot(), 32 | VantageThemeModule, 33 | ], 34 | }).compileComponents(); 35 | })); 36 | 37 | beforeEach(() => { 38 | const iconRegistry: MatIconRegistry = TestBed.inject(MatIconRegistry); 39 | const domSanitizer: DomSanitizer = TestBed.inject(DomSanitizer); 40 | 41 | // Register Teradata icons 42 | iconRegistry.addSvgIconSetInNamespace( 43 | 'td-logo', 44 | domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/teradata-logo.svg'), 45 | ); 46 | 47 | fixture = TestBed.createComponent(VantageAppSwitcherMenuComponent); 48 | component = fixture.componentInstance; 49 | fixture.detectChanges(); 50 | }); 51 | 52 | it('should create', () => { 53 | expect(component).toBeTruthy(); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher-menu/app-switcher-menu.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Input, ElementRef, ViewChild } from '@angular/core'; 2 | 3 | import { MatExpansionPanel } from '@angular/material/expansion'; 4 | 5 | import { IVantageAppSwitcherItem } from '../services/products.service'; 6 | 7 | @Component({ 8 | selector: 'vui-app-switcher-menu', 9 | templateUrl: './app-switcher-menu.component.html', 10 | styleUrls: ['./app-switcher-menu.component.scss'], 11 | changeDetection: ChangeDetectionStrategy.OnPush, 12 | }) 13 | export class VantageAppSwitcherMenuComponent { 14 | @Input() products: IVantageAppSwitcherItem[]; 15 | @Input() otherProducts: IVantageAppSwitcherItem[]; 16 | @Input() exploreMoreLink: string; 17 | 18 | @ViewChild('expansionPanel') expansionPanel: MatExpansionPanel; 19 | 20 | constructor(private elRef: ElementRef) {} 21 | 22 | _blockEvent(event: Event): void { 23 | event.preventDefault(); 24 | event.stopPropagation(); 25 | } 26 | 27 | scrollToBottom(): void { 28 | setTimeout(() => { 29 | const elem: HTMLElement = this.elRef.nativeElement.querySelector('.td-menu-content'); 30 | elem.scrollTop = elem.scrollHeight; 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/lib/app-switcher/app-switcher.component.scss -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { HttpClientTestingModule } from '@angular/common/http/testing'; 3 | import { DomSanitizer } from '@angular/platform-browser'; 4 | import { MatDividerModule } from '@angular/material/divider'; 5 | import { MatExpansionModule } from '@angular/material/expansion'; 6 | import { MatMenuModule } from '@angular/material/menu'; 7 | import { MatIconModule, MatIconRegistry } from '@angular/material/icon'; 8 | import { MatButtonModule } from '@angular/material/button'; 9 | import { MatListModule } from '@angular/material/list'; 10 | import { TranslateModule } from '@ngx-translate/core'; 11 | import { CovalentMenuModule } from '@covalent/core/menu'; 12 | 13 | import { VantageThemeModule } from '../theme/theme.module'; 14 | 15 | import { VantageAppSwitcherComponent } from './app-switcher.component'; 16 | import { VantageAppSwitcherMenuComponent } from './app-switcher-menu/app-switcher-menu.component'; 17 | 18 | describe('VantageAppSwitcherComponent', () => { 19 | let component: VantageAppSwitcherComponent; 20 | let fixture: ComponentFixture; 21 | 22 | beforeEach(async(() => { 23 | TestBed.configureTestingModule({ 24 | declarations: [VantageAppSwitcherComponent, VantageAppSwitcherMenuComponent], 25 | imports: [ 26 | HttpClientTestingModule, 27 | MatMenuModule, 28 | MatIconModule, 29 | MatButtonModule, 30 | MatDividerModule, 31 | MatExpansionModule, 32 | MatListModule, 33 | CovalentMenuModule, 34 | TranslateModule.forRoot(), 35 | VantageThemeModule, 36 | ], 37 | }).compileComponents(); 38 | })); 39 | 40 | beforeEach(() => { 41 | const iconRegistry: MatIconRegistry = TestBed.inject(MatIconRegistry); 42 | const domSanitizer: DomSanitizer = TestBed.inject(DomSanitizer); 43 | 44 | // Register Teradata icons 45 | iconRegistry.addSvgIconSetInNamespace( 46 | 'td-logo', 47 | domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/teradata-logo.svg'), 48 | ); 49 | 50 | fixture = TestBed.createComponent(VantageAppSwitcherComponent); 51 | component = fixture.componentInstance; 52 | fixture.detectChanges(); 53 | }); 54 | 55 | it('should create', () => { 56 | expect(component).toBeTruthy(); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Input, ViewChild, ChangeDetectorRef } from '@angular/core'; 2 | 3 | import { IVantageAppSwitcherItem } from './services/products.service'; 4 | import { VantageAppSwitcherMenuComponent } from './app-switcher-menu/app-switcher-menu.component'; 5 | 6 | @Component({ 7 | selector: 'vui-app-switcher', 8 | templateUrl: './app-switcher.component.html', 9 | styleUrls: ['./app-switcher.component.scss'], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | }) 12 | export class VantageAppSwitcherComponent { 13 | @Input() products: IVantageAppSwitcherItem[]; 14 | @Input() otherProducts: IVantageAppSwitcherItem[]; 15 | @Input() exploreMoreLink: string; 16 | @ViewChild('appSwitcherMenu', { static: true }) appSwitcherMenu: VantageAppSwitcherMenuComponent; 17 | 18 | constructor(private _changeDetectorRef: ChangeDetectorRef) {} 19 | 20 | menuClosed(): void { 21 | this.appSwitcherMenu.expansionPanel.close(); 22 | this._changeDetectorRef.detectChanges(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/lib/app-switcher/app-switcher.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { MatDividerModule } from '@angular/material/divider'; 4 | import { MatMenuModule } from '@angular/material/menu'; 5 | import { MatIconModule } from '@angular/material/icon'; 6 | import { MatButtonModule } from '@angular/material/button'; 7 | import { MatExpansionModule } from '@angular/material/expansion'; 8 | import { MatListModule } from '@angular/material/list'; 9 | 10 | import { CovalentMenuModule } from '@covalent/core/menu'; 11 | 12 | import { TranslateModule } from '@ngx-translate/core'; 13 | 14 | import { VantageThemeModule } from '@td-vantage/ui-platform/theme'; 15 | 16 | import { VantageAppSwitcherMenuComponent } from './app-switcher-menu/app-switcher-menu.component'; 17 | import { VantageAppSwitcherComponent } from './app-switcher.component'; 18 | 19 | @NgModule({ 20 | declarations: [VantageAppSwitcherComponent, VantageAppSwitcherMenuComponent], 21 | imports: [ 22 | CommonModule, 23 | MatMenuModule, 24 | MatIconModule, 25 | MatButtonModule, 26 | MatDividerModule, 27 | MatExpansionModule, 28 | MatListModule, 29 | 30 | /* covalent modules */ 31 | CovalentMenuModule, 32 | 33 | /* third party deps */ 34 | TranslateModule.forChild(), 35 | 36 | /* vantage modules */ 37 | VantageThemeModule, 38 | ], 39 | providers: [], 40 | exports: [VantageAppSwitcherComponent, VantageAppSwitcherMenuComponent], 41 | }) 42 | export class VantageAppSwitcherModule {} 43 | -------------------------------------------------------------------------------- /src/lib/app-switcher/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/app-switcher/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/core/menu": "covalent.core.menu", 7 | "@covalent/http": "covalent.http", 8 | "@ngx-translate/core": "ngx-translate.core" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/lib/app-switcher/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './app-switcher.module'; 2 | export * from './app-switcher.component'; 3 | export * from './app-switcher-menu/app-switcher-menu.component'; 4 | export * from './services/products.service'; 5 | -------------------------------------------------------------------------------- /src/lib/app-switcher/services/products.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Optional, Inject } from '@angular/core'; 2 | import { HttpHeaders } from '@angular/common/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | 6 | import { VANTAGE_BASE_URL_TOKEN } from '@td-vantage/ui-platform/common'; 7 | 8 | export interface IVantageAppSwitcherItem { 9 | id?: string; 10 | text: string; 11 | description?: string; 12 | href: string; 13 | icon?: string; 14 | svgIcon?: string; 15 | iconClasses?: string[]; 16 | divider?: boolean; 17 | newTab?: boolean; 18 | } 19 | 20 | import { mixinHttp, TdGET } from '@covalent/http'; 21 | 22 | @Injectable({ 23 | providedIn: 'root', 24 | }) 25 | export class VantageProductsService extends mixinHttp(class {}, { 26 | baseUrl: '/assets', 27 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 28 | }) { 29 | get basePath(): string { 30 | return this._baseUrlOverride; 31 | } 32 | 33 | constructor(@Optional() @Inject(VANTAGE_BASE_URL_TOKEN) private _baseUrlOverride?: string) { 34 | super(); 35 | } 36 | 37 | @TdGET({ 38 | path: '/products.json', 39 | }) 40 | get(): Observable { 41 | return; 42 | } 43 | 44 | @TdGET({ 45 | path: '/other-products.json', 46 | }) 47 | getOther(): Observable { 48 | return; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/lib/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VANTAGE_APP_PROVIDER } from './app.service'; 5 | import { VANTAGE_TAGS_PROVIDER } from './tags.service'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule], 9 | providers: [VANTAGE_APP_PROVIDER, VANTAGE_TAGS_PROVIDER], 10 | }) 11 | export class VantageAppModule {} 12 | -------------------------------------------------------------------------------- /src/lib/app/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Optional, SkipSelf, Provider, Injectable } from '@angular/core'; 2 | import { HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http'; 3 | 4 | import { 5 | mixinHttp, 6 | TdParam, 7 | TdBody, 8 | TdQueryParams, 9 | TdResponse, 10 | TdGET, 11 | TdPOST, 12 | TdDELETE, 13 | TdPATCH, 14 | } from '@covalent/http'; 15 | 16 | import { Observable } from 'rxjs'; 17 | import { map } from 'rxjs/operators'; 18 | 19 | export enum AppType { 20 | SQL = 'sql', 21 | BTEQ = 'bteq', 22 | CUSTOM = 'custom', 23 | } 24 | 25 | export interface IApp { 26 | app_id?: string; 27 | app_type?: AppType; 28 | app_code?: string; 29 | app_state?: string; 30 | collaborators?: IAppPermissions; 31 | color?: string; 32 | config?: any; 33 | cpus?: number; 34 | description?: string; 35 | dockerImageName?: string; 36 | icon?: string; 37 | install_time?: string; 38 | installed_by?: string; 39 | last_updated_by?: string; 40 | last_updated_time?: string; 41 | memory?: number; 42 | name?: string; 43 | owners?: IAppPermissions; 44 | public?: boolean; 45 | results_config?: any; 46 | versions?: any; 47 | last_version_status?: string; 48 | database?: string; 49 | system_name?: string; 50 | username?: string; 51 | password?: string; 52 | param_name?: string; 53 | ephemeral?: boolean; 54 | can_execute?: boolean; 55 | web_root?: string; 56 | access_url?: string; 57 | tag_names?: any[]; 58 | exposedPorts?: any[]; 59 | system_id?: string; 60 | containerPort?: number; 61 | favorite?: boolean; 62 | } 63 | 64 | export interface IAppConfiguration { 65 | id: string; 66 | name?: string; 67 | type?: 'text' | 'number' | 'boolean' | 'date'; 68 | min?: number | Date; 69 | max?: number | Date; 70 | required?: boolean; 71 | default?: any; 72 | } 73 | 74 | export interface IAppPermissions { 75 | users?: string[]; 76 | groups?: string[]; 77 | } 78 | 79 | @Injectable() 80 | export class VantageAppService extends mixinHttp(class {}, { 81 | baseUrl: '/api/app', 82 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 83 | }) { 84 | @TdGET({ 85 | path: '/apps', 86 | options: { 87 | observe: 'response', 88 | }, 89 | }) 90 | query( 91 | @TdQueryParams() params?: HttpParams, 92 | @TdResponse() response?: Observable>, 93 | ): Observable<{ total: number; data: IApp[] }> { 94 | return response.pipe( 95 | map((res: HttpResponse) => { 96 | return { 97 | total: +res.headers.get('X-Total'), 98 | data: res.body, 99 | }; 100 | }), 101 | ); 102 | } 103 | 104 | @TdGET({ 105 | path: '/apps/:id', 106 | }) 107 | get(@TdParam('id') id: string, @TdResponse() response?: Observable): Observable { 108 | return response; 109 | } 110 | 111 | @TdPOST({ 112 | path: '/apps', 113 | }) 114 | create(@TdBody() body: IApp, @TdResponse() response?: Observable): Observable { 115 | return response; 116 | } 117 | 118 | @TdPATCH({ 119 | path: '/apps/:id', 120 | }) 121 | update(@TdParam('id') id: string, @TdBody() body: IApp, @TdResponse() response?: Observable): Observable { 122 | return response; 123 | } 124 | 125 | @TdDELETE({ 126 | path: '/apps/:id', 127 | }) 128 | delete(@TdParam('id') id: string, @TdResponse() response?: Observable): Observable { 129 | return response; 130 | } 131 | 132 | @TdPOST({ 133 | path: '/apps/:id/container', 134 | }) 135 | public uploadFile( 136 | @TdParam('id') id: string, 137 | @TdBody() formData: FormData, 138 | @TdResponse() response?: Observable>, 139 | ): Observable { 140 | return response.pipe( 141 | map((res: HttpResponse) => { 142 | return true; 143 | }), 144 | ); 145 | } 146 | } 147 | 148 | export function VANTAGE_APP_PROVIDER_FACTORY(parent: VantageAppService): VantageAppService { 149 | return parent || new VantageAppService(); 150 | } 151 | 152 | export const VANTAGE_APP_PROVIDER: Provider = { 153 | // If there is already a service available, use that. Otherwise, provide a new one. 154 | provide: VantageAppService, 155 | deps: [[new Optional(), new SkipSelf(), VantageAppService]], 156 | useFactory: VANTAGE_APP_PROVIDER_FACTORY, 157 | }; 158 | -------------------------------------------------------------------------------- /src/lib/app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/app/public_api.ts: -------------------------------------------------------------------------------- 1 | export { VantageAppModule } from './app.module'; 2 | export { VantageAppService, IApp, AppType, IAppConfiguration } from './app.service'; 3 | export { VantageTagsService, ITag } from './tags.service'; 4 | -------------------------------------------------------------------------------- /src/lib/app/tags.service.ts: -------------------------------------------------------------------------------- 1 | import { Optional, SkipSelf, Provider, Injectable } from '@angular/core'; 2 | import { HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http'; 3 | 4 | import { mixinHttp, TdQueryParams, TdResponse, TdGET } from '@covalent/http'; 5 | 6 | import { Observable } from 'rxjs'; 7 | import { map } from 'rxjs/operators'; 8 | 9 | export interface ITag { 10 | tag_id?: string; 11 | tag?: string; 12 | } 13 | 14 | @Injectable() 15 | export class VantageTagsService extends mixinHttp(class {}, { 16 | baseUrl: '/api/app', 17 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 18 | }) { 19 | @TdGET({ 20 | path: '/tags', 21 | options: { 22 | observe: 'response', 23 | }, 24 | }) 25 | query( 26 | @TdQueryParams() params?: HttpParams, 27 | @TdResponse() response?: Observable>, 28 | ): Observable<{ total: number; data: ITag[] }> { 29 | return response.pipe( 30 | map((res: HttpResponse) => { 31 | return { 32 | total: +res.headers.get('X-Total'), 33 | data: res.body, 34 | }; 35 | }), 36 | ); 37 | } 38 | } 39 | 40 | export function VANTAGE_TAGS_PROVIDER_FACTORY(parent: VantageTagsService): VantageTagsService { 41 | return parent || new VantageTagsService(); 42 | } 43 | 44 | export const VANTAGE_TAGS_PROVIDER: Provider = { 45 | // If there is already a service available, use that. Otherwise, provide a new one. 46 | provide: VantageTagsService, 47 | deps: [[new Optional(), new SkipSelf(), VantageTagsService]], 48 | useFactory: VANTAGE_TAGS_PROVIDER_FACTORY, 49 | }; 50 | -------------------------------------------------------------------------------- /src/lib/assets/assets.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { VANTAGE_ASSETS_PROVIDER } from './assets.service'; 4 | 5 | @NgModule({ 6 | imports: [CommonModule], 7 | providers: [VANTAGE_ASSETS_PROVIDER], 8 | }) 9 | export class VantageAssetsModule {} 10 | -------------------------------------------------------------------------------- /src/lib/assets/assets.service.ts: -------------------------------------------------------------------------------- 1 | import { map, catchError } from 'rxjs/operators'; 2 | import { Injectable, Optional, SkipSelf, Provider } from '@angular/core'; 3 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; 4 | import { mixinHttp, TdGET, TdResponse } from '@covalent/http'; 5 | import { Observable, of } from 'rxjs'; 6 | 7 | import { IMenuItem } from '@covalent/core/dynamic-menu'; 8 | 9 | export interface ILearnLinkItem extends IMenuItem { 10 | description?: string; 11 | } 12 | 13 | export interface IHelpAssets { 14 | [name: string]: { 15 | links: IMenuItem[]; 16 | learn?: ILearnLinkItem[]; 17 | }; 18 | } 19 | 20 | @Injectable() 21 | export class VantageAssetsService extends mixinHttp(class {}, { 22 | baseUrl: '/ui-assets', 23 | baseHeaders: new HttpHeaders({ 24 | Accept: 'application/json', 25 | }), 26 | }) { 27 | /** 28 | * Retrieve the help JSON definition asset 29 | */ 30 | @TdGET({ 31 | path: '/json/help/help.json', 32 | options: { 33 | observe: 'response', 34 | }, 35 | }) 36 | getHelpJSON(@TdResponse() response?: Observable>): Observable { 37 | return response.pipe( 38 | catchError((error: Response) => { 39 | return of(error); 40 | }), 41 | map((res: HttpResponse) => { 42 | return res.body; 43 | }), 44 | ); 45 | } 46 | } 47 | 48 | export function VANTAGE_ASSETS_PROVIDER_FACTORY(parent: VantageAssetsService): VantageAssetsService { 49 | return parent || new VantageAssetsService(); 50 | } 51 | 52 | export const VANTAGE_ASSETS_PROVIDER: Provider = { 53 | // If there is already a service available, use that. Otherwise, provide a new one. 54 | provide: VantageAssetsService, 55 | deps: [[new Optional(), new SkipSelf(), VantageAssetsService]], 56 | useFactory: VANTAGE_ASSETS_PROVIDER_FACTORY, 57 | }; 58 | -------------------------------------------------------------------------------- /src/lib/assets/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/assets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/assets/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './assets.module'; 2 | export * from './assets.service'; 3 | -------------------------------------------------------------------------------- /src/lib/audit/audit.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VANTAGE_AUDIT_PROVIDER } from './audit.service'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule], 8 | providers: [VANTAGE_AUDIT_PROVIDER], 9 | }) 10 | export class VantageAuditModule {} 11 | -------------------------------------------------------------------------------- /src/lib/audit/audit.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Optional, SkipSelf, Provider } from '@angular/core'; 2 | import { HttpParams, HttpHeaders, HttpResponse, HttpErrorResponse } from '@angular/common/http'; 3 | 4 | import { Observable, of } from 'rxjs'; 5 | import { map, catchError } from 'rxjs/operators'; 6 | 7 | import { mixinHttp, TdGET, TdPOST, TdParam, TdBody, TdResponse, TdQueryParams } from '@covalent/http'; 8 | 9 | export interface IAuditLog { 10 | action?: string; 11 | component?: string; 12 | correlation_id?: string; 13 | details?: string; 14 | id?: number; 15 | logtime?: any; 16 | message?: string; 17 | result?: boolean; 18 | username?: string; 19 | } 20 | 21 | @Injectable() 22 | export class VantageAuditService extends mixinHttp(class {}, { 23 | baseUrl: '/api/audit', 24 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 25 | }) { 26 | @TdGET({ 27 | path: '/audit/messages', 28 | options: { 29 | observe: 'response', 30 | }, 31 | }) 32 | query( 33 | @TdQueryParams() params?: HttpParams, 34 | @TdResponse() response?: Observable>, 35 | ): Observable<{ total: number; data: IAuditLog[] }> { 36 | return response.pipe( 37 | map((res: HttpResponse) => { 38 | return { 39 | total: +res.headers.get('X-Total'), 40 | data: res.body, 41 | }; 42 | }), 43 | ); 44 | } 45 | 46 | @TdPOST({ 47 | path: '/audit/messages', 48 | }) 49 | create(@TdBody() body: IAuditLog, @TdResponse() response?: Observable): Observable { 50 | return response; 51 | } 52 | 53 | @TdGET({ 54 | path: '/audit/messages/:id', 55 | }) 56 | get(@TdParam('id') id: number | string, @TdResponse() response?: Observable): Observable { 57 | return response; 58 | } 59 | 60 | @TdGET({ 61 | path: '/health', 62 | }) 63 | health(@TdResponse() response?: Observable>): Observable { 64 | return response.pipe( 65 | catchError((error: HttpErrorResponse) => { 66 | return of(false); 67 | }), 68 | map((res: HttpResponse) => { 69 | return !!res; 70 | }), 71 | ); 72 | } 73 | } 74 | 75 | export function VANTAGE_AUDIT_PROVIDER_FACTORY(parent: VantageAuditService): VantageAuditService { 76 | return parent || new VantageAuditService(); 77 | } 78 | 79 | export const VANTAGE_AUDIT_PROVIDER: Provider = { 80 | // If there is already a service available, use that. Otherwise, provide a new one. 81 | provide: VantageAuditService, 82 | deps: [[new Optional(), new SkipSelf(), VantageAuditService]], 83 | useFactory: VANTAGE_AUDIT_PROVIDER_FACTORY, 84 | }; 85 | -------------------------------------------------------------------------------- /src/lib/audit/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/audit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/audit/public_api.ts: -------------------------------------------------------------------------------- 1 | export { VantageAuditModule } from './audit.module'; 2 | export { VantageAuditService, IAuditLog } from './audit.service'; 3 | -------------------------------------------------------------------------------- /src/lib/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VANTAGE_TOKEN_PROVIDER } from './token/token.service'; 5 | import { VANTAGE_SESSION_PROVIDER } from './session/session.service'; 6 | 7 | import { VantageAuthenticationGuard } from './guards/authentication.guard'; 8 | 9 | @NgModule({ 10 | imports: [CommonModule], 11 | providers: [VANTAGE_TOKEN_PROVIDER, VANTAGE_SESSION_PROVIDER, VantageAuthenticationGuard], 12 | }) 13 | export class VantageAuthenticationModule {} 14 | -------------------------------------------------------------------------------- /src/lib/auth/config/vantageLoginProxyConfig.d.ts: -------------------------------------------------------------------------------- 1 | declare const VantageLoginProxyConfig: any; 2 | -------------------------------------------------------------------------------- /src/lib/auth/config/vantageLoginProxyConfig.js: -------------------------------------------------------------------------------- 1 | function VantageLoginProxyConfig({ serverUrl, localUrl, localProto }) { 2 | return { 3 | '/start-login': { 4 | target: serverUrl, 5 | bypass: function(req, res, proxyOptions) { 6 | req.headers['X-Orig-Host'] = localUrl; 7 | req.headers['X-Orig-Proto'] = localProto; 8 | }, 9 | pathRewrite: function(path) { 10 | return path.replace(/^(\/start-login)/, '') || '/'; 11 | }, 12 | secure: false, 13 | changeOrigin: true, 14 | logLevel: 'debug', 15 | }, 16 | }; 17 | } 18 | module.exports = VantageLoginProxyConfig; 19 | -------------------------------------------------------------------------------- /src/lib/auth/guards/authentication.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpErrorResponse } from '@angular/common/http'; 3 | import { ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate, Router } from '@angular/router'; 4 | import { VantageSessionService } from '../session/session.service'; 5 | import { Observable } from 'rxjs'; 6 | import { timeout, catchError, map, finalize } from 'rxjs/operators'; 7 | import { showPreLoader, hidePreLoader } from '@td-vantage/ui-platform/utilities'; 8 | 9 | const UNAUTHORIZED: number = 401; 10 | 11 | @Injectable() 12 | export class VantageAuthenticationGuard implements CanActivate { 13 | constructor(private _router: Router, private _sessionService: VantageSessionService) {} 14 | 15 | canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { 16 | showPreLoader(); 17 | return this._sessionService.getInfo().pipe( 18 | timeout(5000), 19 | catchError((e: HttpErrorResponse) => { 20 | // if not logged in, go ahead and log in...otherwise logout 21 | // append the current path so we get redirected back upon login 22 | e.status === UNAUTHORIZED 23 | ? (window.location.href = '/start-login?nonce=' + Math.floor(1000000000 + Math.random() * 9000000000)) 24 | : this._sessionService.logout(); 25 | throw e; 26 | }), 27 | map(() => true), 28 | finalize(() => hidePreLoader()), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/lib/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/auth/interceptors/authentication.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpErrorResponse } from '@angular/common/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | import { catchError } from 'rxjs/operators'; 6 | 7 | import { ITdHttpInterceptor } from '@covalent/http'; 8 | 9 | /* 4XX errors */ 10 | const UNAUTHORIZED: number = 401; 11 | const PAYLOAD_TOO_LARGE: number = 413; 12 | 13 | /* 5XX errors */ 14 | const SERVICE_UNAVAILABLE: number = 503; 15 | const GATEWAY_TIMEOUT: number = 504; 16 | 17 | @Injectable() 18 | export class VantageAuthenticationInterceptor implements ITdHttpInterceptor { 19 | onResponseError(error: any): any { 20 | if (error.status === UNAUTHORIZED && !error.url.includes('/token/validity')) { 21 | // if logged in, go ahead an expire the cooke and reload the page 22 | document.cookie = 'XSRF-TOKEN=;expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 23 | window.location.reload(); 24 | } 25 | throw error; 26 | } 27 | 28 | handleResponse(observable: Observable): Observable { 29 | return observable.pipe( 30 | catchError((e: any) => { 31 | // check error and do something 32 | if (e instanceof HttpErrorResponse) { 33 | // do something if its response error 34 | return this.onResponseError(e); 35 | } 36 | }), 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/lib/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http", 7 | "@ngx-translate/core": "ngx-translate.core" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/lib/auth/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './auth.module'; 2 | export * from './session/session.service'; 3 | export * from './token/token.service'; 4 | export * from './guards/authentication.guard'; 5 | export * from './interceptors/authentication.interceptor'; 6 | -------------------------------------------------------------------------------- /src/lib/auth/session/session.service.ts: -------------------------------------------------------------------------------- 1 | import { map, catchError } from 'rxjs/operators'; 2 | import { Injectable, Provider, Optional, SkipSelf } from '@angular/core'; 3 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; 4 | import { mixinHttp, TdGET, TdResponse, TdPOST, TdParam } from '@covalent/http'; 5 | import { Observable, of } from 'rxjs'; 6 | import { IUser } from '@td-vantage/ui-platform/user'; 7 | 8 | import { tap, switchMap } from 'rxjs/operators'; 9 | 10 | export interface ISessionUser { 11 | user?: string; 12 | valid?: boolean; 13 | admin?: boolean; 14 | groups?: string[]; 15 | expires_at?: string; 16 | } 17 | 18 | @Injectable() 19 | export class VantageSessionService extends mixinHttp(class {}, { 20 | baseUrl: '/api/user', 21 | baseHeaders: new HttpHeaders({ 22 | Accept: 'application/json', 23 | }), 24 | }) { 25 | private _user: IUser; 26 | 27 | get user(): IUser { 28 | return this._user; 29 | } 30 | 31 | getInfo(): Observable { 32 | if (!this._user) { 33 | return this._get().pipe( 34 | switchMap((sessionUser: ISessionUser) => { 35 | return this._getUser(sessionUser.user).pipe( 36 | tap((u: IUser) => { 37 | this._user = Object.assign({}, sessionUser, u); 38 | }), 39 | ); 40 | }), 41 | ); 42 | } else { 43 | return of(this._user); 44 | } 45 | } 46 | 47 | public logout(): void { 48 | window.location.href = '/api/user/logout?nonce=' + Math.floor(1000000000 + Math.random() * 9000000000); 49 | } 50 | 51 | /** 52 | * gets the current sso logged in users information 53 | */ 54 | @TdPOST({ 55 | path: '/token/validity?fields=user,groups', 56 | options: { 57 | observe: 'response', 58 | }, 59 | }) 60 | private _get(@TdResponse() response?: Observable>): Observable { 61 | return response.pipe( 62 | map((res: HttpResponse) => { 63 | return res.body; 64 | }), 65 | ); 66 | } 67 | 68 | /** 69 | * gets a single users information 70 | */ 71 | @TdGET({ 72 | path: '/users/:username', 73 | options: { 74 | observe: 'response', 75 | }, 76 | }) 77 | private _getUser( 78 | @TdParam('username') id: string, 79 | @TdResponse() response?: Observable>, 80 | ): Observable { 81 | return response.pipe( 82 | catchError((error: Response) => { 83 | return of(error); 84 | }), 85 | map((res: HttpResponse) => { 86 | return res.body; 87 | }), 88 | ); 89 | } 90 | } 91 | 92 | export function VANTAGE_SESSION_PROVIDER_FACTORY(parent: VantageSessionService): VantageSessionService { 93 | return parent || new VantageSessionService(); 94 | } 95 | 96 | export const VANTAGE_SESSION_PROVIDER: Provider = { 97 | // If there is already a service available, use that. Otherwise, provide a new one. 98 | provide: VantageSessionService, 99 | deps: [[new Optional(), new SkipSelf(), VantageSessionService]], 100 | useFactory: VANTAGE_SESSION_PROVIDER_FACTORY, 101 | }; 102 | -------------------------------------------------------------------------------- /src/lib/auth/token/token.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Optional, SkipSelf, Provider } from '@angular/core'; 2 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | import { map } from 'rxjs/operators'; 6 | 7 | import { mixinHttp, TdPOST, TdBody, TdResponse } from '@covalent/http'; 8 | 9 | export interface IToken { 10 | access_token?: string; 11 | refresh_token?: string; 12 | expires_at?: string; 13 | token_type?: string; 14 | expires_in?: number; 15 | token_in?: string; 16 | } 17 | 18 | @Injectable() 19 | export class VantageTokenService extends mixinHttp(class {}, { 20 | baseUrl: '/api/user', 21 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 22 | }) { 23 | @TdPOST({ 24 | path: '/token', 25 | options: { 26 | observe: 'response', 27 | }, 28 | }) 29 | create( 30 | @TdBody() user: { username: string; password: string }, 31 | @TdResponse() response?: Observable>, 32 | ): Observable { 33 | return response.pipe( 34 | map((res: HttpResponse) => { 35 | const data: IToken = res.body; 36 | const token: string = res.headers.get('X-AUTH-TOKEN') || data.access_token; 37 | return { data, token }; 38 | }), 39 | ); 40 | } 41 | } 42 | 43 | export function VANTAGE_TOKEN_PROVIDER_FACTORY(parent: VantageTokenService): VantageTokenService { 44 | return parent || new VantageTokenService(); 45 | } 46 | 47 | export const VANTAGE_TOKEN_PROVIDER: Provider = { 48 | // If there is already a service available, use that. Otherwise, provide a new one. 49 | provide: VantageTokenService, 50 | deps: [[new Optional(), new SkipSelf(), VantageTokenService]], 51 | useFactory: VANTAGE_TOKEN_PROVIDER_FACTORY, 52 | }; 53 | -------------------------------------------------------------------------------- /src/lib/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/common/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './tokens'; 2 | -------------------------------------------------------------------------------- /src/lib/common/tokens.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from '@angular/core'; 2 | 3 | export const VANTAGE_BASE_URL_TOKEN: InjectionToken = new InjectionToken('vantage-base-url-token'); 4 | -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/lib/ng-package-common.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $schema: '../../node_modules/ng-packagr/ng-package.schema.json', 3 | lib: { 4 | entryFile: 'index.ts', 5 | umdModuleIds: { 6 | '@covalent/core': 'covalent.core', 7 | '@covalent/core/paging': 'covalent.core.paging', 8 | '@covalent/core/virtual-scroll': 'covalent.core.virtual-scroll', 9 | '@covalent/core/notifications': 'covalent.core.notifications', 10 | '@covalent/core/common': 'covalent.core.common', 11 | '@covalent/core/message': 'covalent.core.message', 12 | '@covalent/core/chips': 'covalent.core.chips', 13 | '@covalent/core/data-table': 'covalent.core.data-table', 14 | '@covalent/core/dialogs': 'covalent.core.dialogs', 15 | '@covalent/core/expansion-panel': 'covalent.core.expansion-panel', 16 | '@covalent/core/file': 'covalent.core.file', 17 | '@covalent/core/json-formatter': 'covalent.core.json-formatter', 18 | '@covalent/core/layout': 'covalent.core.layout', 19 | '@covalent/core/loading': 'covalent.core.loading', 20 | '@covalent/core/media': 'covalent.core.media', 21 | '@covalent/core/menu': 'covalent.core.menu', 22 | '@covalent/core/search': 'covalent.core.search', 23 | '@covalent/core/steps': 'covalent.core.steps', 24 | 25 | '@covalent/dynamic-forms': 'covalent.dynamic-forms', 26 | '@covalent/highlight': 'covalent.highlight', 27 | '@covalent/http': 'covalent.http', 28 | '@covalent/markdown': 'covalent.markdown', 29 | 30 | '@ngx-translate/core': 'ngx-translate.core', 31 | }, 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /src/lib/ng-package.js: -------------------------------------------------------------------------------- 1 | let ngPackageSettings = require('./ng-package-common.js'); 2 | ngPackageSettings['dest'] = '../../deploy/ui-platform'; 3 | module.exports = ngPackageSettings; 4 | -------------------------------------------------------------------------------- /src/lib/notification/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/notification/notification.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VANTAGE_SMTP_PROVIDER } from './smtp/smtp.service'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule], 8 | providers: [VANTAGE_SMTP_PROVIDER], 9 | }) 10 | export class VantageNotificationModule {} 11 | -------------------------------------------------------------------------------- /src/lib/notification/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/notification/public_api.ts: -------------------------------------------------------------------------------- 1 | export { VantageNotificationModule } from './notification.module'; 2 | export { VantageSMTPService, ISMTPConfig } from './smtp/smtp.service'; 3 | -------------------------------------------------------------------------------- /src/lib/notification/smtp/smtp.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, Optional, SkipSelf } from '@angular/core'; 2 | import { HttpHeaders, HttpResponse, HttpErrorResponse } from '@angular/common/http'; 3 | 4 | import { Observable, of } from 'rxjs'; 5 | import { map, catchError } from 'rxjs/operators'; 6 | 7 | import { mixinHttp, TdGET, TdPUT, TdDELETE, TdBody, TdResponse } from '@covalent/http'; 8 | 9 | export interface ISMTPConfig { 10 | server?: string; 11 | port?: number; 12 | reply_address?: string; 13 | smtp_username?: string; 14 | smtp_password?: string; 15 | use_ssl?: boolean; 16 | anon_logon?: boolean; 17 | server_timeout?: number; 18 | } 19 | 20 | @Injectable() 21 | export class VantageSMTPService extends mixinHttp(class {}, { 22 | baseUrl: '/api/notification', 23 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 24 | }) { 25 | @TdPUT({ 26 | path: '/smtp-config', 27 | }) 28 | create(@TdBody() body: ISMTPConfig, @TdResponse() response?: Observable): Observable { 29 | return response; 30 | } 31 | 32 | @TdGET({ 33 | path: '/smtp-config', 34 | }) 35 | query(@TdResponse() response?: Observable): Observable { 36 | return response; 37 | } 38 | 39 | @TdDELETE({ 40 | path: '/smtp-config', 41 | }) 42 | delete(@TdResponse() response?: Observable): Observable { 43 | return response; 44 | } 45 | 46 | @TdGET({ 47 | path: '/health', 48 | }) 49 | health(@TdResponse() response?: Observable>): Observable { 50 | return response.pipe( 51 | catchError((error: HttpErrorResponse) => { 52 | return of(false); 53 | }), 54 | map((res: HttpResponse) => { 55 | return !!res; 56 | }), 57 | ); 58 | } 59 | } 60 | 61 | export function VANTAGE_SMTP_PROVIDER_FACTORY(parent: VantageSMTPService): VantageSMTPService { 62 | return parent || new VantageSMTPService(); 63 | } 64 | 65 | export const VANTAGE_SMTP_PROVIDER: Provider = { 66 | // If there is already a service available, use that. Otherwise, provide a new one. 67 | provide: VantageSMTPService, 68 | deps: [[new Optional(), new SkipSelf(), VantageSMTPService]], 69 | useFactory: VANTAGE_SMTP_PROVIDER_FACTORY, 70 | }; 71 | -------------------------------------------------------------------------------- /src/lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@td-vantage/ui-platform", 3 | "version": "0.0.0-PLATFORM", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/Teradata/vantage-ui-platform.git" 7 | }, 8 | "bugs": { 9 | "url": "https://github.com/Teradata/vantage-ui-platform/issues" 10 | }, 11 | "license": "MIT", 12 | "author": "Teradata UI Team", 13 | "peerDependencies": { 14 | "@angular/common": "^0.0.0-NG", 15 | "@angular/core": "^0.0.0-NG", 16 | "@angular/cdk": "^0.0.0-MATERIAL", 17 | "@angular/material": "^0.0.0-MATERIAL", 18 | "@covalent/core": "^0.0.0-COVALENT", 19 | "@covalent/http": "^0.0.0-COVALENT", 20 | "@ngx-translate/core": "^0.0.0-TRANSLATE" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/lib/sqle/credentials-dialog/credentials-dialog.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | {{ 'CREATE_CONNECTION' | translate }} 5 |
6 | 7 |
8 | 9 |
10 | 11 |
12 | 13 | 14 | {{ 'SYSTEM' | translate }} 15 | 16 | 23 | 24 |
{{ system.nickname }}
25 |
{{ system.host }}:{{ system.port }}
26 |
27 | 33 |
{{ sys.nickname }}
34 |
{{ sys.host }}:{{ sys.port }}
35 |
36 |
37 |
38 |
39 |
40 |
41 | 48 | 49 | {{ 'USE_CURRENT_SESSION' | translate }} 50 | 51 | 52 | {{ 'ENTER_CREDENTIALS' | translate }} 53 | 54 | 55 |
56 | 57 |
58 | 59 | 60 | {{ 'USERNAME' | translate }} 61 | 62 | 72 | 73 |
74 |
75 | 76 | 77 | {{ 'PASSWORD' | translate }} 78 | 79 | 88 | 89 |
90 |
91 |
92 |
93 |
102 | dns 103 |

{{ 'NO_SYSTEMS' | translate }}

104 |

{{ 'NO_SYSTEMS.NOTE' | translate }}

105 |
106 |
107 |
108 |
109 | 117 | 127 |
128 |
129 |
130 |
131 | -------------------------------------------------------------------------------- /src/lib/sqle/credentials-dialog/credentials-dialog.component.scss: -------------------------------------------------------------------------------- 1 | ::ng-deep { 2 | .vui-credentials-dialog-system { 3 | .mat-form-field-infix { 4 | padding: 0.4em 0 0.6em; 5 | } 6 | &.mat-form-field-appearance-outline .mat-select-arrow-wrapper { 7 | transform: translateY(-6%); 8 | } 9 | .vui-credentials-dialog-system-option { 10 | .mat-option-text { 11 | line-height: 14px; 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/sqle/credentials-dialog/credentials-dialog.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { HttpParams } from '@angular/common/http'; 3 | 4 | import { MatDialogRef } from '@angular/material/dialog'; 5 | 6 | import { TdLoadingService } from '@covalent/core/loading'; 7 | 8 | import { ISystem, VantageSystemService } from '@td-vantage/ui-platform/system'; 9 | import { VantageConnectionService } from '../connection.service'; 10 | import { ISQLEConnection } from '../query.service'; 11 | 12 | import { Observable, Subject, of } from 'rxjs'; 13 | import { retry, map, tap, catchError } from 'rxjs/operators'; 14 | 15 | import { TranslateService } from '@ngx-translate/core'; 16 | 17 | @Component({ 18 | selector: 'vui-sqle-credentials-dialog', 19 | templateUrl: './credentials-dialog.component.html', 20 | styleUrls: ['./credentials-dialog.component.scss'], 21 | }) 22 | export class VantageCredentialsDialogComponent implements OnInit, OnDestroy { 23 | // listens to times we try to connect regardless 24 | private _connectionAttempt$: Subject = new Subject(); 25 | connectionAttempt$: Observable = this._connectionAttempt$.asObservable(); 26 | 27 | basicAuthEnabled: boolean = false; 28 | systems$: Observable; 29 | 30 | system: ISystem; 31 | connectionType: boolean = false; 32 | username: string; 33 | password: string; 34 | 35 | errorMsg: string; 36 | 37 | constructor( 38 | private _dialogRef: MatDialogRef, 39 | private _connectionService: VantageConnectionService, 40 | private _systemService: VantageSystemService, 41 | private _loadingService: TdLoadingService, 42 | private _translate: TranslateService, 43 | ) {} 44 | 45 | ngOnInit(): void { 46 | // prepopulate connection type 47 | this.connectionType = this.basicAuthEnabled; 48 | // prep systems observable 49 | let queryParams: HttpParams = new HttpParams(); 50 | queryParams = queryParams.append('systemType', 'TERADATA'); 51 | this.systems$ = this._systemService.query(queryParams).pipe( 52 | retry(2), 53 | catchError(() => { 54 | this.errorMsg = this._translate.instant('ERROR_RETRIEVE_DATA'); 55 | return of({ data: [] }); 56 | }), 57 | map((resp: { data: ISystem[] }) => resp.data), 58 | tap((systems: ISystem[]) => { 59 | if (systems && systems.length) { 60 | // select first system by default if no system was prepopulated 61 | if (!this.system) { 62 | this.system = systems[0]; 63 | } 64 | // if there is only one system and basic auth disabled, we try to connect to it automagically 65 | if (systems.length === 1 && !this.basicAuthEnabled) { 66 | this.connect(); 67 | } 68 | } 69 | }), 70 | ); 71 | } 72 | 73 | ngOnDestroy(): void { 74 | // finallize subject 75 | this._connectionAttempt$.complete(); 76 | } 77 | 78 | compareSystemWith(a: ISystem, b: ISystem): boolean { 79 | return a && b && a.nickname === b.nickname; 80 | } 81 | 82 | async connect(): Promise { 83 | try { 84 | this.errorMsg = undefined; 85 | // block users from closing the dialog while connecting 86 | this._dialogRef.disableClose = true; 87 | this._loadingService.register('system.connect'); 88 | const connection: ISQLEConnection = this.connectionType 89 | ? { system: this.system, creds: btoa(this.username + ':' + this.password) } 90 | : { system: this.system }; 91 | 92 | if (this._connectionService.exists(connection)) { 93 | await this._connectionService.setAsCurrent(connection).toPromise(); 94 | } else { 95 | await this._connectionService.addAndSetAsCurrent(connection).toPromise(); 96 | } 97 | 98 | this._dialogRef.close(connection); 99 | } catch (error) { 100 | this.errorMsg = error.message; 101 | } finally { 102 | this._connectionAttempt$.next(); 103 | // allow users to close dialog again 104 | this._dialogRef.disableClose = false; 105 | this._loadingService.resolve('system.connect'); 106 | } 107 | } 108 | 109 | cancel(): void { 110 | this._dialogRef.close(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/lib/sqle/index.ts: -------------------------------------------------------------------------------- 1 | export * from './query.service'; 2 | export * from './spooled-query.service'; 3 | export * from './dictionary.service'; 4 | export * from './connection.service'; 5 | export * from './credentials-dialog/credentials-dialog.component'; 6 | export * from './sqle.module'; 7 | -------------------------------------------------------------------------------- /src/lib/sqle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/core/loading": "covalent.core.loading", 7 | "@covalent/core/message": "covalent.core.message", 8 | "@covalent/http": "covalent.http", 9 | "@ngx-translate/core": "ngx-translate.core" 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/lib/sqle/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './index'; 2 | -------------------------------------------------------------------------------- /src/lib/sqle/spooled-query.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, Optional, SkipSelf } from '@angular/core'; 2 | import { HttpErrorResponse } from '@angular/common/http'; 3 | import { TranslateService } from '@ngx-translate/core'; 4 | import { catchError, expand, map, mapTo, skipWhile, switchMap, take, tap } from 'rxjs/operators'; 5 | import { BehaviorSubject, Observable, of, throwError, timer } from 'rxjs'; 6 | import { VantageConnectionService } from './connection.service'; 7 | import { VantageQueryService, IQueryPayload, IQueryResultSet } from './query.service'; 8 | 9 | interface ISpooledQueryError extends HttpErrorResponse { 10 | id: string; 11 | detailMessage: string; 12 | } 13 | 14 | const MAX_INTERVAL: number = 10000; 15 | const BASE_INTERVAL: number = 2000; 16 | 17 | enum SpooledQueryState { 18 | QUEUED = 'QUEUED', 19 | PENDING = 'PENDING', 20 | SUBMITTED = 'SUBMITTED', 21 | RESPONDING = 'RESPONDING', 22 | SPOOLING = 'SPOOLING', 23 | RESULT_SET_READY = 'RESULT_SET_READY', 24 | } 25 | 26 | @Injectable() 27 | export class VantageSpooledQueryService { 28 | queryStatus: BehaviorSubject = new BehaviorSubject(undefined); 29 | queryStatus$: Observable = this.queryStatus.asObservable(); 30 | queryStack: string[] = []; 31 | constructor( 32 | private connectionService: VantageConnectionService, 33 | private queryService: VantageQueryService, 34 | private translate: TranslateService, 35 | ) {} 36 | 37 | cancelLastQuery(): void { 38 | const thisQuery: string = this.queryStack.pop(); 39 | 40 | return this.deleteSpooledQuery(thisQuery); 41 | } 42 | 43 | getRunningInfo(): Observable { 44 | return this.queryStatus$; 45 | } 46 | 47 | querySystem(payload: IQueryPayload): Observable { 48 | return this.queryService 49 | .querySystem(this.connectionService.currentConnection, { ...payload, spooledResultSet: true }) 50 | .pipe( 51 | tap((res: any) => this.queryStack.push(res.id)), 52 | switchMap((res: any) => this.exponentialBackOffInterval(MAX_INTERVAL, res.id)), 53 | switchMap((id: number) => 54 | this.queryService.getQuery(this.connectionService.currentConnection, id.toString()).pipe( 55 | map((query: any) => query.queryState), 56 | tap((val: any) => this.queryStatus.next(val)), 57 | map((val: any) => [id, val]), 58 | ), 59 | ), 60 | skipWhile(([id, status]: [string, SpooledQueryState]) => status !== SpooledQueryState.RESULT_SET_READY), 61 | take(1), 62 | switchMap(([id]: [string, SpooledQueryState]) => 63 | this.queryService.getQueryResult(this.connectionService.currentConnection, id).pipe( 64 | map((val: IQueryResultSet) => [id, val]), 65 | tap(() => this.queryStack.pop()), 66 | catchError((res: HttpErrorResponse) => { 67 | return throwError({ 68 | ...res, 69 | ...{ id }, 70 | detailMessage: `Error ${res.error.error}: ${res.error.message}`, 71 | } as ISpooledQueryError); 72 | }), 73 | ), 74 | ), 75 | map(([id, results]: [string, IQueryResultSet]) => results), 76 | ); 77 | } 78 | 79 | exponentialBackOffInterval(maxInterval: number, returnVal: any): Observable { 80 | return of(0).pipe( 81 | expand((iteration: number) => timer(this.calcInterval(iteration, maxInterval)).pipe(mapTo(iteration + 1))), 82 | mapTo(returnVal), 83 | ); 84 | } 85 | 86 | calcInterval(iteration: number, maxInterval: number): number { 87 | const expo: number = 1.4; 88 | const interval: number = Math.pow(expo, iteration) * BASE_INTERVAL; 89 | 90 | return Math.min(interval, maxInterval); 91 | } 92 | 93 | deleteSpooledQuery(queryId: string): void { 94 | this.queryService 95 | .deleteQuery(this.connectionService.currentConnection, queryId) 96 | .subscribe(undefined, (err: Error) => { 97 | throw new Error(this.translate.instant('SPOOLED_QUERY_COULD_NOT_BE_DELETED', { error: JSON.stringify(err) })); 98 | }); 99 | } 100 | } 101 | 102 | export function VANTAGE_SPOOLED_QUERY_PROVIDER_FACTORY( 103 | parent: VantageSpooledQueryService, 104 | connectionService: VantageConnectionService, 105 | queryService: VantageQueryService, 106 | translate: TranslateService, 107 | ): VantageSpooledQueryService { 108 | return parent || new VantageSpooledQueryService(connectionService, queryService, translate); 109 | } 110 | 111 | export const VANTAGE_SPOOLED_QUERY_PROVIDER: Provider = { 112 | // If there is already a service available, use that. Otherwise, provide a new one. 113 | provide: VantageSpooledQueryService, 114 | deps: [ 115 | [new Optional(), new SkipSelf(), VantageSpooledQueryService], 116 | VantageConnectionService, 117 | VantageQueryService, 118 | TranslateService, 119 | ], 120 | useFactory: VANTAGE_SPOOLED_QUERY_PROVIDER_FACTORY, 121 | }; 122 | -------------------------------------------------------------------------------- /src/lib/sqle/sqle.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { MatCardModule } from '@angular/material/card'; 6 | import { MatButtonModule } from '@angular/material/button'; 7 | import { MatDialogModule } from '@angular/material/dialog'; 8 | import { MatFormFieldModule } from '@angular/material/form-field'; 9 | import { MatInputModule } from '@angular/material/input'; 10 | import { MatSelectModule } from '@angular/material/select'; 11 | import { MatRadioModule } from '@angular/material/radio'; 12 | import { MatIconModule } from '@angular/material/icon'; 13 | 14 | import { CovalentLoadingModule } from '@covalent/core/loading'; 15 | import { CovalentMessageModule } from '@covalent/core/message'; 16 | 17 | import { VantageSystemModule } from '@td-vantage/ui-platform/system'; 18 | 19 | import { TranslateModule } from '@ngx-translate/core'; 20 | 21 | import { VANTAGE_CONNECTION_PROVIDER } from './connection.service'; 22 | import { VANTAGE_DICTIONARY_PROVIDER } from './dictionary.service'; 23 | import { VANTAGE_QUERY_PROVIDER } from './query.service'; 24 | import { VANTAGE_SPOOLED_QUERY_PROVIDER } from './spooled-query.service'; 25 | 26 | import { VantageCredentialsDialogComponent } from './credentials-dialog/credentials-dialog.component'; 27 | 28 | @NgModule({ 29 | declarations: [VantageCredentialsDialogComponent], 30 | exports: [VantageCredentialsDialogComponent], 31 | imports: [ 32 | CommonModule, 33 | FormsModule, 34 | MatCardModule, 35 | MatButtonModule, 36 | MatDialogModule, 37 | MatFormFieldModule, 38 | MatInputModule, 39 | MatSelectModule, 40 | MatRadioModule, 41 | MatIconModule, 42 | CovalentLoadingModule, 43 | CovalentMessageModule, 44 | VantageSystemModule, 45 | TranslateModule, 46 | ], 47 | providers: [ 48 | VANTAGE_CONNECTION_PROVIDER, 49 | VANTAGE_DICTIONARY_PROVIDER, 50 | VANTAGE_QUERY_PROVIDER, 51 | VANTAGE_SPOOLED_QUERY_PROVIDER, 52 | ], 53 | }) 54 | export class VantageSQLEModule {} 55 | -------------------------------------------------------------------------------- /src/lib/system/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/system/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/system/public_api.ts: -------------------------------------------------------------------------------- 1 | export { VantageSystemModule } from './system.module'; 2 | export { VantageSystemService, ISystem, SystemType, ITestSystem, VANTAGE_SYSTEMS_TYPES } from './system.service'; 3 | -------------------------------------------------------------------------------- /src/lib/system/system.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, Type, InjectionToken } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VANTAGE_SYSTEM_PROVIDER } from './system.service'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule], 8 | providers: [VANTAGE_SYSTEM_PROVIDER], 9 | }) 10 | export class VantageSystemModule {} 11 | -------------------------------------------------------------------------------- /src/lib/system/system.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Optional, SkipSelf, Provider } from '@angular/core'; 2 | import { HttpParams, HttpHeaders, HttpResponse, HttpErrorResponse } from '@angular/common/http'; 3 | 4 | import { Observable, of } from 'rxjs'; 5 | import { map, catchError } from 'rxjs/operators'; 6 | 7 | import { mixinHttp, TdGET, TdPUT, TdPOST, TdDELETE, TdParam, TdBody, TdResponse, TdQueryParams } from '@covalent/http'; 8 | 9 | /* 10 | * These interfaces are duplicated in the system and the query service. 11 | * However, within the system service, SystemType includes Aster & Presto. 12 | * Whereas in the query service, they are excluded. 13 | * TODO: DRY this up 14 | */ 15 | export enum SystemType { 16 | Teradata = 'TERADATA', 17 | Aster = 'ASTER', 18 | Presto = 'PRESTO', 19 | } 20 | 21 | export const VANTAGE_SYSTEMS_TYPES: SystemType[] = [SystemType.Teradata, SystemType.Aster, SystemType.Presto]; 22 | 23 | export interface ISystemAttributes { 24 | attributes?: any; 25 | } 26 | 27 | export interface IAbstractSystem { 28 | host?: string; 29 | port?: number; 30 | system_type?: SystemType; 31 | catalog?: string; 32 | schema?: string; 33 | } 34 | 35 | export interface ISystem extends IAbstractSystem { 36 | attributes?: string; 37 | data_center?: string; 38 | environment?: string; 39 | id?: string; 40 | nickname?: string; 41 | platform_id?: number; 42 | system_attributes?: ISystemAttributes; 43 | version?: string; 44 | } 45 | 46 | export interface ITestSystem extends IAbstractSystem { 47 | account?: string; 48 | default_char_set?: string; 49 | default_database?: string; 50 | log_mech?: string; 51 | password?: string; 52 | username?: string; 53 | } 54 | 55 | @Injectable() 56 | export class VantageSystemService extends mixinHttp(class {}, { 57 | baseUrl: '/api/system', 58 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 59 | }) { 60 | @TdGET({ 61 | path: '/health', 62 | }) 63 | health(@TdResponse() response?: Observable>): Observable { 64 | return response.pipe( 65 | catchError((error: HttpErrorResponse) => { 66 | return of(false); 67 | }), 68 | map((res: HttpResponse) => { 69 | return !!res; 70 | }), 71 | ); 72 | } 73 | 74 | @TdGET({ 75 | path: '/systems', 76 | options: { 77 | observe: 'response', 78 | }, 79 | }) 80 | query( 81 | @TdQueryParams() params?: HttpParams, 82 | @TdResponse() response?: Observable>, 83 | ): Observable<{ total: number; data: ISystem[] }> { 84 | return response.pipe( 85 | map((res: HttpResponse) => { 86 | return { 87 | total: +res.headers.get('X-Total'), 88 | data: res.body, 89 | }; 90 | }), 91 | ); 92 | } 93 | 94 | @TdGET({ 95 | path: '/systems/:id', 96 | }) 97 | get(@TdParam('id') id: string | number, @TdResponse() response?: Observable): Observable { 98 | return response; 99 | } 100 | 101 | @TdPOST({ 102 | path: '/systems', 103 | }) 104 | create(@TdBody() system: ISystem, @TdResponse() response?: Observable): Observable { 105 | return response; 106 | } 107 | 108 | @TdPUT({ 109 | path: '/systems/:id', 110 | }) 111 | update( 112 | @TdParam('id') id: string, 113 | @TdBody() system: ISystem, 114 | @TdResponse() response?: Observable, 115 | ): Observable { 116 | return response; 117 | } 118 | 119 | @TdDELETE({ 120 | path: '/systems/:id', 121 | }) 122 | delete(@TdParam('id') id: string, @TdResponse() response?: Observable): Observable { 123 | return response; 124 | } 125 | 126 | @TdPOST({ 127 | path: '/testsystem', 128 | }) 129 | test(@TdBody() system: ITestSystem, @TdResponse() response?: Observable>): Observable { 130 | return response.pipe( 131 | map((res: HttpResponse) => { 132 | return true; 133 | }), 134 | ); 135 | } 136 | } 137 | 138 | export function VANTAGE_SYSTEM_PROVIDER_FACTORY(parent: VantageSystemService): VantageSystemService { 139 | return parent || new VantageSystemService(); 140 | } 141 | 142 | export const VANTAGE_SYSTEM_PROVIDER: Provider = { 143 | // If there is already a service available, use that. Otherwise, provide a new one. 144 | provide: VantageSystemService, 145 | deps: [[new Optional(), new SkipSelf(), VantageSystemService]], 146 | useFactory: VANTAGE_SYSTEM_PROVIDER_FACTORY, 147 | }; 148 | -------------------------------------------------------------------------------- /src/lib/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | 7 | declare const require: any; 8 | 9 | // First, initialize the Angular testing environment. 10 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 11 | // Then we find all the tests. 12 | const context: any = require.context('./', true, /\.spec\.ts$/); 13 | // And load the modules. 14 | context.keys().map(context); 15 | -------------------------------------------------------------------------------- /src/lib/testing/cypress/index.ts: -------------------------------------------------------------------------------- 1 | export * from './utility/utility'; 2 | export * from './mock/mockutility'; 3 | -------------------------------------------------------------------------------- /src/lib/testing/cypress/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/testing/cypress/utility/README.md: -------------------------------------------------------------------------------- 1 | # Cypress Testing Utilities 2 | 3 | ## Login and logout 4 | 5 | Functions to help facilitate logging in and out 6 | 7 | - `login()` 8 | - `logout()` 9 | 10 | ### Setup 11 | 12 | - `baseUrl` 13 | 14 | - must be defined in the cypress config (cypress.json) 15 | - ex: http://localhost:4200 16 | 17 | - `loginUrl` 18 | - must be defined in the cypress env config (cypress.env.json) 19 | - ex: https://vantage.url.io/auth 20 | 21 | ### Usage 22 | 23 | ```typescript 24 | import { login, logout } from '@td-vantage/ui-platform/testing/cypress'; 25 | 26 | login({ 27 | username: 'username', 28 | password: 'password', 29 | }); 30 | 31 | logout(); 32 | ``` 33 | 34 | ## Whitelisting SSO Cookies 35 | 36 | Cypress deletes cookies between each `it`. This whitelists the sso cookies, so they are not deleted. 37 | 38 | ### Usage 39 | 40 | `support/index.js` 41 | 42 | ```js 43 | import { whiteListSSOCookies } from '@td-vantage/ui-platform/testing/cypress'; 44 | 45 | whiteListSSOCookies(); 46 | ``` 47 | 48 | Or if you want more control just import the SSOCookies 49 | 50 | ```js 51 | import { SSO_COOKIES } from '@td-vantage/ui-platform/testing/cypress'; 52 | 53 | Cypress.Cookies.defaults({ whitelist: [..SSO_COOKIES, 'my-custom-cookie'] }); 54 | ``` 55 | 56 | ## Waiting for Angular 57 | 58 | Wait for Angular to stabilize 59 | 60 | ### Usage 61 | 62 | ```ts 63 | import { waitForAngular } from '@td-vantage/ui-platform/testing/cypress'; 64 | 65 | waitForAngular(); 66 | ``` 67 | -------------------------------------------------------------------------------- /src/lib/testing/cypress/utility/utility.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | const BASE_URL: string = Cypress.config('baseUrl'); // ex: http://localhost:4200 4 | const LOGIN_URL: string = Cypress.env('loginUrl'); // ex: https://vantage.url.io/auth 5 | 6 | export interface ILoginCredentials { 7 | username: string; 8 | password: string; 9 | } 10 | 11 | // inspired by https://vrockai.github.io/blog/2017/10/28/cypress-keycloak-intregration/ 12 | export function login({ username, password }: ILoginCredentials): void { 13 | cy.request({ 14 | url: LOGIN_URL, 15 | }).then((response: any) => { 16 | const loginPageHtml: HTMLElement = document.createElement('html'); 17 | loginPageHtml.innerHTML = response.body; 18 | const loginForm: HTMLFormElement = loginPageHtml.querySelector('#kc-form-login'); 19 | if (loginForm) { 20 | cy.request({ 21 | form: true, 22 | method: 'POST', 23 | url: loginForm.action, 24 | followRedirect: false, 25 | body: { 26 | username, 27 | password, 28 | }, 29 | }).then(() => { 30 | _redirectToHome(); 31 | }); 32 | } else { 33 | _redirectToHome(); 34 | } 35 | }); 36 | } 37 | 38 | export function logout(): void { 39 | cy.request('/api/user/logout'); 40 | } 41 | 42 | function _redirectToHome(): void { 43 | cy.visit(BASE_URL); 44 | cy.url().should('not.include', LOGIN_URL); 45 | cy.url().should('include', BASE_URL); 46 | } 47 | 48 | export const SSO_COOKIES: string[] = ['USER_SSO_ID', 'XSRF-TOKEN']; 49 | export function whiteListSSOCookies(): void { 50 | Cypress.Cookies.defaults({ whitelist: SSO_COOKIES }); 51 | } 52 | 53 | export function waitForAngular(): Cypress.Chainable { 54 | cy.get('[ng-version]').should('exist'); 55 | return cy.window().then((win: Window) => { 56 | return new Cypress.Promise( 57 | (resolve: (thenableOrResult?: {} | PromiseLike<{}>) => void, reject: (error?: any) => void) => { 58 | const testabilities: any = win['getAllAngularTestabilities'](); 59 | if (!testabilities) { 60 | return reject(new Error('No testabilities. Is Angular loaded?')); 61 | } 62 | let count: number = testabilities.length; 63 | testabilities.forEach((testability: any) => 64 | testability.whenStable(() => { 65 | count--; 66 | if (count !== 0) { 67 | return; 68 | } 69 | resolve(); 70 | }), 71 | ); 72 | }, 73 | ); 74 | }); 75 | } 76 | -------------------------------------------------------------------------------- /src/lib/testing/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/testing/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './cypress'; 2 | -------------------------------------------------------------------------------- /src/lib/theme/README.md: -------------------------------------------------------------------------------- 1 | # Vantage Theme Service 2 | 3 | Exposes methods to toggle theme and observables to listen to theme changes. 4 | 5 | ## Sample usage 6 | 7 | ```ts 8 | import { VantageThemeModule } from '@td-vantage/ui-platform/theme'; 9 | { 10 | imports: [VantageThemeModule], 11 | }; 12 | ``` 13 | 14 | Choose your weapon of choice 15 | 16 | ### Within TypeScript 17 | 18 | ```ts 19 | import { VantageThemeService } from '@td-vantage/ui-platform/theme'; 20 | { 21 | constructor(public _themeService: VantageThemeService) {} 22 | 23 | ngOnInit(): void { 24 | this._themeService 25 | .map({ 'dark-theme': 'dark-logo', 'light-theme': 'light-logo' }) 26 | .pipe(takeUntil(this.unsubscribe)) 27 | .subscribe(console.log); 28 | 29 | this._themeService.darkTheme$.pipe(takeUntil(this.unsubscribe)).subscribe(console.log); 30 | this._themeService.lightTheme$.pipe(takeUntil(this.unsubscribe)).subscribe(console.log); 31 | this._themeService.activeTheme$.pipe(takeUntil(this.unsubscribe)).subscribe(console.log); 32 | } 33 | } 34 | ``` 35 | 36 | ### Within HTML 37 | 38 | ```html 39 |
40 |
Active theme: {{ _themeService.activeTheme$ | async }}
41 |
Dark theme is active: {{ _themeService.darkTheme$ | async }}
42 |
Light theme is active: {{ _themeService.lightTheme$ | async }}
43 |
44 | Theme map: {{ _themeService.map({ 'dark-theme': 'hacker vibes 👩‍💻', 'light-theme': 'miami vibes 🏖️' }) | async }} 45 |
46 |
47 | ``` 48 | -------------------------------------------------------------------------------- /src/lib/theme/_all-theme.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * All theme imports 3 | */ 4 | // Order here is important 5 | @import 'palette'; 6 | @import 'mixins'; 7 | @import 'theme'; 8 | @import 'overrides'; 9 | @import 'default-variables'; 10 | -------------------------------------------------------------------------------- /src/lib/theme/_default-variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * DEFAULT VARIABLES FOR VANTAGE UIs 3 | */ 4 | 5 | // Light theme 6 | $td-accent: mat-palette($td-teal, 900, 200, 900); 7 | $td-primary: mat-palette($td-slate, 500, 200, 800); 8 | $td-warn: mat-palette($mat-red, 900); 9 | 10 | // Dark theme 11 | $td-dark-accent: mat-palette($td-teal, 300, 100, 1200); 12 | $td-dark-primary: mat-palette($td-slate, 300, 200, 900); 13 | $td-dark-warn: mat-palette($mat-red, 400); 14 | -------------------------------------------------------------------------------- /src/lib/theme/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Helper mixins for Teradata Brand palettes 2 | // 3 | // Mixins here loop over Teradata brand palette and create classes to be used 4 | // in Teradata Products. 5 | 6 | // Text color palette mixin 7 | @mixin tc($palette, $name, $default) { 8 | .tc-#{$name} { 9 | color: map-get($palette, $default); 10 | } 11 | @each $size, $color in $palette { 12 | @if $size != contrast { 13 | .tc-#{$name}-#{$size} { 14 | color: $color; 15 | } 16 | } 17 | } 18 | } 19 | 20 | // Background color palette mixin 21 | @mixin bgc($palette, $name, $default) { 22 | .bgc-#{$name} { 23 | background-color: map-get($palette, $default); 24 | } 25 | @each $size, $color in $palette { 26 | @if $size != contrast { 27 | .bgc-#{$name}-#{$size} { 28 | background-color: $color; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/lib/theme/_theme.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * FONTS 3 | */ 4 | 5 | // Teradata Font 6 | $td-font-default: 'Arial, Helvetica, sans-serif'; 7 | 8 | $td-font-display-regular: '"RidleyGrotesk", "RidleyGrotesk-Regular", Arial, Helvetica, sans-serif'; 9 | $td-font-display-medium: '"RidleyGrotesk", "RidleyGrotesk-Medium", Arial, Helvetica, sans-serif'; 10 | $td-font-display-semibold: '"RidleyGrotesk","RidleyGrotesk-Semibold", Arial, Helvetica, sans-serif'; 11 | $td-font-display-bold: '"RidleyGrotesk","RidleyGrotesk-Bold", Arial, Helvetica, sans-serif'; 12 | 13 | $fontConfig: ( 14 | font-family: $td-font-default, 15 | display-4: mat-typography-level(96px, 120px, 500, $td-font-display-medium, -1.5px), 16 | display-3: mat-typography-level(60px, 84px, 600, $td-font-display-semibold, -0.5px), 17 | display-2: mat-typography-level(48px, 64px, 600, $td-font-display-semibold, 0), 18 | display-1: mat-typography-level(34px, 48px, 700, $td-font-display-bold, 0.25px), 19 | headline: mat-typography-level(24px, 36px, 700, $td-font-display-bold, 0), 20 | title: mat-typography-level(20px, 28px, 600, $td-font-display-semibold, 0.15px), 21 | subheading-2: mat-typography-level(16px, 24px, 600, $td-font-display-semibold, 0.15px), 22 | subheading-1: mat-typography-level(14px, 20px, 600, $td-font-display-semibold, 0.1px), 23 | body-1: mat-typography-level(14px, 20px, 400, $td-font-default, 0.25px), 24 | body-2: mat-typography-level(14px, 20px, 700, $td-font-default, 0.25px), 25 | button: mat-typography-level(14px, 16px, 600, $td-font-display-semibold, 0.5px), 26 | caption: mat-typography-level(12px, 16px, 400, $td-font-default, 0.4px), 27 | input: mat-typography-level(inherit, 1.125, 400, $td-font-default, 0.4px), 28 | overline: mat-typography-level(10px, 12px, 400, $td-font-default, 1.5px), 29 | ); 30 | 31 | @include mat-core($fontConfig); 32 | 33 | .mat-card-title { 34 | @include mat-typography-level-to-styles($fontConfig, title); 35 | } 36 | 37 | .mat-overline { 38 | text-transform: uppercase; 39 | @include mat-typography-level-to-styles($fontConfig, overline); 40 | } 41 | 42 | // Teradata Palette utility classes 43 | body { 44 | font-family: #{$td-font-default} !important; 45 | // Teradata Slate - foreground & background 46 | @include tc($td-slate, td-slate, 500); 47 | @include bgc($td-slate, td-slate, 500); 48 | 49 | // Teradata Orange - foreground & background 50 | @include tc($td-orange, td-orange, 800); 51 | @include bgc($td-orange, td-orange, 500); 52 | 53 | // Teradata Yellow - foreground & background 54 | @include tc($td-yellow, td-yellow, 900); 55 | @include bgc($td-yellow, td-yellow, 500); 56 | 57 | // Teradata Teal - foreground & background 58 | @include tc($td-teal, td-teal, 900); 59 | @include bgc($td-teal, td-teal, 500); 60 | 61 | // Teradata Blue - foreground & background 62 | @include tc($td-blue, td-blue, 700); 63 | @include bgc($td-blue, td-blue, 500); 64 | } 65 | -------------------------------------------------------------------------------- /src/lib/theme/icons/teradata-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/lib/theme/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/theme/long-form-content/_small-scale.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Vantage UI platform - Long Form Content Styles - Small Scale 3 | // Spec - https://www.figma.com/file/0i2f1i2tkgylxOHLi53IFZ/Long-form-content?node-id=0%3A1 4 | // 5 | 6 | @mixin long-form-content-sm($theme, $fontConfig) { 7 | $foreground: map-get($theme, foreground); 8 | 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p { 16 | color: mat-color($foreground, text); 17 | } 18 | 19 | h2, 20 | h3, 21 | h4, 22 | h5, 23 | h6 { 24 | padding-top: 24px !important; 25 | margin-bottom: 8px !important; 26 | } 27 | 28 | h1 { 29 | @include mat-typography-level-to-styles($fontConfig, headline); 30 | 31 | margin: 8px 0 !important; 32 | } 33 | h2 { 34 | @include mat-typography-level-to-styles($fontConfig, title); 35 | } 36 | h3 { 37 | @include mat-typography-level-to-styles($fontConfig, subheading-2); 38 | } 39 | h4 { 40 | @include mat-typography-level-to-styles($fontConfig, subheading-1); 41 | } 42 | h5 { 43 | @include mat-typography-level-to-styles($fontConfig, body-2); 44 | } 45 | h6 { 46 | @include mat-typography-level-to-styles($fontConfig, caption); 47 | } 48 | p { 49 | @include mat-typography-level-to-styles($fontConfig, body-1); 50 | } 51 | blockquote { 52 | padding-top: 4px !important; 53 | margin-bottom: 16px !important; 54 | p { 55 | @include mat-typography-level-to-styles($fontConfig, input); 56 | 57 | color: mat-color($foreground, secondary-text); 58 | font-style: italic; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/lib/theme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/theme/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './theme.module'; 2 | export * from './theme.service'; 3 | -------------------------------------------------------------------------------- /src/lib/theme/theme.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { VANTAGE_THEME_PROVIDER } from './theme.service'; 4 | 5 | @NgModule({ 6 | imports: [CommonModule], 7 | providers: [VANTAGE_THEME_PROVIDER], 8 | }) 9 | export class VantageThemeModule {} 10 | -------------------------------------------------------------------------------- /src/lib/theme/theme.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Renderer2, Inject, RendererFactory2, Provider, Optional, SkipSelf } from '@angular/core'; 2 | import { fromEvent, BehaviorSubject, Observable, fromEventPattern, merge } from 'rxjs'; 3 | import { filter, map } from 'rxjs/operators'; 4 | import { DOCUMENT } from '@angular/common'; 5 | 6 | export const THEME_LOCAL_STORAGE_KEY: string = 'vantage.theme'; 7 | 8 | export enum VantageTheme { 9 | DARK = 'dark-theme', 10 | LIGHT = 'light-theme', 11 | } 12 | 13 | export interface IVantageThemeMap { 14 | [VantageTheme.DARK]?: any; 15 | [VantageTheme.LIGHT]?: any; 16 | } 17 | 18 | @Injectable() 19 | export class VantageThemeService { 20 | private _renderer2: Renderer2; 21 | 22 | private readonly _activeThemeSubject: BehaviorSubject; 23 | private readonly preferDarkMediaQuery: MediaQueryList = window.matchMedia('(prefers-color-scheme: dark)'); 24 | 25 | public activeTheme$: Observable; 26 | public darkTheme$: Observable; 27 | public lightTheme$: Observable; 28 | 29 | constructor(private rendererFactory: RendererFactory2, @Inject(DOCUMENT) private _document: any) { 30 | const initialValue: VantageTheme = this.localStorageTheme() || this.checkOSPreference(); 31 | 32 | this._renderer2 = rendererFactory.createRenderer(undefined, undefined); 33 | this._activeThemeSubject = new BehaviorSubject(initialValue); 34 | 35 | this.activeTheme$ = this._activeThemeSubject.asObservable(); 36 | this.darkTheme$ = this._activeThemeSubject 37 | .asObservable() 38 | .pipe(map((theme: VantageTheme) => theme === VantageTheme.DARK)); 39 | this.lightTheme$ = this._activeThemeSubject 40 | .asObservable() 41 | .pipe(map((theme: VantageTheme) => theme === VantageTheme.LIGHT)); 42 | 43 | // apply initial theme 44 | this.applyTheme(initialValue, false); 45 | 46 | // observe media query change events 47 | const mediaObserver: Observable = fromEventPattern( 48 | this.preferDarkMediaQuery.addListener.bind(this.preferDarkMediaQuery), 49 | this.preferDarkMediaQuery.removeListener.bind(this.preferDarkMediaQuery), 50 | ).pipe( 51 | map((event: MediaQueryListEvent) => { 52 | return event.matches ? VantageTheme.DARK : VantageTheme.LIGHT; 53 | }), 54 | ); 55 | 56 | // account for storage events in other browser tabs 57 | const storageObserver: Observable = fromEvent(window, 'storage').pipe( 58 | filter((event: StorageEvent) => event.key === THEME_LOCAL_STORAGE_KEY), 59 | map((event: StorageEvent) => (event.newValue ? (event.newValue as VantageTheme) : this.checkOSPreference())), 60 | ); 61 | 62 | // apply theme on storage or media query change 63 | merge(storageObserver, mediaObserver).subscribe((theme: VantageTheme) => this.applyTheme(theme)); 64 | 65 | // account for cached navigation 66 | // needed for Firefox BFCache 67 | window.addEventListener('pageshow', (pageTransition: PageTransitionEvent) => { 68 | const localStorageTheme: VantageTheme = this.localStorageTheme(); 69 | const localStorageDiffersActiveTheme: boolean = localStorageTheme && localStorageTheme !== this._activeTheme; 70 | 71 | if (pageTransition.persisted && localStorageDiffersActiveTheme) { 72 | this.applyTheme(localStorageTheme); 73 | } 74 | }); 75 | } 76 | 77 | private get _activeTheme(): VantageTheme { 78 | return this._activeThemeSubject.getValue(); 79 | } 80 | 81 | private set _activeTheme(theme: VantageTheme) { 82 | this._activeThemeSubject.next(theme); 83 | } 84 | 85 | public get darkThemeIsActive(): boolean { 86 | return this._activeTheme === VantageTheme.DARK; 87 | } 88 | public get lightThemeIsActive(): boolean { 89 | return this._activeTheme === VantageTheme.LIGHT; 90 | } 91 | 92 | public activeTheme(): VantageTheme { 93 | return this._activeTheme; 94 | } 95 | 96 | public applyLightTheme(): VantageTheme { 97 | return this.applyTheme(VantageTheme.LIGHT); 98 | } 99 | 100 | public applyDarkTheme(): VantageTheme { 101 | return this.applyTheme(VantageTheme.DARK); 102 | } 103 | 104 | public toggleTheme(): VantageTheme { 105 | return this._activeTheme === VantageTheme.DARK ? this.applyLightTheme() : this.applyDarkTheme(); 106 | } 107 | 108 | public map(mapObject: IVantageThemeMap, fallback?: any): Observable { 109 | return this.activeTheme$.pipe(map((value: VantageTheme) => (value in mapObject ? mapObject[value] : fallback))); 110 | } 111 | 112 | private localStorageTheme(): VantageTheme { 113 | return localStorage.getItem(THEME_LOCAL_STORAGE_KEY) as VantageTheme; 114 | } 115 | 116 | private applyTheme(theme: VantageTheme, saveSetting: boolean = true): VantageTheme { 117 | this._renderer2.removeClass( 118 | this._document.querySelector('html'), 119 | theme === VantageTheme.DARK ? VantageTheme.LIGHT : VantageTheme.DARK, 120 | ); 121 | this._renderer2.addClass(this._document.querySelector('html'), theme); 122 | 123 | if (saveSetting) { 124 | localStorage.setItem(THEME_LOCAL_STORAGE_KEY, theme); 125 | } 126 | 127 | return (this._activeTheme = theme); 128 | } 129 | 130 | private checkOSPreference(): VantageTheme { 131 | // it should now be light-by-default 132 | return this.preferDarkMediaQuery.matches ? VantageTheme.DARK : VantageTheme.LIGHT; 133 | } 134 | } 135 | 136 | export function VANTAGE_THEME_PROVIDER_FACTORY( 137 | parent: VantageThemeService, 138 | rendererFactory: RendererFactory2, 139 | _document: any, 140 | ): VantageThemeService { 141 | return parent || new VantageThemeService(rendererFactory, _document); 142 | } 143 | 144 | export const VANTAGE_THEME_PROVIDER: Provider = { 145 | // If there is already a service available, use that. Otherwise, provide a new one. 146 | provide: VantageThemeService, 147 | deps: [[new Optional(), new SkipSelf(), VantageThemeService], [RendererFactory2], [DOCUMENT]], 148 | useFactory: VANTAGE_THEME_PROVIDER_FACTORY, 149 | }; 150 | -------------------------------------------------------------------------------- /src/lib/theme/utilities/icons.ts: -------------------------------------------------------------------------------- 1 | export const TD_ICONS: TdIcon[] = [ 2 | 'alias_arrow', 3 | 'api', 4 | 'application', 5 | 'bucket', 6 | 'cluster_analysis', 7 | 'column', 8 | 'connected_identity', 9 | 'data_preparation', 10 | 'data_source', 11 | 'database_changed', 12 | 'database_edit', 13 | 'database_foreign', 14 | 'database_lab', 15 | 'database_search', 16 | 'database_synced', 17 | 'database', 18 | 'disconnect', 19 | 'dock_right', 20 | 'engine', 21 | 'file_changed', 22 | 'file_edit', 23 | 'file_foreign', 24 | 'file_lab', 25 | 'file_search', 26 | 'file_synced', 27 | 'file', 28 | 'formula', 29 | 'lab', 30 | 'loader_dots', 31 | 'machine_learning', 32 | 'model_configuration', 33 | 'model', 34 | 'no_results', 35 | 'node_branch', 36 | 'node_merge', 37 | 'node_notification', 38 | 'object_storage', 39 | 'operations', 40 | 'operators_divide', 41 | 'operators_equals', 42 | 'operators_greater_than_or_equal', 43 | 'operators_greater_than', 44 | 'operators_less_than_or_equal', 45 | 'operators_less_than', 46 | 'operators_multiply', 47 | 'operators_not_equal', 48 | 'operators_parenthesis_left', 49 | 'operators_parenthesis_right', 50 | 'operators_parenthesis', 51 | 'operators_subtract', 52 | 'outbound_campaign_manager', 53 | 'product_analyst', 54 | 'product_console', 55 | 'product_editor', 56 | 'product_explorer', 57 | 'resize_northeast', 58 | 'resize_northwest', 59 | 'resize_southeast', 60 | 'resize_southwest', 61 | 'rules_insert', 62 | 'rules_select', 63 | 'rules', 64 | 'script_macro', 65 | 'script_sql', 66 | 'script_stored_procedure', 67 | 'script', 68 | 'segmentation', 69 | 'server_changed', 70 | 'server_edit', 71 | 'server_foreign', 72 | 'server_lab', 73 | 'server_search', 74 | 'server_synced', 75 | 'server', 76 | 'sftp', 77 | 'table_changed', 78 | 'table_edit', 79 | 'table_foreign', 80 | 'table_lab', 81 | 'table_search', 82 | 'table_synced', 83 | 'table', 84 | 'teradata', 85 | 'text_analysis', 86 | 'undock', 87 | 'variable', 88 | 'view_sankey', 89 | 'wand', 90 | 'workflow', 91 | ]; 92 | 93 | export type TdIcon = 94 | | 'alias_arrow' 95 | | 'api' 96 | | 'application' 97 | | 'bucket' 98 | | 'cluster_analysis' 99 | | 'column' 100 | | 'connected_identity' 101 | | 'data_preparation' 102 | | 'data_source' 103 | | 'database_changed' 104 | | 'database_edit' 105 | | 'database_foreign' 106 | | 'database_lab' 107 | | 'database_search' 108 | | 'database_synced' 109 | | 'database' 110 | | 'disconnect' 111 | | 'dock_right' 112 | | 'engine' 113 | | 'file_changed' 114 | | 'file_edit' 115 | | 'file_foreign' 116 | | 'file_lab' 117 | | 'file_search' 118 | | 'file_synced' 119 | | 'file' 120 | | 'formula' 121 | | 'lab' 122 | | 'loader_dots' 123 | | 'machine_learning' 124 | | 'model_configuration' 125 | | 'model' 126 | | 'no_results' 127 | | 'node_branch' 128 | | 'node_merge' 129 | | 'node_notification' 130 | | 'object_storage' 131 | | 'operations' 132 | | 'operators_divide' 133 | | 'operators_equals' 134 | | 'operators_greater_than_or_equal' 135 | | 'operators_greater_than' 136 | | 'operators_less_than_or_equal' 137 | | 'operators_less_than' 138 | | 'operators_multiply' 139 | | 'operators_not_equal' 140 | | 'operators_parenthesis_left' 141 | | 'operators_parenthesis_right' 142 | | 'operators_parenthesis' 143 | | 'operators_subtract' 144 | | 'outbound_campaign_manager' 145 | | 'product_analyst' 146 | | 'product_console' 147 | | 'product_editor' 148 | | 'product_explorer' 149 | | 'resize_northeast' 150 | | 'resize_northwest' 151 | | 'resize_southeast' 152 | | 'resize_southwest' 153 | | 'rules_insert' 154 | | 'rules_select' 155 | | 'rules' 156 | | 'script_macro' 157 | | 'script_sql' 158 | | 'script_stored_procedure' 159 | | 'script' 160 | | 'segmentation' 161 | | 'server_changed' 162 | | 'server_edit' 163 | | 'server_foreign' 164 | | 'server_lab' 165 | | 'server_search' 166 | | 'server_synced' 167 | | 'server' 168 | | 'sftp' 169 | | 'table_changed' 170 | | 'table_edit' 171 | | 'table_foreign' 172 | | 'table_lab' 173 | | 'table_search' 174 | | 'table_synced' 175 | | 'table' 176 | | 'teradata' 177 | | 'text_analysis' 178 | | 'undock' 179 | | 'variable' 180 | | 'view_sankey' 181 | | 'wand' 182 | | 'workflow'; 183 | -------------------------------------------------------------------------------- /src/lib/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "baseUrl": ".", 6 | "inlineSourceMap": true, 7 | "inlineSources": true, 8 | "skipLibCheck": true, 9 | "paths": { 10 | "@td-vantage/ui-platform": ["./"], 11 | "@td-vantage/ui-platform/*": ["./*"] 12 | } 13 | }, 14 | "exclude": ["./auth/config/*"], 15 | "angularCompilerOptions": { 16 | "annotateForClosureCompiler": true, 17 | "skipTemplateCodegen": true, 18 | "strictMetadataEmit": true, 19 | "fullTemplateTypeCheck": true, 20 | "enableResourceInlining": true, 21 | "enableIvy": false 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "../../out-tsc/spec", 6 | "lib": ["es6", "dom"], 7 | "module": "commonjs", 8 | "types": ["jasmine", "hammerjs", "node"], 9 | "paths": { 10 | "@td-vantage/ui-platform": ["./"], 11 | "@td-vantage/ui-platform/*": ["./*"] 12 | } 13 | }, 14 | "include": ["../polyfills.ts", "test.ts", "**/*.spec.*"] 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/user-profile/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/user-profile/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/user-profile/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './user-profile.component'; 2 | export * from './user-profile.module'; 3 | -------------------------------------------------------------------------------- /src/lib/user-profile/user-profile.component.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/lib/user-profile/user-profile.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Teradata/vantage-ui-platform/f30aafeac6caa7cd76b0cf56f92d0dc6f8af49b1/src/lib/user-profile/user-profile.component.scss -------------------------------------------------------------------------------- /src/lib/user-profile/user-profile.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { VantageThemeService } from '@td-vantage/ui-platform/theme'; 3 | import { VantageSessionService } from '@td-vantage/ui-platform/auth'; 4 | 5 | @Component({ 6 | selector: 'vui-user-profile', 7 | templateUrl: './user-profile.component.html', 8 | styleUrls: ['./user-profile.component.scss'], 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | }) 11 | export class VantageUserProfileComponent { 12 | constructor(public themeService: VantageThemeService, public sessionService: VantageSessionService) {} 13 | } 14 | -------------------------------------------------------------------------------- /src/lib/user-profile/user-profile.module.ts: -------------------------------------------------------------------------------- 1 | import { VantageUserProfileComponent } from './user-profile.component'; 2 | import { NgModule } from '@angular/core'; 3 | import { CommonModule } from '@angular/common'; 4 | import { MatButtonModule } from '@angular/material/button'; 5 | import { MatIconModule } from '@angular/material/icon'; 6 | import { MatTooltipModule } from '@angular/material/tooltip'; 7 | import { CovalentCommonModule } from '@covalent/core/common'; 8 | import { CovalentUserProfileModule } from '@covalent/core/user-profile'; 9 | import { TranslateModule } from '@ngx-translate/core'; 10 | import { MatDividerModule } from '@angular/material/divider'; 11 | import { MatListModule } from '@angular/material/list'; 12 | 13 | @NgModule({ 14 | declarations: [VantageUserProfileComponent], 15 | imports: [ 16 | CommonModule, 17 | MatButtonModule, 18 | MatIconModule, 19 | MatTooltipModule, 20 | MatDividerModule, 21 | MatListModule, 22 | CovalentCommonModule, 23 | CovalentUserProfileModule, 24 | TranslateModule.forRoot(), 25 | ], 26 | exports: [VantageUserProfileComponent], 27 | }) 28 | export class VantageUserProfileModule {} 29 | -------------------------------------------------------------------------------- /src/lib/user/group/group.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; 2 | import { HttpHeaders, HttpResponse, HttpParams } from '@angular/common/http'; 3 | import { mixinHttp, TdGET, TdResponse, TdQueryParams } from '@covalent/http'; 4 | import { Observable, of } from 'rxjs'; 5 | import { map, catchError } from 'rxjs/operators'; 6 | 7 | export interface IGroup { 8 | name?: string; 9 | description?: string; 10 | id?: string; 11 | display_name?: string; 12 | users?: string[]; 13 | } 14 | 15 | @Injectable() 16 | export class VantageGroupService extends mixinHttp(class {}, { 17 | baseUrl: '/api/user', 18 | baseHeaders: new HttpHeaders({ 19 | Accept: 'application/json', 20 | }), 21 | }) { 22 | /** 23 | * get groups in paginated form via query string 24 | */ 25 | @TdGET({ 26 | path: '/groups', 27 | options: { 28 | observe: 'response', 29 | }, 30 | }) 31 | query( 32 | @TdQueryParams() queryParams?: HttpParams, 33 | @TdResponse() response?: Observable>, 34 | ): Observable<{ total: number; data: IGroup[] }> { 35 | return response.pipe( 36 | catchError((error: Response) => { 37 | return of(error); 38 | }), 39 | map((res: HttpResponse) => { 40 | return { 41 | total: +res.headers.get('X-Total'), 42 | data: res.body, 43 | }; 44 | }), 45 | ); 46 | } 47 | } 48 | 49 | export function VANTAGE_GROUP_PROVIDER_FACTORY(parent: VantageGroupService): VantageGroupService { 50 | return parent || new VantageGroupService(); 51 | } 52 | 53 | export const VANTAGE_GROUP_PROVIDER: Provider = { 54 | // If there is already a service available, use that. Otherwise, provide a new one. 55 | provide: VantageGroupService, 56 | deps: [[new Optional(), new SkipSelf(), VantageGroupService]], 57 | useFactory: VANTAGE_GROUP_PROVIDER_FACTORY, 58 | }; 59 | -------------------------------------------------------------------------------- /src/lib/user/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/user/ldap/ldap.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, Optional, SkipSelf } from '@angular/core'; 2 | import { HttpHeaders } from '@angular/common/http'; 3 | 4 | import { Observable } from 'rxjs'; 5 | import { map } from 'rxjs/operators'; 6 | 7 | import { mixinHttp, TdGET, TdPOST, TdPATCH, TdDELETE, TdParam, TdBody, TdResponse } from '@covalent/http'; 8 | 9 | export enum LDAPEncription { 10 | None = 'NONE', 11 | } 12 | 13 | export interface ILDAPConfig { 14 | allowed_groups?: string[]; 15 | base_dn?: string; 16 | config_id?: number; 17 | connectionUrl?: string; 18 | email_field?: string; 19 | encryption?: LDAPEncription; 20 | group_id_field?: string; 21 | groups_base_dn?: string; 22 | id_field?: string; 23 | member_field?: string; 24 | member_of_field?: string; 25 | name_field?: string; 26 | port?: number; 27 | search_pass?: string; 28 | search_user?: string; 29 | server?: string; 30 | url?: string; 31 | } 32 | 33 | @Injectable() 34 | export class VantageLDAPService extends mixinHttp(class {}, { 35 | baseUrl: '/api/user/ldap/config', 36 | baseHeaders: new HttpHeaders({ Accept: 'application/json' }), 37 | }) { 38 | @TdGET({ 39 | path: '/', 40 | }) 41 | query(@TdResponse() response?: Observable): Observable { 42 | return response; 43 | } 44 | 45 | @TdPOST({ 46 | path: '/', 47 | }) 48 | create(@TdBody() body: ILDAPConfig, @TdResponse() response?: Observable): Observable { 49 | return response; 50 | } 51 | 52 | @TdPATCH({ 53 | path: '/:id', 54 | }) 55 | update( 56 | @TdParam('id') id: string | number, 57 | @TdBody() body: ILDAPConfig, 58 | @TdResponse() response?: Observable, 59 | ): Observable { 60 | return response; 61 | } 62 | 63 | @TdDELETE({ 64 | path: '/:id', 65 | }) 66 | delete(@TdParam('id') id: string | number, @TdResponse() response?: Observable): Observable { 67 | return response; 68 | } 69 | 70 | @TdPOST({ 71 | path: '/verify', 72 | options: { 73 | observe: 'response', 74 | }, 75 | }) 76 | test(@TdBody() body: ILDAPConfig, @TdResponse() response?: Observable): Observable { 77 | return response.pipe( 78 | map((res: any) => { 79 | return res.status === 200; 80 | }), 81 | ); 82 | } 83 | } 84 | 85 | export function VANTAGE_LDAP_PROVIDER_FACTORY(parent: VantageLDAPService): VantageLDAPService { 86 | return parent || new VantageLDAPService(); 87 | } 88 | 89 | export const VANTAGE_LDAP_PROVIDER: Provider = { 90 | // If there is already a service available, use that. Otherwise, provide a new one. 91 | provide: VantageLDAPService, 92 | deps: [[new Optional(), new SkipSelf(), VantageLDAPService]], 93 | useFactory: VANTAGE_LDAP_PROVIDER_FACTORY, 94 | }; 95 | -------------------------------------------------------------------------------- /src/lib/user/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/http": "covalent.http" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/user/public_api.ts: -------------------------------------------------------------------------------- 1 | export { VantageUserModule } from './user.module'; 2 | export { VantageLDAPService, LDAPEncription, ILDAPConfig } from './ldap/ldap.service'; 3 | export { VantageGroupService, IGroup } from './group/group.service'; 4 | export { VantageUserService, IUser } from './user/user.service'; 5 | -------------------------------------------------------------------------------- /src/lib/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VANTAGE_LDAP_PROVIDER } from './ldap/ldap.service'; 5 | import { VANTAGE_USER_PROVIDER } from './user/user.service'; 6 | import { VANTAGE_GROUP_PROVIDER } from './group/group.service'; 7 | 8 | @NgModule({ 9 | imports: [CommonModule], 10 | providers: [VANTAGE_LDAP_PROVIDER, VANTAGE_USER_PROVIDER, VANTAGE_GROUP_PROVIDER], 11 | }) 12 | export class VantageUserModule {} 13 | -------------------------------------------------------------------------------- /src/lib/user/user/user.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; 2 | import { HttpHeaders, HttpResponse, HttpParams } from '@angular/common/http'; 3 | import { TdGET, TdResponse, TdParam, TdQueryParams, mixinHttp } from '@covalent/http'; 4 | import { Observable, of } from 'rxjs'; 5 | import { map, catchError } from 'rxjs/operators'; 6 | 7 | export interface IUser { 8 | username?: string; 9 | password?: string; 10 | email?: string; 11 | local?: boolean; 12 | admin?: boolean; 13 | groups?: string[]; 14 | display_name?: string; 15 | access_token?: string; 16 | expires_at?: number; 17 | } 18 | 19 | @Injectable() 20 | export class VantageUserService extends mixinHttp(class {}, { 21 | baseUrl: '/api/user', 22 | baseHeaders: new HttpHeaders({ 23 | Accept: 'application/json', 24 | }), 25 | }) { 26 | /** 27 | * get all users 28 | */ 29 | @TdGET({ 30 | path: '/users', 31 | options: { 32 | observe: 'response', 33 | }, 34 | }) 35 | query( 36 | @TdQueryParams() queryParams?: HttpParams, 37 | @TdResponse() response?: Observable>, 38 | ): Observable<{ total: number; data: IUser[] }> { 39 | return response.pipe( 40 | catchError((error: Response) => { 41 | return of(error); 42 | }), 43 | map((res: HttpResponse) => { 44 | return { 45 | total: +res.headers.get('X-Total'), 46 | data: res.body, 47 | }; 48 | }), 49 | ); 50 | } 51 | 52 | /** 53 | * gets a single users information 54 | */ 55 | @TdGET({ 56 | path: '/users/:username', 57 | options: { 58 | observe: 'response', 59 | }, 60 | }) 61 | get(@TdParam('username') id: string, @TdResponse() response?: Observable>): Observable { 62 | return response.pipe( 63 | catchError((error: Response) => { 64 | return of(error); 65 | }), 66 | map((res: HttpResponse) => { 67 | return res.body; 68 | }), 69 | ); 70 | } 71 | } 72 | 73 | export function VANTAGE_USER_PROVIDER_FACTORY(parent: VantageUserService): VantageUserService { 74 | return parent || new VantageUserService(); 75 | } 76 | 77 | export const VANTAGE_USER_PROVIDER: Provider = { 78 | // If there is already a service available, use that. Otherwise, provide a new one. 79 | provide: VantageUserService, 80 | deps: [[new Optional(), new SkipSelf(), VantageUserService]], 81 | useFactory: VANTAGE_USER_PROVIDER_FACTORY, 82 | }; 83 | -------------------------------------------------------------------------------- /src/lib/utilities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './public_api'; 2 | -------------------------------------------------------------------------------- /src/lib/utilities/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "ngPackage": { 3 | "lib": { 4 | "entryFile": "index.ts", 5 | "umdModuleIds": { 6 | "@covalent/core/dialogs": "covalent.core.dialogs", 7 | "@covalent/core/media": "covalent.core.media", 8 | "@ngx-translate/core": "ngx-translate.core" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/lib/utilities/pre-loader/README.md: -------------------------------------------------------------------------------- 1 | # Pre loader 2 | 3 | A loader that can be displayed before the angular assets are downloaded and angular is ready. 4 | 5 | ## Setup 6 | 7 | `npm i -D @angular-builders/custom-webpack` 8 | 9 | Update the angular.json 10 | 11 | ```json 12 | "build": { 13 | "builder": "@angular-builders/custom-webpack:browser", 14 | "options": { 15 | "indexTransform": "node_modules/@td-vantage/ui-platform/utilities/pre-loader", 16 | ``` 17 | 18 | ```json 19 | "serve": { 20 | "builder": "@angular-builders/custom-webpack:dev-server", 21 | ``` 22 | 23 | That's it! The pre-loader markup will be inserted into the index html right before the closing body tag. 24 | -------------------------------------------------------------------------------- /src/lib/utilities/pre-loader/index.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const sass = require('sass'); 6 | 7 | module.exports = (targetOptions, originalIndexHtml) => { 8 | try { 9 | const preLoaderHtml = fs.readFileSync(path.join(__dirname, 'pre-loader.html'), { encoding: 'utf8' }).toString(); 10 | const preLoaderCss = sass 11 | .renderSync({ file: path.join(__dirname, 'pre-loader.scss'), includePaths: ['node_modules'] }) 12 | .css.toString(); 13 | const preLoaderHtmlWithCss = preLoaderHtml.replace('', ``); 14 | 15 | const closingBodyTag = ''; 16 | const closingBodyTagIndex = originalIndexHtml.indexOf(closingBodyTag); 17 | if (closingBodyTagIndex === -1) { 18 | throw new Error('Cannot find body tag to place pre-loader inside of'); 19 | } 20 | 21 | const newIndexHtml = `${originalIndexHtml.slice( 22 | 0, 23 | closingBodyTagIndex, 24 | )}${preLoaderHtmlWithCss}${originalIndexHtml.slice(closingBodyTagIndex)}`; 25 | return newIndexHtml; 26 | } catch (error) { 27 | console.error(error); 28 | return new Error(error); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/lib/utilities/pre-loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './pre-loader'; 2 | -------------------------------------------------------------------------------- /src/lib/utilities/pre-loader/pre-loader.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 32 | 33 | 78 | 79 |
84 | 85 | 86 | 87 |
88 |
89 | -------------------------------------------------------------------------------- /src/lib/utilities/pre-loader/pre-loader.scss: -------------------------------------------------------------------------------- 1 | @import '@angular/material/theming'; 2 | @import '../../theme/palette'; 3 | @import '../../theme/default-variables'; 4 | 5 | /* stylelint-disable selector-max-id */ 6 | #td-pre-loader { 7 | display: flex; 8 | overflow: hidden; 9 | justify-content: center; 10 | align-items: center; 11 | flex-direction: column; 12 | position: fixed; 13 | top: 0; 14 | right: 0; 15 | left: 0; 16 | bottom: 0; 17 | z-index: 10000; 18 | height: 100%; // for transition 19 | transition: opacity 0.125s 0s ease-in-out, height 0s 0.125s ease-in-out; 20 | 21 | /* light-theme */ 22 | background-color: map-get($mat-light-theme-background, background); 23 | 24 | /* LOGO */ 25 | .teradata-logo { 26 | overflow: visible; 27 | width: 300px; 28 | max-width: 95%; 29 | } 30 | 31 | .teradata-logo .teradata-logo-letters path { 32 | /* light-theme */ 33 | stroke: #354145; 34 | fill: #354145; 35 | } 36 | 37 | /* SPINNER */ 38 | .mat-spinner { 39 | margin-top: 1em; 40 | } 41 | 42 | .mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode='indeterminate'] { 43 | animation: mat-progress-spinner-linear-rotate 2s linear infinite; 44 | } 45 | 46 | .mat-progress-spinner { 47 | display: block; 48 | position: relative; 49 | width: 36px; 50 | height: 36px; 51 | } 52 | 53 | .mat-progress-spinner svg { 54 | position: absolute; 55 | transform: rotate(-90deg); 56 | top: 0; 57 | left: 0; 58 | transform-origin: center; 59 | overflow: visible; 60 | 61 | circle { 62 | animation-name: mat-progress-spinner-stroke-rotate-100; 63 | stroke-dasharray: 282.743px; 64 | stroke-width: 10%; 65 | } 66 | } 67 | 68 | .mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode='indeterminate'] circle { 69 | transition-property: stroke; 70 | animation-duration: 4s; 71 | animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1); 72 | animation-iteration-count: infinite; 73 | } 74 | .mat-progress-spinner circle { 75 | fill: transparent; 76 | transform-origin: center; 77 | transition: stroke-dashoffset 225ms linear; 78 | transition-property: stroke-dashoffset; 79 | } 80 | 81 | /* light-theme */ 82 | .mat-progress-spinner circle, 83 | .mat-spinner circle { 84 | stroke: map-get($td-accent, default); 85 | } 86 | 87 | @keyframes mat-progress-spinner-linear-rotate { 88 | 0% { 89 | transform: rotate(0); 90 | } 91 | 100% { 92 | transform: rotate(360deg); 93 | } 94 | } 95 | @keyframes mat-progress-spinner-stroke-rotate-100 { 96 | 0% { 97 | stroke-dashoffset: 268.60617px; 98 | transform: rotate(0); 99 | } 100 | 12.5% { 101 | stroke-dashoffset: 56.54867px; 102 | transform: rotate(0); 103 | } 104 | 12.5001% { 105 | stroke-dashoffset: 56.54867px; 106 | transform: rotateX(180deg) rotate(72.5deg); 107 | } 108 | 25% { 109 | stroke-dashoffset: 268.60617px; 110 | transform: rotateX(180deg) rotate(72.5deg); 111 | } 112 | 25.0001% { 113 | stroke-dashoffset: 268.60617px; 114 | transform: rotate(270deg); 115 | } 116 | 37.5% { 117 | stroke-dashoffset: 56.54867px; 118 | transform: rotate(270deg); 119 | } 120 | 37.5001% { 121 | stroke-dashoffset: 56.54867px; 122 | transform: rotateX(180deg) rotate(161.5deg); 123 | } 124 | 50% { 125 | stroke-dashoffset: 268.60617px; 126 | transform: rotateX(180deg) rotate(161.5deg); 127 | } 128 | 50.0001% { 129 | stroke-dashoffset: 268.60617px; 130 | transform: rotate(180deg); 131 | } 132 | 62.5% { 133 | stroke-dashoffset: 56.54867px; 134 | transform: rotate(180deg); 135 | } 136 | 62.5001% { 137 | stroke-dashoffset: 56.54867px; 138 | transform: rotateX(180deg) rotate(251.5deg); 139 | } 140 | 75% { 141 | stroke-dashoffset: 268.60617px; 142 | transform: rotateX(180deg) rotate(251.5deg); 143 | } 144 | 75.0001% { 145 | stroke-dashoffset: 268.60617px; 146 | transform: rotate(90deg); 147 | } 148 | 87.5% { 149 | stroke-dashoffset: 56.54867px; 150 | transform: rotate(90deg); 151 | } 152 | 87.5001% { 153 | stroke-dashoffset: 56.54867px; 154 | transform: rotateX(180deg) rotate(341.5deg); 155 | } 156 | 100% { 157 | stroke-dashoffset: 268.60617px; 158 | transform: rotateX(180deg) rotate(341.5deg); 159 | } 160 | } 161 | } 162 | 163 | .dark-theme #td-pre-loader { 164 | /* dark-theme */ 165 | background-color: map-get($mat-dark-theme-background, background); 166 | 167 | /* dark-theme */ 168 | .mat-progress-spinner circle, 169 | .mat-spinner circle { 170 | stroke: map-get($td-dark-accent, default); 171 | } 172 | 173 | /* dark-theme */ 174 | .teradata-logo .teradata-logo-letters path { 175 | stroke: white; 176 | fill: white; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/lib/utilities/pre-loader/pre-loader.ts: -------------------------------------------------------------------------------- 1 | // TD_PRE_LOADER_COUNT variable is defined inside pre-loader.html 2 | 3 | export function showPreLoader(): void { 4 | if ((window).TD_PRE_LOADER_COUNT !== undefined) { 5 | (window).TD_PRE_LOADER_COUNT++; 6 | updatePreLoaderVisibility(); 7 | } 8 | } 9 | 10 | export function hidePreLoader(): void { 11 | if ((window).TD_PRE_LOADER_COUNT !== undefined) { 12 | (window).TD_PRE_LOADER_COUNT--; 13 | updatePreLoaderVisibility(); 14 | } 15 | } 16 | 17 | function updatePreLoaderVisibility(): void { 18 | const loader: HTMLElement = document.getElementById('td-pre-loader'); 19 | if (loader) { 20 | loader.style.height = (window).TD_PRE_LOADER_COUNT > 0 ? '100%' : '0'; 21 | loader.style.opacity = (window).TD_PRE_LOADER_COUNT > 0 ? '1' : '0'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/utilities/public_api.ts: -------------------------------------------------------------------------------- 1 | export * from './user-feedback/index'; 2 | export * from './pre-loader/index'; 3 | -------------------------------------------------------------------------------- /src/lib/utilities/user-feedback/error/error.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; 2 | 3 | import { MatDialogRef } from '@angular/material/dialog'; 4 | 5 | import { TdDialogService, IAlertConfig, TdAlertDialogComponent } from '@covalent/core/dialogs'; 6 | 7 | import { TranslateService } from '@ngx-translate/core'; 8 | 9 | export class VantageError { 10 | message: string; 11 | error: number; 12 | } 13 | 14 | @Injectable() 15 | export class VantageErrorService { 16 | constructor(private _dialogService: TdDialogService, private _translate: TranslateService) {} 17 | 18 | open(error: VantageError): MatDialogRef { 19 | if (error) { 20 | const config: IAlertConfig = { 21 | id: 'vui-error-dialog' + (error.error !== undefined ? `-${error.error.toString()}` : ''), 22 | panelClass: 'vui-error-dialog', 23 | title: this._translate.instant('THERE_WAS_A_PROBLEM'), 24 | message: error.message, 25 | disableClose: true, 26 | closeButton: this._translate.instant('CLOSE'), 27 | }; 28 | if (error.error) { 29 | config.message += ` (${error.error.toString()})`; 30 | } 31 | if (config.message || config.title) { 32 | return this._dialogService.openAlert(config); 33 | } 34 | } 35 | } 36 | } 37 | 38 | export function VANTAGE_ERROR_PROVIDER_FACTORY( 39 | parent: VantageErrorService, 40 | dialogService: TdDialogService, 41 | translate: TranslateService, 42 | ): VantageErrorService { 43 | return parent || new VantageErrorService(dialogService, translate); 44 | } 45 | 46 | export const VANTAGE_ERROR_PROVIDER: Provider = { 47 | // If there is already a service available, use that. Otherwise, provide a new one. 48 | provide: VantageErrorService, 49 | deps: [[new Optional(), new SkipSelf(), VantageErrorService], TdDialogService, TranslateService], 50 | useFactory: VANTAGE_ERROR_PROVIDER_FACTORY, 51 | }; 52 | -------------------------------------------------------------------------------- /src/lib/utilities/user-feedback/index.ts: -------------------------------------------------------------------------------- 1 | export { VantageErrorService, VantageError } from './error/error.service'; 2 | export { VantageToastService } from './toast/toast.service'; 3 | export { VantageUserFeedbackModule } from './user-feedback.module'; 4 | -------------------------------------------------------------------------------- /src/lib/utilities/user-feedback/toast/toast.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Provider, Optional, SkipSelf } from '@angular/core'; 2 | 3 | import { MatSnackBar } from '@angular/material/snack-bar'; 4 | 5 | import { TdMediaService } from '@covalent/core/media'; 6 | 7 | @Injectable() 8 | export class VantageToastService { 9 | constructor(private _snackBarService: MatSnackBar, private _media: TdMediaService) {} 10 | 11 | open(message: string, time: number = 3000): void { 12 | if (message) { 13 | this._snackBarService.open(message, undefined, { 14 | duration: time, 15 | horizontalPosition: this._media && this._media.query('gt-sm') ? 'end' : 'center', 16 | }); 17 | } 18 | } 19 | } 20 | 21 | export function VANTAGE_TOAST_PROVIDER_FACTORY( 22 | parent: VantageToastService, 23 | snackBar: MatSnackBar, 24 | media: TdMediaService, 25 | ): VantageToastService { 26 | return parent || new VantageToastService(snackBar, media); 27 | } 28 | 29 | export const VANTAGE_TOAST_PROVIDER: Provider = { 30 | // If there is already a service available, use that. Otherwise, provide a new one. 31 | provide: VantageToastService, 32 | deps: [[new Optional(), new SkipSelf(), VantageToastService], MatSnackBar, [new Optional(), TdMediaService]], 33 | useFactory: VANTAGE_TOAST_PROVIDER_FACTORY, 34 | }; 35 | -------------------------------------------------------------------------------- /src/lib/utilities/user-feedback/user-feedback.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { CommonModule } from '@angular/common'; 4 | 5 | import { MatSnackBarModule } from '@angular/material/snack-bar'; 6 | 7 | import { CovalentDialogsModule } from '@covalent/core/dialogs'; 8 | import { CovalentMediaModule } from '@covalent/core/media'; 9 | 10 | import { VANTAGE_ERROR_PROVIDER } from './error/error.service'; 11 | import { VANTAGE_TOAST_PROVIDER } from './toast/toast.service'; 12 | 13 | @NgModule({ 14 | imports: [CommonModule, MatSnackBarModule, CovalentDialogsModule, CovalentMediaModule], 15 | providers: [VANTAGE_ERROR_PROVIDER, VANTAGE_TOAST_PROVIDER], 16 | }) 17 | export class VantageUserFeedbackModule {} 18 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /*tslint:disable*/ 2 | /** 3 | * This file includes polyfills needed by Angular and is loaded before the app. 4 | * You can add your own extra polyfills to this file. 5 | * 6 | * This file is divided into 2 sections: 7 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 8 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 9 | * file. 10 | * 11 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 12 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 13 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 14 | * 15 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 16 | */ 17 | 18 | /*************************************************************************************************** 19 | * BROWSER POLYFILLS 20 | */ 21 | 22 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 23 | // import 'core-js/es6/symbol'; 24 | // import 'core-js/es6/object'; 25 | // import 'core-js/es6/function'; 26 | // import 'core-js/es6/parse-int'; 27 | // import 'core-js/es6/parse-float'; 28 | // import 'core-js/es6/number'; 29 | // import 'core-js/es6/math'; 30 | // import 'core-js/es6/string'; 31 | // import 'core-js/es6/date'; 32 | // import 'core-js/es6/array'; 33 | // import 'core-js/es6/regexp'; 34 | // import 'core-js/es6/map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following to support `@angular/animation`. */ 41 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 42 | 43 | /** Evergreen browsers require these. **/ 44 | import 'core-js/es6/reflect'; 45 | 46 | import 'core-js/es7/reflect'; 47 | 48 | /** ALL Firefox browsers require the following to support `@angular/animation`. **/ 49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 50 | 51 | /*************************************************************************************************** 52 | * Zone JS is required by Angular itself. 53 | */ 54 | import 'zone.js/dist/zone'; // Included with Angular-CLI. 55 | 56 | /*************************************************************************************************** 57 | * APPLICATION IMPORTS 58 | */ 59 | 60 | /** 61 | * Date, currency, decimal and percent pipes. 62 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 63 | */ 64 | // import 'intl'; // Run `npm install --save intl`. 65 | -------------------------------------------------------------------------------- /src/theme.scss: -------------------------------------------------------------------------------- 1 | @import '~@angular/material/theming'; 2 | @import '~@covalent/core/theming/all-theme'; 3 | @import '~@covalent/markdown/markdown-theme'; 4 | @import '~@covalent/highlight/highlight-theme'; 5 | // Plus imports for other components in your app. 6 | 7 | // Include the base styles for Angular Material core. We include this here so that you only 8 | // have to load a single css file for Angular Material in your app. 9 | @include mat-core(); 10 | 11 | // Teradata brand 12 | @import './lib/theming'; 13 | 14 | // Include the core styles for Covalent 15 | @include covalent-core(); 16 | 17 | // Include material icons 18 | @import '../node_modules/@covalent/core/common/material-icons.css'; 19 | 20 | // Include covalent utility classes 21 | @include covalent-utilities(); 22 | 23 | // Include flex layout classes 24 | @include covalent-layout(); 25 | 26 | // Include covalent color classes 27 | @include covalent-colors(); 28 | 29 | // Define the palettes for your theme using the Material Design palettes available in palette.scss 30 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker 31 | // hue. 32 | $primary: $td-primary; 33 | $accent: $td-accent; 34 | $warn: $td-warn; 35 | 36 | // Create the theme object (a Sass map containing all of the palettes). 37 | $theme: mat-light-theme($primary, $accent, $warn); 38 | 39 | // Include theme styles for core and each component used in your app. 40 | // Alternatively, you can import and @include the theme mixins for each component 41 | // that you are using. 42 | @include angular-material-theme($theme); 43 | @include covalent-theme($theme); 44 | @include covalent-markdown-theme($theme); 45 | @include covalent-highlight-theme(); 46 | // Include Teradata brand 47 | @include teradata-brand($theme); 48 | 49 | /* ------------------------------------- DARK THEME ------------------------------------------ */ 50 | 51 | .dark-theme { 52 | $dark-primary: $td-dark-primary; 53 | $dark-accent: $td-dark-accent; 54 | $dark-warn: $td-dark-warn; 55 | 56 | $dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn); 57 | 58 | @include angular-material-theme($dark-theme); 59 | @include covalent-theme($dark-theme); 60 | 61 | @include covalent-markdown-theme($dark-theme); 62 | // Include Teradata brand 63 | @include teradata-brand($dark-theme); 64 | } 65 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | // Typings reference file, see links for more information 2 | // https://github.com/typings/typings 3 | // https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html 4 | 5 | declare var System: any; 6 | declare var require: any; 7 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['./node_modules/@covalent/coding-standards/stylelint/stylelint.config.js'], 3 | }; 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "emitDecoratorMetadata": true, 10 | "esModuleInterop": true, 11 | "experimentalDecorators": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "importHelpers": true, 15 | "target": "es2015", 16 | "typeRoots": ["node_modules/@types"], 17 | "lib": ["es2018", "dom"], 18 | "paths": { 19 | "@td-vantage/ui-platform": ["./src/lib"], 20 | "@td-vantage/ui-platform/*": ["./src/lib/*"] 21 | }, 22 | "noUnusedParameters": false, 23 | "noUnusedLocals": false, 24 | "allowUnreachableCode": false, 25 | "pretty": true 26 | }, 27 | "include": ["src/lib/testing/cypress/**/*.ts", "./node_modules/cypress"] 28 | } 29 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["./node_modules/@covalent/coding-standards/tslint/tslint.js"] 3 | } 4 | --------------------------------------------------------------------------------