Compare commits
6
Commits
ef04d3dbea
...
09a66b1f58
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09a66b1f58 | ||
|
|
555b9d4532 | ||
|
|
30d336fed9 | ||
|
|
0d9340f220 | ||
|
|
935d8fc790 | ||
|
|
c281df00c7 |
@@ -0,0 +1,17 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1,46 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,27 @@
|
||||
# Cerberus
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.2.6.
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
||||
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"cerberus": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
},
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/cerberus",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"aot": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "cerberus:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "cerberus:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "cerberus:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "cerberus:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "cerberus:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "cerberus"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/cerberus'),
|
||||
subdir: '.',
|
||||
reporters: [
|
||||
{ type: 'html' },
|
||||
{ type: 'text-summary' }
|
||||
]
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
||||
Generated
+30907
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "cerberus",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --proxy-config proxy.conf.json",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~11.2.7",
|
||||
"@angular/cdk": "^11.2.13",
|
||||
"@angular/common": "~11.2.7",
|
||||
"@angular/compiler": "~11.2.7",
|
||||
"@angular/core": "~11.2.7",
|
||||
"@angular/forms": "~11.2.7",
|
||||
"@angular/material": "^11.2.13",
|
||||
"@angular/platform-browser": "~11.2.7",
|
||||
"@angular/platform-browser-dynamic": "~11.2.7",
|
||||
"@angular/router": "~11.2.7",
|
||||
"rxjs": "~6.6.0",
|
||||
"tslib": "^2.0.0",
|
||||
"zone.js": "~0.11.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.1102.6",
|
||||
"@angular/cli": "~11.2.6",
|
||||
"@angular/compiler-cli": "~11.2.7",
|
||||
"@types/jasmine": "~3.6.0",
|
||||
"@types/node": "^12.11.1",
|
||||
"codelyzer": "^6.0.0",
|
||||
"jasmine-core": "~3.6.0",
|
||||
"jasmine-spec-reporter": "~5.0.0",
|
||||
"karma": "~6.1.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage": "~2.0.3",
|
||||
"karma-jasmine": "~4.0.0",
|
||||
"karma-jasmine-html-reporter": "^1.5.0",
|
||||
"protractor": "~7.0.0",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~6.1.0",
|
||||
"typescript": "~4.1.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"/api": {
|
||||
"target": "http://localhost:8080",
|
||||
"secure": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<app-header></app-header>
|
||||
<div class="content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<app-modal></app-modal>
|
||||
@@ -0,0 +1,4 @@
|
||||
.content {
|
||||
margin-top: 56px;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
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 'cerberus'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('cerberus');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('.content span').textContent).toContain('cerberus app is running!');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'cerberus';
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppRoutingModule } from './app.routing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { SharedModule } from './core/shared.module';
|
||||
import { UiKitComponent } from './ui-kit/ui-kit.component';
|
||||
import { CreateApplicationComponent } from './applications/create-application/create-application.component';
|
||||
import { HeaderComponent } from './header/header.component';
|
||||
import { StatusComponent } from './applications/status/status.component';
|
||||
import { ApplicationCardComponent } from './core/components/application-card/application-card.component';
|
||||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
import { AddApplicationButtonComponent } from './core/components/add-application-button/add-application-button.component';
|
||||
import { ModalComponent } from './core/components/modal/modal.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeaderComponent,
|
||||
CreateApplicationComponent,
|
||||
UiKitComponent,
|
||||
StatusComponent,
|
||||
ApplicationCardComponent,
|
||||
AddApplicationButtonComponent,
|
||||
ModalComponent
|
||||
],
|
||||
imports: [
|
||||
RouterModule,
|
||||
SharedModule,
|
||||
AppRoutingModule,
|
||||
MatTooltipModule
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
@@ -0,0 +1,30 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { CreateApplicationComponent } from './applications/create-application/create-application.component';
|
||||
import { StatusComponent } from './applications/status/status.component';
|
||||
import { SharedModule } from './core/shared.module';
|
||||
import { UiKitComponent } from './ui-kit/ui-kit.component';
|
||||
|
||||
const ApplicationRoutes: Routes = [
|
||||
{
|
||||
path: 'uikit',
|
||||
component: UiKitComponent
|
||||
},
|
||||
{
|
||||
path: 'applications/add',
|
||||
component: CreateApplicationComponent
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
component: StatusComponent
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(ApplicationRoutes, { onSameUrlNavigation: 'reload' }),
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-applications',
|
||||
template: `
|
||||
<h1>Applications</h1>
|
||||
<!-- <router-outlet></router-outlet> -->
|
||||
`,
|
||||
})
|
||||
export class ApplicationsComponent implements OnInit {
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<div class="content">
|
||||
<h1>Add a new application</h1>
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit()" ngNativeValidate>
|
||||
<div class="form-control">
|
||||
<label for="name">Application name</label>
|
||||
<input id="name" formControlName="name" placeholder="Enter application name" required/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label for="service-name">Service name</label>
|
||||
<input id="service-name" formControlName="serviceName" placeholder="Enter service name" required/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label for="service-type">Type</label>
|
||||
<select id="service-type" formControlName="serviceType" placeholder="Enter service type">
|
||||
<option *ngFor="let type of serviceTypes" [value]="type.value">
|
||||
{{type.label}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label for="image">Image</label>
|
||||
<input id="image" formControlName="image" placeholder="Enter image url" required/>
|
||||
</div>
|
||||
<div class="row action">
|
||||
<button type="button" class="secondary" (click)="onCancel()">Cancel</button>
|
||||
<button type="submit">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
.content {
|
||||
width: 300px;
|
||||
margin: auto;
|
||||
|
||||
form {
|
||||
.action {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
width: 100px;
|
||||
flex: 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CreateApplicationComponent } from './create-application.component';
|
||||
|
||||
describe('CreateApplicationComponent', () => {
|
||||
let component: CreateApplicationComponent;
|
||||
let fixture: ComponentFixture<CreateApplicationComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CreateApplicationComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CreateApplicationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Application } from 'src/app/core/entities/Application';
|
||||
import { ReferentialData } from 'src/app/core/entities/ReferentialData';
|
||||
import { ApplicationService } from 'src/app/core/services/application.service';
|
||||
import { ModalService } from 'src/app/core/services/modal.service';
|
||||
import { ReferentialDataService } from 'src/app/core/services/referential-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-create-application',
|
||||
templateUrl: './create-application.component.html',
|
||||
styleUrls: ['./create-application.component.scss']
|
||||
})
|
||||
export class CreateApplicationComponent implements OnInit {
|
||||
form: FormGroup = this._formBuilder.group({
|
||||
name: [undefined, Validators.required],
|
||||
serviceName: [undefined, Validators.required],
|
||||
serviceType: [undefined, Validators.required],
|
||||
image: [undefined, Validators.required]
|
||||
});
|
||||
serviceTypes: ReferentialData[] = [];
|
||||
|
||||
constructor(
|
||||
private _formBuilder: FormBuilder,
|
||||
private _referentialDataService: ReferentialDataService,
|
||||
private _applicationService: ApplicationService,
|
||||
private _modalService: ModalService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this._referentialDataService.getServiceTypes()
|
||||
.then(serviceTypes => this.serviceTypes = serviceTypes)
|
||||
.catch(error => console.error('An error occured while loading service types.'));
|
||||
}
|
||||
|
||||
onSubmit(): void {
|
||||
if (this.form.valid) {
|
||||
const appToAdd: Application = this.form.value as Application;
|
||||
this._applicationService.add(appToAdd)
|
||||
.then(applicationAdded => console.log('Application added.'))
|
||||
.catch(error => console.error('An error occured while adding the new application.'));
|
||||
} else {
|
||||
console.error('Form is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
onCancel(): void {
|
||||
this._modalService.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class="application-list" *ngIf="applicationsStatus?.length; else noAnyApp">
|
||||
<app-application-card *ngFor="let applicationStatus of applicationsStatus" [applicationStatus]="applicationStatus"></app-application-card>
|
||||
</div>
|
||||
<ng-template #noAnyApp>
|
||||
<div class="no-any-app">
|
||||
<p>
|
||||
There is no any application.
|
||||
</p>
|
||||
<p>
|
||||
Add one by clicking here: <app-add-application-button></app-add-application-button>
|
||||
</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,22 @@
|
||||
@import '../../../colors.scss';
|
||||
|
||||
.application-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.no-any-app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: $gray-icon-secondary;
|
||||
|
||||
p {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Application } from 'src/app/core/entities/Application';
|
||||
import { ApplicationStatus } from 'src/app/core/entities/ApplicationStatus';
|
||||
import { ApplicationService } from 'src/app/core/services/application.service';
|
||||
import { ModalService } from 'src/app/core/services/modal.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-status',
|
||||
templateUrl: './status.component.html',
|
||||
styleUrls: ['./status.component.scss']
|
||||
})
|
||||
export class StatusComponent implements OnInit {
|
||||
applicationsStatus: ApplicationStatus[] = [];
|
||||
|
||||
constructor(
|
||||
private _applicationService: ApplicationService,
|
||||
private _modalService: ModalService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._applicationService.getAllStatus()
|
||||
.then(applicationsStatus => this.applicationsStatus = applicationsStatus);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CreateApplicationComponent } from 'src/app/applications/create-application/create-application.component';
|
||||
import { ModalService } from '../../services/modal.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-application-button',
|
||||
template: `
|
||||
<button type="button" (click)="onClick()" matTooltip="Add a new application to monitor">
|
||||
<mat-icon>add</mat-icon>
|
||||
Add
|
||||
</button>
|
||||
`
|
||||
})
|
||||
export class AddApplicationButtonComponent {
|
||||
constructor(
|
||||
private _modalService: ModalService
|
||||
) {}
|
||||
|
||||
onClick(): void {
|
||||
this._modalService.open(CreateApplicationComponent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<div class="application-card">
|
||||
<div class="logo">
|
||||
<img [src]="applicationStatus?.application?.image" />
|
||||
<div class="status {{applicationStatus?.status?.toLowerCase()}}" matTooltip="This application is running"></div>
|
||||
</div>
|
||||
<div class="name">{{applicationStatus?.application?.name}}</div>
|
||||
</div>
|
||||
@@ -0,0 +1,44 @@
|
||||
.application-card {
|
||||
margin: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.logo {
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
width: 164px;
|
||||
height: 164px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.status {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
|
||||
border-radius: 10em;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 5px;
|
||||
|
||||
&.started {
|
||||
background-image: linear-gradient(#5bc13e, #1fa200);
|
||||
border: 2px solid #136900;
|
||||
}
|
||||
&.stopped {
|
||||
background-image: linear-gradient(#c13e3e, #a20000);
|
||||
border: 2px solid #770000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.name {
|
||||
margin: .5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Application } from '../../entities/Application';
|
||||
import { ApplicationStatus } from '../../entities/ApplicationStatus';
|
||||
import { ApplicationService } from '../../services/application.service';
|
||||
|
||||
interface AppDisplaying {
|
||||
name: string,
|
||||
image: string,
|
||||
status: string
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-card',
|
||||
templateUrl: './application-card.component.html',
|
||||
styleUrls: ['./application-card.component.scss']
|
||||
})
|
||||
export class ApplicationCardComponent {
|
||||
@Input() applicationStatus: ApplicationStatus | undefined;
|
||||
|
||||
constructor(
|
||||
private _applicationService: ApplicationService
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<div id="modal-container" [class]="this.displayed ? 'displayed' : 'hidden'">
|
||||
<div id="overlay"></div>
|
||||
<div id="modal-frame" #modalFrame>
|
||||
<div id="modal-window">
|
||||
<div #modalContent></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,63 @@
|
||||
#modal-container {
|
||||
&.hidden {
|
||||
#overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#modal-frame {
|
||||
height: 0;
|
||||
|
||||
#modal-window {
|
||||
top: -500px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.displayed {
|
||||
display: flex;
|
||||
|
||||
#overlay {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#modal-frame {
|
||||
#modal-window {
|
||||
top: 58px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#overlay {
|
||||
position: fixed;
|
||||
top: 56px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#modal-frame {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 101;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
transition: height 1s ease;
|
||||
|
||||
#modal-window {
|
||||
position: absolute;
|
||||
background-color: #f6f6f6;
|
||||
z-index: 102;
|
||||
padding: 1rem;
|
||||
border: 1px solid #bfbfbf;
|
||||
border-top: none;
|
||||
min-width: 600px;
|
||||
max-height: 500px;
|
||||
box-shadow: inset 0px 5px 5px -3px rgba(0,0,0,.2), 0px 5px 10px 1px rgba(0,0,0,.2);
|
||||
transition: top 1s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Component, ComponentFactoryResolver, ElementRef, OnInit, Type, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { ModalService } from "../../services/modal.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-modal',
|
||||
templateUrl: './modal.component.html',
|
||||
styleUrls: ['./modal.component.scss']
|
||||
})
|
||||
export class ModalComponent implements OnInit {
|
||||
displayed: boolean = false;
|
||||
modalContentClass: Type<unknown> | undefined;
|
||||
@ViewChild('modalFrame', { static: true }) modalFrame: ElementRef<HTMLDivElement> | undefined;
|
||||
@ViewChild('modalContent', { read: ViewContainerRef }) modalContent: ViewContainerRef | undefined;
|
||||
|
||||
constructor(
|
||||
private _componentFactoryResolver: ComponentFactoryResolver,
|
||||
private _modalService: ModalService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._modalService.modalContent.subscribe(modalContentClass => {
|
||||
if (!modalContentClass) {
|
||||
this.displayed = false;
|
||||
window.setTimeout(() => {
|
||||
this.modalContent?.detach();
|
||||
}, 1000);
|
||||
} else {
|
||||
this.displayed = true;
|
||||
this.modalContent?.detach();
|
||||
const componentFactory = this._componentFactoryResolver.resolveComponentFactory(modalContentClass);
|
||||
this.modalContent?.createComponent<unknown>(componentFactory);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="container">
|
||||
<select #select>
|
||||
<option>Option 1</option>
|
||||
<option>Option 2</option>
|
||||
</select>
|
||||
<div class="icon">
|
||||
<mat-icon (click)="select.focus()">unfold_more</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
$btn-primary-background-top: #4ca4f6;
|
||||
$btn-primary-background-bottom: #0073f7;
|
||||
|
||||
$select-icon-radius: 4px;
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
select {
|
||||
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 1.5rem;
|
||||
background-image: linear-gradient($btn-primary-background-top, $btn-primary-background-bottom);
|
||||
color: white;
|
||||
height: 23px;
|
||||
top: 3px;
|
||||
right: 0;
|
||||
border-radius: 0 $select-icon-radius $select-icon-radius 0;
|
||||
|
||||
mat-icon {
|
||||
font-size: 19px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SelectComponent } from './select.component';
|
||||
|
||||
describe('SelectComponent', () => {
|
||||
let component: SelectComponent;
|
||||
let fixture: ComponentFixture<SelectComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ SelectComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SelectComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-select',
|
||||
templateUrl: './select.component.html',
|
||||
styleUrls: ['./select.component.scss']
|
||||
})
|
||||
export class SelectComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export interface Application {
|
||||
id: string;
|
||||
name: string;
|
||||
serviceName: string;
|
||||
serviceType: string;
|
||||
image: string;
|
||||
status: string;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { Application } from "./Application";
|
||||
|
||||
export interface ApplicationStatus {
|
||||
application: Application;
|
||||
status: string
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ReferentialData {
|
||||
value: string,
|
||||
label: string
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationService } from './application.service';
|
||||
|
||||
describe('ApplicationService', () => {
|
||||
let service: ApplicationService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(ApplicationService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Application } from '../entities/Application';
|
||||
import { ApplicationStatus } from '../entities/ApplicationStatus';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ApplicationService {
|
||||
|
||||
constructor(
|
||||
private _httpClient: HttpClient
|
||||
) {}
|
||||
|
||||
getAllStatus(): Promise<ApplicationStatus[]> {
|
||||
return this._httpClient.get<ApplicationStatus[]>('/api/applications/status').toPromise();
|
||||
}
|
||||
|
||||
add(application: Application): Promise<Application> {
|
||||
return this._httpClient.post<Application>('/api/applications', application).toPromise();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Injectable, Type } from "@angular/core";
|
||||
import { BehaviorSubject, Observable } from "rxjs";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ModalService {
|
||||
_modalContent: BehaviorSubject<Type<unknown> | undefined> = new BehaviorSubject<Type<unknown> | undefined>(undefined);
|
||||
|
||||
open(componentClass: Type<unknown>): void {
|
||||
this._modalContent.next(componentClass);
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this._modalContent.next(undefined);
|
||||
}
|
||||
|
||||
get modalContent(): Observable<Type<unknown> | undefined> {
|
||||
return this._modalContent.asObservable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ReferentialDataService } from './referential-data.service';
|
||||
|
||||
describe('ReferentialDataService', () => {
|
||||
let service: ReferentialDataService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(ReferentialDataService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ReferentialData } from '../entities/ReferentialData';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ReferentialDataService {
|
||||
constructor(
|
||||
private _httpClient: HttpClient
|
||||
) {}
|
||||
|
||||
getServiceTypes(): Promise<ReferentialData[]> {
|
||||
return this._httpClient.get<ReferentialData[]>('/api/referentialData/serviceTypes').toPromise();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { HttpClientModule } from "@angular/common/http";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { BrowserModule } from "@angular/platform-browser";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { AppRoutingModule } from "../app.routing";
|
||||
import { ApplicationCardComponent } from './components/application-card/application-card.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
MatIconModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
RouterModule,
|
||||
],
|
||||
exports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
MatIconModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
RouterModule,
|
||||
]
|
||||
})
|
||||
export class SharedModule {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<header>
|
||||
<img src="assets/images/logo.png" alt="Cerberus" matTooltip="Cerberus"/>
|
||||
<div class="actions">
|
||||
<app-add-application-button></app-add-application-button>
|
||||
<div class="iconed-input">
|
||||
<mat-icon>search</mat-icon>
|
||||
<input placeholder="Search"/>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,28 @@
|
||||
@import '../../colors.scss';
|
||||
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-image: linear-gradient($gray-top, $gray-bottom);
|
||||
display: flex;
|
||||
flex: 1 0;
|
||||
height: 56px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid #bfbfbf;
|
||||
z-index: 102;
|
||||
|
||||
img {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.scss']
|
||||
})
|
||||
export class HeaderComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<button>Test1</button>
|
||||
|
||||
<input type="checkbox" />
|
||||
|
||||
<div class="login-form card">
|
||||
<div class="row">
|
||||
<input type="text" placeholder="Login"/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<input type="password" placeholder="Password"/>
|
||||
</div>
|
||||
<div class="row action">
|
||||
<button>Login</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="row">
|
||||
<input type="checkbox"/>
|
||||
Log out after
|
||||
<input type="number" value="5"/>
|
||||
minutes
|
||||
</div>
|
||||
<div class="row">
|
||||
<input type="checkbox"/>
|
||||
Require an administrator password
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="select">
|
||||
<select>
|
||||
<option>Option 1</option>
|
||||
<option>Option 2</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<input type="text" class="max-width" placeholder="Rechercher"/>
|
||||
</div>
|
||||
<div class="row action">
|
||||
<button class="help">?</button>
|
||||
<div class="row">
|
||||
<button class="secondary">Annuler</button>
|
||||
<button>Ok</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,11 @@
|
||||
.login-form {
|
||||
width: 15rem;
|
||||
|
||||
div, div input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.action {
|
||||
justify-content: right;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UiKitComponent } from './ui-kit.component';
|
||||
|
||||
describe('UiKitComponent', () => {
|
||||
let component: UiKitComponent;
|
||||
let fixture: ComponentFixture<UiKitComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ UiKitComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UiKitComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-ui-kit',
|
||||
templateUrl: './ui-kit.component.html',
|
||||
styleUrls: ['./ui-kit.component.scss']
|
||||
})
|
||||
export class UiKitComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@@ -0,0 +1,18 @@
|
||||
$blue: #017aff;
|
||||
|
||||
$btn-primary-border: #2f8df9;
|
||||
$btn-primary-background-top: #4ca4f6;
|
||||
$btn-primary-background-bottom: #0073f7;
|
||||
$btn-primary-active-border: #007cf8;
|
||||
$btn-primary-active-background-top: #0093f8;
|
||||
$btn-primary-active-background-bottom: #0064dd;
|
||||
|
||||
$btn-secondary-border: #c3c5c6;
|
||||
$btn-secondary-background: #ffffff;
|
||||
$btn-secondary-active-border: #c8c8c8;
|
||||
$btn-secondary-active-background: #f0f0f0;
|
||||
|
||||
$gray-top: #e6e6e6;
|
||||
$gray-bottom: #cfcfcf;
|
||||
|
||||
$gray-icon-secondary: #777777;
|
||||
@@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: true
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
production: false
|
||||
};
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 948 B |
@@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Cerberus</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<!-- Necessary for onsenUI loading -->
|
||||
<script>
|
||||
window.setImmediate = window.setTimeout;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||
* You can add your own extra polyfills to this file.
|
||||
*
|
||||
* This file is divided into 2 sections:
|
||||
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||
* file.
|
||||
*
|
||||
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||
*
|
||||
* Learn more in https://angular.io/guide/browser-support
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* BROWSER POLYFILLS
|
||||
*/
|
||||
|
||||
/**
|
||||
* IE11 requires the following for NgClass support on SVG elements
|
||||
*/
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/**
|
||||
* Web Animations `@angular/platform-browser/animations`
|
||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||
*/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
/**
|
||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||||
* will put import in the top of bundle, so user need to create a separate file
|
||||
* in this directory (for example: zone-flags.ts), and put the following flags
|
||||
* into that file, and then add the following code before importing zone.js.
|
||||
* import './zone-flags';
|
||||
*
|
||||
* The flags allowed in zone-flags.ts are listed here.
|
||||
*
|
||||
* The following flags will work for all browsers.
|
||||
*
|
||||
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||
*
|
||||
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||
*
|
||||
* (window as any).__Zone_enable_cross_context_check = true;
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by default for Angular itself.
|
||||
*/
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
@@ -0,0 +1,193 @@
|
||||
@import './colors.scss';
|
||||
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
@font-face {
|
||||
font-family: helvetica;
|
||||
src: url(assets/fonts/Helvetica.ttf);
|
||||
}
|
||||
|
||||
$font-size: 14px;
|
||||
|
||||
body {
|
||||
font-size: $font-size;
|
||||
font-family: helvetica;
|
||||
|
||||
::selection {
|
||||
background: $blue;
|
||||
color: white;
|
||||
}
|
||||
::-moz-selection {
|
||||
background: $blue;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
// background-color: $blue;
|
||||
background-image: linear-gradient($btn-primary-background-top, $btn-primary-background-bottom);
|
||||
color: white;
|
||||
border: solid 1px $btn-primary-background-bottom;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 5rem;
|
||||
border-radius: .3rem;
|
||||
padding: .15rem 1rem;
|
||||
font-weight: 600;
|
||||
margin: .2rem .5rem;
|
||||
|
||||
&:active {
|
||||
border-color: $btn-primary-active-border;
|
||||
background-image: linear-gradient($btn-primary-active-background-top, $btn-primary-active-background-bottom);
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
background-image: none;
|
||||
background-color: $btn-secondary-background;
|
||||
border-color: $btn-secondary-border;
|
||||
color: #222;
|
||||
font-weight: 500;
|
||||
|
||||
&:active {
|
||||
background-color: $btn-secondary-active-background;
|
||||
border-color: $btn-secondary-active-border;
|
||||
}
|
||||
}
|
||||
|
||||
&.help {
|
||||
border-radius: 10em;
|
||||
padding: 0;
|
||||
background-image: none;
|
||||
background-color: #eeeeee;
|
||||
color: #333;
|
||||
border-color: #bbb;
|
||||
min-width: min-content;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
|
||||
&:hover {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.card {
|
||||
width: max-content;
|
||||
padding: .5rem 1rem;
|
||||
box-shadow: 0px 13px 28px 4px rgba(0,0,0,0.2);
|
||||
border-radius: .4rem;
|
||||
margin: 2rem;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 1rem 0;
|
||||
|
||||
& > * {
|
||||
display: flex;
|
||||
flex: 1 0;
|
||||
}
|
||||
|
||||
& > input, select {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: .2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 0 .5rem;
|
||||
border: none;
|
||||
box-shadow: 0px 1px 2px 1px rgba(0,0,0,0.1);
|
||||
padding: .2rem .5rem;
|
||||
border-radius: .2rem;
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid $blue;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
// A reset of styles, including removing the default dropdown arrow
|
||||
appearance: none;
|
||||
// Additional resets for further consistency
|
||||
border: none;
|
||||
box-shadow: 0px 1px 2px 1px rgba(0,0,0,0.1);
|
||||
color: #333;
|
||||
border-radius: .3rem;
|
||||
padding: .15rem .5rem;
|
||||
font-weight: 600;
|
||||
margin: .2rem .5rem;
|
||||
font-size: $font-size;
|
||||
|
||||
&::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.select {
|
||||
display: grid;
|
||||
grid-template-areas: "select";
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
// Utilitary classes
|
||||
.max-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin: .5rem 0;
|
||||
max-width: 100%;
|
||||
|
||||
&.action {
|
||||
margin-top: 1.5rem;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
& > * {
|
||||
display: flex;
|
||||
flex: 1 0;
|
||||
}
|
||||
}
|
||||
|
||||
html, body { height: 100%; }
|
||||
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
|
||||
|
||||
|
||||
mat-icon.mat-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
|
||||
.iconed-input {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
color: $gray-icon-secondary;
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
mat-icon.mat-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// 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);
|
||||
@@ -0,0 +1,15 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"types": []
|
||||
},
|
||||
"files": [
|
||||
"src/main.ts",
|
||||
"src/polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "es2020",
|
||||
"lib": [
|
||||
"es2018",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts",
|
||||
"src/polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rulesDirectory": [
|
||||
"codelyzer"
|
||||
],
|
||||
"rules": {
|
||||
"align": {
|
||||
"options": [
|
||||
"parameters",
|
||||
"statements"
|
||||
]
|
||||
},
|
||||
"array-type": false,
|
||||
"arrow-return-shorthand": true,
|
||||
"curly": true,
|
||||
"deprecation": {
|
||||
"severity": "warning"
|
||||
},
|
||||
"eofline": true,
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs/Rx"
|
||||
],
|
||||
"import-spacing": true,
|
||||
"indent": {
|
||||
"options": [
|
||||
"spaces"
|
||||
]
|
||||
},
|
||||
"max-classes-per-file": false,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
],
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
"order": [
|
||||
"static-field",
|
||||
"instance-field",
|
||||
"static-method",
|
||||
"instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-empty": false,
|
||||
"no-inferrable-types": [
|
||||
true,
|
||||
"ignore-params"
|
||||
],
|
||||
"no-non-null-assertion": true,
|
||||
"no-redundant-jsdoc": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-var-requires": false,
|
||||
"object-literal-key-quotes": [
|
||||
true,
|
||||
"as-needed"
|
||||
],
|
||||
"quotemark": [
|
||||
true,
|
||||
"single"
|
||||
],
|
||||
"semicolon": {
|
||||
"options": [
|
||||
"always"
|
||||
]
|
||||
},
|
||||
"space-before-function-paren": {
|
||||
"options": {
|
||||
"anonymous": "never",
|
||||
"asyncArrow": "always",
|
||||
"constructor": "never",
|
||||
"method": "never",
|
||||
"named": "never"
|
||||
}
|
||||
},
|
||||
"typedef": [
|
||||
true,
|
||||
"call-signature"
|
||||
],
|
||||
"typedef-whitespace": {
|
||||
"options": [
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
},
|
||||
{
|
||||
"call-signature": "onespace",
|
||||
"index-signature": "onespace",
|
||||
"parameter": "onespace",
|
||||
"property-declaration": "onespace",
|
||||
"variable-declaration": "onespace"
|
||||
}
|
||||
]
|
||||
},
|
||||
"variable-name": {
|
||||
"options": [
|
||||
"ban-keywords",
|
||||
"check-format",
|
||||
"allow-pascal-case"
|
||||
]
|
||||
},
|
||||
"whitespace": {
|
||||
"options": [
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type",
|
||||
"check-typecast"
|
||||
]
|
||||
},
|
||||
"component-class-suffix": true,
|
||||
"contextual-lifecycle": true,
|
||||
"directive-class-suffix": true,
|
||||
"no-conflicting-lifecycle": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-output-native": true,
|
||||
"no-output-on-prefix": true,
|
||||
"no-output-rename": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"template-banana-in-box": true,
|
||||
"template-no-negated-async": true,
|
||||
"use-lifecycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"app",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
version: '3.6'
|
||||
services:
|
||||
database:
|
||||
build: "./docker/database"
|
||||
container_name: "cerberus-database"
|
||||
volumes:
|
||||
- ./docker/database/var/lib/postgresql/data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- "POSTGRES_DB=db_cerberus"
|
||||
- "POSTGRES_USER=cerberus"
|
||||
- "POSTGRES_PASSWORD=P@ssword1"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM postgres:13
|
||||
RUN localedef -i fr_FR -c -f UTF-8 -A /usr/share/locale/locale.alias fr_FR.UTF-8
|
||||
ENV LANG fr_FR.utf8
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
@@ -5,9 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class CerberusApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CerberusApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.takiguchi.cerberus.cerberusapp.controller;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.Application;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ApplicationStatus;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ServiceStatus;
|
||||
import org.takiguchi.cerberus.cerberusapp.service.ApplicationService;
|
||||
|
||||
@@ -37,6 +38,7 @@ public class ApplicationController {
|
||||
.withName(application.getName())
|
||||
.withServiceName(application.getServiceName())
|
||||
.withServiceType(application.getServiceType())
|
||||
.withImage(application.getImage())
|
||||
.build();
|
||||
return service.add(applicationToAdd);
|
||||
}
|
||||
@@ -80,4 +82,9 @@ public class ApplicationController {
|
||||
public void restart(@PathVariable("applicationId") UUID applicationId) {
|
||||
service.restart(applicationId);
|
||||
}
|
||||
|
||||
@GetMapping("/status")
|
||||
public List<ApplicationStatus> getAllApplicationStatus() {
|
||||
return service.checkAllStatus();
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package org.takiguchi.cerberus.cerberusapp.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ReferentialDataDTO;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ServiceType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.takiguchi.cerberus.cerberusapp.model.ReferentialDataDTO.aReferentialData;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/referentialData")
|
||||
public class ReferentialDataController {
|
||||
@GetMapping("/serviceTypes")
|
||||
public List<ReferentialDataDTO> getServiceTypes() {
|
||||
return Stream.of(ServiceType.values())
|
||||
.map(type -> aReferentialData()
|
||||
.withValue(type.name())
|
||||
.withLabel(type.name().toLowerCase())
|
||||
.build()
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,18 @@ public class Application {
|
||||
/** The technical service name, like a docker container name or a system V service name. */
|
||||
private final String serviceName;
|
||||
private final ServiceType serviceType;
|
||||
private final String image;
|
||||
|
||||
public static Builder anApplication() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private Application(UUID id, String name, String serviceName, ServiceType serviceType) {
|
||||
private Application(UUID id, String name, String serviceName, ServiceType serviceType, String image) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.serviceName = serviceName;
|
||||
this.serviceType = serviceType;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
@@ -37,11 +39,16 @@ public class Application {
|
||||
return serviceType;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private UUID id;
|
||||
private String name;
|
||||
private String serviceName;
|
||||
private ServiceType serviceType;
|
||||
private String image;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
@@ -66,8 +73,13 @@ public class Application {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withImage(String image) {
|
||||
this.image = image;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Application build() {
|
||||
return new Application(id, name, serviceName, serviceType);
|
||||
return new Application(id, name, serviceName, serviceType, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.takiguchi.cerberus.cerberusapp.model;
|
||||
|
||||
public class ApplicationStatus {
|
||||
private final Application application;
|
||||
private final ServiceStatus status;
|
||||
|
||||
public static Builder anApplicationStatus() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public ApplicationStatus(Application application, ServiceStatus status) {
|
||||
this.application = application;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Application getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public ServiceStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Application application;
|
||||
private ServiceStatus status;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder withApplication(Application application) {
|
||||
this.application = application;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withStatus(ServiceStatus status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApplicationStatus build() {
|
||||
return new ApplicationStatus(application, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.takiguchi.cerberus.cerberusapp.model;
|
||||
|
||||
public class ReferentialDataDTO {
|
||||
private final String value;
|
||||
private final String label;
|
||||
|
||||
private ReferentialDataDTO(String value, String label) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public static Builder aReferentialData() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String value;
|
||||
private String label;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder withValue(String value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withLabel(String label) {
|
||||
this.label = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReferentialDataDTO build() {
|
||||
return new ReferentialDataDTO(value, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -15,6 +15,7 @@ public class ApplicationEntityMapper {
|
||||
.withName(entity.getName())
|
||||
.withServiceName(entity.getServiceName())
|
||||
.withServiceType(entity.getServiceType())
|
||||
.withImage(entity.getImage())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -23,7 +24,8 @@ public class ApplicationEntityMapper {
|
||||
application.getId(),
|
||||
application.getName(),
|
||||
application.getServiceName(),
|
||||
application.getServiceType()
|
||||
application.getServiceType(),
|
||||
application.getImage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -1,13 +1,10 @@
|
||||
package org.takiguchi.cerberus.cerberusapp.persistence.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ServiceType;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.UUID;
|
||||
|
||||
import static javax.persistence.EnumType.ORDINAL;
|
||||
|
||||
@Entity
|
||||
@Table(name = "application")
|
||||
public class ApplicationEntity {
|
||||
@@ -18,15 +15,17 @@ public class ApplicationEntity {
|
||||
private String serviceName;
|
||||
@Enumerated
|
||||
private ServiceType serviceType;
|
||||
private String image;
|
||||
|
||||
public ApplicationEntity() {
|
||||
}
|
||||
|
||||
public ApplicationEntity(UUID id, String name, String serviceName, ServiceType serviceType) {
|
||||
public ApplicationEntity(UUID id, String name, String serviceName, ServiceType serviceType, String image) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.serviceName = serviceName;
|
||||
this.serviceType = serviceType;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
@@ -57,6 +56,14 @@ public class ApplicationEntity {
|
||||
return serviceType;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public void setServiceType(ServiceType serviceType) {
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.takiguchi.cerberus.cerberusapp.service;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.takiguchi.cerberus.cerberusapp.exception.NotFoundException;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.Application;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ApplicationStatus;
|
||||
import org.takiguchi.cerberus.cerberusapp.model.ServiceStatus;
|
||||
import org.takiguchi.cerberus.cerberusapp.service.servicemanager.ServiceManagerProvider;
|
||||
import org.takiguchi.cerberus.cerberusapp.service.validator.ApplicationValidator;
|
||||
@@ -10,8 +11,10 @@ import org.takiguchi.cerberus.cerberusapp.service.validator.ApplicationValidator
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.takiguchi.cerberus.cerberusapp.model.Application.anApplication;
|
||||
import static org.takiguchi.cerberus.cerberusapp.model.ApplicationStatus.anApplicationStatus;
|
||||
|
||||
@Service
|
||||
public class ApplicationService {
|
||||
@@ -94,4 +97,16 @@ public class ApplicationService {
|
||||
NotFoundException::new
|
||||
);
|
||||
}
|
||||
|
||||
public List<ApplicationStatus> checkAllStatus() {
|
||||
return getAll().stream()
|
||||
.map(application -> {
|
||||
ServiceStatus status = checkStatus(application.getId());
|
||||
return anApplicationStatus()
|
||||
.withApplication(application)
|
||||
.withStatus(status)
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,12 @@ spring:
|
||||
# -------------------------------------------------
|
||||
datasource:
|
||||
driverClassName: org.postgresql.Driver
|
||||
url: jdbc:postgresql://localhost:50001/cerberus
|
||||
username: h23
|
||||
url: jdbc:postgresql://localhost:5432/db_cerberus
|
||||
username: cerberus
|
||||
password: P@ssword1
|
||||
# Disable feature detection by this undocumented parameter.
|
||||
# Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
|
||||
jpa:
|
||||
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||
properties.hibernate.temp.use_jdbc_metadata_defaults: false
|
||||
open-in-view: false
|
||||
@@ -5,5 +5,6 @@ CREATE TABLE IF NOT EXISTS application (
|
||||
name VARCHAR NOT NULL,
|
||||
service_name VARCHAR NOT NULL,
|
||||
service_type SMALLINT NOT NULL,
|
||||
image VARCHAR NOT NULL,
|
||||
CONSTRAINT application_pk PRIMARY KEY (id)
|
||||
);
|
||||
Reference in New Issue
Block a user