Commit 524f5b2f authored by Simone Vuotto's avatar Simone Vuotto

Replace frontend with submodule

parent 9276f91e
[submodule "backend"]
path = backend
url = https://gitlab.sagelab.it/sage/reqv-backend.git
[submodule "frontend"]
path = frontend
url = https://gitlab.sagelab.it/sage/reqv-frontend.git
Subproject commit 7eaa236fa71f54a1f443d4d2af1c84eab9b4bdc8
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# dependencies
/node_modules
# 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
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
# System Files
.DS_Store
Thumbs.db
# ReqVWebapp
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.1.
## 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 README](https://github.com/angular/angular-cli/blob/master/README.md).
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"req-v-webapp": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico"
],
"styles": [
"src/styles.css",
"node_modules/bootswatch/dist/simplex/bootstrap.min.css",
"node_modules/font-awesome/css/font-awesome.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/popper.js/dist/umd/popper.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "req-v-webapp:build"
},
"configurations": {
"production": {
"browserTarget": "req-v-webapp:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "req-v-webapp:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
],
"styles": [
"src/styles.css",
"node_modules/bootswatch/dist/simplex/bootstrap.min.css",
"node_modules/font-awesome/css/font-awesome.min.css"
],
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"req-v-webapp-e2e": {
"root": "",
"sourceRoot": "",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "req-v-webapp:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "req-v-webapp",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"styleext": "css"
},
"@schematics/angular:directive": {
"prefix": "app"
}
}
}
import { AppPage } from './app.po';
describe('req-v-webapp App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}
// 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'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
This diff is collapsed.
{
"name": "req-v-webapp",
"version": "0.0.1",
"license": "LGPL",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "6.0.3",
"@angular/common": "6.0.3",
"@angular/compiler": "6.0.3",
"@angular/core": "6.0.3",
"@angular/forms": "6.0.3",
"@angular/http": "6.0.3",
"@angular/platform-browser": "6.0.3",
"@angular/platform-browser-dynamic": "6.0.3",
"@angular/router": "6.0.3",
"@auth0/angular-jwt": "^2.0.0",
"@ng-bootstrap/ng-bootstrap": "^2.0.0",
"@swimlane/ngx-datatable": "^13.0.0",
"bootstrap": "^4.1.1",
"bootswatch": "^4.1.1",
"core-js": "^2.5.7",
"file-saver": "^1.3.8",
"font-awesome": "^4.7.0",
"jquery": "^3.3.1",
"popper.js": "^1.14.3",
"rxjs": "^6.0.0",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.6.6",
"@angular/cli": "6.0.7",
"@angular/compiler-cli": "6.0.3",
"@angular/language-service": "6.0.3",
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2",
"@types/node": "^6.0.112",
"codelyzer": "^4.3.0",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.4.3",
"karma-jasmine": "^1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "^5.3.2",
"ts-node": "~3.2.0",
"tslint": "~5.7.0",
"typescript": "2.7.2"
}
}
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.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: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
{
"/api" :{
"target": "http://localhost:8080/",
"secure": false
}
}
<div *ngIf="message"
[ngClass]="{ 'alert': message, 'alert-success': message.type === 'success', 'alert-danger': message.type === 'error' }">
{{message.text}}
</div>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AlertComponent } from './alert.component';
describe('AlertComponent', () => {
let component: AlertComponent;
let fixture: ComponentFixture<AlertComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AlertComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AlertComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import {AlertService} from './alert.service';
@Component({
selector: 'app-alert',
templateUrl: './alert.component.html'
})
export class AlertComponent implements OnInit {
message: any;
constructor(private alertService: AlertService) { }
ngOnInit() {
this.alertService.getMessage().subscribe(message => { this.message = message; });
}
}
import { TestBed, inject } from '@angular/core/testing';
import { AlertService } from './alert.service';
describe('AlertService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AlertService]
});
});
it('should be created', inject([AlertService], (service: AlertService) => {
expect(service).toBeTruthy();
}));
});
import { Injectable } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { Observable, Subject } from 'rxjs';
@Injectable()
export class AlertService {
private subject = new Subject<any>();
private keepAfterNavigationChange = false;
constructor(private router: Router) {
// clear alert message on route change
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
if (this.keepAfterNavigationChange) {
// only keep for a single location change
this.keepAfterNavigationChange = false;
} else {
// clear alert
this.subject.next();
}
}
});
}
success(message: string, keepAfterNavigationChange = false) {
this.keepAfterNavigationChange = keepAfterNavigationChange;
this.subject.next({ type: 'success', text: message });
}
error(message: string, keepAfterNavigationChange = false) {
this.keepAfterNavigationChange = keepAfterNavigationChange;
this.subject.next({ type: 'error', text: message });
}
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}
import { NgModule } from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {LoginComponent} from './login/login.component';
import {ProjectsComponent} from './projects/projects.component';
import {AuthGuard} from './auth.guard';
import { ProjectDetailsComponent } from './project-details/project-details.component';
import { PatternWizardComponent } from './pattern-wizard/pattern-wizard.component';
const routes: Routes = [
{ path: '', component: LoginComponent },
{ path: 'projects', component: ProjectsComponent, canActivate: [AuthGuard] },
{ path: 'projects/:projectId', component: ProjectDetailsComponent, canActivate: [AuthGuard]},
{ path: 'projects/:projectId/addReq', component: PatternWizardComponent, canActivate: [AuthGuard]},
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ],
})
export class AppRoutingModule { }
.container-fluid {
padding: 4em 2em;
}
<!-- navbar -->
<nav class="navbar navbar-default navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" routerLink="/">ReqV</a>
<ul class="navbar-nav navbar-right" *ngIf="authenticationService.isAuthenticated()">
<li class="nav-item">
<a class="nav-link" (click)="logout()" routerLink="/" >Logout</a>
</li>
</ul>
</div>
</nav>
<!-- main app container -->
<div class="container-fluid">
<div class="container">
<app-alert></app-alert>
<router-outlet></router-outlet>
</div>
</div>
<!-- credits -->
<footer>
<div class="container">
<div class="hline"></div>
<p class="small">
Copyright © 2017 Simone Vuotto | All Rights Reserved
</p>
</div>
</footer>
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', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});
import { Component } from '@angular/core';
import { AuthenticationService } from './services/authentication.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(public authenticationService: AuthenticationService) { }
logout() {
this.authenticationService.logout();
}
}
// Modules
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
// Components
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { ProjectsComponent } from './projects/projects.component';
import { AlertComponent } from './alert/alert.component';
import { ProjectDialogComponent } from './project-dialog/project-dialog.component';
import { ProjectDetailsComponent } from './project-details/project-details.component';
import { RequirementDetailsComponent } from './requirement-details/requirement-details.component';
import { RequirementsTabComponent } from './project-details/requirements-tab/requirements-tab.component';
import { TasksTabComponent } from './project-details/tasks-tab/tasks-tab.component';
// Services
import { AuthenticationService } from './services/authentication.service';
import { AlertService } from './alert/alert.service';
import { ProjectService } from './services/project.service';
import { RequirementService } from './services/requirement.service';
import { TaskService } from './services/task.service';
// Guards
import {AuthGuard} from './auth.guard';
// Http Interceptor
import { JwtInterceptor } from './jwt.interceptor.js';
import { PatternWizardComponent } from './pattern-wizard/pattern-wizard.component';
import { ExpressionWizardComponent } from './pattern-wizard/expression-wizard/expression-wizard.component';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
AlertComponent,
ProjectsComponent,
ProjectDialogComponent,
ProjectDetailsComponent,
RequirementDetailsComponent,
RequirementsTabComponent,
TasksTabComponent,
PatternWizardComponent,
ExpressionWizardComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
NgxDatatableModule,
NgbModule.forRoot(),
],
providers: [
AuthenticationService,
AuthGuard,