mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 1263: Cleanup
This commit is contained in:
committed by
Nino Righi
parent
0e5c35fae4
commit
24a008b20d
257
angular.json
257
angular.json
@@ -3,256 +3,6 @@
|
||||
"version": 1,
|
||||
"newProjectRoot": "apps",
|
||||
"projects": {
|
||||
"ui": {
|
||||
"root": "libs/ui",
|
||||
"sourceRoot": "libs/ui",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:ng-packagr",
|
||||
"options": {
|
||||
"tsConfig": "libs/ui/tsconfig.lib.json",
|
||||
"project": "libs/ui/ng-package.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"tsConfig": "libs/ui/tsconfig.lib.prod.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "libs/ui/src/test.ts",
|
||||
"tsConfig": "libs/ui/tsconfig.spec.json",
|
||||
"karmaConfig": "libs/ui/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"libs/ui/tsconfig.lib.json",
|
||||
"libs/ui/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sales": {
|
||||
"root": "apps/sales/",
|
||||
"sourceRoot": "apps/sales/src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-builders/custom-webpack:browser",
|
||||
"options": {
|
||||
"aot": true,
|
||||
"outputPath": "dist/sales",
|
||||
"index": "apps/sales/src/index.html",
|
||||
"main": "apps/sales/src/main.ts",
|
||||
"polyfills": "apps/sales/src/polyfills.ts",
|
||||
"tsConfig": "apps/sales/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/sales/src/favicon.ico",
|
||||
"apps/sales/src/assets",
|
||||
"apps/sales/src/manifest.webmanifest",
|
||||
"apps/sales/src/browserconfig.xml",
|
||||
"apps/sales/src/silent-refresh.html"
|
||||
],
|
||||
"styles": [
|
||||
"apps/sales/src/styles.scss"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"apps/sales/src/scss"
|
||||
]
|
||||
},
|
||||
"scripts": [],
|
||||
"customWebpackConfig": {
|
||||
"path": "apps/sales/webpack.config.js"
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/sales/src/environments/environment.ts",
|
||||
"with": "apps/sales/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "25kb"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
},
|
||||
"development": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "25kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-builders/custom-webpack:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "sales:build"
|
||||
},
|
||||
"configurations": {
|
||||
"test": {
|
||||
"browserTarget": "sales:build:test"
|
||||
},
|
||||
"integration": {
|
||||
"browserTarget": "sales:build:integration"
|
||||
},
|
||||
"staging": {
|
||||
"browserTarget": "sales:build:staging"
|
||||
},
|
||||
"production": {
|
||||
"browserTarget": "sales:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "sales:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/sales/src/test.ts",
|
||||
"polyfills": "apps/sales/src/polyfills.ts",
|
||||
"tsConfig": "apps/sales/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/sales/karma.conf.js",
|
||||
"styles": [
|
||||
"apps/sales/src/styles.scss"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"apps/sales/src/scss"
|
||||
]
|
||||
},
|
||||
"scripts": [],
|
||||
"assets": [
|
||||
"apps/sales/src/favicon.ico",
|
||||
"apps/sales/src/assets",
|
||||
"apps/sales/src/manifest.webmanifest"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/sales/tsconfig.app.json",
|
||||
"apps/sales/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sales-e2e": {
|
||||
"root": "apps/sales-e2e/",
|
||||
"projectType": "application",
|
||||
"prefix": "",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "apps/sales-e2e/protractor.conf.js",
|
||||
"devServerTarget": "sales:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"integration": {
|
||||
"devServerTarget": "sales:serve:integration"
|
||||
},
|
||||
"production": {
|
||||
"devServerTarget": "sales:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": "apps/sales-e2e/tsconfig.e2e.json",
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sso": {
|
||||
"root": "libs/sso",
|
||||
"sourceRoot": "libs/sso/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:ng-packagr",
|
||||
"options": {
|
||||
"tsConfig": "libs/sso/tsconfig.lib.json",
|
||||
"project": "libs/sso/ng-package.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"tsConfig": "libs/sso/tsconfig.lib.prod.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "libs/sso/src/test.ts",
|
||||
"tsConfig": "libs/sso/tsconfig.spec.json",
|
||||
"karmaConfig": "libs/sso/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"libs/sso/tsconfig.lib.json",
|
||||
"libs/sso/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/availability": {
|
||||
"root": "apps/swagger/availability",
|
||||
"sourceRoot": "apps/swagger/availability/src",
|
||||
@@ -3310,6 +3060,11 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"allowedCommonJsDependencies": [
|
||||
"lodash",
|
||||
"pdfjs-dist/es5/build/pdf",
|
||||
"pdfjs-dist/es5/web/pdf_viewer"
|
||||
],
|
||||
"outputPath": "dist/isa-app",
|
||||
"index": "apps/isa-app/src/index.html",
|
||||
"main": "apps/isa-app/src/main.ts",
|
||||
@@ -3875,6 +3630,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"defaultProject": "isa-app"
|
||||
}
|
||||
@@ -28,7 +28,7 @@
|
||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||
*/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
/**
|
||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||
@@ -62,3 +62,4 @@ import 'zone.js'; // Included with Angular CLI.
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
import 'hammerjs';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { ProductImageService } from '@cdn/product-image';
|
||||
import { HistoryComponent } from '@modal/history';
|
||||
import { ImageService } from '@sales/core-services';
|
||||
import { OrderDTO, OrderItemDTO, OrderItemSubsetDTO } from '@swagger/oms';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'page-customer-order-item-card',
|
||||
@@ -41,13 +41,21 @@ export class CustomerOrderItemCardComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private imageService: ImageService, private _modal: UiModalService) {}
|
||||
constructor(private imageService: ProductImageService, private _modal: UiModalService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.imageUrl = this.imageService.getImageUrl(this.orderItem.product.ean, {
|
||||
width: 60,
|
||||
height: 100,
|
||||
});
|
||||
// this.imageUrl = this.imageService.getImageUrl(this.orderItem.product.ean, {
|
||||
// width: 60,
|
||||
// height: 100,
|
||||
// });
|
||||
|
||||
this.imageUrl = of(
|
||||
this.imageService.getImageUrl({
|
||||
imageId: this.orderItem.product.ean,
|
||||
width: 60,
|
||||
height: 100,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
openHistory() {
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: ['./src/**/*.e2e-spec.ts'],
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function () {},
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.e2e.json'),
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
},
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('Welcome to sales!');
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo() {
|
||||
return browser.get('/');
|
||||
}
|
||||
|
||||
getTitleText() {
|
||||
return element(by.css('app-root h1')).getText();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/app",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11
|
||||
@@ -1,32 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../coverage'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true,
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['ChromeHeadless'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"index": "/index.html",
|
||||
"assetGroups": [
|
||||
{
|
||||
"name": "sales",
|
||||
"installMode": "prefetch",
|
||||
"resources": {
|
||||
"files": ["/favicon.ico", "/*.webmanifest", "/*.css", "/*.js"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assets",
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"assets/**",
|
||||
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SignalRHubOptions } from '@core/signalr';
|
||||
import { AuthConfig } from 'angular-oauth2-oidc';
|
||||
|
||||
@Injectable()
|
||||
export class AppConfiguration {
|
||||
includeGoogleAnalytics = false;
|
||||
title?: string;
|
||||
|
||||
cdn: { [key: string]: string };
|
||||
|
||||
sso: AuthConfig;
|
||||
|
||||
hubs: { [key: string]: SignalRHubOptions };
|
||||
|
||||
swagger: { [key: string]: { rootUrl: string } };
|
||||
|
||||
remissionModuleOptions: {
|
||||
useMock: false;
|
||||
endpoints: { [key: string]: string };
|
||||
};
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';
|
||||
import { LogInComponent } from './components/log-in/log-in.component';
|
||||
import { DashboardComponent } from './modules/dashboard/pages/dashboard.component';
|
||||
import { AuthenticationGuard } from './resolvers/authentication.guard';
|
||||
import { ProcessIdResolver } from './resolvers/process-id.resolver';
|
||||
import { BranchSectionResolver, CustomerSectionResolver } from './resolvers/section.resolver';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'login',
|
||||
resolve: { section: CustomerSectionResolver },
|
||||
children: [
|
||||
{ path: '', component: LogInComponent, pathMatch: 'full' },
|
||||
{ path: ':token', component: LogInComponent },
|
||||
],
|
||||
},
|
||||
{ path: 'dashboard', resolve: { section: CustomerSectionResolver }, component: DashboardComponent, canActivate: [AuthenticationGuard] },
|
||||
{
|
||||
path: 'product',
|
||||
resolve: { processId: ProcessIdResolver, section: CustomerSectionResolver },
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'customer',
|
||||
resolve: { processId: ProcessIdResolver, section: CustomerSectionResolver },
|
||||
loadChildren: () => import('@page/customer').then((m) => m.PageCustomerModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'cart',
|
||||
resolve: { processId: ProcessIdResolver, section: CustomerSectionResolver },
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'branch',
|
||||
resolve: { section: BranchSectionResolver },
|
||||
loadChildren: () => import('./modules/branch/branch.module').then((m) => m.BranchModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'debug',
|
||||
loadChildren: () => import('./modules/debug/debug.module').then((m) => m.DebugModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'goods',
|
||||
children: [
|
||||
{
|
||||
path: 'in',
|
||||
resolve: { section: BranchSectionResolver },
|
||||
loadChildren: () => import('@page/goods-in').then((m) => m.GoodsInModule),
|
||||
},
|
||||
{
|
||||
path: 'out',
|
||||
resolve: { section: CustomerSectionResolver },
|
||||
loadChildren: () => import('@page/goods-out').then((m) => m.GoodsOutModule),
|
||||
},
|
||||
],
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'remission',
|
||||
resolve: { section: BranchSectionResolver },
|
||||
loadChildren: () => import('./modules/remission/remission-client.module').then((m) => m.RemissionClientModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'task-calendar',
|
||||
resolve: { section: BranchSectionResolver },
|
||||
loadChildren: () => import('@page/task-calendar').then((m) => m.PageTaskCalendarModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{
|
||||
path: 'shelf',
|
||||
loadChildren: () => import('./modules/shelf/shelf.module').then((m) => m.ShelfModule),
|
||||
canActivate: [AuthenticationGuard],
|
||||
},
|
||||
{ path: '**', redirectTo: 'dashboard' },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(routes, {
|
||||
preloadingStrategy: PreloadAllModules,
|
||||
scrollPositionRestoration: 'enabled',
|
||||
relativeLinkResolution: 'legacy',
|
||||
}),
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { StoreModule, MetaReducer, ActionReducer, INIT } from '@ngrx/store';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { storeFreeze } from 'ngrx-store-freeze';
|
||||
import { environment } from '../environments/environment';
|
||||
import { RootState } from './store/root.state';
|
||||
import { rootReducer } from './store/root.reducer';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { SearchEffects } from './store/customer';
|
||||
import { HistoryEffects } from '@shelf-store/history';
|
||||
import { DetailsEffects } from '@shelf-store/details';
|
||||
import packageInfo from 'package';
|
||||
|
||||
// TODO: In Service Speichern
|
||||
export function storeInLocalStorage(reducer: ActionReducer<any>): ActionReducer<any> {
|
||||
const lsKey = 'ISA_NGRX_STATE_1';
|
||||
|
||||
return function (state, action) {
|
||||
if (action.type === INIT) {
|
||||
const storedState = JSON.parse(localStorage.getItem(lsKey));
|
||||
if (storedState?.version === packageInfo.version) {
|
||||
return reducer(storedState, action);
|
||||
}
|
||||
}
|
||||
const nextState = reducer(state, action);
|
||||
localStorage.setItem(lsKey, JSON.stringify({ ...nextState, version: packageInfo.version }));
|
||||
return nextState;
|
||||
};
|
||||
}
|
||||
|
||||
export const metaReducers: MetaReducer<RootState>[] = !environment.production ? [storeFreeze, storeInLocalStorage] : [storeInLocalStorage];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
StoreModule.forRoot(rootReducer, { metaReducers }),
|
||||
EffectsModule.forRoot([SearchEffects, HistoryEffects, DetailsEffects]),
|
||||
StoreDevtoolsModule.instrument({ name: 'ISA Ngrx Store' }),
|
||||
],
|
||||
})
|
||||
export class AppStoreModule {}
|
||||
@@ -1,64 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { PrintConfiguration } from '@swagger/print';
|
||||
import { OmsConfiguration } from '@swagger/oms';
|
||||
import { IsaConfiguration } from '@swagger/isa';
|
||||
import { CrmConfiguration } from '@swagger/crm';
|
||||
import { CheckoutConfiguration } from '@swagger/checkout';
|
||||
import { AvConfiguration } from '@swagger/availability';
|
||||
import { CatConfiguration } from '@swagger/cat';
|
||||
import { EisConfiguration } from '@swagger/eis';
|
||||
import { RemiConfiguration } from '@swagger/remi';
|
||||
|
||||
import { AppConfiguration } from './app-configuration';
|
||||
|
||||
export function catConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.api;
|
||||
}
|
||||
|
||||
export function avConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.av;
|
||||
}
|
||||
|
||||
export function checkoutConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.checkout;
|
||||
}
|
||||
|
||||
export function crmConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.crm;
|
||||
}
|
||||
|
||||
export function isaConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.isa;
|
||||
}
|
||||
|
||||
export function omsConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.oms;
|
||||
}
|
||||
|
||||
export function printConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.print;
|
||||
}
|
||||
|
||||
export function eisConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.eis;
|
||||
}
|
||||
|
||||
export function remiConfigurationFactory(config: AppConfiguration) {
|
||||
return config.swagger.remi;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{ provide: CatConfiguration, useFactory: catConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: AvConfiguration, useFactory: avConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: CheckoutConfiguration, useFactory: checkoutConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: CrmConfiguration, useFactory: crmConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: IsaConfiguration, useFactory: isaConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: OmsConfiguration, useFactory: omsConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: PrintConfiguration, useFactory: printConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: EisConfiguration, useFactory: eisConfigurationFactory, deps: [AppConfiguration] },
|
||||
{ provide: RemiConfiguration, useFactory: remiConfigurationFactory, deps: [AppConfiguration] },
|
||||
],
|
||||
})
|
||||
export class AppSwaggerModule {}
|
||||
@@ -1,7 +0,0 @@
|
||||
<lib-offline-overlay>
|
||||
<!-- lib offline depends on these three elements to be present inside of it -->
|
||||
<app-header [ngClass]="{ loading: loading$ | async }" *ngIf="authenticated"></app-header>
|
||||
<app-content [ngClass]="{ loading: loading$ | async }"></app-content>
|
||||
<app-menu [ngClass]="{ loading: loading$ | async }" *ngIf="authenticated"></app-menu>
|
||||
<img *ngIf="loading$ | async" src="/assets/images/Icon_Loading.svg" class="app-loader" />
|
||||
</lib-offline-overlay>
|
||||
@@ -1,36 +0,0 @@
|
||||
h1 {
|
||||
color: #369;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 250%;
|
||||
}
|
||||
|
||||
.app-loader {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -20px 0 0 -20px;
|
||||
-webkit-animation: spin 1.5s linear infinite;
|
||||
-moz-animation: spin 1.5s linear infinite;
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
|
||||
.loading {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@-moz-keyframes spin {
|
||||
100% {
|
||||
-moz-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule],
|
||||
declarations: [AppComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -1,132 +0,0 @@
|
||||
import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit, Renderer2 } from '@angular/core';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { take, filter, takeUntil } from 'rxjs/operators';
|
||||
import { SsoService } from 'sso';
|
||||
import { AppService } from './core/services/app.service';
|
||||
import { AppState } from './core/store/state/app.state';
|
||||
import { AppConfiguration } from './app-configuration';
|
||||
import { NativeContainerService } from 'shared/lib/barcode-scanner';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { Actions as NgxsActions, ofActionDispatched } from '@ngxs/store';
|
||||
import { DeleteProcess } from './core/store/actions/process.actions';
|
||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
title = 'Hugendubel InstoreApp';
|
||||
loading$ = new BehaviorSubject(true);
|
||||
includeGoogleAnalytics = this.config.includeGoogleAnalytics;
|
||||
destroy$ = new Subject();
|
||||
|
||||
get authenticated() {
|
||||
return this.ssoService.isAuthenticated();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private config: AppConfiguration,
|
||||
private ssoService: SsoService,
|
||||
private appService: AppService,
|
||||
private router: Router,
|
||||
private store: Store,
|
||||
private nativeContainer: NativeContainerService,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
private renderer: Renderer2,
|
||||
private applicationService: ApplicationService,
|
||||
private domainCheckoutService: DomainCheckoutService,
|
||||
private ngxsActions$: NgxsActions,
|
||||
private deviceDetectorService: DeviceDetectorService
|
||||
) {
|
||||
this.appService.loader$.subscribe(() => {
|
||||
this.loading$.next(false);
|
||||
});
|
||||
|
||||
this.appService.loader$.pipe(take(1)).subscribe(() => {
|
||||
this.containerNotificationMessage();
|
||||
});
|
||||
|
||||
// intialisations done only when app loads
|
||||
this.appService.appLoadInitialisations();
|
||||
|
||||
// this.router.events.subscribe((event) => {
|
||||
// if (event instanceof NavigationStart) {
|
||||
// try {
|
||||
// throw new Error(event.toString());
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd)).subscribe(() => {
|
||||
if (!this.router.url.includes('login')) {
|
||||
// send router navigation events
|
||||
this.appService.registerNavigationEvents();
|
||||
}
|
||||
});
|
||||
|
||||
this.applicationService.section$.pipe(takeUntil(this.destroy$)).subscribe((section) => {
|
||||
document.body.classList.remove('branch', 'customer');
|
||||
document.body.classList.add(section);
|
||||
});
|
||||
|
||||
this.store
|
||||
.select(AppState.getCurrentProcessId)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((processId) => this.applicationService.setActivatedProcessId(processId));
|
||||
|
||||
this.ngxsActions$.pipe(ofActionDispatched(DeleteProcess)).subscribe((action: DeleteProcess) => {
|
||||
this.domainCheckoutService.removeProcess({ processId: action.payload.id });
|
||||
this.applicationService.removeProcess(action.payload.id);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.includeGoogleAnalytics) {
|
||||
this.initGoogleAnalytics();
|
||||
}
|
||||
|
||||
this.renderer.addClass(this.document.body, this.deviceDetectorService.deviceType);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
private containerNotificationMessage() {
|
||||
// Notify the container app if the user has initialized app loggeed in or not
|
||||
// For the purpposes of removing the container Header element
|
||||
if (this.nativeContainer.isUiWebview()) {
|
||||
this.nativeContainer.sendMessage({ userAuthenticated: this.ssoService.isAuthenticated() });
|
||||
}
|
||||
}
|
||||
|
||||
private initGoogleAnalytics() {
|
||||
const htmlScript: HTMLScriptElement = this.renderer.createElement('script');
|
||||
htmlScript.text = `
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
(i[r] =
|
||||
i[r] ||
|
||||
function () {
|
||||
(i[r].q = i[r].q || []).push(arguments);
|
||||
}),
|
||||
(i[r].l = 1 * new Date());
|
||||
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m);
|
||||
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-76423009-5', 'auto');
|
||||
`;
|
||||
this.renderer.appendChild(this.document.body, htmlScript);
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NgModule, ErrorHandler, LOCALE_ID, APP_INITIALIZER } from '@angular/core';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { ComponentsModule } from './modules/components.module';
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { NgxsModule } from '@ngxs/store';
|
||||
import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';
|
||||
import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';
|
||||
import { ProcessState } from './core/store/state/process.state';
|
||||
import { BreadcrumbsState } from './core/store/state/breadcrumbs.state';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { SharedModule } from './shared/shared.module';
|
||||
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
import { NotifierState } from './core/store/state/notifier.state';
|
||||
import { environment } from '../environments/environment';
|
||||
import { ModalModule, IconModule, OfflineOverlayModule } from '@libs/ui';
|
||||
import { ProductState } from './core/store/state/product.state';
|
||||
import { AppState } from './core/store/state/app.state';
|
||||
import { BranchState } from './core/store/state/branches.state';
|
||||
import { SsoModule, SsoInterface, SsoService } from 'sso';
|
||||
import { SsoAuthorizationInterceptor, HttpErrorHandlerInterceptor } from './core/interceptors';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { HimaSalesErrorHandler } from './core/error/hima-sales.error-handler';
|
||||
import { CollectingShelfState } from './core/store/state/collecting-shelf.state';
|
||||
import 'apps/sales/src/app/core/utils/app.prototypes';
|
||||
import { VatState } from './core/store/state/vat.state';
|
||||
import { SupplierState } from './core/store/state/supplier.state';
|
||||
import { GoodsInState } from './core/store/state/goods-in.state';
|
||||
import { BranchProcessState } from './core/store/state/branch-process.state';
|
||||
import { RemissionModule, RemissionModuleOptions } from '@isa/remission';
|
||||
import { RemissionState } from './core/store/state/remission.state';
|
||||
import { NgIdleKeepaliveModule } from '@ng-idle/keepalive';
|
||||
import { AppSwaggerModule } from './app-swagger.module';
|
||||
import { AppConfiguration } from './app-configuration';
|
||||
import { FormsState } from './core/store/state/forms.state';
|
||||
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeDeExtra from '@angular/common/locales/extra/de';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import { RemissionStateHandler } from './core/store/handlers/remission.handlers';
|
||||
import { SsoConfigurationService } from './core/services/sso-configuration.service';
|
||||
import { OverlayModule } from '@angular/cdk/overlay';
|
||||
import { ModalDialogueModule } from './core/overlay/component';
|
||||
import { OverlaysModule } from './core/overlay/overlays.module';
|
||||
import { CoreBreadcrumbModule } from '@core/breadcrumb';
|
||||
import { ApplicationService, CoreApplicationModule, ProcessService } from '@core/application';
|
||||
import { UiModalModule } from '@ui/modal';
|
||||
import { ProcessRefactImp } from './refact-imp/process.refact-imp';
|
||||
import { DomainCheckoutModule } from '@domain/checkout';
|
||||
import { CDN_PRODUCT_PICTURES } from './tokens';
|
||||
import { DateAdapter } from '@ui/common';
|
||||
import { ApplicationRefactImp } from './refact-imp/application.refact-imp';
|
||||
import { CDN_PRODUCT_IMAGE } from 'apps/cdn/product-image/src/lib/tokens';
|
||||
import { DomainCatalogModule } from '@domain/catalog';
|
||||
import { AppStoreModule } from './app-store.module';
|
||||
import { DomainOmsModule } from '@domain/oms';
|
||||
import { DomainAvailabilityModule } from '@domain/availability';
|
||||
import { CoreCommandModule } from '@core/command';
|
||||
import { NotificationsHubModule, NOTIFICATIONS_HUB_OPTIONS } from '@hub/notifications';
|
||||
import { SignalRHubOptions } from '@core/signalr';
|
||||
import { UiIconModule } from '@ui/icon';
|
||||
|
||||
registerLocaleData(localeDe, localeDeExtra);
|
||||
registerLocaleData(localeDe, 'de', localeDeExtra);
|
||||
|
||||
const states = [
|
||||
AppState,
|
||||
ProcessState,
|
||||
BreadcrumbsState,
|
||||
NotifierState,
|
||||
ProductState,
|
||||
BranchState,
|
||||
CollectingShelfState,
|
||||
VatState,
|
||||
SupplierState,
|
||||
BranchProcessState,
|
||||
GoodsInState,
|
||||
RemissionState,
|
||||
FormsState,
|
||||
];
|
||||
|
||||
export function noop() {
|
||||
return function () {};
|
||||
}
|
||||
|
||||
export function remissionModuleOptionsFactory(config: AppConfiguration): RemissionModuleOptions {
|
||||
return config.remissionModuleOptions;
|
||||
}
|
||||
|
||||
export function cdnProdutctPictures(config: AppConfiguration): string {
|
||||
return config.cdn.productPictures;
|
||||
}
|
||||
|
||||
export function _notificationsHubOptionsFactory(config: AppConfiguration, sso: SsoService): SignalRHubOptions {
|
||||
const options = { ...config.hubs.notifications };
|
||||
|
||||
options.httpOptions.accessTokenFactory = () => sso.getToken();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
AppRoutingModule,
|
||||
AppSwaggerModule,
|
||||
AppStoreModule,
|
||||
ComponentsModule,
|
||||
HttpClientModule,
|
||||
NgxsModule.forRoot(states, { developmentMode: !environment.production }),
|
||||
NgxsReduxDevtoolsPluginModule.forRoot({ name: 'ISA NGXS Store' }),
|
||||
NgxsLoggerPluginModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
SharedModule,
|
||||
ScrollingModule,
|
||||
IconModule,
|
||||
ModalModule.forRoot(),
|
||||
SsoModule.forRoot(environment.production),
|
||||
OfflineOverlayModule,
|
||||
NgIdleKeepaliveModule.forRoot(),
|
||||
RemissionModule.forRoot(undefined),
|
||||
OverlayModule,
|
||||
OverlaysModule,
|
||||
ModalDialogueModule,
|
||||
|
||||
/**
|
||||
* @core Modules
|
||||
*/
|
||||
CoreBreadcrumbModule.forRoot(),
|
||||
CoreApplicationModule.forRoot(),
|
||||
CoreCommandModule.forRoot([]),
|
||||
|
||||
/**
|
||||
* @domain Modules
|
||||
*/
|
||||
DomainAvailabilityModule.forRoot(),
|
||||
DomainCheckoutModule.forRoot(),
|
||||
DomainCatalogModule.forRoot(),
|
||||
DomainOmsModule.forRoot(),
|
||||
|
||||
/**
|
||||
* @ui Modules
|
||||
*/
|
||||
UiModalModule.forRoot(),
|
||||
UiIconModule,
|
||||
|
||||
/**
|
||||
* @hub Modules
|
||||
*/
|
||||
NotificationsHubModule.forRoot(),
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: noop,
|
||||
deps: [RemissionStateHandler],
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: SsoAuthorizationInterceptor,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: HttpErrorHandlerInterceptor,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: RemissionModuleOptions,
|
||||
useFactory: remissionModuleOptionsFactory,
|
||||
deps: [AppConfiguration],
|
||||
},
|
||||
DatePipe,
|
||||
{
|
||||
provide: ErrorHandler,
|
||||
useClass: HimaSalesErrorHandler,
|
||||
},
|
||||
{ provide: LOCALE_ID, useValue: 'de-DE' },
|
||||
{
|
||||
provide: SsoInterface,
|
||||
useClass: SsoConfigurationService,
|
||||
},
|
||||
DateAdapter,
|
||||
{
|
||||
provide: ProcessService,
|
||||
useClass: ProcessRefactImp,
|
||||
},
|
||||
{
|
||||
provide: ApplicationService,
|
||||
useClass: ApplicationRefactImp,
|
||||
},
|
||||
{
|
||||
provide: CDN_PRODUCT_PICTURES,
|
||||
useFactory: cdnProdutctPictures,
|
||||
deps: [AppConfiguration],
|
||||
},
|
||||
{
|
||||
provide: CDN_PRODUCT_IMAGE,
|
||||
useFactory: cdnProdutctPictures,
|
||||
deps: [AppConfiguration],
|
||||
},
|
||||
{
|
||||
provide: NOTIFICATIONS_HUB_OPTIONS,
|
||||
useFactory: _notificationsHubOptionsFactory,
|
||||
deps: [AppConfiguration, SsoService],
|
||||
},
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -1,40 +0,0 @@
|
||||
<div class="breadacrumb-grid" [ngClass]="{ 'grid-with-arrow': !showBack, 'breadcumb-mb-5': lowerMargin }" *ngIf="breadcrumbs">
|
||||
<app-back-arrow *ngIf="showBack" (back)="goBack(breadcrumbs[breadcrumbs.length - 2])" class="align-right back-arrow"></app-back-arrow>
|
||||
<div
|
||||
class="layer-fade-start"
|
||||
*ngIf="showBackNavigationArrow"
|
||||
(mouseover)="showBackNavArrow()"
|
||||
(mouseleave)="hideBackNavArrow($event)"
|
||||
></div>
|
||||
<div class="icon-start" *ngIf="showBackNavigationArrow && showBackArrow" (click)="navigateBack()" (mouseleave)="hideBackNavArrowIcon()">
|
||||
<lib-icon class="icon-start" width="40px" name="tab_Arrow_3" type="png"></lib-icon>
|
||||
</div>
|
||||
<div class="breadcrumb-start-layer-fade" *ngIf="!showBackNavigationArrow"></div>
|
||||
<div class="align-center breadcrumb-container" #container>
|
||||
<span
|
||||
*ngFor="let breadcrumb of breadcrumbs; let i = index; let last = last"
|
||||
class="breadcrumb show"
|
||||
(click)="selectBreadcrumb(breadcrumb)"
|
||||
[ngClass]="{ selected: last, branch: module === 1 }"
|
||||
>
|
||||
<lib-icon *ngIf="breadcrumbs.indexOf(breadcrumb) > 0 && i != 0 && i !== last" class="next" name="Arrow_Next" alt="next"></lib-icon>
|
||||
<span>{{ breadcrumb ? breadcrumb.name : '' }}</span>
|
||||
</span>
|
||||
<span class="breadcrumb last" *ngIf="showBack"></span>
|
||||
</div>
|
||||
<div class="breadcrumb-end-layer-fade" *ngIf="!showForwardNavigationalArrow"></div>
|
||||
<div
|
||||
class="layer-fade-end"
|
||||
*ngIf="showForwardNavigationalArrow"
|
||||
(mouseover)="showForwardNavArrow()"
|
||||
(mouseleave)="hideForwardNavArrow($event)"
|
||||
></div>
|
||||
<div
|
||||
class="icon-end"
|
||||
*ngIf="showForwardNavigationalArrow && showForrwardArrow"
|
||||
(click)="navigateForward()"
|
||||
(mouseleave)="hideForwardNavArrowIcon()"
|
||||
>
|
||||
<lib-icon class="icon-end" width="40px" name="tab_Arrow_2" type="png"></lib-icon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,232 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
.breadacrumb-grid {
|
||||
display: grid;
|
||||
grid-template-columns: min-content auto;
|
||||
grid-gap: 15px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.breadcumb-mb-5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.grid-with-arrow {
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
// display: flex;
|
||||
align-items: center;
|
||||
// justify-content: center;
|
||||
white-space: nowrap;
|
||||
overflow-y: hidden;
|
||||
scroll-behavior: smooth;
|
||||
overflow-x: scroll;
|
||||
height: 45px;
|
||||
padding-top: 10px;
|
||||
// width: calc(100% - 100px);
|
||||
}
|
||||
|
||||
:only-child {
|
||||
.breadcrumb-end-layer-fade {
|
||||
position: absolute;
|
||||
min-height: 45px;
|
||||
min-width: 5px;
|
||||
z-index: 20;
|
||||
opacity: 0.7;
|
||||
background-color: #e6eff9;
|
||||
box-shadow: -8px 0px 14px 3px #e6eff9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-start-layer-fade {
|
||||
position: absolute;
|
||||
min-height: 45px;
|
||||
min-width: 5px;
|
||||
z-index: 20;
|
||||
opacity: 0.7;
|
||||
background-color: #e6eff9;
|
||||
box-shadow: 8px 0px 14px 3px #e6eff9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
color: #1f466c;
|
||||
line-height: 21px;
|
||||
padding: 10px 0;
|
||||
padding-bottom: 0px;
|
||||
cursor: pointer;
|
||||
|
||||
&.branch {
|
||||
color: #596470;
|
||||
}
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
|
||||
&:nth-last-child(4) {
|
||||
/*declarations*/
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
flex: 0.0001;
|
||||
animation: fadeSlide 400ms;
|
||||
}
|
||||
&:nth-last-child(-n + 3) {
|
||||
/*declarations*/
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.last {
|
||||
padding: 10px 50px;
|
||||
}
|
||||
|
||||
.back-arrow-container {
|
||||
width: 118px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
transform: rotate(180deg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.foward-arrow-container {
|
||||
width: 118px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@keyframes fadeSlide {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateX(80px);
|
||||
flex: 0.5;
|
||||
overflow: hidden;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
flex: 0.0001;
|
||||
}
|
||||
}
|
||||
|
||||
.back-arrow {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.next {
|
||||
padding: 0 7px;
|
||||
}
|
||||
|
||||
.selected {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.icon-start {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
margin-top: 1px;
|
||||
z-index: 30;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layer-fade-start {
|
||||
position: absolute;
|
||||
min-height: 40px;
|
||||
min-width: 35px;
|
||||
z-index: 20;
|
||||
left: 100px;
|
||||
opacity: 0.4;
|
||||
background-color: white;
|
||||
box-shadow: 3px 0 14px 8px white;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.icon-end {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
margin-top: 1px;
|
||||
z-index: 30;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layer-fade-end {
|
||||
position: absolute;
|
||||
min-height: 40px;
|
||||
min-width: 35px;
|
||||
z-index: 20;
|
||||
right: 15px;
|
||||
opacity: 0.4;
|
||||
background-color: white;
|
||||
box-shadow: 3px 0 14px 8px white;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Big Desktops
|
||||
*/
|
||||
@media (min-width: 1281px) {
|
||||
.breadcrumb-end-layer-fade {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.breadcrumb-start-layer-fade {
|
||||
left: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Laptops, Desktops, Ipad pro
|
||||
*/
|
||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
||||
.breadcrumb-end-layer-fade {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.breadcrumb-start-layer-fade {
|
||||
left: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Tablets, Ipads
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.breadcrumb-end-layer-fade {
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.breadcrumb-start-layer-fade {
|
||||
left: 112px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Low Resolution Tablets, Mobiles (Landscape)
|
||||
*/
|
||||
@media (min-width: 481px) and (max-width: 767px) {
|
||||
.breadcrumb-end-layer-fade {
|
||||
right: 15px;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { BreadcrumbsComponent } from './breadcrumbs.component';
|
||||
|
||||
describe('BreadcrumbsComponent', () => {
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [BreadcrumbsComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -1,286 +0,0 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
ChangeDetectorRef,
|
||||
ChangeDetectionStrategy,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
AfterViewInit,
|
||||
} from '@angular/core';
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { Breadcrumb } from '../../core/models/breadcrumb.model';
|
||||
import { Process } from '../../core/models/process.model';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import { ChangeCurrentRoute, ResetProcessProductFilters } from '../../core/store/actions/process.actions';
|
||||
import { Router } from '@angular/router';
|
||||
import { takeUntil, switchMap, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { SharedSelectors } from '../../core/store/selectors/shared.selectors';
|
||||
import { ResetFilters } from '../../core/store/actions/filter.actions';
|
||||
import { AppService } from '../../core/services/app.service';
|
||||
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';
|
||||
import { BranchProcess } from '../../core/models/branch-process.model';
|
||||
import { SetBranchProcessCurrentPath } from '../../core/store/actions/branch-process.actions';
|
||||
import { AppState } from '../../core/store/state/app.state';
|
||||
import { FILIALE_LANDING_PAGE } from '../../core/utils/app.constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-breadcrumbs',
|
||||
templateUrl: './breadcrumbs.component.html',
|
||||
styleUrls: ['./breadcrumbs.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class BreadcrumbsComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
@ViewChild('container', { read: ElementRef })
|
||||
public container: ElementRef<any>;
|
||||
@Select(SharedSelectors.getBreadcrumbs) breadcrumbs$: Observable<Breadcrumb[]>;
|
||||
@Select(SharedSelectors.getCurrentProcess) currentProcess$: Observable<Process>;
|
||||
module: ModuleSwitcher;
|
||||
destroy$ = new Subject();
|
||||
breadcrumbs: Breadcrumb[] = [];
|
||||
currentRoute = '';
|
||||
start: number;
|
||||
end: number;
|
||||
breadsCount: number;
|
||||
showBack = true;
|
||||
showBackNavigationArrow = false;
|
||||
showBackArrow = false;
|
||||
showForwardNavigationalArrow = false;
|
||||
showForrwardArrow = false;
|
||||
isIPad = false;
|
||||
|
||||
get firstVisibleItem() {
|
||||
if (this.start) {
|
||||
return this.start;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
get lastVisibleItem() {
|
||||
if (this.end) {
|
||||
return this.end;
|
||||
}
|
||||
return this.breadcrumbs ? this.breadcrumbs.length - 1 : 0;
|
||||
}
|
||||
|
||||
get backArrow() {
|
||||
return this.router.url.substring(0, 16) === '/product/details' && this.breadsCount > 1;
|
||||
}
|
||||
|
||||
get selectedBreadCrumbIndex() {
|
||||
if (!this.currentRoute) {
|
||||
return 0;
|
||||
}
|
||||
let route = this.currentRoute;
|
||||
const hasParams = this.currentRoute.includes('?');
|
||||
if (hasParams) {
|
||||
const endOfRouteWithOutParams = this.currentRoute.indexOf('?');
|
||||
route = this.currentRoute.substring(0, endOfRouteWithOutParams);
|
||||
}
|
||||
return this.breadcrumbs.findIndex((t) => t && t.path.indexOf(route) >= 0);
|
||||
}
|
||||
|
||||
get lowerMargin() {
|
||||
if (this.router.url === '/customer/results') {
|
||||
return true;
|
||||
}
|
||||
if (this.router.url.substring(0, 14) === '/customer/edit') {
|
||||
return true;
|
||||
}
|
||||
if (this.router.url.substring(0, 16) === '/product/details') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constructor(private store: Store, private router: Router, private cdrf: ChangeDetectorRef, private appService: AppService) {}
|
||||
|
||||
getBreadcrumbsFromCurentProcess() {
|
||||
this.currentProcess$
|
||||
.pipe(
|
||||
switchMap((process: Process | BranchProcess) => {
|
||||
if (process) {
|
||||
this.currentRoute = `${process.currentRoute}`;
|
||||
this.cdrf.detectChanges();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.container.nativeElement.scrollTo({
|
||||
left: this.container.nativeElement.scrollWidth,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}, 400);
|
||||
return this.breadcrumbs$;
|
||||
}),
|
||||
takeUntil(this.destroy$),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
.subscribe((breadcrumbs: Breadcrumb[]) => {
|
||||
this.showForwardNavigationalArrow = false;
|
||||
this.showBackNavigationArrow = false;
|
||||
if (breadcrumbs) {
|
||||
const breadName =
|
||||
breadcrumbs.length > 0 ? (breadcrumbs[breadcrumbs.length - 1] ? breadcrumbs[breadcrumbs.length - 1].name : '') : '';
|
||||
this.showBack = !(breadName === 'Bestellbestätigung' || breadName === 'Remission');
|
||||
this.breadcrumbs = breadcrumbs;
|
||||
this.breadsCount = Object.keys(this.breadcrumbs) ? Object.keys(this.breadcrumbs).length : 0;
|
||||
this.cdrf.detectChanges();
|
||||
if (!this.isIPad) {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
this.initNavigationalArrow();
|
||||
} catch (error) {}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
selectBreadcrumb(breadcrumb: Breadcrumb) {
|
||||
if (breadcrumb && breadcrumb.path) {
|
||||
if (breadcrumb.path === '/product/search') {
|
||||
this.store.dispatch(new ResetFilters());
|
||||
this.store.dispatch(new ResetProcessProductFilters());
|
||||
}
|
||||
if (this.module === ModuleSwitcher.Customer) {
|
||||
this.store.dispatch(new ChangeCurrentRoute(breadcrumb.path, true));
|
||||
} else {
|
||||
this.store.dispatch(new SetBranchProcessCurrentPath(breadcrumb.path, true));
|
||||
}
|
||||
this.router.navigate([breadcrumb.path], {
|
||||
queryParams: breadcrumb.queryParams ? breadcrumb.queryParams : {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
goBack(breadcrumb: Breadcrumb) {
|
||||
if (breadcrumb && breadcrumb.path) {
|
||||
if (this.module === ModuleSwitcher.Customer) {
|
||||
this.store.dispatch(new ChangeCurrentRoute(breadcrumb.path, false));
|
||||
this.router.navigate(['/product/results']);
|
||||
} else {
|
||||
this.store.dispatch(new SetBranchProcessCurrentPath(breadcrumb.path, false));
|
||||
this.router.navigate([FILIALE_LANDING_PAGE]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.isIPad = this.appService.isIPadEnv();
|
||||
this.getBreadcrumbsFromCurentProcess();
|
||||
this.store
|
||||
.select(AppState.activeModule)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((v: ModuleSwitcher) => {
|
||||
this.module = v;
|
||||
this.cdrf.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (!this.isIPad) {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
this.initNavigationalArrow();
|
||||
} catch (error) {}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
addOne() {
|
||||
this.breadcrumbs.push({
|
||||
name: 'test' + (this.breadcrumbs ? this.breadcrumbs.length : 0),
|
||||
path: './i',
|
||||
});
|
||||
}
|
||||
|
||||
initNavigationalArrow() {
|
||||
if (this.container) {
|
||||
const containerWidth = this.container.nativeElement.offsetWidth;
|
||||
let childrenWidth = 60;
|
||||
let elementProcessed = 0;
|
||||
if (this.container.nativeElement.children) {
|
||||
const breadcrumbs = this.container.nativeElement.children.length - 1;
|
||||
for (let i = 0; i < breadcrumbs; i++) {
|
||||
elementProcessed++;
|
||||
childrenWidth += this.container.nativeElement.children[i].offsetWidth;
|
||||
}
|
||||
if (breadcrumbs === elementProcessed && containerWidth <= childrenWidth) {
|
||||
this.showBackNavigationArrow = true;
|
||||
this.cdrf.detectChanges();
|
||||
} else {
|
||||
this.showBackNavigationArrow = false;
|
||||
this.showForwardNavigationalArrow = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showBackNavArrow() {
|
||||
this.showBackArrow = true;
|
||||
}
|
||||
|
||||
hideBackNavArrow(event) {
|
||||
if (event) {
|
||||
const e = event.toElement || event.relatedTarget;
|
||||
if (e && e.classList && (e.classList[0] === 'icon' || e.classList[0] === 'ng-star-inserted')) {
|
||||
return;
|
||||
}
|
||||
this.showBackArrow = false;
|
||||
}
|
||||
}
|
||||
|
||||
hideBackNavArrowIcon() {
|
||||
this.showBackArrow = false;
|
||||
}
|
||||
|
||||
showForwardNavArrow() {
|
||||
this.showForrwardArrow = true;
|
||||
}
|
||||
|
||||
hideForwardNavArrow(event) {
|
||||
if (event) {
|
||||
const e = event.toElement || event.relatedTarget;
|
||||
if (e && e.classList && (e.classList[0] === 'icon' || e.classList[0] === 'ng-star-inserted')) {
|
||||
return;
|
||||
}
|
||||
this.showForrwardArrow = false;
|
||||
}
|
||||
}
|
||||
|
||||
hideForwardNavArrowIcon() {
|
||||
this.showForrwardArrow = false;
|
||||
}
|
||||
|
||||
navigateBack() {
|
||||
const scrollLeft = this.container.nativeElement.scrollLeft;
|
||||
if (scrollLeft <= 121) {
|
||||
this.showBackNavigationArrow = false;
|
||||
}
|
||||
this.container.nativeElement.scrollTo({
|
||||
left: scrollLeft - 120,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
this.showForwardNavigationalArrow = true;
|
||||
this.cdrf.detectChanges();
|
||||
}
|
||||
|
||||
navigateForward() {
|
||||
const scrollLeft = this.container.nativeElement.scrollLeft;
|
||||
const containerWidth = this.container.nativeElement.offsetWidth;
|
||||
const scrollWidth = this.container.nativeElement.scrollWidth;
|
||||
if (scrollLeft + 119 + containerWidth <= scrollWidth) {
|
||||
this.showForwardNavigationalArrow = false;
|
||||
}
|
||||
this.container.nativeElement.scrollTo({
|
||||
left: scrollLeft + 120,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
this.showBackNavigationArrow = true;
|
||||
this.cdrf.detectChanges();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<div class="container">
|
||||
<app-breadcrumbs *ngIf="showBreadCrumbs$ | async"> </app-breadcrumbs>
|
||||
<app-filter-button
|
||||
[active]="isFilterActive$ | async"
|
||||
[module]="activeModule$ | async"
|
||||
*ngIf="showFilter$ | async"
|
||||
(toggleFilter)="toggleFilter()"
|
||||
></app-filter-button>
|
||||
</div>
|
||||
@@ -1,31 +0,0 @@
|
||||
$filter-width: 106px;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
app-breadcrumbs {
|
||||
flex-grow: 1;
|
||||
margin-left: $filter-width;
|
||||
|
||||
::ng-deep app-back-arrow {
|
||||
margin-right: $filter-width;
|
||||
margin-left: -$filter-width;
|
||||
|
||||
& ~ .breadcrumb-container {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:only-child {
|
||||
margin-left: 0;
|
||||
|
||||
::ng-deep app-back-arrow {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { ComponentsModule } from '../../modules/components.module';
|
||||
import { ContentHeaderComponent } from './content-header.component';
|
||||
|
||||
describe('ContentHeaderComponent', () => {
|
||||
let fixture: ComponentFixture<ContentHeaderComponent>;
|
||||
let component: ContentHeaderComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ComponentsModule],
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(ContentHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should create the component', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show breadcrumbs', () => {});
|
||||
|
||||
it('should show filter button', () => {});
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemissionSelectors } from '../../core/store/selectors/remission.selectors';
|
||||
import { Select } from '@ngxs/store';
|
||||
import { ContentHeaderService } from '../../core/services/content-header.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-content-header',
|
||||
templateUrl: 'content-header.component.html',
|
||||
styleUrls: ['./content-header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ContentHeaderComponent implements OnInit {
|
||||
@Select(RemissionSelectors.getRemissionActiveFilters)
|
||||
remissionFilters$: Observable<string[]>;
|
||||
|
||||
showFilter$: Observable<boolean>;
|
||||
showBreadCrumbs$: Observable<boolean>;
|
||||
isFilterActive$: Observable<boolean>;
|
||||
activeModule$: Observable<'Customer' | 'Branch'>;
|
||||
|
||||
constructor(private contentHeaderService: ContentHeaderService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.showFilter$ = this.contentHeaderService.showFilter$;
|
||||
this.showBreadCrumbs$ = this.contentHeaderService.showBreadcrumbs$;
|
||||
this.activeModule$ = this.contentHeaderService.module$;
|
||||
this.isFilterActive$ = this.contentHeaderService.isFilterActive$;
|
||||
}
|
||||
|
||||
toggleFilter() {
|
||||
this.contentHeaderService.toggleFilter();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
// start:ng42.barrel
|
||||
export * from './content-header.component';
|
||||
// end:ng42.barrel
|
||||
@@ -1,52 +0,0 @@
|
||||
<div class="header-wrapper" [ngClass]="{ 'branch-header-wrapper': module === 1 }">
|
||||
<div class="app-header px-16">
|
||||
<div class="three-col-grid-container">
|
||||
<div class="align-left">
|
||||
<a *ngIf="module === 0" (click)="goToDashboard()" class="nav-link">
|
||||
<lib-icon width="190px" name="Logo-Refined_2-3x" type="png"></lib-icon>
|
||||
</a>
|
||||
<a *ngIf="module === 1">
|
||||
<lib-icon width="190px" name="Logo-Refined_2-3x" type="png"></lib-icon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="align-center">
|
||||
<div class="icons-grid pt-5">
|
||||
<div class="header-item align-center">
|
||||
<button class="header-icon dashboard" type="button" [routerLink]="['/dashboard']" routerLinkActive="active">
|
||||
<ui-icon icon="dashboard" size="26px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="header-item align-center">
|
||||
<button
|
||||
class="header-icon notification"
|
||||
type="button"
|
||||
[class.active]="notificationCount$ | async"
|
||||
[disabled]="(notificationCount$ | async) === 0"
|
||||
(click)="openNotifications()"
|
||||
>
|
||||
<div class="notification-counter" *ngIf="notificationCount$ | async; let count">{{ count }}</div>
|
||||
<ui-icon icon="notification" size="26px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="header-item align-center">
|
||||
<span class="current-branch" *ngIf="currentBranch$ | async; let currentBranch" [title]="currentBranch.name">
|
||||
{{ currentBranch.key | uppercase }}
|
||||
</span>
|
||||
<button class="header-icon logout" type="button" (click)="logoff()">
|
||||
<ui-icon icon="logout" size="26px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="align-right">
|
||||
<div class="switch-wrapper">
|
||||
<div></div>
|
||||
<lib-double-choice-switch [model]="doubleChoiceSwitch" (change)="siteChange($event)"></lib-double-choice-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-process-header></app-process-header>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<app-log-out #logOut></app-log-out>
|
||||
@@ -1,177 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
button.header-icon {
|
||||
@apply border-none outline-none bg-transparent;
|
||||
}
|
||||
|
||||
::ng-deep .customer app-header {
|
||||
button.header-icon {
|
||||
ui-icon {
|
||||
@apply text-wild-blue-yonder;
|
||||
}
|
||||
|
||||
&.active ui-icon {
|
||||
@apply text-inactive-customer;
|
||||
}
|
||||
}
|
||||
|
||||
.current-branch {
|
||||
@apply text-wild-blue-yonder;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .branch app-header {
|
||||
button.header-icon {
|
||||
ui-icon {
|
||||
@apply text-cool-grey;
|
||||
}
|
||||
|
||||
&.active ui-icon {
|
||||
@apply text-active-branch;
|
||||
}
|
||||
}
|
||||
|
||||
.current-branch {
|
||||
@apply text-cool-grey;
|
||||
}
|
||||
}
|
||||
|
||||
button.notification {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.notification-counter {
|
||||
@apply absolute flex items-center justify-center -top-2 -right-1 bg-brand text-white text-sm rounded-full w-6 h-6 font-semibold;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.header-item {
|
||||
@apply flex;
|
||||
|
||||
.current-branch {
|
||||
@apply flex items-center font-bold;
|
||||
}
|
||||
}
|
||||
|
||||
.header-wrapper {
|
||||
background-color: white;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: 105px;
|
||||
width: 100%;
|
||||
z-index: 150;
|
||||
padding-top: 30px;
|
||||
box-shadow: 0px 2px 6px 0px #dde5ec;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.branch-header-wrapper {
|
||||
box-shadow: 0px 2px 6px 0px #e9ebee;
|
||||
}
|
||||
|
||||
.logout {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 737px;
|
||||
height: 105px;
|
||||
padding-top: 30px;
|
||||
z-index: 100;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.three-col-grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
}
|
||||
|
||||
.three-col-grid-container-fixed {
|
||||
display: grid;
|
||||
grid-template-columns: auto max-content 40px;
|
||||
grid-column-gap: 1vh;
|
||||
}
|
||||
|
||||
.profile-name {
|
||||
font-weight: bold;
|
||||
color: $color-active;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.two-col-grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
grid-column-gap: 2vh;
|
||||
}
|
||||
|
||||
.icons-grid {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
grid-column-gap: 1vh;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.switch-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: auto min-content;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Big Desktops
|
||||
*/
|
||||
@media (min-width: 1281px) {
|
||||
.app-header {
|
||||
width: 916px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Laptops, Desktops, Ipad pro
|
||||
*/
|
||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
||||
.app-header {
|
||||
width: 916px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Tablets, Ipads
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.app-header {
|
||||
width: 737px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Low Resolution Tablets, Mobiles (Landscape)
|
||||
*/
|
||||
@media (min-width: 481px) and (max-width: 767px) {
|
||||
.app-header {
|
||||
width: 94%;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Most of the Smartphones Mobiles (Portrait)
|
||||
*/
|
||||
@media (min-width: 320px) and (max-width: 480px) {
|
||||
.app-header {
|
||||
width: 94%;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { HeaderComponent } from './header.component';
|
||||
|
||||
describe('HeaderComponent', () => {
|
||||
let component: HeaderComponent;
|
||||
let fixture: ComponentFixture<HeaderComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [HeaderComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,112 +0,0 @@
|
||||
import { Component, OnInit, ViewChild, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
||||
import { LogOutComponent } from '../log-out/log-out.component';
|
||||
import { DoubleChoiceSwitch, DoubleChoiceSwitchColor } from '@libs/ui';
|
||||
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';
|
||||
import { Subject } from 'rxjs';
|
||||
import { distinctUntilChanged, first, map, takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { ChangeCurrentRoute } from '../../core/store/actions/process.actions';
|
||||
import { Router } from '@angular/router';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { NotificationsHub } from '@hub/notifications';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { ModalNotificationsComponent } from 'apps/modal/notifications/src/public-api';
|
||||
import { DomainAvailabilityService } from '@domain/availability';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.scss'],
|
||||
})
|
||||
export class HeaderComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('logOut') logOutDialog: LogOutComponent;
|
||||
doubleChoiceSwitch: DoubleChoiceSwitch;
|
||||
module: ModuleSwitcher = ModuleSwitcher.Customer;
|
||||
destroy$ = new Subject();
|
||||
|
||||
notifications$ = this._notificationsHub.notifications$;
|
||||
|
||||
notificationCount$ = this.notifications$.pipe(map((message) => message?.data?.length));
|
||||
|
||||
currentBranch$ = this._availabilityService.getCurrentBranch();
|
||||
|
||||
constructor(
|
||||
private store: Store,
|
||||
private router: Router,
|
||||
private breadcrumb: BreadcrumbService,
|
||||
private applicationService: ApplicationService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private _notificationsHub: NotificationsHub,
|
||||
private _modal: UiModalService,
|
||||
private _availabilityService: DomainAvailabilityService
|
||||
) {}
|
||||
|
||||
customer = 'Kunden';
|
||||
|
||||
ngOnInit() {
|
||||
this.doubleChoiceSwitch = <DoubleChoiceSwitch>{
|
||||
firstChoice: 'Kunden',
|
||||
secondChoice: 'Filiale',
|
||||
firstChoiceColor: <DoubleChoiceSwitchColor>{
|
||||
selectedBackground: '#1F466C',
|
||||
selectedText: '#ffffff',
|
||||
unSelectedbackground: '#edeff0',
|
||||
unSelectedText: '#000000',
|
||||
},
|
||||
secondChoiceColor: <DoubleChoiceSwitchColor>{
|
||||
selectedBackground: '#596470',
|
||||
selectedText: '#ffffff',
|
||||
unSelectedbackground: '#E6EFF9',
|
||||
unSelectedText: '#000000',
|
||||
},
|
||||
isFirstSwitchedOn: true,
|
||||
};
|
||||
|
||||
this.applicationService.section$.pipe(distinctUntilChanged(), takeUntil(this.destroy$)).subscribe((section) => {
|
||||
this.module = section === 'branch' ? ModuleSwitcher.Branch : ModuleSwitcher.Customer;
|
||||
this.doubleChoiceSwitch.isFirstSwitchedOn = section === 'customer';
|
||||
this.cdr.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
logoff() {
|
||||
this.logOutDialog.openDialog();
|
||||
}
|
||||
|
||||
async siteChange(model: DoubleChoiceSwitch) {
|
||||
const section = model.isFirstSwitchedOn ? 'customer' : 'branch';
|
||||
|
||||
const crumb = await this.breadcrumb.getLatestBreadcrumbForSection(section).pipe(first()).toPromise();
|
||||
if (crumb) {
|
||||
return this.router.navigate([crumb.path], { queryParams: crumb.params });
|
||||
}
|
||||
|
||||
this.router.navigate([section === 'customer' ? '/dashboard' : '/task-calendar']);
|
||||
}
|
||||
|
||||
goToDashboard() {
|
||||
this.store.dispatch(new ChangeCurrentRoute('/dashboard'));
|
||||
this.router.navigate(['/dashboard']);
|
||||
}
|
||||
|
||||
notificationAction() {
|
||||
// navigations needed for development purpouse
|
||||
// this.router.navigate(['/remission/finish']);
|
||||
}
|
||||
|
||||
async openNotifications() {
|
||||
const notifications = await this.notifications$.pipe(first()).toPromise();
|
||||
this._modal.open({
|
||||
content: ModalNotificationsComponent,
|
||||
data: notifications,
|
||||
config: {
|
||||
showScrollbarY: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { SsoService } from 'sso';
|
||||
|
||||
@Component({
|
||||
selector: 'app-log-in',
|
||||
templateUrl: './log-in.component.html',
|
||||
styleUrls: ['./log-in.component.scss'],
|
||||
})
|
||||
export class LogInComponent implements OnInit {
|
||||
constructor(private route: ActivatedRoute, private ssoService: SsoService) {}
|
||||
|
||||
ngOnInit() {
|
||||
const token = this.route.snapshot.paramMap.get('token');
|
||||
this.logIn(token);
|
||||
}
|
||||
|
||||
private logIn(token: string) {
|
||||
this.ssoService.keyCardLogin(token);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<app-modal id="logout-modal">
|
||||
<div class="logout-modal">
|
||||
<div class="header">
|
||||
<h1>Möchten Sie sich wirklich ausloggen?</h1>
|
||||
<lib-icon (click)="closeModal()" height="21px" class="close-icon" name="close" alt="close"></lib-icon>
|
||||
</div>
|
||||
<div class="body"></div>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<app-button (action)="closeModal()">Abbrechen</app-button>
|
||||
</div>
|
||||
<div class="align-right">
|
||||
<app-button [primary]="true" (action)="logoff()">Ausloggen</app-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</app-modal>
|
||||
@@ -1,36 +0,0 @@
|
||||
.logout-modal {
|
||||
font-family: 'Open Sans';
|
||||
line-height: 21px;
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
min-height: 185px;
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
.close-icon {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 25px;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
.close-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { LogOutComponent } from './log-out.component';
|
||||
|
||||
describe('LogOutComponent', () => {
|
||||
let component: LogOutComponent;
|
||||
let fixture: ComponentFixture<LogOutComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [LogOutComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LogOutComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { SsoService } from 'sso';
|
||||
import { ModalService } from '@libs/ui';
|
||||
import { NativeContainerService } from 'shared/lib/barcode-scanner';
|
||||
|
||||
@Component({
|
||||
selector: 'app-log-out',
|
||||
templateUrl: './log-out.component.html',
|
||||
styleUrls: ['./log-out.component.scss'],
|
||||
})
|
||||
export class LogOutComponent implements OnInit {
|
||||
id = 'logout-modal';
|
||||
constructor(private ssoService: SsoService, private modalService: ModalService, private nativeContainer: NativeContainerService) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
logoff() {
|
||||
this.ssoService.logoff();
|
||||
}
|
||||
|
||||
openDialog() {
|
||||
this.modalService.open(this.id);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
this.modalService.close(this.id);
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
<!-- Customer module menus -->
|
||||
<div class="menu" *ngIf="module === 0">
|
||||
<div class="menu-grid">
|
||||
<div class="menu-item-grid align-center active" (click)="routeToMenu('/product/search', 'productsearch')">
|
||||
<div>
|
||||
<lib-icon
|
||||
class="menu-icon"
|
||||
name="{{
|
||||
router.url === '/product/search' || router.url.startsWith('/product/results') || router.url.startsWith('/product/details')
|
||||
? 'Icon_Artikelsuche'
|
||||
: 'Icon_Artikelsuche_inactive'
|
||||
}}"
|
||||
width="34px"
|
||||
height="24px"
|
||||
></lib-icon>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="
|
||||
router.url === '/product/search' || router.url.startsWith('/product/results') || router.url.startsWith('/product/details');
|
||||
else articleSearchLabelElse
|
||||
"
|
||||
class="menu-item selected"
|
||||
>Artikelsuche</span
|
||||
>
|
||||
<ng-template #articleSearchLabelElse>
|
||||
<span class="menu-item">Artikelsuche</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div
|
||||
class="menu-item-grid align-center active"
|
||||
(click)="routeToMenu('/customer/search', 'customersearch', { customertype: 'store;loyalty;webshop' })"
|
||||
>
|
||||
<div>
|
||||
<lib-icon
|
||||
class="menu-icon"
|
||||
name="{{
|
||||
router.url === '/customer/search' ||
|
||||
router.url === '/customer/results' ||
|
||||
router.url.startsWith('/customer/edit') ||
|
||||
router.url.startsWith('/customer')
|
||||
? 'Icon_Kundensuche'
|
||||
: 'Icon_Kundensuche_inactive'
|
||||
}}"
|
||||
width="34px"
|
||||
height="24px"
|
||||
></lib-icon>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="
|
||||
router.url === '/customer/search' ||
|
||||
router.url === '/customer/results' ||
|
||||
router.url.startsWith('/customer/edit') ||
|
||||
router.url.startsWith('/customer');
|
||||
else customerSearchLabelElse
|
||||
"
|
||||
class="menu-item selected"
|
||||
>Kundensuche</span
|
||||
>
|
||||
<ng-template #customerSearchLabelElse>
|
||||
<span class="menu-item">Kundensuche</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="menu-item-grid align-center active" (click)="routeToMenu('/goods/out', 'shelfsearch')">
|
||||
<!-- <div class="menu-item-grid align-center"> -->
|
||||
<div>
|
||||
<lib-icon
|
||||
class="menu-icon"
|
||||
name="{{ router.url === '/goods/out' || router.url.startsWith('/goods/out') ? 'Icon_Abholfach' : 'Icon_Abholfach_inactive' }}"
|
||||
width="34px"
|
||||
height="24px"
|
||||
></lib-icon>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="router.url === '/shelf/search' || router.url.startsWith('/goods/out'); else shelfSearchLabelElse"
|
||||
class="menu-item selected"
|
||||
>Warenausgabe</span
|
||||
>
|
||||
<ng-template #shelfSearchLabelElse>
|
||||
<span class="menu-item">Warenausgabe</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Branch module menus -->
|
||||
<div class="branch-menu" *ngIf="module === 1">
|
||||
<div class="menu-grid">
|
||||
<!-- <div class="menu-item-grid align-center disabled"></div> -->
|
||||
<div class="menu-item-grid align-center active" (click)="routeToMenu('/task-calendar/calendar', 'calendar')">
|
||||
<div>
|
||||
<lib-icon
|
||||
class="menu-icon"
|
||||
name="{{
|
||||
router.url === '/task-calendar/calendar' || router.url === '/task-calendar/tasks'
|
||||
? 'Icon_Tatigkeitskalender'
|
||||
: 'Icon_Tatigkeitskalender_inactive'
|
||||
}}"
|
||||
width="34px"
|
||||
height="24px"
|
||||
></lib-icon>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="router.url === '/task-calendar/calendar' || router.url === '/task-calendar/tasks'; else taskCalendarLabelElse"
|
||||
class="branch-menu-item branch-selected"
|
||||
>Tätigkeitskalender</span
|
||||
>
|
||||
<ng-template #taskCalendarLabelElse>
|
||||
<span class="branch-menu-item">Tätigkeitskalender</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="menu-item-grid align-center active" (click)="routeToMenu('/goods/in', 'goods-in')">
|
||||
<div>
|
||||
<lib-icon
|
||||
class="menu-icon"
|
||||
name="{{ router.url.startsWith('/goods/in') ? 'Icon_Abholfach_B' : 'Icon_Abholfach_B_inactive' }}"
|
||||
width="34px"
|
||||
height="24px"
|
||||
></lib-icon>
|
||||
</div>
|
||||
<span *ngIf="router.url.startsWith('/goods/in'); else abholfachLabelElse" class="branch-menu-item branch-selected">Abholfach</span>
|
||||
<ng-template #abholfachLabelElse>
|
||||
<span class="branch-menu-item">Abholfach</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="menu-item-grid align-center active" (click)="routeToMenu('/remission/create', 'remission')">
|
||||
<div>
|
||||
<lib-icon
|
||||
class="menu-icon"
|
||||
name="{{
|
||||
router.url === '/remission/create' || router.url === '/remission/started' ? 'Icon_Remission' : 'Icon_Remission_inactive'
|
||||
}}"
|
||||
width="34px"
|
||||
height="24px"
|
||||
></lib-icon>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="router.url === '/remission/create' || router.url === '/remission/started'; else remissionLabelElse"
|
||||
class="branch-menu-item branch-selected"
|
||||
>Remission</span
|
||||
>
|
||||
<ng-template #remissionLabelElse>
|
||||
<span class="branch-menu-item">Remission</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,121 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
.menu {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background-color: white;
|
||||
z-index: 100;
|
||||
box-shadow: 0px -2px 6px 0px #dde5ec;
|
||||
}
|
||||
|
||||
.branch-menu {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background-color: white;
|
||||
z-index: 100;
|
||||
box-shadow: 0px -2px 6px 0px #e9ebee;
|
||||
}
|
||||
|
||||
.menu-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 33% 33% 33%;
|
||||
padding-top: 20px;
|
||||
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.menu-item-grid {
|
||||
display: grid;
|
||||
grid-template-columns: auto;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
font-size: 15px;
|
||||
line-height: 21px;
|
||||
font-weight: 600;
|
||||
color: $color-inactive;
|
||||
}
|
||||
|
||||
.selected {
|
||||
color: $color-active;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.branch-menu-item {
|
||||
font-size: 15px;
|
||||
line-height: 21px;
|
||||
font-weight: 600;
|
||||
color: $branch-color-inactive;
|
||||
|
||||
&.branch-disabled {
|
||||
color: #edeff0;
|
||||
}
|
||||
}
|
||||
|
||||
.branch-selected {
|
||||
color: $branch-color-active;
|
||||
}
|
||||
|
||||
.missing-menu {
|
||||
font-family: 'Open Sans';
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #89949e;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.active {
|
||||
cursor: pointer;
|
||||
}
|
||||
/*
|
||||
##Device = Big Desktops
|
||||
*/
|
||||
@media (min-width: 1281px) {
|
||||
.menu-grid {
|
||||
width: 980px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Laptops, Desktops, Ipad pro
|
||||
*/
|
||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
||||
.menu-grid {
|
||||
width: 980px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Tablets, Ipads
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.menu-grid {
|
||||
width: 768px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Low Resolution Tablets, Mobiles (Landscape)
|
||||
*/
|
||||
@media (min-width: 481px) and (max-width: 767px) {
|
||||
.menu-grid {
|
||||
width: 94%;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Most of the Smartphones Mobiles (Portrait)
|
||||
*/
|
||||
@media (min-width: 320px) and (max-width: 480px) {
|
||||
.menu-grid {
|
||||
width: 94%;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { MenuComponent } from './menu.component';
|
||||
|
||||
describe('MenuComponent', () => {
|
||||
let component: MenuComponent;
|
||||
let fixture: ComponentFixture<MenuComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MenuComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MenuComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,168 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { Process } from '../../core/models/process.model';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import {
|
||||
AddProcess,
|
||||
ChangeCurrentRoute,
|
||||
ResetProcessProductFilters,
|
||||
SetOnlineCustomerCreationStatus,
|
||||
} from '../../core/store/actions/process.actions';
|
||||
import { Breadcrumb } from '../../core/models/breadcrumb.model';
|
||||
import { ResetBreadcrumbsTo } from '../../core/store/actions/breadcrumb.actions';
|
||||
import { takeUntil, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { ProcessSelectors } from '../../core/store/selectors/process.selectors';
|
||||
import { ResetFilters } from '../../core/store/actions/filter.actions';
|
||||
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';
|
||||
import { ModuleSwitcherService } from '../../core/services/module-switcher.service';
|
||||
import { SetBranchProcessCurrentPath } from '../../core/store/actions/branch-process.actions';
|
||||
import { InitRemissionState, SetRemissionFinishedProcessStatus, ResetRemissionState } from '../../core/store/actions/remission.actions';
|
||||
import { RemissionSelectors } from '../../core/store/selectors/remission.selectors';
|
||||
import { RemissionFinishingProcessStatus } from '../../modules/remission/models/remission-finishing-process-status.enum';
|
||||
import { DeleteFormState } from '../../core/store/actions/forms.actions';
|
||||
import { USER_FORM_STATE_KEY, USER_EXTRAS_FORM_STATE_KEY, USER_ERRORS_FORM_STATE_KEY } from '../../core/utils/app.constants';
|
||||
import { ApplicationService } from '@core/application';
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu',
|
||||
templateUrl: './menu.component.html',
|
||||
styleUrls: ['./menu.component.scss'],
|
||||
})
|
||||
export class MenuComponent implements OnInit, OnDestroy {
|
||||
@Select(ProcessSelectors.getProcesses) processes$: Observable<Process[]>;
|
||||
module: ModuleSwitcher = ModuleSwitcher.Customer;
|
||||
processes: Process[] = [];
|
||||
destroy$ = new Subject();
|
||||
breadCrumbId = 'product';
|
||||
|
||||
constructor(
|
||||
public router: Router,
|
||||
private store: Store,
|
||||
private moduleSwitcherService: ModuleSwitcherService,
|
||||
private applicationService: ApplicationService
|
||||
) {}
|
||||
activeMenu = '';
|
||||
|
||||
routeToMenu(menuPath: string, menuTag: string, queryParams?: { [key: string]: string }): void {
|
||||
if (this.processes && this.processes.length < 1 && this.module === ModuleSwitcher.Customer) {
|
||||
this.createProcess(menuPath);
|
||||
}
|
||||
this.activeMenu = menuTag;
|
||||
this.store.dispatch(
|
||||
new ResetBreadcrumbsTo(
|
||||
<Breadcrumb>{
|
||||
name: this.nameFromPath(menuPath),
|
||||
path: menuPath,
|
||||
},
|
||||
this.breadCrumbId,
|
||||
true
|
||||
)
|
||||
);
|
||||
if (menuTag === 'productsearch') {
|
||||
this.store.dispatch(new ResetFilters());
|
||||
this.store.dispatch(new ResetProcessProductFilters());
|
||||
}
|
||||
if (menuTag === 'remission') {
|
||||
this.store.dispatch(new InitRemissionState());
|
||||
}
|
||||
if (menuTag === 'customersearch') {
|
||||
this.store.dispatch(new DeleteFormState(USER_FORM_STATE_KEY));
|
||||
this.store.dispatch(new DeleteFormState(USER_EXTRAS_FORM_STATE_KEY));
|
||||
this.store.dispatch(new DeleteFormState(USER_ERRORS_FORM_STATE_KEY));
|
||||
this.store.dispatch(new SetOnlineCustomerCreationStatus({ error: false, invalidProperties: null }));
|
||||
}
|
||||
if (this.router.url === '/remission/finish' && menuTag === 'remission') {
|
||||
const processStatus = this.store.selectSnapshot(RemissionSelectors.getRemissionFinishingProcessStatus);
|
||||
if (processStatus === RemissionFinishingProcessStatus.start) {
|
||||
this.store.dispatch(new SetRemissionFinishedProcessStatus(RemissionFinishingProcessStatus.notSet));
|
||||
} else {
|
||||
this.store.dispatch(new SetRemissionFinishedProcessStatus(RemissionFinishingProcessStatus.notSet));
|
||||
this.navigateToNewRemissionList();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.module === ModuleSwitcher.Branch) {
|
||||
this.store.dispatch(new SetBranchProcessCurrentPath(menuPath));
|
||||
} else {
|
||||
this.store.dispatch(new ChangeCurrentRoute(menuPath));
|
||||
}
|
||||
this.router.navigate([menuPath], { queryParams });
|
||||
}
|
||||
|
||||
routeToMenuBranch(menuPath: string, menuTag: string): void {
|
||||
this.activeMenu = menuTag;
|
||||
this.router.navigate([menuPath]);
|
||||
}
|
||||
|
||||
createProcess(menuPath: string) {
|
||||
const newProcess = <Process>{
|
||||
id: 1,
|
||||
name: 'Vorgang 1',
|
||||
currentRoute: menuPath,
|
||||
};
|
||||
this.store.dispatch(new AddProcess(newProcess));
|
||||
}
|
||||
|
||||
routeFromPath(path: string) {
|
||||
if (path) {
|
||||
return path.substring(1, path.length);
|
||||
}
|
||||
}
|
||||
|
||||
nameFromPath(path: string) {
|
||||
switch (path) {
|
||||
case '/product/search':
|
||||
this.breadCrumbId = 'product';
|
||||
return 'Artikelsuche';
|
||||
case '/customer/search':
|
||||
this.breadCrumbId = 'customer';
|
||||
return 'Kundensuche';
|
||||
case '/shelf/search':
|
||||
this.breadCrumbId = 'shelf';
|
||||
return 'Warenausgabe';
|
||||
case '/branch/main':
|
||||
this.breadCrumbId = 'goodsin';
|
||||
return 'Abholfach';
|
||||
case '/remission/create':
|
||||
this.breadCrumbId = 'remission';
|
||||
return 'Remission';
|
||||
case '/task-calendar/calendar':
|
||||
this.breadCrumbId = 'taskCalendar';
|
||||
return 'Tätigkeitskalendar';
|
||||
default:
|
||||
this.breadCrumbId = 'product';
|
||||
return 'Artikelsuche';
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.processes$.pipe(takeUntil(this.destroy$)).subscribe((data: Process[]) => (this.processes = data));
|
||||
|
||||
this.applicationService.section$.pipe(takeUntil(this.destroy$), distinctUntilChanged()).subscribe((section) => {
|
||||
this.module = section === 'branch' ? ModuleSwitcher.Branch : ModuleSwitcher.Customer;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
private navigateToNewRemissionList() {
|
||||
this.store.dispatch(new ResetRemissionState());
|
||||
const path = '/remission/create';
|
||||
this.store.dispatch(
|
||||
new ResetBreadcrumbsTo(
|
||||
<Breadcrumb>{
|
||||
name: 'Remission',
|
||||
path: path,
|
||||
},
|
||||
'remission',
|
||||
true
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new SetBranchProcessCurrentPath(path));
|
||||
this.router.navigate([path]);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<app-modal id="printer-modal">
|
||||
<div class="printer-modal">
|
||||
<div class="header">
|
||||
<h1>Wählen Sie einen Drucker aus</h1>
|
||||
<lib-icon (click)="closeModal()" height="21px" class="close-icon" name="close" alt="close"></lib-icon>
|
||||
</div>
|
||||
<span *ngIf="error && errorMessage" class="error-message isa-font-color-warning">{{ errorMessage }}</span>
|
||||
<ng-container *ngIf="!error">
|
||||
<div class="body">
|
||||
<app-dropdown
|
||||
[load]="true"
|
||||
(valueChanges)="printerSelected($event)"
|
||||
[options]="options"
|
||||
[selected]="selected"
|
||||
[loading]="!loaded"
|
||||
[showFull]="true"
|
||||
></app-dropdown>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div>
|
||||
<app-button [primary]="true" [load]="true" [disabled]="!loaded" (action)="emitPrint()" #printBtn>Drucken </app-button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</app-modal>
|
||||
@@ -1,48 +0,0 @@
|
||||
.printer-modal {
|
||||
font-family: 'Open Sans';
|
||||
line-height: 21px;
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
min-height: 185px;
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
.close-icon {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 25px;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
.close-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 35px;
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
padding: 1rem 2rem;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
padding-top: 30px;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { PrinterSelectionComponent } from './printer-selection.component';
|
||||
|
||||
describe('PrinterSelectionComponent', () => {
|
||||
let component: PrinterSelectionComponent;
|
||||
let fixture: ComponentFixture<PrinterSelectionComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [PrinterSelectionComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PrinterSelectionComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,115 +0,0 @@
|
||||
import { Component, OnInit, Output, EventEmitter, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
|
||||
import { PrinterService } from '../../core/services/printer.service';
|
||||
import { ModalService, ButtonComponent } from '@libs/ui';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil, map, tap, delay } from 'rxjs/operators';
|
||||
import { Printer } from '../../core/models/printer.model';
|
||||
import { PRINT_ERROR_MSG } from './printer-selection.constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-printer-selection',
|
||||
templateUrl: './printer-selection.component.html',
|
||||
styleUrls: ['./printer-selection.component.scss'],
|
||||
})
|
||||
export class PrinterSelectionComponent implements OnInit, OnDestroy {
|
||||
id = 'printer-modal';
|
||||
options: string[] | number[];
|
||||
selected: string | number;
|
||||
selectedPrinterValue: string;
|
||||
printers: { key: string; text: string; selected: boolean }[] = [];
|
||||
destroy$ = new Subject();
|
||||
error = false;
|
||||
errorMessage = PRINT_ERROR_MSG;
|
||||
loaded = false;
|
||||
printingRequested = false;
|
||||
submited = false;
|
||||
@Output() print: EventEmitter<string> = new EventEmitter();
|
||||
@Output() closed = new EventEmitter();
|
||||
@ViewChild('printBtn') printBtn: ButtonComponent;
|
||||
|
||||
constructor(private printerService: PrinterService, private modalService: ModalService, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
printerSelected(value: string | number) {
|
||||
this.selected = value;
|
||||
this.selectedPrinterValue = this.printers.find((t) => t.text === this.selected).key;
|
||||
}
|
||||
|
||||
emitPrint() {
|
||||
if (this.loaded) {
|
||||
this.print.emit(this.selectedPrinterValue);
|
||||
this.printBtn.startLoading();
|
||||
} else {
|
||||
this.printingRequested = true;
|
||||
this.printBtn.startLoading();
|
||||
}
|
||||
}
|
||||
|
||||
loadPrinters() {
|
||||
this.loaded = false;
|
||||
this.error = false;
|
||||
this.printerService
|
||||
.getAvailablePrinters()
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((response) => {
|
||||
if ((response as { error: string }).error) {
|
||||
const errorResponse = response as { error: string };
|
||||
this.error = true;
|
||||
this.errorMessage = errorResponse.error;
|
||||
return;
|
||||
}
|
||||
const result = response as Printer[];
|
||||
this.printers = result.map((t) => {
|
||||
return { key: t.key, text: t.description, selected: t.selected };
|
||||
});
|
||||
const selectedPrinter = this.printers.find((printer) => printer.selected);
|
||||
this.options = this.printers.map((t) => t.text);
|
||||
this.selectedPrinterValue = selectedPrinter ? selectedPrinter.key : this.printers[0].key;
|
||||
this.selected = selectedPrinter ? selectedPrinter.text : this.options[0];
|
||||
this.error = false;
|
||||
this.loaded = true;
|
||||
if (this.printBtn) {
|
||||
this.printBtn.stopLoading();
|
||||
}
|
||||
if (!this.selected) {
|
||||
this.error = true;
|
||||
this.errorMessage = 'No available printers';
|
||||
}
|
||||
this.cdr.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
openDialog() {
|
||||
this.loadPrinters();
|
||||
this.modalService.open(this.id);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
this.modalService.close(this.id);
|
||||
if (this.printBtn) {
|
||||
this.printBtn.stopLoading();
|
||||
}
|
||||
this.closed.emit();
|
||||
}
|
||||
|
||||
setError(errorMessage?: string) {
|
||||
this.error = true;
|
||||
if (!!errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.printBtn) {
|
||||
this.printBtn.stopLoading();
|
||||
}
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
contentLoaded() {
|
||||
if (this.printingRequested) {
|
||||
this.print.emit(this.selectedPrinterValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export const PRINT_ERROR_MSG = 'Der Druckauftrag konnte nicht ausgeführt werden.';
|
||||
@@ -1,11 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { PrinterSelectionComponent } from './printer-selection.component';
|
||||
import { IconModule, DropdownModule, ModalModule, ButtonModule } from '@libs/ui';
|
||||
|
||||
@NgModule({
|
||||
declarations: [PrinterSelectionComponent],
|
||||
imports: [CommonModule, IconModule, DropdownModule, ModalModule, ButtonModule],
|
||||
exports: [PrinterSelectionComponent],
|
||||
})
|
||||
export class PrinterSelectionModule {}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { trigger, transition, animate, style } from '@angular/animations';
|
||||
|
||||
export const addAnimation = trigger('add', [
|
||||
transition('void => true', [
|
||||
style({ opacity: 0, transform: 'translateX(200%)' }),
|
||||
animate('0.3s ease-out', style({ opacity: 1, transform: 'translateX(0%)' })),
|
||||
]),
|
||||
]);
|
||||
@@ -1,46 +0,0 @@
|
||||
<div class="grid-container">
|
||||
<div class="align-left">
|
||||
<div class="back-arrow-container" *ngIf="showBackContainer && !isIPad" (mouseover)="showBackIcon()" (mouseleave)="hideBackIcon()">
|
||||
<lib-icon class="icon" width="118px" height="50px" name="tab_Arrow" type="png" (click)="scrollBack()" *ngIf="showBack"></lib-icon>
|
||||
</div>
|
||||
<div class="process-grid-container" [ngClass]="{ adding: showAddingPadding }" *ngIf="module === 0" #panel>
|
||||
<app-process-tab
|
||||
[id]="process.id"
|
||||
style="display: inline-block; height: 100%;"
|
||||
*ngFor="let process of processes; let last = last"
|
||||
[module]="module"
|
||||
[last]="last"
|
||||
[process]="process"
|
||||
[@add]="process.new"
|
||||
></app-process-tab>
|
||||
</div>
|
||||
<div class="process-grid-container" *ngIf="module === 1" #panel>
|
||||
<app-process-tab
|
||||
id="{{ branchProcess.id }}"
|
||||
style="display: inline-block; height: 100%;"
|
||||
[module]="module"
|
||||
[process]="branchProcess"
|
||||
></app-process-tab>
|
||||
</div>
|
||||
<div
|
||||
class="foward-arrow-container"
|
||||
*ngIf="showFowardContainer && !isIPad"
|
||||
(mouseover)="showFowardIcon()"
|
||||
(mouseleave)="hideFowardIcon()"
|
||||
>
|
||||
<lib-icon class="icon" width="118px" height="50px" name="tab_Arrow" type="png" (click)="scrollFoward()" *ngIf="showNext"></lib-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="align-right">
|
||||
<div class="grid-container-fix-width-last-col">
|
||||
<div class="align-right add-process-label">
|
||||
<span *ngIf="processes && processes.length === 0 && module === 0" class="process-span" (click)="addProcess()">{{
|
||||
startProcessLabel
|
||||
}}</span>
|
||||
</div>
|
||||
<app-button *ngIf="module === 0" (action)="addProcess()" class="add-process" [type]="'small'">
|
||||
<lib-icon width="34px" height="36px" name="add-red"></lib-icon>
|
||||
</app-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,113 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
.grid-container {
|
||||
@apply grid grid-flow-col;
|
||||
grid-template-columns: 1fr auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
@apply grid grid-flow-col;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
|
||||
.grid-container-fix-width-last-col {
|
||||
display: grid;
|
||||
grid-template-columns: auto;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
.process-span {
|
||||
color: $hima-color-red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.process-grid-container {
|
||||
white-space: nowrap;
|
||||
padding-top: 13px;
|
||||
padding-right: 25px;
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.adding {
|
||||
padding-right: 200px;
|
||||
}
|
||||
|
||||
.add-process-label {
|
||||
position: absolute;
|
||||
top: 99px;
|
||||
right: 63px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.back-arrow-container {
|
||||
width: 118px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
top: 83px;
|
||||
cursor: pointer;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.foward-arrow-container {
|
||||
width: 118px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
top: 87px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.placeholder-tab {
|
||||
width: 300px;
|
||||
height: 42px;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Big Desktops
|
||||
*/
|
||||
@media (min-width: 1281px) {
|
||||
.grid-container {
|
||||
grid-template-columns: 93% auto;
|
||||
}
|
||||
|
||||
.foward-arrow-container {
|
||||
right: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Laptops, Desktops, Ipad pro
|
||||
*/
|
||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
||||
.grid-container {
|
||||
grid-template-columns: 93% auto;
|
||||
}
|
||||
|
||||
.foward-arrow-container {
|
||||
right: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Tablets, Ipads
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.grid-container {
|
||||
grid-template-columns: 685px auto;
|
||||
}
|
||||
|
||||
.foward-arrow-container {
|
||||
right: 68px;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ProcessHeaderComponent } from './process-header.component';
|
||||
|
||||
describe('ProcessHeaderComponent', () => {
|
||||
let component: ProcessHeaderComponent;
|
||||
let fixture: ComponentFixture<ProcessHeaderComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ProcessHeaderComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProcessHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,248 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy, ElementRef, ViewChild, ChangeDetectorRef, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||
import { Process } from '../../core/models/process.model';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { Breadcrumb } from '../../core/models/breadcrumb.model';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import { AddProcess } from '../../core/store/actions/process.actions';
|
||||
import { addAnimation } from './add.animation';
|
||||
import { Router } from '@angular/router';
|
||||
import { AddBreadcrumb } from '../../core/store/actions/breadcrumb.actions';
|
||||
import { takeUntil, switchMap, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { ProcessSelectors } from '../../core/store/selectors/process.selectors';
|
||||
import { WindowRef } from '../../core/services/window-ref.service';
|
||||
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';
|
||||
import { ApplicationService } from '@core/application';
|
||||
|
||||
@Component({
|
||||
selector: 'app-process-header',
|
||||
templateUrl: './process-header.component.html',
|
||||
styleUrls: ['./process-header.component.scss'],
|
||||
animations: [addAnimation],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ProcessHeaderComponent implements OnInit, OnDestroy {
|
||||
startProcessLabel = 'VORGANG STARTEN';
|
||||
@ViewChild('panel', { read: ElementRef }) public panel: ElementRef<any>;
|
||||
@Select(ProcessSelectors.getProcesses) process$: Observable<Process[]>;
|
||||
@Select(ProcessSelectors.getCurrentProcess) selectedProcess$: Observable<Process>;
|
||||
module: ModuleSwitcher;
|
||||
branchProcess = <Process>{
|
||||
id: 1,
|
||||
name: 'Wareneingang',
|
||||
};
|
||||
processes: Process[] = [];
|
||||
destroy$ = new Subject();
|
||||
showNext = false;
|
||||
showBack = false;
|
||||
showFowardContainer = false;
|
||||
showBackContainer = false;
|
||||
offset: number;
|
||||
selectedProcessId: string;
|
||||
selectedProcess: any;
|
||||
isIPad = false;
|
||||
showAddingPadding = false;
|
||||
private iPadDetected = false;
|
||||
private iPadEventRecieved = false;
|
||||
|
||||
constructor(
|
||||
private store: Store,
|
||||
private router: Router,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private windowRef: WindowRef,
|
||||
private applicationService: ApplicationService
|
||||
) {}
|
||||
|
||||
addProcess() {
|
||||
const itemNo = !this.processes
|
||||
? 0
|
||||
: this.processes && this.processes.length === 0
|
||||
? 1
|
||||
: this.processes[this.processes.length - 1].id + 1;
|
||||
const newProcess = <Process>{
|
||||
id: itemNo,
|
||||
new: true,
|
||||
name: `Vorgang ${itemNo}`,
|
||||
currentRoute: '/product/search',
|
||||
};
|
||||
if (itemNo >= 4) {
|
||||
this.initializeAnimation(itemNo);
|
||||
}
|
||||
this.store
|
||||
.dispatch(new AddProcess(newProcess))
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: 'Artikelsuche',
|
||||
path: '/product/search',
|
||||
},
|
||||
'product',
|
||||
true
|
||||
)
|
||||
);
|
||||
this.router.navigate(['/product/search']);
|
||||
});
|
||||
this.applicationService.setActivatedProcessId(newProcess.id);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.isIPad = this.isIPadEnv();
|
||||
this.selectedProcess$
|
||||
.pipe(
|
||||
switchMap((proc: Process) => {
|
||||
if (proc) {
|
||||
this.selectedProcessId = proc.id + '';
|
||||
}
|
||||
|
||||
return this.process$;
|
||||
}),
|
||||
takeUntil(this.destroy$),
|
||||
distinctUntilChanged((prev, curr) => this.processComperer(prev, curr))
|
||||
)
|
||||
.subscribe(
|
||||
(data) => {
|
||||
this.processes = data;
|
||||
this.cdr.detectChanges();
|
||||
if (this.panel?.nativeElement?.children.length > 0) {
|
||||
this.scrollableArrows();
|
||||
}
|
||||
},
|
||||
(err) => console.error(err)
|
||||
);
|
||||
|
||||
this.applicationService.section$.pipe(distinctUntilChanged(), takeUntil(this.destroy$)).subscribe((section) => {
|
||||
this.module = section === 'branch' ? ModuleSwitcher.Branch : ModuleSwitcher.Customer;
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
private initializeAnimation(processCount: number) {
|
||||
this.showAddingPadding = true;
|
||||
this.cdr.detectChanges();
|
||||
|
||||
setTimeout(() => {
|
||||
this.panel.nativeElement.scrollTo({ left: this.panel.nativeElement.scrollLeft + 300 * processCount, behavior: 'smooth' });
|
||||
this.cdr.detectChanges();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
processComperer(prev: Process[], curr: Process[]) {
|
||||
try {
|
||||
if (!prev || !curr) {
|
||||
return false;
|
||||
}
|
||||
if (prev.length !== curr.length) {
|
||||
return false;
|
||||
}
|
||||
if (prev.length === 0 || curr.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const prevStr = JSON.stringify(
|
||||
prev.map((t) => {
|
||||
return { new: t.new, name: t.name };
|
||||
})
|
||||
);
|
||||
const currStr = JSON.stringify(
|
||||
curr.map((t) => {
|
||||
return { new: t.new, name: t.name };
|
||||
})
|
||||
);
|
||||
const status = prevStr === currStr;
|
||||
return status;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
isIPadEnv() {
|
||||
const navigator = this.windowRef.nativeWindow.navigator as Navigator;
|
||||
const standalone = (navigator as any).standalone,
|
||||
userAgent = navigator.userAgent.toLowerCase(),
|
||||
ios = /iphone|ipod|ipad/.test(userAgent);
|
||||
|
||||
this.iPadDetected = ios && !standalone;
|
||||
return this.iPadDetected || this.iPadEventRecieved;
|
||||
}
|
||||
|
||||
scrollableArrows() {
|
||||
this.offset = Math.ceil(this.panel.nativeElement.clientWidth / 2);
|
||||
let selected: any;
|
||||
|
||||
for (let _i = 0; _i < this.panel.nativeElement.children.length; _i++) {
|
||||
const proc = this.panel.nativeElement.children[_i];
|
||||
if (proc.id === this.selectedProcessId) {
|
||||
selected = proc;
|
||||
this.selectedProcess = proc;
|
||||
}
|
||||
}
|
||||
|
||||
const lastProcess = this.panel.nativeElement.children[this.panel.nativeElement.children.length - 1];
|
||||
|
||||
if (selected) {
|
||||
const clientWidth = this.panel.nativeElement.clientWidth;
|
||||
|
||||
this.showAddingPadding = false;
|
||||
this.cdr.detectChanges();
|
||||
|
||||
const selecetedPos = selected.offsetLeft + selected.offsetWidth;
|
||||
const lastPos = lastProcess.offsetLeft + lastProcess.offsetWidth;
|
||||
|
||||
this.showFowardContainer =
|
||||
(selecetedPos + this.offset * 2 > clientWidth || selecetedPos + this.offset < lastPos) &&
|
||||
lastPos > clientWidth &&
|
||||
lastPos > this.panel.nativeElement.scrollWidth;
|
||||
|
||||
// This number is from testing > 643
|
||||
this.showBackContainer = selecetedPos > 643;
|
||||
}
|
||||
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
scrollBack() {
|
||||
const moveCalc = this.panel.nativeElement.scrollLeft - this.offset;
|
||||
this.panel.nativeElement.scrollTo({ left: moveCalc, behavior: 'smooth' });
|
||||
this.cdr.detectChanges();
|
||||
|
||||
this.showBackContainer = this.panel.nativeElement.scrollLeft - this.offset > 0;
|
||||
this.showBack = false;
|
||||
|
||||
this.showFowardContainer = this.panel.nativeElement.scrollLeft < this.panel.nativeElement.scrollWidth;
|
||||
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
scrollFoward() {
|
||||
const moveCalc = this.panel.nativeElement.scrollLeft + this.offset;
|
||||
this.panel.nativeElement.scrollTo({ left: moveCalc, behavior: 'smooth' });
|
||||
this.cdr.detectChanges();
|
||||
|
||||
this.showFowardContainer = moveCalc + this.offset * 2 < this.panel.nativeElement.scrollWidth;
|
||||
this.showNext = false;
|
||||
|
||||
// If clicked next, then back button is always there
|
||||
this.showBackContainer = true;
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
showFowardIcon() {
|
||||
this.showNext = true;
|
||||
}
|
||||
|
||||
hideFowardIcon() {
|
||||
this.showNext = false;
|
||||
}
|
||||
|
||||
showBackIcon() {
|
||||
this.showBack = true;
|
||||
}
|
||||
|
||||
hideBackIcon() {
|
||||
this.showBack = false;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<!-- Customer module process -->
|
||||
<div class="grid-item" id="{{ process.id }}" *ngIf="module === 0" [ngClass]="{ last: last }">
|
||||
<div class="grid-container" [ngClass]="{ 'selected-process': process.id === (currentProcessId$ | async) }">
|
||||
<div class="process-name-container pt-3" (click)="selectProcess(process)">
|
||||
<span class="process-name">{{ process.name }}</span>
|
||||
</div>
|
||||
<ng-container *ngIf="{ length: cartCount$ | async }; let cartCount">
|
||||
<div
|
||||
[class.items-in-cart]="cartCount.length > 0"
|
||||
class="cart-container"
|
||||
[ngClass]="{ download: cartBackgroundForDownload }"
|
||||
(click)="openCart(process)"
|
||||
>
|
||||
<lib-icon
|
||||
mt="12px"
|
||||
ml="15px"
|
||||
width="17px"
|
||||
height="16px"
|
||||
name="Shopping_Cart"
|
||||
*ngIf="cartCount.length === 0 && !cartBackgroundForDownload && process.id === (currentProcessId$ | async)"
|
||||
class="process-cart-icon"
|
||||
></lib-icon>
|
||||
<lib-icon
|
||||
mt="12px"
|
||||
ml="15px"
|
||||
width="17px"
|
||||
height="16px"
|
||||
name="Shopping_Cart_Inactive"
|
||||
*ngIf="cartCount.length === 0 && !cartBackgroundForDownload && process.id !== (currentProcessId$ | async)"
|
||||
class="process-cart-icon"
|
||||
></lib-icon>
|
||||
<lib-icon
|
||||
mt="12px"
|
||||
ml="15px"
|
||||
width="17px"
|
||||
height="16px"
|
||||
name="shopping_cart_white"
|
||||
*ngIf="cartCount.length > 0 || cartBackgroundForDownload"
|
||||
class="process-cart-icon"
|
||||
></lib-icon>
|
||||
<div [@cartnumber]="cartanimation" class="pt-3 process-cart-number-container">
|
||||
<span
|
||||
[class.items-in-cart]="cartCount.length > 0"
|
||||
class="process-cart-number"
|
||||
[ngClass]="{ 'number-download': cartBackgroundForDownload }"
|
||||
>{{ cartCount.length }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div *ngIf="process.id === (currentProcessId$ | async)">
|
||||
<a (click)="openDeleteConfirmationDialog()">
|
||||
<lib-icon class="process-delete-icon" name="close" width="15px" height="15px" mt="12px"></lib-icon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<app-process-delete-dialog #deleteporcessdialog (deleted)="deleteProcess($event)" [process]="process"></app-process-delete-dialog>
|
||||
</div>
|
||||
@@ -1,133 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
.grid-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 42px;
|
||||
border-bottom: 3px solid #fff;
|
||||
|
||||
& > .cart-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 38px;
|
||||
background-color: #e6eff9;
|
||||
border-radius: 25px;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
padding-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.download {
|
||||
background-color: $hima-download-cart-color !important;
|
||||
}
|
||||
|
||||
.process-name-container {
|
||||
cursor: pointer;
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.process-name-container-branch {
|
||||
cursor: pointer;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.process-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #557596;
|
||||
// opacity: 0.3;
|
||||
margin-top: 5px;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.process-name-branch {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #596470;
|
||||
opacity: 0.3;
|
||||
margin-top: 5px;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.process-cart-number {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #557596;
|
||||
// opacity: 0.3;
|
||||
|
||||
position: relative;
|
||||
top: 4px;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.number-download {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
// .process-cart-icon {
|
||||
// opacity: 0.3;
|
||||
// }
|
||||
|
||||
.selected-process {
|
||||
border-bottom: 3px solid $hima-color-red;
|
||||
|
||||
.process-name {
|
||||
color: $color-active;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.process-name-branch {
|
||||
color: #596470;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.process-cart-number {
|
||||
color: $color-active;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.process-cart-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.process-delete-icon {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.process-cart-icon-numbered {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.process-cart-number-container {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
display: inline-block;
|
||||
padding-right: 30px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.last {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.items-in-cart {
|
||||
@apply bg-active-customer !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ProcessTabComponent } from './process-tab.component';
|
||||
|
||||
describe('ProcessTabComponent', () => {
|
||||
let component: ProcessTabComponent;
|
||||
let fixture: ComponentFixture<ProcessTabComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ProcessTabComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProcessTabComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,182 +0,0 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
ViewChild,
|
||||
OnDestroy,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
AfterViewInit,
|
||||
ViewRef,
|
||||
} from '@angular/core';
|
||||
import { Process } from '../../core/models/process.model';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import {
|
||||
DeleteProcess,
|
||||
PreventProductLoad,
|
||||
ChangeCurrentRoute,
|
||||
SetProcessNewStatusToFalse,
|
||||
} from '../../core/store/actions/process.actions';
|
||||
import { Breadcrumb } from '../../core/models/breadcrumb.model';
|
||||
import { ProcessDeleteDialogComponent } from '../../modules/process/components/process-delete-dialog/process-delete-dialog.component';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { Notify } from '../../core/store/actions/notifier.actions';
|
||||
import { AddBreadcrumb } from '../../core/store/actions/breadcrumb.actions';
|
||||
import { map, switchMap, take, withLatestFrom, first } from 'rxjs/operators';
|
||||
import { trigger, transition, animate, style, keyframes } from '@angular/animations';
|
||||
import { AppState } from '../../core/store/state/app.state';
|
||||
import { AppSetCurrentProcess } from '../../core/store/actions/app.actions';
|
||||
import { ProcessSelectors } from '../../core/store/selectors/process.selectors';
|
||||
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';
|
||||
|
||||
import { USER_FORM_STATE_KEY, USER_EXTRAS_FORM_STATE_KEY, USER_ERRORS_FORM_STATE_KEY } from '../../core/utils/app.constants';
|
||||
import { DeleteFormState } from '../../core/store/actions/forms.actions';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-process-tab',
|
||||
templateUrl: './process-tab.component.html',
|
||||
styleUrls: ['./process-tab.component.scss'],
|
||||
animations: [
|
||||
trigger('cartnumber', [
|
||||
transition('* => delete', [
|
||||
animate(
|
||||
1000,
|
||||
keyframes([
|
||||
style({ transform: 'translateY(-60%)', opacity: 0, offset: 0 }),
|
||||
style({ transform: 'translateY(10%)', opacity: 1, offset: 0.4 }),
|
||||
style({ transform: 'translateY(0%)', opacity: 1, offset: 0.6 }),
|
||||
style({ transform: 'translateY(5%)', opacity: 1, offset: 0.8 }),
|
||||
style({ transform: 'translateY(0%)', opacity: 1, offset: 0.99 }),
|
||||
])
|
||||
),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ProcessTabComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
@Input() process: Process;
|
||||
@Input() processes: Array<Process>;
|
||||
@Input() module: ModuleSwitcher;
|
||||
@Input() last = false;
|
||||
@Select(ProcessSelectors.getProcesses) procecesses$: Observable<Process[]>;
|
||||
@Select(AppState.getCurrentProcessId) currentProcessId$: Observable<number>;
|
||||
destroy$ = new Subject();
|
||||
@ViewChild('deleteporcessdialog')
|
||||
processDeleteDialogComponent: ProcessDeleteDialogComponent;
|
||||
cartCount$: Observable<number>;
|
||||
cartanimation = '';
|
||||
cartBackgroundForDownload = false;
|
||||
|
||||
constructor(
|
||||
private store: Store,
|
||||
private router: Router,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private applicationService: ApplicationService,
|
||||
private domainCheckoutService: DomainCheckoutService,
|
||||
private breadcrumb: BreadcrumbService
|
||||
) {}
|
||||
isProcessFinished = this.router.url === '/cart/confirmation';
|
||||
|
||||
async deleteProcess(process: Process) {
|
||||
this.store.dispatch(new DeleteProcess(process));
|
||||
this.store.dispatch(new Notify(1));
|
||||
const processes = this.store.selectSnapshot(ProcessSelectors.getProcesses) as Process[];
|
||||
if (processes) {
|
||||
this.processDeleteCleanUp();
|
||||
if (processes.length < 1) {
|
||||
this.router.navigate(['/dashboard']);
|
||||
} else {
|
||||
const newSelectedProcess = processes[processes.length - 1];
|
||||
|
||||
const breadcrumbs = await this.breadcrumb.getBreadcrumbByKey$(newSelectedProcess.id).pipe(first()).toPromise();
|
||||
if (!breadcrumbs) return;
|
||||
|
||||
const breadcrumb = breadcrumbs.sort((a, b) => b.timestamp - a.timestamp)[0];
|
||||
if (!breadcrumb?.path) return;
|
||||
|
||||
this.router.navigate([breadcrumb.path], { queryParams: breadcrumb.params });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
openDeleteConfirmationDialog() {
|
||||
if (this.process.closeDirectlyTab || this.isProcessFinished) {
|
||||
this.deleteProcess(this.process);
|
||||
} else {
|
||||
this.processDeleteDialogComponent.openDialog();
|
||||
}
|
||||
}
|
||||
|
||||
selectProcess(process: Process): void {
|
||||
this.store
|
||||
.dispatch(new AppSetCurrentProcess(process.id))
|
||||
.pipe(
|
||||
take(1),
|
||||
switchMap(() => this.store.dispatch(new PreventProductLoad())),
|
||||
switchMap(() => this.store.dispatch(new Notify(process.id))),
|
||||
withLatestFrom(this.breadcrumb.getBreadcrumbByKey$(process.id))
|
||||
)
|
||||
.subscribe(([_, breadcrumbs]) => {
|
||||
if (!breadcrumbs) return;
|
||||
|
||||
const breadcrumb = breadcrumbs.sort((a, b) => b.timestamp - a.timestamp)[0];
|
||||
if (!breadcrumb?.path) return;
|
||||
|
||||
this.router.navigate([breadcrumb.path], { queryParams: breadcrumb.params });
|
||||
});
|
||||
this.applicationService.setActivatedProcessId(process.id);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.cartCount$ = this.domainCheckoutService.getShoppingCart({ processId: this.process.id }).pipe(
|
||||
map((response) => {
|
||||
if (response?.items?.length === undefined) {
|
||||
return 0;
|
||||
} else {
|
||||
return response?.items?.length;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
setTimeout(() => {
|
||||
this.store.dispatch(new SetProcessNewStatusToFalse());
|
||||
}, 400);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
openCart(process: Process) {
|
||||
this.selectProcess(process);
|
||||
const newBread: Breadcrumb = {
|
||||
name: 'Warenkorb',
|
||||
path: '/cart/review',
|
||||
};
|
||||
|
||||
this.store.dispatch(new AddBreadcrumb(newBread, 'shoppingCart'));
|
||||
this.store.dispatch(new ChangeCurrentRoute('/cart/review'));
|
||||
this.router.navigate(['/cart/review']);
|
||||
}
|
||||
|
||||
private processDeleteCleanUp() {
|
||||
this.store.dispatch(new DeleteFormState(USER_FORM_STATE_KEY));
|
||||
this.store.dispatch(new DeleteFormState(USER_EXTRAS_FORM_STATE_KEY));
|
||||
this.store.dispatch(new DeleteFormState(USER_ERRORS_FORM_STATE_KEY));
|
||||
}
|
||||
|
||||
detectChanges() {
|
||||
setTimeout(() => {
|
||||
if (this.cdr !== null && this.cdr !== undefined && !(this.cdr as ViewRef).destroyed) {
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<app-modal id="error-modal" higerOder="true">
|
||||
<div class="error-modal">
|
||||
<div class="header">
|
||||
<h1>{{ title }}</h1>
|
||||
<lib-icon (click)="closeErrorModal()" height="21px" class="close-icon" name="close" alt="close"></lib-icon>
|
||||
</div>
|
||||
<div class="body">
|
||||
<span class="message" *ngIf="!hasInvalidAttributes" [innerHTML]="message"></span>
|
||||
<ng-container *ngIf="hasInvalidAttributes">
|
||||
<span *ngFor="let propertie of invalidAttributes">
|
||||
{{ propertie.key + ' => ' + propertie.value }}
|
||||
</span>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<ng-container *ngIf="!logout">
|
||||
<app-button *ngIf="!safeMode" (action)="resetState()">App neu starten</app-button>
|
||||
<app-button [primary]="true" (action)="closeErrorModal()">Erneut versuchen</app-button></ng-container
|
||||
>
|
||||
<ng-container *ngIf="logout"> <app-button [primary]="true" (action)="closeErrorModal()">Erneut anmelden</app-button></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</app-modal>
|
||||
@@ -1,52 +0,0 @@
|
||||
.error-modal {
|
||||
font-family: 'Open Sans';
|
||||
line-height: 21px;
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
min-height: 185px;
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 15px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header {
|
||||
.close-icon {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 25px;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
.close-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 36px;
|
||||
margin-bottom: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 0px 40px 0px 60px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ErrorComponent } from './error.component';
|
||||
|
||||
describe('ErrorComponent', () => {
|
||||
let component: ErrorComponent;
|
||||
let fixture: ComponentFixture<ErrorComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ErrorComponent],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ErrorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
});
|
||||
@@ -1,92 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { ModalService } from '@libs/ui';
|
||||
import { UserStateService } from '../../services/user-state.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { SsoService } from 'sso';
|
||||
import { ErrorService } from './error.service';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-error',
|
||||
templateUrl: './error.component.html',
|
||||
styleUrls: ['./error.component.scss'],
|
||||
})
|
||||
export class ErrorComponent implements OnInit, OnDestroy {
|
||||
id = 'error-modal';
|
||||
errorOpened = false;
|
||||
message: string;
|
||||
destroy$ = new Subject();
|
||||
logout = false;
|
||||
safeMode = false;
|
||||
invalidAttributes: { key: string; value: string }[];
|
||||
hasInvalidAttributes = false;
|
||||
safeCodes = [400, 409];
|
||||
validMessageCodes = [0, 400, 404, 409, 500, 504];
|
||||
title = 'Irgendwas hat nicht funktioniert…';
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private stateService: UserStateService,
|
||||
private router: Router,
|
||||
private ssoService: SsoService,
|
||||
private errorService: ErrorService
|
||||
) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
openErrorModal({ code, message, invalidProperties, logout }) {
|
||||
if (!this.errorOpened) {
|
||||
this.safeMode = this.safeCodes.includes(code);
|
||||
this.hasInvalidAttributes = !isNullOrUndefined(invalidProperties);
|
||||
if (this.hasInvalidAttributes) {
|
||||
this.formatInvalidProperties(invalidProperties);
|
||||
}
|
||||
this.title = logout ? 'Willkommen zurück!' : 'Irgendwas hat nicht funktioniert…';
|
||||
this.message = logout ? 'Sie waren zu lange nicht in der ISA aktiv.<br>Bitte melden Sie sich erneut an.' : '';
|
||||
if (this.validMessageCodes.includes(code) && !isNullOrUndefined(message)) {
|
||||
this.message = message;
|
||||
}
|
||||
this.errorOpened = true;
|
||||
this.modalService.open(this.id);
|
||||
}
|
||||
this.logout = !this.logout ? logout : this.logout;
|
||||
}
|
||||
|
||||
closeErrorModal() {
|
||||
if (this.logout) {
|
||||
this.ssoService.logoff();
|
||||
return;
|
||||
}
|
||||
this.errorOpened = false;
|
||||
this.errorService.addRecovery(true);
|
||||
this.modalService.close(this.id);
|
||||
}
|
||||
|
||||
async resetState() {
|
||||
if (this.logout) {
|
||||
this.ssoService.logoff();
|
||||
return;
|
||||
}
|
||||
this.modalService.close(this.id);
|
||||
this.router.navigate(['/dashboard']);
|
||||
this.stateService.resetState().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
this.errorOpened = false;
|
||||
}
|
||||
|
||||
formatInvalidProperties(invalidProperties: string) {
|
||||
const properties = invalidProperties.replace('{', '').replace('}', '').replace(/"/g, '').split(',');
|
||||
if (properties && properties.length > 0) {
|
||||
this.invalidAttributes = properties.map((propertie) => {
|
||||
const keyValuePropertie = propertie.split(':');
|
||||
return { key: keyValuePropertie[0], value: keyValuePropertie[1] };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.errorOpened = false;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ErrorComponent } from './error.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ModalModule, IconModule, ButtonModule } from '@libs/ui';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, ModalModule, IconModule, ButtonModule],
|
||||
declarations: [ErrorComponent],
|
||||
exports: [ErrorComponent],
|
||||
})
|
||||
export class ErrorModule {}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ErrorService {
|
||||
private errors = new Subject<{ code: number; message: string; invalidProperties: string; logout: boolean }>();
|
||||
private recovery = new Subject<boolean>();
|
||||
|
||||
constructor() {}
|
||||
|
||||
public addErrors = (code: number, errors: string, invalidProperties: string, logout = false): void =>
|
||||
// tslint:disable-next-line: semicolon
|
||||
this.errors.next({ code: code, message: errors, invalidProperties: invalidProperties, logout: logout });
|
||||
|
||||
public getErrors = () => this.errors.asObservable();
|
||||
|
||||
public addRecovery = (positive: boolean): void => this.recovery.next(positive);
|
||||
|
||||
public recovery$ = () => this.recovery.asObservable();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { ErrorHandler, Injectable } from '@angular/core';
|
||||
import { ErrorService } from './component/error.service';
|
||||
import { LoggingService, LogType } from '../services/logging.service';
|
||||
import { isWhiteList } from '../utils/http-interceptor-whitelist.utils';
|
||||
|
||||
@Injectable()
|
||||
export class HimaSalesErrorHandler implements ErrorHandler {
|
||||
constructor(private errorService: ErrorService, private logger: LoggingService) {}
|
||||
|
||||
handleError(error: any): void {
|
||||
if (
|
||||
// tslint:disable-next-line: quotemark
|
||||
error.message === "You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable."
|
||||
) {
|
||||
return;
|
||||
} else if (error && error.url && error.status && isWhiteList(error.url, error.status)) {
|
||||
return;
|
||||
} else {
|
||||
this.errorService.addErrors(error.status ? error.status : 0, error.message, undefined);
|
||||
this.logger.log('HUNGENDUBEL INSTORE MA APP', error, LogType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/* import { BasicAuthorizationInterceptor } from './basic-authorization.interceptor';
|
||||
import { TestBed, getTestBed } from '@angular/core/testing';
|
||||
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
|
||||
xdescribe('BasicAuthorizationInterceptor', () => {
|
||||
let injector: TestBed;
|
||||
let httpMock: HttpTestingController;
|
||||
let httpClient: HttpClient;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientTestingModule],
|
||||
providers: [
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useFactory: () =>
|
||||
new BasicAuthorizationInterceptor({
|
||||
client: 'testclient',
|
||||
password: 'testpassword',
|
||||
endpoints: ['https://test1.com']
|
||||
}),
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
injector = getTestBed();
|
||||
httpMock = injector.get(HttpTestingController);
|
||||
httpClient = injector.get(HttpClient);
|
||||
});
|
||||
|
||||
it('should add a basic authorization header', () => {
|
||||
httpClient.get('https://test1.com/abcdef').subscribe();
|
||||
|
||||
const req = httpMock.expectOne('https://test1.com/abcdef');
|
||||
|
||||
expect(req.request.headers.has('Authorization')).toBeTruthy();
|
||||
expect(req.request.headers.get('Authorization')).toBe('Basic dGVzdGNsaWVudDp0ZXN0cGFzc3dvcmQ=');
|
||||
});
|
||||
|
||||
it('should not add a basic authorization header', () => {
|
||||
httpClient.get('https://test2.com/abcdef').subscribe();
|
||||
|
||||
const req = httpMock.expectOne('https://test2.com/abcdef');
|
||||
|
||||
expect(req.request.headers.has('Authorization')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
*/
|
||||
@@ -1,55 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
|
||||
import { Observable, AsyncSubject, ReplaySubject } from 'rxjs';
|
||||
import { map, filter, shareReplay, first, flatMap, withLatestFrom, tap } from 'rxjs/operators';
|
||||
|
||||
export interface BasicAuthorizationOptions {
|
||||
client: string;
|
||||
password: string;
|
||||
endpoints: string[];
|
||||
}
|
||||
|
||||
export const SKIP_BASIC_AUTHORIZATION_INTERCEPTOR = '';
|
||||
|
||||
@Injectable()
|
||||
export class BasicAuthorizationInterceptor implements HttpInterceptor {
|
||||
private optionsSub = new ReplaySubject<{ token: string; endpointMatchers: RegExp[] }>();
|
||||
|
||||
constructor(options$: Observable<BasicAuthorizationOptions>) {
|
||||
options$
|
||||
.pipe(
|
||||
map((options) => {
|
||||
const token = btoa(`${options.client}:${options.password}`);
|
||||
const endpointMatchers: RegExp[] = [];
|
||||
for (const endpoint of options.endpoints) {
|
||||
endpointMatchers.push(new RegExp(`^${endpoint}`, 'i'));
|
||||
}
|
||||
|
||||
return { token, endpointMatchers };
|
||||
})
|
||||
)
|
||||
.subscribe(this.optionsSub);
|
||||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
// let request = req;
|
||||
|
||||
if (req.headers.has('SKIP_BASIC_AUTHORIZATION_INTERCEPTOR')) {
|
||||
return next.handle(req);
|
||||
}
|
||||
|
||||
return this.optionsSub.pipe(
|
||||
first(),
|
||||
map((options) => {
|
||||
let request = req;
|
||||
if (options.endpointMatchers.find((matcher) => matcher.test(req.url))) {
|
||||
const headers = req.headers.set('Authorization', `Basic ${options.token}`);
|
||||
request = req.clone({ headers });
|
||||
}
|
||||
|
||||
return request;
|
||||
}),
|
||||
flatMap((request) => next.handle(request))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { ErrorService } from '../error/component/error.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { OAuthErrorEvent } from 'angular-oauth2-oidc';
|
||||
import { LoggingService, LogType } from '../services/logging.service';
|
||||
import { isWhiteList } from '../utils/http-interceptor-whitelist.utils';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
|
||||
@Injectable()
|
||||
export class HttpErrorHandlerInterceptor implements HttpInterceptor {
|
||||
constructor(private errorService: ErrorService, private logger: LoggingService, private modal: UiModalService) {}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(req).pipe(catchError((error: HttpErrorResponse, caught: any) => this.handleError(error)));
|
||||
}
|
||||
|
||||
getInvalidProperties(error: any) {
|
||||
if (
|
||||
error &&
|
||||
this.showInvalidProperties(error.url, error.status) &&
|
||||
error.error &&
|
||||
error.error.invalidProperties &&
|
||||
Object.keys(error.error.invalidProperties) &&
|
||||
Object.keys(error.error.invalidProperties).length > 0
|
||||
) {
|
||||
return JSON.stringify(error.error.invalidProperties);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getMessage(error: any) {
|
||||
return error.error && error.error ? error.error.message : undefined;
|
||||
}
|
||||
|
||||
private handleError(error: HttpErrorResponse) {
|
||||
console.log(error.status);
|
||||
if (error.status === 0) {
|
||||
this.modal.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Die Netzwerkverbindung wurde unterbrochen',
|
||||
data: { message: 'Bitte überprüfen Sie Ihre Netzwerkverbindung.' },
|
||||
});
|
||||
return throwError(error);
|
||||
}
|
||||
|
||||
if (!isWhiteList(error.url)) {
|
||||
if (isWhiteList(error.url, error.status)) {
|
||||
return throwError(error);
|
||||
}
|
||||
let errorMessage = '';
|
||||
this.logger.log('HUGENDUBEL INSTORE MA APP Backend', error, LogType.Error);
|
||||
if (error.error instanceof OAuthErrorEvent) {
|
||||
return;
|
||||
} else if (error.error instanceof ErrorEvent) {
|
||||
// client-side error
|
||||
errorMessage = `Client-Side => Error: ${error.error.message}`;
|
||||
this.errorService.addErrors(error.status, errorMessage, undefined);
|
||||
} else {
|
||||
// server-side error
|
||||
errorMessage = `Server-Side => Error Code: ${error.status}\nMessage: ${error.message}`;
|
||||
if (error.status === 503 && error.url.includes('/availability/')) {
|
||||
return throwError(errorMessage);
|
||||
}
|
||||
|
||||
const message = this.getMessage(error);
|
||||
|
||||
const invalidProperties = this.getInvalidProperties(error);
|
||||
|
||||
const logout = error.status === 401;
|
||||
this.errorService.addErrors(error.status, message, invalidProperties, logout);
|
||||
}
|
||||
return throwError(errorMessage);
|
||||
} else {
|
||||
return throwError(error);
|
||||
}
|
||||
}
|
||||
|
||||
private showInvalidProperties(url: string, code: number = -1) {
|
||||
const blackList: { url: string; codes: number[] }[] = [{ url: '/order/checkout', codes: [400] }];
|
||||
|
||||
return !blackList.find((entry) => !!url.includes(entry.url) && !!entry.codes.includes(code));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './basic-authorization.interceptor';
|
||||
export * from './sso-authorization.interceptor';
|
||||
export * from './http-error-handler.interceptor';
|
||||
@@ -1,19 +0,0 @@
|
||||
import { HttpInterceptor, HttpEvent, HttpRequest, HttpHandler } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { SsoService } from 'sso';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class SsoAuthorizationInterceptor implements HttpInterceptor {
|
||||
constructor(private ssoService: SsoService) {}
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
if (req.headers.has('SKIP_SSO_AUTHORIZATION_INTERCEPTOR')) {
|
||||
return next.handle(req);
|
||||
}
|
||||
|
||||
const token = this.ssoService.getToken();
|
||||
const headers = req.headers.set('Authorization', `Bearer ${token}`);
|
||||
const request = req.clone({ headers });
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import { Organisation, User } from '../models/user.model';
|
||||
import { CustomerMapping } from './customer.mapping';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { CustomerDTO } from '@swagger/crm';
|
||||
import { CustomerTypeInternal } from '../models/customer-type.model';
|
||||
|
||||
fdescribe('CustomerMapping', () => {
|
||||
let mapper: CustomerMapping;
|
||||
const mockUser: User = {
|
||||
id: 123,
|
||||
first_name: 'Vorname',
|
||||
last_name: 'Nachname',
|
||||
title: 'Dr',
|
||||
gender: 'Herr',
|
||||
|
||||
email: 'test@test.de',
|
||||
phone_number: '017012345678',
|
||||
mobile_number: '019998765432',
|
||||
|
||||
organisation: {
|
||||
name: 'Mock Org',
|
||||
department: 'Mock Dept.',
|
||||
vatId: '123',
|
||||
},
|
||||
|
||||
delivery_addres: {
|
||||
id: 456,
|
||||
first_name: 'Vorname Addresse',
|
||||
last_name: 'Nachname Addresse',
|
||||
street: 'Test Strasse',
|
||||
streetNo: 12,
|
||||
zip: '80636',
|
||||
city: 'Munich',
|
||||
country: 'Deutschland',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [DatePipe, CustomerMapping],
|
||||
});
|
||||
|
||||
mapper = TestBed.inject(CustomerMapping);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(mapper instanceof CustomerMapping).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('fromOrganisationToOrganisationDTO', () => {
|
||||
const mockOrganisation: Organisation = mockUser.organisation;
|
||||
it('should map the provided organisation (Organisation) to OrganisationDTO', () => {
|
||||
const result = mapper.fromOrganisationToOrganisationDTO(mockOrganisation);
|
||||
|
||||
expect(result.vatId).toEqual(mockOrganisation.vatId);
|
||||
expect(result.department).toEqual(mockOrganisation.department);
|
||||
expect(result.name).toEqual(mockOrganisation.name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromUserToCommunicationDetails', () => {
|
||||
it('should map the provided user (User) to communication details (CommunicationDetailsDTO)', () => {
|
||||
const result = mapper.fromUserToCommunicationDetails(mockUser);
|
||||
|
||||
expect(result.phone).toEqual(mockUser.phone_number);
|
||||
expect(result.mobile).toEqual(mockUser.mobile_number);
|
||||
expect(result.email).toEqual(mockUser.email);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromUserToShippingAddressDTO', () => {
|
||||
it('should map the provided user (User) to shipping address (ShippingAddressDTO)', () => {
|
||||
const result = mapper.fromUserToShippingAddressDTO(mockUser);
|
||||
|
||||
expect(result.title).toEqual(mockUser.delivery_addres.title);
|
||||
expect(result.gender).toEqual(2);
|
||||
expect(result.firstName).toEqual(mockUser.delivery_addres.first_name);
|
||||
expect(result.lastName).toEqual(mockUser.delivery_addres.last_name);
|
||||
expect(result.source).toEqual(mockUser.delivery_addres.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('customerDTOtoUser', () => {
|
||||
const mockCustomer: CustomerDTO = { id: 123, customerType: 16 };
|
||||
|
||||
it('should return a User with customerType property set to B2B', () => {
|
||||
const result = mapper.customerDTOtoUser(mockCustomer);
|
||||
|
||||
expect(result.customerType).toBe(CustomerTypeInternal.B2B);
|
||||
});
|
||||
});
|
||||
|
||||
describe('customerInfoDTOtoUser', () => {
|
||||
const mockCustomer: CustomerDTO = { id: 123, customerType: 8 };
|
||||
|
||||
it('should return a User with customerType property set to B2C', () => {
|
||||
const result = mapper.customerInfoDTOtoUser(mockCustomer);
|
||||
|
||||
expect(result.customerType).toBe(CustomerTypeInternal.B2C);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,818 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { User, Address, Features, Organisation } from '../models/user.model';
|
||||
import {
|
||||
Gender,
|
||||
AddressDTO,
|
||||
EntityDTOContainerOfShippingAddressDTO,
|
||||
OrganisationDTO,
|
||||
CommunicationDetailsDTO,
|
||||
AssignedPayerDTO,
|
||||
CustomerInfoDTO,
|
||||
PayerDTO,
|
||||
CustomerDTO,
|
||||
ShippingAddressDTO,
|
||||
CustomerType,
|
||||
} from '@swagger/crm';
|
||||
import { NotificationChannels } from '../models/notification-channels.enum';
|
||||
import { EntityDTOContainerOfBranchDTO, ShippingAddressDTO as CheckoutShippingAddressDTO } from '@swagger/checkout';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { BACKEND_API_TIMESTAMP_FORMAT } from '../utils/app.formats';
|
||||
import { KeyValueDTOOfStringAndString } from '@swagger/cat';
|
||||
import { CustomerTypeInternal } from '../models/customer-type.model';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CustomerMapping {
|
||||
constructor(private datePipe: DatePipe) {}
|
||||
|
||||
fromUser(customer: User): CustomerDTO {
|
||||
if (isNullOrUndefined(customer)) {
|
||||
throw new Error('argument customer:User is null or undefined.');
|
||||
}
|
||||
|
||||
let gender: Gender = 0;
|
||||
let address: AddressDTO = {};
|
||||
const addresses: EntityDTOContainerOfShippingAddressDTO[] = [];
|
||||
let organisation: OrganisationDTO = {};
|
||||
let communicationDetails: CommunicationDetailsDTO = {};
|
||||
const notificationChannels = this.getNotificationChannels(customer);
|
||||
const invoiceAdresses: AssignedPayerDTO[] = [];
|
||||
const shippingAddresses: EntityDTOContainerOfShippingAddressDTO[] = [];
|
||||
const features: Array<KeyValueDTOOfStringAndString> = [];
|
||||
let isGuestAccount: boolean;
|
||||
let hasOnlineAccount: boolean;
|
||||
|
||||
if (customer.mobile_number || customer.phone_number || customer.email) {
|
||||
communicationDetails = {
|
||||
email: customer.email ? customer.email : null,
|
||||
mobile: customer.mobile_number ? customer.mobile_number : null,
|
||||
phone: customer.phone_number ? customer.phone_number : null,
|
||||
fax: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (customer.gender) {
|
||||
gender = this.getGender(customer.gender);
|
||||
}
|
||||
|
||||
if (customer.delivery_addres) {
|
||||
address = {
|
||||
city: customer.delivery_addres.city,
|
||||
country: customer.delivery_addres.country,
|
||||
zipCode: customer.delivery_addres.zip + '',
|
||||
street: customer.delivery_addres.street,
|
||||
streetNumber: customer.delivery_addres.streetNo + '',
|
||||
info: customer.delivery_addres.note ? customer.delivery_addres.note : null,
|
||||
};
|
||||
}
|
||||
|
||||
if (customer.invoice_address) {
|
||||
address = {
|
||||
city: customer.invoice_address.city,
|
||||
country: customer.invoice_address.country,
|
||||
zipCode: customer.invoice_address.zip + '',
|
||||
street: customer.invoice_address.street,
|
||||
streetNumber: customer.invoice_address.streetNo + '',
|
||||
info: customer.invoice_address.note ? customer.invoice_address.note : null,
|
||||
};
|
||||
}
|
||||
|
||||
if (customer.organisation) {
|
||||
organisation = {
|
||||
name: customer.organisation.name, // Firma
|
||||
nameSuffix: customer.organisation.extraAddress, // Addresszutsaiz
|
||||
department: customer.organisation.department, // abteilung
|
||||
vatId: customer.organisation.vatId, // USt-ID
|
||||
};
|
||||
}
|
||||
|
||||
if (Array.isArray(customer.poossible_delivery_addresses) && customer.poossible_delivery_addresses.length > 0) {
|
||||
customer.poossible_delivery_addresses.forEach((adrs: Address) => {
|
||||
addresses.push(this.addressesItem(adrs));
|
||||
shippingAddresses.push(this.addressesItem(adrs));
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(customer.poossible_invoice_addresses) && customer.poossible_invoice_addresses.length > 0) {
|
||||
customer.poossible_invoice_addresses.forEach((adrs: Address) => {
|
||||
if (adrs) {
|
||||
addresses.push(this.addressesItem(adrs));
|
||||
invoiceAdresses.push({
|
||||
payer: {
|
||||
data: {
|
||||
firstName: adrs.first_name,
|
||||
lastName: adrs.last_name,
|
||||
gender: adrs.gender ? this.getGender(adrs.gender) : 0,
|
||||
title: adrs.title ? adrs.title : null,
|
||||
address: this.invoiceAdressItem(adrs),
|
||||
payerType: !!adrs.payer_type ? adrs.payer_type : 8,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(customer.features) && customer.features.length > 0) {
|
||||
customer.features.forEach((feature) => {
|
||||
if (feature.key === 'guestaccount') {
|
||||
isGuestAccount = true;
|
||||
}
|
||||
if (feature.key === 'onlineshop') {
|
||||
hasOnlineAccount = true;
|
||||
}
|
||||
features.push({
|
||||
key: feature.key,
|
||||
value: feature.value,
|
||||
description: feature.description,
|
||||
enabled: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const createdInBranch = <EntityDTOContainerOfBranchDTO>{
|
||||
id: customer.createdInBranch,
|
||||
// TODO: what is the meaning of enabled attribute
|
||||
enabled: true,
|
||||
};
|
||||
|
||||
return <CustomerDTO>{
|
||||
id: customer.id,
|
||||
firstName: customer.first_name,
|
||||
lastName: customer.last_name,
|
||||
title: customer.title ? customer.title : null,
|
||||
dateOfBirth: customer.date_of_birth ? customer.date_of_birth : null,
|
||||
customerNumber: customer.customerId ? customer.customerId : null,
|
||||
customerType: 8, // 8 => B2C customer, and the store app will have only B2C customers
|
||||
customerGroup: null,
|
||||
agentComment: null,
|
||||
statusChangeComment: null,
|
||||
deactivationComment: null,
|
||||
statusComment: null,
|
||||
label: null,
|
||||
user: null,
|
||||
campaignCode: null,
|
||||
bonusCard: null,
|
||||
isGuestAccount: isGuestAccount,
|
||||
hasOnlineAccount: hasOnlineAccount,
|
||||
attributes: null,
|
||||
createdInBranch: createdInBranch,
|
||||
customerStatus: 0, // Will this be ever different?
|
||||
gender: gender,
|
||||
address: address,
|
||||
fetchOnDeliveryNote: null,
|
||||
payers: invoiceAdresses,
|
||||
organisation: organisation,
|
||||
shippingAddresses: shippingAddresses,
|
||||
communicationDetails: communicationDetails,
|
||||
notificationChannels: notificationChannels,
|
||||
features: features.length > 0 ? features : null,
|
||||
};
|
||||
}
|
||||
|
||||
getGender(gender: string): Gender {
|
||||
if (gender === 'Frau') {
|
||||
return 4;
|
||||
} else if (gender === 'Herr') {
|
||||
return 2;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private addressesItem(address: Address): EntityDTOContainerOfShippingAddressDTO {
|
||||
if (!address) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
data: {
|
||||
firstName: address.first_name,
|
||||
lastName: address.last_name,
|
||||
gender: address.gender ? this.getGender(address.gender) : 0,
|
||||
title: address.title ? address.title : null,
|
||||
type: 1,
|
||||
address: {
|
||||
city: address.city,
|
||||
country: address.country,
|
||||
zipCode: address.zip + '',
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
info: address.note,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private invoiceAdressItem(address: Address): AddressDTO {
|
||||
return {
|
||||
city: address.city,
|
||||
country: address.country,
|
||||
zipCode: address.zip + '',
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
info: address.note,
|
||||
};
|
||||
}
|
||||
|
||||
customerInfoDTOtoUser(customerInfo: CustomerInfoDTO): User {
|
||||
if (isNullOrUndefined(customerInfo)) {
|
||||
throw new Error('argument customerInfo:CustomerInfoDTO is null or undefined.');
|
||||
}
|
||||
|
||||
const id = customerInfo.id;
|
||||
const firstName = customerInfo.firstName;
|
||||
const lastName = customerInfo.lastName;
|
||||
const gender = this.getGenderFromCode(customerInfo.gender);
|
||||
|
||||
let dateOfBirth: string;
|
||||
if (!!customerInfo.dateOfBirth) {
|
||||
dateOfBirth = customerInfo.dateOfBirth;
|
||||
}
|
||||
|
||||
let email: string;
|
||||
let phoneNumber: string;
|
||||
let mobileNumber: string;
|
||||
if (!!customerInfo.communicationDetails) {
|
||||
email = customerInfo.communicationDetails.email;
|
||||
phoneNumber = customerInfo.communicationDetails.phone;
|
||||
mobileNumber = customerInfo.communicationDetails.mobile;
|
||||
}
|
||||
|
||||
let newUser = false;
|
||||
if (customerInfo.version === 2) {
|
||||
newUser = true;
|
||||
}
|
||||
|
||||
let notificationSms = false;
|
||||
let notificationEmail = false;
|
||||
if (customerInfo.notificationChannels) {
|
||||
notificationSms =
|
||||
customerInfo.notificationChannels === NotificationChannels.Sms ||
|
||||
customerInfo.notificationChannels === NotificationChannels.EmailSms;
|
||||
notificationEmail =
|
||||
customerInfo.notificationChannels === NotificationChannels.Email ||
|
||||
customerInfo.notificationChannels === NotificationChannels.EmailSms;
|
||||
}
|
||||
|
||||
let baseAddres: Address = {} as Address;
|
||||
if (!!customerInfo.address) {
|
||||
baseAddres = {
|
||||
id: Date.now() + Math.random(),
|
||||
title: customerInfo.title,
|
||||
first_name: customerInfo.firstName,
|
||||
last_name: customerInfo.lastName,
|
||||
city: customerInfo.address.city ? customerInfo.address.city : undefined,
|
||||
zip: customerInfo.address.zipCode ? customerInfo.address.zipCode : undefined,
|
||||
country: customerInfo.address.country,
|
||||
street: customerInfo.address.street,
|
||||
streetNo: customerInfo.address.streetNumber ? customerInfo.address.streetNumber : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
let features: Features[] = [];
|
||||
if (customerInfo.features) {
|
||||
features = customerInfo.features
|
||||
.filter((t) => t.enabled === true && !isNullOrUndefined(t.description))
|
||||
.map((t) => {
|
||||
return <Features>{
|
||||
key: t.key,
|
||||
value: t.value,
|
||||
description: t.description,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
let organisation: Organisation = {};
|
||||
if (customerInfo.organisation) {
|
||||
organisation = {
|
||||
name: customerInfo.organisation.name,
|
||||
extraAddress: customerInfo.organisation.nameSuffix,
|
||||
department: customerInfo.organisation.department,
|
||||
vatId: customerInfo.organisation.vatId,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: review missing info from the API
|
||||
return <User>{
|
||||
id: id,
|
||||
customerId: customerInfo.customerNumber,
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
gender: gender,
|
||||
date_of_birth: dateOfBirth,
|
||||
email: email,
|
||||
phone_number: phoneNumber,
|
||||
mobile_number: mobileNumber,
|
||||
newUser: newUser,
|
||||
customer_card: false,
|
||||
newsletter: false, // missing info from API
|
||||
shop: false,
|
||||
notificationSms: notificationSms,
|
||||
notificationEmail: notificationEmail,
|
||||
payement_method: null, // missing info from API
|
||||
tolino: false, // missing info from API
|
||||
title: null, // missing info from API
|
||||
base_addres: baseAddres,
|
||||
hasOnlineAccount: customerInfo.hasOnlineAccount,
|
||||
isGuestAccount: customerInfo.isGuestAccount,
|
||||
features: features,
|
||||
changed: customerInfo.changed,
|
||||
created: customerInfo.created,
|
||||
customerNumber: customerInfo.customerNumber,
|
||||
organisation: organisation,
|
||||
customerType: this.fromCustomerType(customerInfo.customerType),
|
||||
};
|
||||
}
|
||||
|
||||
private getGenderFromCode(gender: number): string {
|
||||
if (gender === 4) {
|
||||
return 'Frau';
|
||||
} else if (gender === 2) {
|
||||
return 'Herr';
|
||||
} else if (gender === 1) {
|
||||
return 'Divers';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
customerDTOtoUser(customerDto: CustomerDTO): User {
|
||||
if (isNullOrUndefined(customerDto)) {
|
||||
throw new Error('argument customerDto:CustomerInfoDTO is null or undefined.');
|
||||
}
|
||||
|
||||
const id = customerDto.id;
|
||||
const firstName = customerDto.firstName;
|
||||
const lastName = customerDto.lastName;
|
||||
const gender = this.getGenderFromCode(customerDto.gender);
|
||||
|
||||
let dateOfBirth: string;
|
||||
if (!!customerDto.dateOfBirth) {
|
||||
dateOfBirth = customerDto.dateOfBirth;
|
||||
}
|
||||
|
||||
let email: string;
|
||||
let phoneNumber: string;
|
||||
let mobileNumber: string;
|
||||
if (!!customerDto.communicationDetails) {
|
||||
email = customerDto.communicationDetails.email;
|
||||
phoneNumber = customerDto.communicationDetails.phone;
|
||||
mobileNumber = customerDto.communicationDetails.mobile;
|
||||
}
|
||||
|
||||
let newUser = false;
|
||||
if (customerDto.version === 2) {
|
||||
newUser = true;
|
||||
}
|
||||
|
||||
let notificationSms = false;
|
||||
let notificationEmail = false;
|
||||
if (customerDto.notificationChannels) {
|
||||
notificationSms =
|
||||
customerDto.notificationChannels === NotificationChannels.Sms || customerDto.notificationChannels === NotificationChannels.EmailSms;
|
||||
notificationEmail =
|
||||
customerDto.notificationChannels === NotificationChannels.Email ||
|
||||
customerDto.notificationChannels === NotificationChannels.EmailSms;
|
||||
}
|
||||
|
||||
let baseAddres: Address;
|
||||
if (!!customerDto.address) {
|
||||
baseAddres = {
|
||||
id: Date.now() + Math.random(),
|
||||
title: customerDto.title,
|
||||
first_name: customerDto.firstName,
|
||||
last_name: customerDto.lastName,
|
||||
city: customerDto.address.city,
|
||||
zip: customerDto.address.zipCode,
|
||||
country: customerDto.address.country,
|
||||
street: customerDto.address.street,
|
||||
streetNo: customerDto.address.streetNumber,
|
||||
};
|
||||
}
|
||||
|
||||
let features: Features[] = [];
|
||||
if (customerDto.features) {
|
||||
features = customerDto.features
|
||||
.filter((t) => t.enabled === true && !isNullOrUndefined(t.description))
|
||||
.map((t) => {
|
||||
return <Features>{
|
||||
key: t.key,
|
||||
value: t.value,
|
||||
description: t.description,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
let organisation: Organisation = {};
|
||||
if (customerDto.organisation) {
|
||||
organisation = {
|
||||
name: customerDto.organisation.name,
|
||||
extraAddress: customerDto.organisation.nameSuffix,
|
||||
department: customerDto.organisation.department,
|
||||
vatId: customerDto.organisation.vatId,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: review missing info from the API
|
||||
return <User>{
|
||||
id: id,
|
||||
customerId: customerDto.customerNumber,
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
gender: gender,
|
||||
date_of_birth: dateOfBirth,
|
||||
email: email,
|
||||
phone_number: phoneNumber,
|
||||
mobile_number: mobileNumber,
|
||||
newUser: newUser,
|
||||
customer_card: false,
|
||||
createdInBranch: customerDto.createdInBranch ? customerDto.createdInBranch.id : null,
|
||||
newsletter: false, // missing info from API
|
||||
shop: false,
|
||||
notificationSms: notificationSms,
|
||||
notificationEmail: notificationEmail,
|
||||
payement_method: null, // missing info from API
|
||||
tolino: false, // missing info from API
|
||||
title: null, // missing info from API
|
||||
features: features,
|
||||
changed: customerDto.changed,
|
||||
created: customerDto.created,
|
||||
customerNumber: customerDto.customerNumber,
|
||||
organisation: organisation,
|
||||
hasOnlineAccount: customerDto.hasOnlineAccount,
|
||||
customerType: this.fromCustomerType(customerDto.customerType),
|
||||
};
|
||||
}
|
||||
|
||||
fromShippingAddressDtoToAddress(shippingAddress: ShippingAddressDTO): Address {
|
||||
if (isNullOrUndefined(shippingAddress)) {
|
||||
throw new Error('argument shippingAddress:ShippingAddressDTO is null or undefined.');
|
||||
}
|
||||
|
||||
let gender = '';
|
||||
if (!!shippingAddress.gender) {
|
||||
gender = this.getGenderFromCode(shippingAddress.gender);
|
||||
}
|
||||
|
||||
let country = '';
|
||||
let city = '';
|
||||
let street = '';
|
||||
let streetNo = null;
|
||||
let zip: string = null;
|
||||
if (!!shippingAddress.address) {
|
||||
country = shippingAddress.address.country;
|
||||
city = shippingAddress.address.city;
|
||||
street = shippingAddress.address.street;
|
||||
streetNo = shippingAddress.address.streetNumber;
|
||||
zip = shippingAddress.address.zipCode;
|
||||
}
|
||||
|
||||
let company_name = null;
|
||||
let company_department = null;
|
||||
let company_tax_number = null;
|
||||
if (!!shippingAddress.organisation) {
|
||||
company_name = shippingAddress.organisation.name;
|
||||
company_department = shippingAddress.organisation.department;
|
||||
company_tax_number = shippingAddress.organisation.vatId;
|
||||
}
|
||||
|
||||
let defaultSince: Date;
|
||||
if (!!shippingAddress.isDefault) {
|
||||
defaultSince = new Date(shippingAddress.isDefault);
|
||||
}
|
||||
|
||||
return <Address>{
|
||||
id: shippingAddress.id,
|
||||
title: shippingAddress.title,
|
||||
first_name: shippingAddress.firstName,
|
||||
last_name: shippingAddress.lastName,
|
||||
gender: gender,
|
||||
country: country,
|
||||
city: city,
|
||||
street: street,
|
||||
streetNo: streetNo,
|
||||
zip: zip,
|
||||
company_name: company_name,
|
||||
company_department: company_department,
|
||||
company_tax_number: company_tax_number,
|
||||
defaultSince: defaultSince,
|
||||
};
|
||||
}
|
||||
|
||||
fromAddressToShippingAddressDTO(address: Address, forUpdate: boolean): ShippingAddressDTO {
|
||||
if (isNullOrUndefined(address)) {
|
||||
throw new Error('argument address:Address is null or undefined.');
|
||||
}
|
||||
|
||||
let _address: AddressDTO;
|
||||
if (forUpdate) {
|
||||
_address = <AddressDTO>{
|
||||
id: address.id,
|
||||
country: address.country,
|
||||
city: address.city,
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
zipCode: address.zip + '',
|
||||
};
|
||||
} else {
|
||||
_address = <AddressDTO>{
|
||||
country: address.country,
|
||||
city: address.city,
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
zipCode: address.zip + '',
|
||||
};
|
||||
}
|
||||
|
||||
return <ShippingAddressDTO>{
|
||||
type: 1,
|
||||
title: address.title,
|
||||
firstName: address.first_name,
|
||||
lastName: address.last_name,
|
||||
gender: this.getGender(address.gender),
|
||||
status: 1,
|
||||
isDefault: this.datePipe.transform(new Date(), BACKEND_API_TIMESTAMP_FORMAT),
|
||||
organisation: <OrganisationDTO>{
|
||||
name: address.company_name,
|
||||
department: address.company_department,
|
||||
vatId: address.company_tax_number,
|
||||
},
|
||||
address: _address,
|
||||
};
|
||||
}
|
||||
|
||||
fromAddressToAddressDTO(address: Address): AddressDTO {
|
||||
if (isNullOrUndefined(address)) {
|
||||
throw new Error('argument address:Address is null or undefined.');
|
||||
}
|
||||
|
||||
return <AddressDTO>{
|
||||
country: address.country,
|
||||
city: address.city,
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
zipCode: address.zip + '',
|
||||
};
|
||||
}
|
||||
|
||||
fromAddressToAssignedPAyerDto(address: Address): PayerDTO {
|
||||
if (!address) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let _address: AddressDTO;
|
||||
if (!isNullOrUndefined(address.id)) {
|
||||
_address = <AddressDTO>{
|
||||
id: address.id,
|
||||
country: address.country,
|
||||
city: address.city,
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
zipCode: address.zip + '',
|
||||
};
|
||||
} else {
|
||||
_address = <AddressDTO>{
|
||||
country: address.country,
|
||||
city: address.city,
|
||||
street: address.street,
|
||||
streetNumber: address.streetNo + '',
|
||||
zipCode: address.zip + '',
|
||||
};
|
||||
}
|
||||
return <PayerDTO>{
|
||||
type: 1,
|
||||
title: address.title,
|
||||
firstName: address.first_name,
|
||||
lastName: address.last_name,
|
||||
gender: this.getGender(address.gender),
|
||||
status: 1,
|
||||
isDefault: this.datePipe.transform(new Date(), BACKEND_API_TIMESTAMP_FORMAT),
|
||||
address: _address,
|
||||
payerNumber: address.payer_number,
|
||||
payerStatus: address.payer_status,
|
||||
payerType: !!address.payer_type ? address.payer_type : 8,
|
||||
organisation: <OrganisationDTO>{
|
||||
name: address.company_name,
|
||||
department: address.company_department,
|
||||
vatId: address.company_tax_number,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fromAssignedPayerDtoToAddress(assignedPayers: AssignedPayerDTO): Address {
|
||||
if (isNullOrUndefined(assignedPayers)) {
|
||||
throw new Error('argument shippingAddress:ShippingAddressDTO is null or undefined.');
|
||||
}
|
||||
|
||||
let id = null;
|
||||
let firstName = null;
|
||||
let lastName = null;
|
||||
if (!!assignedPayers.payer && !!assignedPayers.payer.data) {
|
||||
id = assignedPayers.payer.data.id;
|
||||
firstName = assignedPayers.payer.data.firstName;
|
||||
lastName = assignedPayers.payer.data.lastName;
|
||||
}
|
||||
|
||||
let gender = '';
|
||||
if (!!assignedPayers.payer && !!assignedPayers.payer.data && !!assignedPayers.payer.data.gender) {
|
||||
gender = this.getGenderFromCode(assignedPayers.payer.data.gender);
|
||||
}
|
||||
|
||||
let country = '';
|
||||
let city = '';
|
||||
let street = '';
|
||||
let streetNo = null;
|
||||
let zip: string = null;
|
||||
if (!!assignedPayers.payer && !!assignedPayers.payer.data && !!assignedPayers.payer.data.address) {
|
||||
country = assignedPayers.payer.data.address.country;
|
||||
city = assignedPayers.payer.data.address.city;
|
||||
street = assignedPayers.payer.data.address.street;
|
||||
streetNo = assignedPayers.payer.data.address.streetNumber;
|
||||
zip = assignedPayers.payer.data.address.zipCode;
|
||||
}
|
||||
|
||||
let payerNumber = null;
|
||||
let payerStatus = null;
|
||||
let payerType = null;
|
||||
let title = null;
|
||||
if (!!assignedPayers.payer && !!assignedPayers.payer.data) {
|
||||
payerNumber = assignedPayers.payer.data.payerNumber;
|
||||
payerStatus = assignedPayers.payer.data.payerStatus;
|
||||
payerType = assignedPayers.payer.data.payerType;
|
||||
title = assignedPayers.payer.data.title;
|
||||
}
|
||||
|
||||
let company_name = null;
|
||||
let company_department = null;
|
||||
let company_tax_number = null;
|
||||
if (!!assignedPayers.payer && !!assignedPayers.payer.data && !!assignedPayers.payer.data.organisation) {
|
||||
company_name = assignedPayers.payer.data.organisation.name;
|
||||
company_department = assignedPayers.payer.data.organisation.department;
|
||||
company_tax_number = assignedPayers.payer.data.organisation.vatId;
|
||||
}
|
||||
|
||||
let defaultSince: Date;
|
||||
if (!!assignedPayers.isDefault) {
|
||||
defaultSince = new Date(assignedPayers.isDefault);
|
||||
}
|
||||
|
||||
return <Address>{
|
||||
id: id,
|
||||
title: title,
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
gender: gender,
|
||||
country: country,
|
||||
city: city,
|
||||
street: street,
|
||||
streetNo: streetNo,
|
||||
zip: zip,
|
||||
company_name: company_name,
|
||||
company_department: company_department,
|
||||
company_tax_number: company_tax_number,
|
||||
payer_number: payerNumber,
|
||||
payer_status: payerStatus,
|
||||
payer_type: payerType,
|
||||
defaultSince: defaultSince,
|
||||
};
|
||||
}
|
||||
|
||||
fromUserSimple(customer: User): CustomerDTO {
|
||||
if (isNullOrUndefined(customer)) {
|
||||
throw new Error('argument customer:User is null or undefined.');
|
||||
}
|
||||
|
||||
let gender: Gender = 0;
|
||||
let address: AddressDTO = {};
|
||||
let organisation: OrganisationDTO = {};
|
||||
let communicationDetails: CommunicationDetailsDTO = {};
|
||||
const notificationChannels = this.getNotificationChannels(customer);
|
||||
|
||||
if (customer.mobile_number || customer.phone_number || customer.email) {
|
||||
communicationDetails = {
|
||||
email: customer.email ? customer.email : null,
|
||||
mobile: customer.mobile_number ? customer.mobile_number : null,
|
||||
phone: customer.phone_number ? customer.phone_number : null,
|
||||
fax: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (customer.gender) {
|
||||
gender = this.getGender(customer.gender);
|
||||
}
|
||||
|
||||
if (customer.delivery_addres) {
|
||||
address = {
|
||||
city: customer.delivery_addres.city,
|
||||
country: customer.delivery_addres.country,
|
||||
zipCode: customer.delivery_addres.zip + '',
|
||||
street: customer.delivery_addres.street,
|
||||
streetNumber: customer.delivery_addres.streetNo + '',
|
||||
info: customer.delivery_addres.note ? customer.delivery_addres.note : null,
|
||||
};
|
||||
}
|
||||
|
||||
if (customer.organisation) {
|
||||
organisation = {
|
||||
name: customer.organisation.name, // Firma
|
||||
nameSuffix: customer.organisation.extraAddress, // Addresszutsaiz
|
||||
department: customer.organisation.department, // abteilung
|
||||
vatId: customer.organisation.vatId, // USt-ID
|
||||
};
|
||||
}
|
||||
|
||||
const createdInBranch = <EntityDTOContainerOfBranchDTO>{
|
||||
id: customer.createdInBranch,
|
||||
// TODO: what is the meaning of enabled attribute
|
||||
enabled: true,
|
||||
};
|
||||
|
||||
return <CustomerDTO>{
|
||||
id: customer.id,
|
||||
firstName: customer.first_name,
|
||||
lastName: customer.last_name,
|
||||
title: customer.title ? customer.title : null,
|
||||
dateOfBirth: customer.date_of_birth ? customer.date_of_birth : null,
|
||||
customerNumber: customer.customerId ? customer.customerId : null,
|
||||
customerType: this.toCustomerType(customer.customerType),
|
||||
customerGroup: null,
|
||||
agentComment: null,
|
||||
statusChangeComment: null,
|
||||
deactivationComment: null,
|
||||
statusComment: null,
|
||||
label: null,
|
||||
user: null,
|
||||
campaignCode: null,
|
||||
bonusCard: null,
|
||||
isGuestAccount: null,
|
||||
features: null,
|
||||
attributes: null,
|
||||
createdInBranch: createdInBranch,
|
||||
customerStatus: 0, // Will this be ever different?
|
||||
gender: gender,
|
||||
fetchOnDeliveryNote: null,
|
||||
organisation: organisation,
|
||||
communicationDetails: communicationDetails,
|
||||
notificationChannels: notificationChannels,
|
||||
};
|
||||
}
|
||||
|
||||
getNotificationChannels(c: User): NotificationChannels {
|
||||
if (!c) {
|
||||
return NotificationChannels.NotSet;
|
||||
}
|
||||
return c.notificationEmail && c.notificationSms
|
||||
? NotificationChannels.EmailSms
|
||||
: c.notificationEmail
|
||||
? NotificationChannels.Email
|
||||
: c.notificationSms
|
||||
? NotificationChannels.Sms
|
||||
: NotificationChannels.NotSet;
|
||||
}
|
||||
|
||||
fromOrganisationToOrganisationDTO(organisation: Organisation): OrganisationDTO {
|
||||
if (!organisation) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
name: organisation.name,
|
||||
department: organisation.department,
|
||||
vatId: organisation.vatId,
|
||||
};
|
||||
}
|
||||
|
||||
fromUserToCommunicationDetails(user: User): CommunicationDetailsDTO {
|
||||
return {
|
||||
phone: user.phone_number,
|
||||
mobile: user.mobile_number,
|
||||
email: user.email,
|
||||
};
|
||||
}
|
||||
|
||||
fromUserToShippingAddressDTO(user: User): CheckoutShippingAddressDTO {
|
||||
const deliveryDetails = user.delivery_addres;
|
||||
|
||||
if (!deliveryDetails) {
|
||||
throw Error('No Delivery Address set.');
|
||||
}
|
||||
|
||||
return {
|
||||
title: deliveryDetails.title,
|
||||
gender: this.getGender(user.gender),
|
||||
firstName: deliveryDetails.first_name,
|
||||
lastName: deliveryDetails.last_name,
|
||||
organisation: this.fromOrganisationToOrganisationDTO(user.organisation),
|
||||
communicationDetails: this.fromUserToCommunicationDetails(user),
|
||||
address: this.fromAddressToAddressDTO(deliveryDetails),
|
||||
source: deliveryDetails.id,
|
||||
};
|
||||
}
|
||||
|
||||
fromCustomerType(type: CustomerType): CustomerTypeInternal {
|
||||
return type;
|
||||
}
|
||||
|
||||
toCustomerType(type: CustomerTypeInternal): CustomerType {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { FeedCard } from '../models/feed-card.model';
|
||||
import { FeedBook } from '../models/feed-book.model';
|
||||
import { FeedEvent } from '../models/feed-event.model';
|
||||
import { FeedNews } from '../models/feed-news.model';
|
||||
import { FeedRecommandation } from '../models/feed-recommandation.model';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FeedKpi } from '../models/feed-kpi.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FeedMapping {
|
||||
constructor() {}
|
||||
|
||||
fromFeedDTO(feed: any): FeedCard {
|
||||
const books: FeedBook[] = [];
|
||||
const event: FeedEvent[] = [];
|
||||
const news: FeedNews[] = [];
|
||||
const recommandation: FeedRecommandation = null;
|
||||
let kpi: FeedKpi = null;
|
||||
|
||||
if (feed.items && feed.type === 'products') {
|
||||
feed.items.forEach((item) => {
|
||||
books.push({
|
||||
ean: item.product.ean,
|
||||
name: item.product.name,
|
||||
});
|
||||
});
|
||||
} else if (feed.type === 'info') {
|
||||
feed.items.forEach((i) => {
|
||||
news.push(<FeedNews>{
|
||||
id: i.id,
|
||||
title: i.heading,
|
||||
content: i.text,
|
||||
icon: i.image,
|
||||
});
|
||||
});
|
||||
} else if (feed.type === 'kpi') {
|
||||
kpi = {
|
||||
actual: feed.items[0].actual,
|
||||
target: feed.items[0].target,
|
||||
percantage: Math.round((feed.items[0].actual / feed.items[0].target) * 100),
|
||||
};
|
||||
}
|
||||
|
||||
return <FeedCard>{
|
||||
cardTitle: feed.label,
|
||||
type: feed.type,
|
||||
headline: feed.headline ? feed.headline : '',
|
||||
text: feed.desc ? feed.desc : '',
|
||||
books: books,
|
||||
event: event,
|
||||
news: news,
|
||||
kpi: kpi,
|
||||
recommandation: recommandation,
|
||||
showRecommIcon: feed.emphasize ? true : false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { OrderByDTO } from '@swagger/cat';
|
||||
import { FilterItem } from '../models/filter-item.model';
|
||||
import { OptionDTO } from '@cmf/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FilterItemMapping {
|
||||
constructor() {}
|
||||
|
||||
fromOptionDto(option: OptionDTO): FilterItem {
|
||||
return {
|
||||
id: option.value,
|
||||
name: option.label,
|
||||
selected: false,
|
||||
};
|
||||
}
|
||||
|
||||
fromOrderByDto(orderBy: OrderByDTO): FilterItem {
|
||||
return {
|
||||
id: orderBy.by,
|
||||
name: orderBy.label,
|
||||
desc: orderBy.desc,
|
||||
selected: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { InputDTO, UISettingsDTO, QueryTokenDTO, OrderByDTO } from '@swagger/cat';
|
||||
import { Filter } from '../models/filter.model';
|
||||
import { FilterItemMapping } from './filter-item.mapping';
|
||||
import { FilterItem } from '../models/filter-item.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FilterMapping {
|
||||
constructor(private filterItemMapping: FilterItemMapping) {}
|
||||
|
||||
fromInputDto(input: InputDTO): Filter {
|
||||
let items: FilterItem[] = [];
|
||||
let max: number;
|
||||
|
||||
if (input.options != null && input.options.values) {
|
||||
(max = input.options.max), (items = input.options.values.map((item) => this.filterItemMapping.fromOptionDto(item)));
|
||||
}
|
||||
|
||||
if (input.value != null) {
|
||||
if (max == null) {
|
||||
const selectedValues = input.value.split(';');
|
||||
for (const selected of selectedValues) {
|
||||
const idx = items.findIndex((f) => f.id === selected);
|
||||
if (idx >= 0) {
|
||||
items[idx].selected = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const idx = items.findIndex((f) => f.id === input.value);
|
||||
if (idx >= 0) {
|
||||
items[idx].selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
expanded: false,
|
||||
id: input.key,
|
||||
name: input.label,
|
||||
max,
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
toQueryTokenDto(target: QueryTokenDTO, source: Filter[], archive: boolean, negative: boolean) {
|
||||
const orderBy = source.find((f) => f.id === 'orderBy');
|
||||
if (orderBy != null) {
|
||||
target.orderBy = orderBy.items
|
||||
.filter((i) => i.selected)
|
||||
.map(
|
||||
(m) =>
|
||||
({
|
||||
by: m.id,
|
||||
desc: m.desc,
|
||||
} as OrderByDTO)
|
||||
);
|
||||
}
|
||||
|
||||
const filter = source.filter((f) => f.id !== 'orderBy').filter((f) => f.items && f.items.some((s) => s.selected));
|
||||
if (Array.isArray(filter)) {
|
||||
const kvps = filter.map((fil) => {
|
||||
const key = fil.id;
|
||||
const value = fil.items
|
||||
.filter((f) => f.selected)
|
||||
.map((f) => (negative && fil.id !== 'stock' ? '!' + f.id : f.id))
|
||||
.join(';');
|
||||
return [key, value];
|
||||
});
|
||||
|
||||
if (kvps && kvps.length > 0) {
|
||||
target.filter = {};
|
||||
for (const kvp of kvps) {
|
||||
target.filter[kvp[0]] = kvp[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (archive) {
|
||||
if (!target.filter) {
|
||||
target.filter = {};
|
||||
}
|
||||
target.filter['cattype'] = '2';
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
import { Product } from '../models/product.model';
|
||||
import { ItemDTO, PriceDTO } from '@swagger/cat';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ProductMapping {
|
||||
fromItemDTO(item: ItemDTO): Product {
|
||||
if (isNullOrUndefined(item)) {
|
||||
throw new Error('argument item:ItemDTO is null or undefined.');
|
||||
}
|
||||
|
||||
let currency = '';
|
||||
let price = 0;
|
||||
|
||||
let priceDto: PriceDTO;
|
||||
let ssc = '';
|
||||
let sscText = '';
|
||||
let storeStatusCode = 0;
|
||||
|
||||
if (!!item.catalogAvailability) {
|
||||
priceDto = item.catalogAvailability.price;
|
||||
ssc = item.catalogAvailability.ssc;
|
||||
sscText = item.catalogAvailability.sscText;
|
||||
storeStatusCode = item.catalogAvailability.status;
|
||||
}
|
||||
|
||||
if (!!priceDto && priceDto.value) {
|
||||
price = priceDto.value.value || price;
|
||||
currency = priceDto.value.currency || currency;
|
||||
}
|
||||
|
||||
let itemsInStock = 0;
|
||||
|
||||
if (Array.isArray(item.stockInfos)) {
|
||||
itemsInStock = item.stockInfos.reduce((aggr, si) => aggr + si.inStock, 0);
|
||||
}
|
||||
|
||||
let assortment: string;
|
||||
if (item.shelfInfos) {
|
||||
assortment = item.shelfInfos[0].assortment ? item.shelfInfos[0].assortment : item.shelfInfos[0].label;
|
||||
}
|
||||
|
||||
return {
|
||||
author: item.product.contributors,
|
||||
availability: !!item.catalogAvailability,
|
||||
currency,
|
||||
price,
|
||||
id: item.id,
|
||||
itemsInStock,
|
||||
err: '',
|
||||
category: assortment,
|
||||
icon: '',
|
||||
notAvailableReason: itemsInStock === 0 ? '' : '',
|
||||
publisher: item.product.manufacturer,
|
||||
recommandation: false,
|
||||
serial: item.product.serial,
|
||||
slogan: item.product.additionalName,
|
||||
title: item.product.name,
|
||||
type: item.product.formatDetail,
|
||||
typeIcon: item.product.format,
|
||||
location: item.product.productGroup,
|
||||
publicationDate: new Date(item.product.publicationDate),
|
||||
ean: item.product.ean,
|
||||
imageId: item.imageId,
|
||||
edition: item.product.edition,
|
||||
volume: item.product.volume,
|
||||
ssc,
|
||||
sscText,
|
||||
storeStatusCode: storeStatusCode,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { ItemDTO } from '@swagger/cat';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RecommendationItem } from '../models/recommendation.model';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class RecommendationMapping {
|
||||
fromItemDTO(item: ItemDTO): RecommendationItem {
|
||||
if (isNullOrUndefined(item)) {
|
||||
throw new Error('argument item:ItemDTO is null or undefined.');
|
||||
}
|
||||
|
||||
let price = 0;
|
||||
let images = [];
|
||||
|
||||
if (!!item.catalogAvailability) {
|
||||
price = item.catalogAvailability.price.value.value;
|
||||
}
|
||||
|
||||
if (Array.isArray(item.images) && item.images.length > 0) {
|
||||
images = item.images;
|
||||
}
|
||||
|
||||
return {
|
||||
id: item.ids ? item.ids.dig : null,
|
||||
ean: item.product.ean,
|
||||
name: item.product.name,
|
||||
price: price,
|
||||
imgUrl: images[0].url,
|
||||
type: item.product ? item.product.formatDetail : null,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { OrderItemListItemDTO, OrderDTO } from '@swagger/oms';
|
||||
import { ShelfOrder } from '../models/shelf-order.model';
|
||||
import { CollectingShelfOrder } from '../models/collecting-shelf-order.model';
|
||||
import { CollectingShelfService } from '../services/collecting-shelf.service';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
|
||||
export const orderStatusMapper: { [id: number]: string } = {
|
||||
0: '-', // 'Not Set'
|
||||
1: 'bestellt', // 'neu' 'Ordering'
|
||||
2: '-', // 'Placed'
|
||||
4: '-', // 'Accepted'
|
||||
8: '-', // 'Parked'
|
||||
16: 'bestellt', // 'In Process'
|
||||
32: '-', // 'Preparation For Shipping'
|
||||
64: 'versendet', // 'Dispatched'
|
||||
128: 'eingetroffen', // 'Arrived'
|
||||
256: 'abgeholt', // 'Fetched'
|
||||
512: 'storniert (Kunde)', // 'Canceled By Buyer'
|
||||
1024: 'storniert', // 'Canceled By Retailer'
|
||||
2048: 'storniert (Lieferant)', // 'Canceled By Supplier'
|
||||
4096: 'nicht lieferbar', // 'Not Available'
|
||||
8192: 'nachbestellt', // 'ReOrdered'
|
||||
16384: '-', // 'Returned By Buyer'
|
||||
32768: '-', // 'Available For Download'
|
||||
65536: '-', // 'Downloaded'
|
||||
131072: '-', // 'Not Fetched'
|
||||
262144: 'ans Lager (nicht abgeholt)', // 'Back To Stock'
|
||||
524288: 'angefragt', // 'Requested'
|
||||
1048576: 'weitergeleitet intern', // 'Redirected Internally'
|
||||
2097152: '-', // 'Overdue'
|
||||
4194304: 'zugestellt', // 'Delivered'
|
||||
8388608: 'Lieferant wird ermittelt', // 'Determine Supplier'
|
||||
16777216: 'derzeit nicht lieferbar', // 'Supplier Temporarily OutOfStock'
|
||||
33554432: 'reserviert', // 'Reserved'
|
||||
67108864: '-', // 'Assembled'
|
||||
134217728: '-', // 'Packed'
|
||||
};
|
||||
|
||||
export const activeOrderStatusMapper: { [id: number]: string } = {
|
||||
16: 'bestellt', // 'In Process'
|
||||
64: 'versendet', // 'Dispatched'
|
||||
128: 'eingetroffen', // 'Arrived'
|
||||
256: 'abgeholt', // 'Fetched'
|
||||
512: 'storniert (Kunde)', // 'Canceled By Buyer'
|
||||
1024: 'storniert', // 'Canceled By Retailer'
|
||||
2048: 'storniert (Lieferant)', // 'Canceled By Supplier'
|
||||
4096: 'nicht lieferbar', // 'Not Available'
|
||||
8192: 'nachbestellt', // 'ReOrdered'
|
||||
262144: 'ans Lager (nicht abgeholt)', // 'Back To Stock'
|
||||
524288: 'angefragt', // 'Requested'
|
||||
1048576: 'weitergeleitet intern', // 'Redirected Internally'
|
||||
4194304: 'zugestellt', // 'Delivered'
|
||||
8388608: 'Lieferant wird ermittelt', // 'Determine Supplier'
|
||||
16777216: 'derzeit nicht lieferbar', // 'Supplier Temporarily OutOfStock'
|
||||
33554432: 'reserviert', // 'Reserved'
|
||||
};
|
||||
|
||||
export enum OrderStatus {
|
||||
InProcess = 16, // 'bestellt'
|
||||
Dispatched = 64, // 'versendet'
|
||||
Arrived = 128, // 'eingetroffen'
|
||||
Fetched = 256, // 'abgeholt'
|
||||
CanceledByBuyer = 512, // 'storniert (Kunde)'
|
||||
CanceledByRetailer = 1024, // 'storniert'
|
||||
CanceledBySupplier = 2048, // 'storniert (Lieferant)'
|
||||
NotAvailable = 4096, // 'nicht lieferbar'
|
||||
ReOrdered = 8192, // 'nachbestellt'
|
||||
BackToStock = 262144, // 'ans Lager (nicht abgeholt)'
|
||||
Requested = 524288, // 'angefragt'
|
||||
RedirectedInternally = 1048576, // 'weitergeleitet intern'
|
||||
SupplierTemporarilyOutOfStock = 16777216, // derzeit nicht lieferbar
|
||||
}
|
||||
|
||||
export const orderDetailStatus: { [id: number]: string } = {
|
||||
0: '-',
|
||||
1: 'neu', // 'Ordering'
|
||||
2: 'bestellt', // 'InProcess'
|
||||
3: 'eingetroffen', // 'Arrived'
|
||||
};
|
||||
|
||||
export const orderChannelMapper: { [id: number]: string } = {
|
||||
0: '-', // 'NotSet'
|
||||
1: '', // 'System'
|
||||
2: 'Filiale', // 'Branch'
|
||||
4: 'HSC', // 'CallCenter'
|
||||
8: 'Internet', // 'Online'
|
||||
16: 'Mobil', // 'Mobile'
|
||||
32: '', // 'BackOffice'
|
||||
};
|
||||
|
||||
export const orderPaymentType: { [id: number]: string } = {
|
||||
0: 'NotSet',
|
||||
1: 'Bei Abholung', // 'WhenCollecting',
|
||||
2: 'Kostenfrei', // 'Free',
|
||||
4: 'Barzahlung', // 'Cash',
|
||||
8: 'Einzugsermächtigung', // 'DirectDebit',
|
||||
16: 'Dauerhafte Einzugsermächtigung', // 'DebitAdviceMandate',
|
||||
31: 'Debit Karte', // 'DebitCard',
|
||||
64: 'Kreditkarte', // 'CreditCard',
|
||||
128: 'Rechnung', // 'Invoice',
|
||||
256: 'Vorauskasse', // 'PrePayment',
|
||||
512: 'Gutschein', // 'Voucher',
|
||||
1024: 'Sammelrechnung', // 'CollectiveInvoice',
|
||||
2048: 'PayPal', // 'PayPal',
|
||||
4096: 'Sofortüberweisung', // 'InstantTransfer',
|
||||
8192: 'Nachnahme', // 'PayOnDelivery',
|
||||
16384: 'Kundenkarte', // 'BonusCard',
|
||||
};
|
||||
|
||||
export const receiptType: { [id: number]: string } = {
|
||||
0: 'NotSet',
|
||||
1: 'Lieferschein', // 'ShippingNote',
|
||||
2: 'Gutschrift', // 'CreditNote',
|
||||
4: 'Sammellieferschein', // 'CollectiveShippingNote',
|
||||
8: 'Sammelgutschrift', // 'CollectiveCreditNote',
|
||||
16: 'Sammellieferschein für Kundenkartenkäufe', // 'BonusCardCollectiveShippingNote',
|
||||
31: 'Sammelgutschrift für Kundenkartenkäufe', // 'BonusCardCollectiveCreditNote',
|
||||
64: 'Zahlungsbeleg', // 'PaymentReceipt',
|
||||
128: 'Rechnung', // 'Invoice',
|
||||
256: 'Sammelrechnung', // 'CollectiveInvoice',
|
||||
512: 'Proformarechnung', // 'ProformaInvoice',
|
||||
};
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ShelfMapping {
|
||||
fromOrderItemListItemDTOArrayToCollectingShelfOrder(
|
||||
orders: OrderItemListItemDTO[],
|
||||
collectingShelfService: CollectingShelfService,
|
||||
firstBatch: boolean
|
||||
): CollectingShelfOrder[] {
|
||||
if (isNullOrUndefined(orders) || orders.length < 1) {
|
||||
return [];
|
||||
}
|
||||
return orders.map((order, index) => {
|
||||
const hideCompartmentNumber = collectingShelfService.processOrderCompartmentNumber(orders, order, index, firstBatch);
|
||||
return <CollectingShelfOrder>{
|
||||
orderId: order.orderId,
|
||||
orderItemId: order.orderItemId,
|
||||
orderItemSubsetId: order.orderItemSubsetId,
|
||||
orderPId: order.orderPId,
|
||||
orderItemPId: order.orderItemPId,
|
||||
orderItemSubsetPId: order.orderItemSubsetPId,
|
||||
shopName: order.shopName,
|
||||
orderBranchId: order.orderBranchId,
|
||||
orderNumber: order.orderNumber,
|
||||
orderType: order.orderType,
|
||||
processingStatus: order.processingStatus,
|
||||
orderDate: order.orderDate,
|
||||
product: order.product,
|
||||
quantity: order.quantity,
|
||||
overallQuantity: order.overallQuantity,
|
||||
price: order.price,
|
||||
currency: order.currency,
|
||||
buyerNumber: order.buyerNumber,
|
||||
organisation: order.organisation,
|
||||
gender: order.gender,
|
||||
title: order.title,
|
||||
lastName: order.lastName,
|
||||
firstName: order.firstName,
|
||||
specialComment: order.specialComment,
|
||||
ssc: order.ssc,
|
||||
sscText: order.sscText,
|
||||
supplier: order.supplier,
|
||||
compartmentCode: order.compartmentCode,
|
||||
compartmentInfo: order.compartmentInfo,
|
||||
hideCompartmentNumber: hideCompartmentNumber,
|
||||
isPrebooked: order.isPrebooked,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
fromOrderDTOtoShelfOrder(order: OrderDTO): ShelfOrder {
|
||||
if (isNullOrUndefined(order)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return <ShelfOrder>{
|
||||
id: order.id,
|
||||
created: order.created,
|
||||
changed: order.changed,
|
||||
version: order.version,
|
||||
status: order.status,
|
||||
pId: order.pId,
|
||||
orderType: order.orderType,
|
||||
clientChannel: order.clientChannel,
|
||||
orderNumber: order.orderNumber,
|
||||
orderDate: order.orderDate,
|
||||
acceptanceDate: order.acceptanceDate,
|
||||
orderBranch: order.orderBranch,
|
||||
processingStatus: order.processingStatus,
|
||||
completedDate: order.completedDate,
|
||||
items: order.items,
|
||||
buyer: order.buyer,
|
||||
buyerComment: order.buyerComment,
|
||||
notificationChannels: order.notificationChannels,
|
||||
shippingAddress: order.shipping,
|
||||
targetBranch: order.targetBranch,
|
||||
logistician: order.logistician,
|
||||
payer: order.billing,
|
||||
paymentType: order.paymentType,
|
||||
paymentComment: order.paymentComment,
|
||||
payment: order.payment,
|
||||
invoiceText: order.invoiceText,
|
||||
paymentStatus: order.paymentStatus,
|
||||
paymentReferenceNumber: order.paymentReferenceNumber,
|
||||
agentComment: order.agentComment,
|
||||
specialAgreements: order.specialAgreements,
|
||||
validationStatus: order.validationStatus,
|
||||
termsOfDelivery: order.termsOfDelivery,
|
||||
campaignCode: order.campaignCode,
|
||||
orderValue: order.orderValue,
|
||||
orderValueCurrency: order.orderValueCurrency,
|
||||
itemsCount: order.itemsCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export interface GoodsInSearch {
|
||||
input: string;
|
||||
branchnumber: string;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export interface ActionResult<T> {
|
||||
error?: boolean;
|
||||
errorReasons?: { [key: string]: string };
|
||||
http?: {
|
||||
code: number;
|
||||
};
|
||||
message?: string;
|
||||
result?: T;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export enum ModuleSwitcher {
|
||||
Customer,
|
||||
Branch,
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export interface AutocompleteResults {
|
||||
display?: string;
|
||||
type?: string;
|
||||
query?: string;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { ItemDTO } from '@swagger/cat';
|
||||
import { BranchInfoDTO } from '@swagger/isa';
|
||||
|
||||
export interface BookData {
|
||||
id: number;
|
||||
book: ItemDTO;
|
||||
quantity: number;
|
||||
customQuantity?: number;
|
||||
price: number;
|
||||
currency: string;
|
||||
imgUrl: string;
|
||||
deliveryType: string;
|
||||
cartEntryId: number;
|
||||
branch?: BranchInfoDTO;
|
||||
orderId?: number;
|
||||
orderTypeChanged: boolean;
|
||||
avaMessage: string;
|
||||
pickUpPrice?: number;
|
||||
deliveryPrice?: number;
|
||||
downloadPrice?: number;
|
||||
deliveryDate?: string;
|
||||
pickUpDate?: string;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export interface BranchProcess {
|
||||
id: number;
|
||||
currentRoute?: string;
|
||||
currentRouteQueryParams?: any;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { BranchType } from '@swagger/checkout';
|
||||
|
||||
export const BranchTypeCode: { [key: string]: BranchType } = {
|
||||
NotSet: 0,
|
||||
Store: 1,
|
||||
WebStore: 2,
|
||||
CallCenter: 4,
|
||||
Headquarter: 8,
|
||||
HumanResources: 16,
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
export interface Breadcrumb {
|
||||
name: string;
|
||||
path: string;
|
||||
queryParams?: any;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { AddressDTO } from '@swagger/checkout';
|
||||
import { AvailabilityDTO } from '@swagger/availability';
|
||||
|
||||
export interface CartEntry {
|
||||
bookId: number;
|
||||
quantity: number;
|
||||
deliveryType: string;
|
||||
branch?: number;
|
||||
deliveryDate?: string;
|
||||
pickUpDate?: string;
|
||||
orderTypeChanged: boolean;
|
||||
avaMessage: string;
|
||||
pickUpPrice?: number;
|
||||
deliveryPrice?: number;
|
||||
downloadPrice?: number;
|
||||
shippingAddress?: AddressDTO;
|
||||
availability: AvailabilityDTO;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { ItemDTO } from '@swagger/cat';
|
||||
import { BranchInfoDTO } from '@swagger/isa';
|
||||
|
||||
export interface Cart {
|
||||
cartId: number;
|
||||
cartEntryId: number;
|
||||
book: ItemDTO;
|
||||
quantity: number;
|
||||
deliveryType: string;
|
||||
branch?: BranchInfoDTO;
|
||||
orderTypeChanged: boolean;
|
||||
avaMessage: string;
|
||||
pickUpPrice?: number;
|
||||
deliveryPrice?: number;
|
||||
downloadPrice?: number;
|
||||
deliveryDate?: string;
|
||||
pickUpDate?: string;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export enum CheckoutType {
|
||||
takeNow,
|
||||
store,
|
||||
delivery,
|
||||
donwload,
|
||||
deliveryB2b,
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { OrderType, OrderItemProcessingStatusValue, ProductDTO, Gender } from '@swagger/oms';
|
||||
import { ShelfOrderItemLevel } from './shelf-order-item-level.enum';
|
||||
|
||||
export interface CollectingShelfOrder {
|
||||
orderId?: number;
|
||||
orderItemId?: number;
|
||||
orderItemSubsetId?: number;
|
||||
orderPId?: string;
|
||||
orderItemPId?: string;
|
||||
orderItemSubsetPId?: string;
|
||||
shopName?: string;
|
||||
orderBranchId?: number;
|
||||
orderNumber?: string;
|
||||
orderType?: OrderType;
|
||||
processingStatus?: OrderItemProcessingStatusValue;
|
||||
orderDate?: string;
|
||||
product?: ProductDTO;
|
||||
quantity?: number;
|
||||
overallQuantity?: number;
|
||||
price?: number;
|
||||
currency?: string;
|
||||
buyerNumber?: string;
|
||||
organisation?: string;
|
||||
gender?: Gender;
|
||||
title?: string;
|
||||
lastName?: string;
|
||||
firstName?: string;
|
||||
specialComment?: string;
|
||||
ssc?: string;
|
||||
sscText?: string;
|
||||
supplier?: string;
|
||||
compartmentCode?: string;
|
||||
compartmentInfo?: string;
|
||||
shelfOrderItemLevel?: ShelfOrderItemLevel;
|
||||
hideCompartmentNumber: boolean;
|
||||
isPrebooked?: boolean;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface Country {
|
||||
index: number;
|
||||
id: number;
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
import { Features } from './user.model';
|
||||
|
||||
export class CustomerFeatures {
|
||||
online: boolean;
|
||||
guest: boolean;
|
||||
card: boolean;
|
||||
employee: boolean;
|
||||
|
||||
constructor(features: Features[]) {
|
||||
if (features && features.length > 0) {
|
||||
this.online = !isNullOrUndefined(features.find((feature) => feature.key === 'onlineshop'));
|
||||
this.guest = !isNullOrUndefined(features.find((feature) => feature.key === 'guestaccount'));
|
||||
this.card = !isNullOrUndefined(features.find((feature) => feature.key === 'p4mUser'));
|
||||
this.employee = !isNullOrUndefined(features.find((feature) => feature.key === 'staff'));
|
||||
} else {
|
||||
this.online = false;
|
||||
this.guest = false;
|
||||
this.card = false;
|
||||
this.employee = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
export interface CustomerOrderItem {
|
||||
id: number;
|
||||
name: string;
|
||||
price: number;
|
||||
currency: string;
|
||||
status: string;
|
||||
isbn: string;
|
||||
note: string;
|
||||
orderType: string;
|
||||
fsk: string;
|
||||
ticketNumber: string;
|
||||
suplier: string;
|
||||
vat: number;
|
||||
ssc: string;
|
||||
quantity: number;
|
||||
estimatedDate?: string;
|
||||
shippingAddress?: string;
|
||||
billingAddress?: string;
|
||||
preordered?: boolean;
|
||||
invoiceText?: string;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
export interface CustomerOrder {
|
||||
id: number;
|
||||
date: string;
|
||||
status: string;
|
||||
type: string;
|
||||
location: string;
|
||||
price: number;
|
||||
currency: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export const OrderStatus: { [key: number]: string } = {
|
||||
0: '-',
|
||||
1: 'In Bestellung',
|
||||
2: 'In Bearbeitung',
|
||||
3: 'Abgeschlossen',
|
||||
};
|
||||
|
||||
export const OrderType: { [key: number]: string } = {
|
||||
0: '-',
|
||||
2: 'Filiale',
|
||||
4: 'HSC',
|
||||
8: 'Online',
|
||||
};
|
||||
|
||||
export const OrderItemStatus: { [key: number]: string } = {
|
||||
0: '-',
|
||||
1: 'neu',
|
||||
2: '-',
|
||||
4: '-',
|
||||
8: '-',
|
||||
16: 'bestellt',
|
||||
32: '-',
|
||||
64: 'versendet',
|
||||
128: 'eingetroffen',
|
||||
256: 'abgeholt',
|
||||
512: 'storniert (Kunde)',
|
||||
1024: 'storniert',
|
||||
2048: 'storniert (Lieferant)',
|
||||
4096: 'nicht lieferbar',
|
||||
8192: 'nachbestellt',
|
||||
16384: '-',
|
||||
32768: '-',
|
||||
65536: '-',
|
||||
131072: '-',
|
||||
262144: 'ans Lager (nicht abgeholt)',
|
||||
524288: 'angefragt',
|
||||
1048576: 'weitergeleitet intern',
|
||||
2097152: '-',
|
||||
4194304: 'zugestellt',
|
||||
8388608: 'Lieferant wird ermittelt',
|
||||
16777216: 'derzeit nicht lieferbar',
|
||||
33554432: 'reserviert',
|
||||
67108864: '-',
|
||||
134217728: '-',
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
import { CustomerOrderItem } from './customer-order-item';
|
||||
|
||||
export interface CustomerOrder {
|
||||
id: number;
|
||||
customerName: string;
|
||||
status: string;
|
||||
type: string;
|
||||
date: string;
|
||||
branch: string;
|
||||
items: CustomerOrderItem[];
|
||||
orderType: number;
|
||||
orderNumber: string;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { User } from './user.model';
|
||||
|
||||
export class CustomerSearchResponse {
|
||||
customers: User[];
|
||||
hits: number;
|
||||
message?: string;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { User } from './user.model';
|
||||
|
||||
export interface CustomerSearchResult {
|
||||
processId: number;
|
||||
customers: User[];
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface CustomerSearch {
|
||||
query: string;
|
||||
skip: number;
|
||||
take: number;
|
||||
firstLoad: boolean;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
export type CustomerType = 0 | 1 | 2 | 4 | 8 | 16 | 32;
|
||||
|
||||
export enum CustomerTypeInternal {
|
||||
'' = 0,
|
||||
'Contact' = 1,
|
||||
'Branch' = 2,
|
||||
'Staff' = 4,
|
||||
'B2C' = 8,
|
||||
'B2B' = 16,
|
||||
'WB' = 32,
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { ShippingTarget } from '@swagger/checkout';
|
||||
export class DeliveryOption {
|
||||
static TAKE_NOW = 'Rücklage';
|
||||
static DELIVERY = 'Versand';
|
||||
static PICK_UP = 'Abholung';
|
||||
static DOWNLOAD = 'Download';
|
||||
static DELIVERY_B2B = 'B2B Versand';
|
||||
}
|
||||
|
||||
export const DeliveryType: { [key: string]: ShippingTarget } = {
|
||||
NotSet: 0,
|
||||
Branch: 1,
|
||||
ShippingAddress: 2,
|
||||
BillingAddress: 4,
|
||||
Packstation: 8,
|
||||
Download: 16,
|
||||
Quote: 32,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user