TSK-621 - Make classification categories configurable by type
This commit is contained in:
parent
106cc050ca
commit
2dbc0de402
|
@ -95,8 +95,7 @@ public class TaskanaEngineConfiguration {
|
|||
// List of configured classification types
|
||||
protected List<String> classificationTypes = new ArrayList<String>();
|
||||
|
||||
// List of configured classification categories
|
||||
protected List<String> classificationCategories = new ArrayList<String>();
|
||||
protected Map<String, List<String>> classificationCategoriesByTypeMap = new HashMap<String, List<String>>();
|
||||
|
||||
public TaskanaEngineConfiguration(DataSource dataSource, boolean useManagedTransactions, String schemaName)
|
||||
throws SQLException {
|
||||
|
@ -234,11 +233,20 @@ public class TaskanaEngineConfiguration {
|
|||
}
|
||||
|
||||
private void initClassificationCategories(Properties props) {
|
||||
String classificationCategoryNames = props.getProperty(TASKANA_CLASSIFICATION_CATEGORIES_PROPERTY);
|
||||
if (classificationCategoryNames != null && !classificationCategoryNames.isEmpty()) {
|
||||
StringTokenizer st = new StringTokenizer(classificationCategoryNames, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
classificationCategories.add(st.nextToken().trim().toUpperCase());
|
||||
if (classificationTypes != null && !classificationTypes.isEmpty()) {
|
||||
String classificationCategoryNames;
|
||||
StringTokenizer st;
|
||||
List<String> classificationCategoriesAux;
|
||||
for (String type : classificationTypes) {
|
||||
classificationCategoriesAux = new ArrayList<>();
|
||||
classificationCategoryNames = props.getProperty(TASKANA_CLASSIFICATION_CATEGORIES_PROPERTY + "." + type.toLowerCase());
|
||||
if (classificationCategoryNames != null && !classificationCategoryNames.isEmpty()) {
|
||||
st = new StringTokenizer(classificationCategoryNames, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
classificationCategoriesAux.add(st.nextToken().trim().toUpperCase());
|
||||
}
|
||||
classificationCategoriesByTypeMap.put(type, classificationCategoriesAux);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.debug("Configured classification categories : {}", domains);
|
||||
|
@ -432,12 +440,19 @@ public class TaskanaEngineConfiguration {
|
|||
this.classificationTypes = classificationTypes;
|
||||
}
|
||||
|
||||
public List<String> getClassificationCategories() {
|
||||
public List<String> getAllClassificationCategories() {
|
||||
List<String> classificationCategories = new ArrayList<>();
|
||||
for (Map.Entry<String, List<String>> type : this.classificationCategoriesByTypeMap.entrySet()) {
|
||||
classificationCategories.addAll(type.getValue());
|
||||
}
|
||||
return classificationCategories;
|
||||
}
|
||||
|
||||
public void setClassificationCategories(List<String> classificationCategories) {
|
||||
this.classificationCategories = classificationCategories;
|
||||
public List<String> getClassificationCategoriesByType(String type) {
|
||||
return classificationCategoriesByTypeMap.get(type);
|
||||
}
|
||||
public void setClassificationCategoriesByType(Map<String, List<String>> classificationCategoriesByType) {
|
||||
this.classificationCategoriesByTypeMap = classificationCategoriesByType;
|
||||
}
|
||||
|
||||
public Instant getTaskCleanupJobFirstRun() {
|
||||
|
|
|
@ -290,8 +290,8 @@ public class ClassificationServiceImpl implements ClassificationService {
|
|||
}
|
||||
|
||||
if (classification.getCategory() != null
|
||||
&& !taskanaEngine.getConfiguration().getClassificationCategories().contains(classification.getCategory())) {
|
||||
throw new InvalidArgumentException("Given classification category " + classification.getCategory()
|
||||
&& !taskanaEngine.getConfiguration().getClassificationCategoriesByType(classification.getType()).contains(classification.getCategory())) {
|
||||
throw new InvalidArgumentException("Given classification category " + classification.getCategory() + " with type " + classification.getType()
|
||||
+ " is not valid according to the configuration.");
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,12 @@ public class TaskanaConfigAccTest extends TaskanaEngineImpl {
|
|||
|
||||
@Test
|
||||
public void testClassificationCategories() {
|
||||
assertEquals(4, getConfiguration().getClassificationCategories().size());
|
||||
assertTrue(getConfiguration().getClassificationCategories().contains("EXTERNAL"));
|
||||
assertTrue(getConfiguration().getClassificationCategories().contains("MANUAL"));
|
||||
assertTrue(getConfiguration().getClassificationCategories().contains("AUTOMATIC"));
|
||||
assertTrue(getConfiguration().getClassificationCategories().contains("PROCESS"));
|
||||
assertFalse(getConfiguration().getClassificationCategories().contains("manual"));
|
||||
assertEquals(4, getConfiguration().getClassificationCategoriesByType("TASK").size());
|
||||
assertTrue(getConfiguration().getClassificationCategoriesByType("TASK").contains("EXTERNAL"));
|
||||
assertTrue(getConfiguration().getClassificationCategoriesByType("TASK").contains("MANUAL"));
|
||||
assertTrue(getConfiguration().getClassificationCategoriesByType("TASK").contains("AUTOMATIC"));
|
||||
assertTrue(getConfiguration().getClassificationCategoriesByType("TASK").contains("PROCESS"));
|
||||
assertFalse(getConfiguration().getClassificationCategoriesByType("TASK").contains("manual"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ taskana.roles.monitor=john|teamlead_2 | monitor
|
|||
taskana.domains= Domain_A , DOMAIN_B
|
||||
|
||||
taskana.classification.types= TASK , document
|
||||
taskana.classification.categories= EXTERNAL , manual, autoMAtic ,Process
|
||||
taskana.classification.categories.task= EXTERNAL, manual, autoMAtic, Process
|
||||
taskana.classification.categories.document= EXTERNAL
|
||||
|
||||
taskana.jobs.maxRetries=3
|
||||
taskana.jobs.batchSize=50
|
||||
|
|
|
@ -4,7 +4,8 @@ taskana.roles.businessadmin=max|Moritz|businessadmin
|
|||
|
||||
taskana.domains= Domain_A , DOMAIN_B
|
||||
taskana.classification.types= TASK , document
|
||||
taskana.classification.categories= EXTERNAL , manual, autoMAtic ,Process
|
||||
taskana.classification.categories.task= EXTERNAL, manual, autoMAtic, Process
|
||||
taskana.classification.categories.document= EXTERNAL
|
||||
|
||||
taskana.jobs.cleanup.schedule=0 0 3 * * *
|
||||
taskana.jobs.cleanup.runEvery=P1D
|
||||
|
|
|
@ -4,7 +4,8 @@ taskana.roles.businessadmin=max|Moritz|businessadmin
|
|||
taskana.roles.monitor=john|teamlead_2 | monitor
|
||||
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C
|
||||
taskana.classification.types=TASK,DOCUMENT
|
||||
taskana.classification.categories= EXTERNAL , manual, autoMAtic ,Process
|
||||
taskana.classification.categories.task= EXTERNAL, manual, autoMAtic, Process
|
||||
taskana.classification.categories.document= EXTERNAL
|
||||
|
||||
taskana.jobs.maxRetries=3
|
||||
taskana.jobs.batchSize=50
|
||||
|
|
|
@ -73,7 +73,7 @@ public class TaskanaEngineControllerIntTest {
|
|||
headers.add("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x");
|
||||
HttpEntity<String> request = new HttpEntity<String>(headers);
|
||||
ResponseEntity<List<String>> response = template.exchange(
|
||||
"http://127.0.0.1:" + port + "/v1/classification-categories", HttpMethod.GET, request,
|
||||
"http://127.0.0.1:" + port + "/v1/classification-categories/?type=TASK", HttpMethod.GET, request,
|
||||
new ParameterizedTypeReference<List<String>>() {
|
||||
});
|
||||
assertTrue(response.getBody().contains("MANUAL"));
|
||||
|
|
|
@ -214,7 +214,7 @@
|
|||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -34,8 +34,11 @@ public class TaskanaEngineController {
|
|||
}
|
||||
|
||||
@GetMapping(path = "/v1/classification-categories", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
public ResponseEntity<List<String>> getClassificationCategories() {
|
||||
return new ResponseEntity<>(taskanaEngineConfiguration.getClassificationCategories(), HttpStatus.OK);
|
||||
public ResponseEntity<List<String>> getClassificationCategories(String type) {
|
||||
if (type != null) {
|
||||
return new ResponseEntity<>(taskanaEngineConfiguration.getClassificationCategoriesByType(type), HttpStatus.OK);
|
||||
}
|
||||
return new ResponseEntity<>(taskanaEngineConfiguration.getAllClassificationCategories(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/v1/classification-types", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
|
|
|
@ -30,7 +30,6 @@ import {SavingWorkbasketService} from './services/saving-workbaskets/saving-work
|
|||
import {ClassificationDefinitionService} from './services/classification-definition/classification-definition.service';
|
||||
import {WorkbasketDefinitionService} from './services/workbasket-definition/workbasket-definition.service';
|
||||
import {ClassificationsService} from './services/classifications/classifications.service';
|
||||
import {ClassificationTypesService} from './services/classification-types/classification-types.service';
|
||||
import {ClassificationCategoriesService} from './services/classification-categories-service/classification-categories.service';
|
||||
|
||||
const MODULES = [
|
||||
|
@ -68,7 +67,6 @@ const DECLARATIONS = [
|
|||
WorkbasketDefinitionService,
|
||||
SavingWorkbasketService,
|
||||
ClassificationsService,
|
||||
ClassificationTypesService,
|
||||
ClassificationCategoriesService,
|
||||
]
|
||||
})
|
||||
|
|
|
@ -24,11 +24,9 @@ import { TreeNodeModel } from 'app/models/tree-node';
|
|||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||
import { AlertService } from 'app/services/alert/alert.service';
|
||||
import { TreeService } from 'app/services/tree/tree.service';
|
||||
import { ClassificationTypesService } from 'app/administration/services/classification-types/classification-types.service';
|
||||
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
||||
import { RemoveConfirmationService } from 'app/services/remove-confirmation/remove-confirmation.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
|
@ -45,7 +43,7 @@ describe('ClassificationDetailsComponent', () => {
|
|||
let fixture: ComponentFixture<ClassificationDetailsComponent>;
|
||||
const treeNodes: Array<TreeNodeModel> = new Array(new TreeNodeModel());
|
||||
|
||||
let classificationsService, classificationTypesService, classificationCategoriesService,
|
||||
let classificationsService, classificationCategoriesService,
|
||||
treeService, removeConfirmationService;
|
||||
|
||||
beforeEach(done => {
|
||||
|
@ -54,7 +52,7 @@ describe('ClassificationDetailsComponent', () => {
|
|||
imports: [FormsModule, HttpClientModule, RouterTestingModule.withRoutes(routes), AngularSvgIconModule],
|
||||
declarations: [ClassificationDetailsComponent, DummyDetailComponent],
|
||||
providers: [MasterAndDetailService, RequestInProgressService, ClassificationsService, HttpClient, ErrorModalService, AlertService,
|
||||
TreeService, ClassificationTypesService, ClassificationCategoriesService,
|
||||
TreeService, ClassificationCategoriesService,
|
||||
CustomFieldsService]
|
||||
})
|
||||
};
|
||||
|
@ -62,12 +60,11 @@ describe('ClassificationDetailsComponent', () => {
|
|||
fixture = TestBed.createComponent(ClassificationDetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
classificationsService = TestBed.get(ClassificationsService);
|
||||
classificationTypesService = TestBed.get(ClassificationTypesService);
|
||||
classificationCategoriesService = TestBed.get(ClassificationCategoriesService);
|
||||
classificationsService = TestBed.get(ClassificationsService);
|
||||
removeConfirmationService = TestBed.get(RemoveConfirmationService);
|
||||
spyOn(classificationsService, 'getClassifications').and.returnValue(of(treeNodes));
|
||||
spyOn(classificationTypesService, 'getClassificationTypes').and.returnValue(of([]));
|
||||
spyOn(classificationCategoriesService, 'getClassificationTypes').and.returnValue(of([]));
|
||||
spyOn(classificationCategoriesService, 'getCategories').and.returnValue(of(['firstCategory', 'secondCategory']));
|
||||
spyOn(classificationsService, 'deleteClassification').and.returnValue(of(true));
|
||||
spyOn(classificationCategoriesService, 'getCategoryIcon').and.returnValue(new Pair('assets/icons/categories/external.svg'));
|
||||
|
|
|
@ -16,7 +16,6 @@ import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
|||
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||
import { AlertService } from 'app/services/alert/alert.service';
|
||||
import { TreeService } from 'app/services/tree/tree.service';
|
||||
import { ClassificationTypesService } from 'app/administration/services/classification-types/classification-types.service';
|
||||
import { RemoveConfirmationService } from 'app/services/remove-confirmation/remove-confirmation.service';
|
||||
|
||||
// tslint:disable:max-line-length
|
||||
|
@ -78,7 +77,6 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
private requestInProgressService: RequestInProgressService,
|
||||
private alertService: AlertService,
|
||||
private treeService: TreeService,
|
||||
private classificationTypeService: ClassificationTypesService,
|
||||
private categoryService: ClassificationCategoriesService,
|
||||
private domainService: DomainService,
|
||||
private customFieldsService: CustomFieldsService,
|
||||
|
@ -87,7 +85,7 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.classificationTypeService.getClassificationTypes().subscribe((classificationTypes: Array<string>) => {
|
||||
this.categoryService.getClassificationTypes().subscribe((classificationTypes: Array<string>) => {
|
||||
this.classificationTypes = classificationTypes;
|
||||
})
|
||||
this.classificationSelectedSubscription = this.classificationsService.getSelectedClassification()
|
||||
|
@ -112,7 +110,6 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.fillClassificationInformation(this.selectedClassification ? this.selectedClassification : new ClassificationDefinition())
|
||||
}
|
||||
|
||||
|
||||
if (!this.classification || this.classification.classificationId !== id && id && id !== '') {
|
||||
this.selectClassification(id);
|
||||
}
|
||||
|
@ -122,7 +119,6 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.showDetail = showDetail;
|
||||
});
|
||||
|
||||
|
||||
this.categoriesSubscription = this.categoryService.getCategories().subscribe((categories: Array<string>) => {
|
||||
this.categories = categories;
|
||||
if (categories.length > 0 && this.classification) {
|
||||
|
@ -250,7 +246,7 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.classification.parentKey = classificationSelected.key;
|
||||
this.classification.category = classificationSelected.category;
|
||||
this.classification.domain = this.domainService.getSelectedDomainValue();
|
||||
this.selectedClassificationSubscription = this.classificationTypeService.getSelectedClassificationType().subscribe(type => {
|
||||
this.selectedClassificationSubscription = this.categoryService.getSelectedClassificationType().subscribe(type => {
|
||||
if (this.classification) { this.classification.type = type; }
|
||||
});
|
||||
this.addDateToClassification();
|
||||
|
|
|
@ -19,7 +19,6 @@ import { ClassificationsService } from 'app/administration/services/classificati
|
|||
import { ClassificationDefinitionService } from 'app/administration/services/classification-definition/classification-definition.service';
|
||||
import { DomainService } from 'app/services/domain/domain.service';
|
||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||
import { ClassificationTypesService } from 'app/administration/services/classification-types/classification-types.service';
|
||||
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||
import { configureTests } from 'app/app.test.configuration';
|
||||
import {
|
||||
|
@ -45,7 +44,7 @@ describe('ClassificationListComponent', () => {
|
|||
let fixture: ComponentFixture<ClassificationListComponent>;
|
||||
const treeNodes: Array<TreeNodeModel> = new Array(new TreeNodeModel());
|
||||
const classificationTypes: Array<string> = new Array<string>('type1', 'type2');
|
||||
let classificationsService, classificationTypesService, classificationCategoriesService;
|
||||
let classificationsService, classificationCategoriesService;
|
||||
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
|
@ -55,7 +54,7 @@ describe('ClassificationListComponent', () => {
|
|||
imports: [HttpClientModule, RouterTestingModule.withRoutes(routes), FormsModule, AngularSvgIconModule],
|
||||
providers: [
|
||||
HttpClient, WorkbasketDefinitionService, AlertService, ClassificationsService, DomainService, ClassificationDefinitionService,
|
||||
ErrorModalService, ClassificationTypesService, RequestInProgressService, ClassificationCategoriesService, TreeService
|
||||
ErrorModalService, RequestInProgressService, ClassificationCategoriesService, TreeService
|
||||
]
|
||||
})
|
||||
};
|
||||
|
@ -64,10 +63,9 @@ describe('ClassificationListComponent', () => {
|
|||
component = fixture.componentInstance;
|
||||
|
||||
classificationsService = testBed.get(ClassificationsService);
|
||||
classificationTypesService = testBed.get(ClassificationTypesService);
|
||||
classificationCategoriesService = testBed.get(ClassificationCategoriesService);
|
||||
spyOn(classificationsService, 'getClassifications').and.returnValue(of(treeNodes));
|
||||
spyOn(classificationTypesService, 'getClassificationTypes')
|
||||
spyOn(classificationCategoriesService, 'getClassificationTypes')
|
||||
.and.returnValue(of(classificationTypes));
|
||||
spyOn(classificationCategoriesService, 'getCategories').and.returnValue(of(new Array<string>('cat1', 'cat2')));
|
||||
spyOn(classificationCategoriesService, 'getCategoryIcon').and.returnValue(new Pair('assets/icons/categories/external.svg'));
|
||||
|
|
|
@ -7,7 +7,6 @@ import { Classification } from 'app/models/classification';
|
|||
import { TreeNodeModel } from 'app/models/tree-node';
|
||||
|
||||
import { ClassificationsService } from 'app/administration/services/classifications/classifications.service';
|
||||
import { ClassificationTypesService } from 'app/administration/services/classification-types/classification-types.service';
|
||||
import {
|
||||
ClassificationCategoriesService
|
||||
} from 'app/administration/services/classification-categories-service/classification-categories.service';
|
||||
|
@ -43,7 +42,6 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
private classificationService: ClassificationsService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private classificationTypeService: ClassificationTypesService,
|
||||
private categoryService: ClassificationCategoriesService) {
|
||||
}
|
||||
|
||||
|
@ -53,12 +51,13 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
.subscribe(value => {
|
||||
this.performRequest(true);
|
||||
})
|
||||
this.selectedClassificationSubscription = this.classificationTypeService.getSelectedClassificationType().subscribe(value => {
|
||||
this.classificationTypeSelected = value;
|
||||
this.selectedClassificationSubscription = this.categoryService.getSelectedClassificationType().subscribe(value => {
|
||||
this.classificationTypeSelected = value;
|
||||
this.performRequest();
|
||||
})
|
||||
|
||||
this.categoriesSubscription = this.categoryService.getCategories().subscribe((categories: Array<string>) => {
|
||||
this.categoriesSubscription =
|
||||
this.categoryService.getCategories(this.classificationTypeSelected).subscribe((categories: Array<string>) => {
|
||||
this.categories = categories;
|
||||
});
|
||||
}
|
||||
|
@ -66,12 +65,13 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
selectClassificationType(classificationTypeSelected: string) {
|
||||
this.classifications = [];
|
||||
this.requestInProgress = true;
|
||||
this.classificationTypeService.selectClassificationType(classificationTypeSelected);
|
||||
this.categoryService.selectClassificationType(classificationTypeSelected);
|
||||
this.classificationService.getClassifications()
|
||||
.subscribe((classifications: Array<TreeNodeModel>) => {
|
||||
this.classifications = classifications;
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
});
|
||||
this.selectClassification(undefined);
|
||||
}
|
||||
|
||||
selectClassification(id: string) {
|
||||
|
@ -110,7 +110,7 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
.subscribe((classifications: Array<TreeNodeModel>) => {
|
||||
this.requestInProgress = false;
|
||||
this.classifications = classifications;
|
||||
this.classificationTypeServiceSubscription = this.classificationTypeService.getClassificationTypes()
|
||||
this.classificationTypeServiceSubscription = this.categoryService.getClassificationTypes()
|
||||
.subscribe((classificationsTypes: Array<string>) => {
|
||||
this.classificationsTypes = classificationsTypes;
|
||||
});
|
||||
|
|
|
@ -2,34 +2,41 @@ import { HttpClient } from '@angular/common/http';
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from 'environments/environment';
|
||||
import { Observable , ReplaySubject } from 'rxjs';
|
||||
import { Observable , ReplaySubject, BehaviorSubject } from 'rxjs';
|
||||
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
||||
import { Pair } from 'app/models/pair';
|
||||
|
||||
@Injectable()
|
||||
export class ClassificationCategoriesService {
|
||||
|
||||
private url = environment.taskanaRestUrl + '/v1/classification-categories';
|
||||
private dataObs$ = new ReplaySubject<Array<string>>(1);
|
||||
private mainUrl = environment.taskanaRestUrl;
|
||||
|
||||
// categories
|
||||
private urlCategories = this.mainUrl + '/v1/classification-categories';
|
||||
private param = '/?type=';
|
||||
private dataObsCategories$ = new ReplaySubject<Array<string>>(1);
|
||||
private categoriesObject = new Object();
|
||||
private missingIcon = 'assets/icons/categories/missing-icon.svg';
|
||||
private type = 'UNKNOW';
|
||||
|
||||
// type
|
||||
private classificationTypeSelectedValue = 'TASK';
|
||||
private urlType = this.mainUrl + '/v1/classification-types';
|
||||
private classificationTypeSelected = new BehaviorSubject<string>(this.classificationTypeSelectedValue);
|
||||
private dataObsType$ = new ReplaySubject<Array<string>>(1);
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private customFieldsService: CustomFieldsService) { }
|
||||
|
||||
getCategories(forceRefresh = false): Observable<Array<string>> {
|
||||
if (!this.dataObs$.observers.length || forceRefresh) {
|
||||
this.httpClient.get<Array<string>>(this.url).subscribe(
|
||||
data => { this.dataObs$.next(data); this.categoriesObject = this.getCustomCategoriesObject(data) },
|
||||
error => {
|
||||
this.dataObs$.error(error);
|
||||
this.dataObs$ = new ReplaySubject(1);
|
||||
}
|
||||
getCategories(type?: string): Observable<Array<string>> {
|
||||
if (!this.dataObsCategories$.observers.length || type !== this.type) {
|
||||
this.httpClient.get<Array<string>>(type ? this.urlCategories + this.param + type : this.urlCategories).subscribe(
|
||||
data => { this.dataObsCategories$.next(data); this.categoriesObject = this.getCustomCategoriesObject(data); this.type = type; },
|
||||
error => { this.dataObsCategories$.error(error); this.dataObsCategories$ = new ReplaySubject(1); }
|
||||
);
|
||||
}
|
||||
|
||||
return this.dataObs$;
|
||||
return this.dataObsCategories$;
|
||||
};
|
||||
|
||||
getCategoryIcon(category: string): Pair {
|
||||
|
@ -47,7 +54,6 @@ export class ClassificationCategoriesService {
|
|||
this.getDefaultCategoryMap(categories), 'classifications.categories');
|
||||
}
|
||||
|
||||
|
||||
private getDefaultCategoryMap(categoryList: Array<string>): Object {
|
||||
const defaultCategoryMap = new Object();
|
||||
categoryList.forEach(element => {
|
||||
|
@ -55,4 +61,27 @@ export class ClassificationCategoriesService {
|
|||
});
|
||||
return defaultCategoryMap;
|
||||
}
|
||||
|
||||
getClassificationTypes(forceRefresh = false): Observable<Array<string>> {
|
||||
if (!this.dataObsType$.observers.length || forceRefresh) {
|
||||
this.httpClient.get<Array<string>>(this.urlType).subscribe(
|
||||
data => this.dataObsType$.next(data),
|
||||
error => {
|
||||
this.dataObsType$.error(error);
|
||||
this.dataObsType$ = new ReplaySubject(1);
|
||||
}
|
||||
);
|
||||
}
|
||||
return this.dataObsType$;
|
||||
};
|
||||
|
||||
selectClassificationType(id: string) {
|
||||
this.getCategories(id);
|
||||
this.classificationTypeSelectedValue = id;
|
||||
this.classificationTypeSelected.next(id);
|
||||
}
|
||||
|
||||
getSelectedClassificationType(): Observable<string> {
|
||||
return this.classificationTypeSelected.asObservable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { ClassificationTypesService } from './classification-types.service';
|
||||
|
||||
describe('ClassificationTypesService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientModule],
|
||||
providers: [HttpClient, ClassificationTypesService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([ClassificationTypesService], (service: ClassificationTypesService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
|
@ -1,40 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, BehaviorSubject, ReplaySubject } from 'rxjs';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
@Injectable()
|
||||
export class ClassificationTypesService {
|
||||
private url = environment.taskanaRestUrl + '/v1/classification-types';
|
||||
private classificationTypeSelectedValue = 'TASK';
|
||||
private classificationTypeSelected = new BehaviorSubject<string>(this.classificationTypeSelectedValue);
|
||||
private dataObs$ = new ReplaySubject<Array<string>>(1);
|
||||
|
||||
constructor(private httpClient: HttpClient
|
||||
) { }
|
||||
|
||||
getClassificationTypes(forceRefresh = false): Observable<Array<string>> {
|
||||
|
||||
if (!this.dataObs$.observers.length || forceRefresh) {
|
||||
this.httpClient.get<Array<string>>(this.url).subscribe(
|
||||
data => this.dataObs$.next(data),
|
||||
error => {
|
||||
this.dataObs$.error(error);
|
||||
this.dataObs$ = new ReplaySubject(1);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return this.dataObs$;
|
||||
};
|
||||
|
||||
selectClassificationType(id: string) {
|
||||
this.classificationTypeSelectedValue = id;
|
||||
this.classificationTypeSelected.next(id);
|
||||
}
|
||||
|
||||
getSelectedClassificationType(): Observable<string> {
|
||||
return this.classificationTypeSelected.asObservable();
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ import { Classification } from 'app/models/classification';
|
|||
import { ClassificationDefinition } from 'app/models/classification-definition';
|
||||
|
||||
import { ClassificationResource } from 'app/models/classification-resource';
|
||||
import { ClassificationTypesService } from '../classification-types/classification-types.service';
|
||||
import { ClassificationCategoriesService } from '../classification-categories-service/classification-categories.service';
|
||||
import { DomainService } from 'app/services/domain/domain.service';
|
||||
import { TaskanaQueryParameters } from 'app/shared/util/query-parameters';
|
||||
import { Direction } from 'app/models/sorting';
|
||||
|
@ -22,7 +22,7 @@ export class ClassificationsService {
|
|||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private classificationTypeService: ClassificationTypesService,
|
||||
private classificationCategoriesService: ClassificationCategoriesService,
|
||||
private domainService: DomainService) {
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ export class ClassificationsService {
|
|||
return this.httpClient.get<ClassificationDefinition>(`${environment.taskanaRestUrl}/v1/classifications/${id}`)
|
||||
.pipe(tap((classification: ClassificationDefinition) => {
|
||||
if (classification) {
|
||||
this.classificationTypeService.selectClassificationType(classification.type);
|
||||
this.classificationCategoriesService.selectClassificationType(classification.type);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ export class ClassificationsService {
|
|||
// #endregion
|
||||
|
||||
private getClassificationObservable(classificationRef: Observable<any>): Observable<any> {
|
||||
const classificationTypes = this.classificationTypeService.getSelectedClassificationType();
|
||||
const classificationTypes = this.classificationCategoriesService.getSelectedClassificationType();
|
||||
return combineLatest(
|
||||
classificationRef,
|
||||
classificationTypes,
|
||||
|
@ -132,7 +132,6 @@ export class ClassificationsService {
|
|||
return roots;
|
||||
}
|
||||
|
||||
|
||||
private findChildren(parent: any, children: Array<any>) {
|
||||
if (children[parent.classificationId]) {
|
||||
parent.children = children[parent.classificationId];
|
||||
|
|
|
@ -12,4 +12,42 @@ describe('CustomFieldsService', () => {
|
|||
it('should be created', inject([CustomFieldsService], (service: CustomFieldsService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should take default icon path', inject([CustomFieldsService], (service: CustomFieldsService) => {
|
||||
const categoriesData = {'DEFAULT': 'assets/icons/categories/default.svg'}
|
||||
const returnedValue = service.getCustomObject(categoriesData, undefined);
|
||||
expect(returnedValue).toBe(categoriesData);
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should take default icon path in merge', inject([CustomFieldsService], (service: CustomFieldsService) => {
|
||||
const json = require('./taskana-customization-test.json');
|
||||
service.initCustomFields('EN', json);
|
||||
const categoriesDefault = json.EN.classifications.categories;
|
||||
const categoriesData = {
|
||||
'EXTERNAL': 'assets/icons/categories/external.svg',
|
||||
'MANUAL': 'assets/icons/categories/manual.svg',
|
||||
'AUTOMATIC': 'assets/icons/categories/automatic.svg',
|
||||
'PROCESS': 'assets/icons/categories/external.svg'
|
||||
};
|
||||
const returnedValue = service.getCustomObject(categoriesData, 'classifications.categories');
|
||||
expect(returnedValue).toEqual(categoriesDefault);
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should take merge icon path', inject([CustomFieldsService], (service: CustomFieldsService) => {
|
||||
const json = require('./taskana-customization-test.json');
|
||||
service.initCustomFields('EN', json);
|
||||
const categoriesData = {'DEFAULT': 'assets/icons/categories/default.svg'}
|
||||
const result = {
|
||||
'AUTOMATIC': 'assets/icons/categories/automatic.svg',
|
||||
'DEFAULT': 'assets/icons/categories/default.svg',
|
||||
'EXTERNAL': 'assets/icons/categories/external.svg',
|
||||
'MANUAL': 'assets/icons/categories/manual.svg',
|
||||
'PROCESS': 'assets/icons/categories/process.svg'
|
||||
};
|
||||
const returnedValue = service.getCustomObject(categoriesData, 'classifications.categories');
|
||||
expect(returnedValue).toEqual(result);
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -58,6 +58,26 @@ export class CustomFieldsService {
|
|||
return true;
|
||||
});
|
||||
|
||||
value = this.mergeKeys(value, fallbackObject);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private mergeKeys(defaultObject: Object, newObject: Object) {
|
||||
const value = new Object();
|
||||
|
||||
for (const item of Object.keys(defaultObject)) {
|
||||
if (!value[item]) {
|
||||
value[item] = defaultObject[item];
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of Object.keys(newObject)) {
|
||||
if (!value[item]) {
|
||||
value[item] = newObject[item];
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"EN": {
|
||||
"classifications": {
|
||||
"information": {
|
||||
"custom1": {
|
||||
"field": "Classification custom 1",
|
||||
"visible": true
|
||||
},
|
||||
"custom3": {
|
||||
"field": "",
|
||||
"visible": false
|
||||
}
|
||||
},
|
||||
"categories": {
|
||||
"EXTERNAL": "assets/icons/categories/external.svg",
|
||||
"MANUAL": "assets/icons/categories/manual.svg",
|
||||
"AUTOMATIC": "assets/icons/categories/automatic.svg",
|
||||
"PROCESS": "assets/icons/categories/process.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,4 +59,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue