From fcc4be639da8e670d9d965baa50f4556e26b0fef Mon Sep 17 00:00:00 2001 From: shah1375 Date: Sun, 10 Nov 2024 18:02:11 +0100 Subject: [PATCH] first draft for required value of attribute and value filter #277 --- src/app/layout/font-awesome-icons.ts | 8 ++- .../Criterion/AbstractCriterion.ts | 58 +++++++++++-------- .../Criterion/CriterionBuilder.ts | 5 ++ .../Criterion/ReferenceCriterion.ts | 2 + .../AttributeDefinitions.ts | 2 +- .../CloneReferenceCriterion.ts | 2 + .../edit-criterion-modal.component.ts | 23 +++++++- ...edit-reference-criteria-modal.component.ts | 23 +++++++- .../Builder/Create/CreateCriterion.service.ts | 16 ++++- .../Builder/CriterionMetadata.service.ts | 15 +++++ .../criteria-box/criteria-box.component.html | 15 ++++- .../criteria-box/criteria-box.component.scss | 11 ++++ .../criteria-box/criteria-box.component.ts | 22 +++++++ src/assets/i18n/de.json | 3 + src/assets/i18n/en.json | 3 + 15 files changed, 178 insertions(+), 30 deletions(-) diff --git a/src/app/layout/font-awesome-icons.ts b/src/app/layout/font-awesome-icons.ts index 48b98705..deab8f76 100644 --- a/src/app/layout/font-awesome-icons.ts +++ b/src/app/layout/font-awesome-icons.ts @@ -1,4 +1,9 @@ -import { faAngleDoubleLeft, faExclamation, faFolderOpen } from '@fortawesome/free-solid-svg-icons'; +import { + faAngleDoubleLeft, + faExclamation, + faExclamationTriangle, + faFolderOpen, +} from '@fortawesome/free-solid-svg-icons'; import { faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons'; import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { faArrowDown } from '@fortawesome/free-solid-svg-icons'; @@ -117,4 +122,5 @@ export const FONT_AWESOME_ICONS = [ faFileImage, faFolderOpen, faExclamation, + faExclamationTriangle, ]; diff --git a/src/app/model/FeasibilityQuery/Criterion/AbstractCriterion.ts b/src/app/model/FeasibilityQuery/Criterion/AbstractCriterion.ts index 89b38d81..d5c0c024 100644 --- a/src/app/model/FeasibilityQuery/Criterion/AbstractCriterion.ts +++ b/src/app/model/FeasibilityQuery/Criterion/AbstractCriterion.ts @@ -19,6 +19,7 @@ export abstract class AbstractCriterion { private timeRestriction?: AbstractTimeRestriction; private id: string; private valueFilters?: Array = []; + private isRequiredFilterSet: boolean; /** * Constructor for AbstractCriterion. @@ -34,6 +35,7 @@ export abstract class AbstractCriterion { * @param termCodes - Array of TerminologyCode objects. * @param timeRestriction - AbstractTimeRestriction object. * @param valueFilters - Array of ValueFilter objects. + * @param isRequiredFilterSet */ constructor( isReference: boolean, @@ -42,12 +44,14 @@ export abstract class AbstractCriterion { criterionHash?: string, display?: string, isInvalid?: boolean, + isRequiredFilterSet?: boolean, position?: CritGroupPosition, termCodes?: Array, timeRestriction?: AbstractTimeRestriction, id?: string, valueFilters?: Array ) { + this.isRequiredFilterSet = isRequiredFilterSet; this.attributeFilters = attributeFilters; this.context = context; this.criterionHash = criterionHash; @@ -65,7 +69,7 @@ export abstract class AbstractCriterion { * * @param isReference */ - setisReference(isReference: boolean) { + public setisReference(isReference: boolean) { this.isReference = isReference; } @@ -73,7 +77,7 @@ export abstract class AbstractCriterion { * * @returns */ - getisReference(): boolean { + public getisReference(): boolean { return this.isReference; } @@ -82,14 +86,14 @@ export abstract class AbstractCriterion { * * @returns Array of AttributeFilter objects or false if attributeFilters is undefined. */ - isAttributeFiltersSet(): boolean { + public isAttributeFiltersSet(): boolean { if (this.attributeFilters === undefined) { return false; } return true; } - getAttributeFilters(): Array { + public getAttributeFilters(): Array { if (this.attributeFilters === undefined) { return []; } @@ -101,7 +105,7 @@ export abstract class AbstractCriterion { * * @param attributeFilters - Array of AttributeFilter objects. */ - setAttributeFilters(attributeFilters: Array): void { + public setAttributeFilters(attributeFilters: Array): void { this.attributeFilters = attributeFilters; } @@ -110,7 +114,7 @@ export abstract class AbstractCriterion { * * @returns TerminologyCode object representing the context. */ - getContext(): TerminologyCode | undefined { + public getContext(): TerminologyCode | undefined { return this.context; } @@ -119,7 +123,7 @@ export abstract class AbstractCriterion { * * @param context - TerminologyCode object representing the context. */ - setContext(context: TerminologyCode): void { + public setContext(context: TerminologyCode): void { this.context = context; } @@ -128,7 +132,7 @@ export abstract class AbstractCriterion { * * @returns Hash string for the criterion. */ - getCriterionHash(): string | undefined { + public getCriterionHash(): string | undefined { return this.criterionHash; } @@ -137,7 +141,7 @@ export abstract class AbstractCriterion { * * @param criterionHash - Hash string for the criterion. */ - setCriterionHash(criterionHash: string): void { + public setCriterionHash(criterionHash: string): void { this.criterionHash = criterionHash; } @@ -146,7 +150,7 @@ export abstract class AbstractCriterion { * * @returns Display string for the criterion. */ - getDisplay(): string | undefined { + public getDisplay(): string | undefined { return this.display; } @@ -155,7 +159,7 @@ export abstract class AbstractCriterion { * * @param display - Display string for the criterion. */ - setDisplay(display: string): void { + public setDisplay(display: string): void { this.display = display; } @@ -164,7 +168,7 @@ export abstract class AbstractCriterion { * * @returns Boolean flag indicating if the criterion is invalid. */ - getIsInvalid(): boolean | undefined { + public getIsInvalid(): boolean | undefined { return this.isInvalid; } @@ -173,7 +177,7 @@ export abstract class AbstractCriterion { * * @param isInvalid - Boolean flag indicating if the criterion is invalid. */ - setIsInvalid(isInvalid: boolean): void { + public setIsInvalid(isInvalid: boolean): void { this.isInvalid = isInvalid; } @@ -182,7 +186,7 @@ export abstract class AbstractCriterion { * * @returns CritGroupPosition object representing the position. */ - getPosition(): CritGroupPosition | undefined { + public getPosition(): CritGroupPosition | undefined { return this.position; } @@ -191,7 +195,7 @@ export abstract class AbstractCriterion { * * @param position - CritGroupPosition object representing the position. */ - setPosition(position: CritGroupPosition): void { + public setPosition(position: CritGroupPosition): void { this.position = position; } @@ -200,7 +204,7 @@ export abstract class AbstractCriterion { * * @returns Array of TerminologyCode objects. */ - getTermCodes(): Array | undefined { + public getTermCodes(): Array | undefined { return this.termCodes; } @@ -209,7 +213,7 @@ export abstract class AbstractCriterion { * * @param termCodes - Array of TerminologyCode objects. */ - setTermCodes(termCodes: Array): void { + public setTermCodes(termCodes: Array): void { this.termCodes = termCodes; } @@ -218,7 +222,7 @@ export abstract class AbstractCriterion { * * @returns AbstractTimeRestriction object. */ - getTimeRestriction(): AbstractTimeRestriction | undefined { + public getTimeRestriction(): AbstractTimeRestriction | undefined { return this.timeRestriction; } @@ -227,7 +231,7 @@ export abstract class AbstractCriterion { * * @param timeRestriction - AbstractTimeRestriction object. */ - setTimeRestriction(timeRestriction: AbstractTimeRestriction): void { + public setTimeRestriction(timeRestriction: AbstractTimeRestriction): void { this.timeRestriction = timeRestriction; } @@ -236,7 +240,7 @@ export abstract class AbstractCriterion { * * @returns Unique identifier for the criterion. */ - getId(): string { + public getId(): string { return this.id; } @@ -245,7 +249,7 @@ export abstract class AbstractCriterion { * * @param id - Unique identifier for the criterion. */ - setId(id: string): void { + public setId(id: string): void { this.id = id; } @@ -254,7 +258,7 @@ export abstract class AbstractCriterion { * * @returns Array of ValueFilter objects or false if valueFilters is undefined. */ - getValueFilters(): Array { + public getValueFilters(): Array { return this.valueFilters; } @@ -263,7 +267,15 @@ export abstract class AbstractCriterion { * * @param valueFilters - Array of ValueFilter objects. */ - setValueFilters(valueFilters: Array): void { + public setValueFilters(valueFilters: Array): void { this.valueFilters = valueFilters; } + + public setIsRequiredFilterSet(isRequiredFilterSet: boolean): void { + this.isRequiredFilterSet = isRequiredFilterSet; + } + + public getIsRequiredFilterSet(): boolean { + return this.isRequiredFilterSet; + } } diff --git a/src/app/model/FeasibilityQuery/Criterion/CriterionBuilder.ts b/src/app/model/FeasibilityQuery/Criterion/CriterionBuilder.ts index 60a59184..ad6be583 100644 --- a/src/app/model/FeasibilityQuery/Criterion/CriterionBuilder.ts +++ b/src/app/model/FeasibilityQuery/Criterion/CriterionBuilder.ts @@ -23,6 +23,7 @@ export class CriterionBuilder { private criterionHash?: string; private display?: string; private isInvalid?: boolean; + private isRequiredFilterSet: boolean; private parentId: string; private position?: CritGroupPosition; private termCodes?: Array; @@ -37,6 +38,7 @@ export class CriterionBuilder { criterionHash: string display: string isInvalid: boolean + isRequiredFilterSet: boolean uniqueID: string termCodes: Array } @@ -45,6 +47,7 @@ export class CriterionBuilder { this.criterionHash = mandatoryFields.criterionHash; this.display = mandatoryFields.display; this.isInvalid = mandatoryFields.isInvalid; + this.isRequiredFilterSet = mandatoryFields.isRequiredFilterSet; this.uniqueID = mandatoryFields.uniqueID; this.termCodes = mandatoryFields.termCodes; } @@ -145,6 +148,7 @@ export class CriterionBuilder { this.criterionHash, this.display, this.isInvalid, + this.isRequiredFilterSet, this.position, this.termCodes, this.timeRestriction, @@ -167,6 +171,7 @@ export class CriterionBuilder { this.criterionHash, this.display, this.isInvalid, + this.isRequiredFilterSet, this.position, this.termCodes, this.timeRestriction, diff --git a/src/app/model/FeasibilityQuery/Criterion/ReferenceCriterion.ts b/src/app/model/FeasibilityQuery/Criterion/ReferenceCriterion.ts index 31b92e93..0d770b9f 100644 --- a/src/app/model/FeasibilityQuery/Criterion/ReferenceCriterion.ts +++ b/src/app/model/FeasibilityQuery/Criterion/ReferenceCriterion.ts @@ -16,6 +16,7 @@ export class ReferenceCriterion extends AbstractCriterion { criterionHash: string, display: string, isInvalid: boolean, + isRequiredFilterSet: boolean, position: CritGroupPosition, termCodes: Array, timeRestriction: AbstractTimeRestriction, @@ -29,6 +30,7 @@ export class ReferenceCriterion extends AbstractCriterion { criterionHash, display, isInvalid, + isRequiredFilterSet, position, termCodes, timeRestriction, diff --git a/src/app/model/Utilities/AttributeDefinition.ts/AttributeDefinitions.ts b/src/app/model/Utilities/AttributeDefinition.ts/AttributeDefinitions.ts index c75d831a..6dfb97ad 100644 --- a/src/app/model/Utilities/AttributeDefinition.ts/AttributeDefinitions.ts +++ b/src/app/model/Utilities/AttributeDefinition.ts/AttributeDefinitions.ts @@ -10,7 +10,7 @@ export class AttributeDefinitions extends AbstractAttributeDefinition { constructor( name: string, type: FilterTypes, - optional: boolean = false, + optional: boolean, allowedUnits: Array = [], attributeCode?: TerminologyCode, max?: number, diff --git a/src/app/model/Utilities/CriterionCloner/CloneReferenceCriterion.ts b/src/app/model/Utilities/CriterionCloner/CloneReferenceCriterion.ts index 6532fa9d..2cbfb4d9 100644 --- a/src/app/model/Utilities/CriterionCloner/CloneReferenceCriterion.ts +++ b/src/app/model/Utilities/CriterionCloner/CloneReferenceCriterion.ts @@ -43,6 +43,7 @@ export class CloneAbstractCriterion { criterionHash: string display: string isInvalid: boolean + isRequiredFilterSet: boolean uniqueID: string termCodes: Array } { @@ -59,6 +60,7 @@ export class CloneAbstractCriterion { criterionHash, display, isInvalid: abstractCriterion.getIsInvalid(), + isRequiredFilterSet: abstractCriterion.getIsRequiredFilterSet(), uniqueID: uuidv4(), termCodes, }; diff --git a/src/app/modules/feasibility-query/components/editor/criterion-modal/edit-criterion-modal.component.ts b/src/app/modules/feasibility-query/components/editor/criterion-modal/edit-criterion-modal.component.ts index dca7315d..24c718bd 100644 --- a/src/app/modules/feasibility-query/components/editor/criterion-modal/edit-criterion-modal.component.ts +++ b/src/app/modules/feasibility-query/components/editor/criterion-modal/edit-criterion-modal.component.ts @@ -82,6 +82,7 @@ export class EditCriterionModalComponent implements OnInit { criterionHash: string display: string isInvalid: boolean + isRequiredFilterSet: boolean uniqueID: string termCodes: Array } { @@ -89,17 +90,37 @@ export class EditCriterionModalComponent implements OnInit { const termCodes = criterion.getTermCodes(); const display = criterion.getTermCodes()[0].getDisplay(); const criterionHash = this.criterion.getCriterionHash(); - + const isRequiredFilterSet = this.setIsFilterRequired(criterion); return { isReference: false, context, criterionHash, display, isInvalid: true, + isRequiredFilterSet, uniqueID: criterion.getId(), termCodes, }; } + + private setIsFilterRequired(criterion: Criterion): boolean { + return ( + criterion + .getValueFilters() + .filter( + (valueFilter) => + !valueFilter.getOptional() && + valueFilter.getConcept()?.getSelectedConcepts().length <= 0 + ).length > 0 || + this.criterion + .getAttributeFilters() + .filter( + (attributeFilter) => + !attributeFilter.getOptional() && + attributeFilter.getConcept()?.getSelectedConcepts().length <= 0 + ).length > 0 + ); + } public updateValueFilter(valueFilter: ValueFilter) { this.criterionBuilder.withValueFilters([valueFilter]); } diff --git a/src/app/modules/feasibility-query/components/editor/reference-criteria-modal/edit-reference-criteria-modal.component.ts b/src/app/modules/feasibility-query/components/editor/reference-criteria-modal/edit-reference-criteria-modal.component.ts index 65c941c8..a9403b91 100644 --- a/src/app/modules/feasibility-query/components/editor/reference-criteria-modal/edit-reference-criteria-modal.component.ts +++ b/src/app/modules/feasibility-query/components/editor/reference-criteria-modal/edit-reference-criteria-modal.component.ts @@ -69,6 +69,7 @@ export class EditReferenceCriteriaModalComponent implements OnInit { criterionHash: string display: string isInvalid: boolean + isRequiredFilterSet: boolean uniqueID: string termCodes: Array } { @@ -76,13 +77,14 @@ export class EditReferenceCriteriaModalComponent implements OnInit { const termCodes = criterion.getTermCodes(); const display = criterion.getTermCodes()[0].getDisplay(); const criterionHash = this.criterion.getCriterionHash(); - + const isRequiredFilterSet = this.setIsFilterRequired(criterion); return { isReference: false, context, criterionHash, display, isInvalid: true, + isRequiredFilterSet, uniqueID: criterion.getId(), termCodes, }; @@ -91,4 +93,23 @@ export class EditReferenceCriteriaModalComponent implements OnInit { closeDialog() { this.dialogRef.close(); } + + private setIsFilterRequired(criterion: Criterion): boolean { + return ( + criterion + .getValueFilters() + .filter( + (valueFilter) => + !valueFilter.getOptional() && + valueFilter.getConcept()?.getSelectedConcepts().length <= 0 + ).length > 0 || + this.criterion + .getAttributeFilters() + .filter( + (attributeFilter) => + !attributeFilter.getOptional() && + attributeFilter.getConcept()?.getSelectedConcepts().length <= 0 + ).length > 0 + ); + } } diff --git a/src/app/service/Criterion/Builder/Create/CreateCriterion.service.ts b/src/app/service/Criterion/Builder/Create/CreateCriterion.service.ts index 966f6440..fe8cd490 100644 --- a/src/app/service/Criterion/Builder/Create/CreateCriterion.service.ts +++ b/src/app/service/Criterion/Builder/Create/CreateCriterion.service.ts @@ -107,7 +107,7 @@ export class CreateCriterionService { new ValueDefinition( uiProfile.name, uiProfile.valueDefinition.type, - uiProfile.valueDefinition.optional, + false, //uiProfile.valueDefinition.optional, uiProfile.valueDefinition.allowedUnits?.map( (unit) => new QuantityUnit(unit.code, unit.display, unit.system) ) || [], @@ -160,6 +160,7 @@ export class CreateCriterionService { criterionHash: string display: string isInvalid: boolean + isRequiredFilterSet: boolean uniqueID: string termCodes: Array } { @@ -167,6 +168,7 @@ export class CreateCriterionService { const termCodes = criteriaProfileData.getTermCodes(); const display = criteriaProfileData.getTermCodes()[0].getDisplay(); const criterionHash = this.criterionHashService.createHash(context, termCodes[0]); + const isFilterRequired = !this.setIsRequiredFilterSet(criteriaProfileData); return { isReference: false, @@ -174,11 +176,23 @@ export class CreateCriterionService { criterionHash, display, isInvalid: true, + isRequiredFilterSet: isFilterRequired, uniqueID: uuidv4(), termCodes, }; } + private setIsRequiredFilterSet(criteriaProfileData: CriteriaProfileData) { + return ( + criteriaProfileData + .getAttributeDefinitions() + .filter((attributeDefinition) => !attributeDefinition.getOptional()).length > 0 || + criteriaProfileData + .getValueDefinitions() + .filter((valueDefinition) => !valueDefinition.getOptional()).length > 0 + ); + } + private processAttributeDefinition( criterionBuilder: CriterionBuilder, attributeDefinition: AttributeDefinitions diff --git a/src/app/service/Criterion/Builder/CriterionMetadata.service.ts b/src/app/service/Criterion/Builder/CriterionMetadata.service.ts index 0df63328..e4787a06 100644 --- a/src/app/service/Criterion/Builder/CriterionMetadata.service.ts +++ b/src/app/service/Criterion/Builder/CriterionMetadata.service.ts @@ -3,6 +3,7 @@ import { CriterionHashService } from '../CriterionHash.service'; import { Injectable } from '@angular/core'; import { TerminologyCode } from 'src/app/model/Terminology/TerminologyCode'; import { v4 as uuidv4 } from 'uuid'; +import { ValueDefinition } from 'src/app/model/Utilities/AttributeDefinition.ts/ValueDefnition'; @Injectable({ providedIn: 'root', @@ -22,6 +23,7 @@ export class CriterionMetadataService { criterionHash: string display: string isInvalid: boolean + isRequiredFilterSet: boolean uniqueID: string termCodes: Array } { @@ -29,6 +31,7 @@ export class CriterionMetadataService { const termCodes = criteriaProfileData.getTermCodes(); const display = termCodes[0].getDisplay(); const criterionHash = this.criterionHashService.createHash(context, termCodes[0]); + const isFilterRequired = !this.setIsRequiredFilterSet(criteriaProfileData); return { isReference: false, @@ -36,8 +39,20 @@ export class CriterionMetadataService { criterionHash, display, isInvalid: false, + isRequiredFilterSet: isFilterRequired, uniqueID: uuidv4(), termCodes, }; } + + private setIsRequiredFilterSet(criteriaProfileData: CriteriaProfileData) { + return ( + criteriaProfileData + .getAttributeDefinitions() + .filter((attributeDefinition) => !attributeDefinition.getOptional()).length > 0 || + criteriaProfileData + .getValueDefinitions() + .filter((valueDefinition) => !valueDefinition.getOptional()).length > 0 + ); + } } diff --git a/src/app/shared/components/criteria-box/criteria-box.component.html b/src/app/shared/components/criteria-box/criteria-box.component.html index c84c3a1c..f876d5f6 100644 --- a/src/app/shared/components/criteria-box/criteria-box.component.html +++ b/src/app/shared/components/criteria-box/criteria-box.component.html @@ -6,9 +6,13 @@ class="container" >
-
+
{{ criterion.getTermCodes()[0].getDisplay() }} -
+
{{ criterion.getContext().getDisplay() }}, {{ criterion.getTermCodes()[0].getCode() }}, @@ -16,6 +20,13 @@
+
+ + + {{ 'SHAREDCOMPONENTS.CRITERIA_BOX.REQUIRED_FILTER' | translate }} + +
+
diff --git a/src/app/shared/components/criteria-box/criteria-box.component.scss b/src/app/shared/components/criteria-box/criteria-box.component.scss index b76c894f..c7e7b784 100644 --- a/src/app/shared/components/criteria-box/criteria-box.component.scss +++ b/src/app/shared/components/criteria-box/criteria-box.component.scss @@ -58,3 +58,14 @@ .content { width: 98%; } + +.img-layout { + height: 25px; + width: 25px; + margin-right: 1%; +} + +.warning-message { + color: red; + font-size: medium; +} diff --git a/src/app/shared/components/criteria-box/criteria-box.component.ts b/src/app/shared/components/criteria-box/criteria-box.component.ts index ec51c61c..1702fafd 100644 --- a/src/app/shared/components/criteria-box/criteria-box.component.ts +++ b/src/app/shared/components/criteria-box/criteria-box.component.ts @@ -27,6 +27,8 @@ export class CriteriaBoxComponent implements OnInit { system: string; + isFilterRequired: boolean; + constructor( private menuService: CriterionMenuItems, private filterChipsService: CriterionFilterChipService @@ -38,6 +40,7 @@ export class CriteriaBoxComponent implements OnInit { ); this.getMenuItems(); this.getFilterChips(); + this.isFilterRequired = this.setIsFilterRequired(); } private getMenuItems() { @@ -53,4 +56,23 @@ export class CriteriaBoxComponent implements OnInit { .getAttributeFilters() .some((attributeFilter) => attributeFilter.isReferenceSet()); } + + private setIsFilterRequired(): boolean { + return ( + this.criterion + .getValueFilters() + .filter( + (valueFilter) => + !valueFilter.getOptional() && + valueFilter.getConcept()?.getSelectedConcepts().length <= 0 + ).length > 0 || + this.criterion + .getAttributeFilters() + .filter( + (attributeFilter) => + !attributeFilter.getOptional() && + attributeFilter.getConcept()?.getSelectedConcepts().length <= 0 + ).length > 0 + ); + } } diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 2a60e170..89eb71f6 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -9,6 +9,9 @@ "patient_number": "Anzahl der Patienten", "Display": "Name", "Terminology Code": "Terminologie-Code", + "CRITERIA_BOX": { + "REQUIRED_FILTER": "Bitte einen Filter setzen" + }, "ACTIONBAR": { "SELECTED_CRITERIA": { "SINGULAR": "Sie haben {{amount}} Kriterium ausgewählt", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index c24022ed..4cbd4454 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -19,6 +19,9 @@ "PLURAL": "You have added {{amount}} criteria to the stage" } }, + "CRITERIA_BOX": { + "REQUIRED_FILTER": "Please set a filter" + }, "FILTER": { "CONTEXT": "Context", "AVAILABILITY": "Availability",