chore: Quellcode der bestehenden Angular-Anwendung für die Entwicklung hinzugefügt.
This commit is contained in:
parent
bb9f524648
commit
772a6af503
22
ClientApp/staff-db-ui/.vscode/launch.json
vendored
Normal file
22
ClientApp/staff-db-ui/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "ng serve",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:4204",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "ng test",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: test",
|
||||
"url": "http://localhost:4204/debug.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
6
ClientApp/staff-db-ui/.vscode/settings.json
vendored
Normal file
6
ClientApp/staff-db-ui/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"angular.enable-strict-mode-prompt": false,
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib",
|
||||
"azdoPullRequests.projectName": "StaffDB",
|
||||
"azdoPullRequests.pullRequestTitle": "commit"
|
||||
}
|
||||
302
ClientApp/staff-db-ui/angular.json
Normal file
302
ClientApp/staff-db-ui/angular.json
Normal file
@ -0,0 +1,302 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"staffdb": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"aot": true,
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/assets",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"ignore": [
|
||||
"styles/*"
|
||||
],
|
||||
"input": "src/app/shared/core/assets/",
|
||||
"output": "/assets/"
|
||||
},
|
||||
{
|
||||
"glob": "dhr-icon-152x152i.png",
|
||||
"input": "src/assets/icons/develop/",
|
||||
"output": "/assets/icons/"
|
||||
},
|
||||
"src/webmanifest.json",
|
||||
{
|
||||
"glob": "environment.js",
|
||||
"input": "src/environments/",
|
||||
"output": "/assets/js/"
|
||||
},
|
||||
{
|
||||
"glob": "package.json",
|
||||
"input": "./",
|
||||
"output": "./assets/json"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss",
|
||||
"node_modules/ngx-spinner/animations/ball-clip-rotate.css"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"src/app/shared/core/css/0-base/",
|
||||
"src/app/shared/core/components/popup-base"
|
||||
]
|
||||
},
|
||||
"scripts": [],
|
||||
"serviceWorker": true,
|
||||
"ngswConfigPath": "ngsw-config.json"
|
||||
},
|
||||
"configurations": {
|
||||
"default": {
|
||||
"progress": true,
|
||||
"optimization": false,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": true,
|
||||
"namedChunks": true,
|
||||
"aot": true,
|
||||
"extractLicenses": false,
|
||||
"vendorChunk": true,
|
||||
"buildOptimizer": false,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "30mb",
|
||||
"maximumError": "70mb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"develop": {
|
||||
"assets": [
|
||||
"src/assets",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"ignore": [
|
||||
"styles/*"
|
||||
],
|
||||
"input": "src/app/shared/core/assets/",
|
||||
"output": "/assets/"
|
||||
},
|
||||
{
|
||||
"glob": "dhr-icon-152x152i.png",
|
||||
"input": "src/assets/icons/develop/",
|
||||
"output": "/assets/icons/"
|
||||
},
|
||||
{
|
||||
"glob": "webmanifest.json",
|
||||
"input": "src/manifest/develop/",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"glob": "environment.js",
|
||||
"input": "src/environments/develop/",
|
||||
"output": "/assets/js/"
|
||||
},
|
||||
{
|
||||
"glob": "package.json",
|
||||
"input": "./",
|
||||
"output": "./assets/json"
|
||||
}
|
||||
],
|
||||
"progress": true,
|
||||
"optimization": false,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": true,
|
||||
"namedChunks": true,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": false,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "30mb",
|
||||
"maximumError": "70mb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"production": {
|
||||
"assets": [
|
||||
"src/assets",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"ignore": [
|
||||
"styles/*"
|
||||
],
|
||||
"input": "src/app/shared/core/assets/",
|
||||
"output": "/assets/"
|
||||
},
|
||||
{
|
||||
"glob": "dhr-icon-152x152i.png",
|
||||
"input": "src/assets/icons/production/",
|
||||
"output": "/assets/icons/"
|
||||
},
|
||||
{
|
||||
"glob": "webmanifest.json",
|
||||
"input": "src/manifest/production/",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"glob": "environment.js",
|
||||
"input": "src/environments/production/",
|
||||
"output": "/assets/js/"
|
||||
},
|
||||
{
|
||||
"glob": "package.json",
|
||||
"input": "./",
|
||||
"output": "./assets/json"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "30mb",
|
||||
"maximumError": "50mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "10kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"liveReload": false,
|
||||
"port": 4204,
|
||||
"buildTarget": "staffdb:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "staffdb:build:production"
|
||||
},
|
||||
"develop": {
|
||||
"buildTarget": "staffdb:build:develop"
|
||||
},
|
||||
"default": {
|
||||
"buildTarget": "staffdb:build:default"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "default"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "staffdb:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"styles": [
|
||||
"src/styles.scss",
|
||||
"node_modules/ngx-spinner/animations/ball-clip-rotate.css"
|
||||
],
|
||||
"scripts": [],
|
||||
"assets": [
|
||||
"src/assets",
|
||||
{
|
||||
"glob": "translate-core/*",
|
||||
"input": "src/app/shared/core/assets/",
|
||||
"output": "/assets/"
|
||||
},
|
||||
{
|
||||
"glob": "dhr-icon-152x152i.png",
|
||||
"input": "src/assets/icons/develop/",
|
||||
"output": "/assets/icons/"
|
||||
},
|
||||
"src/webmanifest.json",
|
||||
{
|
||||
"glob": "environment.js",
|
||||
"input": "src/environments/",
|
||||
"output": "/assets/js/"
|
||||
},
|
||||
{
|
||||
"glob": "package.json",
|
||||
"input": "./",
|
||||
"output": "./assets/json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"src/tsconfig.app.json",
|
||||
"src/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"staffdb-e2e": {
|
||||
"root": "e2e/",
|
||||
"projectType": "application",
|
||||
"prefix": "",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "staffdb:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "staffdb:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": "e2e/tsconfig.e2e.json",
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false,
|
||||
"cache": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
9
ClientApp/staff-db-ui/ngcc.config.js
Normal file
9
ClientApp/staff-db-ui/ngcc.config.js
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
packages: {
|
||||
'devextreme-angular': {
|
||||
ignorableDeepImportMatchers: [
|
||||
/devextreme\//
|
||||
]
|
||||
},
|
||||
}
|
||||
};
|
||||
30
ClientApp/staff-db-ui/ngsw-config.json
Normal file
30
ClientApp/staff-db-ui/ngsw-config.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||
"index": "/index.html",
|
||||
"assetGroups": [
|
||||
{
|
||||
"name": "app",
|
||||
"installMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/assets/icons/hr-logo_color.ico",
|
||||
"/index.html",
|
||||
"/webmanifest.json",
|
||||
"/*.css",
|
||||
"/*.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assets",
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/assets/**",
|
||||
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
16517
ClientApp/staff-db-ui/package-lock.json
generated
Normal file
16517
ClientApp/staff-db-ui/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
70
ClientApp/staff-db-ui/package.json
Normal file
70
ClientApp/staff-db-ui/package.json
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "staffdb",
|
||||
"version": "14.23.33",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"reinstall:packages": "rm -rf node_modules dist && npm cache clean --force && rm package-lock.json && npm install",
|
||||
"win_reinstall:packages": "rd /s /q node_modules && npm cache clean --force && del package-lock.json && npm install",
|
||||
"add_pwa": "ng add @angular/pwa@latest"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^17.3.10",
|
||||
"@angular/cdk": "^16.2.14",
|
||||
"@angular/common": "^17.3.10",
|
||||
"@angular/compiler": "^17.3.10",
|
||||
"@angular/core": "^17.3.10",
|
||||
"@angular/forms": "^17.3.10",
|
||||
"@angular/localize": "^17.3.10",
|
||||
"@angular/material": "^16.2.14",
|
||||
"@angular/material-moment-adapter": "^16.2.14",
|
||||
"@angular/platform-browser": "^17.3.10",
|
||||
"@angular/platform-browser-dynamic": "^17.3.10",
|
||||
"@angular/pwa": "^17.3.8",
|
||||
"@angular/router": "^17.3.10",
|
||||
"@angular/service-worker": "^17.3.10",
|
||||
"@ngx-translate/core": "^15.0.0",
|
||||
"@ngx-translate/http-loader": "^8.0.0",
|
||||
"@sentry/angular": "^8.4.0",
|
||||
"angular-in-memory-web-api": "^0.17.0",
|
||||
"devextreme-angular": "~23.2.6",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"jspdf": "^2.5.1",
|
||||
"moment": "^2.30.1",
|
||||
"ngx-clipboard": "^16.0.0",
|
||||
"ngx-device-detector": "^7.0.0",
|
||||
"ngx-mask": "^17.0.8",
|
||||
"ngx-spinner": "^17.0.0",
|
||||
"ngx-translate-multi-http-loader": "^17.0.0",
|
||||
"ngx-webcam": "^0.4.1",
|
||||
"rxjs": "^7.8.1",
|
||||
"zone.js": "^0.14.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^17.3.8",
|
||||
"@angular/cli": "^17.3.8",
|
||||
"@angular/compiler-cli": "^17.3.10",
|
||||
"@angular/language-service": "^17.3.10",
|
||||
"@types/jasmine": "latest",
|
||||
"@types/node": "latest",
|
||||
"codelyzer": "latest",
|
||||
"jasmine-core": "latest",
|
||||
"jasmine-spec-reporter": "latest",
|
||||
"karma": "latest",
|
||||
"karma-chrome-launcher": "latest",
|
||||
"karma-coverage": "latest",
|
||||
"karma-jasmine": "latest",
|
||||
"karma-jasmine-html-reporter": "latest",
|
||||
"protractor": "latest",
|
||||
"ts-node": "latest",
|
||||
"tslint": "latest",
|
||||
"typescript": "~5.4.5"
|
||||
}
|
||||
}
|
||||
21
ClientApp/staff-db-ui/src/app/app-routing.module.ts
Normal file
21
ClientApp/staff-db-ui/src/app/app-routing.module.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
|
||||
import { APP_PAGES } from '@app_consts';
|
||||
import { ACCOUNT_PAGE, Globals, LOGIN_PAGE } from '@app_core/services/globals';
|
||||
|
||||
ACCOUNT_PAGE.loadChildren = () => import('@app_modules/app-account/app-account.module').then(m => m.AppAccountModule);
|
||||
|
||||
const routes: Routes = [
|
||||
...APP_PAGES,
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/' + LOGIN_PAGE.path,
|
||||
pathMatch: 'full'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, { useHash: true, preloadingStrategy: PreloadAllModules })],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { public globals: Globals; }
|
||||
2
ClientApp/staff-db-ui/src/app/app.component.html
Normal file
2
ClientApp/staff-db-ui/src/app/app.component.html
Normal file
@ -0,0 +1,2 @@
|
||||
<app-layout [title]=globals.appTitleWithVersion></app-layout>
|
||||
<ngx-spinner type="ball-clip-rotate"> </ngx-spinner>
|
||||
0
ClientApp/staff-db-ui/src/app/app.component.scss
Normal file
0
ClientApp/staff-db-ui/src/app/app.component.scss
Normal file
27
ClientApp/staff-db-ui/src/app/app.component.spec.ts
Normal file
27
ClientApp/staff-db-ui/src/app/app.component.spec.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
it(`should have as title 'staffdb'`, async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app.title).toEqual('ang-material');
|
||||
}));
|
||||
it('should render title in a h1 tag', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to Angular!');
|
||||
}));
|
||||
});
|
||||
58
ClientApp/staff-db-ui/src/app/app.component.ts
Normal file
58
ClientApp/staff-db-ui/src/app/app.component.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import * as AppCnst from '@app_consts';
|
||||
import * as Cnst from '@app_core/consts';
|
||||
import * as Utils from '@app_core/utils';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import * as AppModule from './app.module';
|
||||
import { ENVIRONMENT_TOKEN } from '@app_core/injection-tokens';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { RepositoryService } from '@app_core/services/http/repository.service';
|
||||
import { ServerInfoService } from '@app_core/services/serverinfo.service';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
|
||||
|
||||
export class AppComponent implements OnInit {
|
||||
private environment = inject(ENVIRONMENT_TOKEN);
|
||||
|
||||
constructor(
|
||||
public globals: Globals,
|
||||
public repository: RepositoryService,
|
||||
public translate: TranslateService,
|
||||
private serverInfoService: ServerInfoService,
|
||||
private localeService: LocaleService,
|
||||
private updateService: SwUpdate
|
||||
|
||||
) {
|
||||
this.initLangCulture();
|
||||
globals.appTitle = AppCnst.APP_TITLE;
|
||||
Utils.setIndexTitle(globals.appTitle);
|
||||
globals.appTitleWithVersion = `${AppCnst.APP_TITLE} V.${this.environment.appVersion} (${this.environment.appBuild})`;
|
||||
globals.appPages = AppCnst.APP_PAGES;
|
||||
globals.mainPage = AppCnst.APP_PAGES[0];
|
||||
this.serverInfoService.defaultServerInfoVisible = false;
|
||||
}
|
||||
|
||||
|
||||
private initLangCulture() {
|
||||
this.translate.addLangs(AppCnst.SUPPORTED_LANGUAGES);
|
||||
|
||||
const languageFromBrowser: string = navigator.language.split('-')[0];
|
||||
const startLanguage: string = Utils.isLanguageSupported(languageFromBrowser, AppCnst.SUPPORTED_LANGUAGES, Cnst.SUPPORTED_LANGUAGES) ? languageFromBrowser : AppCnst.cnst_DefaultLanguage;
|
||||
const startCulture: string = Utils.isCultureSupported(navigator.language, AppModule.SUPPORTED_CULTURES, Cnst.SUPPORTED_CULTURES) ? navigator.language : AppCnst.cnst_DefaultCulture;
|
||||
|
||||
this.localeService.initLocaleLanguage(startCulture, startLanguage);
|
||||
}
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.updateService.checkForUpdate().then((res) => { if (res) { this.updateService.activateUpdate(); window.location.reload(); } });
|
||||
}
|
||||
|
||||
}
|
||||
144
ClientApp/staff-db-ui/src/app/app.module.ts
Normal file
144
ClientApp/staff-db-ui/src/app/app.module.ts
Normal file
@ -0,0 +1,144 @@
|
||||
import { AppComponent } from './app.component';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
/* Routing */
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
/* Angular Material */
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { AngularMaterialModule } from '@app_core/components/angular-material.module';
|
||||
import { APPICON4LIVE_TOKEN, APPICON4NAVBAR_TOKEN, APPICON4TEST_TOKEN, ENVIRONMENT_TOKEN, IENVIRONMENT, SUPPORTED_CULTURES_TOKEN, SUPPORTED_LANGUAGES_TOKEN } from '@app_core/injection-tokens';
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, Injectable } from '@angular/core';
|
||||
|
||||
/* FormsModule */
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
/* Components */
|
||||
import { LayoutModule } from '@app_core/components/layout/layout.module';
|
||||
import { NgxSpinnerModule } from 'ngx-spinner';
|
||||
|
||||
/* data acess */
|
||||
import { HttpInterceptorService } from '@app_core/services/http/http-interceptor.service';
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
|
||||
/* Globals */
|
||||
import { ErrorStateMatcher, ShowOnDirtyErrorStateMatcher } from '@angular/material/core';
|
||||
import { DxFormModule, DxButtonModule, DxTemplateHost, DxTemplateModule, DxChartModule, DxDataGridModule } from 'devextreme-angular';
|
||||
import { NgxMaskDirective, NgxMaskPipe, optionsConfig, provideNgxMask } from 'ngx-mask';
|
||||
import { Router } from '@angular/router';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { MessageBoxModule } from '@app_core/components/message-box/message-box.module';
|
||||
import { ClipboardModule } from 'ngx-clipboard';
|
||||
|
||||
/* Localisaton */
|
||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import { LocaleProvider } from '@app_core/services/localization/locale.provider';
|
||||
import { HenselTranslateService } from '@app_core/services/localization/hensel-translate.service';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import { loadMessages } from 'devextreme/localization';
|
||||
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeUs from '@angular/common/locales/en';
|
||||
import localeFr from '@angular/common/locales/fr';
|
||||
import localeGb from '@angular/common/locales/en-GB';
|
||||
|
||||
export const SUPPORTED_CULTURES = ['de-DE', 'en-GB', 'en-US', 'fr-FR'];
|
||||
registerLocaleData(localeDe, 'de-DE');
|
||||
registerLocaleData(localeUs, 'en-US');
|
||||
registerLocaleData(localeFr, 'fr-FR');
|
||||
registerLocaleData(localeGb, 'en-GB');
|
||||
|
||||
import * as deMessages from 'devextreme/localization/messages/de.json';
|
||||
loadMessages(deMessages);
|
||||
|
||||
// import { HammerGestureConfig, HAMMER_GESTURE_CONFIG, HammerModule } from '@angular/platform-browser';
|
||||
// AoT requires an exported function for factories
|
||||
// export class MyHammerConfig extends HammerGestureConfig {
|
||||
// // tslint:disable-next-line:no-angle-bracket-type-assertion
|
||||
// overrides = <any>{
|
||||
// swipe: { direction: Hammer.DIRECTION_ALL },
|
||||
// };
|
||||
// }
|
||||
|
||||
/* Sentry */
|
||||
import { APP_INITIALIZER, ErrorHandler } from '@angular/core';
|
||||
import * as Sentry from '@sentry/angular';
|
||||
import { SUPPORTED_LANGUAGES } from '@app_consts';
|
||||
import { TranslateLoaderProvider } from '@app_core/services/localization/translation-loader.provider';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@app_core/components/angular-material-index';
|
||||
|
||||
/* important to use mask functionality */
|
||||
const maskConfig: optionsConfig = {
|
||||
validation: false,
|
||||
};
|
||||
|
||||
|
||||
declare const environment: IENVIRONMENT;
|
||||
declare const appVersion: string;
|
||||
declare const appBuild: string;
|
||||
environment['appVersion'] = appVersion;
|
||||
environment['appBuild'] = appBuild;
|
||||
|
||||
@Injectable()
|
||||
export class SentryErrorHandler implements ErrorHandler {
|
||||
handleError(error) {
|
||||
Sentry.captureException(error.originalError || error);
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
],
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
AngularMaterialModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
DxFormModule,
|
||||
DxTemplateModule,
|
||||
DxDataGridModule,
|
||||
DxChartModule,
|
||||
DxButtonModule,
|
||||
MessageBoxModule,
|
||||
ClipboardModule,
|
||||
NgxSpinnerModule,
|
||||
NgxMaskDirective,
|
||||
NgxMaskPipe,
|
||||
TranslateModule.forRoot({loader: TranslateLoaderProvider}),
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
enabled: true, //environment.production,
|
||||
// Register the ServiceWorker as soon as the application is stable
|
||||
// or after 30 seconds (whichever comes first).
|
||||
registrationStrategy: 'registerWhenStable:30000'
|
||||
}),
|
||||
LayoutModule,
|
||||
AppRoutingModule, // must be the last!!!
|
||||
],
|
||||
providers: [
|
||||
DxTemplateHost,
|
||||
LocaleProvider,
|
||||
{ provide: ENVIRONMENT_TOKEN, useValue: environment },
|
||||
{ provide: SUPPORTED_LANGUAGES_TOKEN, useValue: SUPPORTED_LANGUAGES},
|
||||
{ provide: SUPPORTED_CULTURES_TOKEN, useValue: SUPPORTED_CULTURES},
|
||||
{ provide: APPICON4TEST_TOKEN, useValue: 'assets/icons/develop/dhr-icon-48x48.png'},
|
||||
{ provide: APPICON4LIVE_TOKEN, useValue: 'assets/icons/production/dhr-icon-48x48.png'},
|
||||
{ provide: APPICON4NAVBAR_TOKEN, useValue: 'assets/icons/main_48x48.png'},
|
||||
{ provide: TranslateService, useClass: HenselTranslateService },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
|
||||
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { floatLabel: 'auto' } },
|
||||
{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher },
|
||||
/* Sentry */
|
||||
{ provide: ErrorHandler, useClass: SentryErrorHandler/*, useValue: Sentry.createErrorHandler({showDialog: false, })*/ },
|
||||
{ provide: Sentry.TraceService, deps: [Router] },
|
||||
{ provide: APP_INITIALIZER, useFactory: () => () => {}, deps: [Sentry.TraceService], multi: true },
|
||||
provideNgxMask(maskConfig)
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
})
|
||||
|
||||
|
||||
export class AppModule { }
|
||||
@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { AppAccountComponent } from './app-account.component';
|
||||
import { AuthGuard } from '@app_core/services/authguard';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AppAccountComponent,
|
||||
canActivate: [AuthGuard]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppAccountRoutingModule { }
|
||||
@ -0,0 +1,22 @@
|
||||
<app-account>
|
||||
<div profile-settings></div>
|
||||
<div admin-settings>
|
||||
<hensel-selection
|
||||
id="input-WebApp"
|
||||
class="input-webapp"
|
||||
[dataSource]=appDataService.webAppList.items
|
||||
placeholder="Webapp"
|
||||
keyExpr="entityId"
|
||||
displayExpr="webAppName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
(selectedItemsChange)="webAppIdList=$event">
|
||||
</hensel-selection>
|
||||
<button mat-button (click)="onClick()" class="btn">
|
||||
<mat-icon>autorenew</mat-icon>
|
||||
Synchronize WebAppRole mit ADGroupen
|
||||
</button>
|
||||
</div>
|
||||
<div other-settings></div>
|
||||
</app-account>
|
||||
@ -0,0 +1,9 @@
|
||||
.input-webapp{
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
.btn{
|
||||
margin-left: 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { AccountComponent } from '@app_core/components/account/account.component';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-account-ext',
|
||||
templateUrl: 'app-account.component.html',
|
||||
styleUrls: ['app-account.component.scss']
|
||||
})
|
||||
|
||||
export class AppAccountComponent extends AccountComponent {
|
||||
public appDataService = inject(AppDataService);
|
||||
|
||||
onClick() {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DxDataGridModule } from 'devextreme-angular';
|
||||
import { DxoSearchPanelModule } from 'devextreme-angular/ui/nested';
|
||||
import { AppAccountRoutingModule } from './app-account-routing.module';
|
||||
import { AppAccountComponent } from './app-account.component';
|
||||
import { AccountModule } from '@app_core/components/account/account.module';
|
||||
import { AngularMaterialModule } from '@app_core/components/angular-material.module';
|
||||
import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppAccountComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
AppAccountRoutingModule, //must be earlier AccountModule
|
||||
AccountModule,
|
||||
AngularMaterialModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
DxDataGridModule,
|
||||
DxoSearchPanelModule,
|
||||
HenselSelectionComponent,
|
||||
TranslateModule
|
||||
]
|
||||
})
|
||||
export class AppAccountModule { }
|
||||
@ -0,0 +1,181 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { cnst_LoadedEntitiesExpiresInMs, EN_AppEntities, EN_AppPages, EN_HttpQueriesCount4Page } from '@app_consts';
|
||||
import { CoreUser } from '@app_core/models/coreuser';
|
||||
import { RepositoryService } from '@app_core/services/http/repository.service';
|
||||
import { CorePageService } from '@app_core/services/page.service';
|
||||
import { Department, DepartmentFilter } from '@app_models/basedata/department';
|
||||
import { DocumentArtToDepartment } from '@app_models/documentart-to-department';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { User } from '@app_models/user';
|
||||
import { WindreamIndex } from '@app_models/windream-index';
|
||||
import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department';
|
||||
import { ClientIdFilter, WindreamSearch } from '@app_models/windream-search';
|
||||
import { WindreamSearchItem } from '@app_models/windream-search-item';
|
||||
import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department';
|
||||
import { WindreamSearchToDepartment, WindreamSearchToDepartmentFilter } from '@app_models/windream-search-to-department';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
|
||||
export class DepartmentDataService extends CorePageService {
|
||||
protected appPage: EN_AppPages = EN_AppPages.Department;
|
||||
protected loadImedeately: boolean = true; //load on pening the page
|
||||
protected get appPageNoQueries() { return EN_HttpQueriesCount4Page.Department; }
|
||||
|
||||
// --- running data
|
||||
departmentFilter: DepartmentFilter = new DepartmentFilter('DepartmentFullFilter');
|
||||
departmentList: AppBaseEntityListWrapper<Department> = new AppBaseEntityListWrapper<Department>(Department, 'Abteilungsliste', EN_AppEntities.Department);
|
||||
|
||||
departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
windreamSearchToDepartmentDetails: AppBaseEntityWrapper<WindreamSearchToDepartment>;
|
||||
// tslint:disable-next-line: max-line-length
|
||||
windreamSearchToDepartmentList: AppBaseEntityListWrapper<WindreamSearchToDepartment> = new AppBaseEntityListWrapper<WindreamSearchToDepartment>(WindreamSearchToDepartment, 'Windream Suche Kacheln', EN_AppEntities.WindreamSearchToDepartment);
|
||||
windreamSearchToDepartmentFilter: WindreamSearchToDepartmentFilter = new WindreamSearchToDepartmentFilter('DepartmentFilter');
|
||||
// tslint:disable-next-line: max-line-length
|
||||
windreamSearchItemToWindreamSearchToDepartmentList: AppBaseEntityListWrapper<WindreamSearchItemToWindreamSearchToDepartment> = new AppBaseEntityListWrapper<WindreamSearchItemToWindreamSearchToDepartment>(WindreamSearchItemToWindreamSearchToDepartment, 'Windream Suchbausteine', EN_AppEntities.WindreamSearchItemToWindreamSearchToDepartment);
|
||||
windreamSearchItemToWindreamSearchToDepartmentFilter: WindreamSearchToDepartmentFilter = new WindreamSearchToDepartmentFilter('WindreamSearchToDepartmentFilter');
|
||||
windreamSearchItemToWindreamSearchToDepartmentDetails: AppBaseEntityWrapper<WindreamSearchItemToWindreamSearchToDepartment>;
|
||||
|
||||
windreamSearchItemList: AppBaseEntityListWrapper<WindreamSearchItem> = new AppBaseEntityListWrapper<WindreamSearchItem>(WindreamSearchItem, 'windream suche kacheln attribute', EN_AppEntities.WindreamSearchItem);
|
||||
windreamIndexToWindreamSearchToDepartmentDetails: AppBaseEntityWrapper<WindreamIndexToWindreamSearchToDepartment>;
|
||||
// tslint:disable-next-line: max-line-length
|
||||
windreamIndexToWindreamSearchToDepartmentList: AppBaseEntityListWrapper<WindreamIndexToWindreamSearchToDepartment> = new AppBaseEntityListWrapper<WindreamIndexToWindreamSearchToDepartment>(WindreamIndexToWindreamSearchToDepartment, 'Ausgabespalten für Windream Suche', EN_AppEntities.WindreamIndexToWindreamSearchToDepartment);
|
||||
windreamIndexToWindreamSearchToDepartmentFilter: WindreamSearchToDepartmentFilter = new WindreamSearchToDepartmentFilter('WindreamSearchToDepartmentFilter');
|
||||
|
||||
windreamSearchList: AppBaseEntityListWrapper<WindreamSearch> =
|
||||
new AppBaseEntityListWrapper<WindreamSearch>(WindreamSearch, 'Windream Suche Kacheln', EN_AppEntities.WindreamSearch);
|
||||
|
||||
clientIdFilter: ClientIdFilter = new ClientIdFilter('ClientIdFilter');
|
||||
|
||||
windreamIndexList: AppBaseEntityListWrapper<WindreamIndex> =
|
||||
new AppBaseEntityListWrapper<WindreamIndex>(WindreamIndex, 'Windream Index', EN_AppEntities.WindreamIndex);
|
||||
|
||||
documentArtToDepartmentListFilter: DepartmentFilter = new DepartmentFilter('DepartmentFilter');
|
||||
|
||||
documentArtToDepartmentList: AppBaseEntityListWrapper<DocumentArtToDepartment> =
|
||||
new AppBaseEntityListWrapper<DocumentArtToDepartment>(DocumentArtToDepartment, 'Dokumentartenliste für Department', EN_AppEntities.DocumentArtToDepartment);
|
||||
|
||||
employeeList: AppBaseEntityListWrapper<Employee> = new AppBaseEntityListWrapper<Employee>(Employee, 'mitarbeiter', EN_AppEntities.Employee + '/all');
|
||||
|
||||
selectedDocumentarts: number[] = [];
|
||||
clpbrdWindreamOutColHint1: string;
|
||||
clpbrdWindreamOutColHints: string;
|
||||
clpbrdWindreamOutColList: WindreamIndexToWindreamSearchToDepartment[] = [];
|
||||
|
||||
clpbrdWindreamSearchItemHint1: string;
|
||||
clpbrdWindreamSearchItemHints: string;
|
||||
clpbrdWindreamSearchItemList: WindreamSearchItemToWindreamSearchToDepartment[] = [];
|
||||
|
||||
constructor(
|
||||
private repositoryService: RepositoryService,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.departmentList.focusedCallBack = this.focusCallBack.bind(this);
|
||||
this.departmentList.filter = this.departmentFilter;
|
||||
this.departmentDetails = this.departmentList.createFocusedShadowEntity(AppBaseEntityWrapper.EN_ViewMode);
|
||||
this.departmentDetails.loadedDataExpiresInMs = cnst_LoadedEntitiesExpiresInMs;
|
||||
this.baseEntityWrapperWaitLoading = this.departmentDetails;
|
||||
this.activateRouting4EntityList(this.departmentList); //we are using routing
|
||||
|
||||
this.windreamSearchToDepartmentList.filter = this.windreamSearchToDepartmentFilter;
|
||||
this.windreamSearchToDepartmentDetails = this.windreamSearchToDepartmentList.createFocusedShadowEntity();
|
||||
this.windreamSearchToDepartmentDetails.dontLoadEntity = true;
|
||||
this.windreamSearchToDepartmentDetails.beforeNewCallBack = this.prepareSearchToDepartment.bind(this);
|
||||
|
||||
this.windreamIndexToWindreamSearchToDepartmentList.filter = this.windreamIndexToWindreamSearchToDepartmentFilter;
|
||||
this.windreamIndexToWindreamSearchToDepartmentDetails = this.windreamIndexToWindreamSearchToDepartmentList.createFocusedShadowEntity();
|
||||
this.windreamIndexToWindreamSearchToDepartmentDetails.dontLoadEntity = true;
|
||||
|
||||
this.windreamSearchItemToWindreamSearchToDepartmentList.filter = this.windreamSearchItemToWindreamSearchToDepartmentFilter;
|
||||
this.windreamSearchItemToWindreamSearchToDepartmentDetails = this.windreamSearchItemToWindreamSearchToDepartmentList.createFocusedShadowEntity();
|
||||
this.windreamSearchItemToWindreamSearchToDepartmentDetails.dontLoadEntity = true;
|
||||
|
||||
this.windreamSearchList.filter = this.clientIdFilter;
|
||||
this.windreamIndexList.filter = this.clientIdFilter;
|
||||
this.windreamSearchItemList.filter = this.clientIdFilter;
|
||||
this.documentArtToDepartmentList.filter = this.documentArtToDepartmentListFilter;
|
||||
|
||||
|
||||
this.departmentDetails.detailItems.register(this.windreamSearchToDepartmentList, null, 'departmentId');
|
||||
this.departmentDetails.detailItems.register(this.documentArtToDepartmentList, null, 'departmentId', (docarts: DocumentArtToDepartment[]) => {
|
||||
this.selectedDocumentarts = docarts.map(docart => docart.documentArtId);
|
||||
});
|
||||
this.windreamSearchToDepartmentDetails.detailItems.register(this.windreamIndexToWindreamSearchToDepartmentList, null, 'windreamSearchToDepartmentId');
|
||||
this.windreamSearchToDepartmentDetails.detailItems.register(this.windreamSearchItemToWindreamSearchToDepartmentList, null, 'windreamSearchToDepartmentId');
|
||||
|
||||
this.loadBaseData();
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
||||
loadData() {
|
||||
super.loadData();
|
||||
this.departmentList.load(null, null, () => this.pageLoadingService.updatePageLoadedCounters(this.appPage));
|
||||
}
|
||||
|
||||
public loadBaseData() {
|
||||
super.loadBaseData(this.appPage, 1);
|
||||
this.employeeList.load(null, null, () => this.pageLoadingService.updatePageLoadedCounters(this.appPage));
|
||||
}
|
||||
|
||||
public focusCallBack(focusedItem: Department) {
|
||||
this.clientIdFilter.clientId = focusedItem?.clientId;
|
||||
}
|
||||
|
||||
public clearData() {
|
||||
super.clearData();
|
||||
this.departmentFilter.filterReset();
|
||||
this.departmentList.clear();
|
||||
}
|
||||
|
||||
protected onLoggedInOut(user: CoreUser) {
|
||||
this.userChanged(new User(user));
|
||||
super.onLoggedInOut(user);
|
||||
}
|
||||
|
||||
private userChanged(user: User) {
|
||||
if (this.authService.isLoggedIn()) {
|
||||
this.departmentDetails.canNew = user.isMaster;
|
||||
this.departmentDetails.canEdit = this.departmentDetails.canNew;
|
||||
this.departmentDetails.canDelete = this.departmentDetails.canNew;
|
||||
}
|
||||
}
|
||||
|
||||
moveUpDown(direction: number,
|
||||
list:
|
||||
AppBaseEntityListWrapper<WindreamSearchToDepartment>
|
||||
| AppBaseEntityListWrapper<WindreamSearchItemToWindreamSearchToDepartment>
|
||||
| AppBaseEntityListWrapper<WindreamIndexToWindreamSearchToDepartment>
|
||||
) {
|
||||
const curItemIndex: number = list.focusedItemIndex;
|
||||
if (!(direction < 0 && curItemIndex === 0 || direction > 0 && curItemIndex === list.items.length)) {
|
||||
const targetItem = list.items[curItemIndex + direction];
|
||||
const targetSeq: number = targetItem.seq;
|
||||
const currentItem = list.focusedItem;
|
||||
targetItem.seq = currentItem.seq;
|
||||
currentItem.seq = targetSeq;
|
||||
targetItem.entityChanged = true;
|
||||
currentItem.entityChanged = true;
|
||||
|
||||
targetItem.save(this.repositoryService, null, null, null);
|
||||
currentItem.save(this.repositoryService, null, null, null);
|
||||
this.sortBySeq(list.items);
|
||||
}
|
||||
}
|
||||
|
||||
public sortBySeq(list: WindreamSearchToDepartment[] | WindreamSearchItemToWindreamSearchToDepartment[] | WindreamIndexToWindreamSearchToDepartment[]) {
|
||||
list.sort((fp1, fp2) => (fp1.seq - fp2.seq));
|
||||
}
|
||||
|
||||
|
||||
prepareSearchToDepartment(item: WindreamSearchToDepartment) {
|
||||
const maxSeq = this.windreamSearchToDepartmentList.items.reduce<number>((max: number, _index: WindreamSearchToDepartment) => max > _index.seq ? max : _index.seq, 0);
|
||||
item.seq = maxSeq + 1;
|
||||
item.isActive = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
<form class="departmentDetailsContent" #detailForm="ngForm">
|
||||
<hensel-input
|
||||
class="input-departmentName"
|
||||
name="departmentName"
|
||||
placeholder="Abteilungsname"
|
||||
maxlength="50"
|
||||
required
|
||||
[(ngModel)]=department.departmentName
|
||||
[disabled]="!departmentDetails.inNewEditMode"
|
||||
(blur)=depNameWasChanged()>
|
||||
</hensel-input>
|
||||
<hensel-selection
|
||||
name="costcentre"
|
||||
class="input-cost-centre"
|
||||
[dataSource]=costCentreList
|
||||
placeholder="CostCentre"
|
||||
keyExpr="entityId"
|
||||
displayExpr="costCentreName"
|
||||
sortField="*" required
|
||||
[multiSelect]=false
|
||||
[(selectedItems)]="department.costCentreId"
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-selection>
|
||||
<hensel-input
|
||||
class="input-departmentType"
|
||||
name="Type Id"
|
||||
placeholder="Abteilungstyp"
|
||||
maxlength="50"
|
||||
department
|
||||
[(ngModel)]=department.departmentTypeId
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-input>
|
||||
<hensel-selection
|
||||
name="headofDepartmentId"
|
||||
class="input-headofDepartmentId"
|
||||
[dataSource]=employeeList
|
||||
placeholder="Abteilungsleiter"
|
||||
keyExpr="entityId"
|
||||
displayExpr="fullname"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
[(selectedItems)]="department.headofDepartmentId"
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-selection>
|
||||
<hensel-selection
|
||||
name="executiveDirectorId"
|
||||
class="input-executiveDirectorId"
|
||||
[dataSource]=employeeList
|
||||
placeholder="CEO"
|
||||
keyExpr="entityId"
|
||||
displayExpr="fullname"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
[(selectedItems)]="department.executiveDirectorId"
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-selection>
|
||||
<hensel-selection
|
||||
name="managingDirectorId"
|
||||
class="input-managingDirectorId"
|
||||
[dataSource]=employeeList
|
||||
placeholder="COO"
|
||||
keyExpr="entityId"
|
||||
displayExpr="fullname"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
[(selectedItems)]="department.managingDirectorId"
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-selection>
|
||||
<hensel-input
|
||||
class="input-departmentNameFolder"
|
||||
name="departmentNameFolder"
|
||||
placeholder="Folder"
|
||||
maxlength="50"
|
||||
required
|
||||
[(ngModel)]=department.departmentNameFolder
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-input>
|
||||
<hensel-input
|
||||
class="input-adGroupDepartmentName"
|
||||
name="adGroupDepartmentName"
|
||||
placeholder="AD-Group Name"
|
||||
maxlength="50"
|
||||
required
|
||||
[(ngModel)]=department.adGroupDepartmentName
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-input>
|
||||
<hensel-input
|
||||
class="input-clientId"
|
||||
name="clientId"
|
||||
placeholder="Client Id"
|
||||
maxlength="50"
|
||||
required
|
||||
[(ngModel)]=department.clientId
|
||||
[disabled]="!departmentDetails.inNewEditMode">
|
||||
</hensel-input>
|
||||
<mat-checkbox class="input-isVirtual check-box" name="Enabled" style="float: left; margin-top: auto; margin-bottom: 12px;" labelPosition="before"
|
||||
[(ngModel)]=department.isVirtual inactive [disabled]="!departmentDetails.inNewEditMode">
|
||||
Virtual
|
||||
</mat-checkbox>
|
||||
</form>
|
||||
@ -0,0 +1,52 @@
|
||||
.departmentDetailsContent{
|
||||
// z-index: 10;
|
||||
// position: relative; //otherwise z-index is not working
|
||||
padding: 0 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-column-gap: 8px;
|
||||
grid-template-columns: repeat(2, minmax(1px, 1fr)); // column relationship
|
||||
grid-template-rows: repeat(5, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas:
|
||||
"input-departmentName input-cost-centre"
|
||||
"input-departmentType input-headofDepartmentId"
|
||||
"input-executiveDirectorId input-managingDirectorId"
|
||||
"input-departmentNameFolder input-adGroupDepartmentName"
|
||||
"input-clientId input-isVirtual"
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
.input-departmentName{
|
||||
grid-area: input-departmentName;
|
||||
}
|
||||
.input-cost-centre{
|
||||
grid-area: input-cost-centre;
|
||||
}
|
||||
.input-departmentType{
|
||||
grid-area: input-departmentType;
|
||||
}
|
||||
.input-headofDepartmentId{
|
||||
grid-area: input-headofDepartmentId;
|
||||
}
|
||||
.input-executiveDirectorId{
|
||||
grid-area: input-executiveDirectorId;
|
||||
}
|
||||
.input-managingDirectorId{
|
||||
grid-area: input-managingDirectorId;
|
||||
}
|
||||
.input-departmentNameFolder{
|
||||
grid-area: input-departmentNameFolder;
|
||||
}
|
||||
.input-adGroupDepartmentName{
|
||||
grid-area: input-adGroupDepartmentName;
|
||||
}
|
||||
.input-clientId{
|
||||
grid-area: input-clientId;
|
||||
}
|
||||
.input-isVirtual{
|
||||
grid-area: input-isVirtual;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DepartmentContentComponent } from './department-content.component';
|
||||
|
||||
describe('DepartmentContentComponent', () => {
|
||||
let component: DepartmentContentComponent;
|
||||
let fixture: ComponentFixture<DepartmentContentComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DepartmentContentComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DepartmentContentComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,53 @@
|
||||
import { Component, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { CostCentre } from '@app_models/basedata/cost-centre';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
import { NgForm } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-content',
|
||||
templateUrl: './department-content.component.html',
|
||||
styleUrls: ['./department-content.component.scss']
|
||||
})
|
||||
export class DepartmentContentComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('detailForm') detailForm: NgForm;
|
||||
@Input() departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
|
||||
|
||||
public get department(): Department {
|
||||
return this.departmentDetails.entity;
|
||||
}
|
||||
|
||||
|
||||
public get employeeList(): Employee[] {
|
||||
return this.departmentService.employeeList.items;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public get costCentreList(): CostCentre[] {
|
||||
return this.appDataService.costCentreList.items;
|
||||
}
|
||||
|
||||
|
||||
constructor(
|
||||
private appDataService: AppDataService,
|
||||
private departmentService: DepartmentDataService) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.departmentDetails.detailForm = this.detailForm;
|
||||
}
|
||||
|
||||
depNameWasChanged() {
|
||||
if (!this.department.departmentName) return;
|
||||
if (!this.department.departmentNameFolder) this.department.departmentNameFolder = this.department.departmentName;
|
||||
if (!this.department.adGroupDepartmentName) this.department.adGroupDepartmentName = this.department.departmentName;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
<form class="DepartmentDetailsForm" #detailForm="ngForm" id="form_department">
|
||||
<mat-card class="card">
|
||||
<mat-card-header>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="DepartmentDetails">
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<button *ngIf="departmentDetails.canNew" #btnNew id="btnNew" name="btnNew" class="abstand" mat-stroked-button
|
||||
title="Neue Abteilung" (click)="departmentDetails.new()"
|
||||
[disabled]="!departmentDetails.enabledNewButton()">
|
||||
<mat-icon>add</mat-icon> Hinzufügen
|
||||
</button>
|
||||
<button *ngIf="departmentDetails.canEdit" #btnEdit id="btnEdit" name="btnEdit" class="abstand" mat-stroked-button
|
||||
title="Bearbeiten" (click)="departmentDetails.edit()"
|
||||
[disabled]="!departmentDetails.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon> Bearbeiten
|
||||
</button>
|
||||
<button *ngIf="departmentDetails.canEdit||departmentDetails.canNew" id="btnSave" name="btnSave" class="abstand"
|
||||
mat-stroked-button disabled title="Speichern" (click)="save()"
|
||||
[disabled]="!departmentDetails.enabledSaveButton()">
|
||||
<mat-icon>save</mat-icon> Speichern
|
||||
</button>
|
||||
<button *ngIf="departmentDetails.canEdit||departmentDetails.canNew" id="btnUndo" name="btnUndo" class="abstand"
|
||||
mat-stroked-button disabled title="Änderungen verwerfen" (click)="cancel()" [autofocus]=true
|
||||
[disabled]="!departmentDetails.enabledCancelButton()">
|
||||
<mat-icon>undo</mat-icon> Verwerfen
|
||||
</button>
|
||||
<button *ngIf="departmentDetails.canDelete" id="btnDelete" name="btnDelete" mat-stroked-button class="abstand"
|
||||
title="Benutzer löschen" class="last" (click)="departmentDetails.delete()"
|
||||
[disabled]="!departmentDetails.enabledDeleteButton()">
|
||||
<mat-icon>delete</mat-icon> Löschen
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<app-department-content class="DetailsContent"
|
||||
[departmentDetails]="departmentDetails">
|
||||
</app-department-content>
|
||||
|
||||
<app-department-documentart class="DocumentArtList" [departmentDetails]=departmentDetails></app-department-documentart>
|
||||
<app-department-windream-search class="WindreamSearchList"
|
||||
[windreamSearchList]="windreamSearchList"
|
||||
[departmentDetails]="departmentDetails">
|
||||
</app-department-windream-search>
|
||||
<app-department-windream-search-item class="WindreamSearchItemList"
|
||||
[windreamSearchItemList]="windreamSearchItemToWindreamSearchToDepartmentList"
|
||||
[windreamSearchItemDetails]="windreamSearchItemToWindreamSearchToDepartmentDetails"
|
||||
[windreamSearchToDepartmentDetails]="windreamSearchToDepartmentDetails"
|
||||
[departmentDetails]="departmentDetails">
|
||||
</app-department-windream-search-item>
|
||||
<app-department-windream-index class="WindreamIndexList"
|
||||
[windreamIndexList]="windreamIndexList"
|
||||
[windreamIndexDetails]="windreamIndexDetails"
|
||||
[windreamSearchToDepartmentDetails]="windreamSearchToDepartmentDetails"
|
||||
[departmentDetails]="departmentDetails">
|
||||
</app-department-windream-index>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</form>
|
||||
@ -0,0 +1,46 @@
|
||||
.DepartmentDetails {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto repeat(1, minmax(1px, 250px)); // row relationships
|
||||
grid-template-columns: minmax(1px, 0.7fr) minmax(1px, 0.7fr) minmax(1px, 0.5fr) minmax(1px, 0.5fr) minmax(1px, 1fr); // column relationship
|
||||
grid-row-gap: 6px;
|
||||
grid-column-gap: 10px;
|
||||
grid-template-areas:
|
||||
'toolbar toolbar toolbar toolbar toolbar'
|
||||
'detail documentArtList windreamSearchList windreamSearchItemList windreamIndexList';
|
||||
z-index: 10;
|
||||
position: relative; //otherwise z-index is not working
|
||||
}
|
||||
.WindreamSearchItemList{
|
||||
grid-area: windreamSearchItemList;
|
||||
}
|
||||
|
||||
.WindreamIndexList{
|
||||
grid-area: windreamIndexList;
|
||||
}
|
||||
.WindreamSearchList{
|
||||
grid-area: windreamSearchList;
|
||||
}
|
||||
.DetailsContent {
|
||||
grid-area: detail;
|
||||
}
|
||||
.DocumentArtList {
|
||||
grid-area: documentArtList;
|
||||
}
|
||||
|
||||
.abstand {
|
||||
margin-right: 1px !important;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 12px;
|
||||
margin: 2px 2px 2px 2px;
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
import { Component, OnInit, Input, ChangeDetectorRef, DoCheck, ChangeDetectionStrategy, Output, EventEmitter, ViewChild, ElementRef, AfterViewInit, HostListener } from '@angular/core';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { DepartmentDataService } from '../department-data.service';
|
||||
import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department';
|
||||
import { WindreamSearchItem } from '@app_models/windream-search-item';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { reduce } from 'rxjs/operators';
|
||||
import { AuthorizeService } from '@app_core/services/authorize.service';
|
||||
import { PageLoadingService } from '@app_core/services/pageloading.service';
|
||||
import { EN_EntityBeforeSaveCallBackResults } from '@app_core/consts';
|
||||
import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-detail',
|
||||
templateUrl: './department-detail.component.html',
|
||||
styleUrls: ['./department-detail.component.scss'],
|
||||
})
|
||||
export class DepartmentDetailComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild('detailForm') detailForm: NgForm;
|
||||
|
||||
@Input() public departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
|
||||
public get windreamSearchToDepartmentDetails(): AppBaseEntityWrapper<WindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamSearchToDepartmentDetails;
|
||||
}
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
public authorizeService: AuthorizeService,
|
||||
private pageLoadingService: PageLoadingService,
|
||||
) {
|
||||
}
|
||||
public get windreamSearchList(): AppBaseEntityListWrapper<WindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamSearchToDepartmentList;
|
||||
}
|
||||
public get windreamSearchDetails(): AppBaseEntityWrapper<WindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamSearchToDepartmentDetails;
|
||||
}
|
||||
|
||||
|
||||
public get windreamSearchItemToWindreamSearchToDepartmentList(): AppBaseEntityListWrapper<WindreamSearchItemToWindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamSearchItemToWindreamSearchToDepartmentList;
|
||||
}
|
||||
public get windreamSearchItemToWindreamSearchToDepartmentDetails(): AppBaseEntityWrapper<WindreamSearchItemToWindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamSearchItemToWindreamSearchToDepartmentDetails;
|
||||
}
|
||||
public get windreamSearchItemList(): AppBaseEntityListWrapper<WindreamSearchItem> {
|
||||
return this.departmentDataService.windreamSearchItemList;
|
||||
}
|
||||
|
||||
|
||||
public get windreamIndexList(): AppBaseEntityListWrapper<WindreamIndexToWindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamIndexToWindreamSearchToDepartmentList;
|
||||
}
|
||||
public get windreamIndexDetails(): AppBaseEntityWrapper<WindreamIndexToWindreamSearchToDepartment> {
|
||||
return this.departmentDataService.windreamIndexToWindreamSearchToDepartmentDetails;
|
||||
}
|
||||
|
||||
|
||||
public get focusedItem(): Department {
|
||||
return this.departmentDetails.entity;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.departmentDetails.beforeNewCallBack = this.newDepartmentInit.bind(this);
|
||||
this.departmentDetails.beforeSaveCallBack = this.beforeSaveDepartment.bind(this);
|
||||
}
|
||||
|
||||
newDepartmentInit(department: Department) {
|
||||
this.departmentDataService.selectedDocumentarts = [];
|
||||
department.departmentTypeId = 1;
|
||||
department.clientId = 24110;
|
||||
}
|
||||
|
||||
async beforeSaveDepartment(department: Department): Promise<EN_EntityBeforeSaveCallBackResults> {
|
||||
const maxId: number = this.departmentDataService.departmentList.items.reduce((max, currentItem) => (currentItem.entityId > max ? currentItem.entityId : max), 0);
|
||||
if (department.isNew()) department.departmentId = -(maxId + 1);
|
||||
this.departmentDataService.documentArtToDepartmentList.match2KeysArray(department, 'departmentId', this.departmentDataService.selectedDocumentarts, 'documentArtId');
|
||||
return EN_EntityBeforeSaveCallBackResults.Ok_Continue;
|
||||
}
|
||||
|
||||
|
||||
public save = () => { //because of calling as callback of cancel
|
||||
this.pageLoadingService.startSpinner();
|
||||
this.departmentDetails.save((department: Department) => this.afterSave(department), null, () => this.pageLoadingService.hideSpinner());
|
||||
}
|
||||
|
||||
afterSave(department: Department) {
|
||||
// this.departmentDetails.loadDetails(this.catalogDataService.departmentCategoryList);
|
||||
|
||||
}
|
||||
|
||||
public cancel = () => {
|
||||
// this.setCurrentMaster4Subdepartment = null;
|
||||
this.departmentDetails.cancelWithSave(this.save);
|
||||
}
|
||||
|
||||
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
keyboardInput(event: any) {
|
||||
return LoginPopupComponent.LOGIN_IS_SHOWN || this.departmentDetails.shortcutsHandler(event, this.save, this.cancel);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
<div class="department-documentart">
|
||||
<label class="label"></label>
|
||||
<hensel-selection
|
||||
id="documentarts"
|
||||
class="documentart"
|
||||
name="documentarts"
|
||||
[dataSource]=appDataService.documentArtList.items
|
||||
placeholder="Dokumentenart"
|
||||
keyExpr="documentArtId"
|
||||
displayTemplate="${name} (${shortname})"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
[customFilter]="'clientId='+departmentDetails.entity.clientId"
|
||||
separator=","
|
||||
[(selectedItems)]="departmentDataService.selectedDocumentarts"
|
||||
(selectedItemsChange)="departmentDetails.entityWasChanged = true"
|
||||
[disabled]=!departmentDetails.inNewEditMode
|
||||
[height]="'100%'"
|
||||
[useResultGrid]=true>
|
||||
</hensel-selection>
|
||||
</div>
|
||||
@ -0,0 +1,19 @@
|
||||
.department-documentart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: 0 minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas: "label" "attributes";
|
||||
}
|
||||
|
||||
|
||||
.documentart {
|
||||
grid-area: attributes;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-documentart',
|
||||
templateUrl: './department-documentart.component.html',
|
||||
styleUrls: ['./department-documentart.component.scss']
|
||||
})
|
||||
|
||||
export class DepartmentDocumentartsComponent implements OnInit {
|
||||
|
||||
@Input() public departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
|
||||
constructor(
|
||||
public appDataService: AppDataService,
|
||||
public departmentDataService: DepartmentDataService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<form class="PopupContainer" #popupForm="ngForm">
|
||||
<!-- <dx-button class="buttonLayoutCancel" icon="close" (click)="close()"></dx-button> -->
|
||||
<h2 mat-dialog-title class="messageBoxHeader">{{description}} - {{keyItemName}} </h2>
|
||||
|
||||
<mat-dialog-content class="PopupContent">
|
||||
<div class="buttons">
|
||||
<button id="btnSave" name="btnSave" class="btnSave" mat-stroked-button
|
||||
[disabled]="!baseEntityWrapper.enabledSaveButton() || readOnly" (click)="save() ">
|
||||
<mat-icon>save</mat-icon> Übernehmen
|
||||
</button>
|
||||
<button #btnCancel id="btnCancel" name="btnCancel" class="btnCancel" mat-stroked-button (click)="cancel()">
|
||||
<mat-icon>cancel</mat-icon> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hensel-selection
|
||||
#input_windreamIndex
|
||||
id="input-windreamIndex"
|
||||
class="input-windreamIndex"
|
||||
[dataSource]=windreamIndexList
|
||||
placeholder="Ausgabespalte"
|
||||
keyExpr="entityId"
|
||||
displayExpr="selectionName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="windreamIndexIds"
|
||||
[disabled]="readOnly || focusedItem.entityId !== 0"
|
||||
[customFilterFn]="focusedItem.entityId === 0? getNotUsedwindreamIndexes: ''"
|
||||
[showSpinner]=this.departmentDataService.windreamIndexList.isLoading
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
</mat-dialog-content>
|
||||
</form>
|
||||
@ -0,0 +1,24 @@
|
||||
@import 'popup-base.component';
|
||||
|
||||
.PopupContent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid: ;
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto auto; // row relationships
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship
|
||||
grid-column-gap: 15px;
|
||||
grid-row-gap: 15px;
|
||||
grid-template-areas:
|
||||
'input-windreamSearch .'
|
||||
'buttons buttons'
|
||||
}
|
||||
|
||||
.input-windreamSearch {
|
||||
grid-area: input-windreamSearch;
|
||||
}
|
||||
|
||||
.input-seq {
|
||||
grid-area: input-seq;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component';
|
||||
import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component';
|
||||
import { WindreamIndex } from '@app_models/windream-index';
|
||||
import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-windream-index-popupedit',
|
||||
templateUrl: './department-windream-index-popupedit.component.html',
|
||||
styleUrls: ['./department-windream-index-popupedit.component.scss']
|
||||
})
|
||||
export class DepartmentWindreamIndexPopupeditComponent extends PopupBaseComponent {
|
||||
|
||||
public windreamIndexIds: number[] = [];
|
||||
@ViewChild('input_windreamIndex') input_windreamIndex: HenselSelectionComponent;
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
) {
|
||||
super();
|
||||
this.departmentDataService.windreamIndexList.load();
|
||||
}
|
||||
|
||||
|
||||
public get windreamIndexList(): WindreamIndex[] {
|
||||
return this.departmentDataService.windreamIndexList.items;
|
||||
}
|
||||
|
||||
public get focusedItem(): WindreamIndexToWindreamSearchToDepartment {
|
||||
return <WindreamIndexToWindreamSearchToDepartment>(this._focusedItem);
|
||||
}
|
||||
|
||||
getNotUsedwindreamIndexes = (dep: WindreamIndex) => {
|
||||
return !this.list.items.find((item) => item['windreamIndexId'] === dep.entityId);
|
||||
}
|
||||
|
||||
save = () => {
|
||||
let maxSeq = this.list.items.reduce<number>((max: number, _index: WindreamIndexToWindreamSearchToDepartment) => max > _index.seq ? max : _index.seq, 0);
|
||||
// for each selected WindreamIndexIds
|
||||
this.windreamIndexIds.forEach(windreamIndexId => {
|
||||
// create new WindreamIndexMap Item
|
||||
const newWindreamIndex = new WindreamIndexToWindreamSearchToDepartment();
|
||||
// calculate highest seq
|
||||
newWindreamIndex.seq = ++maxSeq;
|
||||
newWindreamIndex.windreamIndexId = windreamIndexId;
|
||||
newWindreamIndex.windreamSearchToDepartmentId = this.focusedItem.windreamSearchToDepartmentId;
|
||||
newWindreamIndex.entityChanged = true;
|
||||
this.list.items.push(newWindreamIndex);
|
||||
});
|
||||
this.list.save(() => {
|
||||
this.baseEntityWrapper.resetEditMode();
|
||||
this.close(true);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
<div class="department-windreamsearch-windreamindex">
|
||||
<label class="label">{{windreamIndexList._listName}}</label>
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<div class="toolbar-flex-container">
|
||||
<button mat-icon-button title="Hinzufügen" (click)=addItem()
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& windreamIndexList.focusedEntityShadowed.enabledNewButton())">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
<!-- <button mat-icon-button title="Bearbeiten" (click)=editItem()
|
||||
[disabled]="!departmentDetails.inEditMode || windreamIndexList.focusedItemId===0 || !windreamIndexList.focusedEntityShadowed.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button> -->
|
||||
<button mat-icon-button title="Kopieren zum Zwischenspeicher" (click)="copyWindreamOutCols()"
|
||||
[disabled]="!(!windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& windreamIndexList.items.length > 0)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button [title]="departmentDataService.clpbrdWindreamOutColHint1+'\n'+departmentDataService.clpbrdWindreamOutColHints" (click)="pasteWindreamOutCols()"
|
||||
[disabled]="!(departmentDataService.clpbrdWindreamOutColHint1
|
||||
&& departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew)">
|
||||
<mat-icon>content_paste</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Löschen"
|
||||
(click)=windreamIndexList.focusedEntityShadowed.delete();
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamIndexList.focusedEntityShadowed.isNew
|
||||
&& windreamIndexList.focusedEntityShadowed.enabledDeleteButton())">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Vorrücken"
|
||||
(click)="departmentDataService.moveUpDown(-1, windreamIndexList)"
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamIndexList.focusedEntityShadowed.isNew
|
||||
&& windreamIndexList.focusedItemIndex>0)">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Hinterrücken" class="toolbar-button-last"
|
||||
(click)="departmentDataService.moveUpDown(1, windreamIndexList)"
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamIndexList.focusedEntityShadowed.isNew
|
||||
&& windreamIndexList.focusedItemIndex<windreamIndexList.items.length-1)">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<dx-data-grid
|
||||
name="windreamSearchGrid"
|
||||
[class]="'grid'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="windreamIndexList.items"
|
||||
keyExpr="entityId"
|
||||
[(focusedRowIndex)]=windreamIndexList.focusedItemGridIndex
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowKey)]="windreamIndexList.focusedItemId"
|
||||
[(selectedRowKeys)]="windreamIndexList.selectedItemIds"
|
||||
[showBorders]="true" [allowColumnResizing]="true"
|
||||
columnResizingMode="widget"
|
||||
noDataText="Keine Daten sind vorhanden"
|
||||
[renderAsync]="true"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'"
|
||||
(onExporting)="globals.doExcelExportSimple($event, windreamIndexList.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<dxo-header-filter [visible]="true"></dxo-header-filter> -->
|
||||
<dxo-filter-row [visible]="false" [applyFilter]="true"></dxo-filter-row>
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple"></dxo-sorting>
|
||||
<dxo-selection mode="none"></dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf="column.visible">
|
||||
<dxi-column [allowHeaderFiltering]=column.allowHeaderFiltering [dataField]=column.dataField
|
||||
[dataType]=column.dataType [caption]=column.caption [width]=column.width
|
||||
[sortIndex]=column.sortIndex [sortOrder]=column.sortOrder [visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible [fixed]=column.fixed [headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate [allowSorting]=column.allowSorting
|
||||
[calculateCellValue]=column.calculateCellValue [calculateDisplayValue]=column.calculateDisplayValue
|
||||
[calculateGroupValue]=column.calculateGroupValue [calculateSortValue]=column.calculateSortValue
|
||||
[alignment]=column.alignment>
|
||||
<dxo-format *ngIf="column.dataType == 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType == 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</div>
|
||||
@ -0,0 +1,23 @@
|
||||
.department-windreamsearch-windreamindex{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas: "label label" "toolbar grid";
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-area: grid;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
// padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DepartmentWindreamIndexComponent } from './department-windream-index.component';
|
||||
|
||||
describe('DepartmentWindreamIndexComponent', () => {
|
||||
let component: DepartmentWindreamIndexComponent;
|
||||
let fixture: ComponentFixture<DepartmentWindreamIndexComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DepartmentWindreamIndexComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DepartmentWindreamIndexComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,101 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department';
|
||||
import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { DepartmentWindreamIndexPopupeditComponent } from './department-windream-index-popupedit/department-windream-index-popupedit.component';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { MatDialogService } from '@app_core/services/mat-dialog.service';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-windream-index',
|
||||
templateUrl: './department-windream-index.component.html',
|
||||
styleUrls: ['./department-windream-index.component.scss']
|
||||
})
|
||||
export class DepartmentWindreamIndexComponent implements OnInit {
|
||||
@Input() windreamIndexList: AppBaseEntityListWrapper<WindreamIndexToWindreamSearchToDepartment>;
|
||||
@Input() windreamIndexDetails: AppBaseEntityWrapper<WindreamIndexToWindreamSearchToDepartment>;
|
||||
@Input() windreamSearchToDepartmentDetails: AppBaseEntityWrapper<WindreamSearchToDepartment>;
|
||||
@Input() departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
|
||||
|
||||
public get windreamSearchName(): string {
|
||||
return this.windreamSearchToDepartmentDetails.entity.windreamSearchName;
|
||||
}
|
||||
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
constructor(
|
||||
private dialog: MatDialogService,
|
||||
public departmentDataService: DepartmentDataService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
col = this.columnConfigList.add('Seq.', 'seq', 2);
|
||||
col.sortIndex = 0;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
col = this.columnConfigList.add('Ausgabespalte', 'objectTypeAttributeSzName', 15);
|
||||
col = this.columnConfigList.add('Indexname', 'attributeSzColumnName', 15);
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
addItem() {
|
||||
this.windreamIndexList.focusedEntityShadowed.new();
|
||||
this.windreamIndexList.focusedEntityShadowed.entity.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId;
|
||||
this.openPopupDialog(this.windreamIndexList.focusedEntityShadowed);
|
||||
}
|
||||
|
||||
public openPopupDialog(editEntity: AppBaseEntityWrapper<WindreamIndexToWindreamSearchToDepartment>) {
|
||||
this.windreamSearchToDepartmentDetails.keyDownListenerStopped = true;
|
||||
this.dialog.openDialog(DepartmentWindreamIndexPopupeditComponent, {
|
||||
baseEntityWrapper: editEntity,
|
||||
keyItemName: this.windreamSearchToDepartmentDetails.entity.windreamSearchName,
|
||||
readOnly: !this.departmentDetails.inEditMode,
|
||||
description: editEntity.entity.entitytitle + (editEntity.entity.entityId === 0 ? ' zuweisen' : ' bearbeiten '),
|
||||
list: this.windreamIndexList,
|
||||
}, true, () => this.windreamSearchToDepartmentDetails.keyDownListenerStopped = false);
|
||||
}
|
||||
|
||||
|
||||
private outColKeyItemDescription() {
|
||||
return `Ausgabespalten für "${this.windreamSearchToDepartmentDetails.entity.windreamSearchName}" Abteilung "${this.departmentDetails.entity.departmentName}"`;
|
||||
|
||||
}
|
||||
|
||||
public copyWindreamOutCols() {
|
||||
this.departmentDataService.clpbrdWindreamOutColList = this.windreamIndexList.items.slice();
|
||||
this.departmentDataService.clpbrdWindreamOutColHint1 = this.outColKeyItemDescription();
|
||||
this.departmentDataService.clpbrdWindreamOutColHints = '';
|
||||
this.departmentDataService.clpbrdWindreamOutColList.forEach(col =>
|
||||
this.departmentDataService.clpbrdWindreamOutColHints += '\n' + col.objectTypeAttributeSzName);
|
||||
}
|
||||
|
||||
|
||||
public pasteWindreamOutCols() {
|
||||
this.windreamIndexDetails.confirmMessageBoxYesNo('Übernahme von ' + this.departmentDataService.clpbrdWindreamOutColHint1, this.outColKeyItemDescription() + ' werden mit ' + this.departmentDataService.clpbrdWindreamOutColHint1 + ' überschrieben. Sind Sie sicher?',
|
||||
() => {
|
||||
this.windreamIndexList.deleteAll();
|
||||
this.windreamIndexList.items.push(...this.departmentDataService.clpbrdWindreamOutColList);
|
||||
this.windreamIndexList.items.forEach(el => {
|
||||
el.entityId = 0;
|
||||
el.entityChanged = true;
|
||||
el.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId;
|
||||
});
|
||||
this.windreamIndexList.save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
<form class="PopupContainer" #popupForm="ngForm">
|
||||
<!-- <dx-button class="buttonLayoutCancel" icon="close" (click)="close()"></dx-button> -->
|
||||
<h2 mat-dialog-title class="messageBoxHeader">{{description}} - {{keyItemName}} </h2>
|
||||
|
||||
<mat-dialog-content class="PopupContent">
|
||||
<div class="buttons">
|
||||
<button id="btnSave" name="btnSave" class="btnSave" mat-stroked-button
|
||||
[disabled]="!baseEntityWrapper.enabledSaveButton() || readOnly" (click)="save() ">
|
||||
<mat-icon>save</mat-icon> Übernehmen
|
||||
</button>
|
||||
<button #btnCancel id="btnCancel" name="btnCancel" class="btnCancel" mat-stroked-button (click)="cancel()">
|
||||
<mat-icon>cancel</mat-icon> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hensel-selection
|
||||
#input_windreamSearchItem
|
||||
id="input_windreamSearchItem"
|
||||
class="input_windreamSearchItem"
|
||||
[dataSource]=windreamSearchItemList
|
||||
placeholder="Suchbaustein"
|
||||
keyExpr="entityId"
|
||||
displayExpr="name"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="windreamSearchItemIds"
|
||||
[disabled]="readOnly || focusedItem.entityId !== 0"
|
||||
[customFilterFn]="focusedItem.entityId === 0? getNotUsedwindreamSearchItems: ''"
|
||||
[showSpinner]=this.departmentDataService.windreamSearchItemList.isLoading
|
||||
required>
|
||||
</hensel-selection>
|
||||
</mat-dialog-content>
|
||||
</form>
|
||||
@ -0,0 +1,24 @@
|
||||
@import 'popup-base.component';
|
||||
|
||||
.PopupContent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid: ;
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto auto; // row relationships
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship
|
||||
grid-column-gap: 15px;
|
||||
grid-row-gap: 15px;
|
||||
grid-template-areas:
|
||||
'input-windreamSearch .'
|
||||
'buttons buttons'
|
||||
}
|
||||
|
||||
.input-windreamSearch {
|
||||
grid-area: input-windreamSearch;
|
||||
}
|
||||
|
||||
.input-seq {
|
||||
grid-area: input-seq;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component';
|
||||
import { WindreamSearchItem } from '@app_models/windream-search-item';
|
||||
import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-windream-search-item-popupedit',
|
||||
templateUrl: './department-windream-search-item-popupedit.component.html',
|
||||
styleUrls: ['./department-windream-search-item-popupedit.component.scss']
|
||||
})
|
||||
export class DepartmentWindreamSearchItemPopupeditComponent extends PopupBaseComponent {
|
||||
|
||||
public windreamSearchItemIds: number[] = [];
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
) {
|
||||
super();
|
||||
this.departmentDataService.windreamSearchItemList.load();
|
||||
this.getNotUsedwindreamSearchItems = this.getNotUsedwindreamSearchItems.bind(this);
|
||||
}
|
||||
|
||||
|
||||
public get windreamSearchItemList(): WindreamSearchItem[] {
|
||||
return this.departmentDataService.windreamSearchItemList.items;
|
||||
}
|
||||
|
||||
public get focusedItem(): WindreamSearchItemToWindreamSearchToDepartment {
|
||||
return <WindreamSearchItemToWindreamSearchToDepartment>(this._focusedItem);
|
||||
}
|
||||
|
||||
getNotUsedwindreamSearchItems(dep: WindreamSearchItem) {
|
||||
return !this.list.items.find((item) => item['windreamSearchItemId'] === dep.entityId);
|
||||
}
|
||||
|
||||
|
||||
save = () => {
|
||||
let maxSeq = this.list.items.reduce<number>((max: number, _index: WindreamSearchItemToWindreamSearchToDepartment) => max > _index.seq ? max : _index.seq, 0);
|
||||
// for each selected WindreamIndexIds
|
||||
this.windreamSearchItemIds.forEach(windreamSearchItemId => {
|
||||
// create new WindreamIndexMap Item
|
||||
const newWindreamItem = new WindreamSearchItemToWindreamSearchToDepartment();
|
||||
// calculate highest seq
|
||||
newWindreamItem.seq = ++maxSeq;
|
||||
newWindreamItem.windreamSearchItemId = windreamSearchItemId;
|
||||
newWindreamItem.windreamSearchToDepartmentId = this.focusedItem.windreamSearchToDepartmentId;
|
||||
newWindreamItem.entityChanged = true;
|
||||
this.list.items.push(newWindreamItem);
|
||||
});
|
||||
this.list.save(() => {
|
||||
this.baseEntityWrapper.resetEditMode();
|
||||
this.close(true);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
<div class="department-windreamsearch-windreamindex">
|
||||
<label class="label">{{windreamSearchItemList._listName}}</label>
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<div class="toolbar-flex-container">
|
||||
<button mat-icon-button title="Hinzufügen" (click)=addItem()
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamSearchItemList.focusedEntityShadowed.entityIsLoading
|
||||
&& windreamSearchItemList.focusedEntityShadowed.enabledNewButton())">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
<!-- <button mat-icon-button title="Bearbeiten" (click)=editItem()
|
||||
[disabled]="!departmentDetails.inEditMode || windreamSearchItemList.focusedItemId===0 || !windreamSearchItemList.focusedEntityShadowed.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button> -->
|
||||
<button mat-icon-button title="Kopieren zum Zwischenspeicher" (click)="copyWindreamOutCols()"
|
||||
[disabled]="!(!windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& windreamSearchItemList.items.length > 0)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button [title]="departmentDataService.clpbrdWindreamSearchItemHint1+'\n'+departmentDataService.clpbrdWindreamSearchItemHints" (click)="pasteWindreamOutCols()"
|
||||
[disabled]="!(departmentDataService.clpbrdWindreamSearchItemHint1
|
||||
&& departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew)">
|
||||
<mat-icon>content_paste</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Löschen"
|
||||
(click)=windreamSearchItemList.focusedEntityShadowed.delete();
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamSearchItemList.focusedEntityShadowed.isNew
|
||||
&& windreamSearchItemList.focusedEntityShadowed.enabledDeleteButton())">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Vorrücken"
|
||||
(click)="departmentDataService.moveUpDown(-1, windreamSearchItemList)"
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamSearchItemList.focusedEntityShadowed.isNew
|
||||
&& windreamSearchItemList.focusedItemIndex>0)">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Hinterrücken" class="toolbar-button-last"
|
||||
(click)="departmentDataService.moveUpDown(1, windreamSearchItemList)"
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !windreamSearchToDepartmentDetails.entityIsLoading
|
||||
&& !windreamSearchToDepartmentDetails.isNew
|
||||
&& !windreamSearchItemList.focusedEntityShadowed.isNew
|
||||
&& windreamSearchItemList.focusedItemIndex<windreamSearchItemList.items.length-1)">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<dx-data-grid
|
||||
name="windreamSearchGrid"
|
||||
[class]="'grid'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="windreamSearchItemList.items"
|
||||
keyExpr="entityId"
|
||||
[(focusedRowIndex)]=windreamSearchItemList.focusedItemGridIndex
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowKey)]="windreamSearchItemList.focusedItemId"
|
||||
[(selectedRowKeys)]="windreamSearchItemList.selectedItemIds"
|
||||
[showBorders]="true"
|
||||
[allowColumnResizing]="true"
|
||||
columnResizingMode="widget"
|
||||
noDataText="Keine Daten sind vorhanden"
|
||||
[renderAsync]="true"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'"
|
||||
(onExporting)="globals.doExcelExportSimple($event, windreamSearchItemList.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<dxo-header-filter [visible]="true"></dxo-header-filter> -->
|
||||
<dxo-filter-row [visible]="false" [applyFilter]="true"></dxo-filter-row>
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple"></dxo-sorting>
|
||||
<dxo-selection mode="none"></dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf="column.visible">
|
||||
<dxi-column [allowHeaderFiltering]=column.allowHeaderFiltering [dataField]=column.dataField
|
||||
[dataType]=column.dataType [caption]=column.caption [width]=column.width
|
||||
[sortIndex]=column.sortIndex [sortOrder]=column.sortOrder [visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible [fixed]=column.fixed [headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate [allowSorting]=column.allowSorting
|
||||
[calculateCellValue]=column.calculateCellValue [calculateDisplayValue]=column.calculateDisplayValue
|
||||
[calculateGroupValue]=column.calculateGroupValue [calculateSortValue]=column.calculateSortValue
|
||||
[alignment]=column.alignment>
|
||||
<dxo-format *ngIf="column.dataType == 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType == 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</div>
|
||||
@ -0,0 +1,23 @@
|
||||
.department-windreamsearch-windreamindex{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas: "label label" "toolbar grid";
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-area: grid;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
// padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { DepartmentWindreamSearchItemComponent } from './department-windream-search-item.component';
|
||||
|
||||
|
||||
describe('DepartmentWindreamIndexComponent', () => {
|
||||
let component: DepartmentWindreamSearchItemComponent;
|
||||
let fixture: ComponentFixture<DepartmentWindreamSearchItemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [DepartmentWindreamSearchItemComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DepartmentWindreamSearchItemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,94 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department';
|
||||
import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { DepartmentWindreamSearchItemPopupeditComponent } from './department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { MatDialogService } from '@app_core/services/mat-dialog.service';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-windream-search-item',
|
||||
templateUrl: './department-windream-search-item.component.html',
|
||||
styleUrls: ['./department-windream-search-item.component.scss']
|
||||
})
|
||||
export class DepartmentWindreamSearchItemComponent implements OnInit {
|
||||
@Input() windreamSearchItemList: AppBaseEntityListWrapper<WindreamSearchItemToWindreamSearchToDepartment>;
|
||||
@Input() windreamSearchItemDetails: AppBaseEntityWrapper<WindreamSearchItemToWindreamSearchToDepartment>;
|
||||
@Input() windreamSearchToDepartmentDetails: AppBaseEntityWrapper<WindreamSearchToDepartment>;
|
||||
@Input() departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
constructor(
|
||||
private dialog: MatDialogService,
|
||||
public departmentDataService: DepartmentDataService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
col = this.columnConfigList.add('Seq.', 'seq', 2);
|
||||
col.sortIndex = 0;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
col = this.columnConfigList.add('Suchbaustein', 'windreamSearchItemName', 10);
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
addItem() {
|
||||
this.windreamSearchItemList.focusedEntityShadowed.new();
|
||||
this.windreamSearchItemList.focusedEntityShadowed.entity.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId;
|
||||
this.openPopupDialog(this.windreamSearchItemList.focusedEntityShadowed);
|
||||
}
|
||||
|
||||
public openPopupDialog(editEntity: AppBaseEntityWrapper<WindreamSearchItemToWindreamSearchToDepartment>) {
|
||||
this.windreamSearchToDepartmentDetails.keyDownListenerStopped = true;
|
||||
this.dialog.openDialog(DepartmentWindreamSearchItemPopupeditComponent, {
|
||||
baseEntityWrapper: editEntity,
|
||||
keyItemName: this.windreamSearchToDepartmentDetails.entity._name,
|
||||
readOnly: !this.departmentDetails.inEditMode,
|
||||
description: editEntity.entity.entitytitle + (editEntity.entity.entityId === 0 ? ' zuweisen' : ' bearbeiten '),
|
||||
list: this.windreamSearchItemList,
|
||||
}, true, () => this.windreamSearchToDepartmentDetails.keyDownListenerStopped = false);
|
||||
}
|
||||
|
||||
|
||||
private outColKeyItemDescription() {
|
||||
return `Suchfelder für "${this.windreamSearchToDepartmentDetails.entity.windreamSearchName}" Abteilung "${this.departmentDetails.entity.departmentName}"`;
|
||||
}
|
||||
|
||||
|
||||
public copyWindreamOutCols() {
|
||||
this.departmentDataService.clpbrdWindreamSearchItemList = this.windreamSearchItemList.items.slice();
|
||||
this.departmentDataService.clpbrdWindreamSearchItemHint1 = this.outColKeyItemDescription();
|
||||
this.departmentDataService.clpbrdWindreamSearchItemHints = '';
|
||||
this.departmentDataService.clpbrdWindreamSearchItemList.forEach(col =>
|
||||
this.departmentDataService.clpbrdWindreamSearchItemHints += '\n' + col.windreamSearchItemName);
|
||||
}
|
||||
|
||||
|
||||
public pasteWindreamOutCols() {
|
||||
this.windreamSearchItemDetails.confirmMessageBoxYesNo('Übernahme von ' + this.departmentDataService.clpbrdWindreamSearchItemHint1, this.outColKeyItemDescription() + ' werden mit ' + this.departmentDataService.clpbrdWindreamSearchItemHint1 + ' überschrieben. Sind Sie sicher?',
|
||||
() => {
|
||||
this.windreamSearchItemList.deleteAll();
|
||||
this.windreamSearchItemList.items.push(...this.departmentDataService.clpbrdWindreamSearchItemList);
|
||||
this.windreamSearchItemList.items.forEach(el => {
|
||||
el.entityId = 0;
|
||||
el.entityChanged = true;
|
||||
el.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId;
|
||||
});
|
||||
this.windreamSearchItemList.save();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
<form class="PopupContainer" #popupForm="ngForm">
|
||||
<!-- <dx-button class="buttonLayoutCancel" icon="close" (click)="close()"></dx-button> -->
|
||||
<h2 mat-dialog-title class="messageBoxHeader">{{description}} - {{keyItemName}} </h2>
|
||||
|
||||
<mat-dialog-content class="PopupContent">
|
||||
|
||||
<div class="buttons">
|
||||
<button id="btnSave" name="btnSave" class="btnSave" mat-stroked-button
|
||||
[disabled]="!baseEntityWrapper.enabledSaveButton() || readOnly" (click)="save() ">
|
||||
<mat-icon>save</mat-icon> Übernehmen
|
||||
</button>
|
||||
<button #btnCancel id="btnCancel" name="btnCancel" class="btnCancel" mat-stroked-button (click)="cancel()">
|
||||
<mat-icon>cancel</mat-icon> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<hensel-selection
|
||||
#input_windreamSearch
|
||||
id="input-windreamSearch"
|
||||
class="input-windreamSearch"
|
||||
[dataSource]=windreamSearchList
|
||||
placeholder="Windream Search Kachel"
|
||||
keyExpr="entityId"
|
||||
displayExpr="selectionName"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.windreamSearchId"
|
||||
[customFilterFn]="focusedItem.entityId === 0? getNotUsedWindreamSearches: ''"
|
||||
[showSpinner]=this.departmentDataService.windreamSearchList.isLoading
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
|
||||
</mat-dialog-content>
|
||||
</form>
|
||||
@ -0,0 +1,20 @@
|
||||
@import 'popup-base.component';
|
||||
|
||||
.PopupContent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid: ;
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto auto; // row relationships
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship
|
||||
grid-column-gap: 15px;
|
||||
grid-row-gap: 15px;
|
||||
grid-template-areas:
|
||||
'input-windreamSearch .'
|
||||
'buttons buttons'
|
||||
}
|
||||
|
||||
.input-windreamSearch {
|
||||
grid-area: input-windreamSearch;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DepartmentWindreamSearchPopupeditComponent } from './department-windream-search-popupedit.component';
|
||||
|
||||
describe('DepartmentWindreamSearchPopupeditComponent', () => {
|
||||
let component: DepartmentWindreamSearchPopupeditComponent;
|
||||
let fixture: ComponentFixture<DepartmentWindreamSearchPopupeditComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DepartmentWindreamSearchPopupeditComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DepartmentWindreamSearchPopupeditComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,34 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component';
|
||||
import { WindreamSearch } from '@app_models/windream-search';
|
||||
import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-windream-search-popupedit',
|
||||
templateUrl: './department-windream-search-popupedit.component.html',
|
||||
styleUrls: ['./department-windream-search-popupedit.component.scss']
|
||||
})
|
||||
export class DepartmentWindreamSearchPopupeditComponent extends PopupBaseComponent {
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
) {
|
||||
super();
|
||||
this.departmentDataService.windreamSearchList.load();
|
||||
}
|
||||
|
||||
|
||||
public get windreamSearchList(): WindreamSearch[] {
|
||||
return this.departmentDataService.windreamSearchList.items;
|
||||
}
|
||||
|
||||
public get focusedItem(): WindreamSearchToDepartment {
|
||||
return <WindreamSearchToDepartment>(this._focusedItem);
|
||||
}
|
||||
|
||||
getNotUsedWindreamSearches = (dep: WindreamSearch) => {
|
||||
return !this.list.items.find((item) => item['windreamSearchId'] === dep.entityId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
<div class="department-windreamsearch">
|
||||
<label class="label">{{windreamSearchList._listName}}</label>
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<div class="toolbar-flex-container">
|
||||
<button mat-icon-button title="Hinzufügen" (click)=addItem()
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !departmentDetails.entityIsLoading
|
||||
&& windreamSearchList.focusedEntityShadowed.enabledNewButton())">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
<!-- <button mat-icon-button title="Bearbeiten" (click)=editItem()
|
||||
[disabled]="!departmentDetails.inEditMode || windreamSearchList.focusedItemId===0 || !windreamSearchList.focusedEntityShadowed.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button> -->
|
||||
<button mat-icon-button title="Kopiere alle Windream-Kacheln zu anderen Abteilungen" (click)="copyAllTiles()"
|
||||
[disabled]="!(windreamSearchList.items.length>0
|
||||
&& !departmentDetails.entityIsLoading)">
|
||||
<mat-icon>copy_all</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Füge die aktuelle Windream-Kachel zu anderen Abteilungen hinzu" (click)="copyCurrentTile()"
|
||||
[disabled]="!(!departmentDetails.entityIsLoading
|
||||
&& !windreamSearchList.focusedEntityShadowed.isNew)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Löschen"
|
||||
(click)=windreamSearchList.focusedEntityShadowed.delete();
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !departmentDetails.entityIsLoading
|
||||
&& !windreamSearchList.focusedEntityShadowed.isNew
|
||||
&& windreamSearchList.focusedEntityShadowed.enabledDeleteButton())">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Vorrücken"
|
||||
(click)="departmentDataService.moveUpDown(-1, windreamSearchList)"
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !departmentDetails.entityIsLoading
|
||||
&& !windreamSearchList.focusedEntityShadowed.isNew
|
||||
&& windreamSearchList.focusedItemIndex>0)">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Hinterrücken" class="toolbar-button-last"
|
||||
(click)="departmentDataService.moveUpDown(1, windreamSearchList)"
|
||||
[disabled]="!(departmentDetails.inEditMode
|
||||
&& !departmentDetails.entityIsLoading
|
||||
&& !windreamSearchList.focusedEntityShadowed.isNew
|
||||
&& windreamSearchList.focusedItemIndex<windreamSearchList.items.length-1)">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<dx-data-grid
|
||||
name="windreamSearchGrid"
|
||||
[class]="'grid'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="windreamSearchList.items"
|
||||
keyExpr="entityId"
|
||||
[(focusedRowIndex)]=windreamSearchList.focusedItemGridIndex
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowKey)]="windreamSearchList.focusedItemId"
|
||||
[(selectedRowKeys)]="windreamSearchList.selectedItemIds"
|
||||
[showBorders]="true"
|
||||
[allowColumnResizing]="true"
|
||||
columnResizingMode="widget"
|
||||
noDataText="Keine Daten sind vorhanden"
|
||||
[renderAsync]="true"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'"
|
||||
(onExporting)="globals.doExcelExportSimple($event, windreamSearchList.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<dxo-header-filter [visible]="true"></dxo-header-filter> -->
|
||||
<dxo-filter-row [visible]="false" [applyFilter]="true"></dxo-filter-row>
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple"></dxo-sorting>
|
||||
<dxo-selection mode="none"></dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf="column.visible">
|
||||
<dxi-column [allowHeaderFiltering]=column.allowHeaderFiltering [dataField]=column.dataField
|
||||
[dataType]=column.dataType [caption]=column.caption [width]=column.width
|
||||
[sortIndex]=column.sortIndex [sortOrder]=column.sortOrder [visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible [fixed]=column.fixed [headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate [allowSorting]=column.allowSorting
|
||||
[calculateCellValue]=column.calculateCellValue [calculateDisplayValue]=column.calculateDisplayValue
|
||||
[calculateGroupValue]=column.calculateGroupValue [calculateSortValue]=column.calculateSortValue
|
||||
[alignment]=column.alignment>
|
||||
<dxo-format *ngIf="column.dataType == 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType == 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<div *dxTemplate="let cell of 'checkbox_template'">
|
||||
<mat-checkbox #checkbox [checked]="cell.value"
|
||||
(click)="changeKeyWS(cell.data)"
|
||||
[disabled]="!departmentDetails.inEditMode"></mat-checkbox>
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</div>
|
||||
@ -0,0 +1,23 @@
|
||||
.department-windreamsearch {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas: "label label" "toolbar grid";
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-area: grid;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
// padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DepartmentWindreamSearchComponent } from './department-windream-search.component';
|
||||
|
||||
describe('DepartmentWindreamSearchComponent', () => {
|
||||
let component: DepartmentWindreamSearchComponent;
|
||||
let fixture: ComponentFixture<DepartmentWindreamSearchComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DepartmentWindreamSearchComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DepartmentWindreamSearchComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,121 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { EN_AppEntities } from '@app_consts';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { DepartmentWindreamSearchPopupeditComponent } from './department-windream-search-popupedit/department-windream-search-popupedit.component';
|
||||
import { SelectDepartmentPopupComponent } from './select-department-popup/select-department-popup.component';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { MatDialogService } from '@app_core/services/mat-dialog.service';
|
||||
import { RepositoryService } from '@app_core/services/http/repository.service';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-windream-search',
|
||||
templateUrl: './department-windream-search.component.html',
|
||||
styleUrls: ['./department-windream-search.component.scss']
|
||||
})
|
||||
export class DepartmentWindreamSearchComponent implements OnInit {
|
||||
|
||||
@Input() windreamSearchList: AppBaseEntityListWrapper<WindreamSearchToDepartment>;
|
||||
@Input() departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialogService,
|
||||
public departmentDataService: DepartmentDataService,
|
||||
public repoService: RepositoryService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
col = this.columnConfigList.addNumber('Seq.', 'seq', 2);
|
||||
col.sortIndex = 0;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
col = this.columnConfigList.add('Suche Kachel', 'windreamSearchName', 10);
|
||||
col = this.columnConfigList.addBoolean('Active', 'isActive', 2);
|
||||
col.cellTemplate = 'checkbox_template';
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
addItem() {
|
||||
this.windreamSearchList.focusedEntityShadowed.new();
|
||||
this.windreamSearchList.focusedEntityShadowed.entity.departmentId = this.departmentDetails.entityId;
|
||||
this.openPopupDialog(this.windreamSearchList.focusedEntityShadowed);
|
||||
}
|
||||
|
||||
public openPopupDialog(editEntity: AppBaseEntityWrapper<WindreamSearchToDepartment>) {
|
||||
this.departmentDetails.keyDownListenerStopped = true;
|
||||
this.dialog.openDialog(DepartmentWindreamSearchPopupeditComponent, {
|
||||
baseEntityWrapper: editEntity,
|
||||
keyItemName: this.departmentDetails.entity.departmentName,
|
||||
readOnly: !this.departmentDetails.inEditMode,
|
||||
description: editEntity.entity.entitytitle + (editEntity.entity.entityId === 0 ? ' zuweisen' : ' bearbeiten '),
|
||||
list: this.windreamSearchList,
|
||||
}, true, () => this.departmentDetails.keyDownListenerStopped = false);
|
||||
}
|
||||
|
||||
|
||||
public get nameOfDepartment(): string {
|
||||
return this.departmentDetails.entity.departmentName;
|
||||
}
|
||||
|
||||
|
||||
public changeKeyWS(wsTD: WindreamSearchToDepartment) {
|
||||
if (this.departmentDetails.inEditMode) {
|
||||
wsTD.isActive = !wsTD.isActive;
|
||||
wsTD.entityChanged = true;
|
||||
wsTD.save(this.repoService, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public copyAllTiles() {
|
||||
this.openSelectDepartmentsPopup(`Wählen Sie Abteilungen, bei welchen alle Suchkacheln von Suchkacheln aus "${this.departmentDetails.entity.departmentName}" ersetzt werden sollen`
|
||||
, 'content_copy'
|
||||
, (depIds: number[]) => {
|
||||
this.repoService.putDataById(EN_AppEntities.DepartmentCopyWindreamTiles, this.departmentDetails.entityId, depIds).subscribe(
|
||||
() => this.departmentDetails.informationMessageBox('Kopieren von Suchkacheln', `Die Suchkacheln aus "${this.departmentDetails.entity.departmentName}" haben Suchkacheln aus den ausgewählten Abteilungen erfolgreich ersetzt`)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public copyCurrentTile() {
|
||||
this.openSelectDepartmentsPopup(`Wählen Sie Abteilungen, für welche die Suchkachel "${this.windreamSearchList.focusedItem.windreamSearchName}" aus "${this.departmentDetails.entity.departmentName}" hinzugefügt werden soll`
|
||||
, 'content_copy'
|
||||
, (depIds: number[]) => {
|
||||
this.repoService.putDataById(EN_AppEntities.WindreamSearchToDepartmentCopyWindreamTile, this.windreamSearchList.focusedItemId, depIds).subscribe(
|
||||
() => this.departmentDetails.informationMessageBox('Kopieren von Suchkacheln', `Die Suchkachel "${this.windreamSearchList.focusedItem.windreamSearchName}" aus "${this.departmentDetails.entity.departmentName}" wurde zu den ausgewählten Abteilungen erfolgreich hinzugefügt`)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public openSelectDepartmentsPopup(text: string, iconanme: string, callBack: (depIds: number[]) => void) {
|
||||
this.departmentDetails.keyDownListenerStopped = true;
|
||||
this.dialog.openDialog(SelectDepartmentPopupComponent
|
||||
, { text: text, iconanme: iconanme }
|
||||
, true
|
||||
, (result) => {
|
||||
if (result && callBack) callBack(result);
|
||||
this.departmentDetails.keyDownListenerStopped = false;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<form class="PopupContainer" #popupForm="ngForm">
|
||||
<h3 mat-dialog-title class="messageBoxHeader">
|
||||
<mat-icon>{{iconanme}}</mat-icon>
|
||||
Windreameinstellungen übernehmen
|
||||
</h3>
|
||||
<div class="text">
|
||||
{{text}}
|
||||
</div>
|
||||
|
||||
<mat-dialog-content class="PopupContent">
|
||||
<div class="buttons">
|
||||
<button id="btnSave" name="btnSave" class="btnSave" mat-stroked-button
|
||||
[disabled]="selectedDepartments.length === 0"
|
||||
[mat-dialog-close]="selectedDepartments">
|
||||
<mat-icon>save</mat-icon> Übernehmen
|
||||
</button>
|
||||
<button #btnCancel id="btnCancel" name="btnCancel" class="btnCancel" mat-stroked-button
|
||||
[mat-dialog-close]="">
|
||||
<mat-icon>cancel</mat-icon> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hensel-selection
|
||||
#input_windreamSearch
|
||||
id="input-departments"
|
||||
class="input-departments"
|
||||
[dataSource]=departmentDataService.departmentList.items
|
||||
placeholder="Windream Search Kachel"
|
||||
keyExpr="entityId"
|
||||
displayExpr="departmentName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="selectedDepartments"
|
||||
[customFilter]="'entityId != ' + departmentDataService.departmentList.focusedItemId"
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
</mat-dialog-content>
|
||||
</form>
|
||||
@ -0,0 +1,21 @@
|
||||
@import 'popup-base.component';
|
||||
|
||||
.PopupContent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid: ;
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto auto auto; // row relationships
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship
|
||||
grid-column-gap: 15px;
|
||||
grid-row-gap: 15px;
|
||||
grid-template-areas:
|
||||
'text text'
|
||||
'input-departments input-departments'
|
||||
'buttons buttons'
|
||||
}
|
||||
|
||||
.input-departments {
|
||||
grid-area: input-departments;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@app_core/components/angular-material-index';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-select-department-popup',
|
||||
templateUrl: './select-department-popup.component.html',
|
||||
styleUrls: [ './select-department-popup.component.scss']
|
||||
})
|
||||
|
||||
export class SelectDepartmentPopupComponent {
|
||||
|
||||
public selectedDepartments: number[] = [];
|
||||
public text: string;
|
||||
public iconanme: string;
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
@Inject(MAT_DIALOG_DATA) data: any
|
||||
) {
|
||||
this.text = data.text;
|
||||
this.iconanme = data.iconanme;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
<mat-card class="card">
|
||||
<mat-card-header>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="filterCardContainer">
|
||||
|
||||
<hensel-input class="filterDepartment"
|
||||
placeholder="Abteilung"
|
||||
[(ngModel)]=filterObject.departmentName
|
||||
(keyup.Enter)="onFilterClick()">
|
||||
</hensel-input>
|
||||
|
||||
<section class="filterButtons">
|
||||
<button id="filterBtnClear" class="filterBtn" mat-stroked-button (click)=onClearClick() title="Reset">
|
||||
<mat-icon>clear</mat-icon><span class="btn-lable-show"> Reset</span>
|
||||
</button>
|
||||
|
||||
<button id="filterBtnFind" class="filterBtn" mat-stroked-button (click)=onFilterClick() title="Suchen">
|
||||
<mat-icon>search</mat-icon><span class="btn-lable-show"> Suchen</span>
|
||||
</button>
|
||||
|
||||
</section>
|
||||
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@ -0,0 +1,49 @@
|
||||
.filterCardContainer {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-column-gap: 15px;
|
||||
grid-template-rows: repeat(1, auto); // row relationships
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr)) auto; // column relationship
|
||||
grid-template-areas:
|
||||
"filterDepartment . . . . filterButtons"
|
||||
}
|
||||
|
||||
// @media screen and (max-width:1024px) {
|
||||
// .woassays {
|
||||
// font-size: 1vw;
|
||||
// }
|
||||
// }
|
||||
|
||||
.filterDepartment {
|
||||
grid-area: filterDepartment;
|
||||
}
|
||||
|
||||
.filterButtons {
|
||||
grid-area: filterButtons;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
// .filterBtn {
|
||||
// font-size: 1vw; //scales buttons caption depended from the current view port resolution
|
||||
// }
|
||||
|
||||
.card {
|
||||
padding: 10px;
|
||||
margin: 2px 2px 0px 2px;
|
||||
}
|
||||
|
||||
.filterBtn {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
margin-right: 1px;
|
||||
margin-top: 6px;
|
||||
width: 90px;
|
||||
}
|
||||
|
||||
// .filterButtons .filterBtn {
|
||||
// width: unset;
|
||||
// }
|
||||
@ -0,0 +1,61 @@
|
||||
import * as keycode from '@angular/cdk/keycodes';
|
||||
import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core';
|
||||
import { Department, DepartmentFilter } from '@app_models/basedata/department';
|
||||
import { DepartmentDataService } from '@app_modules/department/department-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import * as Cnst from '@app_core/consts';
|
||||
import { AuthorizeService } from '@app_core/services/authorize.service';
|
||||
import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-filter',
|
||||
templateUrl: './department-filter.component.html',
|
||||
styleUrls: ['./department-filter.component.scss'],
|
||||
})
|
||||
|
||||
export class DepartmentFilterComponent implements OnInit, AfterViewInit {
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
public appDataService: AppDataService,
|
||||
public authService: AuthorizeService,
|
||||
) { }
|
||||
@Input() public filterObject: DepartmentFilter;
|
||||
@Input() departmentDetails: AppBaseEntityWrapper<Department>;
|
||||
@Output() public filterFetch = new EventEmitter();
|
||||
|
||||
public dropDownAllCaption = Cnst.EN_DropDownConst4Filter.AllCaption;
|
||||
public dropDownAllValueString = Cnst.EN_DropDownConst4Filter.AllValueString;
|
||||
public dropDownAllValueInt = Cnst.EN_DropDownConst4Filter.AllValueInt;
|
||||
public allCaption = Cnst.EN_DropDownConst4Filter.AllCaption;
|
||||
public allValue: number = Cnst.EN_DropDownConst4Filter.AllValueInt;
|
||||
public noneCaption = Cnst.EN_DropDownConst4Filter.NoneCaption;
|
||||
public noneValue = Cnst.EN_DropDownConst4Filter.NoneValueInt;
|
||||
|
||||
ngOnInit() { }
|
||||
ngAfterViewInit() { }
|
||||
onFilterClick() {
|
||||
if (this.departmentDetails.inViewMode) this.filterFetch.emit();
|
||||
}
|
||||
onClearClick() {
|
||||
this.filterObject.filterReset();
|
||||
}
|
||||
|
||||
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
keyboardInput(event: any) {
|
||||
if (!LoginPopupComponent.LOGIN_IS_SHOWN && !this.departmentDetails.keyDownListenerStopped) {
|
||||
if (event.ctrlKey) {
|
||||
switch (event.which) {
|
||||
case keycode.F: //Ctrl + 'f'
|
||||
event.stopPropagation();
|
||||
this.onFilterClick();
|
||||
return false; //processed
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; //default processing
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
<div class="DepartmentList">
|
||||
<app-department-filter class="FilterComponent"
|
||||
[departmentDetails]=this.departmentDataService.departmentDetails
|
||||
[filterObject]=dataSource.filter
|
||||
(filterFetch)="loadData()">
|
||||
</app-department-filter>
|
||||
|
||||
<mat-card class="card">
|
||||
<mat-card-header>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<dx-data-grid
|
||||
#gridDepartment
|
||||
id="gridDepartment"
|
||||
[class]="'gridDepartment'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="dataSource.items"
|
||||
keyExpr="departmentId"
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowIndex)]=dataSource.focusedItemGridIndex
|
||||
[(focusedRowKey)]="dataSource.focusedItemId"
|
||||
[(selectedRowKeys)]="dataSource.selectedItemIds"
|
||||
[showBorders]="true"
|
||||
[allowColumnResizing]="true"
|
||||
columnResizingMode="nextColumn"
|
||||
noDataText="Keine Daten vorhanden"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'; dataSource.gridUpDownProcessing($event)"
|
||||
(onFocusedRowChanging)="dataSource.onFocusedRowChanging($event)"
|
||||
(onRowDblClick)="dataSource.focusedEntityShadowed.delayedEdit($event.data['entityId'])"
|
||||
(onExporting)="globals.doExcelExportSimple($event, dataSource.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<dxo-header-filter [visible]="true"></dxo-header-filter>
|
||||
<!-- <dxo-filter-row [visible]="true" [applyFilter]="true"></dxo-filter-row> -->
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple">
|
||||
<!--"single" | "multiple" | "none" -->
|
||||
</dxo-sorting>
|
||||
<dxo-selection mode="none">
|
||||
<!-- "multiple" | "none" -->
|
||||
</dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf=column.visible>
|
||||
<dxi-column
|
||||
[allowHeaderFiltering]=column.allowHeaderFiltering
|
||||
[dataField]=column.dataField
|
||||
[dataType]=column.dataType
|
||||
[caption]=column.caption
|
||||
[width]=column.width
|
||||
[sortIndex]=column.sortIndex
|
||||
[sortOrder]=column.sortOrder
|
||||
[visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible
|
||||
[fixed]=column.fixed
|
||||
[headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate
|
||||
[alignment]=column.alignment>
|
||||
<!-- cssClass="headeralignment_center" -->
|
||||
|
||||
<dxo-format *ngIf="column.dataType === 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType === 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
<dxo-lookup *ngIf="column.dataField === 'rangId'" [dataSource]="appDataService.rangList?.items" valueExpr="entityId" displayExpr="rangShortname"></dxo-lookup>
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div *ngIf="this.departmentDataService.departmentDetails.inNotViewMode" class="disableClicks"></div>
|
||||
</div>
|
||||
@ -0,0 +1,39 @@
|
||||
.DepartmentList {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto minmax(0, 1fr); // row relationships
|
||||
grid-template-columns: minmax(0, 1fr); // column relationship
|
||||
grid-row-gap: 7px;
|
||||
grid-template-areas:
|
||||
'filter'
|
||||
'grid';
|
||||
}
|
||||
|
||||
|
||||
.FilterComponent {
|
||||
grid-area: filter; // grid area: auto height 1fr width
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
.card {
|
||||
grid-area: grid;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
margin: 0;
|
||||
border-radius: 0px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.gridDepartment {
|
||||
position: absolute; // position absolut ist hier zwingend! Die position ist absolut innerhalb mehrerer parent divs und darf sich NICHT über diese hinausstrecken.
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { DepartmentDataService } from '../department-data.service';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department-list',
|
||||
templateUrl: './department-list.component.html',
|
||||
styleUrls: ['./department-list.component.scss']
|
||||
})
|
||||
export class DepartmentListComponent implements OnInit {
|
||||
@Input() public dataSource: AppBaseEntityListWrapper<Department>;
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService,
|
||||
public appDataService: AppDataService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
col = this.columnConfigList.addNumber('Id', 'departmentId', 5);
|
||||
col = this.columnConfigList.add('Name', 'departmentName', 13);
|
||||
col.sortIndex = 0;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
col.allowHeaderFiltering = true;
|
||||
col = this.columnConfigList.addNumber('Typ Id', 'departmentTypeId', 5);
|
||||
col = this.columnConfigList.addNumber('CostCentre Id', 'costCentreId', 5);
|
||||
col = this.columnConfigList.add('CostCentre', 'costCentre', 10);
|
||||
col = this.columnConfigList.add('Abteilungsleiter', 'headofDepartment', 18);
|
||||
col = this.columnConfigList.add('CEO', 'executiveDirector', 18);
|
||||
col = this.columnConfigList.add('COO', 'managingDirector', 18);
|
||||
col = this.columnConfigList.add('Folder', 'departmentNameFolder', 13);
|
||||
col = this.columnConfigList.add('AD-Group Name', 'adGroupDepartmentName', 13);
|
||||
col = this.columnConfigList.addNumber('Client Id', 'clientId', 5);
|
||||
col = this.columnConfigList.addBoolean('Virtual', 'isVirtual', 2);
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
|
||||
public loadData() {
|
||||
this.departmentDataService.loadData();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
<div class="DepartmentComponent">
|
||||
<app-department-list
|
||||
[dataSource]=departmentDataService.departmentList class="DepartmentListComponent"></app-department-list>
|
||||
<app-department-detail
|
||||
[departmentDetails]="departmentDataService.departmentList.focusedEntityShadowed"
|
||||
class="DepartmentDetailsComponent"></app-department-detail>
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
.DepartmentComponent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: minmax(0, 1fr) auto; // row relationships
|
||||
grid-template-columns: minmax(0, 1fr); // column relationship
|
||||
grid-template-areas: 'list''details';
|
||||
grid-column-gap: 5px;
|
||||
grid-row-gap: 5px;
|
||||
}
|
||||
|
||||
.DepartmentListComponent {
|
||||
grid-area: list;
|
||||
}
|
||||
|
||||
.DepartmentDetailsComponent {
|
||||
grid-area: details;
|
||||
z-index: 10;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { DepartmentDataService } from './department-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-department',
|
||||
templateUrl: './department.component.html',
|
||||
styleUrls: ['./department.component.scss']
|
||||
})
|
||||
export class DepartmentComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
public departmentDataService: DepartmentDataService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { AngularMaterialModule } from '@app_core/components/angular-material.module';
|
||||
import { DxButtonModule, DxDataGridModule, DxFileUploaderModule, DxPieChartModule, DxTemplateModule, DxTooltipModule } from 'devextreme-angular';
|
||||
import { DepartmentContentComponent } from './department-detail/department-content/department-content.component';
|
||||
import { DepartmentDetailComponent } from './department-detail/department-detail.component';
|
||||
import { DepartmentDocumentartsComponent as DepartmentDocumentArtComponent } from './department-detail/department-documentart/department-documentart.component';
|
||||
import { DepartmentWindreamIndexPopupeditComponent } from './department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component';
|
||||
import { DepartmentWindreamIndexComponent } from './department-detail/department-windream-index/department-windream-index.component';
|
||||
import { DepartmentWindreamSearchItemPopupeditComponent } from './department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component';
|
||||
import { DepartmentWindreamSearchItemComponent } from './department-detail/department-windream-search-item/department-windream-search-item.component';
|
||||
import { DepartmentWindreamSearchPopupeditComponent } from './department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component';
|
||||
import { DepartmentWindreamSearchComponent } from './department-detail/department-windream-search/department-windream-search.component';
|
||||
import { SelectDepartmentPopupComponent } from './department-detail/department-windream-search/select-department-popup/select-department-popup.component';
|
||||
import { DepartmentFilterComponent } from './department-list/department-filter/department-filter.component';
|
||||
import { DepartmentListComponent } from './department-list/department-list.component';
|
||||
import { DepartmentComponent } from './department.component';
|
||||
import { DepartmentRoutingModule } from './department.routing.module';
|
||||
import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component';
|
||||
import { HenselInputComponent } from '@app_core/components/hensel-input/hensel-input.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DepartmentComponent,
|
||||
DepartmentListComponent,
|
||||
DepartmentDetailComponent,
|
||||
DepartmentFilterComponent,
|
||||
DepartmentContentComponent,
|
||||
DepartmentWindreamSearchComponent,
|
||||
DepartmentWindreamSearchPopupeditComponent,
|
||||
DepartmentWindreamSearchItemComponent,
|
||||
DepartmentWindreamSearchItemPopupeditComponent,
|
||||
DepartmentWindreamIndexComponent,
|
||||
DepartmentDocumentArtComponent,
|
||||
DepartmentWindreamIndexPopupeditComponent,
|
||||
SelectDepartmentPopupComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
DepartmentRoutingModule,
|
||||
AngularMaterialModule,
|
||||
DxDataGridModule,
|
||||
FormsModule,
|
||||
HenselSelectionComponent,
|
||||
HenselInputComponent,
|
||||
DxFileUploaderModule,
|
||||
DxButtonModule,
|
||||
DxTooltipModule,
|
||||
DxTemplateModule,
|
||||
DxPieChartModule,
|
||||
],
|
||||
providers: [],
|
||||
exports: []
|
||||
})
|
||||
export class DepartmentModule { }
|
||||
@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { DepartmentComponent } from './department.component';
|
||||
import { AuthGuard } from '@app_core/services/authguard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '**',
|
||||
component: DepartmentComponent,
|
||||
canActivate: [AuthGuard]
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DepartmentRoutingModule { }
|
||||
160
ClientApp/staff-db-ui/src/app/modules/employee/Page1.drawio
Normal file
160
ClientApp/staff-db-ui/src/app/modules/employee/Page1.drawio
Normal file
@ -0,0 +1,160 @@
|
||||
<mxfile host="65bd71144e" modified="2021-02-03T15:01:50.644Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.52.1 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36" etag="vABciugGmu_biFYYDpc-" version="13.10.0" type="embed" pages="2">
|
||||
<diagram id="crlGuFxm3afBVpfyN98v" name="Page-1">
|
||||
<mxGraphModel dx="3633" dy="1330" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0">
|
||||
<root>
|
||||
<object label="" id="0">
|
||||
<mxCell/>
|
||||
</object>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-87" value="Filter" parent="0"/>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-177" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-87" vertex="1">
|
||||
<mxGeometry x="-1900" y="30" width="1260" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-178" value="Filer" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="5" width="60" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-175" value="Name" style="text;fontSize=16;verticalAlign=middle;strokeColor=none;fillColor=none;opacity=50;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="10" y="30" width="120" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-179" value="Shortname" style="text;fontSize=16;verticalAlign=middle;strokeColor=none;fillColor=none;opacity=50;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="150" y="30" width="120" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-180" value="Login" style="text;fontSize=16;verticalAlign=middle;strokeColor=none;fillColor=none;opacity=50;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="280" y="30" width="120" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-181" value="Department" style="text;fontSize=16;verticalAlign=middle;strokeColor=none;fillColor=none;opacity=50;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="400" y="30" width="120" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-239" value="EmployeeId (Admin)" style="text;fontSize=16;verticalAlign=middle;opacity=50;glass=0;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="990" y="30" width="120" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="35" value="" style="html=1;strokeWidth=2;shadow=0;dashed=0;shape=mxgraph.ios7ui.selectBar;dx=120;dy=5;dx2=101.43;size=5;fontSize=20;" parent="LfnUcp3E9milZ3mwyznO-177" vertex="1">
|
||||
<mxGeometry x="740" y="27.75" width="215" height="34.5" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="36" value="Zusatzinfo" style="shape=rect;fillColor=none;strokeColor=none;fontSize=15;fontFamily=Helvetica;perimeter=none;resizeHeight=1;" parent="35" vertex="1">
|
||||
<mxGeometry width="95" height="49.03" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="37" value="Select" style="shape=rect;fillColor=none;strokeColor=none;fontSize=12;fontFamily=Helvetica;perimeter=none;resizeHeight=1;" parent="35" vertex="1">
|
||||
<mxGeometry width="75" height="49.026315789473685" relative="1" as="geometry">
|
||||
<mxPoint x="100" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="-TWQrLLDEwFAn9kzfAeb-19" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-87" vertex="1">
|
||||
<mxGeometry x="-670" y="670" width="300" height="470" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="-TWQrLLDEwFAn9kzfAeb-20" value="WebApp-List" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="-TWQrLLDEwFAn9kzfAeb-19" vertex="1">
|
||||
<mxGeometry x="5" width="120" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<object label="WebAppId WebAppName Rolle" placeholders="1" id="-TWQrLLDEwFAn9kzfAeb-21">
|
||||
<mxCell style="rounded=1;arcSize=10;dashed=1;fillColor=none;dashPattern=8 3 1 3;strokeWidth=2;glass=0;fontSize=18;" parent="-TWQrLLDEwFAn9kzfAeb-19" vertex="1">
|
||||
<mxGeometry x="20" y="40" width="270" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</object>
|
||||
<mxCell id="1" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-87" vertex="1">
|
||||
<mxGeometry x="-350" y="670" width="300" height="470" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="2" value="Merkmale" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="5" width="100" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<object label="MerkmalId Merkmal" placeholders="1" id="3">
|
||||
<mxCell style="rounded=1;arcSize=10;dashed=1;fillColor=none;dashPattern=8 3 1 3;strokeWidth=2;glass=0;fontSize=18;" parent="1" vertex="1">
|
||||
<mxGeometry x="20" y="40" width="270" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</object>
|
||||
<mxCell id="39" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-87" vertex="1">
|
||||
<mxGeometry x="-630" y="30" width="540" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="Merkmal Administration" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="39" vertex="1">
|
||||
<mxGeometry x="5" width="200" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="" style="html=1;strokeWidth=2;shadow=0;dashed=0;shape=mxgraph.ios7ui.selectBar;dx=120;dy=5;dx2=101.43;size=5;fontSize=20;" parent="39" vertex="1">
|
||||
<mxGeometry x="20" y="30" width="215" height="34.5" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="Merkmal" style="shape=rect;fillColor=none;strokeColor=none;fontSize=15;fontFamily=Helvetica;perimeter=none;resizeHeight=1;" parent="46" vertex="1">
|
||||
<mxGeometry width="95" height="49.03" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="Select" style="shape=rect;fillColor=none;strokeColor=none;fontSize=12;fontFamily=Helvetica;perimeter=none;resizeHeight=1;" parent="46" vertex="1">
|
||||
<mxGeometry width="75" height="49.026315789473685" relative="1" as="geometry">
|
||||
<mxPoint x="100" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="Bearbeiten" style="rounded=1;html=1;shadow=0;dashed=0;whiteSpace=wrap;fontSize=18;align=center;sketch=0;" parent="39" vertex="1">
|
||||
<mxGeometry x="270" y="31.56" width="105.5" height="28.44" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="Speichern" style="rounded=1;html=1;shadow=0;dashed=0;whiteSpace=wrap;fontSize=18;align=center;sketch=0;" parent="39" vertex="1">
|
||||
<mxGeometry x="390" y="33.03" width="105.5" height="28.44" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value=" <div style="color: rgb(212, 212, 212); background-color: rgb(30, 30, 30); font-family: consolas, &quot;courier new&quot;, monospace; font-weight: normal; font-size: 14px; line-height: 19px;"><div><span style="color: #9cdcfe">grid-area</span><span style="color: #d4d4d4">:</span></div></div> " style="text;whiteSpace=wrap;html=1;" vertex="1" parent="LfnUcp3E9milZ3mwyznO-87">
|
||||
<mxGeometry x="-1910" y="10" width="100" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-182" value="Lists" parent="0"/>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-184" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-182" vertex="1">
|
||||
<mxGeometry x="-1880" y="140" width="1830" height="470" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-185" value="Employee-List" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="LfnUcp3E9milZ3mwyznO-184" vertex="1">
|
||||
<mxGeometry x="5" width="130" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="LfnUcp3E9milZ3mwyznO-196" value="EmployeeId (Admin)" style="text;fontSize=16;verticalAlign=middle;opacity=50;" parent="LfnUcp3E9milZ3mwyznO-184" vertex="1">
|
||||
<mxGeometry x="10" y="30" width="90" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<object label="EmployeeNo	Salutation	FirstName	LastName	ShortName	Position	LoginName	Email	Rang	ClientId" placeholders="1" id="LfnUcp3E9milZ3mwyznO-246">
|
||||
<mxCell style="rounded=1;arcSize=10;dashed=1;fillColor=none;dashPattern=8 3 1 3;strokeWidth=2;glass=0;fontSize=23;" parent="LfnUcp3E9milZ3mwyznO-184" vertex="1">
|
||||
<mxGeometry x="30" y="60" width="1160" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</object>
|
||||
<mxCell id="4" value="" style="verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.tick;fontSize=18;" parent="LfnUcp3E9milZ3mwyznO-184" vertex="1">
|
||||
<mxGeometry x="10" y="140" width="30" height="20" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="6" value="" style="verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.tick;fontSize=18;" parent="LfnUcp3E9milZ3mwyznO-184" vertex="1">
|
||||
<mxGeometry x="10" y="170" width="30" height="20" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="31" value="" style="html=1;aspect=fixed;strokeColor=none;shadow=0;align=center;verticalAlign=top;shape=mxgraph.gcp2.view_list;fontSize=18;" parent="LfnUcp3E9milZ3mwyznO-184" vertex="1">
|
||||
<mxGeometry x="40" y="130" width="110" height="137.5" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="VQwmF7H8NuOuIEITXOnG-4" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-182" vertex="1">
|
||||
<mxGeometry x="-1900" y="670" width="860" height="460" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="VQwmF7H8NuOuIEITXOnG-5" value="Employee-Details" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="VQwmF7H8NuOuIEITXOnG-4" vertex="1">
|
||||
<mxGeometry x="5" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<object label="" placeholders="1" id="VQwmF7H8NuOuIEITXOnG-7">
|
||||
<mxCell style="rounded=1;arcSize=10;dashed=1;fillColor=none;dashPattern=8 3 1 3;strokeWidth=2;glass=0;fontSize=23;" parent="VQwmF7H8NuOuIEITXOnG-4" vertex="1">
|
||||
<mxGeometry x="20" y="60" width="360" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</object>
|
||||
<mxCell id="-TWQrLLDEwFAn9kzfAeb-5" value="" style="shape=mxgraph.mockup.containers.marginRect;rectMarginTop=10;strokeWidth=1;dashed=0;arcSize=5;recursiveResize=0;" parent="LfnUcp3E9milZ3mwyznO-182" vertex="1">
|
||||
<mxGeometry x="-1040" y="670" width="360" height="470" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="-TWQrLLDEwFAn9kzfAeb-6" value="Department-List" style="shape=rect;strokeColor=none;strokeWidth=1;dashed=0;arcSize=20;fontSize=17;spacing=2;spacingTop=-2;align=left;autosize=1;spacingLeft=4;resizeWidth=0;resizeHeight=0;perimeter=none;" parent="-TWQrLLDEwFAn9kzfAeb-5" vertex="1">
|
||||
<mxGeometry x="5" width="140" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<object label="DepartmentId DepartmentName Rang" placeholders="1" id="-TWQrLLDEwFAn9kzfAeb-7">
|
||||
<mxCell style="rounded=1;arcSize=10;dashed=1;fillColor=none;dashPattern=8 3 1 3;strokeWidth=2;glass=0;fontSize=18;" parent="-TWQrLLDEwFAn9kzfAeb-5" vertex="1">
|
||||
<mxGeometry x="20" y="40" width="330" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</object>
|
||||
<mxCell id="-TWQrLLDEwFAn9kzfAeb-18" value="Details" parent="0"/>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
<diagram id="xSUcNyafCY5EnCSOazaM" name="Page-2">
|
||||

 


|
||||
<mxGraphModel dx="1376" dy="910" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||

 


|
||||
<root>
|
||||

 


|
||||
<mxCell id="ewFg04713mjC0kNU1MT--0"/>
|
||||

 


|
||||
<mxCell id="ewFg04713mjC0kNU1MT--1" parent="ewFg04713mjC0kNU1MT--0"/>
|
||||

 


|
||||
<mxCell id="AtFcv4WY-9kmqpDSp6Za-0" value="" style="shape=mxgraph.cisco.misc.page_icon;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;rounded=0;sketch=0;fontColor=#1A1A1A;" vertex="1" parent="ewFg04713mjC0kNU1MT--1">
|
||||

 


|
||||
<mxGeometry x="70" y="160" width="170" height="190" as="geometry"/>
|
||||

 


|
||||
</mxCell>
|
||||

 


|
||||
</root>
|
||||

 


|
||||
</mxGraphModel>
|
||||

 


|
||||
</diagram>
|
||||
</mxfile>
|
||||
@ -0,0 +1,167 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { cnst_LoadedEntitiesExpiresInMs, EN_AppEntities, EN_AppPages, EN_HttpQueriesCount4Page } from '@app_consts';
|
||||
import { EN_EntityBeforeSaveCallBackResults } from '@app_core/consts';
|
||||
import { CoreUser } from '@app_core/models/coreuser';
|
||||
import { RepositoryService } from '@app_core/services/http/repository.service';
|
||||
import { UINotifierService } from '@app_core/services/notification/uinotifier.service';
|
||||
import { CorePageService } from '@app_core/services/page.service';
|
||||
import { Employee, EmployeeFilter, EmployeeFullFilter } from '@app_models/employee';
|
||||
import { EmployeeToAttribute } from '@app_models/employee-to-attribute';
|
||||
import { EmployeeToDepartment } from '@app_models/employee-to-department';
|
||||
import { EmployeeToWebApp } from '@app_models/employee-to-webapp';
|
||||
import { AppBaseEntity } from '@app_models/generic/app.baseentity';
|
||||
|
||||
import { User } from '@app_models/user';
|
||||
import { EmployeeToWebAppFilter, WebAppToDepartment } from '@app_models/webapp-to-department';
|
||||
import { WebAppToWebAppAdditionalRole } from '@app_models/webapp-to-webappadditionalrole';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { AppBaseEntityCallBack } from 'src/app/shared/app.types';
|
||||
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
|
||||
export class EmployeeDataService extends CorePageService {
|
||||
protected appPage: EN_AppPages = EN_AppPages.Employee;
|
||||
protected get appPageNoQueries() { return EN_HttpQueriesCount4Page.Employee; }
|
||||
|
||||
// --- running data
|
||||
employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
employeeList: AppBaseEntityListWrapper<Employee> = new AppBaseEntityListWrapper<Employee>(Employee, 'Mitarbeiterliste', EN_AppEntities.Employee);
|
||||
employeeFilter: EmployeeFullFilter = new EmployeeFullFilter('EmployeeFullFilter');
|
||||
employee2AllFilter: EmployeeFilter = new EmployeeFilter('EmployeeFilter');
|
||||
|
||||
employee2DepartmentList: AppBaseEntityListWrapper<EmployeeToDepartment> = new AppBaseEntityListWrapper<EmployeeToDepartment>(EmployeeToDepartment, 'Abteilungen von Mitarbeiter', EN_AppEntities.EmployeeToDepartment);
|
||||
|
||||
employee2WebAppList: AppBaseEntityListWrapper<EmployeeToWebApp> = new AppBaseEntityListWrapper<EmployeeToWebApp>(EmployeeToWebApp, 'Applikationen von Mitarbeiter', EN_AppEntities.EmployeeToWebapp);
|
||||
|
||||
employee2AttributeList: AppBaseEntityListWrapper<EmployeeToAttribute> = new AppBaseEntityListWrapper<EmployeeToAttribute>(EmployeeToAttribute, 'Merkmale von Mitarbeiter', EN_AppEntities.EmployeeToAttribute);
|
||||
|
||||
constructor(
|
||||
private appDataService: AppDataService,
|
||||
private repositoryService: RepositoryService,
|
||||
protected uiNotificationsService: UINotifierService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.employeeList.alwaysFocused = true;
|
||||
this.employeeList.focusedCallBack = this.focusCallBack.bind(this);
|
||||
this.employeeList.filter = this.employeeFilter;
|
||||
|
||||
this.employeeDetails = this.employeeList.createFocusedShadowEntity(AppBaseEntityWrapper.EN_ViewMode);
|
||||
this.employeeDetails.loadedDataExpiresInMs = cnst_LoadedEntitiesExpiresInMs;
|
||||
|
||||
this.activateRouting4EntityList(this.employeeList); //we are using routing
|
||||
this.baseEntityWrapperWaitLoading = this.employeeDetails;
|
||||
|
||||
this.prepareDetailsList(this.employee2DepartmentList);
|
||||
this.prepareDetailsList(this.employee2WebAppList);
|
||||
|
||||
this.employeeDetails.detailItems.register(this.employee2DepartmentList, null, 'employeeId', /*() => this.employee2DepartmentList.focuseFirstItem()*/);
|
||||
this.employeeDetails.detailItems.register(this.employee2WebAppList, null, 'employeeId');
|
||||
this.employeeDetails.detailItems.register(this.employee2AttributeList, null, 'employeeId');
|
||||
this.employee2WebAppList.batchInsert = false;
|
||||
this.employee2WebAppList.beforeSaveCallBack = this.beforeSaveEmployee2WebAppList.bind(this);
|
||||
this.employee2WebAppList.afterInsertCallBack = this.afterInsertEmployee2WebAppList.bind(this);
|
||||
this.employee2AttributeList.filter = this.employee2AllFilter;
|
||||
|
||||
this.loadBaseData();
|
||||
this.init();
|
||||
}
|
||||
|
||||
async beforeSaveEmployee2WebAppList(entities: EmployeeToWebApp[]): Promise<EN_EntityBeforeSaveCallBackResults> {
|
||||
entities.forEach((entity: EmployeeToWebApp) => {
|
||||
if (entity.entityChanged && !entity.isNew()) this.afterInsertEmployee2WebAppList(entity, null, false);
|
||||
});
|
||||
this.employee2WebAppList.deletedItems.forEach((entity: EmployeeToWebApp) => {
|
||||
entity.arExtendedDepartmentIdList = [];
|
||||
entity.arAdditionalRoleIdList = [];
|
||||
this.afterInsertEmployee2WebAppList(entity, null, false);
|
||||
});
|
||||
return EN_EntityBeforeSaveCallBackResults.Ok_Continue;
|
||||
}
|
||||
|
||||
|
||||
afterInsertEmployee2WebAppList(entity: EmployeeToWebApp, callback?: AppBaseEntityCallBack, reloadEntity = true) {
|
||||
if (entity) {
|
||||
const filter = new EmployeeToWebAppFilter('EmployeeToWebAppFilter');
|
||||
filter.employeeToWebAppId = entity.employeeToWebAppId;
|
||||
//to create wrapper not in the constructor we need to pass appLogsService, repositoryService, uiNotificationsService explicetely!
|
||||
const departmentList = new AppBaseEntityListWrapper<WebAppToDepartment>(WebAppToDepartment, 'Abteilungen für Mitarbeiterapplikation', EN_AppEntities.WebAppToDepartment, filter, this.appLogsService, this.repositoryService, this.uiNotificationsService);
|
||||
const addRoleList =
|
||||
new AppBaseEntityListWrapper<WebAppToWebAppAdditionalRole>(WebAppToWebAppAdditionalRole, 'Zusatzrole für Mitarbeiterapplikation', EN_AppEntities.WebAppToWebAppAdditionalRole, filter, this.appLogsService, this.repositoryService, this.uiNotificationsService);
|
||||
|
||||
this._saveEmployee2WebAppSublists(entity
|
||||
, departmentList
|
||||
, 'arExtendedDepartmentIdList'
|
||||
, 'departmentId'
|
||||
, (result1) => {
|
||||
this._saveEmployee2WebAppSublists(entity
|
||||
, addRoleList
|
||||
, 'arAdditionalRoleIdList'
|
||||
, 'webAppAdditionalRoleId'
|
||||
, (result2) => { if (reloadEntity && (result1 || result2)) entity.load(this.repositoryService, callback); else if (callback) callback(); }
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private _saveEmployee2WebAppSublists(entity: EmployeeToWebApp, list: AppBaseEntityListWrapper<AppBaseEntity>, idListName: string, idName: string, callback?: (entity: boolean) => void) {
|
||||
let result: boolean = false;
|
||||
list.load(() => {
|
||||
if (result = list.match2array(entity, 'employeeToWebAppId', idListName, idName)) {
|
||||
list.save(() => { if (callback) callback(true); }, (err) => { if (callback) callback(true); });
|
||||
} else if (callback) callback(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
prepareDetailsList(list: AppBaseEntityListWrapper<AppBaseEntity>) {
|
||||
list.createFocusedShadowEntity();
|
||||
list.filter = this.employee2AllFilter;
|
||||
list.focusedEntityShadowed.dontLoadEntity = true;
|
||||
list.focusedEntityShadowed.dontUpdateEntityDirectly = true;
|
||||
list.focusedEntityShadowed.dontInsertEntityDirectly = true;
|
||||
}
|
||||
|
||||
|
||||
loadData() {
|
||||
super.loadData();
|
||||
this.employeeList.load(null, null, () => this.pageLoadingService.updatePageLoadedCounters(this.appPage));
|
||||
}
|
||||
|
||||
public loadBaseData() {
|
||||
super.loadBaseData(EN_AppPages.Login, EN_HttpQueriesCount4Page.Login);
|
||||
this.appDataService.loadData(() => this.pageLoadingService.updatePageLoadedCounters(EN_AppPages.Login));
|
||||
}
|
||||
|
||||
|
||||
public focusCallBack(focusedItem: Employee) {
|
||||
}
|
||||
|
||||
|
||||
public clearData() {
|
||||
super.clearData();
|
||||
this.employeeFilter.filterReset();
|
||||
this.employeeList.clear();
|
||||
}
|
||||
|
||||
|
||||
protected onLoggedInOut(user: CoreUser) {
|
||||
this.userChanged(new User(user));
|
||||
super.onLoggedInOut(user);
|
||||
}
|
||||
|
||||
private userChanged(user: User) {
|
||||
if (this.authService.isLoggedIn()) {
|
||||
this.employeeDetails.canNew = user.isMaster;
|
||||
this.employeeDetails.canEdit = this.employeeDetails.canNew;
|
||||
this.employeeDetails.canDelete = this.employeeDetails.canNew;
|
||||
}
|
||||
// this.globalsService.appPages[EN_AppPages.UserConfig].hidden = !user?.isMaster;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
<div class="employee-attribute">
|
||||
<label class="label">Merkmale</label>
|
||||
<hensel-selection
|
||||
id="attributes"
|
||||
class="attributes"
|
||||
name="attributes"
|
||||
[dataSource]=appDataService.employeeAttributeList.items
|
||||
placeholder="Merkmal"
|
||||
keyExpr="entityId"
|
||||
displayTemplate="${name} (${shortname})"
|
||||
sortField="seqNo"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="employeeDetails.entity.arAttributeIdList"
|
||||
(selectedItemsChange)="employeeDetails.entityWasChanged = true"
|
||||
[disabled]=!employeeDetails.inNotViewMode
|
||||
[height]="'100%'"
|
||||
[useResultGrid]=true>
|
||||
</hensel-selection>
|
||||
</div>
|
||||
@ -0,0 +1,20 @@
|
||||
.employee-attribute {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas: "label""attributes";
|
||||
}
|
||||
|
||||
|
||||
.attributes {
|
||||
grid-area: attributes;
|
||||
height: 100%;
|
||||
width: calc(100% - 28px);
|
||||
margin-left: 28px;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-attribute',
|
||||
templateUrl: './employee-attribute.component.html',
|
||||
styleUrls: ['./employee-attribute.component.scss']
|
||||
})
|
||||
export class EmployeeAttributeComponent implements OnInit {
|
||||
|
||||
@Input() public employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
|
||||
constructor(
|
||||
public appDataService: AppDataService,
|
||||
) {
|
||||
}
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,147 @@
|
||||
<form class="employeeDetailsContent" #detailForm="ngForm">
|
||||
<!-- 1-st column start -->
|
||||
<hensel-input
|
||||
class="input-employeeno"
|
||||
name="employeeNo"
|
||||
placeholder="Mitarbeiter Nr."
|
||||
required
|
||||
autocomplete="off"
|
||||
maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.employeeNo
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-salutation"
|
||||
name="salutation"
|
||||
placeholder="Anrede"
|
||||
maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.salutation
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-firstname"
|
||||
name="firstname"
|
||||
placeholder="Vorname"
|
||||
[(ngModel)]=employeeDetails.entity.firstName
|
||||
[disabled]="!employeeDetails.inNewEditMode"
|
||||
required
|
||||
maxlength="50">
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-lastname"
|
||||
name="lastname"
|
||||
placeholder="Nachname"
|
||||
required
|
||||
maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.lastName
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-shortname"
|
||||
name="shortname"
|
||||
placeholder="Kürzel"
|
||||
required
|
||||
maxlength="10"
|
||||
[(ngModel)]=employeeDetails.entity.shortName
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-loginname"
|
||||
name="login"
|
||||
placeholder="Login"
|
||||
required maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.loginName
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-email"
|
||||
name="Email"
|
||||
placeholder="User Email"
|
||||
maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.email
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-selection
|
||||
name="Mandant"
|
||||
class="input-mandant"
|
||||
[dataSource]=appDataService.subsidiaryList.items
|
||||
placeholder="Mandant"
|
||||
keyExpr="clientId"
|
||||
displayExpr="subsidiaryCode"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
[(selectedItems)]="employeeDetails.entity.clientId"
|
||||
[disabled]="!employeeDetails.inNewEditMode"
|
||||
required>
|
||||
</hensel-selection>
|
||||
<!-- 1-st column end -->
|
||||
<!-- 2-nd column start -->
|
||||
<hensel-input
|
||||
class="input-title"
|
||||
name="title"
|
||||
placeholder="Titel"
|
||||
maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.title
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-position"
|
||||
name="position"
|
||||
placeholder="Position"
|
||||
required
|
||||
maxlength="50"
|
||||
[(ngModel)]=employeeDetails.entity.position
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-selection
|
||||
name="rang"
|
||||
class="input-rang"
|
||||
[dataSource]=appDataService.rangList.items
|
||||
placeholder="Rang"
|
||||
keyExpr="entityId"
|
||||
displayExpr="rangName"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
[(selectedItems)]="employeeDetails.entity.rangId"
|
||||
[disabled]="!employeeDetails.inNewEditMode"
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
<hensel-input
|
||||
class="input-mobilephoneno"
|
||||
name="mobileno"
|
||||
placeholder="Handynummer"
|
||||
maxlength="30"
|
||||
[(ngModel)]=employeeDetails.entity.mobilePhoneNo
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input
|
||||
class="input-phoneno"
|
||||
name="phoneno"
|
||||
placeholder="Festnetznummer"
|
||||
maxlength="30"
|
||||
[(ngModel)]=employeeDetails.entity.phoneNo
|
||||
[disabled]="!employeeDetails.inNewEditMode" >
|
||||
</hensel-input>
|
||||
|
||||
<mat-checkbox
|
||||
class="input-isActive"
|
||||
name="Enabled"
|
||||
style="float: left"
|
||||
labelPosition="after"
|
||||
[(ngModel)]="employeeDetails.entity.isActive"
|
||||
[disabled]="!employeeDetails.inNewEditMode">
|
||||
Aktiv
|
||||
</mat-checkbox>
|
||||
<!-- 2-nd column end -->
|
||||
</form>
|
||||
@ -0,0 +1,97 @@
|
||||
|
||||
.employeeDetailsContent {
|
||||
// z-index: 10;
|
||||
// position: relative; //otherwise z-index is not working
|
||||
padding: 0 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-column-gap: 8px;
|
||||
grid-template-columns: repeat(2, minmax(1px, 1fr)); // column relationship
|
||||
grid-template-rows: repeat(7, 42px); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas:
|
||||
"input-employeeno input-title"
|
||||
"input-salutation input-position"
|
||||
"input-firstname input-rang"
|
||||
"input-lastname input-mobilephoneno"
|
||||
"input-shortname input-phoneno"
|
||||
"input-loginname input-mandant"
|
||||
"input-email input-isActive "
|
||||
;
|
||||
}
|
||||
|
||||
.input-isActive {
|
||||
|
||||
margin-top: 12px;
|
||||
grid-area: input-isActive;
|
||||
}
|
||||
.input-mandant {
|
||||
grid-area: input-mandant;
|
||||
}
|
||||
|
||||
.input-employeeno {
|
||||
grid-area: input-employeeno;
|
||||
}
|
||||
|
||||
.input-firstname {
|
||||
grid-area: input-firstname;
|
||||
}
|
||||
|
||||
.input-lastname {
|
||||
grid-area: input-lastname;
|
||||
}
|
||||
|
||||
.input-shortname {
|
||||
grid-area: input-shortname;
|
||||
}
|
||||
|
||||
.input-loginname {
|
||||
grid-area: input-loginname;
|
||||
}
|
||||
|
||||
.input-email {
|
||||
grid-area: input-email;
|
||||
}
|
||||
|
||||
.input-salutation {
|
||||
grid-area: input-salutation;
|
||||
}
|
||||
|
||||
.input-title {
|
||||
grid-area: input-title;
|
||||
}
|
||||
|
||||
.input-position {
|
||||
grid-area: input-position;
|
||||
}
|
||||
|
||||
.input-rang {
|
||||
grid-area: input-rang;
|
||||
}
|
||||
|
||||
.input-email {
|
||||
grid-area: input-email;
|
||||
}
|
||||
|
||||
.input-mobilephoneno {
|
||||
grid-area: input-mobilephoneno;
|
||||
}
|
||||
|
||||
.input-phoneno {
|
||||
grid-area: input-phoneno;
|
||||
}
|
||||
|
||||
.check-box {
|
||||
margin-top: 13px;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 12px;
|
||||
margin: 2px 2px 2px 2px;
|
||||
}
|
||||
|
||||
.abstand {
|
||||
margin-right: 1px !important;
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import { Component, OnInit, Input, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { AuthorizeService } from '@app_core/services/authorize.service';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
|
||||
@Component({
|
||||
selector: 'app-details-content',
|
||||
templateUrl: './employee-content.component.html',
|
||||
styleUrls: ['./employee-content.component.scss'],
|
||||
})
|
||||
export class EmployeeContentComponent implements OnInit, AfterViewInit {
|
||||
@Input() public employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
@ViewChild('detailForm') detailForm: NgForm;
|
||||
|
||||
constructor(
|
||||
public appDataService: AppDataService,
|
||||
public employeeDataService: EmployeeDataService,
|
||||
public authorizeService: AuthorizeService,
|
||||
public globals: Globals
|
||||
) { }
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.employeeDetails.detailForm = this.detailForm;
|
||||
}
|
||||
|
||||
ngOnInit() { }
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
<div class="employee-department">
|
||||
<label class="label">Abteilungsliste</label>
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<div class="toolbar-flex-container">
|
||||
<button mat-icon-button title="Hinzufügen" (click)=addItem()
|
||||
[disabled]="!employeeDetails.inNotViewMode || !employeeDepartmentList.focusedEntityShadowed.enabledNewButton()">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Bearbeiten" (click)=editItem()
|
||||
[disabled]="!employeeDetails.inNotViewMode || !employeeDepartmentList.focusedItem || !employeeDepartmentList.focusedEntityShadowed.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Löschen" class="toolbar-button-last" (click)=deleteDepartment();
|
||||
[disabled]="!employeeDetails.inNotViewMode
|
||||
|| !employeeDepartmentList.focusedItem
|
||||
|| !employeeDepartmentList.focusedEntityShadowed.enabledDeleteButton()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<dx-data-grid
|
||||
name="departmentGrid"
|
||||
[class]="'grid'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="employeeDepartmentList.items"
|
||||
keyExpr="entityId"
|
||||
[(focusedRowIndex)]=employeeDepartmentList.focusedItemGridIndex
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowKey)]="employeeDepartmentList.focusedItemId"
|
||||
[(selectedRowKeys)]="employeeDepartmentList.selectedItemIds"
|
||||
[showBorders]="true"
|
||||
[allowColumnResizing]="true"
|
||||
columnResizingMode="widget"
|
||||
noDataText="Keine Daten sind vorhanden"
|
||||
[renderAsync]="true"
|
||||
(onRowDblClick)="dblClick($event)"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'"
|
||||
(onExporting)="globals.doExcelExportSimple($event, employeeDepartmentList.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<dxo-header-filter [visible]="true"></dxo-header-filter> -->
|
||||
<dxo-filter-row [visible]="false" [applyFilter]="true"></dxo-filter-row>
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple"></dxo-sorting>
|
||||
<dxo-selection mode="none"></dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf="column.visible">
|
||||
<dxi-column
|
||||
[allowHeaderFiltering]=column.allowHeaderFiltering
|
||||
[dataField]=column.dataField
|
||||
[dataType]=column.dataType
|
||||
[caption]=column.caption
|
||||
[width]=column.width
|
||||
[sortIndex]=column.sortIndex
|
||||
[sortOrder]=column.sortOrder
|
||||
[visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible
|
||||
[fixed]=column.fixed
|
||||
[headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate
|
||||
[allowSorting]=column.allowSorting
|
||||
[calculateCellValue]=column.calculateCellValue
|
||||
[calculateDisplayValue]=column.calculateDisplayValue
|
||||
[calculateGroupValue]=column.calculateGroupValue
|
||||
[calculateSortValue]=column.calculateSortValue
|
||||
[alignment]=column.alignment>
|
||||
<dxo-format *ngIf="column.dataType == 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType == 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
<dxo-lookup *ngIf="column.dataField === 'departmentId'" [dataSource]="appDataService.departmentList?.items" valueExpr="entityId" displayExpr="departmentName"></dxo-lookup>
|
||||
<dxo-lookup *ngIf="column.dataField === 'employeeStatusId'" [dataSource]="appDataService.employeeStatusList?.items" valueExpr="entityId" displayExpr="employeeStatusName"></dxo-lookup>
|
||||
<dxo-lookup *ngIf="column.dataField === 'rangId'" [dataSource]="appDataService.rangList?.items" valueExpr="entityId" displayExpr="rangShortname"></dxo-lookup>
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</div>
|
||||
@ -0,0 +1,23 @@
|
||||
.employee-department {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
grid-template-areas: "label label" "toolbar grid";
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-area: grid;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
// padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
|
||||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { EN_EmployeeRang, EN_EmployeeStatus } from '@app_consts';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { EmployeeToDepartment } from '@app_models/employee-to-department';
|
||||
import { EmployeeToWebApp } from '@app_models/employee-to-webapp';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { EmployeeToDepartmentPopupeditComponent } from './employee-department.popupedit/employee-department.popupedit.component';
|
||||
import { MatDialogService } from '@app_core/services/mat-dialog.service';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-department',
|
||||
templateUrl: './employee-department.component.html',
|
||||
styleUrls: ['./employee-department.component.scss']
|
||||
})
|
||||
|
||||
export class EmployeeDepartmentComponent implements OnInit {
|
||||
|
||||
@Input() employeeDepartmentList: AppBaseEntityListWrapper<EmployeeToDepartment>;
|
||||
@Input() public employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialogService,
|
||||
public appDataService: AppDataService,
|
||||
public employeeDataService: EmployeeDataService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
get emplDepDetails(): AppBaseEntityWrapper<EmployeeToDepartment> {
|
||||
return this.employeeDepartmentList.focusedEntityShadowed;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
|
||||
if (this.appDataService.showIds) col = this.columnConfigList.addNumber('Id', 'entityId', 7, 0);
|
||||
|
||||
col = this.columnConfigList.add('Name', 'departmentId', 25);
|
||||
|
||||
col = this.columnConfigList.add('Status', 'employeeStatusId', 20);
|
||||
col.sortIndex = 1;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
col = this.columnConfigList.add('Rang', 'rangId', 10);
|
||||
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
addItem() {
|
||||
this.emplDepDetails.new();
|
||||
this.emplDepDetails.entity.employeeId = this.employeeDetails.entityId;
|
||||
const employeeStatusId = this.employeeDepartmentList.items.find(e2d => e2d.employeeStatusId === EN_EmployeeStatus.MainFunction) ? EN_EmployeeStatus.AdditionalFunction : EN_EmployeeStatus.MainFunction;
|
||||
this.emplDepDetails.entity.employeeStatusId = employeeStatusId;
|
||||
this.emplDepDetails.entity.rangId = EN_EmployeeRang.Mitarbeiter;
|
||||
this.openPopupDialog(this.emplDepDetails);
|
||||
}
|
||||
|
||||
dblClick(event: any) {
|
||||
if (!this.employeeDetails.entityIsLoading) this.employeeDepartmentList.focusedEntityShadowed.delayedEdit(event.data['entityId'], this.editItem);
|
||||
}
|
||||
|
||||
editItem = () => {
|
||||
this.emplDepDetails.edit();
|
||||
this.openPopupDialog(this.emplDepDetails);
|
||||
}
|
||||
|
||||
public openPopupDialog(editEntity: AppBaseEntityWrapper<EmployeeToDepartment>) {
|
||||
this.employeeDetails.keyDownListenerStopped = true;
|
||||
this.dialog.openDialog(EmployeeToDepartmentPopupeditComponent, {
|
||||
baseEntityWrapper: editEntity,
|
||||
keyItemName: this.employeeDetails.entity.firstName + ' ' + this.employeeDetails.entity.lastName,
|
||||
readOnly: !this.employeeDetails.inNotViewMode,
|
||||
description: (editEntity.entity.entityId === 0 ? 'Neue Abteilung zuweisen' : 'Daten zur Abteilung "' + editEntity.entity.departmentName + '" bearbeiten '),
|
||||
list: this.employeeDepartmentList,
|
||||
}, true, () => this.employeeDetails.keyDownListenerStopped = false);
|
||||
}
|
||||
|
||||
|
||||
public deleteDepartment() {
|
||||
let usedDepartmentIdsStr: string = '';
|
||||
this.employeeDataService.employee2WebAppList.items.forEach((e2w: EmployeeToWebApp) => usedDepartmentIdsStr += ',' + e2w.departmentId + ',' + e2w.arExtendedDepartmentIdList);
|
||||
const usedDepartmentIdsList: string[] = usedDepartmentIdsStr.split(',');
|
||||
if (usedDepartmentIdsList.indexOf('' + this.emplDepDetails.entity.departmentId) > -1) {
|
||||
this.emplDepDetails.warningMessageBox(`Löschen von Abteilung <${this.emplDepDetails.entity.departmentName}>`,
|
||||
'Die Abteilung kann nicht gelöscht werden, weil sie zu einer Webapplikation zugewiesen ist');
|
||||
} else this.emplDepDetails.delete();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
<form class="PopupContainer" #popupForm="ngForm">
|
||||
<!-- <dx-button class="buttonLayoutCancel" icon="close" (click)="close()"></dx-button> -->
|
||||
<h2 mat-dialog-title class="messageBoxHeader">{{description}} - {{keyItemName}} </h2>
|
||||
|
||||
<mat-dialog-content class="PopupContent">
|
||||
|
||||
<div class="buttons">
|
||||
<button id="btnSave" name="btnSave" class="btnSave" mat-stroked-button [disabled]="!baseEntityWrapper.enabledSaveButton() || readOnly" (click)="save() ">
|
||||
<mat-icon>save</mat-icon> Übernehmen
|
||||
</button>
|
||||
<button #btnCancel id="btnCancel" name="btnCancel" class="btnCancel" mat-stroked-button (click)="cancel()">
|
||||
<mat-icon>cancel</mat-icon> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hensel-selection
|
||||
#input_department
|
||||
id="input-department"
|
||||
class="input-department"
|
||||
[dataSource]=appDataService.departmentList.items
|
||||
placeholder="Abteilung"
|
||||
keyExpr="entityId"
|
||||
displayExpr="departmentName"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.departmentId"
|
||||
[disabled]="readOnly || focusedItem.entityId !== 0"
|
||||
[customFilterFn]="focusedItem.entityId === 0?getNotUsedDepartments:''"
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
|
||||
<hensel-selection
|
||||
#input_emplstatus
|
||||
id="input-emplstatus"
|
||||
class="input-emplstatus"
|
||||
[dataSource]=appDataService.employeeStatusList.items
|
||||
placeholder="Status"
|
||||
keyExpr="entityId"
|
||||
displayExpr="employeeStatusName"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.employeeStatusId"
|
||||
[disabled]=readOnly
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
|
||||
<hensel-selection
|
||||
#input_rang
|
||||
id="input-rang"
|
||||
class="input-rang"
|
||||
[dataSource]=appDataService.rangList.items
|
||||
placeholder="Rang"
|
||||
keyExpr="entityId"
|
||||
displayExpr="rangName"
|
||||
sortField="rangOrder"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.rangId"
|
||||
[disabled]=readOnly
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
</mat-dialog-content>
|
||||
</form>
|
||||
@ -0,0 +1,28 @@
|
||||
@import 'popup-base.component';
|
||||
|
||||
.PopupContent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid: ;
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto auto; // row relationships
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr)); // column relationship
|
||||
grid-column-gap: 15px;
|
||||
grid-row-gap: 15px;
|
||||
grid-template-areas:
|
||||
'input-department input-emplstatus input-rang'
|
||||
'buttons buttons buttons'
|
||||
}
|
||||
|
||||
.input-department {
|
||||
grid-area: input-department;
|
||||
}
|
||||
|
||||
.input-emplstatus {
|
||||
grid-area: input-emplstatus;
|
||||
}
|
||||
|
||||
.input-rang {
|
||||
grid-area: input-rang;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { EmployeeToDepartment } from '@app_models/employee-to-department';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-department-popupedit',
|
||||
templateUrl: 'employee-department.popupedit.component.html',
|
||||
styleUrls: ['employee-department.popupedit.component.scss']
|
||||
})
|
||||
|
||||
export class EmployeeToDepartmentPopupeditComponent extends PopupBaseComponent {
|
||||
|
||||
constructor(
|
||||
public appDataService: AppDataService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public get focusedItem(): EmployeeToDepartment {
|
||||
return <EmployeeToDepartment>(this._focusedItem);
|
||||
}
|
||||
|
||||
getNotUsedDepartments = (dep: Department) => {
|
||||
return !this.list.items.find((item) => item['departmentId'] === dep.entityId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<form class="EmployeeDetailsForm" #detailForm="ngForm" id="form_employee">
|
||||
<mat-card class="card">
|
||||
<mat-card-header>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="EmployeeDetails">
|
||||
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<button *ngIf="employeeDetails.canNew" #btnNew id="btnNew" name="btnNew" class="abstand" mat-stroked-button
|
||||
title="Neuer Mitarbeiter" (click)="add()"
|
||||
[disabled]="!employeeDetails.enabledNewButton()">
|
||||
<mat-icon>add</mat-icon> Hinzufügen
|
||||
</button>
|
||||
<button *ngIf="employeeDetails.canEdit" #btnEdit id="btnEdit" name="btnEdit" class="abstand" mat-stroked-button
|
||||
title="Bearbeiten" (click)="employeeDetails.edit()"
|
||||
[disabled]="!employeeDetails.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon> Bearbeiten
|
||||
</button>
|
||||
<button *ngIf="employeeDetails.canEdit||employeeDetails.canNew" id="btnSave" name="btnSave" class="abstand"
|
||||
mat-stroked-button disabled title="Speichern" (click)="save()"
|
||||
[disabled]="!employeeDetails.enabledSaveButton()">
|
||||
<mat-icon>save</mat-icon> Speichern
|
||||
</button>
|
||||
<button *ngIf="employeeDetails.canEdit||employeeDetails.canNew" id="btnUndo" name="btnUndo" class="abstand"
|
||||
mat-stroked-button disabled title="Änderungen verwerfen" (click)="cancel()" [autofocus]=true
|
||||
[disabled]="!employeeDetails.enabledCancelButton()">
|
||||
<mat-icon>undo</mat-icon> Verwerfen
|
||||
</button>
|
||||
<button *ngIf="employeeDetails.canDelete" id="btnDelete" name="btnDelete" mat-stroked-button class="abstand"
|
||||
title="Benutzer löschen" class="last" (click)="employeeDetails.delete()"
|
||||
[disabled]="!employeeDetails.enabledDeleteButton()">
|
||||
<mat-icon>delete</mat-icon> Löschen
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<app-details-content class="DetailsContent" [employeeDetails]=employeeDetails></app-details-content>
|
||||
<app-employee-department class=DepartmentList
|
||||
[employeeDepartmentList]=employeeDataService.employee2DepartmentList
|
||||
[employeeDetails]=employeeDetails>
|
||||
</app-employee-department>
|
||||
<app-employee-webapp class="WebAppList"
|
||||
[employeeDetails]=employeeDetails>
|
||||
</app-employee-webapp>
|
||||
<app-employee-attribute class="AttributeList" [employeeDetails]=employeeDetails></app-employee-attribute>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</form>
|
||||
@ -0,0 +1,48 @@
|
||||
.EmployeeDetails {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
grid-template-rows: 42px minmax(1px, 168px) minmax(1px, 120px);
|
||||
grid-template-columns: auto minmax(1px, 1fr) minmax(1px, 1.8fr);
|
||||
grid-row-gap: 6px;
|
||||
grid-column-gap: 13px;
|
||||
grid-template-areas:
|
||||
'toolbar department-grid webapps-grid'
|
||||
'detail department-grid webapps-grid '
|
||||
'detail attribute-grid webapps-grid';
|
||||
z-index: 10;
|
||||
position: relative; //otherwise z-index is not working
|
||||
}
|
||||
|
||||
|
||||
.DetailsContent {
|
||||
grid-area: detail;
|
||||
}
|
||||
|
||||
.DepartmentList {
|
||||
grid-area: department-grid;
|
||||
}
|
||||
|
||||
.WebAppList {
|
||||
grid-area: webapps-grid;
|
||||
}
|
||||
|
||||
.AttributeList {
|
||||
grid-area: attribute-grid;
|
||||
}
|
||||
|
||||
.abstand {
|
||||
margin-right: 1px !important;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 12px;
|
||||
margin: 2px 2px 2px 2px;
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
import { AfterViewInit, Component, HostListener, Input } from '@angular/core';
|
||||
import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component';
|
||||
import { EN_EntityBeforeSaveCallBackResults } from '@app_core/consts';
|
||||
import { AuthorizeService } from '@app_core/services/authorize.service';
|
||||
import { PageLoadingService } from '@app_core/services/pageloading.service';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-detail',
|
||||
templateUrl: './employee-detail.component.html',
|
||||
styleUrls: ['./employee-detail.component.scss'],
|
||||
})
|
||||
export class EmployeeDetailComponent implements AfterViewInit {
|
||||
@Input() public employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
|
||||
constructor(
|
||||
public employeeDataService: EmployeeDataService,
|
||||
public authorizeService: AuthorizeService,
|
||||
private pageLoadingService: PageLoadingService,
|
||||
) {
|
||||
}
|
||||
|
||||
public get focusedItem(): Employee {
|
||||
return this.employeeDetails.entity;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.employeeDetails.beforeNewCallBack = this.newEmployeeInit.bind(this);
|
||||
this.employeeDetails.beforeSaveCallBack = this.beforeSaveEmployee.bind(this);
|
||||
}
|
||||
|
||||
newEmployeeInit(employee: Employee) {
|
||||
/* employee.createdOn = new Date();
|
||||
employee.createdBy = this.authorizeService.user.userCode;
|
||||
employee.changedOn = employee.createdOn;
|
||||
employee.changedBy = employee.createdBy;*/
|
||||
}
|
||||
|
||||
async beforeSaveEmployee(employee: Employee): Promise<EN_EntityBeforeSaveCallBackResults> {
|
||||
this.employeeDataService.employee2AttributeList.match2array(employee, 'employeeId', 'arAttributeIdList', 'employeeAttributeId');
|
||||
return EN_EntityBeforeSaveCallBackResults.Ok_Continue;
|
||||
}
|
||||
|
||||
|
||||
public save = () => { //because of calling as callback of cancel
|
||||
this.pageLoadingService.startSpinner();
|
||||
this.employeeDetails.save((employee: Employee) => this.afterSave(employee), null, () => this.pageLoadingService.hideSpinner());
|
||||
}
|
||||
|
||||
afterSave(employee: Employee) {
|
||||
// this.employeeDetails.loadDetails(this.catalogDataService.employeeCategoryList);
|
||||
|
||||
}
|
||||
|
||||
public cancel = () => {
|
||||
// this.setCurrentMaster4Subemployee = null;
|
||||
this.employeeDetails.cancelWithSave(this.save);
|
||||
}
|
||||
|
||||
public add(){
|
||||
this.employeeDetails.new();
|
||||
this.employeeDetails.entity.isActive = true;
|
||||
}
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
keyboardInput(event: any) {
|
||||
return LoginPopupComponent.LOGIN_IS_SHOWN || this.employeeDetails.shortcutsHandler(event, this.save, this.cancel);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
<div class="employee-webapp">
|
||||
<label class="label">Webapp Liste</label>
|
||||
<section class="toolbar">
|
||||
<div class="toolbar-button-row">
|
||||
<div class="toolbar-flex-container">
|
||||
<button mat-icon-button title="Hinzufügen" (click)=addItem()
|
||||
[disabled]="!this.employeeDetails.entity.isActive || !employeeDetails.inNotViewMode || !employeeWebappList.focusedEntityShadowed.enabledNewButton()">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Bearbeiten" (click)=editItem()
|
||||
[disabled]="!this.employeeDetails.entity.isActive || !employeeDetails.inNotViewMode || !employeeWebappList.focusedItem || !employeeWebappList.focusedEntityShadowed.enabledEditButton()">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button title="Löschen" class="toolbar-button-last" (click)=employeeWebappList.focusedEntityShadowed.delete()
|
||||
[disabled]="!this.employeeDetails.entity.isActive
|
||||
|| !employeeDetails.inNotViewMode
|
||||
|| !employeeWebappList.focusedItem
|
||||
|| !employeeWebappList.focusedEntityShadowed.enabledDeleteButton()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<dx-data-grid
|
||||
name="webappGrid"
|
||||
[class]="'grid'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="employeeWebappList.items"
|
||||
keyExpr="entityId"
|
||||
[(focusedRowIndex)]=employeeWebappList.focusedItemGridIndex
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowKey)]="employeeWebappList.focusedItemId"
|
||||
[(selectedRowKeys)]="employeeWebappList.selectedItemIds"
|
||||
[showBorders]="true"
|
||||
[allowColumnResizing]="true"
|
||||
columnResizingMode="widget"
|
||||
noDataText="Keine Daten sind vorhanden"
|
||||
[renderAsync]="true"
|
||||
(onRowDblClick)="dblClick($event)"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'; employeeWebappList.gridUpDownProcessing($event)"
|
||||
(onExporting)="globals.doExcelExportSimple($event, employeeWebappList.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<!-- <dxo-header-filter [visible]="true"></dxo-header-filter> -->
|
||||
<dxo-filter-row [visible]="true"></dxo-filter-row>
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple"></dxo-sorting>
|
||||
<dxo-selection mode="none"></dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf="column.visible">
|
||||
<dxi-column
|
||||
[allowHeaderFiltering]=column.allowHeaderFiltering
|
||||
[dataField]=column.dataField
|
||||
[dataType]=column.dataType
|
||||
[caption]=column.caption
|
||||
[width]=column.width
|
||||
[sortIndex]=column.sortIndex
|
||||
[sortOrder]=column.sortOrder
|
||||
[visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible
|
||||
[fixed]=column.fixed
|
||||
[headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate
|
||||
[allowSorting]=column.allowSorting
|
||||
[calculateCellValue]=column.calculateCellValue
|
||||
[calculateDisplayValue]=column.calculateDisplayValue
|
||||
[calculateGroupValue]=column.calculateGroupValue
|
||||
[calculateSortValue]=column.calculateSortValue
|
||||
[alignment]=column.alignment>
|
||||
<dxo-format *ngIf="column.dataType == 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType == 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
<!-- <dxo-lookup *ngIf="column.dataField === 'webAppId'" [dataSource]="{store:appDataService.webAppList?.items, sort:'webAppName'}" valueExpr="entityId" displayExpr="webAppName"></dxo-lookup> -->
|
||||
<!-- <dxo-lookup *ngIf="column.dataField === 'webAppId'" [dataSource]="appDataService.webAppList?.items" valueExpr="entityId" displayExpr="webAppName"></dxo-lookup> -->
|
||||
<!-- <dxo-lookup *ngIf="column.dataField === 'departmentId'" [dataSource]="appDataService.departmentList?.items" valueExpr="entityId" displayExpr="departmentName"></dxo-lookup>
|
||||
<dxo-lookup *ngIf="column.dataField === 'webAppRoleId'" [dataSource]="appDataService.roleList?.items" valueExpr="entityId" displayExpr="webAppRoleName"></dxo-lookup> -->
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</div>
|
||||
@ -0,0 +1,24 @@
|
||||
.employee-webapp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr); // column relationship
|
||||
grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships
|
||||
// grid-template-areas: "label""toolbar""grid";
|
||||
grid-template-areas: "label label" "toolbar grid";
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-area: grid;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
grid-area: label;
|
||||
// padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
grid-area: toolbar;
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
|
||||
|
||||
import * as keycode from '@angular/cdk/keycodes';
|
||||
import { Component, HostListener, Input, OnInit } from '@angular/core';
|
||||
import { EN_EmployeeStatus } from '@app_consts';
|
||||
import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { MatDialogService } from '@app_core/services/mat-dialog.service';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { EmployeeToDepartment } from '@app_models/employee-to-department';
|
||||
import { EmployeeToWebApp } from '@app_models/employee-to-webapp';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { EmployeeToWebAppPopupeditComponent } from './employee-webapp.popupedit/employee-webapp.popupedit.component';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-webapp',
|
||||
templateUrl: './employee-webapp.component.html',
|
||||
styleUrls: ['./employee-webapp.component.scss']
|
||||
})
|
||||
|
||||
export class EmployeeWebappComponent implements OnInit {
|
||||
|
||||
public get employeeWebappList(): AppBaseEntityListWrapper<EmployeeToWebApp> {
|
||||
return this.employeeDataService.employee2WebAppList;
|
||||
}
|
||||
|
||||
@Input() public employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialogService,
|
||||
public employeeDataService: EmployeeDataService,
|
||||
public appDataService: AppDataService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
|
||||
if (this.appDataService.showIds) col = this.columnConfigList.addNumber('Id', 'entityId', 7, 0);
|
||||
col = this.columnConfigList.add('Webapp', 'webAppName', 15);
|
||||
// col = this.columnConfigList.addId('Webapp', 'webAppId', 15);
|
||||
// col.calculateSortValue = 'webAppName';
|
||||
col.sortIndex = 1;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
|
||||
col = this.columnConfigList.add('Abteilung', 'departmentName', 20);
|
||||
// col = this.columnConfigList.add('Abteilung', 'departmentId', 20);
|
||||
// col.calculateSortValue = 'departmentName';
|
||||
col = this.columnConfigList.add('Role', 'webAppRoleName', 15);
|
||||
// col = this.columnConfigList.add('Role', 'webAppRoleId', 15);
|
||||
// col.calculateSortValue = 'webAppRoleName';
|
||||
col = this.columnConfigList.add('Zusatzabteilungen', 'extendedDepartmentNameList', 30);
|
||||
col = this.columnConfigList.add('Zusatzrolen', 'additionalRoleNameList', 30);
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
addItem() {
|
||||
this.employeeWebappList.focusedEntityShadowed.new();
|
||||
this.employeeWebappList.focusedEntityShadowed.entity.employeeId = this.employeeDetails.entityId;
|
||||
if (this.employeeDataService.employee2DepartmentList.items.length > 0) {
|
||||
let mainDepId: number = 0;
|
||||
const addDepIds: number[] = [];
|
||||
let addDepNames = '';
|
||||
this.employeeDataService.employee2DepartmentList.items.forEach((e2d: EmployeeToDepartment) => {
|
||||
if (e2d.employeeStatusId === EN_EmployeeStatus.MainFunction) {
|
||||
if (mainDepId === 0) mainDepId = e2d.departmentId;
|
||||
} else {
|
||||
addDepIds.push(e2d.departmentId);
|
||||
const depname = this.appDataService.departmentList?.items.find(dep => dep.entityId === e2d.departmentId)?.departmentName;
|
||||
addDepNames += depname ? depname + ', ' : '';
|
||||
}
|
||||
});
|
||||
if (mainDepId > 0) this.employeeWebappList.focusedEntityShadowed.entity.departmentId = mainDepId;
|
||||
this.employeeWebappList.focusedEntityShadowed.entity.arExtendedDepartmentIdList = addDepIds;
|
||||
this.employeeWebappList.focusedEntityShadowed.entity.extendedDepartmentNameList = addDepNames.slice(0, -2);
|
||||
}
|
||||
this.openPopupDialog(this.employeeWebappList.focusedEntityShadowed);
|
||||
}
|
||||
|
||||
dblClick(event: any) {
|
||||
if (!this.employeeDetails.entityIsLoading) this.employeeWebappList.focusedEntityShadowed.delayedEdit(event.data['entityId'], this.editItem);
|
||||
}
|
||||
|
||||
editItem = () => {
|
||||
this.employeeWebappList.focusedEntityShadowed.edit();
|
||||
this.openPopupDialog(this.employeeWebappList.focusedEntityShadowed);
|
||||
}
|
||||
|
||||
public openPopupDialog(editEntity: AppBaseEntityWrapper<EmployeeToWebApp>) {
|
||||
this.employeeDetails.keyDownListenerStopped = true;
|
||||
this.dialog.openDialog(EmployeeToWebAppPopupeditComponent, {
|
||||
baseEntityWrapper: editEntity,
|
||||
keyItemName: this.employeeDetails.entity.firstName + ' ' + this.employeeDetails.entity.lastName,
|
||||
readOnly: !this.employeeDetails.inNotViewMode || !this.employeeDetails.entity.isActive,
|
||||
description: (editEntity.entity.entityId === 0 ? 'Neue Webbapp zuweisen' : 'Daten zur Webbapp "' + editEntity.entity.webAppName + '" bearbeiten '),
|
||||
list: this.employeeWebappList,
|
||||
}, true, () => this.employeeDetails.keyDownListenerStopped = false);
|
||||
}
|
||||
|
||||
@HostListener('keydown', ['$event'])
|
||||
onKeyDown(event: any) {
|
||||
switch (event. which) {
|
||||
case keycode.ENTER:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
<form class="PopupContainer" #popupForm="ngForm">
|
||||
<!-- <dx-button class="buttonLayoutCancel" icon="close" (click)="close()"></dx-button> -->
|
||||
<h2 mat-dialog-title class="messageBoxHeader">{{description}} - {{keyItemName}} </h2>
|
||||
|
||||
<mat-dialog-content class="PopupContent">
|
||||
|
||||
<div class="buttons">
|
||||
<button id="btnSave" name="btnSave" class="btnSave" mat-stroked-button [disabled]="!baseEntityWrapper.enabledSaveButton() || readOnly"
|
||||
(click)="save()">
|
||||
<mat-icon>save</mat-icon> Übernehmen
|
||||
</button>
|
||||
<button #btnCancel id="btnCancel" name="btnCancel" class="btnCancel" mat-stroked-button (click)="cancel()">
|
||||
<mat-icon>cancel</mat-icon> Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hensel-selection
|
||||
#input_webapp
|
||||
id="input-webapp"
|
||||
class="input-webapp"
|
||||
[dataSource]=appDataService.webAppList.items
|
||||
placeholder="Webapp"
|
||||
keyExpr="entityId"
|
||||
displayExpr="webAppName"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.webAppId"
|
||||
(selectedItemsChange)="loadRoles()"
|
||||
[disabled]="readOnly || focusedItem?.entityId !== 0"
|
||||
[customFilterFn]="getWebapps"
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
<hensel-selection
|
||||
#input_department
|
||||
id="input-department"
|
||||
class="input-department"
|
||||
[dataSource]=appDataService.departmentList.items
|
||||
placeholder="Abteilung"
|
||||
keyExpr="entityId"
|
||||
displayExpr="departmentName"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.departmentId"
|
||||
[customFilterFn]="filterDepartments"
|
||||
[disabled]="readOnly"
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
|
||||
<hensel-selection
|
||||
#input_role
|
||||
id="input-role"
|
||||
class="input-role"
|
||||
[dataSource]=webAppRoleList.items
|
||||
placeholder="Role"
|
||||
keyExpr="webAppRoleId"
|
||||
displayExpr="webAppRoleName"
|
||||
sortField="webAppRoleHierarchy"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.webAppRoleId"
|
||||
[disabled]=readOnly
|
||||
[showSpinner]="webAppRoleList.isLoading"
|
||||
required>
|
||||
</hensel-selection>
|
||||
|
||||
<hensel-selection
|
||||
#input_adddepartment
|
||||
id="input-adddepartment"
|
||||
class="input-adddepartment"
|
||||
[dataSource]=appDataService.departmentList.items
|
||||
placeholder="Zusatzabteilungen"
|
||||
keyExpr="entityId"
|
||||
displayExpr="departmentName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[customFilterFn]="filterDepartments"
|
||||
[(selectedItems)]="focusedItem.arExtendedDepartmentIdList"
|
||||
(selectedItemsDisplayChange)="focusedItem.extendedDepartmentNameList = $event"
|
||||
[disabled]="readOnly"
|
||||
[height]="'100%'"
|
||||
[useResultGrid]=true
|
||||
>
|
||||
</hensel-selection>
|
||||
|
||||
<hensel-selection
|
||||
#input_addrole
|
||||
*ngIf="!focusedItem.isNew() && focusedItem.additionalRoleIdList !== null || focusedItem.isNew() && additionalRoleList.items.length>0"
|
||||
id="input-addrole"
|
||||
class="input-addrole"
|
||||
[dataSource]=additionalRoleList.items
|
||||
placeholder="Zusatzrole"
|
||||
keyExpr="entityId"
|
||||
displayExpr="webAppAdditionalRoleName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="focusedItem.arAdditionalRoleIdList"
|
||||
(selectedItemsDisplayChange)="focusedItem.additionalRoleNameList = $event"
|
||||
[disabled]="readOnly"
|
||||
[height]="'100%'"
|
||||
[width]="300"
|
||||
[useResultGrid]=true
|
||||
[showSpinner]="webAppRoleList.isLoading"
|
||||
>
|
||||
</hensel-selection>
|
||||
|
||||
</mat-dialog-content>
|
||||
</form>
|
||||
@ -0,0 +1,38 @@
|
||||
@import 'popup-base.component';
|
||||
|
||||
.PopupContent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid: ;
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: repeat(3, 42px) auto; // row relationships
|
||||
grid-template-columns: repeat(2, minmax(1px, 300px)) auto; // column relationship
|
||||
grid-column-gap: 15px;
|
||||
grid-row-gap: 15px;
|
||||
grid-template-areas:
|
||||
'input-webapp input-adddepartment input-addrole'
|
||||
'input-department input-adddepartment input-addrole'
|
||||
'input-role input-adddepartment input-addrole'
|
||||
'buttons buttons buttons'
|
||||
}
|
||||
|
||||
.input-department {
|
||||
grid-area: input-department;
|
||||
}
|
||||
|
||||
.input-adddepartment {
|
||||
grid-area: input-adddepartment;
|
||||
}
|
||||
|
||||
.input-addrole {
|
||||
grid-area: input-addrole;
|
||||
}
|
||||
|
||||
.input-webapp {
|
||||
grid-area: input-webapp;
|
||||
}
|
||||
|
||||
.input-role {
|
||||
grid-area: input-role;
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { EN_AppEntities } from '@app_consts';
|
||||
import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component';
|
||||
import { Department } from '@app_models/basedata/department';
|
||||
import { WebApp } from '@app_models/basedata/webapp';
|
||||
import { WebAppToWebAppRole } from '@app_models/basedata/webapp-to-webapprole';
|
||||
import { WebAppAdditionalRole } from '@app_models/basedata/webappadditionalrole ';
|
||||
import { EmployeeToWebApp } from '@app_models/employee-to-webapp';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-webapp-popupedit',
|
||||
templateUrl: 'employee-webapp.popupedit.component.html',
|
||||
styleUrls: ['employee-webapp.popupedit.component.scss']
|
||||
})
|
||||
|
||||
export class EmployeeToWebAppPopupeditComponent extends PopupBaseComponent {
|
||||
public webAppRoleList: AppBaseEntityListWrapper<WebAppToWebAppRole> = new AppBaseEntityListWrapper<WebAppToWebAppRole>(WebAppToWebAppRole, 'Applikation Rolenliste', EN_AppEntities.WebAppToWebAppRole);
|
||||
public additionalRoleList: AppBaseEntityListWrapper<WebAppAdditionalRole> =
|
||||
new AppBaseEntityListWrapper<WebAppAdditionalRole>(WebAppAdditionalRole, 'Applikation Rolenliste', EN_AppEntities.WebAppAdditionalRole);
|
||||
|
||||
public departmentIdList: number[] = this.employeeService.employee2DepartmentList.items.map(e2d => e2d.departmentId);
|
||||
|
||||
constructor(
|
||||
public appDataService: AppDataService,
|
||||
public employeeService: EmployeeDataService,
|
||||
) {
|
||||
super();
|
||||
this.webAppRoleList.filter = this.appDataService.webAppFilter;
|
||||
this.additionalRoleList.filter = this.appDataService.webAppFilter;
|
||||
this.loadRoles();
|
||||
}
|
||||
|
||||
|
||||
loadRoles() {
|
||||
if (this.focusedItem.webAppId) {
|
||||
this.appDataService.webAppFilter.webAppId = this.focusedItem.webAppId;
|
||||
this.webAppRoleList.load();
|
||||
if (this.focusedItem.isNew() || this.focusedItem.additionalRoleIdList !== null) this.additionalRoleList.load();
|
||||
} else {
|
||||
this.webAppRoleList.clear();
|
||||
this.additionalRoleList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public get focusedItem(): EmployeeToWebApp {
|
||||
return <EmployeeToWebApp>(this._focusedItem);
|
||||
}
|
||||
|
||||
|
||||
getWebapps = (wa: WebApp) => {
|
||||
return this.focusedItem.entityId !== 0 || !this.list.items.find((item) => item['webAppId'] === wa.entityId) && wa.isActive;
|
||||
}
|
||||
|
||||
|
||||
public filterDepartments = (department: Department) => {
|
||||
return this.departmentIdList.indexOf(department.departmentId) > -1;
|
||||
}
|
||||
|
||||
public save = () => {
|
||||
this.focusedItem.webAppName = this.appDataService.webAppList?.getItemById(this.focusedItem.webAppId)?.webAppName;
|
||||
this.focusedItem.departmentName = this.appDataService.departmentList?.getItemById(this.focusedItem.departmentId)?.departmentName;
|
||||
this.focusedItem.webAppRoleName = this.appDataService.roleList?.getItemById(this.focusedItem.webAppRoleId)?.webAppRoleName;
|
||||
|
||||
this.baseEntityWrapper.save(() => this.close(true));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
<mat-card class="card">
|
||||
<mat-card-header>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="filterCardContainer">
|
||||
|
||||
<hensel-input class="filterName"
|
||||
title="Suche in Nachnamen, Vornamen"
|
||||
placeholder="Vor- oder Nachname"
|
||||
[(ngModel)]=filterObject.name
|
||||
(keyup.Enter)="onFilterClick()"
|
||||
suffix="---">
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input class="filterShortName"
|
||||
placeholder="Kürzel"
|
||||
[(ngModel)]=filterObject.shortName
|
||||
(keyup.Enter)="onFilterClick()">
|
||||
</hensel-input>
|
||||
|
||||
<hensel-input class="filterLogin"
|
||||
placeholder="Login"
|
||||
[(ngModel)]=filterObject.loginName
|
||||
(keyup.Enter)="onFilterClick()">
|
||||
</hensel-input>
|
||||
|
||||
<!--
|
||||
<hensel-input class="filterEmail"
|
||||
placeholder="Email"
|
||||
[(ngModel)]=filterObject.email
|
||||
(keyup.Enter)="onFilterClick()">
|
||||
</hensel-input> -->
|
||||
|
||||
<hensel-selection
|
||||
id="filterDepartment"
|
||||
class="filterDepartment"
|
||||
[dataSource]=appDataService.departmentList.items
|
||||
placeholder="Abteilung"
|
||||
keyExpr="entityId"
|
||||
displayExpr="departmentName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="filterObject.departmentIds"
|
||||
(selectedItemsChange)="onFilterClick()">
|
||||
</hensel-selection>
|
||||
|
||||
<hensel-selection
|
||||
id="filterWebApp"
|
||||
class="filterWebApp"
|
||||
[dataSource]=appDataService.webAppList.items
|
||||
placeholder="Webapp"
|
||||
keyExpr="entityId"
|
||||
displayExpr="webAppName"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="filterObject.webappIds"
|
||||
(selectedItemsChange)="onFilterClick()">
|
||||
</hensel-selection>
|
||||
|
||||
|
||||
<hensel-selection
|
||||
id="filterAttribute"
|
||||
class="filterAttribute"
|
||||
[dataSource]=appDataService.employeeAttributeList.items
|
||||
placeholder="Merkmal"
|
||||
keyExpr="entityId"
|
||||
displayExpr="name"
|
||||
sortField="*"
|
||||
[multiSelect]=true
|
||||
separator=","
|
||||
[(selectedItems)]="filterObject.attributeIds"
|
||||
(selectedItemsChange)="onFilterClick()">
|
||||
</hensel-selection>
|
||||
|
||||
<!-- <mat-form-field class="filterEmployeeId">
|
||||
<input
|
||||
[leadZero]="true"
|
||||
matInput
|
||||
type="tet"
|
||||
mask="separator.3"
|
||||
[decimalMarker]="localeService.decimalSeparator"
|
||||
[thousandSeparator]="''"
|
||||
placeholder="MitarbeiterId"
|
||||
[(ngModel)]=filterObject.employeeId
|
||||
greater="0"
|
||||
(keyup.Enter)="onFilterClick()">
|
||||
</mat-form-field> -->
|
||||
|
||||
<!--
|
||||
<hensel-input class="filterEmployeeId"
|
||||
mask="separator.2"
|
||||
[leadZero]="false"
|
||||
[decimalMarker]="localeService.decimalSeparator"
|
||||
[thousandSeparator]="localeService.thousandSeparator"
|
||||
placeholder="MitarbeiterId"
|
||||
[(ngModel)]=filterObject.employeeId
|
||||
henselDecimal="2"
|
||||
[henselDecimalAllowEmpty]="true"
|
||||
(keyup.Enter)="onFilterClick()"
|
||||
greater="0"
|
||||
>
|
||||
</hensel-input>
|
||||
-->
|
||||
<hensel-input class="filterEmployeeId"
|
||||
mask="separator.0"
|
||||
[leadZero]="true"
|
||||
[decimalMarker]="localeService.decimalSeparator"
|
||||
[thousandSeparator]="''"
|
||||
placeholder="MitarbeiterId"
|
||||
[(ngModel)]=filterObject.employeeId
|
||||
(keyup.Enter)="onFilterClick()"
|
||||
>
|
||||
</hensel-input>
|
||||
|
||||
<hensel-selection
|
||||
id="filterMandant"
|
||||
class="filterMandant"
|
||||
[dataSource]=appDataService.subsidiaryList.items
|
||||
placeholder="Mandant"
|
||||
keyExpr="clientId"
|
||||
displayExpr="subsidiaryCode"
|
||||
sortField="*"
|
||||
[multiSelect]=false
|
||||
separator=","
|
||||
[(selectedItems)]="filterObject.clientId"
|
||||
(selectedItemsChange)="onFilterClick()">
|
||||
</hensel-selection>
|
||||
|
||||
<mat-checkbox
|
||||
class="filterIsActive"
|
||||
name="Enabled"
|
||||
style="float: left"
|
||||
labelPosition="after"
|
||||
(change)="onFilterClick()"
|
||||
[(ngModel)]="filterObject.isActive">
|
||||
Aktiv
|
||||
</mat-checkbox>
|
||||
|
||||
<section class="filterButtons mat-button-withoutcaption">
|
||||
<button id="filterBtnClear" class="filterBtn" mat-stroked-button type=button (click)=onClearClick() title="Reset">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
<button id="filterBtnEmails" class="filterBtn" mat-stroked-button type=button (click)=onEmailClick() title="Emaildresse für ausgewählten Mitarbeiter in die Zwischenablage speichern">
|
||||
<mat-icon>alternate_email</mat-icon>
|
||||
</button>
|
||||
<button id="filterBtnFind" class="filterBtn" mat-stroked-button type=submit (click)=onFilterClick() titel="Suchen">
|
||||
<mat-icon>search</mat-icon>
|
||||
</button>
|
||||
</section>
|
||||
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@ -0,0 +1,77 @@
|
||||
.filterCardContainer {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
grid-column-gap: 15px;
|
||||
grid-template-rows: repeat(1, auto);
|
||||
grid-template-columns: repeat(8, minmax(0, 1fr)) auto auto;
|
||||
grid-template-areas:
|
||||
"filterName filterShortName filterLogin filterDepartment filterWebApp filterAttribute filterEmployeeId filterMandant filterIsActive filterButtons "
|
||||
}
|
||||
|
||||
// @media screen and (max-width:1024px) {
|
||||
// .woassays {
|
||||
// font-size: 1vw;
|
||||
// }
|
||||
// }
|
||||
|
||||
.filterIsActive{
|
||||
|
||||
margin: auto;
|
||||
grid-area: filterIsActive;
|
||||
}
|
||||
.filterMandant {
|
||||
grid-area: filterMandant;
|
||||
}
|
||||
.filterName {
|
||||
grid-area: filterName;
|
||||
}
|
||||
|
||||
.filterShortName {
|
||||
grid-area: filterShortName;
|
||||
}
|
||||
|
||||
.filterLogin {
|
||||
grid-area: filterLogin;
|
||||
}
|
||||
|
||||
.filterWebApp {
|
||||
grid-area: filterWebApp;
|
||||
}
|
||||
|
||||
// .filterEmail {
|
||||
// grid-area: filterEmail;
|
||||
// }
|
||||
|
||||
.filterDepartment {
|
||||
grid-area: filterDepartment;
|
||||
}
|
||||
|
||||
.filterEmployeeId {
|
||||
grid-area: filterEmployeeId;
|
||||
}
|
||||
|
||||
.filterAttribute {
|
||||
grid-area: filterAttribute;
|
||||
}
|
||||
|
||||
.filterButtons {
|
||||
grid-area: filterButtons;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
// .filterBtn {
|
||||
// font-size: 1vw; //scales buttons caption depended from the current view port resolution
|
||||
// }
|
||||
|
||||
.card {
|
||||
padding: 10px;
|
||||
margin: 2px 2px 0px 2px;
|
||||
}
|
||||
|
||||
.filterButtons .filterBtn {
|
||||
width: unset;
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
import * as keycode from '@angular/cdk/keycodes';
|
||||
import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core';
|
||||
import { Employee, EmployeeFullFilter } from '@app_models/employee';
|
||||
import { EmployeeDataService } from '@app_modules/employee/employee-data.service';
|
||||
import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import * as Cnst from '@app_core/consts';
|
||||
import { ClipboardService } from 'ngx-clipboard';
|
||||
import { AuthorizeService } from '@app_core/services/authorize.service';
|
||||
import { UINotifierService } from '@app_core/services/notification/uinotifier.service';
|
||||
import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-filter',
|
||||
templateUrl: './employee-filter.component.html',
|
||||
styleUrls: ['./employee-filter.component.scss'],
|
||||
})
|
||||
export class EmployeeFilterComponent implements OnInit, AfterViewInit {
|
||||
|
||||
constructor(
|
||||
public employeeDataService: EmployeeDataService,
|
||||
public appDataService: AppDataService,
|
||||
public authService: AuthorizeService,
|
||||
public localeService: LocaleService,
|
||||
private clipboardService: ClipboardService,
|
||||
private notifierService: UINotifierService,
|
||||
) { }
|
||||
@Input() public filterObject: EmployeeFullFilter;
|
||||
@Input() employeeDetails: AppBaseEntityWrapper<Employee>;
|
||||
@Input() employeeList: AppBaseEntityListWrapper<Employee>;
|
||||
@Output() public filterFetch = new EventEmitter();
|
||||
|
||||
public dropDownAllCaption = Cnst.EN_DropDownConst4Filter.AllCaption;
|
||||
public dropDownAllValueString = Cnst.EN_DropDownConst4Filter.AllValueString;
|
||||
public dropDownAllValueInt = Cnst.EN_DropDownConst4Filter.AllValueInt;
|
||||
public allCaption = Cnst.EN_DropDownConst4Filter.AllCaption;
|
||||
public allValue: number = Cnst.EN_DropDownConst4Filter.AllValueInt;
|
||||
public noneCaption = Cnst.EN_DropDownConst4Filter.NoneCaption;
|
||||
public noneValue = Cnst.EN_DropDownConst4Filter.NoneValueInt;
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
ngAfterViewInit() { }
|
||||
|
||||
onFilterClick() {
|
||||
if (this.employeeDetails.inViewMode) this.filterFetch.emit();
|
||||
}
|
||||
|
||||
onClearClick() {
|
||||
this.filterObject.filterReset();
|
||||
this.filterObject.isActive = true;
|
||||
this.onFilterClick();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
onEmailClick() {
|
||||
const listEmployeeIds = this.employeeList.items.filter((empl: Employee) => !!empl.email).map((empl: Employee) => empl.entityId);
|
||||
const listEmails = this.employeeList.items.sort((empl1, empl2) => empl1.lastName.localeCompare(empl2.lastName)).map((empl: Employee) => empl.email).filter(email => !!email);
|
||||
if (listEmails.length === 0) return;
|
||||
this.clipboardService.copy(listEmails.join('; '));
|
||||
const endung = (listEmails.length > 1 ? 'n' : '');
|
||||
this.notifierService.showMessage(`${listEmails.length} Emailadresse${endung} wurde${endung} in die Zwischenablage gespeichert`);
|
||||
}
|
||||
|
||||
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
keyboardInput(event: any) {
|
||||
if (!LoginPopupComponent.LOGIN_IS_SHOWN && !this.employeeDetails.keyDownListenerStopped) {
|
||||
if (event.ctrlKey) {
|
||||
switch (event.which) {
|
||||
case keycode.F: //Ctrl + 'f'
|
||||
event.stopPropagation();
|
||||
this.onFilterClick();
|
||||
return false; //processed
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; //default processing
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
<div class="EmployeeList">
|
||||
<app-employee-filter class="FilterComponent"
|
||||
[employeeDetails]=this.employeeDataService.employeeDetails
|
||||
[employeeList]=this.employeeDataService.employeeList
|
||||
[filterObject]=dataSource.filter
|
||||
(filterFetch)="loadData()">
|
||||
</app-employee-filter>
|
||||
<mat-card class="card">
|
||||
<mat-card-header>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<dx-data-grid
|
||||
#gridEmployee
|
||||
id="gridEmployee"
|
||||
[class]="'gridEmployee'+(columnConfigList.withExport ? ' withexport' : '')"
|
||||
[dataSource]="dataSource.items"
|
||||
keyExpr="employeeId"
|
||||
[focusedRowEnabled]="true"
|
||||
[autoNavigateToFocusedRow]="true"
|
||||
[(focusedRowIndex)]=dataSource.focusedItemGridIndex
|
||||
[(focusedRowKey)]="dataSource.focusedItemId"
|
||||
[(selectedRowKeys)]="dataSource.selectedItemIds"
|
||||
[showBorders]="true"
|
||||
[allowColumnResizing]="true"
|
||||
columnResizingMode="nextColumn"
|
||||
noDataText="Keine Daten vorhanden"
|
||||
(onKeyDown)="$event.handled = $event.event.key==='Escape'; dataSource.gridUpDownProcessing($event)"
|
||||
(onFocusedRowChanging)="dataSource.onFocusedRowChanging($event)"
|
||||
(onRowDblClick)="dataSource.focusedEntityShadowed.delayedEdit($event.data['entityId'])"
|
||||
(onExporting)="globals.doExcelExportSimple($event, dataSource.getExportFilename4List())">
|
||||
|
||||
<dxo-export [enabled]="columnConfigList.withExport" [texts]="{exportAll: 'Excel Export'}"></dxo-export>
|
||||
<dxo-header-filter [visible]="false"></dxo-header-filter>
|
||||
<dxo-filter-row [visible]="false" [applyFilter]="true"></dxo-filter-row>
|
||||
<dxo-paging [enabled]="false"></dxo-paging>
|
||||
<dxo-scrolling mode="virtual"></dxo-scrolling>
|
||||
<dxo-load-panel [enabled]="true"></dxo-load-panel>
|
||||
<dxo-sorting mode="multiple">
|
||||
<!--"single" | "multiple" | "none" -->
|
||||
</dxo-sorting>
|
||||
<dxo-selection mode="none">
|
||||
<!-- "multiple" | "none" -->
|
||||
</dxo-selection>
|
||||
|
||||
<ng-container *ngFor="let column of columnConfigList.columns">
|
||||
<ng-container *ngIf=column.visible>
|
||||
<dxi-column
|
||||
[allowHeaderFiltering]=column.allowHeaderFiltering
|
||||
[dataField]=column.dataField
|
||||
[dataType]=column.dataType
|
||||
[caption]=column.caption
|
||||
[width]=column.width
|
||||
[sortIndex]=column.sortIndex
|
||||
[sortOrder]=column.sortOrder
|
||||
[visibleIndex]=column.visibleIndex
|
||||
[visible]=column.visible
|
||||
[fixed]=column.fixed
|
||||
[headerCellTemplate]=column.headerCellTemplate
|
||||
[cellTemplate]=column.cellTemplate
|
||||
[alignment]=column.alignment>
|
||||
<!-- cssClass="headeralignment_center" -->
|
||||
|
||||
<dxo-format *ngIf="column.dataType === 'date'" [type]=localeService.dateFormat></dxo-format>
|
||||
<dxo-format *ngIf="column.dataType === 'datetime'" [type]=localeService.dateTimeFormat></dxo-format>
|
||||
<dxo-lookup *ngIf="column.dataField === 'rangId'" [dataSource]="appDataService.rangList?.items" valueExpr="entityId" displayExpr="rangShortname"></dxo-lookup>
|
||||
</dxi-column>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div *dxTemplate="let cell of 'numberTemplate_0'">
|
||||
{{cell.value | number:'1.0-0':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_1'">
|
||||
{{cell.value | number:'1.1-1':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_2'">
|
||||
{{cell.value | number:'1.2-2':culture}}
|
||||
</div>
|
||||
<div *dxTemplate="let cell of 'numberTemplate_3'">
|
||||
{{cell.value | number:'1.3-3':culture}}
|
||||
</div>
|
||||
</dx-data-grid>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div *ngIf="this.employeeDataService.employeeDetails.inNotViewMode" class="disableClicks"></div>
|
||||
</div>
|
||||
@ -0,0 +1,38 @@
|
||||
.EmployeeList {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: auto minmax(0, 1fr); // row relationships
|
||||
grid-template-columns: minmax(0, 1fr); // column relationship
|
||||
grid-row-gap: 7px;
|
||||
grid-template-areas:
|
||||
'filter'
|
||||
'grid';
|
||||
}
|
||||
|
||||
.FilterComponent {
|
||||
grid-area: filter; // grid area: auto height 1fr width
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
.card {
|
||||
grid-area: grid;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
margin: 0;
|
||||
border-radius: 0px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.gridEmployee {
|
||||
position: absolute; // position absolut ist hier zwingend! Die position ist absolut innerhalb mehrerer parent divs und darf sich NICHT über diese hinausstrecken.
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist';
|
||||
import { Globals } from '@app_core/services/globals';
|
||||
import { LocaleService } from '@app_core/services/localization/locale.service';
|
||||
import { Employee } from '@app_models/employee';
|
||||
import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper';
|
||||
import { AppDataService } from '@app_services/app.data.service';
|
||||
import { EmployeeDataService } from '../employee-data.service';
|
||||
import { ColumnConfig, EN_Alignment, EN_SortOrder } from '@app_core/components/grid-config/columnconfig';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee-list',
|
||||
templateUrl: './employee-list.component.html',
|
||||
styleUrls: ['./employee-list.component.scss']
|
||||
})
|
||||
export class EmployeeListComponent implements OnInit {
|
||||
@Input() public dataSource: AppBaseEntityListWrapper<Employee>;
|
||||
// @ViewChild('gridCatalog') dxGrid: DxDataGridComponent;
|
||||
|
||||
public columnConfigList: ColumnConfigList = new ColumnConfigList();
|
||||
|
||||
|
||||
constructor(
|
||||
public employeeDataService: EmployeeDataService,
|
||||
public appDataService: AppDataService,
|
||||
public localeService: LocaleService,
|
||||
public globals: Globals,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initColumns();
|
||||
}
|
||||
|
||||
|
||||
initColumns() {
|
||||
let col: ColumnConfig;
|
||||
|
||||
// col = this.columnConfigList.addNumber('id', 'EmployeeId', 7);
|
||||
|
||||
if (this.appDataService.showIds) col = this.columnConfigList.addNumber('Id', 'entityId', 7, 0);
|
||||
if (this.appDataService.showIds) col = this.columnConfigList.add('Nr', 'employeeNo', 7);
|
||||
|
||||
col = this.columnConfigList.add('Nachname', 'lastName', 25);
|
||||
col.sortIndex = 1;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
|
||||
col = this.columnConfigList.add('Vorname', 'firstName', 15);
|
||||
col.sortIndex = 2;
|
||||
col.sortOrder = EN_SortOrder.asc;
|
||||
|
||||
// col = this.columnConfigList.add('Anrede', 'salutation', 10);
|
||||
col = this.columnConfigList.add('Kürzel', 'shortName', 7);
|
||||
col = this.columnConfigList.add('Position', 'position', 25);
|
||||
|
||||
col = this.columnConfigList.add('Login', 'loginName', 15);
|
||||
col = this.columnConfigList.add('Email', 'email', 30);
|
||||
col = this.columnConfigList.add('Rang', 'rangId', 10);
|
||||
|
||||
col = this.columnConfigList.add('Handynummer', 'mobilePhoneNo', 20);
|
||||
col = this.columnConfigList.add('Festnetznummer', 'phoneNo', 20);
|
||||
|
||||
|
||||
// if (this.appDataService.showIds) col =
|
||||
col = this.columnConfigList.add('Department', 'departmentNamesList', 30);
|
||||
col = this.columnConfigList.add('Webapps', 'webappNamesList', 25);
|
||||
col = this.columnConfigList.add('Merkmale', 'attributeNamesList', 20);
|
||||
// this.columnConfigList.addNumber('Firma-Id', 'clientId', 7);
|
||||
col = this.columnConfigList.add('Mandant', 'mandantCode', 15);
|
||||
col = this.columnConfigList.addBoolean('Aktiv', 'isActive', -50);
|
||||
col.alignment = EN_Alignment.left;
|
||||
|
||||
this.columnConfigList.recalcWidth();
|
||||
}
|
||||
|
||||
|
||||
public loadData() {
|
||||
this.employeeDataService.loadData();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
<div class="EmployeeComponent">
|
||||
<app-employee-list [dataSource]=employeeDataService.employeeList class="EmployeeListComponent"></app-employee-list>
|
||||
<app-employee-detail [employeeDetails]="employeeDataService.employeeList.focusedEntityShadowed" class="EmployeeDetailsComponent"></app-employee-detail>
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
.EmployeeComponent {
|
||||
padding: 0 0 0; // no extra padding -> padding is calculated in the child comp
|
||||
margin: 0; // see above
|
||||
overflow: hidden; // overflow hidden => all "to big" child components are hidden
|
||||
display: grid; // we define a grid
|
||||
width: 100%; // 100 % view width (hardware screen)
|
||||
height: 100%; // 100% view height
|
||||
grid-template-rows: minmax(0, 1fr) auto; // row relationships
|
||||
grid-template-columns: minmax(0, 1fr); // column relationship
|
||||
grid-template-areas: 'list''details';
|
||||
grid-column-gap: 5px;
|
||||
grid-row-gap: 5px;
|
||||
}
|
||||
|
||||
.EmployeeListComponent {
|
||||
grid-area: list;
|
||||
}
|
||||
|
||||
.EmployeeDetailsComponent {
|
||||
grid-area: details;
|
||||
z-index: 10;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { EmployeeDataService } from './employee-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employee',
|
||||
templateUrl: './employee.component.html',
|
||||
styleUrls: ['./employee.component.scss']
|
||||
})
|
||||
export class EmployeeComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
public employeeDataService: EmployeeDataService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { AngularMaterialModule } from '@app_core/components/angular-material.module';
|
||||
import { DxButtonModule, DxDataGridModule, DxFileUploaderModule, DxPieChartModule, DxTemplateModule, DxTooltipModule } from 'devextreme-angular';
|
||||
import { EmployeeAttributeComponent } from './employee-detail/employee-attribute/employee-attribute.component';
|
||||
import { EmployeeContentComponent } from './employee-detail/employee-content/employee-content.component';
|
||||
import { EmployeeDepartmentComponent } from './employee-detail/employee-department/employee-department.component';
|
||||
import { EmployeeToDepartmentPopupeditComponent } from './employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component';
|
||||
import { EmployeeDetailComponent } from './employee-detail/employee-detail.component';
|
||||
import { EmployeeWebappComponent } from './employee-detail/employee-webapp/employee-webapp.component';
|
||||
import { EmployeeToWebAppPopupeditComponent } from './employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component';
|
||||
import { EmployeeFilterComponent } from './employee-list/employee-filter/employee-filter.component';
|
||||
import { EmployeeListComponent } from './employee-list/employee-list.component';
|
||||
import { EmployeeComponent } from './employee.component';
|
||||
import { EmployeeRoutingModule } from './employee.routing.module';
|
||||
import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component';
|
||||
import { HenselInputComponent } from '@app_core/components/hensel-input/hensel-input.component';
|
||||
import { NgxMaskDirective, NgxMaskPipe } from 'ngx-mask';
|
||||
import { HenselMaskDecimalDirective } from '@app_core/directives/hensel-decimal.directive';
|
||||
import { HenselValidator } from '@app_core/validators/hensel-validator.directive';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
EmployeeComponent,
|
||||
EmployeeListComponent,
|
||||
EmployeeContentComponent,
|
||||
EmployeeAttributeComponent,
|
||||
EmployeeDetailComponent,
|
||||
EmployeeFilterComponent,
|
||||
EmployeeWebappComponent,
|
||||
EmployeeDepartmentComponent,
|
||||
EmployeeToDepartmentPopupeditComponent,
|
||||
EmployeeToWebAppPopupeditComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
EmployeeRoutingModule,
|
||||
AngularMaterialModule,
|
||||
DxDataGridModule,
|
||||
FormsModule,
|
||||
HenselSelectionComponent,
|
||||
HenselInputComponent,
|
||||
HenselMaskDecimalDirective,
|
||||
HenselValidator,
|
||||
DxFileUploaderModule,
|
||||
DxButtonModule,
|
||||
DxTooltipModule,
|
||||
DxTemplateModule,
|
||||
DxPieChartModule,
|
||||
NgxMaskDirective,
|
||||
NgxMaskPipe,
|
||||
],
|
||||
providers: [],
|
||||
exports: []
|
||||
})
|
||||
export class EmployeeModule { }
|
||||
@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { EmployeeComponent } from './employee.component';
|
||||
import { AuthGuard } from '@app_core/services/authguard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '**',
|
||||
component: EmployeeComponent,
|
||||
canActivate: [AuthGuard]
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class EmployeeRoutingModule { }
|
||||
97
ClientApp/staff-db-ui/src/app/shared/app.consts.ts
Normal file
97
ClientApp/staff-db-ui/src/app/shared/app.consts.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { IENVIRONMENT } from '@app_core/injection-tokens';
|
||||
import { ACCOUNT_PAGE, IAppPage, LOGIN_PAGE } from '@app_core/services/globals';
|
||||
|
||||
export const SUPPORTED_LANGUAGES = ['de', 'en'];
|
||||
|
||||
declare const environment: IENVIRONMENT;
|
||||
export const APP_TITLE: string = environment['APP_TITLE'] ?? 'StaffDB';
|
||||
export const cnst_DefaultCulture = environment.culture ?? 'de-DE';
|
||||
export const cnst_DefaultLanguage = environment.language ?? 'de';
|
||||
|
||||
// page description, wich is used for routing as well for preparing routings menus and intern for page loading
|
||||
export const APP_PAGES: IAppPage[] = [
|
||||
{
|
||||
caption: 'Mitarbeiter',
|
||||
path: 'employee',
|
||||
loadChildren: () => import('@app_modules/employee/employee.module').then(m => m.EmployeeModule),
|
||||
icon: '',
|
||||
messageCaption: 'Employee',
|
||||
},
|
||||
{
|
||||
caption: 'Abteilungen',
|
||||
path: 'departments',
|
||||
loadChildren: () => import('@app_modules/department/department.module').then(m => m.DepartmentModule),
|
||||
icon: '',
|
||||
messageCaption: 'Department',
|
||||
},
|
||||
ACCOUNT_PAGE,
|
||||
LOGIN_PAGE,
|
||||
];
|
||||
|
||||
// named constants to access the arry APP_PAGES
|
||||
|
||||
export const enum EN_AppPages {
|
||||
Employee = 0,
|
||||
Department = 1,
|
||||
Settings = 2,
|
||||
Login = 3,
|
||||
}
|
||||
|
||||
// named constants with numbers of http requests of data loading for every page for maintain of spinner
|
||||
|
||||
export const enum EN_HttpQueriesCount4Page {
|
||||
Employee = 1,
|
||||
Department = 1,
|
||||
Login = 10, //no of quires in load stammdata
|
||||
}
|
||||
|
||||
export function getPageIndex(page: string): number {
|
||||
return APP_PAGES.findIndex((pg) => pg.path === page);
|
||||
}
|
||||
|
||||
|
||||
export enum EN_AppEntities {
|
||||
//-- base data entities
|
||||
Employee = 'employee',
|
||||
CostCentre = 'costcentre',
|
||||
Vendor = 'vendor',
|
||||
EmployeeStatus = 'employeestatus',
|
||||
Rang = 'rang',
|
||||
DocumentArt = 'documentart',
|
||||
Project = 'project',
|
||||
Department = 'department',
|
||||
WindreamSearch = 'windreamsearch',
|
||||
WindreamIndex = 'windreamindex',
|
||||
WindreamIndexToWindreamSearchToDepartment = 'windreamindextowindreamsearchtodepartment',
|
||||
WindreamSearchToDepartment = 'windreamsearchtodepartment',
|
||||
WindreamSearchItemToWindreamSearchToDepartment = 'windreamsearchitemtowindreamsearchtodepartment',
|
||||
WindreamSearchItem = 'windreamsearchitem',
|
||||
DocumentArtToDepartment = 'documentarttodepartment',
|
||||
EmployeeToDepartment = 'employeetodepartment',
|
||||
EmployeeToWebapp = 'employeetowebapp',
|
||||
WebApp = 'webapp',
|
||||
WebAppRole = 'webapprole',
|
||||
WebAppToDepartment = 'webapptodepartment',
|
||||
WebAppToWebAppRole = 'webapptowebapprole',
|
||||
EmployeeAttribute = 'employeeattribute',
|
||||
EmployeeToAttribute = 'employeetoattribute',
|
||||
WebAppAdditionalRole = 'webappadditionalrole',
|
||||
WebAppToWebAppAdditionalRole = 'webapptowebappadditionalrole',
|
||||
WindreamSearchToDepartmentCopyWindreamTile = 'windreamSearchToDepartment/CopyWindreamTile',
|
||||
DepartmentCopyWindreamTiles = 'department/copyWindreamTiles',
|
||||
Subsidiary = 'Subsidiary'
|
||||
}
|
||||
|
||||
|
||||
export enum EN_EmployeeStatus {
|
||||
MainFunction = 1,
|
||||
AdditionalFunction = 2,
|
||||
}
|
||||
|
||||
|
||||
export enum EN_EmployeeRang {
|
||||
Mitarbeiter = 4,
|
||||
}
|
||||
|
||||
|
||||
export const cnst_LoadedEntitiesExpiresInMs = 30000; //30s
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user