From 1560f09a38138c7d4d771de4fba9a2b1664ae2e2 Mon Sep 17 00:00:00 2001 From: Miquel Gall Date: Tue, 22 Apr 2025 12:04:49 -0400 Subject: [PATCH 1/2] Adjustments ready and tested --- .../assets/js/models/FormModel.ts | 17 ++++++++++- samples/017-populateTeamProperties/README.md | 29 +++++++++++++++++- .../assets/js/custom.ts | 30 +++++++++++++++---- .../descriptor.json | 27 ++++++++++------- 4 files changed, 84 insertions(+), 19 deletions(-) diff --git a/samples/016-ManageTeamWork/assets/js/models/FormModel.ts b/samples/016-ManageTeamWork/assets/js/models/FormModel.ts index 646ccdb..dbc50f6 100644 --- a/samples/016-ManageTeamWork/assets/js/models/FormModel.ts +++ b/samples/016-ManageTeamWork/assets/js/models/FormModel.ts @@ -147,6 +147,14 @@ export class LaborFormModel { }); this.trackStep("POPULATE TECHNICIANS", "END"); } + private cleanTechnicianDropdown(): void { + this.trackStep("CLEAN TECHNICIANS", "START"); + // Remove all options ( to prevent re-loading of same options) + while (this.technicianSelect.options.length > 0) { + this.technicianSelect.remove(0); + } + this.trackStep("CLEAN TECHNICIANS", "END"); + } private trackStep( action: string, step: string, @@ -172,7 +180,12 @@ export class LaborFormModel { this.laborTypeSelect.appendChild(option); }); } - + private cleanLaborTypeDropdown(): void { + // Clean this.laborTypeSelect + while (this.laborTypeSelect.options.length > 0) { + this.laborTypeSelect.remove(0); + } + } // Get the value of an input field getInputValue(id: string): string { return (document.getElementById(id) as HTMLInputElement).value; @@ -378,6 +391,8 @@ export class LaborFormModel { loadForm = (): void => { this.trackStep("LOAD", "START"); this.cleanLaborLines(); + this.cleanLaborTypeDropdown(); + this.cleanTechnicianDropdown(); this.resetForm(); this.populateTechnicianDropdown(); this.populateLaborTypeDropdown(); diff --git a/samples/017-populateTeamProperties/README.md b/samples/017-populateTeamProperties/README.md index 550ac9f..458872d 100644 --- a/samples/017-populateTeamProperties/README.md +++ b/samples/017-populateTeamProperties/README.md @@ -9,6 +9,7 @@ This plugins allows the update the right properties to report team labor using a **_Secure Parameters_** - `propertiesPrefix` : Prefix to be used to update the properties. Recommended value : A*TEAM_PROPERTIES* +- `maxNumberOfassistants` : Max. number of team members ( in addition to the team leader ) that the application will manage. Default = 5 **_Open Parameters_** @@ -16,10 +17,36 @@ None **_Properties needed_** -None +- `length` +- `ETA` +- `end_time` +- `A_TEAM_PROPERTIES_pname_1` +- `A_TEAM_PROPERTIES_pid_1` +- `A_TEAM_PROPERTIES_ETA_1` +- `A_TEAM_PROPERTIES_end_time_1` +- `A_TEAM_PROPERTIES_pname_2` +- `A_TEAM_PROPERTIES_pid_2` +- `A_TEAM_PROPERTIES_ETA_2` +- `A_TEAM_PROPERTIES_end_time_2` +- `A_TEAM_PROPERTIES_pname_3` +- `A_TEAM_PROPERTIES_pid_3` +- `A_TEAM_PROPERTIES_ETA_3` +- `A_TEAM_PROPERTIES_end_time_3` +- `A_TEAM_PROPERTIES_pname_4` +- `A_TEAM_PROPERTIES_pid_4` +- `A_TEAM_PROPERTIES_ETA_4` +- `A_TEAM_PROPERTIES_end_time_4` +- `A_TEAM_PROPERTIES_pname_5` +- `A_TEAM_PROPERTIES_pid_5` +- `A_TEAM_PROPERTIES_ETA_5` +- `A_TEAM_PROPERTIES_end_time_5` ## How to use +Create the properties according to the max number of team member ( default is 5 + the team leader). + +For the ETA and end_time properties, it is recommended to include the regular expression /^\b((1[0-2]|0?[1-9]):([0-5][0-9]) ([AaPp][Mm]))/ + Add the plugin as a button within the activity details screen. Once the button is clicked, it will update the properties and it will allow the Form to show the list of technicians. diff --git a/samples/017-populateTeamProperties/assets/js/custom.ts b/samples/017-populateTeamProperties/assets/js/custom.ts index cd471c1..b2f01ab 100644 --- a/samples/017-populateTeamProperties/assets/js/custom.ts +++ b/samples/017-populateTeamProperties/assets/js/custom.ts @@ -18,17 +18,35 @@ export class CustomPlugin extends OFSPlugin { let teamMembers = _data.team?.teamMembers || {}; // For all elements in the team, set the properties starting with A_TEAM_PROPERTIES_pname_1 = member.pname and A_TEAM_PROPERTIES_pid_1 = key let index = 1; - let activityData = _data.activity; + let activityData: any = { aid: _data.activity.aid }; + // Read secure paramenters maxNumberOfassistants and propertiesPrefix + let maxNumberOfassistants: number = 5; + let propertiesPrefix: string = "A_TEAM_PROPERTIES_"; + // Check if the secure parameters are set + for (var param in _data.securedData) { + if (param == "maxNumberOfassistants") { + maxNumberOfassistants = Number( + _data.securedData.maxNumberOfassistants + ); + } else if (param == "propertiesPrefix") { + propertiesPrefix = _data.securedData.propertiesPrefix; + } + } // Initialize A_TEAM_PROPERTIES_pname_ A_TEAM_PROPERTIES_pid from 1 to 5 to "" - for (let i = 1; i <= 5; i++) { - activityData[`A_TEAM_PROPERTIES_pname_${i}`] = ""; - activityData[`A_TEAM_PROPERTIES_pid_${i}`] = ""; + for (let i = 1; i <= maxNumberOfassistants; i++) { + activityData[`${propertiesPrefix}pname_${i}`] = ""; + activityData[`${propertiesPrefix}pid_${i}`] = ""; + activityData[`${propertiesPrefix}ETA_${i}`] = ""; + activityData[`${propertiesPrefix}end_time_${i}`] = ""; } for (const [key, member] of Object.entries(teamMembers)) { const typedMember = member as { pname: string }; // Explicitly type member - activityData[`A_TEAM_PROPERTIES_pname_${index}`] = + activityData[`${propertiesPrefix}pname_${index}`] = typedMember.pname; - activityData[`A_TEAM_PROPERTIES_pid_${index}`] = key; + activityData[`${propertiesPrefix}pid_${index}`] = key; + activityData[`${propertiesPrefix}ETA_${index}`] = activityData.ETA; + activityData[`${propertiesPrefix}end_time_${index}`] = + activityData.end_time; index++; } let dataToSend: any = { diff --git a/samples/017-populateTeamProperties/descriptor.json b/samples/017-populateTeamProperties/descriptor.json index 7e4566d..1905da4 100644 --- a/samples/017-populateTeamProperties/descriptor.json +++ b/samples/017-populateTeamProperties/descriptor.json @@ -1,28 +1,29 @@ { "properties": { "activity": [ - "appt_number", "length", "ETA", - "astatus", - "date", - "caddress", - "ccity", - "ccompany", - "cname", - "cstate", - "appt_number", - "czip", + "end_time", "A_TEAM_PROPERTIES_pname_1", "A_TEAM_PROPERTIES_pid_1", + "A_TEAM_PROPERTIES_ETA_1", + "A_TEAM_PROPERTIES_end_time_1", "A_TEAM_PROPERTIES_pname_2", "A_TEAM_PROPERTIES_pid_2", + "A_TEAM_PROPERTIES_ETA_2", + "A_TEAM_PROPERTIES_end_time_2", "A_TEAM_PROPERTIES_pname_3", "A_TEAM_PROPERTIES_pid_3", + "A_TEAM_PROPERTIES_ETA_3", + "A_TEAM_PROPERTIES_end_time_3", "A_TEAM_PROPERTIES_pname_4", "A_TEAM_PROPERTIES_pid_4", + "A_TEAM_PROPERTIES_ETA_4", + "A_TEAM_PROPERTIES_end_time_4", "A_TEAM_PROPERTIES_pname_5", - "A_TEAM_PROPERTIES_pid_5" + "A_TEAM_PROPERTIES_pid_5", + "A_TEAM_PROPERTIES_ETA_5", + "A_TEAM_PROPERTIES_end_time_5" ], "provider": [ "pid", @@ -33,6 +34,10 @@ { "name": "propertiesPrefix", "value": "A_TEAM_PROPERTIES_" + }, + { + "name": "maxNumberOfassistants", + "value": "5" } ] } \ No newline at end of file From 8ae89e23d82fec42431fdbf129c37fa29239393e Mon Sep 17 00:00:00 2001 From: Miquel Gall Date: Tue, 22 Apr 2025 13:42:20 -0400 Subject: [PATCH 2/2] Adjustments to manage previously created Members labor lines --- .../assets/js/custom.ts | 82 +++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/samples/017-populateTeamProperties/assets/js/custom.ts b/samples/017-populateTeamProperties/assets/js/custom.ts index b2f01ab..310c9b7 100644 --- a/samples/017-populateTeamProperties/assets/js/custom.ts +++ b/samples/017-populateTeamProperties/assets/js/custom.ts @@ -17,8 +17,9 @@ export class CustomPlugin extends OFSPlugin { open(_data: OFSOpenMessageCustom) { let teamMembers = _data.team?.teamMembers || {}; // For all elements in the team, set the properties starting with A_TEAM_PROPERTIES_pname_1 = member.pname and A_TEAM_PROPERTIES_pid_1 = key - let index = 1; + let activityData: any = { aid: _data.activity.aid }; + const inputActivityData = _data.activity; // Read secure paramenters maxNumberOfassistants and propertiesPrefix let maxNumberOfassistants: number = 5; let propertiesPrefix: string = "A_TEAM_PROPERTIES_"; @@ -32,21 +33,92 @@ export class CustomPlugin extends OFSPlugin { propertiesPrefix = _data.securedData.propertiesPrefix; } } + console.info( + `${this.tag} : Team members before ${JSON.stringify(teamMembers)}` + ); + let existentTeamMembers: any = {}; // Initialize A_TEAM_PROPERTIES_pname_ A_TEAM_PROPERTIES_pid from 1 to 5 to "" for (let i = 1; i <= maxNumberOfassistants; i++) { - activityData[`${propertiesPrefix}pname_${i}`] = ""; + // activityData[`${propertiesPrefix}pid_${i}`exists in teamMembers as key, remove + // the team member from the teamMembers object and ignore continue the loop to the next one + if (`${propertiesPrefix}pid_${i}` in inputActivityData) { + console.debug( + `${this.tag} : Let's check if team - member ${ + inputActivityData[`${propertiesPrefix}pid_${i}`] + } - Exists in the teamMembers object` + ); + if ( + inputActivityData[`${propertiesPrefix}pid_${i}`] in + teamMembers + ) { + console.debug( + `${this.tag} : Found the team member ${ + inputActivityData[`${propertiesPrefix}pid_${i}`] + } - It will be removed from teamMembers entity` + ); + // Add this team member to existentTeamMembers + let teamMember: any = + teamMembers[ + inputActivityData[`${propertiesPrefix}pid_${i}`] + ]; + teamMember.ETA = + inputActivityData[`${propertiesPrefix}ETA_${i}`]; + teamMember.end_time = + inputActivityData[`${propertiesPrefix}end_time_${i}`]; + existentTeamMembers[ + inputActivityData[`${propertiesPrefix}pid_${i}`] + ] = teamMember; + delete teamMembers[ + inputActivityData[`${propertiesPrefix}pid_${i}`] + ]; + // Add this + } + } + } + // Now I can reset all properties + for (let i = 1; i <= maxNumberOfassistants; i++) { + console.debug( + `${this.tag} : Team member ${ + inputActivityData[`${propertiesPrefix}pid_${i}`] + } not found in the teamMembers object` + ); + // If the key does not exist, set the value to "" activityData[`${propertiesPrefix}pid_${i}`] = ""; + activityData[`${propertiesPrefix}pname_${i}`] = ""; activityData[`${propertiesPrefix}ETA_${i}`] = ""; activityData[`${propertiesPrefix}end_time_${i}`] = ""; } + console.info( + `${this.tag} : Team members after ${JSON.stringify(teamMembers)}` + ); + let index = 1; + for (const [key, member] of Object.entries(existentTeamMembers)) { + const typedMember = member as { + pname: string; + ETA: string; + end_time: string; + }; + activityData[`${propertiesPrefix}pname_${index}`] = + typedMember.pname; + activityData[`${propertiesPrefix}pid_${index}`] = key; + activityData[`${propertiesPrefix}ETA_${index}`] = typedMember.ETA; + activityData[`${propertiesPrefix}end_time_${index}`] = + typedMember.end_time; + index++; + } + // This team member should exist in the activity properties for (const [key, member] of Object.entries(teamMembers)) { - const typedMember = member as { pname: string }; // Explicitly type member + const typedMember = member as { pname: string }; + // Check if the key already exists in the activityData object + // as one of the ${propertiesPrefix}pname_$other_index values + // If it does, ignore this member and go to the next one activityData[`${propertiesPrefix}pname_${index}`] = typedMember.pname; activityData[`${propertiesPrefix}pid_${index}`] = key; - activityData[`${propertiesPrefix}ETA_${index}`] = activityData.ETA; + activityData[`${propertiesPrefix}ETA_${index}`] = + inputActivityData.ETA; activityData[`${propertiesPrefix}end_time_${index}`] = - activityData.end_time; + inputActivityData.end_time; index++; } let dataToSend: any = {