diff --git a/README.md b/README.md index f0afc8e..b607ed5 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ Community examples, open to everyone. This is the section external contributions | [`expense-policy-agent-skill`](examples/expense-policy-agent-skill) | A markdown skill that teaches an agent to answer expense policy questions and escalate anything it cannot verify. | Agent Skill | | [`employee-data-orchestration`](examples/employee-data-orchestration) | An orchestration that reads worker data from one tenant and creates matching records through the Workday REST API. | Orchestration | | [`peer-kudos-home-card`](examples/peer-kudos-home-card) | An Extend app with a Home page card, custom business object, and orchestration that lets employees celebrate peer contributions and notifies managers. | Extend App | +| [`promotion-nomination`](examples/promotion-nomination) | A manager nominates a direct report for promotion. Career data is prefilled from Workday, the nomination is saved to a business object, and a business process routes it for approval. | Extend App | | [`pto-policy-agent-skill`](examples/pto-policy-agent-skill) | A markdown skill that teaches an agent to answer employee questions about PTO, leave accrual, rollover, and sick leave policy with clear escalation rules. | Agent Skill | | [`stock-notifications`](examples/stock-notifications) | An Extend app that fetches Workday's current stock price from an external API and displays it on a home page card. | Extend App | | [`wql-anniversary-celebrations`](examples/wql-anniversary-celebrations) | An orchestration that queries Workday via WQL for active workers celebrating milestone work anniversaries and formats an announcement digest payload for collaboration channels. | Orchestration | diff --git a/examples/promotion-nomination/README.md b/examples/promotion-nomination/README.md new file mode 100644 index 0000000..e2be148 --- /dev/null +++ b/examples/promotion-nomination/README.md @@ -0,0 +1,34 @@ +# Promotion Nomination + +## What it is + +A Workday Extend app that lets a manager nominate one of their direct reports for promotion. The manager picks an employee, sees career details pulled from Workday, adds a justification, and submits. The nomination is saved to a custom business object and sent into a business process for approval. A second page shows a submitted nomination as read-only details when someone opens the business process event. + +It is a good reference if you want to see WQL-driven form prefill, a two-step submit (save an object, then start a business process on it), and a VIEW page driven by a business process event ID. + +## What's inside + +- `presentation/managerNomination.pmd`: the landing page (route `/`). Employee picker, prefilled career fields, nomination form, and the submit logic. +- `presentation/eventDetails.pmd`: the read-only page (route `/eventDetails/{eventId}`). Loads the business process event, follows it to the saved nomination, and displays it. +- `presentation/promotionNomination_rvylxm.amd`: the app definition. Declares the two routes and the five data providers (`workday-staffing`, `workday-wql`, `workday-common`, `workday-bp`, `app`), all built on `apiGatewayEndpoint`. +- `presentation/promotionNomination_rvylxm.smd`: the site definition. Holds the app and site ids, the language, and the SSO authentication scheme. + +Both pages use the `ManagerPromotionNomination` security domain. + +## How to use it + +1. **Pick an employee.** The list comes from a WQL query on `myDirectReports`. +2. **Review the prefilled data.** Once an employee is chosen, the page fills in current job profile, current job title, time in job profile, hire date and last promotion date. These fields are read-only. +3. **Complete the nomination.** Choose a reason (Merit/Performance, Increased Responsibilities, or Organizational Restructuring), a proposed effective date and a proposed job profile. The promotion cycle is set to the current year. Then answer three required questions: why the worker is being considered, what the business need is, and how the worker suits the role. +4. **Submit.** The page posts the nomination to the `promotionNominationBOS` business object, then posts to `promotionNominationBPEvents` with that object as the business process target. The new event ID is returned to the flow as `PromotionSubmissionResponseValue`. +5. **View the result.** Opening the business process event lands on `eventDetails`, which shows the nominee, nominator, reason, dates, job profiles and the three written answers. + +To test, sign in as a manager with direct reports and run through the steps above. Also try an employee with no hire date, and a submission with no proposed job profile selected. Both should still submit. + +## Before you deploy + +- **App reference id.** If he site.applicationid throws an error on the app builder, please replace it with your application ID. +- **Worker type ID.** The `getEmployeeList` endpoint in `managerNomination.pmd` limits direct reports to one worker type, using the ID `d588c41a446c11de98360015c5e6daf6`. That ID is specific to the tenant this example came from. Replace it with the worker type you want, or remove the filter. +- **Security domain.** Map `ManagerPromotionNomination` to the security groups that should submit and view nominations, then activate pending security policy changes. +- **Business object and business process.** The app expects a `promotionNominationBOS` business object and a `promotionNominationBPEvents` business process. Approval steps, such as routing to a next-level manager or a People Business Partner, are set up in the business process definition, not in these page files. Configure them for your own approval chain. +- **Last promotion date fallback.** When a worker has no last promotion date, `managerNomination.pmd` uses `2020-01-01`. Change that default in the employee `onChange` if it does not suit your data. diff --git a/examples/promotion-nomination/example.json b/examples/promotion-nomination/example.json new file mode 100644 index 0000000..4e55cfa --- /dev/null +++ b/examples/promotion-nomination/example.json @@ -0,0 +1,5 @@ +{ + "title": "Promotion Nomination", + "description": "A manager nominates a direct report for promotion. Career data is prefilled from Workday, the nomination is saved to a business object, and a business process routes it for approval.", + "type": "Extend App" +} diff --git a/examples/promotion-nomination/model/DefaultPhoto.attachment b/examples/promotion-nomination/model/DefaultPhoto.attachment new file mode 100644 index 0000000..b7730ee --- /dev/null +++ b/examples/promotion-nomination/model/DefaultPhoto.attachment @@ -0,0 +1,13 @@ +{ + "id": 1, + "name": "DefaultPhoto", + "label": "Default Photo", + "defaultSecurityDomains": [ + "ManagerPromotionNomination" + ], + "defaultCollection": { + "name": "defaultPhotos", + "label": "Default Photos" + }, + "fields": [] +} \ No newline at end of file diff --git a/examples/promotion-nomination/model/ManagerPromotionNomination.securitydomain b/examples/promotion-nomination/model/ManagerPromotionNomination.securitydomain new file mode 100644 index 0000000..ba44c22 --- /dev/null +++ b/examples/promotion-nomination/model/ManagerPromotionNomination.securitydomain @@ -0,0 +1,6 @@ +{ + "id": 1, + "name": "ManagerPromotionNomination", + "enabledForPageSecurity": true, + "enabledForOrchestrationSecurity": false +} \ No newline at end of file diff --git a/examples/promotion-nomination/model/NominateEmployee.task b/examples/promotion-nomination/model/NominateEmployee.task new file mode 100644 index 0000000..e01d788 --- /dev/null +++ b/examples/promotion-nomination/model/NominateEmployee.task @@ -0,0 +1,10 @@ +{ + "id": 1, + "name": "NominateEmployee", + "label": "Nominate Employee", + "securityDomains": [ + "ManagerPromotionNomination" + ], + "businessObject": "PromotionNominationBO", + "routePath": "/" +} \ No newline at end of file diff --git a/examples/promotion-nomination/model/PromotionNominationBO.businessobject b/examples/promotion-nomination/model/PromotionNominationBO.businessobject new file mode 100644 index 0000000..cc34647 --- /dev/null +++ b/examples/promotion-nomination/model/PromotionNominationBO.businessobject @@ -0,0 +1,149 @@ +{ + "id": 1, + "name": "PromotionNominationBO", + "label": "Promotion Nomination B O", + "defaultSecurityDomains": [ + "ManagerPromotionNomination" + ], + "defaultCollection": { + "name": "promotionNominationBOS", + "label": "Promotion Nomination B O S" + }, + "fields": [ + { + "enableReportingFromTarget": false, + "secureByTarget": true, + "target": "WORKER", + "isPurgeable": false, + "useForDisplay": false, + "type": "SINGLE_INSTANCE", + "name": "nominee", + "id": 1 + }, + { + "enableReportingFromTarget": false, + "secureByTarget": true, + "target": "WORKER", + "isPurgeable": false, + "useForDisplay": false, + "type": "SINGLE_INSTANCE", + "name": "nominator", + "id": 2 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "label": "Nomination Reason", + "type": "TEXT", + "name": "nominationReason", + "id": 3 + }, + { + "precision": "DAY", + "enableIndex": false, + "isPurgeable": false, + "type": "DATE", + "name": "proposedDate", + "id": 4 + }, + { + "enableReportingFromTarget": false, + "secureByTarget": false, + "target": "JOB_PROFILE", + "isPurgeable": false, + "useForDisplay": false, + "type": "SINGLE_INSTANCE", + "name": "proposedJobProfile", + "id": 5 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "type": "TEXT", + "name": "promotionCycle", + "id": 6 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "type": "TEXT", + "name": "timeInJobProfile", + "id": 7 + }, + { + "precision": "DAY", + "enableIndex": false, + "isPurgeable": false, + "type": "DATE", + "name": "hireDate", + "id": 8 + }, + { + "enableReportingFromTarget": false, + "secureByTarget": false, + "target": "JOB_PROFILE", + "isPurgeable": false, + "useForDisplay": false, + "type": "SINGLE_INSTANCE", + "name": "currentJobProfile", + "id": 9 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "type": "TEXT", + "name": "currentJobTitle", + "id": 10 + }, + { + "precision": "DAY", + "enableIndex": false, + "isPurgeable": false, + "type": "DATE", + "name": "lastPromotionDate", + "id": 11 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "type": "TEXT", + "name": "workerConsideration", + "id": 12 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "type": "TEXT", + "name": "businessNeed", + "id": 13 + }, + { + "enableSearch": false, + "enableIndex": false, + "isPurgeable": false, + "useForDisplay": false, + "isReferenceId": false, + "type": "TEXT", + "name": "workerSuitRole", + "id": 14 + } + ] +} \ No newline at end of file diff --git a/examples/promotion-nomination/model/PromotionNominationBP.businessprocess b/examples/promotion-nomination/model/PromotionNominationBP.businessprocess new file mode 100644 index 0000000..39dd80a --- /dev/null +++ b/examples/promotion-nomination/model/PromotionNominationBP.businessprocess @@ -0,0 +1,25 @@ +{ + "id": 1, + "name": "PromotionNominationBP", + "label": "Promotion Nomination BP", + "description": "Business Process Type for PromotionNominationBP", + "useForOrchestrate": false, + "allowsCancel": true, + "approvalStep": { + "pageRoute": "/eventDetails", + "actions": [ + "APPROVE", + "DENY" + ] + }, + "actionSteps": [], + "targetBusinessObject": "PromotionNominationBO", + "securityDomains": [ + "ManagerPromotionNomination" + ], + "details": { + "pageRoute": "/eventDetails/{eventId}" + }, + "allowsManualSendBack": false, + "allowsRescind": true +} \ No newline at end of file diff --git a/examples/promotion-nomination/model/PromotionNominations.report b/examples/promotion-nomination/model/PromotionNominations.report new file mode 100644 index 0000000..972caf2 --- /dev/null +++ b/examples/promotion-nomination/model/PromotionNominations.report @@ -0,0 +1,101 @@ +{ + "id": 1, + "name": "PromotionNominations", + "businessObject": "PromotionNominationBO", + "defaultSecurityDomains": [ + "ManagerPromotionNomination" + ], + "sortConfigs": [], + "columns": [ + { + "id": 1, + "name": "PromotionNominationBO", + "order": "a", + "isSelfReferencing": true + }, + { + "id": 2, + "name": "Nominee", + "order": "b", + "field": "nominee" + }, + { + "id": 3, + "name": "Nominator", + "order": "c", + "field": "nominator" + }, + { + "id": 4, + "name": "Nomination Reason", + "order": "d", + "field": "nominationReason" + }, + { + "id": 5, + "name": "Proposed Date", + "order": "e", + "field": "proposedDate" + }, + { + "id": 6, + "name": "Proposed Job Profile", + "order": "f", + "field": "proposedJobProfile" + }, + { + "id": 7, + "name": "Promotion Cycle", + "order": "g", + "field": "promotionCycle" + }, + { + "id": 8, + "name": "Time In Job Profile", + "order": "h", + "field": "timeInJobProfile" + }, + { + "id": 9, + "name": "Hire Date", + "order": "i", + "field": "hireDate" + }, + { + "id": 10, + "name": "Current Job Profile", + "order": "j", + "field": "currentJobProfile" + }, + { + "id": 11, + "name": "Current Job Title", + "order": "k", + "field": "currentJobTitle" + }, + { + "id": 12, + "name": "Last Promotion Date", + "order": "l", + "field": "lastPromotionDate" + }, + { + "id": 13, + "name": "Worker Consideration", + "order": "m", + "field": "workerConsideration" + }, + { + "id": 15, + "name": "Worker Suit Role", + "order": "o", + "field": "workerSuitRole" + }, + { + "id": 16, + "name": "Business Need", + "order": "p", + "field": "businessNeed" + } + ] +} \ No newline at end of file diff --git a/examples/promotion-nomination/presentation/eventDetails.pmd b/examples/promotion-nomination/presentation/eventDetails.pmd new file mode 100644 index 0000000..3822984 --- /dev/null +++ b/examples/promotion-nomination/presentation/eventDetails.pmd @@ -0,0 +1,165 @@ +{ + "id": "eventDetails", + "securityDomains": [ + "ManagerPromotionNomination" + ], + "endPoints": [ + { + "name": "eventGenericBP", + "baseUrlType": "workday-bp", + "url": "<% `events/{{queryParams.eventId}}` %>", + "authType": "sso", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + } + ] + }, + { + "name": "getPromotionNominationBP", + "baseUrlType": "app", + "url": "<% `promotionNominationBOS/{{eventGenericBP.for.id}}` %>", + "authType": "sso", + "httpMethod": "GET", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + } + ] + } + ], + "presentation": { + "title": { + "type": "title", + "label": "View Promotion Nomination Details", + "id": "titleHeading" + }, + "body": { + "type": "section", + "id": "sectionID1", + "horizontal": false, + "children": [ + { + "enabled": false, + "type": "text", + "label": "Nominee", + "id": "nomineeWidget", + "value": "<% empty getPromotionNominationBP.nominee.descriptor ? 'No Nominee value found' : getPromotionNominationBP.nominee.descriptor %>" + }, + { + "enabled": false, + "type": "text", + "label": "Nominator", + "id": "nominatorWidget", + "value": "<% empty getPromotionNominationBP.nominator.descriptor ? 'No Nominator value found' : getPromotionNominationBP.nominator.descriptor %>" + }, + { + "type": "fieldSet", + "id": "fieldSet1", + "children": [ + { + "type": "text", + "id": "nominationReasonWidget", + "label": "Nomination Reason", + "value": "<% empty getPromotionNominationBP.nominationReason ? 'No Nominator value found' : getPromotionNominationBP.nominationReason %>" + }, + { + "visible": true, + "type": "date", + "id": "proposedDateWidget", + "label": "Proposed Date", + "value": "<% empty getPromotionNominationBP.proposedDate ? null : getPromotionNominationBP.proposedDate %>" + }, + { + "enabled": false, + "type": "text", + "label": "Proposed Job Profile", + "id": "proposedJobProfileWidget", + "value": "<% empty getPromotionNominationBP.proposedJobProfile.descriptor ? 'No Nominator value found' : getPromotionNominationBP.proposedJobProfile.descriptor %>" + }, + { + "type": "text", + "id": "promotionCycleWidget", + "label": "Promotion Cycle", + "value": "<% empty getPromotionNominationBP.promotionCycle ? 'No Nominator value found' : getPromotionNominationBP.promotionCycle %>" + }, + { + "type": "text", + "id": "timeInJobProfileWidget", + "label": "Time in Job Profile", + "value": "<% empty getPromotionNominationBP.timeInJobProfile ? 'No Nominator value found' : getPromotionNominationBP.timeInJobProfile %>" + }, + { + "type": "date", + "id": "hireDateeWidget", + "label": "Hire Date", + "value": "<% empty getPromotionNominationBP.hireDate ? null : getPromotionNominationBP.hireDate %>" + }, + { + "type": "text", + "id": "currentJobProfileWidget", + "label": "Current Job Profile", + "value": "<% empty getPromotionNominationBP.currentJobProfile.descriptor ? 'No Nominator value found' : getPromotionNominationBP.currentJobProfile.descriptor %>" + }, + { + "type": "text", + "id": "currentJobTitleWidget", + "label": "Current Job Title", + "value": "<% empty getPromotionNominationBP.currentJobTitle ? 'No Nominator value found' : getPromotionNominationBP.currentJobTitle %>" + }, + { + "visible": true, + "type": "date", + "id": "lastPromotionDateWidget", + "label": "Last Promotion Date", + "value": "<% empty getPromotionNominationBP.lastPromotionDate ? null : getPromotionNominationBP.lastPromotionDate %>" + }, + { + "type": "date", + "id": "hireDateWidget", + "label": "Employee Hire Date", + "value": "<% empty getPromotionNominationBP.hireDate ? null : getPromotionNominationBP.hireDate %>" + }, + { + "type": "textArea", + "id": "workerConsiderationWidget", + "label": "Why do you consicder the worker?", + "value": "<% empty getPromotionNominationBP.workerConsideration ? 'No Nominator value found' : getPromotionNominationBP.workerConsideration %>" + }, + { + "type": "textArea", + "id": "businessNeedWidget", + "label": "What is the business need?", + "value": "<% empty getPromotionNominationBP.businessNeed ? 'No Nominator value found' : getPromotionNominationBP.businessNeed %>" + }, + { + "type": "textArea", + "id": "workerSuitRoleWidget", + "label": "Does the Worker suit the role?", + "value": "<% empty getPromotionNominationBP.workerSuitRole ? 'No Nominator value found' : getPromotionNominationBP.workerSuitRole %>" + } + ] + } + ] + }, + "footer": { + "type": "footer", + "id": "footerTextID1", + "children": [ + { + "type": "richText", + "id": "footerTextID", + "enabled": false, + "value": "Powered By Workday Extend" + } + ] + }, + "pageType": "VIEW" + } +} diff --git a/examples/promotion-nomination/presentation/managerNomination.pmd b/examples/promotion-nomination/presentation/managerNomination.pmd new file mode 100644 index 0000000..6bc3f98 --- /dev/null +++ b/examples/promotion-nomination/presentation/managerNomination.pmd @@ -0,0 +1,366 @@ +{ + "id": "managerNomination", + "securityDomains": [ + "ManagerPromotionNomination" + ], + "endPoints": [ + { + "name": "me", + "baseUrlType": "workday-staffing", + "authType": "sso", + "url": "/workers/me", + "failOnStatusCodes": [{"code": 400}, {"code": 403}] + }, + { + "name": "getEmployeeList", + "baseUrlType": "workday-wql", + "authType": "sso", + "url": "<% + let query= `/data?query={{string:urlEncode'SELECT worker FROM myDirectReports WHERE workerType in (d588c41a446c11de98360015c5e6daf6)'}}` + return query; + %>", + "failOnStatusCodes": [{"code": 400}, {"code": 403}] + }, + { + "deferred": true, + "name": "getEmployeeData", + "baseUrlType": "workday-wql", + "authType": "sso", + "url": "<% return '/data?query=' + string:urlEncode(`SELECT worker, location, manager_Level01, hireDate, timeInJobProfile, jobProfile, jobTitle, lastPromotionDate FROM myDirectReports WHERE worker in \"{{selectedWorkerIdQuery}}\"`); %>", + "failOnStatusCodes": [{"code": 400}, {"code": 403}] +}, + { + "deferred": true, + "name": "getJobProfiles", + "baseUrlType": "workday-wql", + "authType": "sso", + "url": "<% + let query= '/data?query=' + string:urlEncode(`SELECT jobProfileName, workdayID FROM allActiveJobProfiles (dataSourceFilter = defaultFilter) WHERE jobProfileName startswith \"{{instanceListQuery}}\"`); + // console.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXz', query); + return query.replace('%2B','%20'); + %>", + + "failOnStatusCodes": [{"code": 400}, {"code": 403}] + }, + { + "name": "getJobProfilesNoSearch", + "baseUrlType": "workday-wql", + "authType": "sso", + "url": "<% + const query= `/data?query={{string:urlEncode'SELECT jobProfileName, workdayID FROM allActiveJobProfiles (dataSourceFilter = defaultFilter)'}}`; + // console.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXz', query); + return query.replace('%2B','%20'); + %>", + "failOnStatusCodes": [{"code": 400}, {"code": 403}] + } + ], + "outboundData": { + "outboundEndPoints": [ + { + "name": "storePromotionNominationBO", + "baseUrlType": "app", + "authType": "sso", + "url": "promotionNominationBOS", + "httpMethod": "POST", + + "onSend": "<% + //Outbound endpoint that submits the BO + + let obj = {:}; + + // Required or always-present values, no guards needed + obj.add('nominee', {'id': selectedEmployeeWidget.selectedEntries[0].id}); + obj.add('nominator', {'id': me.id}); + obj.add('nominationReason', promotionReasonWidget.selectedEntries[0].descriptor); + obj.add('proposedDate', date:format(proposedDateWidget.value, 'yyyy-MM-dd')); + obj.add('workerConsideration', promotionConsiderationQ1.value); + obj.add('businessNeed', promotionBusNeedQ2.value); + obj.add('workerSuitRole', roleConsiderationQ3.value); + + // Derived text values, passed through as-is + obj.add('promotionCycle', promotionCycleWidget.value); + obj.add('timeInJobProfile', timeJobProfileWidget.value); + obj.add('currentJobTitle', currentJobTitleWidget.value); + obj.add('lastPromotionDate', date:format(lastPromotionDateWidget.value, 'yyyy-MM-dd')); + + // Only the values that can legitimately be empty keep a guard + obj.add('hireDate', (!empty hireDateWidget.value) ? date:format(hireDateWidget.value, 'yyyy-MM-dd') : null); + obj.add('currentJobProfile', (!empty currentJobProfileWidget.selectedEntries[0].id) ? {'id': currentJobProfileWidget.selectedEntries[0].id} : null); + obj.add('proposedJobProfile', (!empty proposedJobProfileWidget.selectedEntries[0].id) ? {'id': proposedJobProfileWidget.selectedEntries[0].id} : null); + + self.data = obj; + return self.data; + + + %>", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + } + ] + }, + { + "name": "submitPromotion", + "baseUrlType": "app", + "authType": "sso", + "url": "<% 'promotionNominationBPEvents' %>", + + "onSend": "<% + let payload = + { + 'description': 'Approval for Promotion Nomination', + 'businessProcessTarget': {'id': storePromotionNominationBO.id} + }; + //console.info('zzzzzzzzzzz ' + payload.businessProcessTarget); + return payload; + %>", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + } + ] + }, + { + "type": "outboundVariable", + "name": "ExtensionResponse", + "variableScope": "flow", + "values": [ + { + "outboundPath": "PromotionSubmissionResponseValue", + "value": "<% submitPromotion.id %>" + } + ] + } + ] + }, + "presentation": { + "title": { + "type": "title", + "id": "mainTitleLabel", + "label": "Employee Promotion Nomination" + }, + "body": { + "type": "fieldSet", + "id": "fieldSetVertical", + "horizontal": false, + "children": [ + { + "type": "section", + "id": "section1", + "children": [ + { + "type": "readOnlyText", + "id": "welcomeLabel", + "value": "Welcome to the Promotion Nomination App. Please select an employee to begin" + }, + { + "horizontal": true, + "type": "section", + "id": "section2", + "verticalAlignment": "top", + "children": [ + { + "required": true, + "type": "instanceList", + "label": "Select an Employee", + "id": "selectedEmployeeWidget", + "displayKey": "worker.descriptor", + "idKey": "worker.id", + "values": "<% getEmployeeList.data %>", + "onChange": "<% + if (!empty selectedEmployeeWidget.value[0]) //Retrieve selected employee information + { + + var responseEmpData =getEmployeeData.invoke({'selectedWorkerIdQuery': selectedEmployeeWidget.value[0]}); + + + var timeInJobProfileVar =(!empty responseEmpData.data[0].timeInJobProfile) ? responseEmpData.data[0].timeInJobProfile : null; + var currentJobProfileVar = (!empty responseEmpData.data[0].jobProfile.descriptor) ? responseEmpData.data[0].jobProfile.descriptor: null; + var currentJobProfileIDVar = (!empty responseEmpData.data[0].jobProfile.id) ? responseEmpData.data[0].jobProfile.id: null; + var currentJobProfileResponseValue = [{'id': currentJobProfileIDVar, 'descriptor': currentJobProfileVar}]; + var rawHireDateVar = (!empty responseEmpData.data[0].hireDate) ? responseEmpData.data[0].hireDate: null; + var parsedHireDateVar = date:parse(rawHireDateVar, 'yyyy-MM-dd'); + var jobTitleVar = (!empty responseEmpData.data[0].jobTitle) ? responseEmpData.data[0].jobTitle: null; + var rawLastPromotionDateVar = (!empty responseEmpData.data[0].lastPromotionDate) ? responseEmpData.data[0].lastPromotionDate : '2020-01-01'; + var parsedLastPromotionDateVar = date:parse(rawLastPromotionDateVar, 'yyyy-MM-dd'); + + + promotionReasonWidget.visible = true; + proposedDateWidget.visible = true; + proposedDateWidget.visible = true; + proposedJobProfileWidget.visible = true; + promotionCycleWidget.visible = true; + + timeJobProfileWidget.value = timeInJobProfileVar; + timeJobProfileWidget.visible = true; + + currentJobProfileWidget.setValues(currentJobProfileResponseValue); + currentJobProfileWidget.setValue(currentJobProfileResponseValue.map(item => {item.id})); + currentJobProfileWidget.visible = true; + + hireDateWidget.value = parsedHireDateVar; + hireDateWidget.visible = true; + + currentJobTitleWidget.value = jobTitleVar; + currentJobTitleWidget.visible = true; + + lastPromotionDateWidget.value = parsedLastPromotionDateVar; + lastPromotionDateWidget.visible = true; + + promotionConsiderationQ1.visible = true; + promotionBusNeedQ2.visible = true; + roleConsiderationQ3.visible = true; + } + else + { + self.setError('Please select a worker to nominate'); + } %>" + } + ], + "columnWidthRatios": [ + "0.75", + "0.25" + ] + }, + { + "required": true, + "visible": false, + "type": "radioGroup", + "id": "promotionReasonWidget", + "label": "Reason for Promotion", + "instanceList": [ + { + "id": "100A", + "descriptor": "Merit/Performance" + }, + { + "id": "101B", + "descriptor": "Increased Responsibilities" + }, + { + "id": "102C", + "descriptor": "Organizational Restructuring" + } + ] + }, + { + "required": true, + "visible": false, + "label": "Proposed Effective Date", + "type": "date", + "id": "proposedDateWidget" + }, + { + "visible": false, + "label": "Proposed Job Profile", + "type": "instanceList", + "id": "proposedJobProfileWidget", + "values": "<% getJobProfilesNoSearch.data %>", + "displayKey": "jobProfileName", + "idKey": "workdayID" + } + ] + }, + { + "type": "section", + "id": "derivedFieldsSection", + "children": [ + { + "enabled": false, + "visible": false, + "label": "Promotion Cycle", + "type": "text", + "id": "promotionCycleWidget", + "value": "<% return date:year([TODAY_DATE]).toString(); %>" + }, + { + "enabled": false, + "label": "Current Manager", + "visible": false, + "type": "text", + "id": "currentManagerWidget" + }, + { + "enabled": false, + "label": "Time in Job Profile", + "visible": false, + "type": "text", + "id": "timeJobProfileWidget" + }, + { + "enabled": false, + "label": "Hire Date", + "visible": false, + "type": "date", + "id": "hireDateWidget" + }, + { + "enabled": false, + "visible": false, + "label": "Current Job Profile", + "type": "instanceList", + "idKey": "id", + "id": "currentJobProfileWidget", + "values": "<% [] %>" + }, + { + "enabled": false, + "label": "Current Job Title", + "visible": false, + "type": "text", + "id": "currentJobTitleWidget" + }, + { + "enabled": false, + "label": "Date of Last Promotion", + "visible": false, + "type": "date", + "id": "lastPromotionDateWidget" + }, + { + "required": true, + "visible": false, + "type": "textArea", + "id": "promotionConsiderationQ1", + "label": "Why is the worker being considered?" + }, + { + "required": true, + "visible": false, + "type": "textArea", + "id": "promotionBusNeedQ2", + "label": "What is the business need?" + }, + { + "required": true, + "visible": false, + "type": "textArea", + "id": "roleConsiderationQ3", + "label": "How does this worker suit the role?" + } + ] + } + ] + }, + "footer": { + "type": "footer", + "id": "footerTextID", + "children": [ + { + "enabled": false, + "id": "footerrichTextID", + "type": "richText" + } + ] + }, + "pageType": "EDIT" + } + + +} diff --git a/examples/promotion-nomination/presentation/promotionNomination_rvylxm.amd b/examples/promotion-nomination/presentation/promotionNomination_rvylxm.amd new file mode 100644 index 0000000..3dccbb1 --- /dev/null +++ b/examples/promotion-nomination/presentation/promotionNomination_rvylxm.amd @@ -0,0 +1,42 @@ +{ + "appProperties": [], + "tasks": [ + { + "id": "managerNomination", + "routingPattern": "/", + "page": { + "id": "managerNomination" + } + }, + { + "id": "eventDetails", + "routingPattern": "/eventDetails/{eventId}", + "page": { + "id": "eventDetails" + } + } + ], +"applicationId": site.applicationId, + "dataProviders": [ + { + "key": "workday-staffing", + "value": "<% apiGatewayEndpoint + '/staffing/v7/' %>" + }, + { + "key": "workday-wql", + "value": "<% apiGatewayEndpoint + '/wql/v1' %>" + }, + { + "key": "workday-common", + "value": "<% apiGatewayEndpoint + '/common/v1' %>" + }, + { + "key": "workday-bp", + "value": "<% apiGatewayEndpoint + '/businessProcess/v1/' %>" + }, + { + "key": "app", + "value": "<% apiGatewayEndpoint + '/apps/promotionNomination_rvylxm/v1/' %>" + } + ] +} diff --git a/examples/promotion-nomination/presentation/promotionNomination_rvylxm.smd b/examples/promotion-nomination/presentation/promotionNomination_rvylxm.smd new file mode 100644 index 0000000..67a7573 --- /dev/null +++ b/examples/promotion-nomination/presentation/promotionNomination_rvylxm.smd @@ -0,0 +1,19 @@ +{ + "id": "promotionNomination_rvylxm", + "applicationId": "promotionNomination_rvylxm", + "siteId": "promotionNomination_rvylxm", + "languages": [ + { + "code": "en-US", + "description": "English" + } + ], + "siteAuth": { + "authTypes": [ + { + "scheme": "SSO", + "id": "sso" + } + ] + } +}