Skip to content

Commit

Permalink
Merge pull request #34 from Michaelndula/main
Browse files Browse the repository at this point in the history
Remove unwanted errors from the app
  • Loading branch information
PiusKariuki authored Aug 7, 2024
2 parents a356478 + abcf910 commit cdcf2e8
Show file tree
Hide file tree
Showing 36 changed files with 31,898 additions and 1,657 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

550 changes: 550 additions & 0 deletions packages/esm-procedure-app/.yarn/plugins/@yarnpkg/plugin-version.cjs

Large diffs are not rendered by default.

874 changes: 874 additions & 0 deletions packages/esm-procedure-app/.yarn/releases/yarn-3.6.1.cjs

Large diffs are not rendered by default.

Empty file.
55 changes: 55 additions & 0 deletions packages/esm-procedure-app/__mocks__/react-i18next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** At present, this entire mock is boilerplate. */
const React = require("react");
const reactI18next = require("react-i18next");

const hasChildren = (node) =>
node && (node.children || (node.props && node.props.children));

const getChildren = (node) =>
node && node.children ? node.children : node.props && node.props.children;

const renderNodes = (reactNodes) => {
if (typeof reactNodes === "string") {
return reactNodes;
}

return Object.keys(reactNodes).map((key, i) => {
const child = reactNodes[key];
const isElement = React.isValidElement(child);

if (typeof child === "string") {
return child;
}
if (hasChildren(child)) {
const inner = renderNodes(getChildren(child));
return React.cloneElement(child, { ...child.props, key: i }, inner);
}
if (typeof child === "object" && !isElement) {
return Object.keys(child).reduce(
(str, childKey) => `${str}${child[childKey]}`,
""
);
}

return child;
});
};

const useMock = [(k) => k, {}];
useMock.t = (k, o) => (o && o.defaultValue) || (typeof o === "string" ? o : k);
useMock.i18n = {};

module.exports = {
// this mock makes sure any components using the translate HoC receive the t function as a prop
Trans: ({ children }) => renderNodes(children),
Translation: ({ children }) => children((k) => k, { i18n: {} }),
useTranslation: () => useMock,

// mock if needed
I18nextProvider: reactI18next.I18nextProvider,
initReactI18next: reactI18next.initReactI18next,
setDefaults: reactI18next.setDefaults,
getDefaults: reactI18next.getDefaults,
setI18n: reactI18next.setI18n,
getI18n: reactI18next.getI18n,
};
19 changes: 10 additions & 9 deletions packages/esm-procedure-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sjthc/esm-procedure-app",
"version": "1.0.0",
"version": "1.0.2",
"license": "MPL-2.0",
"description": "An OpenMRS seed application for building microfrontends",
"browser": "dist/sjthc-esm-procedure-app.js",
Expand All @@ -9,15 +9,16 @@
"scripts": {
"start": "openmrs develop",
"serve": "webpack serve --mode=development",
"debug": "npm run serve",
"build": "webpack --mode production",
"analyze": "webpack --mode=production --env.analyze=true",
"lint": "cross-env eslint src --ext ts,tsx",
"test": "cross-env TZ=UTC jest --config jest.config.js --verbose false --passWithNoTests --color",
"test:watch": "cross-env TZ=UTC jest --watch --config jest.config.js --color",
"coverage": "yarn test --coverage",
"analyze": "webpack --mode=production --env analyze=true",
"lint": "TIMING=1 eslint src --ext js,jsx,ts,tsx",
"prettier": "prettier --write \"src/**/*.{ts,tsx}\" --list-different",
"typescript": "tsc",
"extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.extension.tsx' 'src/**/*modal.tsx' 'src/**/*.workspace.tsx' 'src/index.ts' --config ../../tools/i18next-parser.config.js"
"test": "jest --config jest.config.js --passWithNoTests",
"verify": "turbo lint typescript coverage",
"coverage": "yarn test --coverage",
"extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.extension.tsx' 'src/**/*.workspace.tsx' 'src/index.ts' --config ./i18next-parser.config.js",
"test-e2e": "playwright test"
},
"husky": {
"hooks": {
Expand Down Expand Up @@ -112,5 +113,5 @@
"webpack-cli": "^5.1.4"
},
"packageManager": "[email protected]",
"gitHead": "f1661da45d2c1cd9be4305a0e015a6f66685af85"
"gitHead": "50c3c5d51d59bbab87b49e830a948aab4a152e44"
}
253 changes: 253 additions & 0 deletions packages/esm-procedure-app/src/common/groupedOrdersTable.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import React, { useMemo, useState } from "react";
import styles from "./groupedOrdersTable.scss";
import { useTranslation } from "react-i18next";
import { formatDate, parseDate, usePagination } from "@openmrs/esm-framework";
import { useSearchGroupedResults } from "../hooks/useSearchGroupedResults";
import {
Table,
TableHead,
TableRow,
TableHeader,
TableBody,
TableExpandRow,
TableExpandedRow,
TableExpandHeader,
TableCell,
DataTable,
Pagination,
TableContainer,
TableToolbar,
TableToolbarContent,
TableToolbarSearch,
Layer,
Dropdown,
DatePicker,
DatePickerInput,
} from "@carbon/react";
import ListOrderDetails from "./listOrderDetails.component";
import Overlay from "../components/overlay/overlay.component";
import { GroupedOrdersTableProps, OrderStatusFilterType } from "../types";

// render Grouped by patient Orders in procedures app
const GroupedOrdersTable: React.FC<GroupedOrdersTableProps> = (props) => {
const workListEntries = props.orders;
const { t } = useTranslation();
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [searchString, setSearchString] = useState<string>("");
const [activatedOnOrAfterDate, setActivatedOnOrAfterDate] = useState("");

const OrderStatuses = [
"All",
"RECEIVED",
"IN_PROGRESS",
"COMPLETED",
"EXCEPTION",
"ON_HOLD",
"DECLINED",
];

const [filter, setFilter] = useState<OrderStatusFilterType>("All");

const filteredEntries = useMemo(() => {
if (!filter || filter == "All") {
return workListEntries;
}

if (filter) {
return workListEntries?.filter(
(order) => order.fulfillerStatus === filter
);
}

return workListEntries;
}, [filter, workListEntries]);

const handleOrderStatusChange = ({ selectedItem }) => setFilter(selectedItem);

function groupOrdersById(orders) {
if (orders && orders.length > 0) {
const groupedOrders = orders.reduce((acc, item) => {
if (!acc[item.patient.uuid]) {
acc[item.patient.uuid] = [];
}
acc[item.patient.uuid].push(item);
return acc;
}, {});

// Convert the result to an array of objects with patientId and orders
return Object.keys(groupedOrders).map((patientId) => ({
patientId: patientId,
orders: groupedOrders[patientId],
}));
} else {
return [];
}
}
const groupedOrdersByPatient = groupOrdersById(filteredEntries);
const searchResults = useSearchGroupedResults(
groupedOrdersByPatient,
searchString
);
const {
goTo,
results: paginatedResults,
currentPage,
} = usePagination(searchResults, currentPageSize);

const pageSizes = [10, 20, 30, 40, 50];

const rowsData = useMemo(() => {
return paginatedResults.map((patient) => ({
id: patient.patientId,
patientName: patient.orders[0].patient?.display?.split("-")[1],
orders: patient.orders,
totalOrders: patient.orders?.length,
}));
}, [paginatedResults]);

const tableColumns = [
{ id: 0, header: t("patient", "Patient"), key: "patientName" },
{ id: 1, header: t("totalorders", "Total Orders"), key: "totalOrders" },
];
return (
<div>
<DataTable
rows={rowsData}
headers={tableColumns}
useZebraStyles
overflowMenuOnHover={true}
>
{({
rows,
headers,
getHeaderProps,
getTableProps,
getRowProps,
onInputChange,
}) => (
<TableContainer className={styles.tableContainer}>
<TableToolbar
style={{
position: "static",
}}
>
<TableToolbarContent>
{props.showStatusFilter && (
<Layer style={{ margin: "5px" }}>
<Dropdown
id="orderStatus"
initialSelectedItem={"All"}
label=""
titleText={
t("filterOrdersByStatus", "Filter orders by status") +
":"
}
type="inline"
items={OrderStatuses}
onChange={handleOrderStatusChange}
/>
</Layer>
)}
{props.showDateFilter && (
<Layer style={{ margin: "5px" }}>
<DatePicker dateFormat="Y-m-d" datePickerType="single">
<DatePickerInput
labelText={""}
id="activatedOnOrAfterDate"
placeholder="YYYY-MM-DD"
onChange={(event) => {
setActivatedOnOrAfterDate(event.target.value);
}}
type="date"
value={activatedOnOrAfterDate}
/>
</DatePicker>
</Layer>
)}
<Layer style={{ margin: "5px" }}>
<TableToolbarSearch
expanded
onChange={onInputChange}
placeholder={t("searchThisList", "Search this list")}
size="sm"
/>
</Layer>
</TableToolbarContent>
</TableToolbar>
<Table {...getTableProps()} className={styles.activePatientsTable}>
<TableHead>
<TableRow>
<TableExpandHeader />
{headers.map((header) => (
<TableHeader {...getHeaderProps({ header })}>
{header.header}
</TableHeader>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.length > 0 ? (
rows.map((row) => (
<React.Fragment key={row.id}>
<TableExpandRow {...getRowProps({ row })}>
{row.cells.map((cell) => (
<TableCell key={cell.id}>
{cell.id.endsWith("created")
? formatDate(parseDate(cell.value))
: cell.value}
</TableCell>
))}
</TableExpandRow>
<TableExpandedRow colSpan={headers.length + 1}>
<ListOrderDetails
actions={props.actions}
groupedOrders={groupedOrdersByPatient.find(
(item) => item.patientId === row.id
)}
showActions={props.showActions}
showOrderType={props.showOrderType}
showStatus={props.showStatus}
/>
</TableExpandedRow>
</React.Fragment>
))
) : (
<TableRow>
<TableCell
colSpan={headers.length + 1}
style={{ textAlign: "center" }}
className={styles.noOrdersDiv}
>
{t("noOrderAvailable", "No orders available")}
</TableCell>
</TableRow>
)}
</TableBody>
</Table>

<Pagination
forwardText="Next page"
backwardText="Previous page"
page={currentPage}
pageSize={currentPageSize}
pageSizes={pageSizes}
totalItems={filteredEntries?.length}
className={styles.pagination}
onChange={({ pageSize, page }) => {
if (pageSize !== currentPageSize) {
// setPageSize(pageSize);
}
if (page !== currentPage) {
goTo(page);
}
}}
/>
</TableContainer>
)}
</DataTable>
<Overlay />
</div>
);
};

export default GroupedOrdersTable;
45 changes: 45 additions & 0 deletions packages/esm-procedure-app/src/common/groupedOrdersTable.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@use '@carbon/layout';
@use '@carbon/colors';
@use '@openmrs/esm-styleguide/src/vars' as *;
@use '@carbon/styles/scss/type';

.tableContainer {
background-color: $ui-01;
margin: layout.$spacing-05;
padding: 0;

a {
text-decoration: none;
}

th {
color: $text-02;
}

:global(.cds--data-table) {
background-color: $ui-03;
}

.toolbarContent {
height: layout.$spacing-07;
margin-bottom: layout.$spacing-02;
}
}
.noOrdersDiv{
background-color: #fff;
text-align: center;
font-weight:bold;
width: 100%;
}

.ordersTableToolbar{
position: static;
height: 3rem;
overflow: visible;
margin: 0;
}

.ordersToolbarSearchBar{
background-color:#f4f4f4 ;
}

Loading

0 comments on commit cdcf2e8

Please sign in to comment.