diff --git a/anet-dictionary.yml b/anet-dictionary.yml index 0328548f0a..abfcbf8748 100644 --- a/anet-dictionary.yml +++ b/anet-dictionary.yml @@ -130,6 +130,33 @@ fields: validations: - type: required params: [You must provide the top 3 issues] + - recurrence: once + relatedObjectType: report + questions: + question1: + type: special_field + widget: likertScale + label: Instant assessment Question 1 + helpText: Please provide assessment for something important + levels: + - color: red + endValue: 2 + label: test + - color: "#FFBF00" + endValue: 8 + label: mid + - color: green + endValue: 10 + label: high + aggregation: + widget: likertScale + question2: + type: number + label: Instant assessment Question 2 + question3: + type: number + label: Instant assessment Question 3 + customFieldRef1: label: Parent task placeholder: Start typing to search for a higher level task @@ -166,54 +193,6 @@ fields: responsiblePositions: label: Responsible positions placeholder: Search for a position... - customFields: - assessments: - type: array_of_objects - label: Assessments definition - helpText: Here you can add as many assessments as needed - addButtonLabel: Add an assessment - objectLabel: Assessment - objectFields: - recurrence: - type: enum - label: Recurrence - helpText: Select a recurrence for this periodic assessment - choices: - once: - label: once - daily: - label: daily - weekly: - label: weekly - biweekly: - label: biweekly - semimonthly: - label: semimonthly - monthly: - label: monthly - quarterly: - label: quarterly - semiannualy: - label: semiannually - annually: - label: annually - relatedObjectType: - type: enum - label: Related object type - helpText: object type context in which the assessment will be made - choices: - report: - label: Report - null: - label: None - questions: - type: json - label: Questions - helpText: JSON that defines the assessment (you need to know what you are doing) - placeholder: Fill in valid JSON - asA: textarea - style: - height: 200px report: canUnpublishReports: true diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 6421169c57..0e03a12f5c 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -600,22 +600,13 @@ export default class Model { } generalAssessmentsConfig() { - // assessments configuration defined for more than one instance - return [] - } - - instanceAssessmentsConfig() { - // assessments configuration defined for one specific instance + // default assessments configuration return [] } getAssessmentsConfig() { - const general = this.generalAssessmentsConfig() - const instance = this.instanceAssessmentsConfig() return Object.assign( - Model.parseAssessmentsConfig(general), - // instance config can override - Model.parseAssessmentsConfig(instance) + Model.parseAssessmentsConfig(this.generalAssessmentsConfig()) ) } diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 2feffab244..a591c9ed96 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -182,11 +182,6 @@ export default class Task extends Model { return this.fieldSettings().assessments || [] } - instanceAssessmentsConfig() { - // The given task instance might have a specific assessments config - return utils.parseJsonSafe(this.customFields).assessments || [] - } - static FILTERED_CLIENT_SIDE_FIELDS = ["assessment_customFieldEnum1"] static filterClientSideFields(obj, ...additionalFields) { diff --git a/client/tests/webdriver/baseSpecs/showReport.spec.js b/client/tests/webdriver/baseSpecs/showReport.spec.js index 125e241849..b6a47ba5d1 100644 --- a/client/tests/webdriver/baseSpecs/showReport.spec.js +++ b/client/tests/webdriver/baseSpecs/showReport.spec.js @@ -11,17 +11,17 @@ describe("Show report page", () => { it("We should see a table of tasks instant assessments related to the current report", () => { ShowReport.tasksEngagementAssessments.waitForDisplayed() // Both 1.2.A as 1.2.B tasks on the page have an svg type of assessment (LikertScale widgets) + // and two other questions const svgAssessments = ShowReport.tasksEngagementAssessments.$$("svg") expect(svgAssessments).to.have.length(2) - // Check on assessments of task 1.2.A const question2Assessments = ShowReport.tasksEngagementAssessments.$$( "[name*=question2]" ) - expect(question2Assessments).to.have.length(1) + expect(question2Assessments).to.have.length(2) const question3Assessments = ShowReport.tasksEngagementAssessments.$$( "[name*=question3]" ) - expect(question3Assessments).to.have.length(1) + expect(question3Assessments).to.have.length(2) }) }) }) diff --git a/client/tests/webdriver/customFieldsSpecs/customFields.spec.js b/client/tests/webdriver/customFieldsSpecs/customFields.spec.js index d9f79d5ff3..1835b61a19 100644 --- a/client/tests/webdriver/customFieldsSpecs/customFields.spec.js +++ b/client/tests/webdriver/customFieldsSpecs/customFields.spec.js @@ -1,7 +1,5 @@ import { expect } from "chai" -import { v4 as uuidv4 } from "uuid" import CreatePerson from "../pages/createNewPerson.page" -import CreateTask from "../pages/createNewTask.page" import CreateReport from "../pages/createReport.page" const INVALID_NUMBER_INPUT = "-10" @@ -14,10 +12,6 @@ const REQUIRED_PERSON_FIELDS = { gender: "MALE" } -const REQUIRED_TASK_FIELDS = { - shortName: "customTask" -} - describe("When working with custom fields for different anet objects", () => { // ------------------------------ REPORT CUSTOM FIELDS ----------------------------------------- describe("For report's custom fields", () => { @@ -262,40 +256,4 @@ describe("When working with custom fields for different anet objects", () => { CreatePerson.waitForAlertSuccessToLoad() }) }) - // ------------------------------ TASK CUSTOM FIELDS ----------------------------------------- - describe("For task's custom fields", () => { - it("Should be able load a new task form and fill normal required fields", () => { - CreateTask.openAsAdmin() - CreateTask.form.waitForExist() - CreateTask.form.waitForDisplayed() - // Fill other required fields so that we can test custom field validation - CreateTask.shortName.setValue( - `${REQUIRED_TASK_FIELDS.shortName} ${uuidv4()}` - ) - }) - - it("Should be able to see assessment fields", () => { - CreateTask.addAssessmentButton.click() - CreateTask.assessmentFields.forEach(field => { - field.waitForExist() - }) - }) - - it("Should warn invalid json for questions", () => { - CreateTask.questionsField.setValue("invalidJsonTest") - // normally there is already a help block, we need the other warning text - CreateTask.questionsFieldWarningText.waitForExist() - }) - - it("Should not warn valid json for questions", () => { - CreateTask.questionsField.setValue("{}") - // only the warning help text should be removed with valid json - CreateTask.questionsFieldWarningText.waitForExist({ reverse: true }) - }) - - it("Should be able to submit valid task", () => { - CreateTask.submitForm() - CreateTask.waitForAlertSuccessToLoad() - }) - }) }) diff --git a/client/tests/webdriver/customFieldsSpecs/myOrg.spec.js b/client/tests/webdriver/customFieldsSpecs/myOrg.spec.js index eaffbba94d..37dada97b6 100644 --- a/client/tests/webdriver/customFieldsSpecs/myOrg.spec.js +++ b/client/tests/webdriver/customFieldsSpecs/myOrg.spec.js @@ -34,9 +34,9 @@ describe("My Organization page", () => { expect(engagementStatusLegend).to.have.length(4) MyOrg.tasks.waitForDisplayed() - // There are 4 tasks on the x-axis + // There are 3 tasks on the x-axis const tasks = MyOrg.tasks.$("svg g").$$(".bars-group") - expect(tasks).to.have.length(4) + expect(tasks).to.have.length(3) let countTasksBars = 0 tasks.forEach(bar => { if (+bar.$("rect").getAttribute("height") > 0) { diff --git a/client/tests/webdriver/customFieldsSpecs/showTask.spec.js b/client/tests/webdriver/customFieldsSpecs/showTask.spec.js index f479cbcc9d..d065b9c2d4 100644 --- a/client/tests/webdriver/customFieldsSpecs/showTask.spec.js +++ b/client/tests/webdriver/customFieldsSpecs/showTask.spec.js @@ -13,18 +13,18 @@ describe("Show task page", () => { describe("When on the show page of a task with assessments", () => { it("We should see a table of assessments related to the current task", () => { ShowTask.assessmentResultsMonthly.waitForDisplayed() - const frenchFlagAssessmentMonthly = ShowTask.assessmentResultsMonthly.$( - "[id*=frenchFlag-assessment]" + const question1AssessmentMonthly = ShowTask.assessmentResultsMonthly.$( + "[id*=question1-assessment]" ) // eslint-disable-next-line no-unused-expressions - expect(frenchFlagAssessmentMonthly.isExisting()).to.be.true + expect(question1AssessmentMonthly.isExisting()).to.be.true ShowTask.assessmentResultsWeekly.waitForDisplayed() - const frenchFlagAssessmentWeekly = ShowTask.assessmentResultsWeekly.$( - "[id*=levels-assessment]" + const question1AssessmentWeekly = ShowTask.assessmentResultsWeekly.$( + "[id*=question1-assessment]" ) // eslint-disable-next-line no-unused-expressions - expect(frenchFlagAssessmentWeekly.isExisting()).to.be.true + expect(question1AssessmentWeekly.isExisting()).to.be.true }) }) }) diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 7a26d7f42b..b71683790c 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -425,16 +425,10 @@ INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, cu (N'1b5eb36b-456c-46b7-ae9e-1c89e9075292', '1.1.B', 'Milestone the Second in EF 1.1', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fdf107e7-a88a-4dc4-b744-748e9aaffabc'), (N'7fdef880-1bf3-4e56-8476-79166324023f', '1.1.C', 'Milestone the Third in EF 1.1', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fdf107e7-a88a-4dc4-b744-748e9aaffabc'), (N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', 'EF 1.2', 'Budgeting in the MoI', 'Sub-EF', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'1145e584-4485-4ce0-89c4-2fa2e1fe846a'), - (N'ac466253-1456-4fc8-9b14-a3643746e5a6', 'EF 1.3', 'Budgeting in the Police?', 'Sub-EF', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'1145e584-4485-4ce0-89c4-2fa2e1fe846a'); - -INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid, customFields) - VALUES - (N'953e0b0b-25e6-44b6-bc77-ef98251d046a', '1.2.A', 'Milestone the First in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessments":[{"questions":{ "question1": { "type": "special_field", "widget": "likertScale", "label": "Test Question 1", "helpText": "Please provide assessment for something important", "levels": [ { "color": "red", "endValue": 2, "label": "test" }, { "color": "#FFBF00", "endValue": 8, "label": "mid" }, { "color": "green", "endValue": 10, "label": "high" } ], "aggregation": { "widget": "likertScale" } }, "question2": { "type": "number", "label": "Test Question 2", "aggregation": { "widget": "numberAggregation" } }, "question3": { "type": "number", "label": "Test Question 3", "aggregation": { "widget": "numberAggregation" } } },"relatedObjectType":"report"}] }'), - (N'9d3da7f4-8266-47af-b518-995f587250c9', '1.2.B', 'Milestone the Second in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessments":[{"questions":{ "frenchFlag": { "type": "special_field", "widget": "likertScale", "label": "French Flag assessment", "helpText": "Please tell us which is the best color in the French flag", "levels": [ { "color": "blue", "endValue": 3.3, "label": "blue" }, { "color": "white", "endValue": 6.6, "label": "white" }, { "color": "red", "endValue": 10, "label": "red" } ] }, "levels": { "type": "enumset", "label": "Achieved levels", "choices": { "lvl1": { "label": "Level 1" }, "lvl2": { "label": "Level 2" }, "lvl3": { "label": "Level 3" } } }, "description": { "type": "special_field", "label": "Detail levels", "widget": "richTextEditor" } },"relatedObjectType":"report"}] }'), - (N'6bbb1be9-4655-48d7-83f2-bc474781544a', '1.2.C', 'Milestone the Third in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessments":[{"questions":{ "question1": { "type": "special_field", "widget": "likertScale", "label": "Monthly assessment Question 1", "helpText": "Please provide assessment for something important", "levels": [ { "color": "red", "endValue": 2, "label": "test" }, { "color": "#FFBF00", "endValue": 8, "label": "mid" }, { "color": "green", "endValue": 10, "label": "high" } ], "aggregation": { "widget": "likertScale" } }, "question2": { "type": "number", "label": "Monthly assessment Question 2", "aggregation": { "widget": "numberAggregation" } }, "question3": { "type": "number", "label": "Monthly assessment Question 3", "aggregation": { "widget": "numberAggregation" } } },"recurrence":"quarterly"},{"questions":{ "question1": { "type": "special_field", "widget": "likertScale", "label": "Weekly assessment Question 1", "helpText": "Please provide assessment for something important", "levels": [ { "color": "red", "endValue": 2, "label": "test" }, { "color": "#FFBF00", "endValue": 8, "label": "mid" }, { "color": "green", "endValue": 10, "label": "high" } ], "aggregation": { "widget": "likertScale" } }, "question2": { "type": "number", "label": "Weekly assessment Question 2", "aggregation": { "widget": "numberAggregation" } }, "question3": { "type": "number", "label": "Weekly assessment Question 3", "aggregation": { "widget": "numberAggregation" } } },"recurrence":"daily"},{"questions":{ "question1": { "type": "special_field", "widget": "likertScale", "label": "Instant assessment Question 1", "helpText": "Please provide assessment for something important", "levels": [ { "color": "red", "endValue": 2, "label": "test" }, { "color": "#FFBF00", "endValue": 8, "label": "mid" }, { "color": "green", "endValue": 10, "label": "high" } ], "aggregation": { "widget": "likertScale" } }, "question2": { "type": "number", "label": "Instant assessment Question 2", "aggregation": { "widget": "numberAggregation" } }, "question3": { "type": "number", "label": "Instant assessment Question 3", "aggregation": { "widget": "numberAggregation" } } },"relatedObjectType":"report"}] }'); - -INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid) - VALUES + (N'ac466253-1456-4fc8-9b14-a3643746e5a6', 'EF 1.3', 'Budgeting in the Police?', 'Sub-EF', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'1145e584-4485-4ce0-89c4-2fa2e1fe846a'), + (N'953e0b0b-25e6-44b6-bc77-ef98251d046a', '1.2.A', 'Milestone the First in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0'), + (N'9d3da7f4-8266-47af-b518-995f587250c9', '1.2.B', 'Milestone the Second in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0'), + (N'6bbb1be9-4655-48d7-83f2-bc474781544a', '1.2.C', 'Milestone the Third in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0'), (N'076793eb-9950-4ea6-bbd5-2d8b8827828c', '1.3.A', 'Getting a budget in place', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'ac466253-1456-4fc8-9b14-a3643746e5a6'), (N'30bc5708-c12d-4a21-916c-5acd7f6f11da', '1.3.B', 'Tracking your expenses', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'ac466253-1456-4fc8-9b14-a3643746e5a6'), (N'df920c99-10ea-44e8-940f-cb1d1cbd22da', '1.3.C', 'Knowing when you run out of money', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'ac466253-1456-4fc8-9b14-a3643746e5a6'), @@ -848,11 +842,9 @@ INSERT INTO reportPeople (personUuid, reportUuid, isPrimary, isAuthor) INSERT INTO reportPeople (personUuid, reportUuid, isPrimary) VALUES ((SELECT uuid FROM people where emailAddress='hunter+shardul@example.com'), @reportUuid, 1); INSERT INTO reportTasks (taskUuid, reportUuid) - VALUES ((SELECT uuid from tasks where shortName = '1.1.B'), @reportUuid); -INSERT INTO reportTasks (taskUuid, reportUuid) - VALUES ((SELECT uuid from tasks where shortName = '1.2.A'), @reportUuid); + VALUES ((SELECT uuid from tasks where shortName = '1.2.A'), @reportUuid); INSERT INTO reportTasks (taskUuid, reportUuid) - VALUES ((SELECT uuid from tasks where shortName = '1.2.B'), @reportUuid); + VALUES ((SELECT uuid from tasks where shortName = '1.2.B'), @reportUuid); SET @reportUuid = lower(newid()); INSERT INTO reports (uuid, createdAt, updatedAt, locationUuid, intent, text, nextSteps, keyOutcomes, state, engagementDate, atmosphere, advisorOrganizationUuid, principalOrganizationUuid) @@ -864,11 +856,9 @@ INSERT INTO reportPeople (personUuid, reportUuid, isPrimary, isAuthor) INSERT INTO reportPeople (personUuid, reportUuid, isPrimary) VALUES ((SELECT uuid FROM people where emailAddress='hunter+shardul@example.com'), @reportUuid, 1); INSERT INTO reportTasks (taskUuid, reportUuid) - VALUES ((SELECT uuid from tasks where shortName = '1.1.B'), @reportUuid); -INSERT INTO reportTasks (taskUuid, reportUuid) - VALUES ((SELECT uuid from tasks where shortName = '1.2.A'), @reportUuid); + VALUES ((SELECT uuid from tasks where shortName = '1.2.A'), @reportUuid); INSERT INTO reportTasks (taskUuid, reportUuid) - VALUES ((SELECT uuid from tasks where shortName = '1.2.B'), @reportUuid); + VALUES ((SELECT uuid from tasks where shortName = '1.2.B'), @reportUuid); -- Release all of the reports right now, so they show up in the rollup. UPDATE reports SET releasedAt = reports.createdAt WHERE state = 2 OR state = 4; @@ -1096,7 +1086,7 @@ INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) FROM reports r WHERE r.text LIKE 'Today%'; --- Add measurement assessments to tasks related to reports +-- Add instant assessments to tasks related to reports SET @noteUuid = lower(newid()); INSERT INTO notes (uuid, authorUuid, type, text, createdAt, updatedAt) VALUES (@noteUuid, @authorUuid, 3, '{"__recurrence":"once","__relatedObjectType":"report","question1":4.462819020045945,"question2":"1","question3":"22"}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); @@ -1111,7 +1101,7 @@ INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) SET @noteUuid = lower(newid()); INSERT INTO notes (uuid, authorUuid, type, text, createdAt, updatedAt) - VALUES (@noteUuid, @authorUuid, 3, '{"__recurrence":"once","__relatedObjectType":"report","description":"
level 1
easily achieved
level 3
easily achieved
","frenchFlag":7.670554793177809,"levels":["lvl1","lvl3"]}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); + VALUES (@noteUuid, @authorUuid, 3, '{"__recurrence":"once","__relatedObjectType":"report","question1":3.141592653589793,"question2":"3","question3":"14"}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) SELECT @noteUuid, 'reports', r.uuid FROM reports r diff --git a/src/main/java/mil/dds/anet/utils/PendingAssessmentsHelper.java b/src/main/java/mil/dds/anet/utils/PendingAssessmentsHelper.java index 9db883ea93..11ed8fdccb 100644 --- a/src/main/java/mil/dds/anet/utils/PendingAssessmentsHelper.java +++ b/src/main/java/mil/dds/anet/utils/PendingAssessmentsHelper.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.ImmutableList; import java.lang.invoke.MethodHandles; import java.time.DayOfWeek; @@ -225,9 +224,7 @@ public Set