Skip to content

Commit

Permalink
#1263 | Configure duration input for 'Recent' type Standard Report Cards
Browse files Browse the repository at this point in the history
  • Loading branch information
1t5j0y committed Jun 28, 2024
1 parent 58a8ca6 commit e22f9ed
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 45 deletions.
26 changes: 26 additions & 0 deletions src/common/components/ValueTextUnitSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import TextField from "@material-ui/core/TextField";
import Select from "@material-ui/core/Select";
import InputLabel from "@material-ui/core/InputLabel";

export const ValueTextUnitSelect = ({ label, value, unit, units, textProps, selectProps, errorMsg, onValueChange, onUnitChange }) => {
return (
<React.Fragment>
<p />
<div style={{ display: "flex", alignItems: "baseline" }}>
{label && <InputLabel>{label}</InputLabel>}
<TextField
autoComplete="off"
value={value}
style={{ marginLeft: "20px", width: "50px" }}
onChange={event => onValueChange(event)}
{...textProps}
/>
<Select value={unit} onChange={event => onUnitChange(event)} style={{ marginLeft: "20px", width: "100px" }} {...selectProps}>
{units}
</Select>
</div>
{errorMsg && errorMsg}
</React.Fragment>
);
};
35 changes: 28 additions & 7 deletions src/common/model/WebReportCard.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ReportCard } from "openchs-models";
import { isEmpty, isNil } from "lodash";
import { isEmpty, isNil, isInteger, toNumber, lowerCase } from "lodash";
import WebStandardReportCardType from "./WebStandardReportCardType";
import WebSubjectType from "./WebSubjectType";
import WebProgram from "./WebProgram";
Expand All @@ -16,7 +16,8 @@ function populateRecordCardFields(
countOfCards,
standardReportCardInputSubjectTypes,
standardReportCardInputPrograms,
standardReportCardInputEncounterTypes
standardReportCardInputEncounterTypes,
standardReportCardInputRecentDuration
) {
reportCard.id = id;
reportCard.iconFileS3Key = iconFileS3Key;
Expand All @@ -28,6 +29,7 @@ function populateRecordCardFields(
reportCard.standardReportCardInputSubjectTypes = standardReportCardInputSubjectTypes;
reportCard.standardReportCardInputPrograms = standardReportCardInputPrograms;
reportCard.standardReportCardInputEncounterTypes = standardReportCardInputEncounterTypes;
reportCard.standardReportCardInputRecentDuration = standardReportCardInputRecentDuration;
}

class WebReportCard extends ReportCard {
Expand Down Expand Up @@ -60,7 +62,10 @@ class WebReportCard extends ReportCard {

static createNewReportCard() {
const webReportCard = new WebReportCard();
populateRecordCardFields(webReportCard, "", "", "", [], false, null, WebReportCard.MinimumNumberOfNestedCards, [], [], []);
populateRecordCardFields(webReportCard, "", "", "", [], false, null, WebReportCard.MinimumNumberOfNestedCards, [], [], [], {
value: "1",
unit: "days"
});
webReportCard.colour = "#ff0000";
return webReportCard;
}
Expand All @@ -78,7 +83,8 @@ class WebReportCard extends ReportCard {
other.countOfCards,
[...other.standardReportCardInputSubjectTypes],
[...other.standardReportCardInputPrograms],
[...other.standardReportCardInputEncounterTypes]
[...other.standardReportCardInputEncounterTypes],
other.standardReportCardInputRecentDuration
);
webReportCard.standardReportCardType = other.standardReportCardType;
webReportCard.colour = other.colour;
Expand All @@ -98,7 +104,8 @@ class WebReportCard extends ReportCard {
resource.count,
WebSubjectType.fromResources(resource.standardReportCardInputSubjectTypes),
WebProgram.fromResources(resource.standardReportCardInputPrograms),
WebEncounterType.fromResources(resource.standardReportCardInputEncounterTypes)
WebEncounterType.fromResources(resource.standardReportCardInputEncounterTypes),
resource.standardReportCardInputRecentDuration
);
webReportCard.colour = resource.color;
if (!isNil(resource.standardReportCardType))
Expand All @@ -110,7 +117,7 @@ class WebReportCard extends ReportCard {
return isNil(this.id);
}

validate(isStandardReportCard) {
validateCard(isStandardReportCard) {
const errors = [];
if (isEmpty(this.name)) {
errors.push({ key: "EMPTY_NAME", message: "Name cannot be empty" });
Expand Down Expand Up @@ -146,6 +153,19 @@ class WebReportCard extends ReportCard {
message: "Nested Card count cannot be less than 1 or greater than 9"
});
}
if (isStandardReportCard && this.isRecentType()) {
const recentDurationValueAsNumber = toNumber(this.standardReportCardInputRecentDuration.value);
if (
!isInteger(recentDurationValueAsNumber) ||
!(recentDurationValueAsNumber > 0) ||
lowerCase(this.standardReportCardInputRecentDuration.value).indexOf("e") > -1
) {
errors.push({
key: "INVALID_DURATION",
message: "Recent duration is mandatory and should be a positive number"
});
}
}
return errors;
}

Expand All @@ -162,7 +182,8 @@ class WebReportCard extends ReportCard {
iconFileS3Key: this.iconFileS3Key,
standardReportCardInputSubjectTypes: this.standardReportCardInputSubjectTypes.map(x => x.uuid),
standardReportCardInputPrograms: this.standardReportCardInputPrograms.map(x => x.uuid),
standardReportCardInputEncounterTypes: this.standardReportCardInputEncounterTypes.map(x => x.uuid)
standardReportCardInputEncounterTypes: this.standardReportCardInputEncounterTypes.map(x => x.uuid),
standardReportCardInputRecentDuration: this.standardReportCardInputRecentDuration
};
}
}
Expand Down
66 changes: 50 additions & 16 deletions src/formDesigner/components/ReportCard/CreateEditReportCard.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { ReportCardReducer, ReportCardReducerKeys } from "./ReportCardReducer";
import http from "../../../common/utils/httpClient";
import { get, isNil } from "lodash";
import { get, isNil, sortBy } from "lodash";
import Box from "@material-ui/core/Box";
import { DocumentationContainer } from "../../../common/components/DocumentationContainer";
import Grid from "@material-ui/core/Grid";
Expand All @@ -25,6 +25,8 @@ import { PopoverColorPicker } from "../../../common/components/PopoverColorPicke
import WebReportCard from "../../../common/model/WebReportCard";
import DashboardService from "../../../common/service/DashboardService";
import FormMetaDataSelect from "../../../common/components/FormMetaDataSelect";
import { StandardReportCardType } from "openchs-models";
import { ValueTextUnitSelect } from "../../../common/components/ValueTextUnitSelect";

export const CreateEditReportCard = ({ edit, ...props }) => {
const [card, dispatch] = React.useReducer(ReportCardReducer, WebReportCard.createNewReportCard());
Expand Down Expand Up @@ -62,8 +64,15 @@ export const CreateEditReportCard = ({ edit, ...props }) => {
}
}, [isStandardReportCard]);

React.useEffect(() => {
//to handle existing recent type cards without duration configured
if (card.isRecentType() && isNil(card.standardReportCardInputRecentDuration)) {
dispatch({ type: ReportCardReducerKeys.duration, payload: { value: "1", unit: "days" } });
}
}, [card]);

const validateRequest = () => {
const errors = card.validate(isStandardReportCard);
const errors = card.validateCard(isStandardReportCard);
console.log(errors);
setError(errors);
return errors.length === 0;
Expand Down Expand Up @@ -144,18 +153,14 @@ export const CreateEditReportCard = ({ edit, ...props }) => {
toolTipKey={"APP_DESIGNER_CARD_DESCRIPTION"}
/>
<p />
{!isStandardReportCard && (
<React.Fragment>
<AvniFormLabel label={"Colour Picker"} toolTipKey={"APP_DESIGNER_CARD_COLOR"} />
<PopoverColorPicker
id="colour"
label="Colour"
color={card.color}
onChange={color => dispatch({ type: ReportCardReducerKeys.color, payload: color })}
/>
{getErrorByKey(error, "EMPTY_COLOR")}
</React.Fragment>
)}
<AvniFormLabel label={"Colour Picker"} toolTipKey={"APP_DESIGNER_CARD_COLOR"} />
<PopoverColorPicker
id="colour"
label="Colour"
color={card.colour}
onChange={color => dispatch({ type: ReportCardReducerKeys.color, payload: color })}
/>
{getErrorByKey(error, "EMPTY_COLOR")}
<p />
<AvniImageUpload
onSelect={setFile}
Expand Down Expand Up @@ -219,17 +224,46 @@ export const CreateEditReportCard = ({ edit, ...props }) => {
type: ReportCardReducerKeys.standardReportCardType,
payload: standardReportCardTypes.find(x => event.target.value === x.name)
});
dispatch({
type: ReportCardReducerKeys.duration,
payload: card.isRecentType() ? { value: "1", unit: "days" } : null
});
}}
style={{ width: "200px" }}
style={{ width: "250px" }}
required
options={standardReportCardTypes.map((type, index) => (
options={sortBy(standardReportCardTypes, ["name"]).map((type, index) => (
<MenuItem value={type.name} key={index}>
{type.name}
</MenuItem>
))}
toolTipKey={"APP_DESIGNER_CARD_IS_STANDARD_TYPE"}
/>
)}
{isStandardReportCard && card.isRecentType() && (
<ValueTextUnitSelect
label={`${card.standardReportCardType.name} in the last*`}
value={get(card, "standardReportCardInputRecentDuration.value")}
unit={get(card, "standardReportCardInputRecentDuration.unit")}
units={StandardReportCardType.recentCardDurationUnits.map((unit, index) => (
<MenuItem value={unit} key={index}>
{unit}
</MenuItem>
))}
onValueChange={event =>
dispatch({
type: ReportCardReducerKeys.duration,
payload: { value: event.target.value, unit: card.standardReportCardInputRecentDuration.unit }
})
}
onUnitChange={event =>
dispatch({
type: ReportCardReducerKeys.duration,
payload: { value: card.standardReportCardInputRecentDuration.value, unit: event.target.value }
})
}
errorMsg={getErrorByKey(error, "INVALID_DURATION")}
/>
)}
{card.isSubjectTypeFilterSupported() && (
<>
<p />
Expand Down
13 changes: 12 additions & 1 deletion src/formDesigner/components/ReportCard/ReportCardReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const ReportCardReducerKeys = {
nested: "nested",
standardReportCardType: "standardReportCardType",
setData: "setData",
cardFormMetaData: "cardFormMetaData"
cardFormMetaData: "cardFormMetaData",
duration: "duration"
};

export const ReportCardReducer = (reportCard, action) => {
Expand Down Expand Up @@ -40,6 +41,16 @@ export const ReportCardReducer = (reportCard, action) => {
reportCard.standardReportCardInputPrograms = programs;
reportCard.standardReportCardInputEncounterTypes = encounterTypes;
break;
case ReportCardReducerKeys.duration:
if (action.payload) {
const { value, unit } = action.payload;
reportCard.standardReportCardInputRecentDuration = {};
reportCard.standardReportCardInputRecentDuration.value = value;
reportCard.standardReportCardInputRecentDuration.unit = unit;
} else {
reportCard.standardReportCardInputRecentDuration = null;
}
break;
default:
break;
}
Expand Down
7 changes: 7 additions & 0 deletions src/formDesigner/components/ReportCard/ReportCardShow.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ function RenderCard({ reportCard }) {
{reportCard.isStandardReportType() && (
<ShowLabelValue label={"Standard Report Card Type"} value={reportCard.standardReportCardType.name} />
)}
<p />
{reportCard.isStandardReportType() && reportCard.isRecentType() && !_.isNil(reportCard.standardReportCardInputRecentDuration) && (
<ShowLabelValue
label={`${reportCard.standardReportCardType.name} in the last`}
value={`${reportCard.standardReportCardInputRecentDuration.value} ${reportCard.standardReportCardInputRecentDuration.unit}`}
/>
)}
{reportCard.isSubjectTypeFilterSupported() && (
<>
<br />
Expand Down
55 changes: 34 additions & 21 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7468,9 +7468,9 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000918, caniuse-lite@^1.0.30000929, can
integrity sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg==

caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001629:
version "1.0.30001636"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz#b15f52d2bdb95fad32c2f53c0b68032b85188a78"
integrity sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==
version "1.0.30001638"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001638.tgz#598e1f0c2ac36f37ebc3f5b8887a32ca558e5d56"
integrity sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==

capture-exit@^1.2.0:
version "1.2.0"
Expand Down Expand Up @@ -9439,9 +9439,9 @@ electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.621:
integrity sha512-mPEG/52142po0XK1jQkZtbMmp38MZtQ3JDFItYxV65WXyhxDYEQ54tP4rb93m0RbMlZqQ+4zBw2N7UumSgGfbA==

electron-to-chromium@^1.3.47, electron-to-chromium@^1.4.796:
version "1.4.806"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.806.tgz#2cb046631cbabceb26fc72be68d273fa183e36bc"
integrity sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg==
version "1.4.814"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.814.tgz#176535a0b899c9c473464502ab77576aa8bb1cbe"
integrity sha512-GVulpHjFu1Y9ZvikvbArHmAhZXtm3wHlpjTMcXNGKl4IQ4jMQjlnz8yMQYYqdLHKi/jEL2+CBC2akWVCoIGUdw==

elegant-spinner@^1.0.1:
version "1.0.1"
Expand Down Expand Up @@ -11665,7 +11665,7 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3"
minimalistic-assert "^1.0.1"

hasown@^2.0.0:
hasown@^2.0.0, hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
Expand Down Expand Up @@ -12594,11 +12594,11 @@ is-color-stop@^1.0.0:
rgba-regex "^1.0.0"

is-core-module@^2.13.0:
version "2.13.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
version "2.14.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1"
integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==
dependencies:
hasown "^2.0.0"
hasown "^2.0.2"

is-data-descriptor@^0.1.4:
version "0.1.4"
Expand Down Expand Up @@ -14468,9 +14468,9 @@ lowlight@^1.14.0:
highlight.js "~10.4.0"

lru-cache@^10.2.0:
version "10.2.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
version "10.3.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.3.0.tgz#4a4aaf10c84658ab70f79a85a9a3f1e1fb11196b"
integrity sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==

lru-cache@^4.0.1, lru-cache@^4.1.1:
version "4.1.5"
Expand Down Expand Up @@ -15476,9 +15476,9 @@ object-hash@^1.1.4:
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==

object-inspect@^1.13.1:
version "1.13.1"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
version "1.13.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==

object-inspect@^1.7.0, object-inspect@^1.8.0:
version "1.8.0"
Expand Down Expand Up @@ -15686,10 +15686,10 @@ open@^7.1.0:
grunt "^1.0.3"
webpack "^4.13.0"

[email protected].79:
version "1.31.79"
resolved "https://registry.yarnpkg.com/openchs-models/-/openchs-models-1.31.79.tgz#58706743f73bdadef907eace9c1249a65bdb96a9"
integrity sha512-SMhnZbFqDsmXILMIGTM3dKaH8EU2+FljqLBa1IvfrfpdwVKdqksBTEhvFEJPlDHLlX06/eeeEvmxaNnmCmjCqg==
[email protected].86:
version "1.31.86"
resolved "https://registry.yarnpkg.com/openchs-models/-/openchs-models-1.31.86.tgz#67c1fdfb4b6631b6f99b70559c010f435bec6068"
integrity sha512-Ye2f8tuTJO21wKfHsM8ZAnGbMUAceoffb0qnbN/zm6v8jLeznTkI71yFz6FbiV/dnG4p1PLWYrvYoXvKA4sQfg==
dependencies:
uuid "^9.0.1"

Expand Down Expand Up @@ -19186,6 +19186,19 @@ rsvp@^4.8.4:
"rules-config@github:avniproject/rules-config#fe552da405368bfd138e2f38e605c1d307e3ebe4":
version "0.0.1"
resolved "https://codeload.github.com/avniproject/rules-config/tar.gz/fe552da405368bfd138e2f38e605c1d307e3ebe4"
dependencies:
"@quasar/babel-preset-app" "^2.0.1"
babel-preset-env "^1.7.0"
babel-register "^6.26.0"
chai "^4.1.2"
lodash "^4.17.11"
moment "^2.29.4"
superagent "^3.8.3"
test "^0.6.0"
uglifyjs-webpack-plugin "^1.2.5"
webpack "^3.12.0"
webpack-cli "^3.0.3"
webpack-node-externals "1.6.0"

run-async@^2.2.0, run-async@^2.4.0:
version "2.4.1"
Expand Down

0 comments on commit e22f9ed

Please sign in to comment.