Added TS Unit Testing, TS Lint, Yarn package management.
Using this new structure, developers can rebuild, test, and lint individually, saving time an effort in the event of a failure. Added Frontend unit testing alongside a more modular module design to make components and services easier to test and easy to manage dependencies for. Adding Yarn for more performant package management Change-Id: I56a57100b5d831bb31bc18e2c62c78bf63265324
This commit is contained in:
parent
93fc1b1ac8
commit
8f426a0bb2
192
Makefile
192
Makefile
@ -13,8 +13,8 @@ WEBDIR := client
|
|||||||
LINTER := $(TOOLBINDIR)/golangci-lint
|
LINTER := $(TOOLBINDIR)/golangci-lint
|
||||||
LINTER_CONFIG := .golangci.yaml
|
LINTER_CONFIG := .golangci.yaml
|
||||||
NODEJS_BIN := $(realpath tools)/node-v12.16.3/bin
|
NODEJS_BIN := $(realpath tools)/node-v12.16.3/bin
|
||||||
NPM := $(NODEJS_BIN)/npm
|
|
||||||
NG := $(NODEJS_BIN)/ng
|
NG := $(NODEJS_BIN)/ng
|
||||||
|
YARN := $(NODEJS_BIN)/yarn
|
||||||
|
|
||||||
# docker
|
# docker
|
||||||
DOCKER_MAKE_TARGET := build
|
DOCKER_MAKE_TARGET := build
|
||||||
@ -65,44 +65,127 @@ endif
|
|||||||
DIRS = internal
|
DIRS = internal
|
||||||
RECURSIVE_DIRS = $(addprefix ./, $(addsuffix /..., $(DIRS)))
|
RECURSIVE_DIRS = $(addprefix ./, $(addsuffix /..., $(DIRS)))
|
||||||
|
|
||||||
|
### Composite Make Commands ###
|
||||||
|
|
||||||
|
.PHONY: $(MAIN)
|
||||||
|
$(MAIN): build
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(NPM) $(MAIN)
|
build: frontend-build
|
||||||
$(MAIN): FORCE
|
build: backend-build
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: tidy-lint
|
||||||
|
lint: check-copyright-lint
|
||||||
|
lint: whitespace-lint
|
||||||
|
lint: frontend-lint
|
||||||
|
lint: backend-lint
|
||||||
|
|
||||||
|
.PHONY: unit-test
|
||||||
|
test: frontend-unit-test
|
||||||
|
test: backend-unit-test
|
||||||
|
|
||||||
|
.PHONY: coverage
|
||||||
|
coverage: frontend-coverage
|
||||||
|
coverage: backend-coverage
|
||||||
|
|
||||||
|
.PHONY: verify
|
||||||
|
verify: build
|
||||||
|
verify: coverage
|
||||||
|
verify: lint
|
||||||
|
|
||||||
|
### Backend (Go) Make Commands ###
|
||||||
|
|
||||||
|
.PHONY: backend-build
|
||||||
|
backend-build:
|
||||||
|
@echo "Executing backend build steps..."
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NPM) install) && cd ..
|
@go build -o $(MAIN)$(EXTENSION) $(GO_FLAGS) cmd/main.go
|
||||||
cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NG) build) && cd ..
|
@echo "Backend build completed successfully"
|
||||||
go build -o $(MAIN)$(EXTENSION) $(GO_FLAGS) cmd/main.go
|
|
||||||
|
|
||||||
FORCE:
|
.PHONY: backend-unit-test
|
||||||
|
backend-unit-test:
|
||||||
.PHONY: examples
|
@echo "Performing backend unit test step..."
|
||||||
examples: $(NPM) $(EXAMPLES)
|
|
||||||
$(EXAMPLES): FORCE
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
cd $(WEBDIR) && npm install && cd ..
|
|
||||||
cd $(WEBDIR) && ng build && cd ..
|
|
||||||
go build -o $@$(EXTENSION) $(GO_FLAGS) examples/$(@F)/main.go
|
|
||||||
|
|
||||||
.PHONY: install-octant-plugins
|
|
||||||
install-octant-plugins:
|
|
||||||
@mkdir -p $(OCTANT_PLUGINSTUB_DIR)
|
|
||||||
cp $(addsuffix $(EXTENSION), $(BUILD_DIR)/octant) $(OCTANT_PLUGINSTUB_DIR)
|
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
test: lint
|
|
||||||
test: cover
|
|
||||||
test: check-copyright
|
|
||||||
|
|
||||||
.PHONY: unit-tests
|
|
||||||
unit-tests:
|
|
||||||
@echo "Performing unit test step..."
|
|
||||||
@go test -run $(TESTS) $(PKG) $(TESTFLAGS) $(COVER_FLAGS)
|
@go test -run $(TESTS) $(PKG) $(TESTFLAGS) $(COVER_FLAGS)
|
||||||
@echo "All unit tests passed"
|
@echo "Backend unit tests completed successfully"
|
||||||
|
|
||||||
.PHONY: cover
|
.PHONY: backend-coverage
|
||||||
cover: TESTFLAGS = -covermode=atomic -coverprofile=fullcover.out
|
backend-coverage: TESTFLAGS = -covermode=atomic -coverprofile=fullcover.out
|
||||||
cover: unit-tests
|
backend-coverage: backend-unit-test
|
||||||
|
@echo "Generating backend coverage report..."
|
||||||
@grep -vE "$(COVER_EXCLUDE)" fullcover.out > $(COVER_PROFILE)
|
@grep -vE "$(COVER_EXCLUDE)" fullcover.out > $(COVER_PROFILE)
|
||||||
|
@echo "Backend coverage report completed successfully"
|
||||||
|
|
||||||
|
.PHONY: backend-lint
|
||||||
|
backend-lint: $(LINTER)
|
||||||
|
backend-lint:
|
||||||
|
@echo "Running backend linting step..."
|
||||||
|
@$(LINTER) run --config $(LINTER_CONFIG)
|
||||||
|
@echo "Backend linting completed successfully"
|
||||||
|
|
||||||
|
### Frontend (Angular) Make Commands ###
|
||||||
|
|
||||||
|
.PHONY: frontend-build
|
||||||
|
frontend-build: $(YARN)
|
||||||
|
frontend-build:
|
||||||
|
@echo "Executing frontend build steps..."
|
||||||
|
@cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NG) build) && cd ..
|
||||||
|
@echo "Frontend build completed successfully"
|
||||||
|
|
||||||
|
.PHONY: frontend-unit-test
|
||||||
|
frontend-unit-test: $(YARN)
|
||||||
|
frontend-unit-test:
|
||||||
|
@echo "Performing frontend unit test step..."
|
||||||
|
@cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NG) test) && cd ..
|
||||||
|
@echo "Frontend unit tests completed successfully"
|
||||||
|
|
||||||
|
.PHONY: frontend-coverage
|
||||||
|
frontend-coverage: frontend-unit-test
|
||||||
|
|
||||||
|
.PHONY: frontend-lint
|
||||||
|
frontend-lint: $(YARN)
|
||||||
|
frontend-lint:
|
||||||
|
@echo "Running frontend linting step..."
|
||||||
|
@cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NG) lint) && cd ..
|
||||||
|
@echo "Frontend linting completed successfully"
|
||||||
|
|
||||||
|
### Misc. Linting Commands ###
|
||||||
|
|
||||||
|
.PHONY: whitespace-lint
|
||||||
|
whitespace-lint:
|
||||||
|
@echo "Running whitespace linting step..."
|
||||||
|
@./tools/whitespace_linter
|
||||||
|
@echo "Whitespace linting completed successfully"
|
||||||
|
|
||||||
|
.PHONY: tidy-lint
|
||||||
|
tidy-lint:
|
||||||
|
@echo "Checking that go.mod is up to date..."
|
||||||
|
@./tools/gomod_check
|
||||||
|
@echo "go.mod check completed successfully"
|
||||||
|
|
||||||
|
# check-copyright is a utility to check if copyright header is present on all files
|
||||||
|
.PHONY: check-copyright-lint
|
||||||
|
check-copyright-lint:
|
||||||
|
@echo "Checking file for copyright statement..."
|
||||||
|
@./tools/check_copyright
|
||||||
|
@echo "Copyright check completed successfully"
|
||||||
|
|
||||||
|
### Helper Installations ###
|
||||||
|
|
||||||
|
$(LINTER):
|
||||||
|
@echo "Installing Go linter..."
|
||||||
|
@mkdir -p $(TOOLBINDIR)
|
||||||
|
./tools/install_go_linter
|
||||||
|
@echo "Go linter installation completed successfully"
|
||||||
|
|
||||||
|
$(YARN):
|
||||||
|
@echo "Installing Node.js, npm, yarn & project packages..."
|
||||||
|
@mkdir -p $(TOOLBINDIR)
|
||||||
|
./tools/install_npm
|
||||||
|
@cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(YARN) install) && cd ..
|
||||||
|
@echo "Node.js, npm, yarn, and project package installation completed successfully"
|
||||||
|
|
||||||
|
### Docker ###
|
||||||
|
|
||||||
.PHONY: images
|
.PHONY: images
|
||||||
images: docker-image
|
images: docker-image
|
||||||
@ -142,7 +225,7 @@ docker-image-test-suite: DOCKER_TARGET_STAGE = builder
|
|||||||
docker-image-test-suite: docker-image
|
docker-image-test-suite: docker-image
|
||||||
|
|
||||||
.PHONY: docker-image-unit-tests
|
.PHONY: docker-image-unit-tests
|
||||||
docker-image-unit-tests: DOCKER_MAKE_TARGET = cover
|
docker-image-unit-tests: DOCKER_MAKE_TARGET = coverage
|
||||||
docker-image-unit-tests: DOCKER_TARGET_STAGE = builder
|
docker-image-unit-tests: DOCKER_TARGET_STAGE = builder
|
||||||
docker-image-unit-tests: docker-image
|
docker-image-unit-tests: docker-image
|
||||||
|
|
||||||
@ -153,11 +236,9 @@ docker-image-lint: docker-image
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
@echo "Removing build directories..."
|
||||||
rm -rf $(BUILD_DIR) $(COVERAGE_OUTPUT)
|
rm -rf $(BUILD_DIR) $(COVERAGE_OUTPUT)
|
||||||
|
@echo "Removal completed successfully"
|
||||||
.PHONY: docs
|
|
||||||
docs:
|
|
||||||
tox
|
|
||||||
|
|
||||||
# The golang-unit zuul job calls the env target, so create one
|
# The golang-unit zuul job calls the env target, so create one
|
||||||
# Note: on windows if there is a WSL curl in c:\windows\system32
|
# Note: on windows if there is a WSL curl in c:\windows\system32
|
||||||
@ -165,40 +246,11 @@ docs:
|
|||||||
# The use of cygwin curl is working however
|
# The use of cygwin curl is working however
|
||||||
.PHONY: env
|
.PHONY: env
|
||||||
|
|
||||||
.PHONY: lint
|
### Helper Make Commands ###
|
||||||
lint: tidy $(NPM) $(LINTER)
|
|
||||||
@echo "Performing linting steps..."
|
|
||||||
@echo "Running whitespace linting step..."
|
|
||||||
@./tools/whitespace_linter
|
|
||||||
@echo "Running golangci-lint linting step..."
|
|
||||||
$(LINTER) run --config $(LINTER_CONFIG)
|
|
||||||
# TODO: Replace eslint with TS lint
|
|
||||||
# @echo "Installing NPM & running client linting step..."
|
|
||||||
# ./tools/install_npm
|
|
||||||
# cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NPM) install) && cd ..
|
|
||||||
# cd $(WEBDIR) && (PATH="$(PATH):$(NODEJS_BIN)"; $(NG) build) && cd ..
|
|
||||||
@echo "Linting completed successfully"
|
|
||||||
|
|
||||||
.PHONY: tidy
|
|
||||||
tidy:
|
|
||||||
@echo "Checking that go.mod is up to date..."
|
|
||||||
@./tools/gomod_check
|
|
||||||
@echo "go.mod is up to date"
|
|
||||||
|
|
||||||
$(LINTER):
|
|
||||||
@mkdir -p $(TOOLBINDIR)
|
|
||||||
./tools/install_go_linter
|
|
||||||
|
|
||||||
$(NPM):
|
|
||||||
@mkdir -p $(TOOLBINDIR)
|
|
||||||
./tools/install_npm
|
|
||||||
|
|
||||||
# add-copyright is a utility to add copyright header to missing files
|
# add-copyright is a utility to add copyright header to missing files
|
||||||
.PHONY: add-copyright
|
.PHONY: add-copyright
|
||||||
add-copyright:
|
add-copyright:
|
||||||
|
@echo "Adding copyright license to necessary files..."
|
||||||
@./tools/add_license.sh
|
@./tools/add_license.sh
|
||||||
|
@echo "Copyright license additions completed successfully"
|
||||||
# check-copyright is a utility to check if copyright header is present on all files
|
|
||||||
.PHONY: check-copyright
|
|
||||||
check-copyright:
|
|
||||||
@./tools/check_copyright
|
|
||||||
|
@ -79,46 +79,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
"builder": "@angular-builders/jest:run",
|
||||||
"options": {
|
"options": {}
|
||||||
"main": "src/test.ts",
|
|
||||||
"polyfills": "src/polyfills.ts",
|
|
||||||
"tsConfig": "tsconfig.spec.json",
|
|
||||||
"karmaConfig": "karma.conf.js",
|
|
||||||
"assets": [
|
|
||||||
"src/favicon.ico",
|
|
||||||
"src/assets"
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"src/styles.css"
|
|
||||||
],
|
|
||||||
"scripts": []
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
"options": {
|
"options": {
|
||||||
"tsConfig": [
|
"tsConfig": [
|
||||||
"tsconfig.app.json",
|
"tsconfig.app.json",
|
||||||
"tsconfig.spec.json",
|
"tsconfig.spec.json"
|
||||||
"e2e/tsconfig.json"
|
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"**/node_modules/**"
|
"**/node_modules/**"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"e2e": {
|
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
|
||||||
"options": {
|
|
||||||
"protractorConfig": "e2e/protractor.conf.js",
|
|
||||||
"devServerTarget": "airshipui:serve"
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"devServerTarget": "airshipui:serve:production"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
// Protractor configuration file, see link for more information
|
|
||||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
|
||||||
|
|
||||||
const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type { import("protractor").Config }
|
|
||||||
*/
|
|
||||||
exports.config = {
|
|
||||||
allScriptsTimeout: 11000,
|
|
||||||
specs: [
|
|
||||||
'./src/**/*.e2e-spec.ts'
|
|
||||||
],
|
|
||||||
capabilities: {
|
|
||||||
browserName: 'chrome'
|
|
||||||
},
|
|
||||||
directConnect: true,
|
|
||||||
baseUrl: 'http://localhost:4200/',
|
|
||||||
framework: 'jasmine',
|
|
||||||
jasmineNodeOpts: {
|
|
||||||
showColors: true,
|
|
||||||
defaultTimeoutInterval: 30000,
|
|
||||||
print: function() {}
|
|
||||||
},
|
|
||||||
onPrepare() {
|
|
||||||
require('ts-node').register({
|
|
||||||
project: require('path').join(__dirname, './tsconfig.json')
|
|
||||||
});
|
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({
|
|
||||||
spec: {
|
|
||||||
displayStacktrace: StacktraceOption.PRETTY
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,23 +0,0 @@
|
|||||||
import { AppPage } from './app.po';
|
|
||||||
import { browser, logging } from 'protractor';
|
|
||||||
|
|
||||||
describe('workspace-project App', () => {
|
|
||||||
let page: AppPage;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
page = new AppPage();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display welcome message', () => {
|
|
||||||
page.navigateTo();
|
|
||||||
expect(page.getTitleText()).toEqual('airshipui-ui app is running!');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
// Assert that there are no errors emitted from the browser
|
|
||||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
|
||||||
expect(logs).not.toContain(jasmine.objectContaining({
|
|
||||||
level: logging.Level.SEVERE,
|
|
||||||
} as logging.Entry));
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
import { browser, by, element } from 'protractor';
|
|
||||||
|
|
||||||
export class AppPage {
|
|
||||||
navigateTo(): Promise<unknown> {
|
|
||||||
return browser.get(browser.baseUrl) as Promise<unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTitleText(): Promise<string> {
|
|
||||||
return element(by.css('app-root .content span')).getText() as Promise<string>;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../out-tsc/e2e",
|
|
||||||
"module": "commonjs",
|
|
||||||
"target": "es2018",
|
|
||||||
"types": [
|
|
||||||
"jasmine",
|
|
||||||
"jasminewd2",
|
|
||||||
"node"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
4
client/jest.config.js
Normal file
4
client/jest.config.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
coverageReporters: ['html', 'text', 'text-summary']
|
||||||
|
};
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
// Karma configuration file, see link for more information
|
|
||||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
|
||||||
|
|
||||||
module.exports = function (config) {
|
|
||||||
config.set({
|
|
||||||
basePath: '',
|
|
||||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
|
||||||
plugins: [
|
|
||||||
require('karma-jasmine'),
|
|
||||||
require('karma-chrome-launcher'),
|
|
||||||
require('karma-jasmine-html-reporter'),
|
|
||||||
require('karma-coverage-istanbul-reporter'),
|
|
||||||
require('@angular-devkit/build-angular/plugins/karma')
|
|
||||||
],
|
|
||||||
client: {
|
|
||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
|
||||||
},
|
|
||||||
coverageIstanbulReporter: {
|
|
||||||
dir: require('path').join(__dirname, './coverage/airshipui-ui'),
|
|
||||||
reports: ['html', 'lcovonly', 'text-summary'],
|
|
||||||
fixWebpackSourcePaths: true
|
|
||||||
},
|
|
||||||
reporters: ['progress', 'kjhtml'],
|
|
||||||
port: 9876,
|
|
||||||
colors: true,
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
autoWatch: true,
|
|
||||||
browsers: ['Chrome'],
|
|
||||||
singleRun: false,
|
|
||||||
restartOnFileChange: true
|
|
||||||
});
|
|
||||||
};
|
|
13771
client/package-lock.json
generated
13771
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -6,8 +6,7 @@
|
|||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
"lint": "ng lint",
|
"lint": "ng lint"
|
||||||
"e2e": "ng e2e"
|
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -23,7 +22,6 @@
|
|||||||
"@angular/platform-browser-dynamic": "~10.0.3",
|
"@angular/platform-browser-dynamic": "~10.0.3",
|
||||||
"@angular/router": "~10.0.3",
|
"@angular/router": "~10.0.3",
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
"monaco-editor": "^0.20.0",
|
|
||||||
"ngx-monaco-editor": "^9.0.0",
|
"ngx-monaco-editor": "^9.0.0",
|
||||||
"ngx-toastr": "^13.0.0",
|
"ngx-toastr": "^13.0.0",
|
||||||
"rxjs": "~6.5.5",
|
"rxjs": "~6.5.5",
|
||||||
@ -31,22 +29,17 @@
|
|||||||
"zone.js": "~0.10.3"
|
"zone.js": "~0.10.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@angular-builders/jest": "^10.0.0",
|
||||||
"@angular-devkit/build-angular": "~0.1000.2",
|
"@angular-devkit/build-angular": "~0.1000.2",
|
||||||
"@angular/cli": "~10.0.2",
|
"@angular/cli": "~10.0.2",
|
||||||
"@angular/compiler-cli": "~10.0.3",
|
"@angular/compiler-cli": "~10.0.3",
|
||||||
"@types/jasmine": "~3.5.0",
|
"@types/jest": "^26.0.9",
|
||||||
"@types/jasminewd2": "~2.0.3",
|
|
||||||
"@types/node": "^12.11.1",
|
"@types/node": "^12.11.1",
|
||||||
"codelyzer": "^6.0.0",
|
"codelyzer": "^6.0.0",
|
||||||
"eslint-plugin-html": "^6.0.3",
|
"eslint-plugin-html": "^6.0.3",
|
||||||
"jasmine-core": "~3.5.0",
|
"jest": "^26.2.2",
|
||||||
"jasmine-spec-reporter": "~5.0.0",
|
"jest-preset-angular": "^8.2.1",
|
||||||
"karma": "~5.0.0",
|
"ts-jest": "^26.1.4",
|
||||||
"karma-chrome-launcher": "~3.1.0",
|
|
||||||
"karma-coverage-istanbul-reporter": "~3.0.2",
|
|
||||||
"karma-jasmine": "~3.3.0",
|
|
||||||
"karma-jasmine-html-reporter": "^1.5.0",
|
|
||||||
"protractor": "~7.0.0",
|
|
||||||
"ts-node": "~8.3.0",
|
"ts-node": "~8.3.0",
|
||||||
"tslint": "~6.1.0",
|
"tslint": "~6.1.0",
|
||||||
"typescript": "~3.9.5"
|
"typescript": "~3.9.5"
|
||||||
|
@ -1,31 +1,17 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
import { HomeComponent } from './home/home.component';
|
import {HomeComponent} from './home/home.component';
|
||||||
import { DashboardsComponent } from './dashboards/dashboards.component';
|
import {CtlComponent} from './ctl/ctl.component';
|
||||||
import { CTLComponent } from './ctl/ctl.component';
|
|
||||||
import { BareMetalComponent } from './ctl/baremetal/baremetal.component';
|
|
||||||
import { DocumentComponent } from './ctl/document/document.component';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
const routes: Routes = [{
|
||||||
path: 'ctl',
|
path: 'ctl',
|
||||||
component: CTLComponent,
|
component: CtlComponent,
|
||||||
children: [
|
loadChildren: './ctl/ctl.module#CtlModule',
|
||||||
{
|
}, {
|
||||||
path: 'baremetal',
|
|
||||||
component: BareMetalComponent
|
|
||||||
}, {
|
|
||||||
path: 'documents',
|
|
||||||
component: DocumentComponent
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
path: 'dashboard',
|
|
||||||
component: DashboardsComponent
|
|
||||||
}, {
|
|
||||||
path: '',
|
path: '',
|
||||||
component: HomeComponent
|
component: HomeComponent
|
||||||
},
|
}];
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes)],
|
imports: [RouterModule.forRoot(routes)],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<mat-sidenav-container class="sidenav-container">
|
<mat-sidenav-container class="sidenav-container">
|
||||||
<mat-sidenav class="sidenav-content" #snav [mode]="'side'" opened="true">
|
<mat-sidenav class="sidenav-content" #sidenav [mode]="'side'" opened="true">
|
||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
<svg width="249" height="46">
|
<svg width="249" height="46">
|
||||||
<use xlink:href="assets/logo/airship-horizontal-logo.svg#Layer_1"></use>
|
<use xlink:href="assets/logo/airship-horizontal-logo.svg#Layer_1"></use>
|
||||||
@ -55,7 +55,7 @@
|
|||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content>
|
<mat-sidenav-content>
|
||||||
<mat-toolbar color="primary" class="toolbar-header">
|
<mat-toolbar color="primary" class="toolbar-header">
|
||||||
<button mat-icon-button (click)="snav.toggle()"><mat-icon svgIcon="list"></mat-icon></button>
|
<button mat-icon-button (click)="sidenav.toggle()"><mat-icon svgIcon="list"></mat-icon></button>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<button mat-icon-button><mat-icon svgIcon="account"></mat-icon></button>
|
<button mat-icon-button><mat-icon svgIcon="account"></mat-icon></button>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should create the app', () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should have as title 'airshipui-ui'`, () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect('airshipui-ui').toEqual('airshipui-ui');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render title', () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
fixture.detectChanges();
|
|
||||||
const compiled = fixture.nativeElement;
|
|
||||||
expect(compiled.querySelector('.content span').textContent).toContain('airshipui-ui app is running!');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,11 +1,9 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import { NavInterface } from './models/nav.interface';
|
import {environment} from '../environments/environment';
|
||||||
import { environment } from '../environments/environment';
|
import {IconService} from '../services/icon/icon.service';
|
||||||
import { IconService } from '../services/icon/icon.service';
|
import {WebsocketService} from '../services/websocket/websocket.service';
|
||||||
import { WebsocketService } from '../services/websocket/websocket.service';
|
import {Dashboard, WebsocketMessage, WSReceiver} from '../services/websocket/websocket.models';
|
||||||
import { WSReceiver } from '../services/websocket/websocket.models';
|
import {Nav} from './app.models';
|
||||||
import { Dashboard } from '../services/websocket/models/websocket-message/dashboard/dashboard';
|
|
||||||
import { WebsocketMessage } from 'src/services/websocket/models/websocket-message/websocket-message';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -13,13 +11,13 @@ import { WebsocketMessage } from 'src/services/websocket/models/websocket-messag
|
|||||||
styleUrls: ['./app.component.css']
|
styleUrls: ['./app.component.css']
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit, WSReceiver {
|
export class AppComponent implements OnInit, WSReceiver {
|
||||||
type: string = "ui";
|
type = 'ui';
|
||||||
component: string = "any";
|
component = 'any';
|
||||||
|
|
||||||
currentYear: number;
|
currentYear: number;
|
||||||
version: string;
|
version: string;
|
||||||
|
|
||||||
menu: NavInterface [] = [
|
menu: Nav [] = [
|
||||||
{
|
{
|
||||||
displayName: 'Airship',
|
displayName: 'Airship',
|
||||||
iconName: 'airplane',
|
iconName: 'airplane',
|
||||||
@ -46,14 +44,14 @@ export class AppComponent implements OnInit, WSReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async receiver(message: WebsocketMessage): Promise<void> {
|
async receiver(message: WebsocketMessage): Promise<void> {
|
||||||
if (message.hasOwnProperty("error")) {
|
if (message.hasOwnProperty('error')) {
|
||||||
this.websocketService.printIfToast(message);
|
this.websocketService.printIfToast(message);
|
||||||
} else {
|
} else {
|
||||||
if (message.hasOwnProperty("dashboards")) {
|
if (message.hasOwnProperty('dashboards')) {
|
||||||
this.updateDashboards(message.dashboards);
|
this.updateDashboards(message.dashboards);
|
||||||
} else {
|
} else {
|
||||||
// TODO (aschiefe): determine what should be notifications and what should be 86ed
|
// TODO (aschiefe): determine what should be notifications and what should be 86ed
|
||||||
console.log("Message received in app: ", message);
|
console.log('Message received in app: ', message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +65,7 @@ export class AppComponent implements OnInit, WSReceiver {
|
|||||||
this.menu[1].children = [];
|
this.menu[1].children = [];
|
||||||
}
|
}
|
||||||
dashboards.forEach((dashboard) => {
|
dashboards.forEach((dashboard) => {
|
||||||
const navInterface = new NavInterface();
|
const navInterface = new Nav();
|
||||||
navInterface.displayName = dashboard.name;
|
navInterface.displayName = dashboard.name;
|
||||||
navInterface.route = dashboard.baseURL;
|
navInterface.route = dashboard.baseURL;
|
||||||
navInterface.external = true;
|
navInterface.external = true;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
export class NavInterface {
|
export class Nav {
|
||||||
displayName: string;
|
displayName: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
iconName?: string;
|
iconName?: string;
|
||||||
route?: string;
|
route?: string;
|
||||||
external?: boolean;
|
external?: boolean;
|
||||||
children?: NavInterface[];
|
children?: Nav[];
|
||||||
}
|
}
|
@ -1,65 +1,45 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
|
import {AppRoutingModule} from './app-routing.module';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import {AppComponent} from './app.component';
|
||||||
import { AppComponent } from './app.component';
|
import {RouterModule} from '@angular/router';
|
||||||
|
import {HttpClientModule} from '@angular/common/http';
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import {WebsocketService} from '../services/websocket/websocket.service';
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
import {ToastrModule} from 'ngx-toastr';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import {MonacoEditorModule} from 'ngx-monaco-editor';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import {MatSidenavModule} from '@angular/material/sidenav';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import {MatIconModule} from '@angular/material/icon';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import {MatExpansionModule} from '@angular/material/expansion';
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import {FlexLayoutModule} from '@angular/flex-layout';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
import {MatListModule} from '@angular/material/list';
|
||||||
import { MatExpansionModule } from '@angular/material/expansion';
|
import {MatToolbarModule} from '@angular/material/toolbar';
|
||||||
import { RouterModule } from '@angular/router';
|
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
import { CTLComponent } from './ctl/ctl.component';
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
import { DashboardsComponent } from './dashboards/dashboards.component';
|
import {MatTabsModule} from '@angular/material/tabs';
|
||||||
import { HomeComponent } from './home/home.component';
|
import {CtlModule} from './ctl/ctl.module';
|
||||||
import { BareMetalComponent } from './ctl/baremetal/baremetal.component';
|
|
||||||
import { DocumentComponent } from './ctl/document/document.component';
|
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
|
||||||
import { WebsocketService } from '../services/websocket/websocket.service';
|
|
||||||
import { ToastrModule } from 'ngx-toastr';
|
|
||||||
import {FormsModule} from '@angular/forms';
|
|
||||||
import {MonacoEditorModule, NgxMonacoEditorConfig } from 'ngx-monaco-editor';
|
|
||||||
import {MatTreeModule} from '@angular/material/tree';
|
|
||||||
import {MatButtonToggleModule} from '@angular/material/button-toggle';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
CTLComponent,
|
|
||||||
DashboardsComponent,
|
|
||||||
HomeComponent,
|
|
||||||
BareMetalComponent,
|
|
||||||
DocumentComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
|
|
||||||
|
CtlModule,
|
||||||
|
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
FlexLayoutModule,
|
FlexLayoutModule,
|
||||||
FormsModule,
|
|
||||||
MatToolbarModule,
|
|
||||||
MatSidenavModule,
|
|
||||||
MatListModule,
|
|
||||||
MatIconModule,
|
|
||||||
MatButtonModule,
|
|
||||||
MatTableModule,
|
|
||||||
MatCheckboxModule,
|
|
||||||
MatExpansionModule,
|
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatSidenavModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatExpansionModule,
|
||||||
|
MatListModule,
|
||||||
|
MatToolbarModule,
|
||||||
RouterModule,
|
RouterModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
ToastrModule.forRoot(),
|
ToastrModule.forRoot(),
|
||||||
MonacoEditorModule.forRoot(),
|
MonacoEditorModule.forRoot(),
|
||||||
MatTreeModule,
|
|
||||||
MatButtonToggleModule,
|
|
||||||
],
|
],
|
||||||
|
declarations: [AppComponent],
|
||||||
providers: [WebsocketService],
|
providers: [WebsocketService],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -1,20 +1,27 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
import {BaremetalComponent} from './baremetal.component';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {ToastrModule} from 'ngx-toastr';
|
||||||
|
|
||||||
import { BareMetalComponent } from './baremetal.component';
|
describe('BaremetalComponent', () => {
|
||||||
|
let component: BaremetalComponent;
|
||||||
describe('BareMetalComponent', () => {
|
let fixture: ComponentFixture<BaremetalComponent>;
|
||||||
let component: BareMetalComponent;
|
|
||||||
let fixture: ComponentFixture<BareMetalComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ BareMetalComponent ]
|
imports: [
|
||||||
|
MatButtonModule,
|
||||||
|
ToastrModule.forRoot()
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
BaremetalComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(BareMetalComponent);
|
fixture = TestBed.createComponent(BaremetalComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import {WebsocketMessage} from '../../../services/websocket/models/websocket-message/websocket-message';
|
|
||||||
import {WebsocketService} from '../../../services/websocket/websocket.service';
|
import {WebsocketService} from '../../../services/websocket/websocket.service';
|
||||||
import { WSReceiver } from '../../../services/websocket//websocket.models';
|
import {WebsocketMessage, WSReceiver} from '../../../services/websocket/websocket.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bare-metal',
|
selector: 'app-bare-metal',
|
||||||
@ -9,25 +8,25 @@ import { WSReceiver } from '../../../services/websocket//websocket.models';
|
|||||||
styleUrls: ['./baremetal.component.css']
|
styleUrls: ['./baremetal.component.css']
|
||||||
})
|
})
|
||||||
|
|
||||||
export class BareMetalComponent implements WSReceiver {
|
export class BaremetalComponent implements WSReceiver {
|
||||||
// TODO (aschiefe): extract these strings to constants
|
// TODO (aschiefe): extract these strings to constants
|
||||||
type: string = "ctl";
|
type = 'ctl';
|
||||||
component: string = "baremetal";
|
component = 'baremetal';
|
||||||
|
|
||||||
constructor(private websocketService: WebsocketService) {
|
constructor(private websocketService: WebsocketService) {
|
||||||
this.websocketService.registerFunctions(this);
|
this.websocketService.registerFunctions(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async receiver(message: WebsocketMessage): Promise<void> {
|
async receiver(message: WebsocketMessage): Promise<void> {
|
||||||
if (message.hasOwnProperty("error")) {
|
if (message.hasOwnProperty('error')) {
|
||||||
this.websocketService.printIfToast(message);
|
this.websocketService.printIfToast(message);
|
||||||
} else {
|
} else {
|
||||||
// TODO (aschiefe): determine what should be notifications and what should be 86ed
|
// TODO (aschiefe): determine what should be notifications and what should be 86ed
|
||||||
console.log("Message received in baremetal: ", message);
|
console.log('Message received in baremetal: ', message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateIso(): void {
|
generateIso(): void {
|
||||||
this.websocketService.sendMessage(new WebsocketMessage(this.type, this.component, "generateISO"));
|
this.websocketService.sendMessage(new WebsocketMessage(this.type, this.component, 'generateISO'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
client/src/app/ctl/baremetal/baremetal.module.ts
Normal file
14
client/src/app/ctl/baremetal/baremetal.module.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {BaremetalComponent} from './baremetal.component';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
MatButtonModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
BaremetalComponent
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class BaremetalModule {}
|
18
client/src/app/ctl/ctl-routing.module.ts
Normal file
18
client/src/app/ctl/ctl-routing.module.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
|
import {DocumentComponent} from './document/document.component';
|
||||||
|
import {BaremetalComponent} from './baremetal/baremetal.component';
|
||||||
|
|
||||||
|
const routes: Routes = [{
|
||||||
|
path: 'documents',
|
||||||
|
component: DocumentComponent,
|
||||||
|
}, {
|
||||||
|
path: 'baremetal',
|
||||||
|
component: BaremetalComponent
|
||||||
|
}];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class CtlRoutingModule {}
|
28
client/src/app/ctl/ctl.component.spec.ts
Normal file
28
client/src/app/ctl/ctl.component.spec.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
import {CtlComponent} from './ctl.component';
|
||||||
|
import {RouterTestingModule} from '@angular/router/testing';
|
||||||
|
|
||||||
|
describe('CtlComponent', () => {
|
||||||
|
let component: CtlComponent;
|
||||||
|
let fixture: ComponentFixture<CtlComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
|
declarations: [CtlComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(CtlComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -1,10 +1,9 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-airship',
|
selector: 'app-ctl',
|
||||||
templateUrl: './ctl.component.html',
|
templateUrl: './ctl.component.html',
|
||||||
styleUrls: ['./ctl.component.css']
|
styleUrls: ['./ctl.component.css']
|
||||||
})
|
})
|
||||||
export class CTLComponent {
|
export class CtlComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
19
client/src/app/ctl/ctl.module.ts
Normal file
19
client/src/app/ctl/ctl.module.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {RouterModule} from '@angular/router';
|
||||||
|
import {CtlComponent} from './ctl.component';
|
||||||
|
import {DocumentModule} from './document/document.module';
|
||||||
|
import {BaremetalModule} from './baremetal/baremetal.module';
|
||||||
|
import {CtlRoutingModule} from './ctl-routing.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CtlRoutingModule,
|
||||||
|
|
||||||
|
RouterModule,
|
||||||
|
DocumentModule,
|
||||||
|
BaremetalModule
|
||||||
|
],
|
||||||
|
declarations: [ CtlComponent ],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class CtlModule {}
|
@ -1,25 +0,0 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { CTLComponent } from './ctl.component';
|
|
||||||
|
|
||||||
describe('CTLComponent', () => {
|
|
||||||
let component: CTLComponent;
|
|
||||||
let fixture: ComponentFixture<CTLComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ CTLComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(CTLComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,6 +1,14 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
import {DocumentComponent} from './document.component';
|
||||||
import { DocumentComponent } from './document.component';
|
import {MatTabsModule} from '@angular/material/tabs';
|
||||||
|
import {MatTreeModule} from '@angular/material/tree';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {MatButtonToggleModule} from '@angular/material/button-toggle';
|
||||||
|
import {MatIconModule} from '@angular/material/icon';
|
||||||
|
import {MonacoEditorModule} from 'ngx-monaco-editor';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
import {ToastrModule} from 'ngx-toastr';
|
||||||
|
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
describe('DocumentComponent', () => {
|
describe('DocumentComponent', () => {
|
||||||
let component: DocumentComponent;
|
let component: DocumentComponent;
|
||||||
@ -8,7 +16,18 @@ describe('DocumentComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ DocumentComponent ]
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
MatTabsModule,
|
||||||
|
MatTreeModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatButtonToggleModule,
|
||||||
|
MatIconModule,
|
||||||
|
MonacoEditorModule,
|
||||||
|
FormsModule,
|
||||||
|
ToastrModule.forRoot()
|
||||||
|
],
|
||||||
|
declarations: [DocumentComponent]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import {WebsocketService} from '../../../services/websocket/websocket.service';
|
import {WebsocketService} from '../../../services/websocket/websocket.service';
|
||||||
import { WSReceiver } from '../../../services/websocket/websocket.models';
|
import {WebsocketMessage, WSReceiver} from '../../../services/websocket/websocket.models';
|
||||||
import {WebsocketMessage} from '../../../services/websocket/models/websocket-message/websocket-message';
|
|
||||||
import {KustomNode} from './kustom-node';
|
|
||||||
import {NestedTreeControl} from '@angular/cdk/tree';
|
import {NestedTreeControl} from '@angular/cdk/tree';
|
||||||
import {MatTreeNestedDataSource} from '@angular/material/tree';
|
import {MatTreeNestedDataSource} from '@angular/material/tree';
|
||||||
|
import {KustomNode} from './document.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-document',
|
selector: 'app-document',
|
||||||
@ -15,30 +14,31 @@ import {MatTreeNestedDataSource} from '@angular/material/tree';
|
|||||||
export class DocumentComponent implements WSReceiver {
|
export class DocumentComponent implements WSReceiver {
|
||||||
obby: string;
|
obby: string;
|
||||||
|
|
||||||
type: string = 'ctl';
|
type = 'ctl';
|
||||||
component: string = 'document';
|
component = 'document';
|
||||||
|
|
||||||
activeLink = 'overview';
|
activeLink = 'overview';
|
||||||
|
|
||||||
obj: KustomNode[] = [];
|
obj: KustomNode[] = [];
|
||||||
currentDocId: string;
|
currentDocId: string;
|
||||||
|
|
||||||
saveBtnDisabled: boolean = true;
|
saveBtnDisabled = true;
|
||||||
hideButtons: boolean = true;
|
hideButtons = true;
|
||||||
isRendered: boolean = false;
|
isRendered = false;
|
||||||
|
|
||||||
editorOptions = {language: 'yaml', automaticLayout: true, value: ''};
|
editorOptions = {language: 'yaml', automaticLayout: true, value: ''};
|
||||||
code: string;
|
code: string;
|
||||||
editorTitle: string;
|
editorTitle: string;
|
||||||
onInit(editor) {
|
|
||||||
editor.onDidChangeModelContent(() => {
|
|
||||||
this.saveBtnDisabled = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
treeControl = new NestedTreeControl<KustomNode>(node => node.children);
|
treeControl = new NestedTreeControl<KustomNode>(node => node.children);
|
||||||
dataSource = new MatTreeNestedDataSource<KustomNode>();
|
dataSource = new MatTreeNestedDataSource<KustomNode>();
|
||||||
|
|
||||||
|
onInit(editor): void {
|
||||||
|
editor.onDidChangeModelContent(() => {
|
||||||
|
this.saveBtnDisabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
constructor(private websocketService: WebsocketService) {
|
constructor(private websocketService: WebsocketService) {
|
||||||
this.websocketService.registerFunctions(this);
|
this.websocketService.registerFunctions(this);
|
||||||
this.getSource(); // load the source first
|
this.getSource(); // load the source first
|
||||||
@ -47,7 +47,7 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
hasChild = (_: number, node: KustomNode) => !!node.children && node.children.length > 0;
|
hasChild = (_: number, node: KustomNode) => !!node.children && node.children.length > 0;
|
||||||
|
|
||||||
public async receiver(message: WebsocketMessage): Promise<void> {
|
public async receiver(message: WebsocketMessage): Promise<void> {
|
||||||
if (message.hasOwnProperty("error")) {
|
if (message.hasOwnProperty('error')) {
|
||||||
this.websocketService.printIfToast(message);
|
this.websocketService.printIfToast(message);
|
||||||
} else {
|
} else {
|
||||||
switch (message.subComponent) {
|
switch (message.subComponent) {
|
||||||
@ -69,11 +69,7 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
this.changeEditorContents((message.yaml));
|
this.changeEditorContents((message.yaml));
|
||||||
this.editorTitle = message.name;
|
this.editorTitle = message.name;
|
||||||
this.currentDocId = message.message;
|
this.currentDocId = message.message;
|
||||||
if (!this.isRendered) {
|
this.hideButtons = this.isRendered;
|
||||||
this.hideButtons = false;
|
|
||||||
} else {
|
|
||||||
this.hideButtons = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'yamlWrite':
|
case 'yamlWrite':
|
||||||
this.changeEditorContents((message.yaml));
|
this.changeEditorContents((message.yaml));
|
||||||
@ -81,10 +77,10 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
this.currentDocId = message.message;
|
this.currentDocId = message.message;
|
||||||
break;
|
break;
|
||||||
case 'docPull':
|
case 'docPull':
|
||||||
this.obby = "Message pull was a " + message.message;
|
this.obby = 'Message pull was a ' + message.message;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log("Document message sub component not handled: ", message);
|
console.log('Document message sub component not handled: ', message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +88,7 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
|
|
||||||
getYaml(id: string): void {
|
getYaml(id: string): void {
|
||||||
this.code = null;
|
this.code = null;
|
||||||
const websocketMessage = this.constructDocumentWsMessage("getYaml");
|
const websocketMessage = this.constructDocumentWsMessage('getYaml');
|
||||||
websocketMessage.message = id;
|
websocketMessage.message = id;
|
||||||
this.websocketService.sendMessage(websocketMessage);
|
this.websocketService.sendMessage(websocketMessage);
|
||||||
}
|
}
|
||||||
@ -102,7 +98,7 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveYaml(): void {
|
saveYaml(): void {
|
||||||
const websocketMessage = this.constructDocumentWsMessage("yamlWrite");
|
const websocketMessage = this.constructDocumentWsMessage('yamlWrite');
|
||||||
websocketMessage.message = this.currentDocId;
|
websocketMessage.message = this.currentDocId;
|
||||||
websocketMessage.name = this.editorTitle;
|
websocketMessage.name = this.editorTitle;
|
||||||
websocketMessage.yaml = btoa(this.code);
|
websocketMessage.yaml = btoa(this.code);
|
||||||
@ -111,13 +107,13 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
|
|
||||||
getSource(): void {
|
getSource(): void {
|
||||||
this.isRendered = false;
|
this.isRendered = false;
|
||||||
const websocketMessage = this.constructDocumentWsMessage("getSource");
|
const websocketMessage = this.constructDocumentWsMessage('getSource');
|
||||||
this.websocketService.sendMessage(websocketMessage);
|
this.websocketService.sendMessage(websocketMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRendered(): void {
|
getRendered(): void {
|
||||||
this.isRendered = true;
|
this.isRendered = true;
|
||||||
const websocketMessage = this.constructDocumentWsMessage("getRendered");
|
const websocketMessage = this.constructDocumentWsMessage('getRendered');
|
||||||
this.websocketService.sendMessage(websocketMessage);
|
this.websocketService.sendMessage(websocketMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,12 +123,12 @@ export class DocumentComponent implements WSReceiver {
|
|||||||
|
|
||||||
closeEditor(): void {
|
closeEditor(): void {
|
||||||
this.code = null;
|
this.code = null;
|
||||||
this.editorTitle = "";
|
this.editorTitle = '';
|
||||||
this.hideButtons = true;
|
this.hideButtons = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
documentPull(): void {
|
documentPull(): void {
|
||||||
this.websocketService.sendMessage(new WebsocketMessage(this.type, this.component, "docPull"));
|
this.websocketService.sendMessage(new WebsocketMessage(this.type, this.component, 'docPull'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,4 +3,4 @@ export class KustomNode {
|
|||||||
name: string;
|
name: string;
|
||||||
data: string;
|
data: string;
|
||||||
children: KustomNode[];
|
children: KustomNode[];
|
||||||
}
|
}
|
30
client/src/app/ctl/document/document.module.ts
Normal file
30
client/src/app/ctl/document/document.module.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {MatTabsModule} from '@angular/material/tabs';
|
||||||
|
import {DocumentComponent} from './document.component';
|
||||||
|
import {MatTreeModule} from '@angular/material/tree';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {MatButtonToggleModule} from '@angular/material/button-toggle';
|
||||||
|
import {MatIconModule} from '@angular/material/icon';
|
||||||
|
import {MonacoEditorModule} from 'ngx-monaco-editor';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
import {ToastrModule} from 'ngx-toastr';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
DocumentComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MatTabsModule,
|
||||||
|
MatTreeModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatButtonToggleModule,
|
||||||
|
MatIconModule,
|
||||||
|
MonacoEditorModule,
|
||||||
|
FormsModule,
|
||||||
|
ToastrModule,
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class DocumentModule {}
|
@ -1 +0,0 @@
|
|||||||
<p>dashboards works!</p>
|
|
@ -1,25 +0,0 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { DashboardsComponent } from './dashboards.component';
|
|
||||||
|
|
||||||
describe('DashboardsComponent', () => {
|
|
||||||
let component: DashboardsComponent;
|
|
||||||
let fixture: ComponentFixture<DashboardsComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ DashboardsComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(DashboardsComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-dashboards',
|
|
||||||
templateUrl: './dashboards.component.html',
|
|
||||||
styleUrls: ['./dashboards.component.css']
|
|
||||||
})
|
|
||||||
export class DashboardsComponent {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrls: ['./home.component.css']
|
styleUrls: ['./home.component.css']
|
||||||
})
|
})
|
||||||
export class HomeComponent implements OnInit {
|
export class HomeComponent {}
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import { Dashboard } from './dashboard';
|
|
||||||
|
|
||||||
describe('Dashboard', () => {
|
|
||||||
it('should create an instance', () => {
|
|
||||||
expect(new Dashboard()).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,6 +0,0 @@
|
|||||||
export class Dashboard {
|
|
||||||
name: string;
|
|
||||||
baseURL: string;
|
|
||||||
path: string;
|
|
||||||
isProxied: boolean;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { WebsocketMessage } from './websocket-message';
|
|
||||||
|
|
||||||
describe('WebsocketMessage', () => {
|
|
||||||
it('should create an instance', () => {
|
|
||||||
expect(new WebsocketMessage()).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,25 +0,0 @@
|
|||||||
import {Dashboard} from './dashboard/dashboard';
|
|
||||||
|
|
||||||
export class WebsocketMessage {
|
|
||||||
type: string;
|
|
||||||
component: string;
|
|
||||||
subComponent: string;
|
|
||||||
timestamp: number;
|
|
||||||
dashboards: Dashboard[];
|
|
||||||
error: string;
|
|
||||||
fade: boolean;
|
|
||||||
html: string;
|
|
||||||
name: string;
|
|
||||||
isAuthenticated: boolean;
|
|
||||||
message: string;
|
|
||||||
data: JSON;
|
|
||||||
yaml: string;
|
|
||||||
|
|
||||||
// this constructor looks like this in case anyone decides they want just a raw message with no data predefined
|
|
||||||
// or an easy way to specify the defaults
|
|
||||||
constructor (type?: string | undefined, component?: string | undefined, subComponent?: string | undefined) {
|
|
||||||
this.type = type;
|
|
||||||
this.component = component;
|
|
||||||
this.subComponent = subComponent;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,39 @@
|
|||||||
import { WebsocketMessage } from './models/websocket-message/websocket-message';
|
export interface WSReceiver {
|
||||||
|
// the holy trinity of the websocket messages, a triumvirate if you will, which is how all are routed
|
||||||
export interface WSReceiver {
|
type: string;
|
||||||
// the holy trinity of the websocket messages, a triumvirate if you will, which is how all are routed
|
component: string;
|
||||||
type: string;
|
|
||||||
component: string;
|
// This is the method which will need to be implemented in the component to handle the messages
|
||||||
|
receiver(message: WebsocketMessage): Promise<void>;
|
||||||
// This is the method which will need to be implemented in the component to handle the messages
|
}
|
||||||
receiver(message: WebsocketMessage): Promise<void>;
|
|
||||||
}
|
export class WebsocketMessage {
|
||||||
|
type: string;
|
||||||
|
component: string;
|
||||||
|
subComponent: string;
|
||||||
|
timestamp: number;
|
||||||
|
dashboards: Dashboard[];
|
||||||
|
error: string;
|
||||||
|
fade: boolean;
|
||||||
|
html: string;
|
||||||
|
name: string;
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
message: string;
|
||||||
|
data: JSON;
|
||||||
|
yaml: string;
|
||||||
|
|
||||||
|
// this constructor looks like this in case anyone decides they want just a raw message with no data predefined
|
||||||
|
// or an easy way to specify the defaults
|
||||||
|
constructor(type?: string | undefined, component?: string | undefined, subComponent?: string | undefined) {
|
||||||
|
this.type = type;
|
||||||
|
this.component = component;
|
||||||
|
this.subComponent = subComponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Dashboard {
|
||||||
|
name: string;
|
||||||
|
baseURL: string;
|
||||||
|
path: string;
|
||||||
|
isProxied: boolean;
|
||||||
|
}
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
import {WebsocketService} from './websocket.service';
|
||||||
import { WebsocketService } from './websocket.service';
|
import {ToastrModule} from 'ngx-toastr';
|
||||||
|
|
||||||
describe('WebsocketService', () => {
|
describe('WebsocketService', () => {
|
||||||
let service: WebsocketService;
|
let service: WebsocketService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({});
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
ToastrModule.forRoot(),
|
||||||
|
]
|
||||||
|
});
|
||||||
service = TestBed.inject(WebsocketService);
|
service = TestBed.inject(WebsocketService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import {Injectable, OnDestroy} from '@angular/core';
|
||||||
import { WebsocketMessage } from './models/websocket-message/websocket-message';
|
import {WebsocketMessage, WSReceiver} from './websocket.models';
|
||||||
import { WSReceiver } from './websocket.models';
|
import {ToastrService} from 'ngx-toastr';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -14,15 +13,14 @@ export class WebsocketService implements OnDestroy {
|
|||||||
|
|
||||||
// functionMap is how we know where to send the direct messages
|
// functionMap is how we know where to send the direct messages
|
||||||
// the structure of this map is: type -> component -> receiver
|
// the structure of this map is: type -> component -> receiver
|
||||||
private functionMap = new Map<string, Map<string,WSReceiver>>();
|
private functionMap = new Map<string, Map<string, WSReceiver>>();
|
||||||
|
|
||||||
// messageToObject unmarshalls the incoming message into a WebsocketMessage object
|
// messageToObject unmarshalls the incoming message into a WebsocketMessage object
|
||||||
private static messageToObject(incomingMessage: string): WebsocketMessage {
|
private static messageToObject(incomingMessage: string): WebsocketMessage {
|
||||||
let json = JSON.parse(incomingMessage);
|
const json = JSON.parse(incomingMessage);
|
||||||
let wsm = new WebsocketMessage();
|
const obj = new WebsocketMessage();
|
||||||
Object.assign(wsm, json);
|
Object.assign(obj, json);
|
||||||
|
return obj;
|
||||||
return wsm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// when the WebsocketService is created the toast message is initialized and a websocket is registered
|
// when the WebsocketService is created the toast message is initialized and a websocket is registered
|
||||||
@ -131,8 +129,8 @@ export class WebsocketService implements OnDestroy {
|
|||||||
this.functionMap[message.type][message.component].receiver(message);
|
this.functionMap[message.type][message.component].receiver(message);
|
||||||
} else {
|
} else {
|
||||||
// special case where we want to handle all top level messages at a specific component
|
// special case where we want to handle all top level messages at a specific component
|
||||||
if (this.functionMap[message.type].hasOwnProperty("any")) {
|
if (this.functionMap[message.type].hasOwnProperty('any')) {
|
||||||
this.functionMap[message.type]["any"].receiver(message);
|
this.functionMap[message.type].any.receiver(message);
|
||||||
} else {
|
} else {
|
||||||
this.printIfToast(message);
|
this.printIfToast(message);
|
||||||
}
|
}
|
||||||
@ -158,12 +156,12 @@ export class WebsocketService implements OnDestroy {
|
|||||||
|
|
||||||
// registerFunctions is a is called out of the target's constructor so it can auto populate the function map
|
// registerFunctions is a is called out of the target's constructor so it can auto populate the function map
|
||||||
public registerFunctions(target: WSReceiver): void {
|
public registerFunctions(target: WSReceiver): void {
|
||||||
let type = target.type;
|
const type = target.type;
|
||||||
let component = target.component;
|
const component = target.component;
|
||||||
if (this.functionMap.hasOwnProperty(type)) {
|
if (this.functionMap.hasOwnProperty(type)) {
|
||||||
this.functionMap[type][component] = target;
|
this.functionMap[type][component] = target;
|
||||||
} else {
|
} else {
|
||||||
let components = new Map<string,WSReceiver>();
|
const components = new Map<string, WSReceiver>();
|
||||||
components[component] = target;
|
components[component] = target;
|
||||||
this.functionMap[type] = components;
|
this.functionMap[type] = components;
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
|
||||||
|
|
||||||
import 'zone.js/dist/zone-testing';
|
|
||||||
import { getTestBed } from '@angular/core/testing';
|
|
||||||
import {
|
|
||||||
BrowserDynamicTestingModule,
|
|
||||||
platformBrowserDynamicTesting
|
|
||||||
} from '@angular/platform-browser-dynamic/testing';
|
|
||||||
|
|
||||||
declare const require: {
|
|
||||||
context(path: string, deep?: boolean, filter?: RegExp): {
|
|
||||||
keys(): string[];
|
|
||||||
<T>(id: string): T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// First, initialize the Angular testing environment.
|
|
||||||
getTestBed().initTestEnvironment(
|
|
||||||
BrowserDynamicTestingModule,
|
|
||||||
platformBrowserDynamicTesting()
|
|
||||||
);
|
|
||||||
// Then we find all the tests.
|
|
||||||
const context = require.context('./', true, /\.spec\.ts$/);
|
|
||||||
// And load the modules.
|
|
||||||
context.keys().map(context);
|
|
@ -1,6 +1,6 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
{
|
{
|
||||||
"extends": "./tsconfig.base.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./out-tsc/app",
|
"outDir": "./out-tsc/app",
|
||||||
"types": []
|
"types": []
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"compileOnSave": false,
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": "./",
|
|
||||||
"outDir": "./dist/out-tsc",
|
|
||||||
"sourceMap": true,
|
|
||||||
"declaration": false,
|
|
||||||
"downlevelIteration": true,
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"importHelpers": true,
|
|
||||||
"target": "es2015",
|
|
||||||
"module": "es2020",
|
|
||||||
"lib": [
|
|
||||||
"es2018",
|
|
||||||
"dom"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
|
|
||||||
It is not intended to be used to perform a compilation.
|
|
||||||
|
|
||||||
To learn more about this file see: https://angular.io/config/solution-tsconfig.
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
"files": [],
|
"compileOnSave": false,
|
||||||
"references": [
|
"compilerOptions": {
|
||||||
{
|
"baseUrl": "./",
|
||||||
"path": "./tsconfig.app.json"
|
"outDir": "./dist/out-tsc",
|
||||||
},
|
"sourceMap": true,
|
||||||
{
|
"declaration": false,
|
||||||
"path": "./tsconfig.spec.json"
|
"downlevelIteration": true,
|
||||||
},
|
"experimentalDecorators": true,
|
||||||
{
|
"moduleResolution": "node",
|
||||||
"path": "./e2e/tsconfig.json"
|
"importHelpers": true,
|
||||||
}
|
"target": "es2015",
|
||||||
]
|
"module": "es2020",
|
||||||
|
"lib": [
|
||||||
|
"es2018",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
{
|
{
|
||||||
"extends": "./tsconfig.base.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./out-tsc/spec",
|
"outDir": "./out-tsc/spec",
|
||||||
"types": [
|
"types": ["jest"],
|
||||||
"jasmine"
|
"emitDecoratorMetadata": true,
|
||||||
]
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src/test.ts",
|
|
||||||
"src/polyfills.ts"
|
"src/polyfills.ts"
|
||||||
],
|
],
|
||||||
"include": [
|
"include": [
|
||||||
|
9902
client/yarn.lock
Normal file
9902
client/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -113,7 +113,6 @@ func onMessage() {
|
|||||||
// common websocket close with logging
|
// common websocket close with logging
|
||||||
func onClose() {
|
func onClose() {
|
||||||
log.Printf("Closing websocket")
|
log.Printf("Closing websocket")
|
||||||
ws.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// common websocket error handling with logging
|
// common websocket error handling with logging
|
||||||
|
@ -44,16 +44,14 @@ if [[ ! -d $tools_bin_dir/node-$node_version ]]; then
|
|||||||
export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
|
export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# npm will write to a node_modules even with the --directory flag it's better to be in the root of where you want this to live
|
# angular-cli is required by angular build
|
||||||
cd client
|
if ! npm i -g @angular/cli; then
|
||||||
npm config set user "${npm_user}"
|
printf "Something went wrong while installing Angular CLI (ng)\n" 1>&2
|
||||||
if ! npm install eslint-plugin-html@latest --save-dev --production; then
|
|
||||||
printf "Something went wrong while installing eslint-plugin-html\n" 1>&2
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# angular-cli is required by angular build
|
# yarn is required by angular build
|
||||||
if ! npm i -g @angular/cli --production; then
|
if ! npm i -g yarn; then
|
||||||
printf "Something went wrong while installing ng\n" 1>&2
|
printf "Something went wrong while installing yarn\n" 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
cd ..
|
cd ..
|
||||||
|
Loading…
x
Reference in New Issue
Block a user