-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from Michaelndula/main
Remove unwanted errors from the app
- Loading branch information
Showing
36 changed files
with
31,898 additions
and
1,657 deletions.
There are no files selected for viewing
541 changes: 541 additions & 0 deletions
541
packages/esm-procedure-app/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
Large diffs are not rendered by default.
Oops, something went wrong.
35 changes: 35 additions & 0 deletions
35
packages/esm-procedure-app/.yarn/plugins/@yarnpkg/plugin-outdated.cjs
Large diffs are not rendered by default.
Oops, something went wrong.
550 changes: 550 additions & 0 deletions
550
packages/esm-procedure-app/.yarn/plugins/@yarnpkg/plugin-version.cjs
Large diffs are not rendered by default.
Oops, something went wrong.
874 changes: 874 additions & 0 deletions
874
packages/esm-procedure-app/.yarn/releases/yarn-3.6.1.cjs
Large diffs are not rendered by default.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
|
@@ -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": { | ||
|
@@ -112,5 +113,5 @@ | |
"webpack-cli": "^5.1.4" | ||
}, | ||
"packageManager": "[email protected]", | ||
"gitHead": "f1661da45d2c1cd9be4305a0e015a6f66685af85" | ||
"gitHead": "50c3c5d51d59bbab87b49e830a948aab4a152e44" | ||
} |
253 changes: 253 additions & 0 deletions
253
packages/esm-procedure-app/src/common/groupedOrdersTable.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
45
packages/esm-procedure-app/src/common/groupedOrdersTable.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ; | ||
} | ||
|
Oops, something went wrong.