From 06cfc13428388480b474e1cfa9de239ac671105c Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Tue, 4 Feb 2025 08:34:43 -0600 Subject: [PATCH 1/4] Handle a null external score properly, with respect to averages. --- web-ui/src/pages/PulseReportPage.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web-ui/src/pages/PulseReportPage.jsx b/web-ui/src/pages/PulseReportPage.jsx index 83d4ef0b7..1e2d60369 100644 --- a/web-ui/src/pages/PulseReportPage.jsx +++ b/web-ui/src/pages/PulseReportPage.jsx @@ -228,7 +228,9 @@ const PulseReportPage = () => { internalScores: [] }; } - averages.externalScores.push(externalScore); + if (externalScore != null) { + averages.externalScores.push(externalScore); + } averages.internalScores.push(internalScore); } } From 3973e9b7a0b6e2df4ef4e71066e0b48ad0e2cfb9 Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Tue, 4 Feb 2025 08:35:51 -0600 Subject: [PATCH 2/4] Handle block_action submissions which happen whenever a radio button value is changed. Only create the pulse response when processing a view_submission. --- .../services/pulseresponse/PulseResponse.java | 6 +- .../PulseResponseController.java | 14 +-- .../SlackPulseResponseConverter.java | 87 ++++++++++--------- 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java index e77145fd4..32b013aa1 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java @@ -77,7 +77,7 @@ public class PulseResponse { protected PulseResponse() { } - public PulseResponse(UUID id, Integer internalScore, @Nullable Integer externalScore, LocalDate submissionDate, @Nullable UUID teamMemberId, String internalFeelings, String externalFeelings) { + public PulseResponse(UUID id, Integer internalScore, @Nullable Integer externalScore, LocalDate submissionDate, @Nullable UUID teamMemberId, @Nullable String internalFeelings, @Nullable String externalFeelings) { this.id = id; this.internalScore = internalScore; this.externalScore = externalScore; @@ -90,7 +90,7 @@ public PulseResponse(UUID id, Integer internalScore, @Nullable Integer externalS public PulseResponse(Integer internalScore, Integer externalScore, LocalDate submissionDate, UUID teamMemberId, String internalFeelings, String externalFeelings) { this(null, internalScore, externalScore, submissionDate, teamMemberId, internalFeelings, externalFeelings); } - +/* public UUID getId() { return this.id; } @@ -146,7 +146,7 @@ public String getExternalFeelings() { public void setExternalFeelings(String externalFeelings) { this.externalFeelings = externalFeelings; } - +*/ @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponseController.java b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponseController.java index 20c14c80d..9c42795be 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponseController.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponseController.java @@ -148,7 +148,7 @@ public HttpResponse commandPulseResponse( @Secured(SecurityRule.IS_ANONYMOUS) @Post(uri = "/external", consumes = MediaType.APPLICATION_FORM_URLENCODED) - public HttpResponse externalPulseResponse( + public HttpResponse externalPulseResponse( @Header("X-Slack-Signature") String signature, @Header("X-Slack-Request-Timestamp") String timestamp, @Body String requestBody, @@ -174,6 +174,12 @@ public HttpResponse externalPulseResponse( PulseResponseCreateDTO pulseResponseDTO = slackPulseResponseConverter.get(memberProfileServices, (String)body.get(key)); + // If we receive a null DTO, that means that this is not the + // actual submission of the form. We can just return 200 so + // that Slack knows to continue without error. + if (pulseResponseDTO == null) { + return HttpResponse.ok(); + } // DEBUG Only LOG.info("Request has been converted"); @@ -195,11 +201,7 @@ public HttpResponse externalPulseResponse( return HttpResponse.status(HttpStatus.CONFLICT, "Already submitted today"); } else { - return HttpResponse.created(pulseResponse) - .headers(headers -> headers.location( - URI.create(String.format("%s/%s", - request.getPath(), - pulseResponse.getId())))); + return HttpResponse.ok(); } } else { return HttpResponse.unprocessableEntity(); diff --git a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/SlackPulseResponseConverter.java b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/SlackPulseResponseConverter.java index f2fe86cb6..be9ba90ff 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/SlackPulseResponseConverter.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/SlackPulseResponseConverter.java @@ -35,42 +35,51 @@ public PulseResponseCreateDTO get( final ObjectMapper mapper = new ObjectMapper(); final Map map = mapper.readValue(body, new TypeReference<>() {}); - final Map view = - (Map)map.get("view"); - final Map state = - (Map)view.get("state"); - final Map values = - (Map)state.get("values"); - - dumpMap(values, ""); - - // Create the pulse DTO and fill in the values. - PulseResponseCreateDTO response = new PulseResponseCreateDTO(); - response.setTeamMemberId(lookupUser(memberProfileServices, map)); - response.setSubmissionDate(LocalDate.now()); - - // Internal Score - Map internalBlock = - (Map)values.get("internalNumber"); - response.setInternalScore(Integer.parseInt(getMappedValue( - internalBlock, "internalScore", "selected_option", true))); - // Internal Feelings - response.setInternalFeelings(getMappedValue( - values, "internaltext", "internalFeelings", false)); - - // External Score - Map externalBlock = - (Map)values.get("externalNumber"); - String score = getMappedValue(externalBlock, "externalScore", - "selected_option", false); - if (score != null && !score.isEmpty()) { - response.setExternalScore(Integer.parseInt(score)); + final String type = (String)map.get("type"); + + if (type.equals("view_submission")) { + final Map view = + (Map)map.get("view"); + final Map state = + (Map)view.get("state"); + final Map values = + (Map)state.get("values"); + + dumpMap(values, ""); + + // Create the pulse DTO and fill in the values. + PulseResponseCreateDTO response = new PulseResponseCreateDTO(); + response.setTeamMemberId(lookupUser(memberProfileServices, map)); + response.setSubmissionDate(LocalDate.now()); + + // Internal Score + Map internalBlock = + (Map)values.get("internalNumber"); + response.setInternalScore(Integer.parseInt(getMappedValue( + internalBlock, "internalScore", "selected_option", true))); + // Internal Feelings + response.setInternalFeelings(getMappedValue( + values, "internaltext", "internalFeelings", false)); + + // External Score + Map externalBlock = + (Map)values.get("externalNumber"); + String score = getMappedValue(externalBlock, "externalScore", + "selected_option", false); + if (score != null && !score.isEmpty()) { + response.setExternalScore(Integer.parseInt(score)); + } + // External Feelings + response.setExternalFeelings(getMappedValue( + values, "externalText", "externalFeelings", false)); + + return response; + } else { + // If it's not a view submission, we need to return null so + // the the caller knows that this is not the full pulse + // response. + return null; } - // External Feelings - response.setExternalFeelings(getMappedValue( - values, "externalText", "externalFeelings", false)); - - return response; } catch(JsonProcessingException ex) { LOG.error(ex.getMessage()); throw new BadArgException(ex.getMessage()); @@ -83,12 +92,12 @@ public PulseResponseCreateDTO get( private String getMappedValue(Map map, String key1, String key2, boolean required) { final String valueKey = "value"; - if (map.containsKey(key1)) { + if (map != null && map.containsKey(key1)) { Map firstMap = (Map)map.get(key1); - if (firstMap.containsKey(key2)) { + if (firstMap != null && firstMap.containsKey(key2)) { final Map secondMap = (Map)firstMap.get(key2); - if (secondMap.containsKey(valueKey)) { + if (secondMap != null && secondMap.containsKey(valueKey)) { return (String)secondMap.get(valueKey); } } @@ -100,7 +109,7 @@ private String getMappedValue(Map map, String key1, String.format("Expected %s.%s.%s was not found", key1, key2, valueKey)); } else { - return ""; + return null; } } From f112043e34a223b728bb0f1d317b7feab5c262a7 Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Tue, 4 Feb 2025 08:37:51 -0600 Subject: [PATCH 3/4] Let lombok handle the getters and setters. --- .../services/pulseresponse/PulseResponse.java | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java index 32b013aa1..fe2065388 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/pulseresponse/PulseResponse.java @@ -90,63 +90,7 @@ public PulseResponse(UUID id, Integer internalScore, @Nullable Integer externalS public PulseResponse(Integer internalScore, Integer externalScore, LocalDate submissionDate, UUID teamMemberId, String internalFeelings, String externalFeelings) { this(null, internalScore, externalScore, submissionDate, teamMemberId, internalFeelings, externalFeelings); } -/* - public UUID getId() { - return this.id; - } - - public void setId(UUID id) { - this.id = id; - } - - public Integer getInternalScore() { - return internalScore; - } - - public void setInternalScore(Integer internalScore) { - this.internalScore = internalScore; - } - public Integer getExternalScore() { - return externalScore; - } - - public void setExternalScore(Integer externalScore) { - this.externalScore = externalScore; - } - - public LocalDate getSubmissionDate() { - return submissionDate; - } - - public void setSubmissionDate(LocalDate submissionDate) { - this.submissionDate = submissionDate; - } - - public UUID getTeamMemberId() { - return this.teamMemberId; - } - - public void setTeamMemberId(UUID teamMemberId) { - this.teamMemberId = teamMemberId; - } - - public String getInternalFeelings() { - return internalFeelings; - } - - public void setInternalFeelings(String internalFeelings) { - this.internalFeelings = internalFeelings; - } - - public String getExternalFeelings() { - return externalFeelings; - } - - public void setExternalFeelings(String externalFeelings) { - this.externalFeelings = externalFeelings; - } -*/ @Override public boolean equals(Object o) { if (this == o) return true; From 22b6925b932c107fdc4ae9329fee7782d411f73b Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Tue, 4 Feb 2025 08:44:52 -0600 Subject: [PATCH 4/4] Touch to reset the database. --- server/src/main/resources/db/dev/R__Load_testing_data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/resources/db/dev/R__Load_testing_data.sql b/server/src/main/resources/db/dev/R__Load_testing_data.sql index 95722469b..198035b47 100644 --- a/server/src/main/resources/db/dev/R__Load_testing_data.sql +++ b/server/src/main/resources/db/dev/R__Load_testing_data.sql @@ -60,7 +60,7 @@ VALUES INSERT INTO member_profile -- Unreal Ulysses (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Unreal','${aeskey}'), PGP_SYM_ENCRYPT('Ulysses','${aeskey}'), PGP_SYM_ENCRYPT('Test Engineer 2','${aeskey}'), '1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('testing2@objectcomputing.com','${aeskey}'), '010101012', '2021-05-22', PGP_SYM_ENCRYPT('Test user 2','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', '1950-01-01', '2021-05-22'); +('dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Unreal','${aeskey}'), PGP_SYM_ENCRYPT('Ulysses','${aeskey}'), PGP_SYM_ENCRYPT('Test Engineer 2','${aeskey}'), '1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('testing2@objectcomputing.com','${aeskey}'), '010101012', '2021-05-22', PGP_SYM_ENCRYPT('Test user 2','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', '1950-02-01', '2021-05-22'); INSERT INTO member_profile -- Kazuhira Miller (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen)