Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5364 gis scanner handling #5382

Merged
merged 13 commits into from
Nov 13, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ import {
useNavigate,
useDisabledNotificationPopover,
RouteBuilder,
useConfirmationModal,
FnUtils,
AssetLogStatusInput,
} from '@openmsupply-client/common';
import { AppRoute } from '@openmsupply-client/config';
import { useAssets } from '../api';
import { DraftAsset } from '../types';

export const AddFromScannerButtonComponent = () => {
const t = useTranslation();
Expand All @@ -30,19 +34,60 @@ export const AddFromScannerButtonComponent = () => {
const equipmentRoute = RouteBuilder.create(AppRoute.Coldchain).addPart(
AppRoute.Equipment
);
const { mutateAsync: fetchAsset } = useAssets.document.fetch();
const { mutateAsync: scanAsset } = useAssets.document.scan();
const { mutateAsync: saveNewAsset } = useAssets.document.insert();
const { insertLog, invalidateQueries } = useAssets.log.insert();
const newAssetData = useRef<DraftAsset>();

const showCreateConfirmation = useConfirmationModal({
onConfirm: () => {
if (newAssetData.current) {
saveNewAsset(newAssetData.current)
.catch(e => error(t('error.unable-to-save-asset', { error: e }))())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This catch doesn't work for some reason!
I tired adding throw e into the useAssets.document.insert(); useMutation:onError but that didn't work.
Help please!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears to work fine for me? Though you'd need to add {{ error }} to the 'error.unable-to-save-asset' translation for the error message to show... not entirely sure it should though!

The only time I can seem to see where it doesn't show a message is when newAssetData.current isn't defined.... I think somewhere we have an example of passing data into confirm (so we can pass directly from handleScanResult, and skip the ref thing completely) - but I can't find right now, and I know we're on a time crunch to get something for RC!

Can be a clean up for another PR, maybe as part of that other issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move the catch below the .then() though! If saveNewAsset errors, we don't want to catch, and then try do the insertLog/redirect, should throw to below that

.then(async () => {
if (newAssetData.current) {
await insertLog({
Copy link
Contributor Author

@jmbrunskill jmbrunskill Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated functionality as the add new asset modal does this too.
Would be nice to consolidate in #5392

id: FnUtils.generateUUID(),
assetId: newAssetData.current.id,
comment: t('label.created'),
status: AssetLogStatusInput.Functioning,
});
invalidateQueries();
navigate(equipmentRoute.addPart(newAssetData.current.id).build());
}
});
}
},
message: t('heading.create-new-asset'),
title: t('messages.create-new-asset-confirmation'),
});

const handleScanResult = async (result: ScanResult) => {
if (!!result.content) {
const { content } = result;
const id = content;
const asset = await fetchAsset(id).catch(() => {});
if (asset) {
navigate(equipmentRoute.addPart(id).build());

const asset = await scanAsset(content).catch(() => {});

if (asset?.__typename !== 'AssetNode') {
error(t('error.no-matching-asset', { id: result.content }))();
return;
}
if (asset?.id) {
navigate(equipmentRoute.addPart(asset?.id).build());
return;
}

error(t('error.no-matching-asset', { id }))();
// If not existing, offer to create from the parsed GS1 data
if (!asset?.id) {
newAssetData.current = {
...asset,
id: FnUtils.generateUUID(),
locationIds: [],
parsedProperties: {},
parsedCatalogProperties: {},
};
showCreateConfirmation();
}
}
};

Expand Down
7 changes: 7 additions & 0 deletions client/packages/coldchain/src/Equipment/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ export const getAssetQueries = (sdk: Sdk, storeId: string) => ({

throw new Error('Asset not found');
},
byScannerString: async (inputText: string) => {
const { assetByScannedString } = await sdk.assetByScannedString({
storeId,
inputText,
});
return assetByScannedString;
},
list: async (
{ first, offset, sortBy, filterBy }: ListParams<AssetFragment>,
storeCode?: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { useAsset, useFetchAssetById } from './useAsset';
import {
useAsset,
useFetchAssetById,
useFetchAssetByScannerString,
} from './useAsset';
import { useAssetDelete } from './useAssetDelete';
import { useAssetFields } from './useAssetFields';
import { useAssetInsert } from './useAssetInsert';
Expand All @@ -18,5 +22,6 @@ export const Document = {
useAssetsDelete,
useAssetUpdate,
useFetchAssetById,
useFetchAssetByScannerString,
useAssetProperties,
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ export const useFetchAssetById = () => {
onError: () => {},
});
};

export const useFetchAssetByScannerString = () => {
const api = useAssetApi();
return useMutation(api.get.byScannerString, {
onError: () => {},
});
};
1 change: 1 addition & 0 deletions client/packages/coldchain/src/Equipment/api/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const useAssets = {

document: {
fetch: Document.useFetchAssetById,
scan: Document.useFetchAssetByScannerString,
get: Document.useAsset,
list: Document.useAssets,
listAll: Document.useAssetsAll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ export type AssetByIdQueryVariables = Types.Exact<{

export type AssetByIdQuery = { __typename: 'Queries', assets: { __typename: 'AssetConnector', totalCount: number, nodes: Array<{ __typename: 'AssetNode', catalogueItemId?: string | null, assetNumber?: string | null, createdDatetime: any, id: string, installationDate?: string | null, properties: string, catalogProperties?: string | null, modifiedDatetime: any, notes?: string | null, replacementDate?: string | null, serialNumber?: string | null, storeId?: string | null, donorNameId?: string | null, warrantyStart?: string | null, warrantyEnd?: string | null, needsReplacement?: boolean | null, documents: { __typename: 'SyncFileReferenceConnector', nodes: Array<{ __typename: 'SyncFileReferenceNode', fileName: string, id: string, mimeType?: string | null }> }, locations: { __typename: 'LocationConnector', totalCount: number, nodes: Array<{ __typename: 'LocationNode', id: string, code: string, name: string, onHold: boolean, coldStorageType?: { __typename: 'ColdStorageTypeNode', id: string, name: string, maxTemperature: number, minTemperature: number } | null }> }, statusLog?: { __typename: 'AssetLogNode', logDatetime: any, status?: Types.StatusType | null, reason?: { __typename: 'AssetLogReasonNode', reason: string } | null } | null, store?: { __typename: 'StoreNode', id: string, code: string, storeName: string } | null, catalogueItem?: { __typename: 'AssetCatalogueItemNode', manufacturer?: string | null, model: string } | null, assetType?: { __typename: 'AssetTypeNode', id: string, name: string } | null, assetClass?: { __typename: 'AssetClassNode', id: string, name: string } | null, assetCategory?: { __typename: 'AssetCategoryNode', id: string, name: string } | null, donor?: { __typename: 'NameNode', id: string, name: string } | null }> } };

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


export type AssetByScannedStringQuery = { __typename: 'Queries', assetByScannedString: { __typename: 'AssetNode', catalogueItemId?: string | null, assetNumber?: string | null, createdDatetime: any, id: string, installationDate?: string | null, properties: string, catalogProperties?: string | null, modifiedDatetime: any, notes?: string | null, replacementDate?: string | null, serialNumber?: string | null, storeId?: string | null, donorNameId?: string | null, warrantyStart?: string | null, warrantyEnd?: string | null, needsReplacement?: boolean | null, documents: { __typename: 'SyncFileReferenceConnector', nodes: Array<{ __typename: 'SyncFileReferenceNode', fileName: string, id: string, mimeType?: string | null }> }, locations: { __typename: 'LocationConnector', totalCount: number, nodes: Array<{ __typename: 'LocationNode', id: string, code: string, name: string, onHold: boolean, coldStorageType?: { __typename: 'ColdStorageTypeNode', id: string, name: string, maxTemperature: number, minTemperature: number } | null }> }, statusLog?: { __typename: 'AssetLogNode', logDatetime: any, status?: Types.StatusType | null, reason?: { __typename: 'AssetLogReasonNode', reason: string } | null } | null, store?: { __typename: 'StoreNode', id: string, code: string, storeName: string } | null, catalogueItem?: { __typename: 'AssetCatalogueItemNode', manufacturer?: string | null, model: string } | null, assetType?: { __typename: 'AssetTypeNode', id: string, name: string } | null, assetClass?: { __typename: 'AssetClassNode', id: string, name: string } | null, assetCategory?: { __typename: 'AssetCategoryNode', id: string, name: string } | null, donor?: { __typename: 'NameNode', id: string, name: string } | null } | { __typename: 'ScannedDataParseError' } };

export type AssetLogsQueryVariables = Types.Exact<{
filter: Types.AssetLogFilterInput;
sort?: Types.InputMaybe<Array<Types.AssetLogSortInput> | Types.AssetLogSortInput>;
Expand Down Expand Up @@ -242,6 +250,15 @@ export const AssetByIdDocument = gql`
}
}
${AssetFragmentDoc}`;
export const AssetByScannedStringDocument = gql`
query assetByScannedString($storeId: String!, $inputText: String!) {
assetByScannedString(storeId: $storeId, inputText: $inputText) {
... on AssetNode {
...Asset
}
}
}
${AssetFragmentDoc}`;
export const AssetLogsDocument = gql`
query assetLogs($filter: AssetLogFilterInput!, $sort: [AssetLogSortInput!], $storeId: String!) {
assetLogs(filter: $filter, sort: $sort, storeId: $storeId) {
Expand Down Expand Up @@ -346,6 +363,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
assetById(variables: AssetByIdQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<AssetByIdQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<AssetByIdQuery>(AssetByIdDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'assetById', 'query', variables);
},
assetByScannedString(variables: AssetByScannedStringQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<AssetByScannedStringQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<AssetByScannedStringQuery>(AssetByScannedStringDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'assetByScannedString', 'query', variables);
},
assetLogs(variables: AssetLogsQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<AssetLogsQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<AssetLogsQuery>(AssetLogsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'assetLogs', 'query', variables);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ query assetById($storeId: String!, $assetId: String!) {
}
}

query assetByScannedString($storeId: String!, $inputText: String!) {
assetByScannedString(storeId: $storeId, inputText: $inputText) {
... on AssetNode {
...Asset
}
}
}

query assetLogs(
$filter: AssetLogFilterInput!
$sort: [AssetLogSortInput!]
Expand Down
4 changes: 3 additions & 1 deletion client/packages/common/src/intl/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@
"heading.consumption-history": "Consumption History (monthly)",
"heading.create-outbound-shipment": "Create Outbound Shipment",
"heading.create-vaccine-course": "Create vaccine course",
"heading.create-new-asset": "Create new asset",
"heading.custom": "Custom",
"heading.custom-logo": "Custom logo",
"heading.custom-logo-info": "Replaces the default \"mSupply man\". The logo has to be in svg format, e.g. <?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>...<svg...>",
Expand Down Expand Up @@ -1268,6 +1269,7 @@
"messages.create-stocktake-1": "You can create a stocktake based on items currently assigned to a location, items that you currently have in stock, items assigned to a master list, or items expiring before a particular date.",
"messages.create-stocktake-2": "To create an empty stocktake, simply click OK to continue.",
"messages.created-new-vaccine-course": "Successfully created vaccine course",
"messages.create-new-asset-confirmation": "The asset you scanned is not currently in the system, but has provided appropriate GS1 data. Would you like to create a new asset with this data?",
"messages.customer-requisition-created-on": "Customer requisition created on {{date}}",
"messages.delete-this-line": "Delete this line",
"messages.deleted-assets_one": "Deleted {{count}} asset",
Expand Down Expand Up @@ -1666,4 +1668,4 @@
"warning.caps-lock": "Warning: Caps lock is on",
"warning.field-not-parsed": "{{field}} not parsed",
"warning.nothing-to-supply": "Nothing left to supply!"
}
}
Loading
Loading