Commit 22dbe0d7 authored by Christopher Keim's avatar Christopher Keim
Browse files

[TOB-68] feat: Extend page for creating new statements



 * Install PrimeNg
 * Install MomentJS
 * Add user control for dates
 * Add user control for file dropping
 * Add progress spinner component
 * Add form for creating new statements
 * Add store module for statements and statement types
 * Include API calls to backend

[TOB-164] test: Increase test coverage for utility functions

 * Use barrel files for imports
 * Add tests for utility functions
Signed-off-by: Christopher Keim's avatarChristopher Keim <keim@develop-group.de>
parent 3624a6da
......@@ -111,6 +111,14 @@ material-design-icons (3.0.1)
* License: Apache-2.0
* Source: https://github.com/google/material-design-icons
moment (2.24.0)
* License: MIT
* Source: https://github.com/moment/moment
primeng (9.0.6)
* License: MIT
* Source: https://github.com/primefaces/primeng
proj4 (2.6.1)
* License: MIT
* Source: https://github.com/proj4js/proj4js
......
{
"name": "openkonsequenz-statement-public-affairs",
"version": "0.0.1",
"version": "0.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -3191,6 +3191,12 @@
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true
},
"acorn-walk": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
"integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==",
"dev": true
},
"address": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz",
......@@ -4306,6 +4312,18 @@
"callsite": "1.0.0"
}
},
"bfj": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz",
"integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==",
"dev": true,
"requires": {
"bluebird": "^3.5.5",
"check-types": "^8.0.3",
"hoopy": "^0.1.4",
"tryer": "^1.0.1"
}
},
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
......@@ -4961,6 +4979,12 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"check-types": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
"integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==",
"dev": true
},
"chokidar": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
......@@ -8314,6 +8338,12 @@
"react-is": "^16.7.0"
}
},
"hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
"integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
"dev": true
},
"hosted-git-info": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.4.tgz",
......@@ -10977,6 +11007,11 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
......@@ -11515,6 +11550,12 @@
"integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==",
"dev": true
},
"opener": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
"integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==",
"dev": true
},
"opn": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
......@@ -12932,6 +12973,11 @@
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
"dev": true
},
"primeng": {
"version": "9.0.6",
"resolved": "https://registry.npmjs.org/primeng/-/primeng-9.0.6.tgz",
"integrity": "sha512-RGVTkXwHTb7609zTU/uJFYdbJV124kOwrMiwnHjFn6UkwmS3yTX0Kkr21v8KOTJqsKLq3OWVYhkOwvUklipAAg=="
},
"prismjs": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.19.0.tgz",
......@@ -17715,6 +17761,12 @@
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
"dev": true
},
"tryer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
"dev": true
},
"ts-dedent": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-1.1.1.tgz",
......@@ -19378,6 +19430,35 @@
}
}
},
"webpack-bundle-analyzer": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.7.0.tgz",
"integrity": "sha512-mETdjZ30a3Yf+NTB/wqTgACK7rAYQl5uxKK0WVTNmF0sM3Uv8s3R58YZMW7Rhu0Lk2Rmuhdj5dcH5Q76zCDVdA==",
"dev": true,
"requires": {
"acorn": "^7.1.1",
"acorn-walk": "^7.1.1",
"bfj": "^6.1.1",
"chalk": "^2.4.1",
"commander": "^2.18.0",
"ejs": "^2.6.1",
"express": "^4.16.3",
"filesize": "^3.6.1",
"gzip-size": "^5.0.0",
"lodash": "^4.17.15",
"mkdirp": "^0.5.1",
"opener": "^1.5.1",
"ws": "^6.0.0"
},
"dependencies": {
"acorn": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"dev": true
}
}
},
"webpack-dev-middleware": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
......
{
"name": "openkonsequenz-statement-public-affairs",
"version": "0.1.0",
"version": "0.2.0",
"description": "Statement Public Affairs",
"license": "Eclipse Public License - v 2.0",
"routes": {
......@@ -12,6 +12,8 @@
"-- Build ----------------": "",
"build": "ng build --prod --base-href $npm_package_routes_spaFrontend/",
"build:archive": "jar -cvf ./dist/statement-public-affairs-frontend.war -C ./dist/statement-public-affairs .",
"build:stats": "ng build --prod --base-href $npm_package_routes_spaFrontend/ --statsJson true",
"build:stats:analyze": "webpack-bundle-analyzer ./dist/statement-public-affairs/stats-es2015.json",
"-- Development ----------": "",
"start": "ng serve",
"test": "ng test --codeCoverage=true --watch=false",
......@@ -47,11 +49,13 @@
"@ngx-translate/http-loader": "^4.0.0",
"leaflet": "^1.6.0",
"material-design-icons": "^3.0.1",
"primeng": "^9.0.6",
"proj4": "^2.6.1",
"rxjs": "~6.5.4",
"source-sans-pro": "^3.6.0",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
"zone.js": "~0.10.2",
"moment": "2.24.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.901.0",
......@@ -88,6 +92,7 @@
"stylelint-config-sass-guidelines": "^7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~3.8.3"
"typescript": "~3.8.3",
"webpack-bundle-analyzer": "^3.7.0"
}
}
......@@ -17,17 +17,17 @@ import {RouterModule, Routes} from "@angular/router";
const routes: Routes = [
{
path: "",
loadChildren: () => import("./pages/dashboard/dashboard.module")
loadChildren: () => import("./features/dashboard")
.then((m) => m.DashboardModule)
},
{
path: "new",
loadChildren: () => import("./pages/new/new-statement.module")
loadChildren: () => import("./features/new")
.then((m) => m.NewStatementModule)
},
{
path: "details",
loadChildren: () => import("./pages/details/statement-details.module")
loadChildren: () => import("./features/details")
.then((m) => m.StatementDetailsModule)
},
// The wildcard has to be placed as the last item (otherwise, its overriding routes)
......
......@@ -11,8 +11,8 @@
* SPDX-License-Identifier: EPL-2.0
-------------------------------------------------------------------------------->
<app-navigation-frame>
<app-navigation>
<router-outlet></router-outlet>
</app-navigation-frame>
</app-navigation>
......@@ -18,9 +18,9 @@ import {TranslateModule} from "@ngx-translate/core";
import {environment} from "../environments/environment";
import {AppRoutingModule} from "./app-routing.module";
import {AppComponent} from "./app.component";
import {CoreModule} from "./core/core.module";
import {AppNavigationFrameModule} from "./pages/app-navigation-frame/app-navigation-frame.module";
import {AppStoreModule} from "./store/app-store.module";
import {CoreModule} from "./core";
import {AppNavigationFrameModule} from "./features";
import {AppStoreModule} from "./store";
@NgModule({
declarations: [
......@@ -31,13 +31,13 @@ import {AppStoreModule} from "./store/app-store.module";
BrowserAnimationsModule,
TranslateModule,
AppStoreModule,
CoreModule,
AppRoutingModule,
CoreModule,
AppStoreModule,
AppNavigationFrameModule,
// This import is only important for development; in production, nothing is imported.
// ! This import must come after the NGRX store modules in order make the NGRX Store Devtools available. !
// ! This import must come after AppStoreModule in order make the NGRX Store Devtools available. !
...environment.imports
],
bootstrap: [
......
......@@ -13,8 +13,8 @@
import {HttpClient} from "@angular/common/http";
import {Inject, Injectable} from "@angular/core";
import {urlJoin} from "../../../util/http.util";
import {SPA_BACKEND_ROUTE} from "../../external-routes/spa-backend-route.token";
import {urlJoin} from "../../../util";
import {SPA_BACKEND_ROUTE} from "../../external-routes";
import {IAPIUserInfo} from "./IAPIUserInfo";
import {IAPIVersion} from "./IAPIVersion";
......
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export * from "./core-api.service";
export * from "./IAPIUserInfo";
export * from "./IAPIVersion";
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export * from "./core";
export * from "./settings";
export * from "./statements";
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export interface IAPIStatementType {
id: number;
name: string;
}
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export * from "./IAPIStatementType";
export * from "./settings-api.service";
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
import {HttpClient} from "@angular/common/http";
import {Inject, Injectable} from "@angular/core";
import {urlJoin} from "../../../util";
import {SPA_BACKEND_ROUTE} from "../../external-routes";
import {IAPIStatementType} from "./IAPIStatementType";
@Injectable({
providedIn: "root"
})
export class SettingsApiService {
public constructor(
protected readonly httpClient: HttpClient,
@Inject(SPA_BACKEND_ROUTE) protected readonly baseUrl: string
) {
}
/**
* Fetches the version info from back end.
*/
public getStatementTypes() {
const endPoint = `statement-data/types`;
return this.httpClient.get<IAPIStatementType[]>(urlJoin(this.baseUrl, endPoint));
}
}
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export interface IAPIAttachmentModel {
id: number;
name: string;
type: string;
size: number;
timestamp: string;
}
......@@ -19,8 +19,16 @@ export interface IAPIStatementModel {
dueDate: string;
receiptDate: string;
taskId: number;
finished: boolean;
typeId: number;
city: string;
district: string;
}
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export * from "./IAPIAttachmentModel";
export * from "./IAPIStatementModel";
export * from "./statements-api.service";
......@@ -13,8 +13,9 @@
import {HttpClient} from "@angular/common/http";
import {Inject, Injectable} from "@angular/core";
import {urlJoin} from "../../../util/http.util";
import {SPA_BACKEND_ROUTE} from "../../external-routes/spa-backend-route.token";
import {urlJoin} from "../../../util";
import {SPA_BACKEND_ROUTE} from "../../external-routes";
import {IAPIAttachmentModel} from "./IAPIAttachmentModel";
import {IAPIStatementModel} from "./IAPIStatementModel";
@Injectable({
......@@ -54,4 +55,22 @@ export class StatementsApiService {
return this.httpClient.post<IAPIStatementModel>(urlJoin(this.baseUrl, endPoint), statement);
}
/**
* Fetches a list of all attachments belonging to an statement.
*/
public getAllAttachments(statementId: number) {
const endPoint = `/statements/${statementId}/attachments`;
return this.httpClient.get<IAPIAttachmentModel[]>(urlJoin(this.baseUrl, endPoint));
}
/**
* Uploads a new file to a statement.
*/
public postAttachment(statementId: number, file: File) {
const endPoint = `/statements/${statementId}/attachments`;
const formData = new FormData();
formData.append("attachment", file, file.name);
return this.httpClient.post<IAPIAttachmentModel>(urlJoin(this.baseUrl, endPoint), formData);
}
}
......@@ -15,9 +15,8 @@ import {HTTP_INTERCEPTORS, HttpErrorResponse, HttpEvent, HttpHandler, HttpInterc
import {Inject, Injectable} from "@angular/core";
import {Observable, Subject} from "rxjs";
import {tap} from "rxjs/operators";
import {EHttpStatusCodes} from "../../util/EHttpStatusCodes";
import {isHttpErrorWithStatus, urlJoin} from "../../util/http.util";
import {SPA_BACKEND_ROUTE} from "../external-routes/spa-backend-route.token";
import {EHttpStatusCodes, isHttpErrorWithStatus, urlJoin} from "../../util";
import {SPA_BACKEND_ROUTE} from "../external-routes";
import {AuthService} from "./auth.service";
@Injectable({providedIn: "root"})
......
......@@ -14,7 +14,7 @@
import {DOCUMENT} from "@angular/common";
import {TestBed} from "@angular/core/testing";
import {RouterTestingModule} from "@angular/router/testing";
import {LOCAL_STORAGE} from "../dom/local-storage.token";
import {LOCAL_STORAGE} from "../dom";
import {AuthService} from "./auth.service";
class StorageStub {
......
......@@ -15,7 +15,7 @@ import {DOCUMENT} from "@angular/common";
import {Inject, Injectable} from "@angular/core";
import {ActivatedRoute, Router} from "@angular/router";
import {concatMap, filter} from "rxjs/operators";
import {LOCAL_STORAGE} from "../dom/local-storage.token";
import {LOCAL_STORAGE} from "../dom";
@Injectable({providedIn: "root"})
export class AuthService {
......
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
export * from "./auth.module";
export * from "./auth.service";
export * from "./auth-interceptor.service";
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment