A new {! Title !} Application has been submitted.
+ {! Sections !} + +diff --git a/.gitignore b/.gitignore index ea48d65..00d593e 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,5 @@ lerna-debug.log* !.vscode/launch.json !.vscode/extensions.json -.env \ No newline at end of file +.env +.djlintrc diff --git a/package.json b/package.json index 96a81e6..78ebe56 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "db:migrate": "npm run typeorm migration:run -- -d src/database/datasource.ts", "db:revert": "npm run typeorm migration:revert -- -d src/database/datasource.ts", "db:drop": "npm run typeorm schema:drop -- -d src/database/datasource.ts", - "db:migrate:prod": "node ./node_modules/typeorm/cli migration:run -d ./dist/database/datasource.js" + "db:migrate:prod": "node ./node_modules/typeorm/cli migration:run -d ./dist/database/datasource.js", + "template:create-admin-email": "pwsh ./scripts/admin_email_create.ps1" }, "dependencies": { "@aws-sdk/client-s3": "^3.954.0", diff --git a/schemas/temporary-teacher-application.json b/schemas/temporary-teacher-application.json new file mode 100644 index 0000000..c706389 --- /dev/null +++ b/schemas/temporary-teacher-application.json @@ -0,0 +1,512 @@ +{ + "id": "temporary-teacher-application", + "name": "Temporary Teacher Application", + "description": "Apply to be a temporary teacher", + "fields": [ + { + "name": "applicant", + "type": "object", + "required": true, + "fields": [ + { + "name": "firstName", + "type": "string", + "label": "First Name", + "required": true, + "validations": { + "min": 2, + "max": 50 + } + }, + { + "name": "middleName", + "type": "string", + "label": "Middle name(s)", + "required": false, + "validations": { + "min": 2, + "max": 50 + } + }, + { + "name": "lastName", + "type": "string", + "label": "Last Name", + "required": true, + "validations": { + "min": 2, + "max": 50 + } + }, + { + "name": "dateOfBirth", + "type": "date", + "label": "Date of Birth", + "required": true, + "validations": { + "regex": "^\\d{4}-\\d{2}-\\d{2}$", + "message": "Date must be in YYYY-MM-DD format" + } + }, + { + "name": "placeOfBirth", + "type": "string", + "label": "Place of birth", + "required": true + }, + { + "name": "nationality", + "type": "string", + "label": "Nationality", + "required": true + }, + { + "name": "sex", + "type": "string", + "label": "Sex", + "required": true, + "validations": { + "regex": "^(male|female)$", + "message": "Must select a valid sex" + } + }, + { + "name": "maritalStatus", + "type": "string", + "label": "Marital status", + "required": true, + "validations": { + "regex": "^(single|married|divorced)$", + "message": "Must select a marital status" + } + }, + { + "name": "nationalIdNumber", + "type": "string", + "label": "National Identification (ID) number", + "required": false, + "validations": { + "regex": "^[0-9]{6}-[0-9]{4}$", + "message": "Invalid ID number." + } + }, + { + "name": "passportNumber", + "type": "string", + "label": "Passport Number (#)", + "required": false + }, + { + "name": "nationalInsuranceNumber", + "type": "string", + "label": "National Insurance number (NIS)", + "required": false + } + ] + }, + { + "name": "barbadosResidencyDuration", + "type": "object", + "required": false, + "fields": [ + { + "name": "residencyDuration", + "label": "How long have you lived in Barbados?", + "type": "number", + "required": true, + "validations": { + "min": 2, + "max": 20 + } + } + ] + }, + { + "name": "contact", + "type": "object", + "required": true, + "fields": [ + { + "name": "addressLine1", + "type": "string", + "label": "Address Line 1", + "required": true + }, + { + "name": "addressLine2", + "type": "string", + "label": "Address Line 2", + "required": false + }, + { + "name": "country", + "type": "select", + "label": "Country", + "required": true, + "validations": { + "regex": "^barbados$" + } + }, + { + "name": "parish", + "type": "string", + "label": "Parish", + "required": true, + "validations": { + "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$", + "message": "Must select a valid parish" + } + }, + { + "name": "postalCode", + "type": "string", + "label": "Postal Code", + "required": false, + "validations": { + "regex": "^BB\\d{5}$", + "message": "Enter a valid postal code (e.g., BB17004)" + } + }, + { + "name": "emailAddress", + "type": "email", + "label": "Email address", + "required": true + }, + { + "name": "telephoneNumber", + "type": "string", + "label": "Telephone Number", + "required": true + } + ] + }, + { + "name": "applicantEducation", + "type": "object", + "required": true, + "fields": [ + { + "name": "nameOfInstitution", + "type": "string", + "label": "Name of Institution", + "required": true + }, + { + "name": "country", + "type": "string", + "label": "Country", + "required": false + }, + { + "name": "startYear", + "label": "Start Year", + "type": "number", + "required": true, + "validations": { + "min": 1930 + } + }, + { + "name": "endYear", + "label": "End Year", + "type": "number", + "required": true, + "validations": { + "min": 1930 + } + }, + { + "name": "anotherEducation", + "label": "Do you want to add another education experience?", + "type": "string", + "required": true, + "validations": { + "regex": "^(yes|no)$", + "message": "Must select an option" + } + } + ] + }, + { + "name": "applicantQualification", + "type": "object", + "required": true, + "fields": [ + { + "name": "subject", + "label": "Subject", + "type": "string", + "required": true + }, + { + "name": "examiningBody", + "label": "Examining Body", + "type": "string", + "required": true + }, + { + "name": "year", + "label": "Year", + "type": "number", + "required": true, + "validations": { + "min": 1930 + } + }, + { + "name": "levelGrade", + "label": "Level / Grade Obtained", + "type": "string", + "required": true + }, + { + "name": "anotherQualification", + "label": "Do you want to add another qualification", + "type": "string", + "required": true, + "validations": { + "regex": "^(yes|no)$" + } + } + ] + }, + { + "name": "applicantWorkExperience", + "required": true, + "type": "object", + "fields": [ + { + "name": "employerName", + "label": "Name of employer or organization", + "type": "string", + "required": true + }, + { + "name": "positionHeld", + "label": "Position held", + "type": "string", + "required": true + }, + { + "name": "fromYear", + "label": "From (year)", + "type": "number", + "required": true, + "validations": { + "min": 1930 + } + }, + { + "name": "toYear", + "label": "To (year)", + "type": "number", + "required": false, + "validations": { + "min": 1930 + } + }, + { + "name": "currentlyWorking", + "label": "I am currently working here", + "type": "boolean", + "required": false + }, + { + "name": "tasks", + "label": "Your main tasks", + "required": true, + "type": "string" + }, + { + "name": "anotherExperience", + "required": true, + "type": "string", + "label": "Do you want to add another experience?", + "validations": { + "regex": "^(yes|no)$", + "message": "Must select an option" + } + } + ] + }, + { + "name": "skillsAndExperience", + "type": "object", + "required": true, + "fields": [ + { + "name": "athleticsGamesCraftSkills", + "label": "Athletics, games, or craft skills", + "type": "string", + "required": false + }, + { + "name": "youthCommunityVolunteerGroups", + "label": "Experience in youth, community, or volunteer groups", + "type": "string", + "required": false + }, + { + "name": "responsibilityPositions", + "label": "Positions of responsibility held", + "type": "string", + "required": false + }, + { + "name": "extraDetails", + "label": "Anything else relevant to your application?", + "type": "string", + "required": false + } + ] + }, + { + "name": "reference", + "required": true, + "type": "object", + "fields": [ + { + "name": "title", + "label": "Title", + "required": true, + "type": "string", + "validations": { + "regex": "^(mr|ms|mrs)$", + "message": "Must select a valid title" + } + }, + { + "name": "firstName", + "type": "string", + "label": "First Name", + "required": true, + "validations": { + "min": 2, + "max": 50 + } + }, + { + "name": "lastName", + "type": "string", + "label": "Last Name", + "required": true, + "validations": { + "min": 2, + "max": 50 + } + }, + { + "name": "addressLine1", + "type": "string", + "label": "Address Line 1", + "required": true + }, + { + "name": "addressLine2", + "type": "string", + "label": "Address Line 2", + "required": false + }, + { + "name": "country", + "type": "string", + "label": "Country", + "required": true, + "validations": { + "regex": "^(barbados)$", + "message": "Must select an option" + } + }, + { + "name": "parish", + "type": "select", + "label": "Parish", + "required": true, + "validations": { + "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$", + "message": "Must select a valid parish" + } + }, + { + "name": "postalCode", + "type": "string", + "label": "Postal code", + "required": false, + "validations": { + "regex": "^BB\\d{5}$", + "message": "Enter a valid postal code (e.g., BB17004)" + } + }, + { + "name": "occupation", + "label": "Occupation", + "required": true, + "type": "string" + }, + { + "name": "emailAddress", + "type": "email", + "label": "Email address", + "required": true + }, + { + "name": "telephoneNumber", + "type": "string", + "label": "Telephone Number", + "required": true + }, + { + "name": "anotherReference", + "required": true, + "type": "string", + "label": "Do you want to add another reference?", + "validations": { + "regex": "^(yes|no)$", + "message": "Must select a valid option" + } + } + ] + }, + { + "name": "documents", + "type": "object", + "required": true, + "fields": [ + { + "name": "certificateDiplomaTranscript", + "label": "Upload your certificates, diplomas, and transcripts", + "required": true, + "type": "string" + }, + { + "name": "testimonials", + "label": "Upload your two testimonials", + "required": true, + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "processors": [ + { + "type": "email", + "config": { + "to": "{{db:temporary-teacher-application:admin_email}}", + "subject": "New Temporary Teacher Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", + "template": "temporary-teacher-application" + } + }, + { + "type": "email", + "config": { + "to": "{{formData.contact.emailAddress}}", + "subject": "Application Received - Government of Barbados", + "template": "temporary-teacher-application-receipt" + } + } + ] +} diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..a2a6d23 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,40 @@ +# Form-Processor-Api Scripts + +This document seeks to outline custom scripts developed to automate certain processes within the `form-processor-api` service. + +This folder provides the following structure: + +- `templates/`: Directory for any template files used by scripts +- `README.md`: This File +- `*.ps1/*.js`: Script files that accomplish some task. + + +## Admin Email Template Creation + +This script is called `admin_email_create.ps1`, and is used to quickly scaffold admin email templates, given a schema from `../schemas/`. +This is a powershell script, and will require Powershell to be installed, along with being able to run the `pwsh` command. + +### Using the Script + +In this project, the script is intended to be used by running: + +`npm run template:create-admin-email` + +However, the prompt for a form id can be skipped by running: + +`npm run template:create-admin-email -- -FormId id-of-form` + +For example: + +`npm run template:create-admin-email -- -FormId jobstart-plus-programme` + +The script can also be run manually from this directory by using `pwsh ./admin_email_create.ps1`, however, no command line configuration is provided to allow for moving to different directories. + +> [!NOTE] +> I also have not added error handling to the script. Will have that as a TODO. + +### Known Issues + +1. Does not yet handle missing files, or any errors resulting from such +1. You will still need to perform manual edits, such as merging First Name, Last Name, and Middle Names into one field, and fixing the casing for `section-title`s. +1. Requires Powershell diff --git a/scripts/admin_email_create.ps1 b/scripts/admin_email_create.ps1 new file mode 100644 index 0000000..f6c9cca --- /dev/null +++ b/scripts/admin_email_create.ps1 @@ -0,0 +1,119 @@ +# Command line args + +param ( + [Parameter(Mandatory=$true)] + [string]$FormId +) + +# Constants + +$schemaLocations = "./schemas" # Start location is where `npm run` is executed +$templateFile = "./scripts/templates/admin_email_template.tmp" +$outputDir = "./src/email/templates/" + +# Functions + +function ConvertFrom-Field-To-HBS +{ + [CmdletBinding()] + param( + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $SectionName, + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [PsCustomObject]$Field + ) + + process + { + $fieldInfo = [PsCustomObject]@{ + name = $Field.name + type = $Field.type + label = $Field.label + required = $Field.required + } + + $fieldValue = "$SectionName.$($fieldInfo.name)" + + $fieldHbs = @" +
A new {! Title !} Application has been submitted.
+ {! Sections !} + +
+ Dear applicant,
+
+ Your application to be a temporary teacher has been submitted.
+
+ Your application reference number is {{ referenceNumber }}.
+
+ We will review your application.
+
+ If we need more information or supporting documents, we will contact you using the details you provided.
+
A new Temporary Teacher Application has been submitted.
+