Skip to content

Commit

Permalink
Merge pull request #1967 from IDEMSInternational/fix/combo-box-answer…
Browse files Browse the repository at this point in the history
…-list-data-list

Fix: combo box answer_list can be a data_list
  • Loading branch information
esmeetewinkel authored Jul 4, 2023
2 parents 83893ed + 907cb96 commit 46f02c7
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import {
getNumberParamFromTemplateRow,
getParamFromTemplateRow,
getStringParamFromTemplateRow,
IAnswerListItem,
parseAnswerList,
} from "src/app/shared/utils";
import { FormBuilder, FormControl, FormGroup } from "@angular/forms";
import { ModalController } from "@ionic/angular";

interface AnswerBody {
name: string | null;
text: string | null;
}
import { objectToArray } from "../../../utils";

@Component({
selector: "combo-box-modal",
Expand All @@ -26,7 +24,7 @@ export class ComboBoxModalComponent implements OnInit {
@Input() customAnswerSelected: boolean;
@Input() style: string;
formData: FormGroup | null;
valuesFromListAnswers: AnswerBody[];
valuesFromListAnswers: IAnswerListItem[];
textTitle: string | null;
inputAllowed: boolean = false;
form: FormGroup;
Expand All @@ -41,7 +39,7 @@ export class ComboBoxModalComponent implements OnInit {
}

getParams() {
this.valuesFromListAnswers = this.convertToObject(
this.valuesFromListAnswers = parseAnswerList(
getParamFromTemplateRow(this.row, "answer_list", null)
);
this.textTitle = getStringParamFromTemplateRow(this.row, "text", null);
Expand All @@ -65,27 +63,6 @@ export class ComboBoxModalComponent implements OnInit {
}
}

convertToObject(answers_list: string[]): AnswerBody[] {
let answers: AnswerBody[] = [];
if (answers_list) {
answers_list.map((item) => {
const obj: AnswerBody = {
text: null,
name: null,
};
const stringProperties = item.split("|");
stringProperties.forEach((s) => {
const [field, value] = s.split(":").map((v) => v.trim());
if (field && value) {
obj[field] = value;
}
});
answers.push(obj);
});
return answers;
}
}

buildForm() {
this.form = this.fb.group({
answer: new FormControl(null, []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getBooleanParamFromTemplateRow,
getParamFromTemplateRow,
getStringParamFromTemplateRow,
parseAnswerList,
} from "src/app/shared/utils";
import { TemplateBaseComponent } from "../base";
import { ITemplateRowProps } from "../../models";
Expand All @@ -27,19 +28,27 @@ export class TmplComboBoxComponent
style: string;
text = "";
customAnswerSelected: boolean = false;
customAnswerText: string;
private componentDestroyed$ = new ReplaySubject(1);
constructor(private modalController: ModalController, private templateService: TemplateService) {
super();
}

ngOnInit(): void {
this.getParams();
const listAnswers: string[] = getParamFromTemplateRow(this._row, "answer_list", null);
const answerList = parseAnswerList(getParamFromTemplateRow(this._row, "answer_list", []));

this.customAnswerSelected =
listAnswers && this._row.value
? !listAnswers.find((x) => x.includes(this._row.value))
answerList.length > 0 && this._row.value
? !answerList.find((x) => x.name === this._row.value)
: false;
this.text = this.getText(this._row.value, listAnswers);

this.text = "";
if (this._row.value) {
this.text = this.customAnswerSelected
? this.customAnswerText
: answerList.find((answerListItem) => answerListItem.name === this._row.value)?.text;
}
}

getParams() {
Expand All @@ -52,19 +61,6 @@ export class TmplComboBoxComponent
this.style = getStringParamFromTemplateRow(this._row, "style", "");
}

getText(aValue: string, listAnswers: string[]): string {
if (aValue) {
if (aValue === "other") {
return this._row.parameter_list["customAnswer"];
}
const textFromList = listAnswers
.find((answer: string) => answer.includes(aValue))
?.match(/(?<=text:).+/)[0]
.trim();
return textFromList ? textFromList : aValue;
}
}

async openModal() {
const modal = await this.modalController.create({
component: ComboBoxModalComponent,
Expand All @@ -81,15 +77,12 @@ export class TmplComboBoxComponent

modal.onDidDismiss().then(async (data) => {
this.prioritisePlaceholder = false;
const value = data?.data?.answer?.name;
this.text = data?.data?.answer?.text;
this.customAnswerSelected = data?.data?.customAnswerSelected;
if (this.customAnswerSelected) {
this._row.parameter_list["customAnswer"] = data?.data?.answer?.text;
} else {
this._row.parameter_list["customAnswer"] = null;
}
await this.setValue(value);
this.customAnswerText = this.customAnswerSelected
? (this.text = data?.data?.answer?.text)
: "";
await this.setValue(data?.data?.answer?.name);
await this.triggerActions("changed");
});
await modal.present();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { Component, Input } from "@angular/core";
import { TemplateBaseComponent } from "../base";
import { FlowTypes, ITemplateRowProps } from "../../models";
import { getParamFromTemplateRow } from "src/app/shared/utils";
import { objectToArray } from "../../utils";

interface IAnswerListItem {
name: string;
image?: string;
text?: string;
}
import { getParamFromTemplateRow, IAnswerListItem, parseAnswerList } from "src/app/shared/utils";

interface IRadioButtonGridParams {
/** List of options presented as radio items */
Expand Down Expand Up @@ -72,7 +65,8 @@ export class TmplRadioButtonGridComponent

private setParams() {
this.parameter_list = this._row.parameter_list || ({} as any);
this.radioItems = this.generateItemList();
const answerList = getParamFromTemplateRow(this._row, "answer_list", []);
this.radioItems = parseAnswerList(answerList);
this.gridStyle = this.generateGridStyle();
}

Expand All @@ -98,41 +92,4 @@ export class TmplRadioButtonGridComponent
};
return style;
}

/**
* Adapted from radio-group.component
* Convert input answer_list to rendered item list
*/
private generateItemList() {
let answerList = getParamFromTemplateRow(this._row, "answer_list", []);
// Convert if datalist input (hashmap to array)
if (answerList.constructor === {}.constructor) {
answerList = objectToArray(answerList);
}
const radioItems: IAnswerListItem[] = answerList.map(
(item: string | Record<string, string>) => {
if (typeof item === "string") {
return this.parseAnswerListItemString(item);
}
return item as any;
}
);
return radioItems;
}

/**
* convert string to relevant mappings
* TODO - CC 2023-03-16 - should ideally convert in parsers instead of at runtime
*/
private parseAnswerListItemString(item: string) {
const itemObj: IAnswerListItem = {} as any;
const stringProperties = item.split("|");
stringProperties.forEach((s) => {
const [field, value] = s.split(":").map((v) => v.trim());
if (field && value) {
itemObj[field] = value;
}
});
return itemObj;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,10 @@ import {
getNumberParamFromTemplateRow,
getParamFromTemplateRow,
getStringParamFromTemplateRow,
parseAnswerList,
IAnswerListItem,
} from "../../../../utils";
import { ReplaySubject } from "rxjs";
import { objectToArray } from "../../utils/template-utils";

interface IButton {
name: string | null;
image: string | null;
text: string | null;
image_checked: string | null;
}

@Component({
selector: "plh-radio-group",
Expand All @@ -37,7 +31,7 @@ export class TmplRadioGroupComponent
@Input() changeTheme: EventEmitter<boolean>;
@Input() parent: TemplateContainerComponent;
@ViewChild("labelImage", { static: false, read: true }) labelImage: ElementRef;
arrayOfBtn: Array<IButton>;
arrayOfBtn: Array<IAnswerListItem>;
groupName: string;
windowWidth: number;
private componentDestroyed$ = new ReplaySubject(1);
Expand Down Expand Up @@ -84,30 +78,9 @@ export class TmplRadioGroupComponent
*/
createArrayBtnElement(answer_list: string[]) {
if (answer_list) {
// NOTE CC 2021-08-07 - datalists might be used which currently only format as objects
// manually convert to array if required (temp method until better handling found)
if (typeof answer_list === "object") {
answer_list = objectToArray(answer_list);
}
const arrayOfBtn = answer_list.map((item) => {
// convert string to relevant mappings
let itemObj: IButton = {} as any;
if (typeof item === "string") {
const stringProperties = item.split("|");
stringProperties.forEach((s) => {
const [field, value] = s.split(":").map((v) => v.trim());
if (field && value) {
itemObj[field] = value;
}
});
}
// NOTE CC 2021-08-07 - allow passing of object, not just string for conversion
else {
itemObj = item;
}
const processed = this.processButtonFields(itemObj);
return processed;
});
let arrayOfBtn = parseAnswerList(answer_list);
arrayOfBtn = arrayOfBtn.map((itemObj) => this.processButtonFields(itemObj));

// TODO - CC 2023-03-15 could lead to strange behaviour, to review
// (checks every item but keeps overriding the button type depending on what it finds)
arrayOfBtn.forEach((item) => {
Expand All @@ -122,8 +95,8 @@ export class TmplRadioGroupComponent
return arrayOfBtn;
}
}
private processButtonFields(button: IButton) {
const processed: IButton = {
private processButtonFields(button: IAnswerListItem) {
const processed: IAnswerListItem = {
text: null,
image: null,
name: null,
Expand Down
46 changes: 46 additions & 0 deletions src/app/shared/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { diff } from "deep-object-diff";
import { Observable } from "rxjs";
import { map, pairwise, filter, share } from "rxjs/operators";
import { FlowTypes } from "../model";
import { objectToArray } from "../components/template/utils";

/**
* Generate a random string of characters in base-36 (a-z and 0-9 characters)
Expand Down Expand Up @@ -392,3 +393,48 @@ function supportsOptionalChaining() {
}
return true;
}

export interface IAnswerListItem {
name: string;
image?: string;
text?: string;
image_checked?: string | null;
}

/**
* Parse an answer_list parameter and return an array of AnswerListItems
* @param answerList an answer_list parameter, either an array of IAnswerListItems
* (possibly still in string representation) or a data list (hashmap of IAnswerListItems)
*/
export function parseAnswerList(answerList: any) {
// If a data_list (hashmap) is provided as input, convert to an array
if (answerList.constructor === {}.constructor) {
answerList = objectToArray(answerList);
}
const answerListItems: IAnswerListItem[] = answerList.map(
(item: string | Record<string, string>) => {
return parseAnswerListItem(item);
}
);
return answerListItems;
}

/**
* Convert answer list item (string or object) to relevant mappings
* TODO - CC 2023-03-16 - should ideally convert in parsers instead of at runtime
*/
function parseAnswerListItem(item: any) {
const itemObj: IAnswerListItem = {} as any;
if (typeof item === "string") {
const stringProperties = item.split("|");
stringProperties.forEach((s) => {
const [field, value] = s.split(":").map((v) => v.trim());
if (field && value) {
itemObj[field] = value;
}
});
// NOTE CC 2021-08-07 - allow passing of object, not just string for conversion
return itemObj;
}
return item;
}

0 comments on commit 46f02c7

Please sign in to comment.