diff --git a/web/package-lock.json b/web/package-lock.json
index 27da3c403..9eb81ac5f 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -38,10 +38,19 @@
"requires": {
"ajv": "5.5.2",
"chokidar": "1.7.0",
- "rxjs": "5.5.6",
+ "rxjs": "5.5.10",
"source-map": "0.5.7"
},
"dependencies": {
+ "rxjs": {
+ "version": "5.5.10",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz",
+ "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==",
+ "dev": true,
+ "requires": {
+ "symbol-observable": "1.0.1"
+ }
+ },
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -57,7 +66,18 @@
"dev": true,
"requires": {
"@ngtools/json-schema": "1.2.0",
- "rxjs": "5.5.6"
+ "rxjs": "5.5.10"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "5.5.10",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz",
+ "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==",
+ "dev": true,
+ "requires": {
+ "symbol-observable": "1.0.1"
+ }
+ }
}
},
"@angular/animations": {
@@ -117,7 +137,7 @@
"postcss-url": "7.3.1",
"raw-loader": "0.5.1",
"resolve": "1.5.0",
- "rxjs": "5.5.6",
+ "rxjs": "5.5.10",
"sass-loader": "6.0.7",
"semver": "5.5.0",
"silent-error": "1.1.0",
@@ -176,6 +196,15 @@
"osenv": "0.1.4"
}
},
+ "rxjs": {
+ "version": "5.5.10",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz",
+ "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==",
+ "dev": true,
+ "requires": {
+ "symbol-observable": "1.0.1"
+ }
+ },
"supports-color": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
@@ -345,9 +374,20 @@
"integrity": "sha512-7aVP4994Hu8vRdTTohXkfGWEwLhrdNP3EZnWyBootm5zshWqlQojUGweZe5zwewsKcixeVOiy2YtW+aI4aGSLA==",
"dev": true,
"requires": {
- "rxjs": "5.5.6",
+ "rxjs": "5.5.10",
"semver": "5.5.0",
"semver-intersect": "1.3.1"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "5.5.10",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz",
+ "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==",
+ "dev": true,
+ "requires": {
+ "symbol-observable": "1.0.1"
+ }
+ }
}
},
"@types/jasmine": {
@@ -2096,7 +2136,7 @@
},
"compression": {
"version": "1.7.2",
- "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.2.tgz",
+ "resolved": "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz",
"integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=",
"dev": true,
"requires": {
@@ -9482,9 +9522,9 @@
}
},
"rxjs": {
- "version": "5.5.6",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
- "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
+ "version": "5.5.9",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.9.tgz",
+ "integrity": "sha512-DHG9AHmCmgaFWgjBcXp6NxFDmh3MvIA62GqTWmLnTzr/3oZ6h5hLD8NA+9j+GF0jEwklNIpI4KuuyLG8UWMEvQ==",
"requires": {
"symbol-observable": "1.0.1"
}
diff --git a/web/package.json b/web/package.json
index 743baaca0..d4a8c0f55 100644
--- a/web/package.json
+++ b/web/package.json
@@ -23,21 +23,21 @@
"@angular/platform-browser": "5.2.10",
"@angular/platform-browser-dynamic": "5.2.10",
"@angular/router": "5.2.10",
- "file-saver": "1.3.3",
"angular-svg-icon": "5.0.0",
"angular-tree-component": "7.1.0",
"bootstrap": "3.3.7",
"bootstrap-sass": "3.3.7",
+ "chart.js": "2.7.1",
"core-js": "2.5.3",
+ "file-saver": "1.3.3",
"jquery": "3.3.1",
"magic-string": "0.22.4",
+ "ng2-auto-complete": "0.12.0",
+ "ng2-charts": "1.6.0",
"ngx-bootstrap": "2.0.1",
"node-sass": "4.7.2",
- "rxjs": "5.5.6",
- "zone.js": "0.8.20",
- "chart.js": "2.7.1",
- "ng2-charts": "1.6.0",
- "ng2-auto-complete": "0.12.0"
+ "rxjs": "5.5.9",
+ "zone.js": "0.8.20"
},
"devDependencies": {
"@angular/cli": "1.7.3",
diff --git a/web/src/app/administration/administration.module.ts b/web/src/app/administration/administration.module.ts
index 7abeb9776..96f3b6d7b 100644
--- a/web/src/app/administration/administration.module.ts
+++ b/web/src/app/administration/administration.module.ts
@@ -7,6 +7,7 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
import { AlertModule } from 'ngx-bootstrap';
import { SharedModule } from 'app/shared/shared.module';
import { AdministrationRoutingModule } from './administration-routing.module';
+import { TypeaheadModule } from 'ngx-bootstrap';
/**
* Components
@@ -39,7 +40,6 @@ import { ClassificationsService } from './services/classifications/classificatio
import { ClassificationTypesService } from './services/classification-types/classification-types.service';
import { ClassificationCategoriesService } from './services/classification-categories-service/classification-categories.service';
-
const MODULES = [
CommonModule,
FormsModule,
@@ -47,7 +47,8 @@ const MODULES = [
AngularSvgIconModule,
AlertModule,
SharedModule,
- AdministrationRoutingModule
+ AdministrationRoutingModule,
+ TypeaheadModule
];
const DECLARATIONS = [
diff --git a/web/src/app/administration/workbasket/details/access-items/access-items.component.html b/web/src/app/administration/workbasket/details/access-items/access-items.component.html
index f600442fe..287fc473f 100644
--- a/web/src/app/administration/workbasket/details/access-items/access-items.component.html
+++ b/web/src/app/administration/workbasket/details/access-items/access-items.component.html
@@ -41,13 +41,13 @@
-
-
-
-
+ |
+
+
+
|
diff --git a/web/src/app/administration/workbasket/details/access-items/access-items.component.scss b/web/src/app/administration/workbasket/details/access-items/access-items.component.scss
index 6f3248ece..f813f7f30 100644
--- a/web/src/app/administration/workbasket/details/access-items/access-items.component.scss
+++ b/web/src/app/administration/workbasket/details/access-items/access-items.component.scss
@@ -5,9 +5,14 @@ td > input[type="checkbox"] {
overflow-x: auto;
}
.text-width{
+ width: 100%;
min-width: 180px;
}
+.required-header {
+ width: 200px;
+}
.required-header:after {
+
content:" *";
color: red;
}
@@ -17,3 +22,11 @@ td {
border-bottom: 1px solid #f0ad4e;;
}
}
+.table > thead > tr > th {
+ max-width: 150px;
+ border-bottom: none;
+}
+
+.has-warning.taskana-type-ahead {
+ border-bottom: 1px solid #f0ad4e;
+}
\ No newline at end of file
diff --git a/web/src/app/administration/workbasket/details/access-items/access-items.component.spec.ts b/web/src/app/administration/workbasket/details/access-items/access-items.component.spec.ts
index 54cbdda7f..ddc172a54 100644
--- a/web/src/app/administration/workbasket/details/access-items/access-items.component.spec.ts
+++ b/web/src/app/administration/workbasket/details/access-items/access-items.component.spec.ts
@@ -1,6 +1,6 @@
-import { SimpleChange } from '@angular/core';
+import { SimpleChange, Component, forwardRef, Input } from '@angular/core';
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule, JsonpModule } from '@angular/http';
import { AngularSvgIconModule } from 'angular-svg-icon';
@@ -26,6 +26,37 @@ import { DomainService } from 'app/services/domain/domain.service';
import { DomainServiceMock } from 'app/services/domain/domain.service.mock';
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
+
+@Component({
+ selector: 'taskana-type-ahead',
+ template: 'dummydetail',
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ multi: true,
+ useExisting: forwardRef(() => TaskanaTypeAheadComponent),
+ }
+ ]
+})
+export class TaskanaTypeAheadComponent implements ControlValueAccessor {
+ @Input()
+ placeHolderMessage;
+
+ writeValue(obj: any): void {
+
+ }
+ registerOnChange(fn: any): void {
+
+ }
+ registerOnTouched(fn: any): void {
+
+ }
+ setDisabledState?(isDisabled: boolean): void {
+
+ }
+
+}
+
describe('AccessItemsComponent', () => {
let component: AccessItemsComponent;
let fixture: ComponentFixture;
@@ -33,7 +64,7 @@ describe('AccessItemsComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [SpinnerComponent, AccessItemsComponent, GeneralMessageModalComponent],
+ declarations: [SpinnerComponent, AccessItemsComponent, GeneralMessageModalComponent, TaskanaTypeAheadComponent],
imports: [FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule, ReactiveFormsModule],
providers: [WorkbasketService, AlertService, ErrorModalService, SavingWorkbasketService, RequestInProgressService,
{
diff --git a/web/src/app/administration/workbasket/details/access-items/access-items.component.ts b/web/src/app/administration/workbasket/details/access-items/access-items.component.ts
index 938ef0efd..f1f351d91 100644
--- a/web/src/app/administration/workbasket/details/access-items/access-items.component.ts
+++ b/web/src/app/administration/workbasket/details/access-items/access-items.component.ts
@@ -15,9 +15,10 @@ import { AlertService } from 'app/services/alert/alert.service';
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
import { TitlesService } from 'app/services/titles/titles.service';
import { CustomFieldsService } from '../../../../services/custom-fields/custom-fields.service';
+import { Observable } from 'rxjs/Observable';
+import { TypeaheadMatch } from 'ngx-bootstrap/typeahead';
declare var $: any;
-
@Component({
selector: 'taskana-workbasket-access-items',
templateUrl: './access-items.component.html',
@@ -25,7 +26,6 @@ declare var $: any;
})
export class AccessItemsComponent implements OnChanges, OnDestroy {
-
@Input()
workbasket: Workbasket;
@Input()
@@ -65,7 +65,11 @@ export class AccessItemsComponent implements OnChanges, OnDestroy {
private errorModalService: ErrorModalService,
private savingWorkbaskets: SavingWorkbasketService,
private requestInProgressService: RequestInProgressService,
- private customFieldService: CustomFieldsService) { }
+ private customFieldService: CustomFieldsService) {
+
+ }
+
+
ngOnChanges(changes: SimpleChanges): void {
if (!this.initialized && changes.active && changes.active.currentValue === 'accessItems') {
@@ -75,6 +79,7 @@ export class AccessItemsComponent implements OnChanges, OnDestroy {
this.setBadge();
}
}
+
private init() {
this.initialized = true;
if (!this.workbasket._links.accessItems) {
@@ -133,6 +138,7 @@ export class AccessItemsComponent implements OnChanges, OnDestroy {
})
return false;
}
+
private setBadge() {
if (this.action === ACTION.COPY) {
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
diff --git a/web/src/app/administration/workbasket/details/information/workbasket-information.component.html b/web/src/app/administration/workbasket/details/information/workbasket-information.component.html
index 9bd0e07ec..b4fea6bfe 100644
--- a/web/src/app/administration/workbasket/details/information/workbasket-information.component.html
+++ b/web/src/app/administration/workbasket/details/information/workbasket-information.component.html
@@ -6,7 +6,7 @@
+
@@ -39,9 +39,8 @@
-
+
-
+
-
+
diff --git a/web/src/app/administration/workbasket/details/information/workbasket-information.component.spec.ts b/web/src/app/administration/workbasket/details/information/workbasket-information.component.spec.ts
index 304166566..e0d2fe94e 100644
--- a/web/src/app/administration/workbasket/details/information/workbasket-information.component.spec.ts
+++ b/web/src/app/administration/workbasket/details/information/workbasket-information.component.spec.ts
@@ -1,13 +1,13 @@
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { WorkbasketService } from 'app/administration/services/workbasket/workbasket.service';
import { WorkbasketInformationComponent } from './workbasket-information.component';
-import { FormsModule } from '@angular/forms';
+import { FormsModule, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
import { RouterTestingModule } from '@angular/router/testing';
import { Observable } from 'rxjs/Observable';
-import { Component } from '@angular/core';
+import { Component, Input, forwardRef } from '@angular/core';
import { Routes } from '@angular/router';
import { AppModule } from 'app/app.module'
@@ -37,6 +37,36 @@ import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.se
export class DummyDetailComponent {
}
+@Component({
+ selector: 'taskana-type-ahead',
+ template: 'dummydetail',
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ multi: true,
+ useExisting: forwardRef(() => TaskanaTypeAheadComponent),
+ }
+ ]
+})
+export class TaskanaTypeAheadComponent implements ControlValueAccessor {
+ @Input()
+ placeHolderMessage;
+
+ writeValue(obj: any): void {
+
+ }
+ registerOnChange(fn: any): void {
+
+ }
+ registerOnTouched(fn: any): void {
+
+ }
+ setDisabledState?(isDisabled: boolean): void {
+
+ }
+
+}
+
const routes: Routes = [
{ path: ':id', component: DummyDetailComponent, outlet: 'detail' },
{ path: 'someNewId', component: DummyDetailComponent }
@@ -50,7 +80,8 @@ describe('InformationComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [WorkbasketInformationComponent, IconTypeComponent, MapValuesPipe,
- RemoveNoneTypePipe, SpinnerComponent, GeneralMessageModalComponent, DummyDetailComponent],
+ RemoveNoneTypePipe, SpinnerComponent, GeneralMessageModalComponent, DummyDetailComponent,
+ TaskanaTypeAheadComponent],
imports: [FormsModule,
AngularSvgIconModule,
HttpClientModule,
diff --git a/web/src/app/administration/workbasket/details/information/workbasket-information.component.ts b/web/src/app/administration/workbasket/details/information/workbasket-information.component.ts
index 3c70b0a01..66ec053fb 100644
--- a/web/src/app/administration/workbasket/details/information/workbasket-information.component.ts
+++ b/web/src/app/administration/workbasket/details/information/workbasket-information.component.ts
@@ -42,7 +42,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
custom3Field = this.customFieldsService.getCustomField('Custom 3', 'workbaskets.information.custom3');
custom4Field = this.customFieldsService.getCustomField('Custom 4', 'workbaskets.information.custom4');
-
private workbasketSubscription: Subscription;
private routeSubscription: Subscription;
@@ -132,7 +131,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
});
}
-
private beforeRequest() {
this.requestInProgressService.setRequestInProgress(true);
}
diff --git a/web/src/app/administration/workbasket/details/workbasket-details.component.spec.ts b/web/src/app/administration/workbasket/details/workbasket-details.component.spec.ts
index c6d722cee..88b847dd7 100644
--- a/web/src/app/administration/workbasket/details/workbasket-details.component.spec.ts
+++ b/web/src/app/administration/workbasket/details/workbasket-details.component.spec.ts
@@ -1,8 +1,8 @@
-import { Component, Input } from '@angular/core';
+import { Component, Input, forwardRef } from '@angular/core';
import { async, ComponentFixture, TestBed, } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router, Routes } from '@angular/router';
-import { FormsModule } from '@angular/forms';
+import { FormsModule, NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
@@ -58,6 +58,37 @@ export class FilterComponent {
export class DummyDetailComponent {
}
+@Component({
+ selector: 'taskana-type-ahead',
+ template: 'dummydetail',
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ multi: true,
+ useExisting: forwardRef(() => TaskanaTypeAheadComponent),
+ }
+ ]
+})
+export class TaskanaTypeAheadComponent implements ControlValueAccessor {
+
+ @Input()
+ placeHolderMessage;
+
+ writeValue(obj: any): void {
+
+ }
+ registerOnChange(fn: any): void {
+
+ }
+ registerOnTouched(fn: any): void {
+
+ }
+ setDisabledState?(isDisabled: boolean): void {
+
+ }
+
+}
+
describe('WorkbasketDetailsComponent', () => {
let component: WorkbasketDetailsComponent;
let fixture: ComponentFixture;
@@ -77,7 +108,8 @@ describe('WorkbasketDetailsComponent', () => {
imports: [RouterTestingModule.withRoutes(routes), FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
declarations: [WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent,
IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, AlertComponent, GeneralMessageModalComponent, AccessItemsComponent,
- DistributionTargetsComponent, FilterComponent, DualListComponent, DummyDetailComponent, SelectWorkBasketPipe],
+ DistributionTargetsComponent, FilterComponent, DualListComponent, DummyDetailComponent,
+ TaskanaTypeAheadComponent, SelectWorkBasketPipe],
providers: [WorkbasketService, MasterAndDetailService, ErrorModalService, RequestInProgressService,
AlertService, SavingWorkbasketService, {
provide: DomainService,
diff --git a/web/src/app/app.module.ts b/web/src/app/app.module.ts
index f58dde95d..37984d1b3 100644
--- a/web/src/app/app.module.ts
+++ b/web/src/app/app.module.ts
@@ -50,11 +50,11 @@ import { APP_BASE_HREF } from '@angular/common';
const MODULES = [
+ TabsModule.forRoot(),
+ AlertModule.forRoot(),
BrowserModule,
FormsModule,
- TabsModule.forRoot(),
AppRoutingModule,
- AlertModule.forRoot(),
AngularSvgIconModule,
HttpClientModule,
BrowserAnimationsModule,
@@ -66,7 +66,7 @@ const MODULES = [
const DECLARATIONS = [
AppComponent,
NavBarComponent,
- UserInformationComponent
+ UserInformationComponent,
];
export function startupServiceFactory(startupService: StartupService): () => Promise {
diff --git a/web/src/app/guards/admin-guard.ts b/web/src/app/guards/admin-guard.ts
deleted file mode 100644
index d21a9513e..000000000
--- a/web/src/app/guards/admin-guard.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Observable } from 'rxjs/Observable';
-import { HttpClient } from '@angular/common/http';
-import { CanActivate, Router } from '@angular/router';
-import { Injectable } from '@angular/core';
-import { DomainService } from 'app/services/domain/domain.service';
-import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
-import { ErrorModel } from 'app/models/modal-error';
-import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
-
-@Injectable()
-export class AdminGuard implements CanActivate {
- constructor(private taskanaEngineService: TaskanaEngineService, public router: Router) { }
-
- canActivate() {
- return this.taskanaEngineService.getUserInformation().map(userInfo => {
- if (userInfo.roles.length === 0) {
- return this.navigateToWorplace();
- }
- const adminRole = userInfo.roles.find(role => {
- if (role === 'ADMIN') {
- return true;
- }
- });
- if (adminRole) {
- return true;
- }
- return this.navigateToWorplace();
- }).catch(() => {
- return Observable.of(this.navigateToWorplace())
- });
- }
-
- navigateToWorplace(): boolean {
- this.router.navigate(['workplace']);
- return false
- }
-}
diff --git a/web/src/app/guards/business-admin-guard.ts b/web/src/app/guards/business-admin-guard.ts
index b1fd56379..a593e89d6 100644
--- a/web/src/app/guards/business-admin-guard.ts
+++ b/web/src/app/guards/business-admin-guard.ts
@@ -6,10 +6,12 @@ import { DomainService } from 'app/services/domain/domain.service';
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
import { ErrorModel } from 'app/models/modal-error';
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
+import { WindowRefService } from 'app/services/window/window.service';
@Injectable()
export class BusinessAdminGuard implements CanActivate {
- constructor(private taskanaEngineService: TaskanaEngineService, public router: Router) { }
+ constructor(private taskanaEngineService: TaskanaEngineService, public router: Router,
+ private window: WindowRefService) { }
canActivate() {
return this.taskanaEngineService.getUserInformation().map(userInfo => {
@@ -17,7 +19,7 @@ export class BusinessAdminGuard implements CanActivate {
return this.navigateToWorplace();
}
const adminRole = userInfo.roles.find(role => {
- if (role === 'BUSINESS_ADMIN' || role === 'ADMIN' ) {
+ if (role === 'BUSINESS_ADMIN' || role === 'ADMIN') {
return true;
}
});
@@ -32,7 +34,9 @@ export class BusinessAdminGuard implements CanActivate {
}
navigateToWorplace(): boolean {
- this.router.navigate(['workplace']);
+ if (this.window.nativeWindow.location.href.indexOf('administration') !== -1) {
+ this.router.navigate(['workplace']);
+ }
return false
}
}
diff --git a/web/src/app/guards/monitor-guard.ts b/web/src/app/guards/monitor-guard.ts
index 37f3eaf51..7add44c11 100644
--- a/web/src/app/guards/monitor-guard.ts
+++ b/web/src/app/guards/monitor-guard.ts
@@ -6,10 +6,12 @@ import { DomainService } from 'app/services/domain/domain.service';
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
import { ErrorModel } from 'app/models/modal-error';
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
+import { WindowRefService } from 'app/services/window/window.service';
@Injectable()
export class MonitorGuard implements CanActivate {
- constructor(private taskanaEngineService: TaskanaEngineService, public router: Router) { }
+ constructor(private taskanaEngineService: TaskanaEngineService, public router: Router,
+ private window: WindowRefService) { }
canActivate() {
return this.taskanaEngineService.getUserInformation().map(userInfo => {
@@ -17,7 +19,7 @@ export class MonitorGuard implements CanActivate {
return this.navigateToWorplace();
}
const adminRole = userInfo.roles.find(role => {
- if (role === 'MONITOR' || role === 'ADMIN' ) {
+ if (role === 'MONITOR' || role === 'ADMIN') {
return true;
}
});
@@ -32,7 +34,9 @@ export class MonitorGuard implements CanActivate {
}
navigateToWorplace(): boolean {
- this.router.navigate(['workplace']);
+ if (this.window.nativeWindow.location.href.indexOf('monitor') !== -1) {
+ this.router.navigate(['workplace']);
+ }
return false
}
}
diff --git a/web/src/app/models/access-id.ts b/web/src/app/models/access-id.ts
new file mode 100644
index 000000000..16cfb5e4d
--- /dev/null
+++ b/web/src/app/models/access-id.ts
@@ -0,0 +1,8 @@
+import { LinksClassification } from 'app/models/links-classfication';
+
+export class AccessIdDefinition {
+ constructor(
+ public accessId: string = undefined,
+ public name: string = undefined) {
+ }
+}
diff --git a/web/src/app/shared/services/access-ids/access-ids.service.spec.ts b/web/src/app/shared/services/access-ids/access-ids.service.spec.ts
new file mode 100644
index 000000000..fc5019db4
--- /dev/null
+++ b/web/src/app/shared/services/access-ids/access-ids.service.spec.ts
@@ -0,0 +1,18 @@
+import { TestBed, inject } from '@angular/core/testing';
+
+import { AccessIdsService } from './access-ids.service';
+import { HttpClientModule } from '@angular/common/http';
+import { HttpModule } from '@angular/http';
+
+describe('ValidateAccessItemsService', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientModule, HttpModule],
+ providers: [AccessIdsService]
+ });
+ });
+
+ it('should be created', inject([AccessIdsService], (service: AccessIdsService) => {
+ expect(service).toBeTruthy();
+ }));
+});
diff --git a/web/src/app/shared/services/access-ids/access-ids.service.ts b/web/src/app/shared/services/access-ids/access-ids.service.ts
new file mode 100644
index 000000000..1f5ffc3a6
--- /dev/null
+++ b/web/src/app/shared/services/access-ids/access-ids.service.ts
@@ -0,0 +1,24 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { environment } from 'environments/environment';
+
+
+import { AccessIdDefinition } from 'app/models/access-id';
+import { Observable } from 'rxjs/Observable';
+
+@Injectable()
+export class AccessIdsService {
+
+ private url = environment.taskanaRestUrl + '/v1/validate-access-id';
+
+ constructor(
+ private httpClient: HttpClient) { }
+
+ getAccessItemsInformation(token): Observable> {
+ if (!token) {
+ return Observable.of([]);
+ }
+ return this.httpClient.get>(`${this.url}?search=${token}`);
+ };
+
+}
diff --git a/web/src/app/shared/shared.module.ts b/web/src/app/shared/shared.module.ts
index 048b542c7..bcbff6135 100644
--- a/web/src/app/shared/shared.module.ts
+++ b/web/src/app/shared/shared.module.ts
@@ -6,12 +6,14 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
import { AlertModule } from 'ngx-bootstrap';
import { RouterModule } from '@angular/router';
import { TreeModule } from 'angular-tree-component';
+import { TypeaheadModule } from 'ngx-bootstrap';
import { GeneralMessageModalComponent } from 'app/shared/general-message-modal/general-message-modal.component';
import { SpinnerComponent } from 'app/shared/spinner/spinner.component';
import { AlertComponent } from 'app/shared/alert/alert.component';
import { MasterAndDetailComponent } from 'app/shared/master-and-detail/master-and-detail.component';
import { TaskanaTreeComponent } from 'app/shared/tree/tree.component';
+import { TypeAheadComponent } from 'app/shared/type-ahead/type-ahead.component';
/**
* Pipes
@@ -22,17 +24,24 @@ import { SelectWorkBasketPipe } from './pipes/selectedWorkbasket/seleted-workbas
import { SpreadNumberPipe } from './pipes/spreadNumber/spread-number';
import { OrderBy } from './pipes/orderBy/orderBy';
import { MapToIterable } from './pipes/mapToIterable/mapToIterable';
+
+/**
+ * Services
+ */
import { HttpClientInterceptor } from './services/httpClientInterceptor/http-client-interceptor.service';
+import { AccessIdsService } from './services/access-ids/access-ids.service';
+
const MODULES = [
CommonModule,
FormsModule,
AlertModule.forRoot(),
+ TypeaheadModule.forRoot(),
AngularSvgIconModule,
HttpClientModule,
RouterModule,
- TreeModule
+ TreeModule,
];
const DECLARATIONS = [
@@ -41,6 +50,7 @@ const DECLARATIONS = [
AlertComponent,
MasterAndDetailComponent,
TaskanaTreeComponent,
+ TypeAheadComponent,
MapValuesPipe,
RemoveNoneTypePipe,
SelectWorkBasketPipe,
@@ -58,7 +68,8 @@ const DECLARATIONS = [
provide: HTTP_INTERCEPTORS,
useClass: HttpClientInterceptor,
multi: true
- }
+ },
+ AccessIdsService
]
})
export class SharedModule {
diff --git a/web/src/app/shared/spinner/spinner.component.scss b/web/src/app/shared/spinner/spinner.component.scss
index 7e15c1d82..472dff29d 100644
--- a/web/src/app/shared/spinner/spinner.component.scss
+++ b/web/src/app/shared/spinner/spinner.component.scss
@@ -133,4 +133,11 @@
.no-display{
display: none;
-}
\ No newline at end of file
+}
+
+.type-ahead-spinner {
+ position: relative;
+ width: 20px;
+ height: 20px;
+ margin-right: 15px;
+}
diff --git a/web/src/app/shared/type-ahead/type-ahead.component.html b/web/src/app/shared/type-ahead/type-ahead.component.html
new file mode 100644
index 000000000..e87e6f792
--- /dev/null
+++ b/web/src/app/shared/type-ahead/type-ahead.component.html
@@ -0,0 +1,38 @@
+
\ No newline at end of file
diff --git a/web/src/app/shared/type-ahead/type-ahead.component.scss b/web/src/app/shared/type-ahead/type-ahead.component.scss
new file mode 100644
index 000000000..0385320dd
--- /dev/null
+++ b/web/src/app/shared/type-ahead/type-ahead.component.scss
@@ -0,0 +1,47 @@
+$blue: #2e9eca;
+$grey: #ddd;
+.wrapper-text {
+ height: 47px;
+ & label {
+ width: 100%;
+ margin-bottom: 0px;
+ }
+ & div {
+ width: 100%;
+ border-bottom: 1px solid $grey;
+ margin-top:6px;
+ }
+}
+
+.input-text {
+ background: none;
+ box-shadow: none;
+ border: none;
+ padding: 0px;
+ border-radius: 0px;
+ //margin-top: 18px;
+ height: 22px;
+ border-bottom: 1px solid $grey;
+ &:focus{
+ border-bottom: 1px solid $blue;
+ }
+
+}
+
+.field-label-wrapper{
+ position: relative;
+ //left: 8px;
+ box-sizing: content-box;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+
+.form-control:focus {
+ border-color: none;
+ box-shadow: none;
+}
+.loading {
+ position: absolute;
+ right: 0;
+}
diff --git a/web/src/app/shared/type-ahead/type-ahead.component.ts b/web/src/app/shared/type-ahead/type-ahead.component.ts
new file mode 100644
index 000000000..3f4c557ba
--- /dev/null
+++ b/web/src/app/shared/type-ahead/type-ahead.component.ts
@@ -0,0 +1,130 @@
+import { Component, OnInit, Input, EventEmitter, Output, ViewChild, ElementRef, forwardRef } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+import { TypeaheadMatch } from 'ngx-bootstrap/typeahead';
+
+import { AccessIdsService } from 'app/shared/services/access-ids/access-ids.service';
+import { AccessItemsComponent } from 'app/administration/workbasket/details/access-items/access-items.component';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+
+const noop = () => {
+};
+
+@Component({
+ selector: 'taskana-type-ahead',
+ templateUrl: './type-ahead.component.html',
+ styleUrls: ['./type-ahead.component.scss'],
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => TypeAheadComponent),
+ multi: true
+ }
+
+ ]
+
+})
+export class TypeAheadComponent implements OnInit, ControlValueAccessor {
+
+ dataSource: any;
+ typing = false;
+
+ @Input()
+ placeHolderMessage;
+
+ @ViewChild('inputTypeAhead')
+ private inputTypeAhead;
+
+ typeaheadLoading = false;
+ typeaheadMinLength = 2;
+ typeaheadWaitMs = 500;
+ typeaheadOptionsInScrollableView = 6;
+
+ // The internal data model
+ private innerValue: any = '';
+
+ // Placeholders for the callbacks which are later provided
+ // by the Control Value Accessor
+ private onTouchedCallback: () => void = noop;
+ private onChangeCallback: (_: any) => void = noop;
+
+ // get accessor
+ get value(): any {
+ return this.innerValue;
+ };
+
+ // set accessor including call the onchange callback
+ set value(v: any) {
+ if (v !== this.innerValue) {
+ this.innerValue = v;
+ this.onChangeCallback(v);
+ }
+ }
+
+ // From ControlValueAccessor interface
+ writeValue(value: any) {
+ if (value !== this.innerValue) {
+ this.innerValue = value;
+ this.initializeDataSource();
+ }
+ }
+
+ // From ControlValueAccessor interface
+ registerOnChange(fn: any) {
+ this.onChangeCallback = fn;
+ }
+
+ // From ControlValueAccessor interface
+ registerOnTouched(fn: any) {
+ this.onTouchedCallback = fn;
+ }
+
+ constructor(private accessIdsService: AccessIdsService) {
+ }
+
+ ngOnInit() {
+
+ }
+
+ initializeDataSource() {
+ this.dataSource = Observable.create((observer: any) => {
+ observer.next(this.value);
+ }).mergeMap((token: string) => this.getUsersAsObservable(token));
+ this.accessIdsService.getAccessItemsInformation(this.value).subscribe(items => {
+ if (items.length > 0) {
+ this.dataSource.selected = items.find(item => item.accessId === this.value);
+ }
+ });
+ }
+
+
+ getUsersAsObservable(token: string): Observable {
+ return this.accessIdsService.getAccessItemsInformation(token);
+ }
+
+ typeaheadOnSelect(event: TypeaheadMatch): void {
+ if (event && event.item) {
+ this.value = event.item.accessId;
+ this.dataSource.selected = event.item;
+ }
+ this.setTyping(false);
+ }
+
+ setTyping(value) {
+ if (value) {
+ setTimeout(() => {
+ this.inputTypeAhead.nativeElement.focus();
+ }, 1)
+
+ }
+ this.typing = value;
+ }
+
+ changeTypeaheadLoading(e: boolean): void {
+ this.typeaheadLoading = e;
+ }
+
+ join(text: string, str: string) {
+ return text.toLocaleLowerCase().split(str).join(`${str}`);
+ }
+
+}
diff --git a/web/src/assets/_styles.scss b/web/src/assets/_styles.scss
index f5675116f..3b27c8fa9 100644
--- a/web/src/assets/_styles.scss
+++ b/web/src/assets/_styles.scss
@@ -3,4 +3,5 @@
@import '../../node_modules/angular-tree-component/dist/angular-tree-component.css';
@import 'site';
@import 'forms';
-@import 'tree';
\ No newline at end of file
+@import 'tree';
+@import 'type-ahead';
\ No newline at end of file
diff --git a/web/src/assets/_type-ahead.scss b/web/src/assets/_type-ahead.scss
new file mode 100644
index 000000000..1a8404533
--- /dev/null
+++ b/web/src/assets/_type-ahead.scss
@@ -0,0 +1,12 @@
+
+typeahead-container >ul.dropdown-menu{
+ width: 215px;
+ & >li.active {
+ &>a {
+ background-color: $green;
+ }
+ &>a:hover {
+ background-color: $green;
+ }
+ }
+}
diff --git a/web/taskana-web.iml b/web/taskana-web.iml
new file mode 100644
index 000000000..4fd5057cb
--- /dev/null
+++ b/web/taskana-web.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
|