├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── angular.json
├── e2e
├── protractor.conf.js
├── src
│ ├── app.e2e-spec.ts
│ └── app.po.ts
└── tsconfig.e2e.json
├── package-lock.json
├── package.json
├── proxy.conf.json
├── server.js
├── src
├── app
│ ├── app.component.html
│ ├── app.component.scss
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── app.routing.ts
│ ├── communication
│ │ ├── emails
│ │ │ ├── add-email
│ │ │ │ ├── add-email.component.html
│ │ │ │ ├── add-email.component.scss
│ │ │ │ └── add-email.component.ts
│ │ │ ├── conversation
│ │ │ │ ├── conversation.component.html
│ │ │ │ ├── conversation.component.scss
│ │ │ │ └── conversation.component.ts
│ │ │ ├── inbox
│ │ │ │ ├── inbox.component.html
│ │ │ │ ├── inbox.component.scss
│ │ │ │ └── inbox.component.ts
│ │ │ ├── outbox
│ │ │ │ ├── outbox.component.html
│ │ │ │ ├── outbox.component.scss
│ │ │ │ └── outbox.component.ts
│ │ │ └── reply-dialog
│ │ │ │ ├── reply-dialog.component.html
│ │ │ │ ├── reply-dialog.component.scss
│ │ │ │ └── reply-dialog.component.ts
│ │ ├── notifications
│ │ │ ├── add-notification
│ │ │ │ ├── add-notification.component.html
│ │ │ │ ├── add-notification.component.scss
│ │ │ │ └── add-notification.component.ts
│ │ │ ├── notification
│ │ │ │ ├── notification.component.html
│ │ │ │ ├── notification.component.scss
│ │ │ │ └── notification.component.ts
│ │ │ └── notifications
│ │ │ │ ├── notifications.component.html
│ │ │ │ ├── notifications.component.scss
│ │ │ │ └── notifications.component.ts
│ │ └── suggestions
│ │ │ ├── add-suggestion
│ │ │ ├── add-suggestion.component.html
│ │ │ ├── add-suggestion.component.scss
│ │ │ └── add-suggestion.component.ts
│ │ │ ├── suggestion
│ │ │ ├── suggestion.component.html
│ │ │ ├── suggestion.component.scss
│ │ │ └── suggestion.component.ts
│ │ │ └── suggestions
│ │ │ ├── suggestions.component.html
│ │ │ ├── suggestions.component.scss
│ │ │ └── suggestions.component.ts
│ ├── custom
│ │ └── error-dialog
│ │ │ ├── error-dialog.component.html
│ │ │ ├── error-dialog.component.scss
│ │ │ └── error-dialog.component.ts
│ ├── globals.ts
│ ├── interceptor.ts
│ ├── material.ts
│ ├── pipes
│ │ ├── enumeration.pipe.ts
│ │ ├── minute-seconds.pipe.ts
│ │ ├── no-comma-number.pipe.ts
│ │ ├── tasks-doing.pipe.ts
│ │ ├── tasks-done.pipe.ts
│ │ └── tasks-todo.pipe.ts
│ ├── production
│ │ ├── finance
│ │ │ ├── add-expense-dialog
│ │ │ │ ├── add-expense-dialog.component.html
│ │ │ │ ├── add-expense-dialog.component.scss
│ │ │ │ └── add-expense-dialog.component.ts
│ │ │ ├── add-income-dialog
│ │ │ │ ├── add-income-dialog.component.html
│ │ │ │ ├── add-income-dialog.component.scss
│ │ │ │ └── add-income-dialog.component.ts
│ │ │ ├── current-report
│ │ │ │ ├── current-report.component.html
│ │ │ │ ├── current-report.component.scss
│ │ │ │ └── current-report.component.ts
│ │ │ ├── recalculate-dialog
│ │ │ │ ├── recalculate-dialog.component.html
│ │ │ │ ├── recalculate-dialog.component.scss
│ │ │ │ └── recalculate-dialog.component.ts
│ │ │ ├── report
│ │ │ │ ├── report.component.html
│ │ │ │ ├── report.component.scss
│ │ │ │ └── report.component.ts
│ │ │ └── reports
│ │ │ │ ├── reports.component.html
│ │ │ │ ├── reports.component.scss
│ │ │ │ └── reports.component.ts
│ │ ├── planning
│ │ │ ├── planning
│ │ │ │ ├── planning.component.html
│ │ │ │ ├── planning.component.scss
│ │ │ │ └── planning.component.ts
│ │ │ ├── show-special-plan-dialog
│ │ │ │ ├── show-special-plan-dialog.component.html
│ │ │ │ ├── show-special-plan-dialog.component.scss
│ │ │ │ └── show-special-plan-dialog.component.ts
│ │ │ ├── special-plan-dialog
│ │ │ │ ├── special-plan-dialog.component.html
│ │ │ │ ├── special-plan-dialog.component.scss
│ │ │ │ └── special-plan-dialog.component.ts
│ │ │ ├── special-plan-no-date-dialog
│ │ │ │ ├── special-plan-no-date-dialog.component.html
│ │ │ │ ├── special-plan-no-date-dialog.component.scss
│ │ │ │ └── special-plan-no-date-dialog.component.ts
│ │ │ ├── special-plans
│ │ │ │ ├── special-plans.component.html
│ │ │ │ ├── special-plans.component.scss
│ │ │ │ └── special-plans.component.ts
│ │ │ └── update-daily-plan
│ │ │ │ ├── update-daily-plan.component.html
│ │ │ │ ├── update-daily-plan.component.scss
│ │ │ │ └── update-daily-plan.component.ts
│ │ └── tasks
│ │ │ ├── add-task
│ │ │ ├── add-task.component.html
│ │ │ ├── add-task.component.scss
│ │ │ └── add-task.component.ts
│ │ │ ├── assignment
│ │ │ ├── assignment.component.html
│ │ │ ├── assignment.component.scss
│ │ │ └── assignment.component.ts
│ │ │ ├── indicators
│ │ │ ├── indicators.component.html
│ │ │ ├── indicators.component.scss
│ │ │ └── indicators.component.ts
│ │ │ ├── kanban
│ │ │ ├── kanban.component.html
│ │ │ ├── kanban.component.scss
│ │ │ └── kanban.component.ts
│ │ │ ├── task
│ │ │ ├── task.component.html
│ │ │ ├── task.component.scss
│ │ │ └── task.component.ts
│ │ │ └── tasks
│ │ │ ├── tasks.component.html
│ │ │ ├── tasks.component.scss
│ │ │ └── tasks.component.ts
│ ├── security
│ │ ├── login
│ │ │ ├── login.component.html
│ │ │ ├── login.component.scss
│ │ │ └── login.component.ts
│ │ └── validate
│ │ │ ├── validate.component.html
│ │ │ ├── validate.component.scss
│ │ │ └── validate.component.ts
│ ├── services
│ │ ├── complaint.service.ts
│ │ ├── delivery.service.ts
│ │ ├── email.service.ts
│ │ ├── employee.service.ts
│ │ ├── holiday.service.ts
│ │ ├── item.service.ts
│ │ ├── login.service.ts
│ │ ├── notification.service.ts
│ │ ├── order.service.ts
│ │ ├── planning.service.ts
│ │ ├── report.service.ts
│ │ ├── return.service.ts
│ │ ├── setup.service.ts
│ │ ├── suggestion.service.ts
│ │ ├── task.service.ts
│ │ └── team.service.ts
│ ├── setup
│ │ ├── setup.component.html
│ │ ├── setup.component.scss
│ │ └── setup.component.ts
│ ├── shop
│ │ ├── complaints
│ │ │ ├── complaint-resolution-dialog
│ │ │ │ ├── complaint-resolution-dialog.component.html
│ │ │ │ ├── complaint-resolution-dialog.component.scss
│ │ │ │ └── complaint-resolution-dialog.component.ts
│ │ │ ├── complaint-status-dialog
│ │ │ │ ├── complaint-status-dialog.component.html
│ │ │ │ ├── complaint-status-dialog.component.scss
│ │ │ │ └── complaint-status-dialog.component.ts
│ │ │ ├── complaint
│ │ │ │ ├── complaint.component.html
│ │ │ │ ├── complaint.component.scss
│ │ │ │ └── complaint.component.ts
│ │ │ └── complaints
│ │ │ │ ├── complaints.component.html
│ │ │ │ ├── complaints.component.scss
│ │ │ │ └── complaints.component.ts
│ │ ├── deliveries
│ │ │ ├── add-delivery
│ │ │ │ ├── add-delivery.component.html
│ │ │ │ ├── add-delivery.component.scss
│ │ │ │ └── add-delivery.component.ts
│ │ │ ├── deliveries
│ │ │ │ ├── deliveries.component.html
│ │ │ │ ├── deliveries.component.scss
│ │ │ │ └── deliveries.component.ts
│ │ │ └── delivery
│ │ │ │ ├── delivery.component.html
│ │ │ │ ├── delivery.component.scss
│ │ │ │ └── delivery.component.ts
│ │ ├── items
│ │ │ ├── add-item
│ │ │ │ ├── add-item.component.html
│ │ │ │ ├── add-item.component.scss
│ │ │ │ └── add-item.component.ts
│ │ │ ├── item
│ │ │ │ ├── item.component.html
│ │ │ │ ├── item.component.scss
│ │ │ │ └── item.component.ts
│ │ │ ├── items
│ │ │ │ ├── items.component.html
│ │ │ │ ├── items.component.scss
│ │ │ │ └── items.component.ts
│ │ │ ├── new-price-dialog
│ │ │ │ ├── new-price-dialog.component.html
│ │ │ │ ├── new-price-dialog.component.scss
│ │ │ │ └── new-price-dialog.component.ts
│ │ │ └── special-offer-dialog
│ │ │ │ ├── special-offer-dialog.component.html
│ │ │ │ ├── special-offer-dialog.component.scss
│ │ │ │ └── special-offer-dialog.component.ts
│ │ ├── orders
│ │ │ ├── add-order
│ │ │ │ ├── add-order.component.html
│ │ │ │ ├── add-order.component.scss
│ │ │ │ └── add-order.component.ts
│ │ │ ├── order-status-dialog
│ │ │ │ ├── order-status-dialog.component.html
│ │ │ │ ├── order-status-dialog.component.scss
│ │ │ │ └── order-status-dialog.component.ts
│ │ │ ├── order
│ │ │ │ ├── order.component.html
│ │ │ │ ├── order.component.scss
│ │ │ │ └── order.component.ts
│ │ │ └── orders
│ │ │ │ ├── orders.component.html
│ │ │ │ ├── orders.component.scss
│ │ │ │ └── orders.component.ts
│ │ └── returns
│ │ │ ├── return
│ │ │ ├── return.component.html
│ │ │ ├── return.component.scss
│ │ │ └── return.component.ts
│ │ │ ├── returns
│ │ │ ├── returns.component.html
│ │ │ ├── returns.component.scss
│ │ │ └── returns.component.ts
│ │ │ └── status-dialog
│ │ │ ├── status-dialog.component.html
│ │ │ ├── status-dialog.component.scss
│ │ │ └── status-dialog.component.ts
│ ├── staff
│ │ ├── employees
│ │ │ ├── add-employee
│ │ │ │ ├── add-employee.component.html
│ │ │ │ ├── add-employee.component.scss
│ │ │ │ └── add-employee.component.ts
│ │ │ ├── employee
│ │ │ │ ├── employee.component.html
│ │ │ │ ├── employee.component.scss
│ │ │ │ └── employee.component.ts
│ │ │ └── employees
│ │ │ │ ├── employees.component.html
│ │ │ │ ├── employees.component.scss
│ │ │ │ └── employees.component.ts
│ │ ├── holidays
│ │ │ ├── add-holiday
│ │ │ │ ├── add-holiday.component.html
│ │ │ │ ├── add-holiday.component.scss
│ │ │ │ └── add-holiday.component.ts
│ │ │ └── manage-holidays-dialog
│ │ │ │ ├── manage-holidays-dialog.component.html
│ │ │ │ ├── manage-holidays-dialog.component.scss
│ │ │ │ └── manage-holidays-dialog.component.ts
│ │ └── teams
│ │ │ ├── team
│ │ │ ├── team.component.html
│ │ │ ├── team.component.scss
│ │ │ └── team.component.ts
│ │ │ └── teams
│ │ │ ├── teams.component.html
│ │ │ ├── teams.component.scss
│ │ │ └── teams.component.ts
│ ├── token.ts
│ └── types.ts
├── assets
│ └── .gitkeep
├── browserslist
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── karma.conf.js
├── main.ts
├── polyfills.ts
├── styles.scss
├── test.ts
├── theme.scss
├── tsconfig.app.json
├── tsconfig.spec.json
├── tslint.json
└── variables.scss
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | /typings
36 |
37 | # System Files
38 | .DS_Store
39 | Thumbs.db
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Joe Kutner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './src/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: require('path').join(__dirname, './tsconfig.e2e.json')
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('workspace-project App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to erp-mes-frontend!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "erp-mes-frontend",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "node server.js",
7 | "build": "ng build",
8 | "test": "ng test",
9 | "lint": "ng lint",
10 | "e2e": "ng e2e",
11 | "postinstall": "ng build --prod"
12 | },
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "^6.1.9",
16 | "@angular/cdk": "^6.4.7",
17 | "@angular/cli": "~6.0.8",
18 | "@angular/common": "^6.1.9",
19 | "@angular/compiler": "^6.1.9",
20 | "@angular/compiler-cli": "^6.1.9",
21 | "@angular/core": "^6.1.9",
22 | "@angular/flex-layout": "github:angular/flex-layout-builds",
23 | "@angular/forms": "^6.1.9",
24 | "@angular/http": "^6.1.9",
25 | "@angular/material": "^6.4.7",
26 | "@angular/platform-browser": "^6.1.9",
27 | "@angular/platform-browser-dynamic": "^6.1.9",
28 | "@angular/router": "^6.1.9",
29 | "chart.js": "^2.7.3",
30 | "core-js": "^2.5.4",
31 | "express": "^4.16.3",
32 | "hammerjs": "^2.0.8",
33 | "jquery": "^3.3.1",
34 | "net": "^1.0.2",
35 | "rxjs": "^6.3.3",
36 | "sockjs-client": "^1.3.0",
37 | "stompjs": "^2.3.3",
38 | "typescript": "~2.7.2",
39 | "zone.js": "^0.8.26"
40 | },
41 | "devDependencies": {
42 | "@angular-devkit/build-angular": "^0.11.3",
43 | "@angular/language-service": "^6.1.9",
44 | "@types/jasmine": "^2.8.9",
45 | "@types/jasminewd2": "^2.0.5",
46 | "@types/node": "~8.9.4",
47 | "codelyzer": "~4.2.1",
48 | "jasmine-core": "~2.99.1",
49 | "jasmine-spec-reporter": "~4.2.1",
50 | "karma": "~1.7.1",
51 | "karma-chrome-launcher": "~2.2.0",
52 | "karma-coverage-istanbul-reporter": "^2.0.4",
53 | "karma-jasmine": "~1.1.1",
54 | "karma-jasmine-html-reporter": "^0.2.2",
55 | "protractor": "^5.4.1",
56 | "ts-node": "~5.0.1",
57 | "tslint": "~5.9.1"
58 | },
59 | "engines": {
60 | "node": "8.11.3",
61 | "npm": "5.6.0"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/proxy.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "/": {
3 | "target": "http://localhost:8080",
4 | "secure": false
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express'),
2 | path = require('path');
3 |
4 | const app = express();
5 |
6 | app.use(express.static('./dist/erp-mes-frontend'));
7 |
8 | app.get('/*', (req, res) => {
9 | res.sendFile(path.join(__dirname, '/dist/erp-mes-frontend/index.html'));
10 | });
11 |
12 | app.listen(process.env.PORT || 8080, () => {
13 | console.log('Server started');
14 | })
--------------------------------------------------------------------------------
/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 | @import "../variables";
2 |
3 | mat-drawer {
4 | background-color: $light;
5 | }
6 |
7 | mat-drawer-container {
8 | height: 100%;
9 | background-color: white;
10 | }
11 |
12 | mat-expansion-panel {
13 | margin: 0;
14 | background-color: $normal;
15 | }
16 |
17 | .mat-nav-list[dense] {
18 | padding-top: 0;
19 | background-color: $light;
20 | }
21 |
22 | mat-expansion-panel-header {
23 | padding: 0 20px;
24 | }
25 |
26 | mat-icon {
27 | font-size: 22px !important;
28 | }
29 |
30 | mat-card {
31 | border-radius: 0;
32 | padding: 15px 15px 15px 20px;
33 | background-color: $dark;
34 | &:hover {
35 | cursor: pointer;
36 | }
37 | }
38 |
39 | .open-button {
40 | background-color: $dark;
41 | box-shadow: none;
42 | color: black;
43 | border: none;
44 | cursor: pointer;
45 | position: fixed;
46 | bottom: 30px;
47 | right: 30px;
48 | z-index: 30;
49 | }
50 |
51 | .send-button {
52 | background-color: $dark;
53 | box-shadow: none;
54 | color: black;
55 | border: none;
56 | cursor: pointer;
57 | position: fixed;
58 | bottom: 95px;
59 | right: 30px;
60 | }
61 |
62 | h3 {
63 | margin: 10px auto;
64 | text-align: center;
65 | }
66 |
67 | .popup {
68 | z-index: 20;
69 | display: none;
70 | position: fixed;
71 | bottom: 15px;
72 | right: 15px;
73 | background-color: $normal;
74 | min-width: 400px;
75 | min-height: 400px;
76 | max-width: 400px;
77 | }
78 |
79 | #chat {
80 | overflow: scroll;
81 | overflow-x: hidden;
82 | text-align: left;
83 | height: 40vh;
84 | width: auto;
85 | background-color: $light;
86 | margin: 10px 10px 0 10px;
87 | }
88 |
89 | .popup textarea {
90 | min-width: 300px;
91 | min-height: 120px;
92 | text-align: left;
93 | margin: 10px;
94 | border: none;
95 | resize: none;
96 | }
97 |
98 | .popup textarea:focus {
99 | background-color: $light;
100 | outline: none;
101 | }
102 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 | import {Token} from './token';
3 | import {Router} from '@angular/router';
4 | import {SetupService} from './services/setup.service';
5 | import {LoginService} from './services/login.service';
6 | import {BACKEND_URL, FRONTEND_URL} from './globals';
7 | import * as Stomp from 'stompjs';
8 | import * as SockJS from 'sockjs-client';
9 | import $ from 'jquery';
10 |
11 | @Component({
12 | selector: 'app-root',
13 | templateUrl: './app.component.html',
14 | styleUrls: ['./app.component.scss']
15 | })
16 | export class AppComponent {
17 | collapsedHeight = '48px';
18 | expandedHeight = '48px';
19 | serverUrl = BACKEND_URL + 'socket';
20 | stompClient;
21 |
22 | constructor(private token: Token, private router: Router, private setupService: SetupService,
23 | private loginService: LoginService) {
24 | if (!this.isUserLoggedIn()) {
25 | this.setupService.checkSetup().subscribe(res => {
26 | if (res) {
27 | this.router.navigate(['login']);
28 | } else {
29 | this.router.navigate(['setup']);
30 | }
31 | });
32 | } else if (window.location.href === FRONTEND_URL) {
33 | this.loginService.fetchUser().subscribe(user => {
34 | this.router.navigate(['employees', user.id]);
35 | });
36 | }
37 | this.initializeWebSocketConnection();
38 | }
39 |
40 | initializeWebSocketConnection() {
41 | const ws = new SockJS(this.serverUrl);
42 | this.stompClient = Stomp.over(ws);
43 | const that = this;
44 | this.stompClient.connect({}, function () {
45 | that.stompClient.debug = () => {};
46 | that.stompClient.subscribe('/chat', (message) => {
47 | if (message.body) {
48 | $('#chat').append('
' + message.body + '
');
49 | }
50 | });
51 | });
52 | }
53 |
54 | sendMessage(message) {
55 | this.loginService.fetchUser().subscribe(res => {
56 | const name = res.firstName.charAt(0) + '. ' + res.lastName;
57 | this.stompClient.send('/app/send/message', {}, name + ' | ' + message);
58 | $('#input').val('');
59 | window.setInterval(function() {
60 | const elem = document.getElementById('chat');
61 | elem.scrollTop = elem.scrollHeight;
62 | }, 300);
63 | });
64 | }
65 |
66 | isUserLoggedIn(): boolean {
67 | return this.token.getToken() != null;
68 | }
69 |
70 | visitMyProfile() {
71 | this.loginService.fetchUser().subscribe(user => {
72 | this.router.navigate(['employees', user.id]);
73 | });
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/communication/emails/add-email/add-email.component.html:
--------------------------------------------------------------------------------
1 | Write email
2 |
3 |
4 |
5 | To
6 |
7 |
8 |
9 |
10 | Subject
11 |
12 |
13 |
14 |
15 | Content
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/app/communication/emails/add-email/add-email.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/communication/emails/conversation/conversation.component.html:
--------------------------------------------------------------------------------
1 | Email #{{selectedEmail.id}} - {{selectedEmail.email}}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Type: {{email.emailType}}
10 |
11 |
12 |
13 | Address: {{email.email}}
14 |
15 |
16 |
17 | Date and time: {{email.timestamp | date: 'yyyy-MM-dd, HH:mm'}}
18 |
19 |
20 |
21 | Subject: {{email.subject}}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/app/communication/emails/conversation/conversation.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .content {
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | button {
9 | margin-right: 0;
10 | }
11 |
12 | .email {
13 | margin: 15px;
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/communication/emails/inbox/inbox.component.html:
--------------------------------------------------------------------------------
1 | Inbox
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | From: {{email.email}}
10 |
11 |
12 |
13 | Date and time: {{email.timestamp | date: 'yyyy-MM-dd, HH:mm'}}
14 |
15 |
16 |
17 | Subject: {{email.subject}}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/app/communication/emails/inbox/inbox.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .content {
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | button {
9 | margin-right: 0;
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/communication/emails/inbox/inbox.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {EmailEntity} from '../../../types';
3 | import {EmailService} from '../../../services/email.service';
4 | import {Router} from '@angular/router';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {Observable} from "rxjs/index";
7 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
8 |
9 | @Component({
10 | selector: 'app-inbox',
11 | templateUrl: './inbox.component.html',
12 | styleUrls: ['./inbox.component.scss']
13 | })
14 | export class InboxComponent implements OnInit {
15 |
16 | emails: Array;
17 | areEmailsLoaded: boolean;
18 | obs: Observable;
19 | dataSource: MatTableDataSource = new MatTableDataSource([]);
20 | paginator: any;
21 |
22 | constructor(private emailService: EmailService, private router: Router, private dialog: MatDialog) {
23 | }
24 |
25 | @ViewChild(MatPaginator)
26 | set pagination(paginator: MatPaginator) {
27 | this.paginator = paginator;
28 | this.dataSource.paginator = this.paginator;
29 | }
30 |
31 | ngOnInit() {
32 | this.fetchEmails();
33 | }
34 |
35 | fetchEmails() {
36 | this.emailService.fetchReceivedEmails().subscribe(res => this.emails = res,
37 | err => {
38 | if (err.status == 401) {
39 | this.router.navigate(['/login']);
40 | } else {
41 | this.showError(err);
42 | }
43 | },
44 | () => {
45 | this.areEmailsLoaded = true;
46 | this.dataSource = new MatTableDataSource(this.emails);
47 | this.obs = this.dataSource.connect();
48 | });
49 | }
50 |
51 | sendEmail() {
52 | this.router.navigate(['/emails/add']);
53 | }
54 |
55 | showError(err) {
56 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
57 | width: '700px',
58 | data: {
59 | error: err.error,
60 | status: err.status
61 | }
62 | });
63 |
64 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/app/communication/emails/outbox/outbox.component.html:
--------------------------------------------------------------------------------
1 | Outbox
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | To: {{email.email}}
10 |
11 |
12 |
13 | Date and time: {{email.timestamp | date: 'yyyy-MM-dd, HH:mm'}}
14 |
15 |
16 |
17 | Subject: {{email.subject}}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/app/communication/emails/outbox/outbox.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .content {
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | button {
9 | margin-right: 0;
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/communication/emails/outbox/outbox.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {EmailEntity} from '../../../types';
3 | import {EmailService} from '../../../services/email.service';
4 | import {Router} from '@angular/router';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {Observable} from "rxjs/index";
7 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
8 |
9 | @Component({
10 | selector: 'app-outbox',
11 | templateUrl: './outbox.component.html',
12 | styleUrls: ['./outbox.component.scss']
13 | })
14 | export class OutboxComponent implements OnInit {
15 |
16 | emails: Array;
17 | areEmailsLoaded: boolean;
18 | obs: Observable;
19 | dataSource: MatTableDataSource = new MatTableDataSource([]);
20 | paginator: any;
21 |
22 | constructor(private emailService: EmailService, private router: Router, private dialog: MatDialog) {
23 | }
24 |
25 | @ViewChild(MatPaginator)
26 | set pagination(paginator: MatPaginator) {
27 | this.paginator = paginator;
28 | this.dataSource.paginator = this.paginator;
29 | }
30 |
31 | ngOnInit() {
32 | this.fetchEmails();
33 | }
34 |
35 | fetchEmails() {
36 | this.emailService.fetchSentEmails().subscribe(res => this.emails = res,
37 | err => {
38 | if (err.status == 401) {
39 | this.router.navigate(['/login']);
40 | } else {
41 | this.showError(err);
42 | }
43 | },
44 | () => {
45 | this.areEmailsLoaded = true;
46 | this.dataSource = new MatTableDataSource(this.emails);
47 | this.obs = this.dataSource.connect();
48 | });
49 | }
50 |
51 | sendEmail() {
52 | this.router.navigate(['/emails/add']);
53 | }
54 |
55 | showError(err) {
56 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
57 | width: '700px',
58 | data: {
59 | error: err.error,
60 | status: err.status
61 | }
62 | });
63 |
64 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/app/communication/emails/reply-dialog/reply-dialog.component.html:
--------------------------------------------------------------------------------
1 | Type your email:
2 | {{error}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/app/communication/emails/reply-dialog/reply-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/communication/emails/reply-dialog/reply-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
3 | import {EmailEntityRequest} from "../../../types";
4 | import {EmailService} from "../../../services/email.service";
5 | import {FormControl, FormGroup, Validators} from "@angular/forms";
6 |
7 | export interface DialogData {
8 | email: string;
9 | }
10 |
11 | @Component({
12 | selector: 'app-reply-dialog',
13 | templateUrl: './reply-dialog.component.html',
14 | styleUrls: ['./reply-dialog.component.scss']
15 | })
16 | export class ReplyDialogComponent {
17 |
18 | form: FormGroup;
19 | subject: FormControl;
20 | fullContent: FormControl;
21 | content = [];
22 | emailEntityRequest: EmailEntityRequest;
23 | error: string;
24 | shouldShowError: boolean;
25 |
26 | constructor(public dialogRef: MatDialogRef,
27 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
28 | private emailService: EmailService) {
29 | this.setupFormControls();
30 | this.form = new FormGroup({
31 | "subject": this.subject,
32 | "content": this.fullContent,
33 | });
34 | }
35 |
36 | setupFormControls() {
37 | this.subject = new FormControl('', [
38 | Validators.required
39 | ]);
40 | this.fullContent = new FormControl('', [
41 | Validators.required
42 | ]);
43 | }
44 |
45 | cancel() {
46 | this.dialogRef.close(null);
47 | }
48 |
49 | submit() {
50 | this.divideContent();
51 | this.emailEntityRequest = {
52 | email: this.data.email,
53 | subject: this.subject.value,
54 | content: this.content
55 | };
56 | this.emailService.sendEmail(this.emailEntityRequest)
57 | .subscribe(res => {
58 | },
59 | err => {
60 | this.shouldShowError = true;
61 | this.error = err.error;
62 | },
63 | () => {
64 | this.dialogRef.close(null);
65 | });
66 | }
67 |
68 | divideContent() {
69 | let i: number;
70 | let lastInd = 0;
71 | const threshold = 250;
72 | for (i = 0; i < Math.floor(this.fullContent.value.length / threshold); i++) {
73 | const firstInd = lastInd;
74 | const tempString = this.fullContent.value.substring(0, (i + 1) * threshold);
75 | lastInd = tempString.lastIndexOf(' ') + 1;
76 | this.content[i] = this.fullContent.value.substring(firstInd, lastInd);
77 | }
78 | this.content[i] = this.fullContent.value.substring(lastInd);
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/add-notification/add-notification.component.html:
--------------------------------------------------------------------------------
1 | Add notification
2 |
38 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/add-notification/add-notification.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/notification/notification.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .mat-divider {
4 | margin: 10px 0;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/notification/notification.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Notification} from '../../../types';
3 | import {NotificationService} from '../../../services/notification.service';
4 | import {ActivatedRoute, Router} from '@angular/router';
5 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
6 | import {MatDialog} from '@angular/material';
7 | import {State} from '../../../globals';
8 |
9 | @Component({
10 | selector: 'app-notification',
11 | templateUrl: './notification.component.html',
12 | styleUrls: ['./notification.component.scss']
13 | })
14 | export class NotificationComponent implements OnInit {
15 |
16 | notification: Notification;
17 | isNotificationLoaded = false;
18 | isResolved = State.RESOLVED;
19 |
20 | constructor(private notificationService: NotificationService, private route: ActivatedRoute,
21 | private router: Router, private dialog: MatDialog) {
22 | }
23 |
24 | ngOnInit() {
25 | this.route.params.subscribe(
26 | params => {
27 | this.fetchNotification();
28 | }
29 | );
30 | }
31 |
32 | fetchNotification() {
33 | this.notificationService.fetchOneNotification(this.route.snapshot.params[('id')])
34 | .subscribe(res => {
35 | this.notification = res;
36 | }, err => {
37 | if (err.status === 401) {
38 | this.router.navigate(['/login']);
39 | } else {
40 | this.showError(err, true);
41 | }
42 | }, () => {
43 | this.isNotificationLoaded = true;
44 | });
45 | }
46 |
47 | submitForm() {
48 | this.notificationService.setNextState(this.route.snapshot.params[('id')])
49 | .subscribe(res => {
50 | this.notification = res;
51 | }, err => {
52 | if (err.status === 401) {
53 | this.router.navigate(['/login']);
54 | } else {
55 | this.showError(err, false);
56 | }
57 | }, () => {
58 | this.router.navigate(['/notifications', this.route.snapshot.params[('id')]]);
59 | });
60 | }
61 |
62 | seeEmployee(id: number) {
63 | this.router.navigate(['/employees', id]);
64 | }
65 |
66 | showError(err, redirect: boolean) {
67 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
68 | width: '700px',
69 | data: {
70 | error: err.error,
71 | status: err.status
72 | }
73 | });
74 |
75 | if (redirect) {
76 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/notifications']));
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/notifications/notifications.component.html:
--------------------------------------------------------------------------------
1 | Notifications
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Creation time |
14 | {{row.creationTime | date:'short'}} |
15 |
16 |
17 |
18 | State |
19 | {{row.state | enumeration}} |
20 |
21 |
22 |
23 | Type |
24 | {{row.type | enumeration}} |
25 |
26 |
27 |
28 | ID |
29 | {{row.id}} |
30 |
31 |
32 |
33 | Instruction |
34 | {{row.instruction}} |
35 |
36 |
37 |
38 | Notifier |
39 | {{row.notifier.firstName}} {{row.notifier.lastName}} |
40 |
41 |
42 |
43 | Transferee |
44 |
45 | {{row.transferee ? row.transferee.firstName : null}}
46 | {{row.transferee ? row.transferee.lastName : null}}
47 | |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/notifications/notifications.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/communication/notifications/notifications/notifications.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {NotificationService} from '../../../services/notification.service';
3 | import {Router} from '@angular/router';
4 | import {Notification} from '../../../types';
5 | import {MatDialog, MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
6 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
7 |
8 | @Component({
9 | selector: 'app-notifications',
10 | templateUrl: './notifications.component.html',
11 | styleUrls: ['./notifications.component.scss']
12 | })
13 | export class NotificationsComponent implements OnInit {
14 |
15 | notifications: Array;
16 | areNotificationsLoaded = false;
17 | displayedColumns: string[] = ['creationTime', 'state', 'type', 'id', 'instruction', 'notifier', 'transferee'];
18 | dataSource: MatTableDataSource = new MatTableDataSource();
19 | paginator: any;
20 | sort: any;
21 |
22 | @ViewChild(MatPaginator)
23 | set pagination(paginator: MatPaginator) {
24 | this.paginator = paginator;
25 | this.dataSource.paginator = this.paginator;
26 | }
27 |
28 | @ViewChild(MatSort)
29 | set sorting(sort: MatSort) {
30 | this.sort = sort;
31 | this.dataSource.sort = this.sort;
32 | }
33 |
34 | constructor(private notificationService: NotificationService, private router: Router, private dialog: MatDialog) { }
35 |
36 | ngOnInit() {
37 | this.notificationService.fetchAllNotifications().subscribe(res => {
38 | this.notifications = res;
39 | }, err => {
40 | if (err.status === 401) {
41 | this.router.navigate(['/login']);
42 | } else {
43 | this.showError(err);
44 | }
45 | }, () => {
46 | this.areNotificationsLoaded = true;
47 | this.dataSource = new MatTableDataSource(this.notifications);
48 | });
49 | }
50 |
51 | seeNotification(id: number) {
52 | this.router.navigate(['/notifications', id]);
53 | }
54 |
55 | addNotification() {
56 | this.router.navigate(['/notifications/add']);
57 | }
58 |
59 | applyFilter(filterValue: string) {
60 | this.dataSource.filter = filterValue.trim().toLowerCase();
61 | }
62 |
63 | showError(err) {
64 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
65 | width: '700px',
66 | data: {
67 | error: err.error,
68 | status: err.status
69 | }
70 | });
71 |
72 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/add-suggestion/add-suggestion.component.html:
--------------------------------------------------------------------------------
1 | Add new suggestion
2 |
30 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/add-suggestion/add-suggestion.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/suggestion/suggestion.component.html:
--------------------------------------------------------------------------------
1 | Suggestion
2 |
3 |
4 |
5 |
{{suggestion.name}}
6 |
7 |
{{suggestion.description}}
8 |
9 |
10 |
19 |
20 |
Reported at:
21 |
22 | {{suggestion.creationTime | date: 'short'}}
23 |
24 |
25 |
Reported by:
26 |
27 | {{suggestion.author.firstName}} {{suggestion.author.lastName}}
28 |
29 |
30 |
31 |
Launch at:
32 |
33 | {{suggestion.startTime ? (suggestion.startTime | date: 'short') : 'N/A'}}
34 |
35 |
36 |
Launch by:
37 |
38 | {{suggestion.startEmployee ? (suggestion.startEmployee.firstName + ' ' + suggestion.startEmployee.lastName) : 'N/A'}}
39 |
40 |
41 |
42 |
Ended at:
43 |
44 | {{suggestion.endTime ? (suggestion.endTime | date: 'short') : 'N/A'}}
45 |
46 |
47 |
Ended by:
48 |
49 | {{suggestion.endEmployee ? (suggestion.endEmployee.firstName + ' ' + suggestion.endEmployee.lastName) : 'N/A'}}
50 |
51 |
52 |
53 |
54 |
55 |
Recipients:
56 |
57 |
58 | {{r.firstName}} {{r.lastName}} ({{r.role | enumeration}})
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/suggestion/suggestion.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .mat-divider {
4 | margin: 10px 0;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/suggestion/suggestion.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Suggestion} from '../../../types';
3 | import {SuggestionService} from '../../../services/suggestion.service';
4 | import {ActivatedRoute, Router} from '@angular/router';
5 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
6 | import {MatDialog} from '@angular/material';
7 | import {Phase} from '../../../globals';
8 |
9 | @Component({
10 | selector: 'app-suggestion',
11 | templateUrl: './suggestion.component.html',
12 | styleUrls: ['./suggestion.component.scss']
13 | })
14 | export class SuggestionComponent implements OnInit {
15 |
16 | suggestion: Suggestion;
17 | isSuggestionLoaded = false;
18 | isImplemented = Phase.IMPLEMENTED;
19 |
20 | constructor(private suggestionService: SuggestionService, private route: ActivatedRoute,
21 | private router: Router, private dialog: MatDialog) { }
22 |
23 | ngOnInit() {
24 | this.route.params.subscribe(
25 | params => {
26 | this.fetchSuggestion();
27 | }
28 | );
29 | }
30 |
31 | fetchSuggestion() {
32 | this.suggestionService.fetchOneSuggestion(this.route.snapshot.params[('id')])
33 | .subscribe(res => {
34 | this.suggestion = res;
35 | }, err => {
36 | if (err.status === 401) {
37 | this.router.navigate(['/login']);
38 | } else {
39 | this.showError(err, true);
40 | }
41 | }, () => {
42 | this.isSuggestionLoaded = true;
43 | });
44 | }
45 |
46 | submitForm() {
47 | this.suggestionService.setNextPhase(this.route.snapshot.params[('id')])
48 | .subscribe(res => {
49 | this.suggestion = res;
50 | }, err => {
51 | if (err.status === 401) {
52 | this.router.navigate(['/login']);
53 | } else {
54 | this.showError(err, false);
55 | }
56 | }, () => {
57 | this.router.navigate(['/suggestions', this.route.snapshot.params[('id')]]);
58 | });
59 | }
60 |
61 | seeEmployee(id: number) {
62 | this.router.navigate(['/employees', id]);
63 | }
64 |
65 | showError(err, redirect: boolean) {
66 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
67 | width: '700px',
68 | data: {
69 | error: err.error,
70 | status: err.status
71 | }
72 | });
73 |
74 | if (redirect) {
75 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/suggestions']));
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/suggestions/suggestions.component.html:
--------------------------------------------------------------------------------
1 | Suggestions
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Creation time |
14 | {{row.creationTime | date:'short'}} |
15 |
16 |
17 |
18 | Phase |
19 | {{row.phase | enumeration}} |
20 |
21 |
22 |
23 | ID |
24 | {{row.id}} |
25 |
26 |
27 |
28 | Name |
29 | {{row.name}} |
30 |
31 |
32 |
33 | Author |
34 |
35 | {{row.author.firstName}}
36 | {{row.author.lastName}}
37 | |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/suggestions/suggestions.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/communication/suggestions/suggestions/suggestions.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {Suggestion} from '../../../types';
3 | import {SuggestionService} from '../../../services/suggestion.service';
4 | import {Router} from '@angular/router';
5 | import {MatDialog, MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
6 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
7 |
8 | @Component({
9 | selector: 'app-suggestions',
10 | templateUrl: './suggestions.component.html',
11 | styleUrls: ['./suggestions.component.scss']
12 | })
13 | export class SuggestionsComponent implements OnInit {
14 |
15 | suggestions: Array;
16 | areSuggestionsLoaded = false;
17 | displayedColumns: string[] = ['creationTime', 'phase', 'id', 'name', 'author'];
18 | dataSource: MatTableDataSource = new MatTableDataSource();
19 | paginator: any;
20 | sort: any;
21 |
22 | @ViewChild(MatPaginator)
23 | set pagination(paginator: MatPaginator) {
24 | this.paginator = paginator;
25 | this.dataSource.paginator = this.paginator;
26 | }
27 |
28 | @ViewChild(MatSort)
29 | set sorting(sort: MatSort) {
30 | this.sort = sort;
31 | this.dataSource.sort = this.sort;
32 | }
33 |
34 | constructor(private suggestionService: SuggestionService, private router: Router, private dialog: MatDialog) { }
35 |
36 | ngOnInit() {
37 | this.suggestionService.fetchAllSuggestions().subscribe(res => {
38 | this.suggestions = res;
39 | }, err => {
40 | if (err.status === 401) {
41 | this.router.navigate(['/login']);
42 | } else {
43 | this.showError(err);
44 | }
45 | }, () => {
46 | this.areSuggestionsLoaded = true;
47 | this.dataSource = new MatTableDataSource(this.suggestions);
48 | });
49 | }
50 |
51 | seeSuggestion(id: number) {
52 | this.router.navigate(['/suggestions', id]);
53 | }
54 |
55 | addSuggestion() {
56 | this.router.navigate(['/suggestions/add']);
57 | }
58 |
59 | applyFilter(filterValue: string) {
60 | this.dataSource.filter = filterValue.trim().toLowerCase();
61 | }
62 |
63 | showError(err) {
64 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
65 | width: '700px',
66 | data: {
67 | error: err.error,
68 | status: err.status
69 | }
70 | });
71 |
72 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/app/custom/error-dialog/error-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/app/custom/error-dialog/error-dialog.component.scss:
--------------------------------------------------------------------------------
1 | button {
2 | font-style: italic;
3 | }
4 |
5 | .decline {
6 | color: darkred;
7 | }
8 |
9 | mat-icon {
10 | margin-right: 5px;
11 | margin-left: 15px;
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/custom/error-dialog/error-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
3 |
4 | export interface DialogData {
5 | error: string;
6 | status?: number
7 | }
8 |
9 | @Component({
10 | selector: 'app-error-dialog',
11 | templateUrl: './error-dialog.component.html',
12 | styleUrls: ['./error-dialog.component.scss']
13 | })
14 | export class ErrorDialogComponent {
15 |
16 | constructor(public dialogRef: MatDialogRef,
17 | @Inject(MAT_DIALOG_DATA) public data: DialogData) {
18 | }
19 |
20 | cancel() {
21 | this.dialogRef.close(null);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/globals.ts:
--------------------------------------------------------------------------------
1 | // export const FRONTEND_URL = 'http://localhost:4200/';
2 | export const FRONTEND_URL = 'https://erp-mes-frontend.herokuapp.com/';
3 | // export const BACKEND_URL = 'http://localhost:8080/';
4 | export const BACKEND_URL = 'https://erp-mes-backend.herokuapp.com/';
5 |
6 | export enum Role {
7 | ADMIN = 'ADMIN',
8 | ACCOUNTANT = 'ACCOUNTANT',
9 | ADMIN_ACCOUNTANT = 'ADMIN_ACCOUNTANT',
10 | ANALYST = 'ANALYST',
11 | ADMIN_ANALYST = 'ADMIN_ANALYST',
12 | WAREHOUSE = 'WAREHOUSE',
13 | ADMIN_WAREHOUSE = 'ADMIN_WAREHOUSE'
14 | }
15 |
16 | export enum HolidayType {
17 | VACATION = 'VACATION',
18 | SICK_LEAVE = 'SICK_LEAVE',
19 | PARENTAL_LEAVE = 'PARENTAL_LEAVE',
20 | BEREAVEMENT = 'BEREAVEMENT',
21 | EMERGENCY_CHILD_CARE = 'EMERGENCY_CHILD_CARE'
22 | }
23 |
24 | export enum ApprovalState {
25 | APPROVED = 'APPROVED',
26 | DECLINED = 'DECLINED',
27 | PENDING = 'PENDING'
28 | }
29 |
30 | export enum Category {
31 | TO_DO = 'TO_DO',
32 | DOING = 'DOING',
33 | DONE = 'DONE'
34 | }
35 |
36 | export enum ExpenseType {
37 | SHIPPING = 'SHIPPING',
38 | BILLS = 'BILLS',
39 | RENT = 'RENT',
40 | SALARIES = 'SALARIES',
41 | STOCK = 'STOCK',
42 | SOCIAL_FUND = 'SOCIAL_FUND',
43 | UNEXPECTED = 'UNEXPECTED',
44 | TAXES = 'TAXES'
45 | }
46 |
47 | export enum Status {
48 | WAITING_FOR_PAYMENT = 'WAITING_FOR_PAYMENT',
49 | IN_PROGRESS = 'IN_PROGRESS',
50 | SENT = 'SENT',
51 | DECLINED = 'DECLINED'
52 | }
53 |
54 | export enum State {
55 | REPORTED = 'REPORTED',
56 | IN_PROGRESS = 'IN_PROGRESS',
57 | RESOLVED = 'RESOLVED'
58 | }
59 |
60 | export enum Phase {
61 | REPORTED = 'REPORTED',
62 | IN_IMPLEMENTATION = 'IN_IMPLEMENTATION',
63 | IMPLEMENTED = 'IMPLEMENTED',
64 | }
65 |
66 | export enum Type {
67 | DELIVERY = 'DELIVERY',
68 | ORDER = 'ORDER',
69 | COMPLAINT = 'COMPLAINT',
70 | RETURN = 'RETURN',
71 | OTHER = 'OTHER'
72 | }
73 |
74 | export enum ReturnStatus {
75 | IN_PROGRESS = 'IN_PROGRESS',
76 | ACCEPTED = 'ACCEPTED',
77 | DECLINED = 'DECLINED',
78 | MONEY_RETURNED = 'MONEY_RETURNED'
79 | }
80 |
81 | export enum ComplaintStatus {
82 | IN_PROGRESS = 'IN_PROGRESS',
83 | ACCEPTED = 'ACCEPTED',
84 | DECLINED = 'DECLINED',
85 | MONEY_RETURNED = 'MONEY_RETURNED',
86 | NEW_ITEM_SENT = 'NEW_ITEM_SENT',
87 | REPAIRING_ITEM = 'REPAIRING_ITEM',
88 | REPAIRED_ITEM_SENT = 'REPAIRED_ITEM_SENT',
89 | DECLINED_ITEM_SENT = 'DECLINED_ITEM_SENT'
90 | }
91 |
92 | export enum Resolution {
93 | UNRESOLVED = 'UNRESOLVED',
94 | MONEY_RETURN = 'MONEY_RETURN',
95 | REPAIR = 'REPAIR',
96 | EXCHANGE_FOR_NEW = 'EXCHANGE_FOR_NEW'
97 | }
98 |
99 | export enum EmailType {
100 | SENT = 'SENT',
101 | RECEIVED = 'RECEIVED'
102 | }
103 |
--------------------------------------------------------------------------------
/src/app/interceptor.ts:
--------------------------------------------------------------------------------
1 | import {
2 | HttpErrorResponse,
3 | HttpHandler,
4 | HttpHeaderResponse,
5 | HttpInterceptor,
6 | HttpProgressEvent,
7 | HttpRequest,
8 | HttpResponse,
9 | HttpSentEvent,
10 | HttpUserEvent
11 | } from '@angular/common/http';
12 | import {Injectable} from '@angular/core';
13 | import {Token} from './token';
14 | import {Router} from '@angular/router';
15 | import {Observable} from 'rxjs';
16 | import {tap} from 'rxjs/internal/operators';
17 |
18 | @Injectable()
19 | export class Interceptor implements HttpInterceptor {
20 |
21 | constructor(private token: Token, private router: Router) {
22 | }
23 |
24 | intercept(req: HttpRequest, next: HttpHandler): Observable | HttpUserEvent> {
25 | let authReq = req;
26 | if (this.token.getToken() != null) {
27 | authReq = req.clone({headers: req.headers.set('Authorization', 'Bearer ' + this.token.getToken())});
28 | }
29 | return next.handle(authReq).pipe(
30 | tap((err: any) => {
31 | if (err instanceof HttpErrorResponse) {
32 | if (err.status === 401) {
33 | this.router.navigate(['employees']);
34 | }
35 | }
36 | }
37 | ));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/material.ts:
--------------------------------------------------------------------------------
1 | import {
2 | MatButtonModule, MatCardModule,
3 | MatCheckboxModule, MatDatepickerModule, MatDialogModule,
4 | MatExpansionModule, MatFormFieldModule,
5 | MatDividerModule, MatGridListModule,
6 | MatIconModule, MatInputModule,
7 | MatListModule, MatNativeDateModule, MatSelectModule,
8 | MatSidenavModule, MatTableModule,
9 | MatPaginatorModule, MatProgressSpinnerModule, MatTabsModule
10 | } from '@angular/material';
11 | import {NgModule} from '@angular/core';
12 |
13 | @NgModule({
14 | imports: [
15 | MatButtonModule,
16 | MatCheckboxModule,
17 | MatIconModule,
18 | MatSidenavModule,
19 | MatExpansionModule,
20 | MatListModule,
21 | MatCardModule,
22 | MatProgressSpinnerModule,
23 | MatTableModule,
24 | MatPaginatorModule,
25 | MatFormFieldModule,
26 | MatInputModule,
27 | MatSelectModule,
28 | MatDatepickerModule,
29 | MatNativeDateModule,
30 | MatListModule,
31 | MatSelectModule,
32 | MatTabsModule,
33 | MatDividerModule,
34 | MatGridListModule,
35 | MatDialogModule,
36 | MatExpansionModule
37 | ],
38 | exports: [
39 | MatButtonModule,
40 | MatCheckboxModule,
41 | MatIconModule,
42 | MatSidenavModule,
43 | MatExpansionModule,
44 | MatListModule,
45 | MatCardModule,
46 | MatProgressSpinnerModule,
47 | MatTableModule,
48 | MatPaginatorModule,
49 | MatFormFieldModule,
50 | MatInputModule,
51 | MatSelectModule,
52 | MatDatepickerModule,
53 | MatNativeDateModule,
54 | MatListModule,
55 | MatDialogModule,
56 | MatSelectModule,
57 | MatTabsModule,
58 | MatDividerModule,
59 | MatGridListModule,
60 | MatExpansionModule
61 | ],
62 | })
63 | export class MaterialModule { }
64 |
--------------------------------------------------------------------------------
/src/app/pipes/enumeration.pipe.ts:
--------------------------------------------------------------------------------
1 | import {Pipe, PipeTransform} from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'enumeration'
5 | })
6 | export class EnumerationPipe implements PipeTransform {
7 |
8 | transform(word: string): string {
9 | if (word !== undefined && word !== null) {
10 | word = word[0].toUpperCase() + word.substr(1).toLowerCase();
11 | return word.toString().replace('_', ' ');
12 | }
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/pipes/minute-seconds.pipe.ts:
--------------------------------------------------------------------------------
1 | import {Pipe, PipeTransform} from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'minuteSeconds'
5 | })
6 | export class MinuteSecondsPipe implements PipeTransform {
7 |
8 | transform(value: number): string {
9 | const minutes: number = Math.floor(value / 60);
10 | return minutes + 'm ' + (value - minutes * 60) + 's';
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/pipes/no-comma-number.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'noCommaNumber'
5 | })
6 | export class NoCommaNumberPipe implements PipeTransform {
7 |
8 | transform(value: number): string {
9 | if (value !== undefined && value !== null) {
10 | return value.toString().replace(",", " ");
11 | } else {
12 | return "";
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/pipes/tasks-doing.pipe.ts:
--------------------------------------------------------------------------------
1 | import {Pipe, PipeTransform} from '@angular/core';
2 | import {Task} from '../types';
3 | import {Category} from '../globals';
4 |
5 | @Pipe({
6 | name: 'tasksDoing'
7 | })
8 | export class TasksDoingPipe implements PipeTransform {
9 |
10 | transform(myTasks: Task[]) {
11 | if (!myTasks) {
12 | return myTasks;
13 | }
14 | return myTasks.filter(task => task.category === Category.DOING);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/pipes/tasks-done.pipe.ts:
--------------------------------------------------------------------------------
1 | import {Pipe, PipeTransform} from '@angular/core';
2 | import {Task} from '../types';
3 | import {Category} from '../globals';
4 |
5 | @Pipe({
6 | name: 'tasksDone'
7 | })
8 | export class TasksDonePipe implements PipeTransform {
9 |
10 | transform(myTasks: Task[]) {
11 | if (!myTasks) {
12 | return myTasks;
13 | }
14 | return myTasks.filter(task => task.category === Category.DONE);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/pipes/tasks-todo.pipe.ts:
--------------------------------------------------------------------------------
1 | import {Pipe, PipeTransform} from '@angular/core';
2 | import {Task} from '../types';
3 | import {Category} from '../globals';
4 |
5 | @Pipe({
6 | name: 'tasksTodo'
7 | })
8 | export class TasksTodoPipe implements PipeTransform {
9 |
10 | transform(myTasks: Task[]) {
11 | if (!myTasks) {
12 | return myTasks;
13 | }
14 | return myTasks.filter(task => task.category === Category.TO_DO);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/production/finance/add-expense-dialog/add-expense-dialog.component.html:
--------------------------------------------------------------------------------
1 | Enter expense details:
2 | {{error}}
3 |
4 |
5 |
6 |
7 | {{t}}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/app/production/finance/add-expense-dialog/add-expense-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/production/finance/add-expense-dialog/add-expense-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import {ExpenseRequest} from "../../../types";
3 | import {MatDialogRef} from "@angular/material";
4 | import {ReportService} from "../../../services/report.service";
5 | import {ExpenseType} from "../../../globals";
6 |
7 | @Component({
8 | selector: 'app-add-expense-dialog',
9 | templateUrl: './add-expense-dialog.component.html',
10 | styleUrls: ['./add-expense-dialog.component.scss']
11 | })
12 | export class AddExpenseDialogComponent {
13 |
14 | expenseType: ExpenseType;
15 | types;
16 | amount: number;
17 | error: string;
18 | shouldShowError: boolean;
19 |
20 | constructor(public dialogRef: MatDialogRef,
21 | private reportService: ReportService) {
22 | this.types = Object.keys(ExpenseType);
23 | }
24 |
25 | isFormValid() {
26 | const regexp = new RegExp('\\d{2}');
27 | return this.amount != null && regexp.test(this.amount.toString()) && this.expenseType != null;
28 | }
29 |
30 | cancel() {
31 | this.dialogRef.close(null);
32 | }
33 |
34 | submit() {
35 | const expenseRequest: ExpenseRequest = {
36 | expenseType: this.expenseType,
37 | amount: this.amount
38 | };
39 |
40 | this.reportService.addExpense(expenseRequest).subscribe(res => {
41 | }, err => {
42 | this.shouldShowError = true;
43 | this.error = err.error;
44 | }, () => {
45 | this.cancel();
46 | });
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/production/finance/add-income-dialog/add-income-dialog.component.html:
--------------------------------------------------------------------------------
1 | Enter income value:
2 | {{error}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/app/production/finance/add-income-dialog/add-income-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/production/finance/add-income-dialog/add-income-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import {MatDialogRef} from "@angular/material";
3 | import {ReportService} from "../../../services/report.service";
4 |
5 | @Component({
6 | selector: 'app-add-income-dialog',
7 | templateUrl: './add-income-dialog.component.html',
8 | styleUrls: ['./add-income-dialog.component.scss']
9 | })
10 | export class AddIncomeDialogComponent {
11 |
12 | income = 0;
13 | error: string;
14 | shouldShowError: boolean;
15 |
16 | constructor(public dialogRef: MatDialogRef,
17 | private reportService: ReportService) {}
18 |
19 | isFormValid() {
20 | const regexp = new RegExp('\\d{2}');
21 | return this.income != null && regexp.test(this.income.toString());
22 | }
23 |
24 | cancel() {
25 | this.dialogRef.close(null);
26 | }
27 |
28 | submit() {
29 | this.reportService.addIncome(this.income).subscribe(res => {
30 | }, err => {
31 | this.shouldShowError = true;
32 | this.error = err.error;
33 | }, () => {
34 | this.cancel();
35 | });
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/app/production/finance/current-report/current-report.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 10px;
5 | margin-right: 5px;
6 | }
7 |
8 | .date-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | padding-bottom: 10px;
12 | }
13 |
14 | .info {
15 | margin-top: 5px;
16 | }
17 |
18 | button {
19 | margin-left: 10px;
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/production/finance/recalculate-dialog/recalculate-dialog.component.html:
--------------------------------------------------------------------------------
1 | Enter recalculated estimates:
2 | {{error}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/app/production/finance/recalculate-dialog/recalculate-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/production/finance/recalculate-dialog/recalculate-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {ReportService} from "../../../services/report.service";
3 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
4 |
5 | export interface DialogData {
6 | estimatedIncome: number;
7 | estimatedShipping: number;
8 | estimatedBills: number;
9 | rent: number;
10 | salaries: number;
11 | stockCosts: number;
12 | socialFund: number;
13 | unexpected: number;
14 | }
15 |
16 | @Component({
17 | selector: 'app-recalculate-dialog',
18 | templateUrl: './recalculate-dialog.component.html',
19 | styleUrls: ['./recalculate-dialog.component.scss']
20 | })
21 | export class RecalculateDialogComponent {
22 |
23 | error: string;
24 | shouldShowError: boolean;
25 |
26 | constructor(public dialogRef: MatDialogRef,
27 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
28 | private reportService: ReportService) {
29 | }
30 |
31 | isFormValid() {
32 | const regexp = new RegExp('\\d{2}');
33 | return regexp.test(this.data.estimatedIncome.toString()) && regexp.test(this.data.estimatedShipping.toString())
34 | && regexp.test(this.data.estimatedBills.toString()) && regexp.test(this.data.rent.toString())
35 | && regexp.test(this.data.salaries.toString()) && regexp.test(this.data.stockCosts.toString())
36 | && regexp.test(this.data.socialFund.toString()) && regexp.test(this.data.unexpected.toString());
37 | }
38 |
39 | cancel() {
40 | this.dialogRef.close(null);
41 | }
42 |
43 | submit() {
44 | const estimatedCostsRequest = {
45 | estimatedIncome: this.data.estimatedIncome,
46 | estimatedShippingCosts: this.data.estimatedShipping,
47 | estimatedBills: this.data.estimatedBills,
48 | rent: this.data.rent,
49 | salaries: this.data.salaries,
50 | stockCosts: this.data.stockCosts,
51 | socialFund: this.data.socialFund,
52 | unexpected: this.data.unexpected
53 | };
54 | this.reportService.recalculateCosts(estimatedCostsRequest).subscribe(res => {
55 | }, err => {
56 | this.shouldShowError = true;
57 | this.error = err.error;
58 | }, () => {
59 | this.cancel();
60 | });
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/app/production/finance/report/report.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 10px;
5 | margin-right: 5px;
6 | }
7 |
8 | .date-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | padding-bottom: 10px;
12 | }
13 |
14 | .info {
15 | margin-top: 5px;
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/production/finance/report/report.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {ReportService} from '../../../services/report.service';
3 | import {ActivatedRoute, Router} from '@angular/router';
4 | import {MonthlyReport} from '../../../types';
5 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
6 | import {MatDialog} from "@angular/material";
7 |
8 | @Component({
9 | selector: 'app-report',
10 | templateUrl: './report.component.html',
11 | styleUrls: ['./report.component.scss']
12 | })
13 | export class ReportComponent implements OnInit {
14 |
15 | report: MonthlyReport;
16 | isReportLoaded = false;
17 |
18 | constructor(private reportService: ReportService,
19 | private route: ActivatedRoute,
20 | private router: Router,
21 | private dialog: MatDialog) { }
22 |
23 | ngOnInit() {
24 | this.fetchReport(this.route.snapshot.params['id']);
25 | }
26 |
27 | fetchReport(id: number) {
28 | this.reportService.fetchOneReport(id).subscribe(res => {
29 | this.report = res;
30 | }, err => {
31 | if (err.status == 401) {
32 | this.router.navigate(['/login']);
33 | } else {
34 | this.showError(err);
35 | }
36 | }, () => {
37 | this.isReportLoaded = true;
38 | });
39 | }
40 |
41 | showError(err) {
42 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
43 | width: '700px',
44 | data: {
45 | error: err.error,
46 | status: err.status
47 | }
48 | });
49 |
50 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/reports']));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/production/finance/reports/reports.component.html:
--------------------------------------------------------------------------------
1 | Monthly reports
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Start date |
14 | {{row.startDate}} |
15 |
16 |
17 |
18 | Expenses |
19 | {{row.overallExpenses}} |
20 |
21 |
22 |
23 | Income |
24 | {{row.overallIncome}} |
25 |
26 |
27 |
28 | Balance |
29 | {{row.balance}} |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/app/production/finance/reports/reports.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/production/finance/reports/reports.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {ReportService} from '../../../services/report.service';
3 | import {Router} from '@angular/router';
4 | import {MonthlyReport} from '../../../types';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-reports',
10 | templateUrl: './reports.component.html',
11 | styleUrls: ['./reports.component.scss']
12 | })
13 | export class ReportsComponent implements OnInit {
14 |
15 | reports: Array;
16 | areReportsLoaded = false;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private reportService: ReportService,
27 | private router: Router, private dialog: MatDialog) { }
28 |
29 | ngOnInit() {
30 | this.fetchReports();
31 | }
32 |
33 | fetchReports() {
34 | this.reportService.fetchAllReports().subscribe(res => {
35 | this.reports = res;
36 | }, err => {
37 | if (err.status == 401) {
38 | this.router.navigate(['/login']);
39 | } else {
40 | this.showError(err);
41 | }
42 | }, () => {
43 | this.areReportsLoaded = true;
44 | this.dataSource = new MatTableDataSource(this.reports);
45 | });
46 | }
47 |
48 | seeReport(id: number) {
49 | this.router.navigate(['/reports', id]);
50 | }
51 |
52 | showError(err) {
53 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
54 | width: '700px',
55 | data: {
56 | error: err.error,
57 | status: err.status
58 | }
59 | });
60 |
61 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/app/production/planning/planning/planning.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 10px;
5 | margin-right: 5px;
6 | }
7 |
8 | .daily-plan-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | }
12 |
13 | .info {
14 | margin-top: 20px;
15 | }
16 |
17 | .alert {
18 | display: inline-flex;
19 | vertical-align: middle;
20 | color: crimson;
21 | font-style: italic;
22 | }
23 |
24 | .special {
25 | display: inline-flex;
26 | vertical-align: middle;
27 | color: deeppink;
28 | font-style: italic;
29 | }
30 |
31 | .alert-label {
32 | padding-top: 22px;
33 | padding-left: 25px;
34 | }
35 |
36 | .title {
37 | padding-bottom: 0;
38 | }
39 |
--------------------------------------------------------------------------------
/src/app/production/planning/show-special-plan-dialog/show-special-plan-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{data.specialPlan.description}}
4 |
5 |
6 |
7 | Date: {{data.specialPlan.day}}
8 |
9 |
10 |
11 | Employees per day: {{data.specialPlan.employeesPerDay}}
12 |
13 |
14 |
15 | Orders per day: {{data.specialPlan.ordersPerDay}}
16 |
17 |
18 |
19 | Returns per day: {{data.specialPlan.returnsPerDay}}
20 |
21 |
22 |
23 | Complaints resolved per day: {{data.specialPlan.complaintsResolvedPerDay}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/app/production/planning/show-special-plan-dialog/show-special-plan-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .description {
2 | margin: 15px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/production/planning/show-special-plan-dialog/show-special-plan-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject, OnInit} from '@angular/core';
2 | import {SpecialPlan} from "../../../types";
3 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
4 |
5 | export interface DialogData {
6 | specialPlan: SpecialPlan;
7 | }
8 |
9 | @Component({
10 | selector: 'app-show-special-plan-dialog',
11 | templateUrl: './show-special-plan-dialog.component.html',
12 | styleUrls: ['./show-special-plan-dialog.component.scss']
13 | })
14 | export class ShowSpecialPlanDialogComponent {
15 |
16 | constructor(public dialogRef: MatDialogRef,
17 | @Inject(MAT_DIALOG_DATA) public data: DialogData) {}
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plan-dialog/special-plan-dialog.component.html:
--------------------------------------------------------------------------------
1 | Insert special plan details
2 | {{error}}
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 | Description
15 |
16 |
17 |
18 |
19 | Employees per day
20 |
21 |
22 |
23 |
24 | Orders per day
25 |
26 |
27 |
28 |
29 | Returns per day
30 |
31 |
32 |
33 |
34 | Complaints resolved per day
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plan-dialog/special-plan-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plan-no-date-dialog/special-plan-no-date-dialog.component.html:
--------------------------------------------------------------------------------
1 | Special plan for: {{data.date}}
2 | {{error}}
3 |
4 |
5 |
6 |
7 | Description
8 |
9 |
10 |
11 |
12 | Employees per day
13 |
14 |
15 |
16 |
17 | Orders per day
18 |
19 |
20 |
21 |
22 | Returns per day
23 |
24 |
25 |
26 |
27 | Complaints resolved per day
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plan-no-date-dialog/special-plan-no-date-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plans/special-plans.component.html:
--------------------------------------------------------------------------------
1 | Special plans
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Description |
14 | {{row.description}} |
15 |
16 |
17 |
18 | Day |
19 | {{row.day}} |
20 |
21 |
22 |
23 | Number of employees |
24 | {{row.employeesPerDay}} |
25 |
26 |
27 |
28 | Orders |
29 | {{row.ordersPerDay}} |
30 |
31 |
32 |
33 | Returns |
34 | {{row.returnsPerDay}} |
35 |
36 |
37 |
38 | Complaints |
39 | {{row.complaintsResolvedPerDay}} |
40 |
41 |
42 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plans/special-plans.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | tr {
4 | &:hover {
5 | cursor: default;
6 | background-color: $light;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/production/planning/special-plans/special-plans.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {PlanningService} from '../../../services/planning.service';
3 | import {SpecialPlan} from '../../../types';
4 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
5 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
6 | import {Router} from "@angular/router";
7 |
8 | @Component({
9 | selector: 'app-special-plans',
10 | templateUrl: './special-plans.component.html',
11 | styleUrls: ['./special-plans.component.scss']
12 | })
13 | export class SpecialPlansComponent implements OnInit {
14 |
15 | specialPlans: Array;
16 | arePlansLoaded = false;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private planningService: PlanningService, private router: Router, private dialog: MatDialog) {}
27 |
28 | ngOnInit() {
29 | this.planningService.fetchSpecialPlans().subscribe(res => {
30 | this.specialPlans = res;
31 | }, err => {
32 | if (err.status == 401) {
33 | this.router.navigate(['/login']);
34 | } else {
35 | this.showError(err);
36 | }
37 | }, () => {
38 | this.arePlansLoaded = true;
39 | this.dataSource = new MatTableDataSource(this.specialPlans);
40 | });
41 | }
42 |
43 | showError(err) {
44 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
45 | width: '700px',
46 | data: {
47 | error: err.error,
48 | status: err.status
49 | }
50 | });
51 |
52 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/app/production/planning/update-daily-plan/update-daily-plan.component.html:
--------------------------------------------------------------------------------
1 | Update Daily Plan
2 |
3 |
4 |
5 | Employees per day
6 |
7 |
8 |
9 |
10 | Orders per day
11 |
12 |
13 |
14 |
15 | Returns per day
16 |
17 |
18 |
19 |
20 | Complaints resolved per day
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/app/production/planning/update-daily-plan/update-daily-plan.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/production/tasks/add-task/add-task.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/production/tasks/assignment/assignment.component.html:
--------------------------------------------------------------------------------
1 | Assignment tasks
2 |
37 |
--------------------------------------------------------------------------------
/src/app/production/tasks/assignment/assignment.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/production/tasks/indicators/indicators.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .row {
4 | margin: 2vh 0;
5 | }
6 |
7 | .grid {
8 | margin: 0;
9 | min-width: 0;
10 | }
11 |
12 | p {
13 | margin-top: 0.8vw;
14 | margin-left: 9vh;
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/production/tasks/kanban/kanban.component.html:
--------------------------------------------------------------------------------
1 | Kanban board
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{e.firstName}} {{e.lastName}} ({{e.role | enumeration}})
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
ID: {{myTask.id}} Type: {{myTask.type ? myTask.type : 'N/A'}}
17 |
18 |
{{myTask.name}}
19 |
20 |
Created: {{myTask.creationTime | date:'short'}}
21 |
22 |
Deadline: {{myTask.deadline | date:'short'}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
ID: {{myTask.id}} Type: {{myTask.type ? myTask.type : 'N/A'}}
30 |
31 |
{{myTask.name}}
32 |
33 |
Started: {{myTask.startTime | date:'short'}}
34 |
35 |
Deadline: {{myTask.deadline | date:'short'}}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
ID: {{myTask.id}} Type: {{myTask.type ? myTask.type : 'N/A'}}
43 |
44 |
{{myTask.name}}
45 |
46 |
Ended: {{myTask.endTime | date:'short'}}
47 |
48 |
Deadline: {{myTask.deadline | date:'short'}}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/app/production/tasks/kanban/kanban.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-select {
4 | margin-bottom: 3vh;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/production/tasks/kanban/kanban.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Employee, Task} from '../../../types';
3 | import {TaskService} from '../../../services/task.service';
4 | import {ActivatedRoute, Router} from '@angular/router';
5 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
6 | import {MatDialog} from '@angular/material';
7 | import {EmployeeService} from '../../../services/employee.service';
8 |
9 | @Component({
10 | selector: 'app-kanban',
11 | templateUrl: './kanban.component.html',
12 | styleUrls: ['./kanban.component.scss']
13 | })
14 | export class KanbanComponent implements OnInit {
15 |
16 | employees: Array;
17 | tasks: Array;
18 | areEmployeesLoaded = false;
19 | areTasksLoaded = false;
20 | currentId: number;
21 |
22 | constructor(private taskService: TaskService, private router: Router, private route: ActivatedRoute,
23 | private dialog: MatDialog, private employeeService: EmployeeService) {
24 | }
25 |
26 | ngOnInit() {
27 | this.route.params.subscribe(
28 | params => {
29 | this.fetchKanban();
30 | }
31 | );
32 | }
33 |
34 | fetchKanban() {
35 | this.currentId = +this.route.snapshot.params['id'];
36 | this.employeeService.fetchAllEmployees()
37 | .subscribe(res => {
38 | this.employees = res;
39 | }, err => {
40 | if (err.status == 401) {
41 | this.router.navigate(['/login']);
42 | } else {
43 | this.showError(err);
44 | }
45 | }, () => {
46 | this.areEmployeesLoaded = true;
47 | });
48 | this.taskService.fetchTasksByAssignee(this.route.snapshot.params[('id')])
49 | .subscribe(res => {
50 | this.tasks = res;
51 | }, err => {
52 | if (err.status == 401) {
53 | this.router.navigate(['/login']);
54 | } else {
55 | this.showError(err);
56 | }
57 | }, () => {
58 | this.areTasksLoaded = true;
59 | });
60 | }
61 |
62 | seeTask(id: number) {
63 | this.router.navigate(['/tasks', id]);
64 | }
65 |
66 | seeKanban(id: number) {
67 | this.router.navigate(['/kanban', id]);
68 | }
69 |
70 | showError(err) {
71 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
72 | width: '700px',
73 | data: {
74 | error: err.error,
75 | status: err.status
76 | }
77 | });
78 |
79 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/app/production/tasks/task/task.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | .mat-divider {
4 | margin: 10px 0;
5 | }
6 |
7 | mat-expansion-panel {
8 | margin: 0;
9 | background-color: $normal;
10 | }
11 |
12 | mat-expansion-panel-header {
13 | padding: 0 20px;
14 | }
15 |
16 | .expansion-panel-paragraph {
17 | padding: 5px 20px;
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/production/tasks/task/task.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {TaskService} from '../../../services/task.service';
3 | import {ActivatedRoute, Router} from '@angular/router';
4 | import {Task} from '../../../types';
5 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
6 | import {MatDialog} from '@angular/material';
7 | import {Category} from '../../../globals';
8 |
9 | @Component({
10 | selector: 'app-task',
11 | templateUrl: './task.component.html',
12 | styleUrls: ['./task.component.scss']
13 | })
14 | export class TaskComponent implements OnInit {
15 |
16 | task: Task;
17 | isTaskLoaded = false;
18 | isDone = Category.DONE;
19 |
20 | constructor(private taskService: TaskService, private route: ActivatedRoute,
21 | private router: Router, private dialog: MatDialog) { }
22 |
23 | ngOnInit() {
24 | this.route.params.subscribe(
25 | params => {
26 | this.fetchTask();
27 | }
28 | );
29 | }
30 |
31 | fetchTask() {
32 | this.taskService.fetchOneTask(this.route.snapshot.params[('id')])
33 | .subscribe(res => {
34 | this.task = res;
35 | }, err => {
36 | if (err.status === 401) {
37 | this.router.navigate(['/login']);
38 | } else {
39 | this.showError(err, true);
40 | }
41 | }, () => {
42 | this.isTaskLoaded = true;
43 | });
44 | }
45 |
46 | setNextCategory() {
47 | this.taskService.setNextCategory(this.route.snapshot.params[('id')])
48 | .subscribe(res => {
49 | this.task = res;
50 | }, err => {
51 | if (err.status === 401) {
52 | this.router.navigate(['/login']);
53 | } else {
54 | this.showError(err, false);
55 | }
56 | }, () => {
57 | this.router.navigate(['/tasks']);
58 | });
59 | }
60 |
61 | assignToMe() {
62 | this.taskService.assignToMe(this.route.snapshot.params[('id')])
63 | .subscribe(res => {
64 | this.task = res;
65 | }, err => {
66 | if (err.status === 401) {
67 | this.router.navigate(['/login']);
68 | } else {
69 | this.showError(err, false);
70 | }
71 | }, () => {
72 | this.router.navigate(['/tasks']);
73 | });
74 | }
75 |
76 | seeTask(id: number) {
77 | this.router.navigate(['/tasks', id]);
78 | }
79 |
80 | showError(err, redirect: boolean) {
81 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
82 | width: '700px',
83 | data: {
84 | error: err.error,
85 | status: err.status
86 | }
87 | });
88 |
89 | if (redirect) {
90 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/tasks']));
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/app/production/tasks/tasks/tasks.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/production/tasks/tasks/tasks.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {TaskService} from '../../../services/task.service';
3 | import {Router} from '@angular/router';
4 | import {Task} from '../../../types';
5 | import {MatDialog, MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
6 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
7 |
8 | @Component({
9 | selector: 'app-tasks',
10 | templateUrl: './tasks.component.html',
11 | styleUrls: ['./tasks.component.scss']
12 | })
13 | export class TasksComponent implements OnInit {
14 |
15 | tasks: Array;
16 | tasksAssigneeIsNull: Array;
17 | areTasksLoaded = false;
18 | displayedColumns: string[] = ['creationTime', 'deadline', 'category', 'name', 'type', 'assignee', 'id'];
19 | dataSource: MatTableDataSource = new MatTableDataSource();
20 | paginator: any;
21 | sort: any;
22 |
23 | constructor(private taskService: TaskService, private router: Router, private dialog: MatDialog) {
24 | }
25 |
26 | @ViewChild(MatPaginator)
27 | set pagination(paginator: MatPaginator) {
28 | this.paginator = paginator;
29 | this.dataSource.paginator = this.paginator;
30 | }
31 |
32 | @ViewChild(MatSort)
33 | set sorting(sort: MatSort) {
34 | this.sort = sort;
35 | this.dataSource.sort = this.sort;
36 | }
37 |
38 | ngOnInit() {
39 | this.taskService.fetchAllTasks().subscribe(res => {
40 | this.tasks = res;
41 | }, err => {
42 | if (err.status === 401) {
43 | this.router.navigate(['/login']);
44 | } else {
45 | this.showError(err);
46 | }
47 | }, () => {
48 | this.areTasksLoaded = true;
49 | this.dataSource = new MatTableDataSource(this.tasks);
50 | this.tasksAssigneeIsNull = this.tasks.filter((task: Task) => task.assignee == null);
51 | });
52 | }
53 |
54 | seeTask(id: number) {
55 | this.router.navigate(['/tasks', id]);
56 | }
57 |
58 | addTask() {
59 | this.router.navigate(['/tasks/add']);
60 | }
61 |
62 | goToAssignment() {
63 | this.router.navigate(['/assignment']);
64 | }
65 |
66 | applyFilter(filterValue: string) {
67 | this.dataSource.filter = filterValue.trim().toLowerCase();
68 | }
69 |
70 | showError(err) {
71 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
72 | width: '700px',
73 | data: {
74 | error: err.error,
75 | status: err.status
76 | }
77 | });
78 |
79 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/app/security/login/login.component.html:
--------------------------------------------------------------------------------
1 | Sign in
2 |
3 |
4 |
5 | Email
6 |
7 |
8 |
9 |
10 | Password
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/app/security/login/login.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/security/login/login.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 | import {Router} from '@angular/router';
3 | import {LoginService} from '../../services/login.service';
4 | import {Token} from '../../token';
5 | import {FormControl, FormGroup, Validators} from "@angular/forms";
6 | import {ErrorDialogComponent} from "../../custom/error-dialog/error-dialog.component";
7 | import {MatDialog} from "@angular/material";
8 |
9 | @Component({
10 | selector: 'app-login',
11 | templateUrl: './login.component.html',
12 | styleUrls: ['./login.component.scss']
13 | })
14 | export class LoginComponent {
15 |
16 | form: FormGroup;
17 | email: FormControl;
18 | password: FormControl;
19 |
20 | constructor(private router: Router,
21 | private loginService: LoginService,
22 | private token: Token,
23 | private dialog: MatDialog) {
24 | this.setupFormControls();
25 | this.form = new FormGroup({
26 | "email": this.email,
27 | "password": this.password
28 | });
29 | }
30 | setupFormControls() {
31 | this.email = new FormControl('', [
32 | Validators.required,
33 | Validators.email
34 | ]);
35 | this.password = new FormControl('', [
36 | Validators.required
37 | ]);
38 | }
39 |
40 |
41 | login() {
42 | this.loginService.login(this.form.get('email').value, this.form.get('password').value).subscribe(res => {
43 | this.token.saveToken(res.token);
44 | }, err => {
45 | if (err.status == 401) {
46 | this.router.navigate(['/login']);
47 | } else {
48 | this.showError(err);
49 | }
50 | }, () => {
51 | this.loginService.fetchUser().subscribe(res => {
52 | if (!res.passwordValid) {
53 | this.router.navigate(['employees', res.id, 'validate']);
54 | } else {
55 | this.router.navigate(['employees']);
56 | }
57 | }, err => {
58 | this.showError(err);
59 | });
60 | });
61 | }
62 |
63 | showError(err) {
64 | this.dialog.open(ErrorDialogComponent, {
65 | width: '700px',
66 | data: {
67 | error: err.error,
68 | status: err.status
69 | }
70 | });
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/app/security/validate/validate.component.html:
--------------------------------------------------------------------------------
1 | Validate password
2 |
3 |
4 | Password
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/app/security/validate/validate.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/security/validate/validate.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 | import {LoginService} from '../../services/login.service';
3 | import {ActivatedRoute} from '@angular/router';
4 | import {FormControl, FormGroup, Validators} from "@angular/forms";
5 |
6 | @Component({
7 | selector: 'app-validate',
8 | templateUrl: './validate.component.html',
9 | styleUrls: ['./validate.component.scss']
10 | })
11 | export class ValidateComponent {
12 |
13 | form: FormGroup;
14 | password: FormControl;
15 |
16 | constructor(private loginService: LoginService,
17 | private route: ActivatedRoute) {
18 | this.password = new FormControl('', [
19 | Validators.required
20 | ]);
21 | this.form = new FormGroup({
22 | "password": this.password
23 | });
24 | }
25 |
26 | submit() {
27 | this.loginService.validateUser(this.route.snapshot.params['id'], this.form.get('password').value);
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/app/services/complaint.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {Complaint, ShopServiceRequest} from '../types';
3 | import {Observable} from 'rxjs';
4 | import {HttpClient, HttpHeaders} from '@angular/common/http';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class ComplaintService {
11 |
12 | private readonly httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
17 | }
18 |
19 | fetchAllComplaints(): Observable> {
20 | return this.http.get>(BACKEND_URL + 'complaints', {headers: this.httpHeaders});
21 | }
22 |
23 | fetchOneComplaint(id: number): Observable {
24 | return this.http.get(BACKEND_URL + 'complaints/' + id, {headers: this.httpHeaders});
25 | }
26 |
27 | addOneComplaint(request: ShopServiceRequest): Observable {
28 | return this.http.post(BACKEND_URL + 'complaints', request, {headers: this.httpHeaders});
29 | }
30 |
31 | updateComplaintStatus(status: string, id: number): Observable {
32 | return this.http.put(BACKEND_URL + 'complaints/' + id, status, {headers: this.httpHeaders});
33 | }
34 |
35 | updateComplaintResolution(resolution: string, id: number): Observable {
36 | return this.http.put(BACKEND_URL + 'complaints/' + id + '/resolution', resolution,
37 | {headers: this.httpHeaders});
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/services/delivery.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs';
4 | import {Delivery, DeliveryItemRequest, DeliveryRequest} from '../types';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class DeliveryService {
11 |
12 | private httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
17 | }
18 |
19 | fetchAllDeliveries(): Observable> {
20 | return this.http.get>(BACKEND_URL + 'deliveries', {headers: this.httpHeaders});
21 | }
22 |
23 | fetchOneDelivery(id: number): Observable {
24 | return this.http.get(BACKEND_URL + 'deliveries/' + id, {headers: this.httpHeaders});
25 | }
26 |
27 | addNewDelivery(request: DeliveryRequest): Observable {
28 | return this.http.post(BACKEND_URL + 'deliveries', request, {headers: this.httpHeaders});
29 | }
30 |
31 | confirmDelivery(id: number): Observable {
32 | return this.http.post(BACKEND_URL + 'deliveries/' + id, null, {headers: this.httpHeaders});
33 | }
34 |
35 | getRecommendations(): Observable> {
36 | return this.http.get>(BACKEND_URL + 'deliveries/recommended-delivery',
37 | {headers: this.httpHeaders});
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/services/email.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Router} from '@angular/router';
4 | import {Observable} from 'rxjs';
5 | import {EmailEntity, EmailEntityRequest} from '../types';
6 | import {ErrorDialogComponent} from "../custom/error-dialog/error-dialog.component";
7 | import {MatDialog} from "@angular/material";
8 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
9 |
10 | @Injectable({
11 | providedIn: 'root'
12 | })
13 | export class EmailService {
14 |
15 | private httpHeaders: HttpHeaders;
16 |
17 | constructor(private http: HttpClient, private router: Router, private dialog: MatDialog) {
18 | this.httpHeaders = new HttpHeaders()
19 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
20 | }
21 |
22 | fetchReceivedEmails(): Observable> {
23 | return this.http.get>(BACKEND_URL + 'emails/inbox',
24 | {headers: this.httpHeaders});
25 | }
26 |
27 | fetchSentEmails(): Observable> {
28 | return this.http.get>(BACKEND_URL + 'emails/outbox',
29 | {headers: this.httpHeaders});
30 | }
31 |
32 | sendEmail(request: EmailEntityRequest): Observable {
33 | return this.http.post(BACKEND_URL + 'emails', request,
34 | {headers: this.httpHeaders});
35 | }
36 |
37 | reply(request: EmailEntityRequest, id: number): Observable {
38 | return this.http.post(BACKEND_URL + 'emails/' + id, request,
39 | {headers: this.httpHeaders});
40 | }
41 |
42 | fetchConversation(id: number): Observable> {
43 | return this.http.get>(BACKEND_URL + 'emails/' + id,
44 | {headers: this.httpHeaders});
45 | }
46 |
47 | removeMessage(id: number) {
48 | this.http.delete(BACKEND_URL + 'emails/' + id, {headers: this.httpHeaders})
49 | .subscribe(() => {
50 | },
51 | err => {
52 | if (err.status == 401) {
53 | this.router.navigate(['/login']);
54 | } else {
55 | this.showError(err);
56 | }
57 | },
58 | () => {
59 | this.router.navigate(['/emails/inbox']);
60 | });
61 | }
62 |
63 | showError(err) {
64 | this.dialog.open(ErrorDialogComponent, {
65 | width: '700px',
66 | data: {
67 | error: err.error,
68 | status: err.status
69 | }
70 | });
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/app/services/holiday.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {Router} from '@angular/router';
3 | import {HttpClient, HttpHeaders} from '@angular/common/http';
4 | import {Holiday, HolidayRequest} from '../types';
5 | import {Observable} from 'rxjs';
6 | import {ErrorDialogComponent} from "../custom/error-dialog/error-dialog.component";
7 | import {MatDialog} from "@angular/material";
8 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
9 |
10 | @Injectable({
11 | providedIn: 'root'
12 | })
13 | export class HolidayService {
14 |
15 | private httpHeaders: HttpHeaders;
16 |
17 | constructor(private http: HttpClient, private router: Router, private dialog: MatDialog) {
18 | this.httpHeaders = new HttpHeaders()
19 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
20 | }
21 |
22 | fetchHolidays(employeeId: number): Observable> {
23 | return this.http.get>(BACKEND_URL + 'employees/' + employeeId + '/holidays',
24 | {headers: this.httpHeaders});
25 | }
26 |
27 | addHoliday(request: HolidayRequest, employeeId: number) {
28 | this.http.post(BACKEND_URL + 'employees/' + employeeId + '/holidays',
29 | request, {headers: this.httpHeaders})
30 | .subscribe(() => {
31 | },
32 | err => {
33 | if (err.status == 401) {
34 | this.router.navigate(['/login']);
35 | } else {
36 | this.showError(err);
37 | }
38 | },
39 | () => {
40 | this.router.navigate(['/employees', employeeId]);
41 | });
42 | }
43 |
44 | fetchHolidaysToApprove(managerId: number): Observable> {
45 | return this.http.get>(BACKEND_URL + 'employees/' + managerId +
46 | '/subordinates/holiday-requests', {headers: this.httpHeaders});
47 | }
48 |
49 | manageHolidays(managerId: number, employeeId: number, holidayId: number, approve: string): Observable {
50 | return this.http.post(BACKEND_URL + 'employees/' + managerId + '/subordinates/'
51 | + employeeId + '/holidays', holidayId, {
52 | headers: this.httpHeaders,
53 | params: {
54 | approve: approve
55 | }
56 | });
57 | }
58 |
59 | showError(err) {
60 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
61 | width: '700px',
62 | data: {
63 | error: err.error,
64 | status: err.status
65 | }
66 | });
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/app/services/item.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs';
4 | import {Item, ItemRequest} from '../types';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class ItemService {
11 |
12 | private httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL)
17 | .set('Content-Type', 'application/json');
18 | }
19 |
20 | fetchAllItems(): Observable> {
21 | return this.http.get>(BACKEND_URL + 'items', {headers: this.httpHeaders});
22 | }
23 |
24 | fetchOneItem(id: number): Observable- {
25 | return this.http.get
- (BACKEND_URL + 'items/' + id, {headers: this.httpHeaders});
26 | }
27 |
28 | addNewItem(request: ItemRequest): Observable
- {
29 | return this.http.post
- (BACKEND_URL + 'items', request, {headers: this.httpHeaders});
30 | }
31 |
32 | setNewPrice(id: number, price: number): Observable
- {
33 | return this.http.post
- (BACKEND_URL + 'items/' + id, price, {headers: this.httpHeaders});
34 | }
35 |
36 | supplyItem(id: number, quantity: number): Observable
- {
37 | return this.http.post
- (BACKEND_URL + 'items/' + id + '/supply',
38 | quantity, {headers: this.httpHeaders});
39 | }
40 |
41 | buyItem(id: number, quantity: number): Observable
- {
42 | return this.http.post
- (BACKEND_URL + 'items/' + id + '/buy',
43 | quantity, {headers: this.httpHeaders});
44 | }
45 |
46 | setSpecialOffer(percentOff: string, query: string): Observable> {
47 | return this.http.post>(BACKEND_URL + 'set-special-offer', '', {
48 | headers: this.httpHeaders,
49 | params: {
50 | percentOff: percentOff,
51 | query: query
52 | }
53 | });
54 | }
55 |
56 | cancelSpecialOffer(): Observable> {
57 | return this.http.post>(BACKEND_URL + 'cancel-special-offer', '',
58 | {headers: this.httpHeaders});
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/app/services/login.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs';
4 | import {Employee} from '../types';
5 | import {Router} from '@angular/router';
6 | import {ErrorDialogComponent} from "../custom/error-dialog/error-dialog.component";
7 | import {MatDialog} from "@angular/material";
8 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
9 |
10 | @Injectable({
11 | providedIn: 'root'
12 | })
13 | export class LoginService {
14 |
15 | private httpHeaders: HttpHeaders;
16 |
17 | constructor(private http: HttpClient, private router: Router, private dialog: MatDialog) {
18 | this.httpHeaders = new HttpHeaders()
19 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
20 | }
21 |
22 | login(email: string, password: string): Observable {
23 | const credentials = {email: email, password: password};
24 | return this.http.post(BACKEND_URL + 'generate-token', credentials,
25 | {headers: this.httpHeaders});
26 | }
27 |
28 | fetchUser(): Observable {
29 | return this.http.get(BACKEND_URL + 'logged-in-user',
30 | {headers: this.httpHeaders});
31 | }
32 |
33 | validateUser(id: string, password: string) {
34 | this.http.post(BACKEND_URL + 'employees/' + id + '/validate-password', password,
35 | {headers: this.httpHeaders}).subscribe(res => {},
36 | err => {
37 | if (err.status == 401) {
38 | this.router.navigate(['/login']);
39 | } else {
40 | this.showError(err);
41 | }
42 | }, () => {
43 | this.router.navigate(['employees', id]);
44 | });
45 | }
46 |
47 | showError(err) {
48 | this.dialog.open(ErrorDialogComponent, {
49 | width: '700px',
50 | data: {
51 | error: err.error,
52 | status: err.status
53 | }
54 | });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/app/services/notification.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Notification, NotificationRequest} from '../types';
4 | import {Observable} from 'rxjs';
5 | import {BACKEND_URL, FRONTEND_URL} from '../globals';
6 |
7 | @Injectable()
8 | export class NotificationService {
9 |
10 | private httpHeaders: HttpHeaders;
11 |
12 | constructor(private http: HttpClient) {
13 | this.httpHeaders = new HttpHeaders()
14 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
15 | }
16 |
17 | fetchAllNotifications(): Observable> {
18 | return this.http.get>(BACKEND_URL + 'notifications', {headers: this.httpHeaders});
19 | }
20 |
21 | fetchOneNotification(id: number): Observable {
22 | return this.http.get(BACKEND_URL + 'notifications/' + id, {headers: this.httpHeaders});
23 | }
24 |
25 | fetchNotificationsByRecipient(id: number): Observable> {
26 | return this.http.get>(BACKEND_URL + 'employees/' + id + '/notifications', {headers: this.httpHeaders});
27 | }
28 |
29 | addNotification(notificationRequest: NotificationRequest): Observable {
30 | return this.http.post(BACKEND_URL + 'notifications', notificationRequest, {headers: this.httpHeaders});
31 | }
32 |
33 | setNextState(id: number): Observable {
34 | return this.http.put(BACKEND_URL + 'notifications/' + id, {headers: this.httpHeaders});
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/app/services/order.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs';
4 | import {Order, ShopServiceRequest} from '../types';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class OrderService {
11 |
12 | private readonly httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
17 | }
18 |
19 | fetchAllOrders(): Observable> {
20 | return this.http.get>(BACKEND_URL + 'orders', {headers: this.httpHeaders});
21 | }
22 |
23 | fetchOneOrder(id: number): Observable {
24 | return this.http.get(BACKEND_URL + 'orders/' + id, {headers: this.httpHeaders});
25 | }
26 |
27 | addOneOrder(orderRequest: ShopServiceRequest): Observable {
28 | return this.http.post(BACKEND_URL + 'orders', orderRequest, {headers: this.httpHeaders});
29 | }
30 |
31 | updateOrderStatus(status: string, id: number): Observable {
32 | return this.http.put(BACKEND_URL + 'orders/' + id, status, {headers: this.httpHeaders});
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/app/services/planning.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs/index';
4 | import {DailyPlan, DailyPlanRequest, SpecialPlan, SpecialPlanRequest} from '../types';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class PlanningService {
11 |
12 | private httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
17 | }
18 |
19 | fetchDailyPlan(): Observable {
20 | return this.http.get(BACKEND_URL + 'daily-plan', {headers: this.httpHeaders});
21 | }
22 |
23 | updateDailyPlan(request: DailyPlanRequest): Observable {
24 | return this.http.put(BACKEND_URL + 'daily-plan', request,
25 | {headers: this.httpHeaders});
26 | }
27 |
28 | fetchSpecialPlans(): Observable> {
29 | return this.http.get>(BACKEND_URL + 'special-plans',
30 | {headers: this.httpHeaders});
31 | }
32 |
33 | fetchSpecialPlan(day: string): Observable {
34 | return this.http.get(BACKEND_URL + 'special-plan', {
35 | headers: this.httpHeaders,
36 | params: {
37 | day: day
38 | }
39 | });
40 | }
41 |
42 | addSpecialPlan(request: SpecialPlanRequest): Observable {
43 | return this.http.post(BACKEND_URL + 'special-plan', request,
44 | {headers: this.httpHeaders});
45 | }
46 |
47 | countScheduledOrders(when: string): Observable {
48 | return this.http.get(BACKEND_URL + 'scheduled-orders', {
49 | headers: this.httpHeaders,
50 | params: {
51 | when: when
52 | }
53 | });
54 | }
55 |
56 | countScheduledReturns(when: string): Observable {
57 | return this.http.get(BACKEND_URL + 'scheduled-returns', {
58 | headers: this.httpHeaders,
59 | params: {
60 | when: when
61 | }
62 | });
63 | }
64 |
65 | countScheduledComplaints(when: string): Observable {
66 | return this.http.get(BACKEND_URL + 'scheduled-complaints', {
67 | headers: this.httpHeaders,
68 | params: {
69 | when: when
70 | }
71 | });
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/app/services/report.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs';
4 | import {CurrentReport, EstimatedCostsRequest, ExpenseRequest, MonthlyReport} from '../types';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class ReportService {
11 |
12 | private httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL)
17 | .set('Content-Type', 'application/json');
18 | }
19 |
20 | fetchAllReports(): Observable> {
21 | return this.http.get>(BACKEND_URL + 'reports',
22 | {headers: this.httpHeaders});
23 | }
24 |
25 | fetchOneReport(id: number): Observable {
26 | return this.http.get(BACKEND_URL + 'reports/' + id,
27 | {headers: this.httpHeaders});
28 | }
29 |
30 | fetchCurrentReport(): Observable {
31 | return this.http.get(BACKEND_URL + 'current-report',
32 | {headers: this.httpHeaders});
33 | }
34 |
35 | recalculateCosts(request: EstimatedCostsRequest): Observable {
36 | return this.http.put(BACKEND_URL + 'current-report', request,
37 | {headers: this.httpHeaders});
38 | }
39 |
40 | addIncome(amount: number): Observable {
41 | return this.http.post(BACKEND_URL + 'current-report/income', amount,
42 | {headers: this.httpHeaders});
43 | }
44 |
45 | addExpense(request: ExpenseRequest): Observable {
46 | return this.http.post(BACKEND_URL + 'current-report/expense', request,
47 | {headers: this.httpHeaders});
48 | }
49 |
50 | fetchRecommendations(): Observable {
51 | return this.http.get(BACKEND_URL + 'current-report/recommended-recalculations',
52 | {headers: this.httpHeaders});
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/app/services/return.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {Return, ShopServiceRequest} from '../types';
3 | import {Observable} from 'rxjs';
4 | import {HttpClient, HttpHeaders} from '@angular/common/http';
5 | import {BACKEND_URL, FRONTEND_URL, ReturnStatus} from "../globals";
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class ReturnService {
11 |
12 | private readonly httpHeaders: HttpHeaders;
13 |
14 | constructor(private http: HttpClient) {
15 | this.httpHeaders = new HttpHeaders()
16 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
17 | }
18 |
19 | fetchAllReturns(): Observable> {
20 | return this.http.get>(BACKEND_URL + 'returns', {headers: this.httpHeaders});
21 | }
22 |
23 | fetchOneReturn(id: number): Observable {
24 | return this.http.get(BACKEND_URL + 'returns/' + id, {headers: this.httpHeaders});
25 | }
26 |
27 | addOneReturn(request: ShopServiceRequest): Observable {
28 | return this.http.post(BACKEND_URL + 'returns', request, {headers: this.httpHeaders});
29 | }
30 |
31 | updateReturnStatus(status: string, id: number): Observable {
32 | return this.http.put(BACKEND_URL + 'returns/' + id, status, {headers: this.httpHeaders});
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/app/services/setup.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Observable} from 'rxjs';
4 | import {AdminRequest, Employee} from "../types";
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable()
8 | export class SetupService {
9 |
10 | private httpHeaders: HttpHeaders;
11 |
12 | constructor(private http: HttpClient) {
13 | this.httpHeaders = new HttpHeaders()
14 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
15 | }
16 |
17 | checkSetup(): Observable {
18 | return this.http.get(BACKEND_URL + 'check-setup', {headers: this.httpHeaders});
19 | }
20 |
21 | setupAdmin(request: AdminRequest): Observable {
22 | return this.http.post(BACKEND_URL + 'setup-admin', request, {headers: this.httpHeaders});
23 | }
24 |
25 | setupTeams(): Observable {
26 | return this.http.post(BACKEND_URL + 'setup-teams', {headers: this.httpHeaders});
27 | }
28 |
29 | setupDailyPlan(): Observable {
30 | return this.http.post(BACKEND_URL + 'setup-daily-plan', {headers: this.httpHeaders});
31 | }
32 |
33 | setupReports(): Observable {
34 | return this.http.post(BACKEND_URL + 'setup-reports', {headers: this.httpHeaders});
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/app/services/suggestion.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Suggestion, SuggestionRequest} from '../types';
4 | import {Observable} from 'rxjs';
5 | import {BACKEND_URL, FRONTEND_URL} from '../globals';
6 |
7 | @Injectable()
8 | export class SuggestionService {
9 |
10 | private readonly httpHeaders: HttpHeaders;
11 |
12 | constructor(private http: HttpClient) {
13 | this.httpHeaders = new HttpHeaders()
14 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
15 | }
16 |
17 | fetchAllSuggestions(): Observable> {
18 | return this.http.get>(BACKEND_URL + 'suggestions', {headers: this.httpHeaders});
19 | }
20 |
21 | fetchOneSuggestion(id: number): Observable {
22 | return this.http.get(BACKEND_URL + 'suggestions/' + id, {headers: this.httpHeaders});
23 | }
24 |
25 | addSuggestion(suggestionRequest: SuggestionRequest): Observable {
26 | return this.http.post(BACKEND_URL + 'suggestions', suggestionRequest, {headers: this.httpHeaders});
27 | }
28 |
29 | setNextPhase(id: number): Observable {
30 | return this.http.put(BACKEND_URL + 'suggestions/' + id, {headers: this.httpHeaders});
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/app/services/task.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {AssignmentRequest, Indicators, Task, TaskRequest} from '../types';
4 | import {Observable} from 'rxjs';
5 | import {BACKEND_URL, FRONTEND_URL} from '../globals';
6 |
7 | @Injectable()
8 | export class TaskService {
9 |
10 | private readonly httpHeaders: HttpHeaders;
11 |
12 | constructor(private http: HttpClient) {
13 | this.httpHeaders = new HttpHeaders()
14 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
15 | }
16 |
17 | fetchAllTasks(): Observable> {
18 | return this.http.get>(BACKEND_URL + 'tasks', {headers: this.httpHeaders});
19 | }
20 |
21 | fetchOneTask(id: number): Observable {
22 | return this.http.get(BACKEND_URL + 'tasks/' + id, {headers: this.httpHeaders});
23 | }
24 |
25 | fetchTasksByAssignee(id: number): Observable> {
26 | return this.http.get>(BACKEND_URL + 'kanban/' + id, {headers: this.httpHeaders});
27 | }
28 |
29 | fetchTasksByAssigneeIsNull(): Observable> {
30 | return this.http.get>(BACKEND_URL + 'assignment', {headers: this.httpHeaders});
31 | }
32 |
33 | addTask(taskRequest: TaskRequest): Observable {
34 | return this.http.post(BACKEND_URL + 'tasks', taskRequest, {headers: this.httpHeaders});
35 | }
36 |
37 | assignToEmployees(assignmentRequest: AssignmentRequest): Observable> {
38 | return this.http.put>(BACKEND_URL + 'assignment', assignmentRequest, {headers: this.httpHeaders});
39 | }
40 |
41 | setNextCategory(id: number): Observable {
42 | return this.http.put(BACKEND_URL + 'tasks/' + id, {headers: this.httpHeaders});
43 | }
44 |
45 | assignToMe(id: number): Observable {
46 | return this.http.put(BACKEND_URL + 'tasks/' + id + '/assign', {headers: this.httpHeaders});
47 | }
48 |
49 | fetchIndicators(id: number): Observable {
50 | return this.http.get(BACKEND_URL + 'indicators/' + id, {headers: this.httpHeaders});
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/services/team.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {HttpClient, HttpHeaders} from '@angular/common/http';
3 | import {Team} from '../types';
4 | import {Observable} from 'rxjs';
5 | import {BACKEND_URL, FRONTEND_URL} from "../globals";
6 |
7 | @Injectable()
8 | export class TeamService {
9 |
10 | private httpHeaders: HttpHeaders;
11 |
12 | constructor(private http: HttpClient) {
13 | this.httpHeaders = new HttpHeaders()
14 | .set('Access-Control-Allow-Origin', FRONTEND_URL);
15 | }
16 |
17 | fetchAllTeams(): Observable> {
18 | return this.http.get>(BACKEND_URL + 'teams', {headers: this.httpHeaders});
19 | }
20 |
21 | fetchOneTeam(id: number): Observable {
22 | return this.http.get(BACKEND_URL + 'teams/' + id, {headers: this.httpHeaders});
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/app/setup/setup.component.html:
--------------------------------------------------------------------------------
1 | Fill system admin details
2 |
3 |
4 |
5 | First name
6 |
7 |
8 |
9 |
10 | Last name
11 |
12 |
13 |
14 |
15 | Email
16 |
17 | {{getErrorMessage()}}
18 |
19 |
20 |
21 | Password
22 |
23 |
24 |
25 |
26 | Account number
27 |
29 | 26 digits
30 |
31 |
32 |
33 | Salary
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/app/setup/setup.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint-resolution-dialog/complaint-resolution-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{error}}
3 |
8 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint-resolution-dialog/complaint-resolution-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .content {
2 | display: inline-flex;
3 | }
4 |
5 | button {
6 | margin-left: 10px;
7 | margin-top: 10px;
8 | align-items: center;
9 | }
10 |
11 | mat-progress-spinner {
12 | margin: auto;
13 | }
14 |
15 | .error {
16 | font-style: italic;
17 | color: darkred;
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint-resolution-dialog/complaint-resolution-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {Complaint} from "../../../types";
3 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
4 | import {ComplaintService} from "../../../services/complaint.service";
5 |
6 | export interface DialogData {
7 | status: string[];
8 | complaint: Complaint;
9 | }
10 |
11 | @Component({
12 | selector: 'app-complaint-resolution-dialog',
13 | templateUrl: './complaint-resolution-dialog.component.html',
14 | styleUrls: ['./complaint-resolution-dialog.component.scss']
15 | })
16 | export class ComplaintResolutionDialogComponent {
17 |
18 | showSpinner: boolean;
19 | error: string;
20 | shouldShowError: boolean;
21 |
22 | constructor(public dialogRef: MatDialogRef,
23 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
24 | private complaintService: ComplaintService) {
25 | }
26 |
27 | cancel() {
28 | this.dialogRef.close(null);
29 | }
30 |
31 | submit(s: string) {
32 | this.showSpinner = true;
33 | this.complaintService.updateComplaintResolution(s, this.data.complaint.id).subscribe(res => {
34 | }, err => {
35 | this.shouldShowError = true;
36 | this.error = err.error;
37 | this.showSpinner = false;
38 | }, () => {
39 | this.cancel();
40 | });
41 | }
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint-status-dialog/complaint-status-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{error}}
3 |
8 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint-status-dialog/complaint-status-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .content {
2 | display: inline-flex;
3 | }
4 |
5 | button {
6 | margin-left: 10px;
7 | margin-top: 10px;
8 | align-items: center;
9 | }
10 |
11 | mat-progress-spinner {
12 | margin: auto;
13 | }
14 |
15 | .error {
16 | font-style: italic;
17 | color: darkred;
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint-status-dialog/complaint-status-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {Complaint, ExpenseRequest} from "../../../types";
3 | import {ComplaintService} from "../../../services/complaint.service";
4 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
5 | import {ReportService} from "../../../services/report.service";
6 | import {ItemService} from "../../../services/item.service";
7 | import {ComplaintStatus, ExpenseType} from "../../../globals";
8 |
9 | export interface DialogData {
10 | status: string[];
11 | complaint: Complaint;
12 | }
13 |
14 | @Component({
15 | selector: 'app-complaint-status-dialog',
16 | templateUrl: './complaint-status-dialog.component.html',
17 | styleUrls: ['./complaint-status-dialog.component.scss']
18 | })
19 | export class ComplaintStatusDialogComponent {
20 |
21 | showSpinner: boolean;
22 | error: string;
23 | shouldShowError: boolean;
24 |
25 | constructor(public dialogRef: MatDialogRef,
26 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
27 | private complaintService: ComplaintService,
28 | private itemService: ItemService,
29 | private reportService: ReportService) {
30 | }
31 |
32 | cancel() {
33 | this.dialogRef.close(null);
34 | }
35 |
36 | submit(s: string) {
37 | this.showSpinner = true;
38 | this.complaintService.updateComplaintStatus(s, this.data.complaint.id)
39 | .subscribe(res => {
40 | this.data.complaint = res;
41 | if (this.data.complaint.status === ComplaintStatus.MONEY_RETURNED) {
42 | const expenseRequest: ExpenseRequest = {
43 | expenseType: ExpenseType.UNEXPECTED,
44 | amount: this.data.complaint.value
45 | };
46 | this.reportService.addExpense(expenseRequest).subscribe(res => {
47 | });
48 | } else if (this.data.complaint.status === ComplaintStatus.NEW_ITEM_SENT) {
49 | this.data.complaint.deliveryItems.forEach(deliveryItem => {
50 | this.itemService.buyItem(deliveryItem.item.id, deliveryItem.quantity).subscribe(res => {
51 | });
52 | });
53 | }
54 | }, err => {
55 | this.shouldShowError = true;
56 | this.error = err.error;
57 | this.showSpinner = false;
58 | }, () => {
59 | this.cancel();
60 | });
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaint/complaint.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 25px;
5 | margin-right: 5px;
6 | }
7 |
8 | .customer-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | padding-bottom: 10px;
12 | }
13 |
14 | .info {
15 | margin-top: 5px;
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaints/complaints.component.html:
--------------------------------------------------------------------------------
1 | Complaints
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Customer name |
14 | {{row.firstName}} {{row.lastName}} |
15 |
16 |
17 |
18 | Current status |
19 | {{row.status}} |
20 |
21 |
22 |
23 | Requested resolution |
24 | {{row.requestedResolution}} |
25 |
26 |
27 |
28 | Resolution |
29 | {{row.resolution}} |
30 |
31 |
32 |
33 | Deadline |
34 | {{row.scheduledFor}} |
35 |
36 |
37 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaints/complaints.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/complaints/complaints/complaints.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {Complaint} from '../../../types';
3 | import {ComplaintService} from '../../../services/complaint.service';
4 | import {Router} from '@angular/router';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-complaints',
10 | templateUrl: './complaints.component.html',
11 | styleUrls: ['./complaints.component.scss']
12 | })
13 | export class ComplaintsComponent implements OnInit {
14 |
15 | complaints: Array;
16 | areComplaintsLoaded = false;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private complaintService: ComplaintService, private router: Router, private dialog: MatDialog) {
27 | }
28 |
29 | ngOnInit() {
30 | this.fetchComplaints();
31 | }
32 |
33 | fetchComplaints() {
34 | this.complaintService.fetchAllComplaints().subscribe(res => {
35 | this.complaints = res;
36 | }, err => {
37 | if (err.status == 401) {
38 | this.router.navigate(['/login']);
39 | } else {
40 | this.showError(err);
41 | }
42 | }, () => {
43 | this.areComplaintsLoaded = true;
44 | this.dataSource = new MatTableDataSource(this.complaints);
45 | });
46 | }
47 |
48 | seeComplaint(id: number) {
49 | this.router.navigate(['/complaints', id]);
50 | }
51 |
52 | addComplaint() {
53 | this.router.navigate(['shop-service/add'], {
54 | queryParams: {
55 | service: 'complaint'
56 | }
57 | });
58 | }
59 |
60 | showError(err) {
61 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
62 | width: '700px',
63 | data: {
64 | error: err.error,
65 | status: err.status
66 | }
67 | });
68 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/app/shop/deliveries/add-delivery/add-delivery.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/deliveries/deliveries/deliveries.component.html:
--------------------------------------------------------------------------------
1 | Deliveries
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Scheduled for |
14 | {{row.scheduledFor}} |
15 |
16 |
17 |
18 | Value |
19 | {{row.value}} |
20 |
21 |
22 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/app/shop/deliveries/deliveries/deliveries.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/deliveries/deliveries/deliveries.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {DeliveryService} from '../../../services/delivery.service';
3 | import {Router} from '@angular/router';
4 | import {Delivery} from '../../../types';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from '@angular/material';
6 | import {ErrorDialogComponent} from '../../../custom/error-dialog/error-dialog.component';
7 |
8 | @Component({
9 | selector: 'app-deliveries',
10 | templateUrl: './deliveries.component.html',
11 | styleUrls: ['./deliveries.component.scss']
12 | })
13 | export class DeliveriesComponent implements OnInit {
14 |
15 | areDeliveriesLoaded = false;
16 | deliveries: Array;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | constructor(private deliveryService: DeliveryService,
21 | private router: Router,
22 | private dialog: MatDialog) {
23 | }
24 |
25 | @ViewChild(MatPaginator)
26 | set pagination(paginator: MatPaginator) {
27 | this.paginator = paginator;
28 | this.dataSource.paginator = this.paginator;
29 | }
30 |
31 | ngOnInit() {
32 | this.fetchDeliveries();
33 | }
34 |
35 | fetchDeliveries() {
36 | this.deliveryService.fetchAllDeliveries().subscribe(res => {
37 | this.deliveries = res;
38 | }, err => {
39 | if (err.status == 401) {
40 | this.router.navigate(['/login']);
41 | } else {
42 | this.showError(err);
43 | }
44 | }, () => {
45 | this.areDeliveriesLoaded = true;
46 | this.dataSource = new MatTableDataSource(this.deliveries);
47 | });
48 | }
49 |
50 | seeDelivery(id: number) {
51 | this.router.navigate(['/deliveries', id]);
52 | }
53 |
54 | addDelivery() {
55 | this.router.navigate(['deliveries/add']);
56 | }
57 |
58 | showError(err) {
59 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
60 | width: '700px',
61 | data: {
62 | error: err.error,
63 | status: err.status
64 | }
65 | });
66 |
67 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/app/shop/deliveries/delivery/delivery.component.html:
--------------------------------------------------------------------------------
1 | Delivery #{{delivery.id}}
2 |
3 |
4 |
5 |
7 | Items
8 |
9 |
10 |
11 | {{deliveryItem.item.name}}, quantity: {{deliveryItem.quantity}}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | calendar_today
20 | {{delivery.scheduledFor}}
21 | attach_money
22 | {{delivery.value}}
23 |
24 |
25 |
26 |
27 | Delivery successfully went through.
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/app/shop/deliveries/delivery/delivery.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 25px;
5 | margin-right: 5px;
6 | }
7 |
8 | .delivery-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | padding-bottom: 10px;
12 | }
13 |
14 | .info {
15 | margin-top: 5px;
16 | }
17 |
18 | .confirmed {
19 | color: limegreen;
20 | font-style: italic;
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/shop/items/add-item/add-item.component.html:
--------------------------------------------------------------------------------
1 | Add item
2 |
3 |
4 |
5 | Name
6 |
7 |
8 |
9 |
10 | Stock price
11 |
12 | {{getStockErrorMessage()}}
13 |
14 |
15 |
16 | Price
17 |
18 | {{getPriceErrorMessage()}}
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/app/shop/items/add-item/add-item.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/items/add-item/add-item.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import {ItemService} from '../../../services/item.service';
3 | import {Router} from '@angular/router';
4 | import {Item, ItemRequest} from '../../../types';
5 | import {FormControl, FormGroup, Validators} from "@angular/forms";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 | import {MatDialog} from "@angular/material";
8 |
9 | @Component({
10 | selector: 'app-add-item',
11 | templateUrl: './add-item.component.html',
12 | styleUrls: ['./add-item.component.scss']
13 | })
14 | export class AddItemComponent {
15 |
16 | form: FormGroup;
17 | name: FormControl;
18 | stockPrice: FormControl;
19 | price: FormControl;
20 | itemRequest: ItemRequest;
21 |
22 | constructor(private itemService: ItemService,
23 | private router: Router,
24 | private dialog: MatDialog) {
25 | this.setupFormControls();
26 | this.form = new FormGroup({
27 | "name": this.name,
28 | "stockPrice": this.stockPrice,
29 | "price": this.price
30 | });
31 | }
32 |
33 | setupFormControls() {
34 | this.name = new FormControl('', [
35 | Validators.required
36 | ]);
37 | this.stockPrice = new FormControl('', [
38 | Validators.required,
39 | Validators.pattern("^[0-9]*$"),
40 | ]);
41 | this.price = new FormControl('', [
42 | Validators.required,
43 | Validators.pattern("^[0-9]*$"),
44 | ]);
45 | }
46 |
47 | submitForm() {
48 | this.itemRequest = {
49 | name: this.form.get('name').value,
50 | stockPrice: this.form.get('stockPrice').value,
51 | price: this.form.get('price').value
52 | };
53 | let item: Item;
54 | this.itemService.addNewItem(this.itemRequest).subscribe(res => {
55 | item = res;
56 | }, err => {
57 | if (err.status == 401) {
58 | this.router.navigate(['/login']);
59 | } else {
60 | this.showError(err);
61 | }
62 | }, () => {
63 | this.router.navigate(['/items', item.id]);
64 | });
65 | }
66 |
67 | getStockErrorMessage() {
68 | return this.stockPrice.hasError('pattern') ? 'Enter a number' : '';
69 | }
70 |
71 | getPriceErrorMessage() {
72 | return this.price.hasError('pattern') ? 'Enter a number' : '';
73 | }
74 |
75 | showError(err) {
76 | this.dialog.open(ErrorDialogComponent, {
77 | width: '700px',
78 | data: {
79 | error: err.error,
80 | status: err.status
81 | }
82 | });
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/app/shop/items/item/item.component.html:
--------------------------------------------------------------------------------
1 | {{item.name}}
2 |
3 |
4 | Quantity: {{item.quantity}}
5 |
6 |
7 |
8 | Current price: {{item.currentPrice}} PLN
9 |
10 |
11 |
12 |
13 | Base price: {{item.originalPrice}} PLN
14 |
15 |
16 |
17 | Stock price: {{item.stockPrice}} PLN
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/app/shop/items/item/item.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/items/item/item.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Item} from '../../../types';
3 | import {ItemService} from '../../../services/item.service';
4 | import {ActivatedRoute, Router} from '@angular/router';
5 | import {NewPriceDialogComponent} from "../new-price-dialog/new-price-dialog.component";
6 | import {MatDialog} from "@angular/material";
7 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
8 |
9 | @Component({
10 | selector: 'app-item',
11 | templateUrl: './item.component.html',
12 | styleUrls: ['./item.component.scss']
13 | })
14 | export class ItemComponent implements OnInit {
15 |
16 | isItemLoaded = false;
17 | item: Item;
18 |
19 | constructor(private itemService: ItemService,
20 | private route: ActivatedRoute,
21 | private dialog: MatDialog,
22 | private router: Router) {
23 | }
24 |
25 | ngOnInit() {
26 | this.fetchItem();
27 | }
28 |
29 | fetchItem() {
30 | this.itemService.fetchOneItem(this.route.snapshot.params['id']).subscribe(res => {
31 | this.item = res;
32 | }, err => {
33 | if (err.status == 401) {
34 | this.router.navigate(['/login']);
35 | } else {
36 | this.showError(err);
37 | }
38 | }, () => {
39 | this.isItemLoaded = true;
40 | });
41 | }
42 |
43 | changePrice() {
44 | const dialogRef = this.dialog.open(NewPriceDialogComponent, {
45 | width: '350px',
46 | data: {id: this.item.id}
47 | });
48 |
49 | dialogRef.afterClosed().subscribe(result => {
50 | this.isItemLoaded = false;
51 | this.fetchItem();
52 | });
53 | }
54 |
55 | showError(err) {
56 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
57 | width: '700px',
58 | data: {
59 | error: err.error,
60 | status: err.status
61 | }
62 | });
63 |
64 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/items']));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/app/shop/items/items/items.component.html:
--------------------------------------------------------------------------------
1 | Items
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Index |
11 | {{row.id}} |
12 |
13 |
14 |
15 | Name |
16 | {{row.name}} |
17 |
18 |
19 |
20 | Quantity |
21 | {{row.quantity}} |
22 |
23 |
24 |
25 | Stock price |
26 | {{row.stockPrice}} |
27 |
28 |
29 |
30 | Original price |
31 | {{row.originalPrice}} |
32 |
33 |
34 |
35 | Current price |
36 | {{row.currentPrice}} |
37 |
38 |
39 |
41 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/app/shop/items/items/items.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | button {
4 | margin-left: 10px;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/shop/items/new-price-dialog/new-price-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{error}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/app/shop/items/new-price-dialog/new-price-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .error {
2 | font-style: italic;
3 | color: darkred;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/shop/items/new-price-dialog/new-price-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {ItemService} from "../../../services/item.service";
3 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
4 |
5 | export interface DialogData {
6 | id: number;
7 | }
8 |
9 | @Component({
10 | selector: 'app-new-price-dialog',
11 | templateUrl: './new-price-dialog.component.html',
12 | styleUrls: ['./new-price-dialog.component.scss']
13 | })
14 | export class NewPriceDialogComponent {
15 |
16 | price = null;
17 | error: string;
18 | shouldShowError: boolean;
19 |
20 | constructor(public dialogRef: MatDialogRef,
21 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
22 | private itemService: ItemService) {
23 | }
24 |
25 | cancel() {
26 | this.dialogRef.close(null);
27 | }
28 |
29 | submit() {
30 | this.itemService.setNewPrice(this.data.id, this.price)
31 | .subscribe(() => {
32 | },
33 | err => {
34 | this.shouldShowError = true;
35 | this.error = err.error;
36 | },
37 | () => this.cancel()
38 | );
39 | }
40 |
41 | isPriceValid() {
42 | const regexp = new RegExp('^\\d+\\.\\d{2}$');
43 | return this.price != null && regexp.test(this.price.toString());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/app/shop/items/special-offer-dialog/special-offer-dialog.component.html:
--------------------------------------------------------------------------------
1 | Enter special offer details:
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/app/shop/items/special-offer-dialog/special-offer-dialog.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plkpiotr/erp-mes-frontend/70b2e4c0afa39ccaddbe098b573eaa9c57adf5b6/src/app/shop/items/special-offer-dialog/special-offer-dialog.component.scss
--------------------------------------------------------------------------------
/src/app/shop/items/special-offer-dialog/special-offer-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject, OnInit} from '@angular/core';
2 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
3 |
4 | export interface DialogData {
5 | percentOff: string;
6 | query: string;
7 | }
8 |
9 | @Component({
10 | selector: 'app-special-offer-dialog',
11 | templateUrl: './special-offer-dialog.component.html',
12 | styleUrls: ['./special-offer-dialog.component.scss']
13 | })
14 | export class SpecialOfferDialogComponent {
15 |
16 | constructor(
17 | public dialogRef: MatDialogRef,
18 | @Inject(MAT_DIALOG_DATA) public data: DialogData) {
19 | }
20 |
21 | isFormValid() {
22 | const regexp = new RegExp('\\d{2}');
23 | return regexp.test(this.data.percentOff);
24 | }
25 |
26 | cancel() {
27 | this.dialogRef.close(null);
28 | }
29 |
30 | submit() {
31 | this.dialogRef.close(this.data);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/app/shop/orders/add-order/add-order.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/orders/order-status-dialog/order-status-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{error}}
3 |
8 |
--------------------------------------------------------------------------------
/src/app/shop/orders/order-status-dialog/order-status-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .content {
2 | display: inline-flex;
3 | }
4 |
5 | button {
6 | margin-left: 10px;
7 | align-items: center;
8 | }
9 |
10 | mat-progress-spinner {
11 | margin: auto;
12 | }
13 |
14 | .error {
15 | font-style: italic;
16 | color: darkred;
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/shop/orders/order-status-dialog/order-status-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject} from '@angular/core';
2 | import {OrderService} from "../../../services/order.service";
3 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
4 | import {ItemService} from "../../../services/item.service";
5 | import {ReportService} from "../../../services/report.service";
6 | import {Order} from "../../../types";
7 |
8 | export interface DialogData {
9 | status: string[];
10 | order: Order;
11 | }
12 |
13 | @Component({
14 | selector: 'app-order-status-dialog',
15 | templateUrl: './order-status-dialog.component.html',
16 | styleUrls: ['./order-status-dialog.component.scss']
17 | })
18 | export class OrderStatusDialogComponent {
19 |
20 | showSpinner: boolean;
21 | error: string;
22 | shouldShowError: boolean;
23 |
24 | constructor(public dialogRef: MatDialogRef,
25 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
26 | private orderService: OrderService,
27 | private itemService: ItemService,
28 | private reportService: ReportService) {
29 | }
30 |
31 | cancel() {
32 | this.dialogRef.close(null);
33 | }
34 |
35 | submit(s: string) {
36 | this.showSpinner = true;
37 | this.orderService.updateOrderStatus(s, this.data.order.id)
38 | .subscribe(res => {
39 | if (s === 'SENT') {
40 | const expenseRequest = {
41 | amount: this.data.order.value
42 | };
43 | this.reportService.addIncome(expenseRequest.amount).subscribe(res => {});
44 | }
45 | }, err => {
46 | this.shouldShowError = true;
47 | this.error = err.error;
48 | this.showSpinner = false;
49 | }, () => {
50 | this.cancel();
51 | });
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/app/shop/orders/order/order.component.html:
--------------------------------------------------------------------------------
1 | Order #{{order.id}}
2 |
3 |
4 |
5 |
6 |
7 | Status: {{order.status}}
8 |
10 |
11 |
12 |
13 | Deadline: {{order.scheduledFor}}
14 |
15 |
16 |
17 | Value: {{order.value}} PLN
18 |
19 |
20 |
21 |
22 |
23 |
25 | Customer information
26 |
27 |
28 | face
29 | {{order.firstName}} {{order.lastName}}
30 | email
31 | {{order.email}}
32 | call
33 | {{order.phoneNumber}}
34 |
35 | location_city
36 | {{order.street}} {{order.houseNumber}}, {{order.postalCode}} {{order.city}}
37 |
38 |
39 |
40 |
41 |
43 | Items
44 |
45 |
46 |
47 | {{deliveryItem.item.name}}, price: {{deliveryItem.item.currentPrice}} PLN, quantity: {{deliveryItem.quantity}}
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/app/shop/orders/order/order.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 25px;
5 | margin-right: 5px;
6 | }
7 |
8 | .customer-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | padding-bottom: 10px;
12 | }
13 |
14 | .info {
15 | margin-top: 5px;
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/shop/orders/order/order.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Order} from '../../../types';
3 | import {OrderService} from '../../../services/order.service';
4 | import {ActivatedRoute, Router} from '@angular/router';
5 | import {OrderStatusDialogComponent} from "../order-status-dialog/order-status-dialog.component";
6 | import {MatDialog} from "@angular/material";
7 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
8 | import {Status} from "../../../globals";
9 |
10 | @Component({
11 | selector: 'app-order',
12 | templateUrl: './order.component.html',
13 | styleUrls: ['./order.component.scss']
14 | })
15 | export class OrderComponent implements OnInit {
16 |
17 | isOrderLoaded = false;
18 | order: Order;
19 |
20 | constructor(private orderService: OrderService,
21 | private route: ActivatedRoute,
22 | private dialog: MatDialog,
23 | private router: Router) {
24 | }
25 |
26 | ngOnInit() {
27 | this.fetchOrder();
28 | }
29 |
30 | fetchOrder() {
31 | this.orderService.fetchOneOrder(this.route.snapshot.params['id']).subscribe(res => {
32 | this.order = res;
33 | }, err => {
34 | if (err.status == 401) {
35 | this.router.navigate(['/login']);
36 | } else {
37 | this.showError(err);
38 | }
39 | }, () => {
40 | this.isOrderLoaded = true;
41 | });
42 | }
43 |
44 | updateOrderStatus() {
45 | let status = [];
46 | if (this.order.status === Status.WAITING_FOR_PAYMENT) {
47 | status = ['IN_PROGRESS', 'DECLINED'];
48 | } else if (this.order.status === Status.IN_PROGRESS) {
49 | status = ['SENT', 'DECLINED'];
50 | }
51 | const dialogRef = this.dialog.open(OrderStatusDialogComponent, {
52 | width: '350px',
53 | data: {
54 | status: status,
55 | order: this.order
56 | }
57 | });
58 |
59 | dialogRef.afterClosed().subscribe(result => {
60 | this.isOrderLoaded = false;
61 | this.fetchOrder();
62 | });
63 | }
64 |
65 | showError(err) {
66 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
67 | width: '700px',
68 | data: {
69 | error: err.error,
70 | status: err.status
71 | }
72 | });
73 |
74 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/orders']));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/app/shop/orders/orders/orders.component.html:
--------------------------------------------------------------------------------
1 | Orders
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Customer name |
14 | {{row.firstName}} {{row.lastName}} |
15 |
16 |
17 |
18 | Status |
19 | {{row.status}} |
20 |
21 |
22 |
23 | Value |
24 | {{row.value}} |
25 |
26 |
27 |
28 | Deadline |
29 | {{row.scheduledFor}} |
30 |
31 |
32 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/app/shop/orders/orders/orders.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/orders/orders/orders.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {Order} from '../../../types';
3 | import {OrderService} from '../../../services/order.service';
4 | import {Router} from '@angular/router';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-orders',
10 | templateUrl: './orders.component.html',
11 | styleUrls: ['./orders.component.scss']
12 | })
13 | export class OrdersComponent implements OnInit {
14 |
15 | orders: Array;
16 | areOrdersLoaded = false;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private orderService: OrderService, private router: Router, private dialog: MatDialog) {
27 | }
28 |
29 | ngOnInit() {
30 | this.fetchOrders();
31 | }
32 |
33 | fetchOrders() {
34 | this.orderService.fetchAllOrders().subscribe(res => {
35 | this.orders = res;
36 | }, err => {
37 | if (err.status == 401) {
38 | this.router.navigate(['/login']);
39 | } else {
40 | this.showError(err);
41 | }
42 | }, () => {
43 | this.areOrdersLoaded = true;
44 | this.dataSource = new MatTableDataSource(this.orders);
45 | });
46 | }
47 |
48 | seeOrder(id: number) {
49 | this.router.navigate(['/orders', id]);
50 | }
51 |
52 | addOrder() {
53 | this.router.navigate(['shop-service/add'], {
54 | queryParams: {
55 | service: 'order'
56 | }
57 | });
58 | }
59 |
60 | showError(err) {
61 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
62 | width: '700px',
63 | data: {
64 | error: err.error,
65 | status: err.status
66 | }
67 | });
68 |
69 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/app/shop/returns/return/return.component.html:
--------------------------------------------------------------------------------
1 | Return #{{return.id}}
2 |
3 |
4 |
5 |
6 |
7 | Status: {{return.status}}
8 |
10 |
11 |
12 |
13 | Deadline: {{return.scheduledFor}}
14 |
15 |
16 |
17 | Value: {{return.value}} PLN
18 |
19 |
20 |
21 |
22 |
23 |
25 | Customer information
26 |
27 |
28 | face
29 | {{return.firstName}} {{return.lastName}}
30 | email
31 | {{return.email}}
32 | call
33 | {{return.phoneNumber}}
34 |
35 | location_city
36 | {{return.street}} {{return.houseNumber}}, {{return.postalCode}} {{return.city}}
37 |
38 |
39 |
40 |
41 |
43 | Items
44 |
45 |
46 |
47 | {{deliveryItem.item.name}}, price: {{deliveryItem.item.currentPrice}} PLN, quantity: {{deliveryItem.quantity}}
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/app/shop/returns/return/return.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 25px;
5 | margin-right: 5px;
6 | }
7 |
8 | .customer-info {
9 | display: inline-flex;
10 | vertical-align: middle;
11 | padding-bottom: 10px;
12 | }
13 |
14 | .info {
15 | margin-top: 5px;
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/shop/returns/return/return.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Return} from '../../../types';
3 | import {ReturnService} from '../../../services/return.service';
4 | import {ActivatedRoute, Router} from '@angular/router';
5 | import {MatDialog} from "@angular/material";
6 | import {StatusDialogComponent} from "../status-dialog/status-dialog.component";
7 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
8 | import {ReturnStatus} from "../../../globals";
9 |
10 | @Component({
11 | selector: 'app-return',
12 | templateUrl: './return.component.html',
13 | styleUrls: ['./return.component.scss']
14 | })
15 | export class ReturnComponent implements OnInit {
16 |
17 | isReturnLoaded = false;
18 | return: Return;
19 | status: ReturnStatus;
20 |
21 | constructor(private returnService: ReturnService, private route: ActivatedRoute,
22 | private dialog: MatDialog, private router: Router) {
23 | }
24 |
25 | ngOnInit() {
26 | this.fetchReturn();
27 | }
28 |
29 | fetchReturn() {
30 | this.returnService.fetchOneReturn(this.route.snapshot.params['id']).subscribe(res => {
31 | this.return = res;
32 | }, err => {
33 | if (err.status == 401) {
34 | this.router.navigate(['/login']);
35 | } else {
36 | this.showError(err);
37 | }
38 | }, () => {
39 | this.isReturnLoaded = true;
40 | this.status = this.return.status;
41 | });
42 | }
43 |
44 | updateReturnStatus() {
45 | let status = [];
46 | if (this.return.status === ReturnStatus.IN_PROGRESS) {
47 | status = ['ACCEPTED', 'DECLINED'];
48 | } else if (this.return.status === ReturnStatus.ACCEPTED) {
49 | status = ['MONEY_RETURNED'];
50 | }
51 | const dialogRef = this.dialog.open(StatusDialogComponent, {
52 | width: '350px',
53 | data: {
54 | status: status,
55 | r: this.return
56 | }
57 | });
58 |
59 | dialogRef.afterClosed().subscribe(result => {
60 | this.isReturnLoaded = false;
61 | this.fetchReturn();
62 | });
63 | }
64 |
65 | showError(err) {
66 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
67 | width: '700px',
68 | data: {
69 | error: err.error,
70 | status: err.status
71 | }
72 | });
73 |
74 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/returns']));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/app/shop/returns/returns/returns.component.html:
--------------------------------------------------------------------------------
1 | Returns
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Customer name |
14 | {{row.firstName}} {{row.lastName}} |
15 |
16 |
17 |
18 | Status |
19 | {{row.status}} |
20 |
21 |
22 |
23 | Value |
24 | {{row.value}} |
25 |
26 |
27 |
28 | Deadline |
29 | {{row.scheduledFor}} |
30 |
31 |
32 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/app/shop/returns/returns/returns.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/shop/returns/returns/returns.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {Return} from '../../../types';
3 | import {ReturnService} from '../../../services/return.service';
4 | import {Router} from '@angular/router';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-returns',
10 | templateUrl: './returns.component.html',
11 | styleUrls: ['./returns.component.scss']
12 | })
13 | export class ReturnsComponent implements OnInit {
14 |
15 | returns: Array;
16 | areReturnsLoaded = false;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private returnService: ReturnService, private router: Router, private dialog: MatDialog) {
27 | }
28 |
29 | ngOnInit() {
30 | this.fetchReturns();
31 | }
32 |
33 | fetchReturns() {
34 | this.returnService.fetchAllReturns().subscribe(res => {
35 | this.returns = res;
36 | }, err => {
37 | if (err.status == 401) {
38 | this.router.navigate(['/login']);
39 | } else {
40 | this.showError(err);
41 | }
42 | }, () => {
43 | this.areReturnsLoaded = true;
44 | this.dataSource = new MatTableDataSource(this.returns);
45 | });
46 | }
47 |
48 | seeReturn(id: number) {
49 | this.router.navigate(['/returns', id]);
50 | }
51 |
52 | addReturn() {
53 | this.router.navigate(['shop-service/add'], {
54 | queryParams: {
55 | service: 'return'
56 | }
57 | });
58 | }
59 |
60 | showError(err) {
61 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
62 | width: '700px',
63 | data: {
64 | error: err.error,
65 | status: err.status
66 | }
67 | });
68 |
69 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/app/shop/returns/status-dialog/status-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{error}}
3 |
8 |
--------------------------------------------------------------------------------
/src/app/shop/returns/status-dialog/status-dialog.component.scss:
--------------------------------------------------------------------------------
1 | .content {
2 | display: inline-flex;
3 | }
4 |
5 | button {
6 | margin-left: 10px;
7 | align-items: center;
8 | }
9 |
10 | mat-progress-spinner {
11 | margin: auto;
12 | }
13 |
14 | .error {
15 | font-style: italic;
16 | color: darkred;
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/src/app/shop/returns/status-dialog/status-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject, OnInit} from '@angular/core';
2 | import {ReturnService} from "../../../services/return.service";
3 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
4 | import {ExpenseRequest, Return} from "../../../types";
5 | import {ItemService} from "../../../services/item.service";
6 | import {ReportService} from "../../../services/report.service";
7 | import {ExpenseType} from "../../../globals";
8 |
9 | export interface DialogData {
10 | status: string[];
11 | r: Return;
12 | }
13 |
14 | @Component({
15 | selector: 'app-status-dialog',
16 | templateUrl: './status-dialog.component.html',
17 | styleUrls: ['./status-dialog.component.scss']
18 | })
19 | export class StatusDialogComponent {
20 |
21 | showSpinner: boolean;
22 | error: string;
23 | shouldShowError: boolean;
24 |
25 | constructor(public dialogRef: MatDialogRef,
26 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
27 | private returnService: ReturnService,
28 | private itemService: ItemService,
29 | private reportService: ReportService) {
30 | }
31 |
32 | cancel() {
33 | this.dialogRef.close(null);
34 | }
35 |
36 | submit(s: string) {
37 | this.showSpinner = true;
38 | this.returnService.updateReturnStatus(s, this.data.r.id)
39 | .subscribe(res => {
40 | if (s === 'MONEY_RETURNED') {
41 | this.data.r.deliveryItems.forEach(deliveryItem => {
42 | this.itemService.supplyItem(deliveryItem.item.id,
43 | deliveryItem.quantity).subscribe(() => {
44 | });
45 | });
46 | const expenseRequest: ExpenseRequest = {
47 | expenseType: ExpenseType.UNEXPECTED,
48 | amount: this.data.r.value
49 | };
50 | this.reportService.addExpense(expenseRequest).subscribe(() => {});
51 | }
52 | }, err => {
53 | this.shouldShowError = true;
54 | this.error = err.error;
55 | this.showSpinner = false;
56 | }, () => {
57 | this.cancel();
58 | });
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/app/staff/employees/add-employee/add-employee.component.html:
--------------------------------------------------------------------------------
1 | Add employee
2 |
3 |
4 |
5 | First name
6 |
7 |
8 |
9 |
10 | Last name
11 |
12 |
13 |
14 |
15 | Email
16 |
17 | {{getErrorMessage()}}
18 |
19 |
20 |
21 | Role
22 |
23 |
24 | {{r}}
25 |
26 |
27 |
28 |
29 |
30 | Account number
31 |
33 | 26 digits
34 |
35 |
36 |
37 | Days off per year
38 |
40 | 0 - 26
41 |
42 |
43 |
44 | Salary
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/app/staff/employees/add-employee/add-employee.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/staff/employees/employee/employee.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 25px;
5 | }
6 | .out-of-office {
7 | color: limegreen;
8 | font-style: italic;
9 | }
10 |
11 | .pending-vacation {
12 | color: darkorange;
13 | font-style: italic;
14 | }
15 |
16 | .contract {
17 | display: inline-flex;
18 | vertical-align: middle;
19 | padding-bottom: 10px;
20 | }
21 |
22 | button:hover {
23 | background-color: transparent;
24 | }
25 |
--------------------------------------------------------------------------------
/src/app/staff/employees/employees/employees.component.html:
--------------------------------------------------------------------------------
1 | Employees
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Name |
14 | {{row.firstName}} {{row.lastName}} |
15 |
16 |
17 |
18 | Role |
19 | {{row.role}} |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/app/staff/employees/employees/employees.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/staff/employees/employees/employees.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {EmployeeService} from '../../../services/employee.service';
3 | import {Router} from '@angular/router';
4 | import {Employee} from '../../../types';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-employees',
10 | templateUrl: './employees.component.html',
11 | styleUrls: ['./employees.component.scss']
12 | })
13 | export class EmployeesComponent implements OnInit {
14 |
15 | employees: Array;
16 | areLoaded: boolean;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private employeeService: EmployeeService, private router: Router, private dialog: MatDialog) {
27 | }
28 |
29 | ngOnInit() {
30 | this.fetchEmployees();
31 | }
32 |
33 | fetchEmployees() {
34 | this.employeeService.fetchAllEmployees().subscribe(res => this.employees = res,
35 | err => {
36 | if (err.status == 401) {
37 | this.router.navigate(['/login']);
38 | } else {
39 | this.showError(err);
40 | }
41 | },
42 | () => {
43 | this.areLoaded = true;
44 | this.dataSource = new MatTableDataSource(this.employees);
45 | }
46 | );
47 | }
48 |
49 | fetchEmployee(id: number) {
50 | this.router.navigate(['/employees', id]);
51 | }
52 |
53 | addEmployee() {
54 | this.router.navigate(['/employees/add']);
55 | }
56 |
57 | showError(err) {
58 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
59 | width: '700px',
60 | data: {
61 | error: err.error,
62 | status: err.status
63 | }
64 | });
65 |
66 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/teams']));
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/app/staff/holidays/add-holiday/add-holiday.component.html:
--------------------------------------------------------------------------------
1 | Add holiday
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Duration
12 |
13 | {{getErrorMessage()}}
14 |
15 |
16 |
17 | Holiday type
18 |
19 |
20 | {{t}}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/app/staff/holidays/add-holiday/add-holiday.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/staff/holidays/add-holiday/add-holiday.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {HolidayService} from '../../../services/holiday.service';
3 | import {ActivatedRoute} from '@angular/router';
4 | import {HolidayType} from '../../../globals';
5 | import {FormControl, FormGroup, Validators} from "@angular/forms";
6 |
7 | @Component({
8 | selector: 'app-add-holiday',
9 | templateUrl: './add-holiday.component.html',
10 | styleUrls: ['./add-holiday.component.scss']
11 | })
12 | export class AddHolidayComponent implements OnInit {
13 |
14 | employeeId: number;
15 | holidayRequest;
16 | form: FormGroup;
17 | startDate: FormControl;
18 | duration: FormControl;
19 | holidayType: FormControl;
20 | types;
21 |
22 | constructor(private holidayService: HolidayService,
23 | private route: ActivatedRoute) {
24 | }
25 |
26 | ngOnInit() {
27 | this.route.queryParams.subscribe(params => this.employeeId = params['employeeId']);
28 | this.types = Object.keys(HolidayType);
29 | this.setupFormControls();
30 | this.form = new FormGroup({
31 | "startDate": this.startDate,
32 | "duration": this.duration,
33 | "holidayType": this.holidayType
34 | });
35 | }
36 |
37 | setupFormControls() {
38 | this.startDate = new FormControl('', [
39 | Validators.required
40 | ]);
41 | this.duration = new FormControl('', [
42 | Validators.required,
43 | Validators.pattern("^[0-9]*$"),
44 | ]);
45 | this.holidayType = new FormControl('', [
46 | Validators.required
47 | ]);
48 | }
49 |
50 | submitForm() {
51 | this.holidayRequest = {
52 | startDate: this.form.get('startDate').value,
53 | duration: this.form.get('duration').value,
54 | holidayType: this.form.get('holidayType').value
55 | };
56 | this.holidayService.addHoliday(this.holidayRequest, this.employeeId);
57 | }
58 |
59 | getErrorMessage() {
60 | return this.duration.hasError('pattern') ? 'Enter a number' : '';
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/app/staff/holidays/manage-holidays-dialog/manage-holidays-dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{error}}
3 |
4 |
5 |
8 | 0">
9 |
10 | account_circle {{req.employee.firstName}} {{req.employee.lastName}}
11 | business_center {{req.holidayType}}
12 | calendar_today {{req.startDate}}
13 | timeline {{req.duration}} day(s)
14 | hourglass_empty {{req.approvalState}}
15 |
18 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/app/staff/holidays/manage-holidays-dialog/manage-holidays-dialog.component.scss:
--------------------------------------------------------------------------------
1 | mat-progress-spinner {
2 | margin: auto;
3 | }
4 |
5 | button {
6 | font-style: italic;
7 | }
8 |
9 | .accept {
10 | color: limegreen;
11 | }
12 |
13 | .decline {
14 | color: darkred;
15 | }
16 |
17 | mat-icon {
18 | margin-right: 5px;
19 | margin-left: 15px;
20 | }
21 |
22 | .error {
23 | font-style: italic;
24 | color: darkred;
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/app/staff/holidays/manage-holidays-dialog/manage-holidays-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Inject, OnInit} from '@angular/core';
2 | import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
3 | import {HolidayService} from "../../../services/holiday.service";
4 | import {Holiday} from "../../../types";
5 |
6 | export interface DialogData {
7 | id: number;
8 | }
9 |
10 | @Component({
11 | selector: 'app-manage-holidays-dialog',
12 | templateUrl: './manage-holidays-dialog.component.html',
13 | styleUrls: ['./manage-holidays-dialog.component.scss']
14 | })
15 | export class ManageHolidaysDialogComponent {
16 |
17 | holidayRequests: Holiday[];
18 | areRequestsLoaded: boolean;
19 | error: string;
20 | shouldShowError: boolean;
21 |
22 | constructor(
23 | public dialogRef: MatDialogRef,
24 | @Inject(MAT_DIALOG_DATA) public data: DialogData,
25 | private holidayService: HolidayService) {
26 | this.fetchRequests();
27 | }
28 |
29 | fetchRequests() {
30 | this.holidayService.fetchHolidaysToApprove(this.data.id).subscribe(
31 | res => {
32 | this.holidayRequests = res;
33 | }, err => {
34 | this.shouldShowError = true;
35 | this.error = err.error;
36 | }, () => {
37 | this.areRequestsLoaded = true;
38 | }
39 | );
40 | }
41 |
42 | cancel() {
43 | this.dialogRef.close(null);
44 | }
45 |
46 | approve(holidayId: number, employeeId: number) {
47 | this.holidayService.manageHolidays(this.data.id, employeeId, holidayId, 'true')
48 | .subscribe(
49 | () => {},
50 | err => {
51 | this.shouldShowError = true;
52 | this.error = err.error;
53 | }, () => {
54 | this.areRequestsLoaded = false;
55 | this.fetchRequests();
56 | }
57 | );
58 | }
59 |
60 | decline(holidayId: number, employeeId: number) {
61 | this.holidayService.manageHolidays(this.data.id, employeeId, holidayId, 'false')
62 | .subscribe(
63 | () => {},
64 | err => {
65 | this.shouldShowError = true;
66 | this.error = err.error;
67 | }, () => {
68 | this.areRequestsLoaded = false;
69 | this.fetchRequests();
70 | }
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/app/staff/teams/team/team.component.html:
--------------------------------------------------------------------------------
1 | Team {{team.role}}
2 |
35 |
--------------------------------------------------------------------------------
/src/app/staff/teams/team/team.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
3 | mat-icon {
4 | margin-left: 25px;
5 | }
6 |
7 | mat-list-item {
8 | margin-right: 25px;
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/staff/teams/team/team.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {TeamService} from '../../../services/team.service';
3 | import {ActivatedRoute, Router} from '@angular/router';
4 | import {Team} from '../../../types';
5 | import {MatDialog} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-team',
10 | templateUrl: './team.component.html',
11 | styleUrls: ['./team.component.scss']
12 | })
13 | export class TeamComponent implements OnInit {
14 |
15 | team: Team;
16 | isLoaded = false;
17 |
18 | constructor(private teamService: TeamService,
19 | private route: ActivatedRoute,
20 | private dialog: MatDialog,
21 | private router: Router) {
22 | }
23 |
24 | ngOnInit() {
25 | this.teamService.fetchOneTeam(this.route.snapshot.params[('id')])
26 | .subscribe(res => {
27 | this.team = res;
28 | },
29 | err => {
30 | if (err.status == 401) {
31 | this.router.navigate(['/login']);
32 | } else {
33 | this.showError(err);
34 | }
35 | },
36 | () => {
37 | this.isLoaded = true;
38 | });
39 | }
40 |
41 | showError(err) {
42 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
43 | width: '700px',
44 | data: {
45 | error: err.error,
46 | status: err.status
47 | }
48 | });
49 |
50 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/teams']));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/staff/teams/teams/teams.component.html:
--------------------------------------------------------------------------------
1 | Teams
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index |
9 | {{row.id}} |
10 |
11 |
12 |
13 | Role |
14 | {{row.role}} |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/app/staff/teams/teams/teams.component.scss:
--------------------------------------------------------------------------------
1 | @import "../../../../theme";
2 |
--------------------------------------------------------------------------------
/src/app/staff/teams/teams/teams.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit, ViewChild} from '@angular/core';
2 | import {Router} from '@angular/router';
3 | import {TeamService} from '../../../services/team.service';
4 | import {Team} from '../../../types';
5 | import {MatDialog, MatPaginator, MatTableDataSource} from "@angular/material";
6 | import {ErrorDialogComponent} from "../../../custom/error-dialog/error-dialog.component";
7 |
8 | @Component({
9 | selector: 'app-teams',
10 | templateUrl: './teams.component.html',
11 | styleUrls: ['./teams.component.scss']
12 | })
13 | export class TeamsComponent implements OnInit {
14 |
15 | teams: Array;
16 | isLoaded = false;
17 | dataSource: MatTableDataSource = new MatTableDataSource([]);
18 | paginator: any;
19 |
20 | @ViewChild(MatPaginator)
21 | set pagination(paginator: MatPaginator) {
22 | this.paginator = paginator;
23 | this.dataSource.paginator = this.paginator;
24 | }
25 |
26 | constructor(private router: Router,
27 | private teamService: TeamService,
28 | private dialog: MatDialog) {
29 | }
30 |
31 | ngOnInit() {
32 | this.teamService.fetchAllTeams().subscribe(res => {
33 | this.teams = res;
34 | }, err => {
35 | if (err.status == 401) {
36 | this.router.navigate(['/login']);
37 | } else {
38 | this.showError(err);
39 | }
40 | }, () => {
41 | this.isLoaded = true;
42 | this.dataSource = new MatTableDataSource(this.teams);
43 | });
44 | }
45 |
46 | seeTeam(id: number) {
47 | this.router.navigate(['/teams', id]);
48 | }
49 |
50 | showError(err) {
51 | const dialogRef = this.dialog.open(ErrorDialogComponent, {
52 | width: '700px',
53 | data: {
54 | error: err.error,
55 | status: err.status
56 | }
57 | });
58 |
59 | dialogRef.afterClosed().subscribe(() => this.router.navigate(['/employees']));
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/app/token.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | @Injectable()
4 | export class Token {
5 |
6 | constructor() { }
7 |
8 | public saveToken(token: string) {
9 | window.sessionStorage.removeItem('AuthToken');
10 | window.sessionStorage.setItem('AuthToken', token);
11 | }
12 |
13 | public getToken(): string {
14 | return sessionStorage.getItem('AuthToken');
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plkpiotr/erp-mes-frontend/70b2e4c0afa39ccaddbe098b573eaa9c57adf5b6/src/assets/.gitkeep
--------------------------------------------------------------------------------
/src/browserslist:
--------------------------------------------------------------------------------
1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 | # For IE 9-11 support, please uncomment the last line of the file and adjust as needed
5 | > 0.5%
6 | last 2 versions
7 | Firefox ESR
8 | not dead
9 | # IE 9-11
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * In development mode, to ignore zone related error stack frames such as
11 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
12 | * import the following file, but please comment it out in production mode
13 | * because it will have performance impact when throw error
14 | */
15 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
16 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plkpiotr/erp-mes-frontend/70b2e4c0afa39ccaddbe098b573eaa9c57adf5b6/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | ERP-MES Inc.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import {enableProdMode} from '@angular/core';
2 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
3 |
4 | import {AppModule} from './app/app.module';
5 | import {environment} from './environments/environment';
6 | import 'hammerjs';
7 |
8 | if (environment.production) {
9 | enableProdMode();
10 | }
11 |
12 | platformBrowserDynamic().bootstrapModule(AppModule)
13 | .catch(err => console.log(err));
14 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/prebuilt-themes/indigo-pink.css';
2 | @import '~@angular/material/theming';
3 | @include mat-core();
4 |
5 | $primary: mat-palette($mat-blue, 400);
6 | $accent: mat-palette($mat-pink, 400);
7 | $warn: mat-palette($mat-pink, 400);
8 |
9 | $theme: mat-light-theme($primary, $accent, $warn);
10 |
11 | @include angular-material-theme($theme);
12 |
13 | html, body {
14 | height: 100%;
15 | }
16 |
17 | body {
18 | margin: 0;
19 | font-family: 'Roboto', sans-serif;
20 | }
21 |
22 | .mat-expansion-panel-content > .mat-expansion-panel-body {
23 | padding: 0;
24 | }
25 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./test', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "es2015",
6 | "types": []
7 | },
8 | "exclude": [
9 | "src/test.ts",
10 | "**/*.spec.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "module": "commonjs",
6 | "types": [
7 | "jasmine",
8 | "node"
9 | ]
10 | },
11 | "files": [
12 | "test.ts",
13 | "polyfills.ts"
14 | ],
15 | "include": [
16 | "**/*.spec.ts",
17 | "**/*.d.ts"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/src/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/variables.scss:
--------------------------------------------------------------------------------
1 | $link: #439AE2;
2 | $dark: #90CAF9;
3 | $normal: #BBDEFB;
4 | $light: #E3F2FD;
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "moduleResolution": "node",
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "target": "es5",
12 | "typeRoots": [
13 | "node_modules/@types"
14 | ],
15 | "lib": [
16 | "es2017",
17 | "dom"
18 | ]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------