Skip to content

Commit

Permalink
Merge pull request #5778 from msupply-foundation/v2.4.1
Browse files Browse the repository at this point in the history
V2.4.1
  • Loading branch information
roxy-dao authored Dec 12, 2024
2 parents c4baafe + 1a99da3 commit 903872f
Show file tree
Hide file tree
Showing 113 changed files with 3,124 additions and 444 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ export const Summary = ({ draft, onChange, locations }: SummaryProps) => {
onChange={e => onChange({ serialNumber: e.target.value })}
/>
</Row>
<Row label={t('label.asset-number')}>
<BasicTextInput
value={draft.assetNumber ?? ''}
fullWidth
onChange={e => onChange({ assetNumber: e.target.value })}
/>
</Row>
<Row label={t('label.installation-date')}>
<DateTimePickerInput
value={DateUtils.getDateOrNull(draft.installationDate)}
Expand Down
4 changes: 4 additions & 0 deletions client/packages/common/src/hooks/useQueryParams/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export type FilterRule = {

export type FilterBy = Record<string, FilterRule | null>;
export type FilterByWithBoolean = Record<string, FilterRule | null | boolean>;
export type FilterByWithStringAndBool = Record<
string,
FilterRule | null | boolean | string
>;

export interface FilterController {
filterBy: FilterByWithBoolean | null;
Expand Down
8 changes: 6 additions & 2 deletions client/packages/common/src/intl/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@
"label.clear-filter": "Clear filter",
"label.clear-selection": "Clear selection",
"label.click-to-sort": "Click to sort by ",
"label.click-to-view": "Click to view details",
"label.client": "Client",
"label.clinician": "Clinician",
"label.code": "Code",
Expand Down Expand Up @@ -614,6 +615,7 @@
"label.create-log-reason": "Create log reason",
"label.create-new-program": "Create immunization program",
"label.create-pack-variant": "Create Pack Variant",
"label.create-prescription": "Create Prescription",
"label.created": "Created",
"label.created-datetime": "Created date / time",
"label.cumulative": "Cumulative",
Expand Down Expand Up @@ -1359,10 +1361,10 @@
"messages.fridge-tag-import-successful": "Success! {{numberOfLogs}} logs and {{numberOfBreaches}} breaches imported.",
"messages.full-screen-enabled": "Full screen mode enabled, press ESC or click the Exit button in the top right to exit",
"messages.how-to-read-expiring-items": "Column descriptions: \n* Expiring in (days): Number of days left until batch expires using the expiring items period preference. \nYellow - batches below the expiring item period. \nGreen - anything above the expiring item period. \nRed - expired items. \n* Expected usage: AMC of the item multiplied by the number of months left until expiry. \n* Stock at risk: Quantity of stock that will likely expire before it is used. \nSOH - Expected usage. If the stock is expired, then this should show all SOH for that stock line.",
"messages.how-to-read-item-usage": "Column descriptions: \n* Stock on order: Sum of quantity in Internal Orders minus any linked Inbound Shipments. \n* Months cover: Number of months the current stock will last based on AMC.",
"messages.how-to-read-item-usage": "Column descriptions: \n* Stock on order: Sum of quantity in Internal Orders minus any linked Inbound Shipments \n* Months cover: Number of months the current stock is expected to last. The value is 'In stock' / 'AMC'. Note that AMC is calculated using the number of months given by the 'AMC lookback period' shown in the report filter which is configured with the 'monthly consumption lookback period' store preference.",
"messages.how-to-read-report": "How to read {{reportName}} report?",
"messages.how-to-read-stock-detail": "This report has the same information as the stock page without any interactivity.",
"messages.how-to-read-stock-status": "Status descriptions: \n* Understocked - MOS is lower than min MOS (preference: threshold for understock). \n* Overstock - MOS is higher than max MOS (preference: threshold for overstock). \n* Out of stock - SOH and AMC is 0. \n* Well stocked - MOS is between min and max MOS. \n* No consumption - AMC is 0.",
"messages.how-to-read-stock-status": "Status descriptions: \n* Understocked - MOS is lower than min MOS (store preference: threshold for understock) \n* Overstocked - MOS is higher than max MOS (store preference: threshold for overstock) \n* Out of stock - SOH and AMC is 0 \n* Well stocked - MOS is between min and max MOS \n* No consumption - AMC is 0",
"messages.import-error": "Some or all assets failed to import. Click export to download a csv file with rows which caused an error. Error free rows will have been imported",
"messages.import-error-on-upload": "Import error on upload. Please fix errors and re upload",
"messages.import-generic": "import successful",
Expand Down Expand Up @@ -1435,6 +1437,8 @@
"messages.period-not-available": "No available periods",
"messages.placeholder-allocated": "Not enough stock is available to allocate the requested quantity. A placeholder has been added for {{placeholderQuantity}} units.",
"messages.prescription-saved": "Prescription saved 🥳",
"messages.prescription-created": "Prescription #{{count}} created",
"messages.prescription-will-be-created": "Prescription will be created when form is saved",
"messages.properties-download-example": "Download a template CSV",
"messages.properties-template-download-text": " with the facilities' current properties ",
"messages.record-not-found": "Record not found",
Expand Down
12 changes: 12 additions & 0 deletions client/packages/common/src/styles/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ declare module '@mui/material/styles/createPalette' {
pending: string;
late: string;
};
programs: {
encounterCategory: string;
encounterCategoryHover: string;
iconGradientStart: string;
iconGradientStop: string;
};
drawerDivider: string;
gray: PaletteColor & { pale: string };
outline: Palette['primary'];
Expand Down Expand Up @@ -228,6 +234,12 @@ export const themeOptions = {
pending: 'info.light',
late: 'error.main',
},
programs: {
encounterCategory: '#e7effe',
encounterCategoryHover: '#D2DFFF',
iconGradientStart: '#E73735',
iconGradientStop: '#FC7E08',
},
},
zIndex: {
tableHeader: 1000,
Expand Down
2 changes: 2 additions & 0 deletions client/packages/common/src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3555,6 +3555,8 @@ export type ItemCountsResponse = {
};

export type ItemFilterInput = {
categoryId?: InputMaybe<Scalars['String']['input']>;
categoryName?: InputMaybe<Scalars['String']['input']>;
code?: InputMaybe<StringFilterInput>;
codeOrName?: InputMaybe<StringFilterInput>;
id?: InputMaybe<EqualFilterStringInput>;
Expand Down
95 changes: 0 additions & 95 deletions client/packages/host/public/medical-icons.css

This file was deleted.

1 change: 0 additions & 1 deletion client/packages/host/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ module.exports = env => {
}),
new CopyPlugin({
patterns: [
{ from: './public/medical-icons.css', to: 'medical-icons.css' },
{ from: './public/game', to: 'game' },
{
context: path.resolve(
Expand Down
16 changes: 16 additions & 0 deletions client/packages/invoices/src/Prescriptions/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@ export const getPrescriptionQueries = (sdk: Sdk, storeId: string) => ({
throw new Error('Could not find invoice');
}
},
byId: async (
invoiceId: string
): Promise<PrescriptionRowFragment | void> => {
const result = await sdk.prescriptionById({
invoiceId,
storeId,
});
const invoice = result?.invoice;

if (invoice?.__typename === 'InvoiceNode') {
return invoice;
}
// Don't throw error for this one if not found -- it's mainly used by
// Program component (Prescription), which may have stored an id for a
// prescription that doesn't yet exist
},
},
insert: async (
invoice: Omit<InsertPrescriptionMutationVariables, 'storeId'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { usePrescription } from './usePrescription';
import { usePrescriptionById } from './usePrescriptionById';
import { usePrescriptionDelete } from './usePrescriptionDelete';
import { usePrescriptionDeleteRows } from './usePrescriptionDeleteRows';
import { usePrescriptionFields } from './usePrescriptionFields';
Expand All @@ -8,6 +9,7 @@ import { usePrescriptions } from './usePrescriptions';

export const Document = {
usePrescription,
usePrescriptionById,
usePrescriptions,
usePrescriptionInsert,
usePrescriptionUpdate,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useQuery } from '@openmsupply-client/common';
import { usePrescriptionApi } from '../../utils/usePrescriptionApi';

export const usePrescriptionById = (invoiceId: string = '') => {
const api = usePrescriptionApi();

return useQuery(api.keys.detail(invoiceId), () => api.get.byId(invoiceId), {
refetchOnMount: false,
cacheTime: 0,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Utils } from './utils';
export const usePrescription = {
document: {
get: Document.usePrescription,
getById: Document.usePrescriptionById,
fields: Document.usePrescriptionFields,
list: Document.usePrescriptions,
insert: Document.usePrescriptionInsert,
Expand Down
1 change: 1 addition & 0 deletions client/packages/invoices/src/Prescriptions/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './hooks';
export * from './operations.generated';
export * from './api';
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ export type PrescriptionByNumberQueryVariables = Types.Exact<{

export type PrescriptionByNumberQuery = { __typename: 'Queries', invoiceByNumber: { __typename: 'InvoiceNode', comment?: string | null, createdDatetime: string, pickedDatetime?: string | null, verifiedDatetime?: string | null, id: string, invoiceNumber: number, otherPartyId: string, otherPartyName: string, clinicianId?: string | null, type: Types.InvoiceNodeType, status: Types.InvoiceNodeStatus, colour?: string | null, currencyRate: number, prescriptionDate?: string | null, pricing: { __typename: 'PricingNode', totalAfterTax: number, totalBeforeTax: number, stockTotalBeforeTax: number, stockTotalAfterTax: number, serviceTotalAfterTax: number, serviceTotalBeforeTax: number, taxPercentage?: number | null }, user?: { __typename: 'UserNode', username: string, email?: string | null } | null, lines: { __typename: 'InvoiceLineConnector', totalCount: number, nodes: Array<{ __typename: 'InvoiceLineNode', id: string, type: Types.InvoiceLineNodeType, batch?: string | null, expiryDate?: string | null, numberOfPacks: number, packSize: number, invoiceId: string, sellPricePerPack: number, note?: string | null, totalBeforeTax: number, totalAfterTax: number, taxPercentage?: number | null, itemName: string, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, location?: { __typename: 'LocationNode', id: string, name: string, code: string, onHold: boolean } | null, stockLine?: { __typename: 'StockLineNode', id: string, itemId: string, batch?: string | null, availableNumberOfPacks: number, totalNumberOfPacks: number, onHold: boolean, sellPricePerPack: number, packSize: number, expiryDate?: string | null, item: { __typename: 'ItemNode', name: string, code: string } } | null }> }, patient?: { __typename: 'PatientNode', id: string, name: string, code: string, isDeceased: boolean } | null, clinician?: { __typename: 'ClinicianNode', id: string, firstName?: string | null, lastName: string } | null, currency?: { __typename: 'CurrencyNode', id: string, code: string, rate: number, isHomeCurrency: boolean } | null } | { __typename: 'NodeError', error: { __typename: 'DatabaseError', description: string, fullError: string } | { __typename: 'RecordNotFound', description: string } } };

export type PrescriptionByIdQueryVariables = Types.Exact<{
invoiceId: Types.Scalars['String']['input'];
storeId: Types.Scalars['String']['input'];
}>;


export type PrescriptionByIdQuery = { __typename: 'Queries', invoice: { __typename: 'InvoiceNode', comment?: string | null, createdDatetime: string, pickedDatetime?: string | null, verifiedDatetime?: string | null, id: string, invoiceNumber: number, otherPartyId: string, otherPartyName: string, clinicianId?: string | null, type: Types.InvoiceNodeType, status: Types.InvoiceNodeStatus, colour?: string | null, currencyRate: number, prescriptionDate?: string | null, pricing: { __typename: 'PricingNode', totalAfterTax: number, totalBeforeTax: number, stockTotalBeforeTax: number, stockTotalAfterTax: number, serviceTotalAfterTax: number, serviceTotalBeforeTax: number, taxPercentage?: number | null }, user?: { __typename: 'UserNode', username: string, email?: string | null } | null, lines: { __typename: 'InvoiceLineConnector', totalCount: number, nodes: Array<{ __typename: 'InvoiceLineNode', id: string, type: Types.InvoiceLineNodeType, batch?: string | null, expiryDate?: string | null, numberOfPacks: number, packSize: number, invoiceId: string, sellPricePerPack: number, note?: string | null, totalBeforeTax: number, totalAfterTax: number, taxPercentage?: number | null, itemName: string, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, location?: { __typename: 'LocationNode', id: string, name: string, code: string, onHold: boolean } | null, stockLine?: { __typename: 'StockLineNode', id: string, itemId: string, batch?: string | null, availableNumberOfPacks: number, totalNumberOfPacks: number, onHold: boolean, sellPricePerPack: number, packSize: number, expiryDate?: string | null, item: { __typename: 'ItemNode', name: string, code: string } } | null }> }, patient?: { __typename: 'PatientNode', id: string, name: string, code: string, isDeceased: boolean } | null, clinician?: { __typename: 'ClinicianNode', id: string, firstName?: string | null, lastName: string } | null, currency?: { __typename: 'CurrencyNode', id: string, code: string, rate: number, isHomeCurrency: boolean } | null } | { __typename: 'NodeError', error: { __typename: 'DatabaseError', description: string, fullError: string } | { __typename: 'RecordNotFound', description: string } } };

export type InsertPrescriptionMutationVariables = Types.Exact<{
id: Types.Scalars['String']['input'];
patientId: Types.Scalars['String']['input'];
Expand Down Expand Up @@ -175,6 +183,31 @@ export const PrescriptionByNumberDocument = gql`
}
}
${PrescriptionRowFragmentDoc}`;
export const PrescriptionByIdDocument = gql`
query prescriptionById($invoiceId: String!, $storeId: String!) {
invoice(id: $invoiceId, storeId: $storeId) {
__typename
... on NodeError {
__typename
error {
description
... on DatabaseError {
__typename
description
fullError
}
... on RecordNotFound {
__typename
description
}
}
}
... on InvoiceNode {
...PrescriptionRow
}
}
}
${PrescriptionRowFragmentDoc}`;
export const InsertPrescriptionDocument = gql`
mutation insertPrescription($id: String!, $patientId: String!, $storeId: String!) {
insertPrescription(storeId: $storeId, input: {id: $id, patientId: $patientId}) {
Expand Down Expand Up @@ -424,6 +457,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
prescriptionByNumber(variables: PrescriptionByNumberQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<PrescriptionByNumberQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<PrescriptionByNumberQuery>(PrescriptionByNumberDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'prescriptionByNumber', 'query', variables);
},
prescriptionById(variables: PrescriptionByIdQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<PrescriptionByIdQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<PrescriptionByIdQuery>(PrescriptionByIdDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'prescriptionById', 'query', variables);
},
insertPrescription(variables: InsertPrescriptionMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<InsertPrescriptionMutation> {
return withWrapper((wrappedRequestHeaders) => client.request<InsertPrescriptionMutation>(InsertPrescriptionDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'insertPrescription', 'mutation', variables);
},
Expand Down
24 changes: 24 additions & 0 deletions client/packages/invoices/src/Prescriptions/api/operations.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,30 @@ query prescriptionByNumber($invoiceNumber: Int!, $storeId: String!) {
}
}

query prescriptionById($invoiceId: String!, $storeId: String!) {
invoice(id: $invoiceId, storeId: $storeId) {
__typename
... on NodeError {
__typename
error {
description
... on DatabaseError {
__typename
description
fullError
}
... on RecordNotFound {
__typename
description
}
}
}
... on InvoiceNode {
...PrescriptionRow
}
}
}

mutation insertPrescription(
$id: String!
$patientId: String!
Expand Down
1 change: 1 addition & 0 deletions client/packages/invoices/src/Prescriptions/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { PrescriptionListView } from './ListView';
export { PrescriptionDetailView } from './DetailView';
export * from './api';
9 changes: 7 additions & 2 deletions client/packages/programs/src/JsonForms/common/JsonForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
FORM_COLUMN_MAX_WIDTH,
FORM_LABEL_COLUMN_WIDTH,
} from './styleConstants';
import { FormActionStructure } from '../useFormActions';

export type JsonType = string | number | boolean | null | undefined;

Expand All @@ -69,7 +70,9 @@ export type JsonData =

interface JsonFormProps {
data?: JsonData;
config?: Record<string, JsonData>;
config?: JsonFormsConfig & {
formActions: FormActionStructure;
};
jsonSchema: JsonSchema;
uiSchema: UISchemaElement;
isError: boolean;
Expand All @@ -87,7 +90,9 @@ interface JsonFormsComponentProps {
setData: (data: JsonData) => void;
setError?: (error: string | false) => void;
renderers: JsonFormsRendererRegistryEntry[];
config?: Record<string, JsonData>;
config?: JsonFormsConfig & {
formActions: FormActionStructure;
};
}

// Prevents Form window being loaded with the same scroll position as its parent
Expand Down
Loading

0 comments on commit 903872f

Please sign in to comment.