Skip to content

Commit 378cfb0

Browse files
authored
Added upload PDF (#890)
* Added post and get PDF routes * Added gotOneInspectionPdf to MonkState
1 parent 2a145a5 commit 378cfb0

File tree

17 files changed

+492
-2
lines changed

17 files changed

+492
-2
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { MonkAction, MonkActionType } from './monkAction';
2+
import { MonkState } from '../state';
3+
4+
/**
5+
* The payload of a MonkGotOneInspectionPdfPayload.
6+
*/
7+
export interface MonkGotOneInspectionPdfPayload {
8+
/**
9+
* The ID of the inspection to which the PDF was fetched.
10+
*/
11+
inspectionId: string;
12+
/**
13+
* The URL of the PDF.
14+
*/
15+
pdfUrl: string;
16+
}
17+
18+
/**
19+
* Action dispatched when a inspection PDF has been fetched.
20+
*/
21+
export interface MonkGotOneInspectionPdfAction extends MonkAction {
22+
/**
23+
* The type of the action : `MonkActionType.GOT_ONE_INSPECTION_PDF`.
24+
*/
25+
type: MonkActionType.GOT_ONE_INSPECTION_PDF;
26+
/**
27+
* The payload of the action containing the fetched entities.
28+
*/
29+
payload: MonkGotOneInspectionPdfPayload;
30+
}
31+
32+
/**
33+
* Matcher function that matches a GotOneInspection while also inferring its type using TypeScript's type predicate
34+
* feature.
35+
*/
36+
export function isGotOneInspectionPdfAction(
37+
action: MonkAction,
38+
): action is MonkGotOneInspectionPdfAction {
39+
return action.type === MonkActionType.GOT_ONE_INSPECTION_PDF;
40+
}
41+
42+
/**
43+
* Reducer function for a GotOneInspection action.
44+
*/
45+
export function gotOneInspectionPdf(
46+
state: MonkState,
47+
action: MonkGotOneInspectionPdfAction,
48+
): MonkState {
49+
const { inspections } = state;
50+
const { payload } = action;
51+
52+
const inspection = inspections.find((value) => value.id === payload.inspectionId);
53+
if (inspection) {
54+
inspection.pdfUrl = payload.pdfUrl;
55+
}
56+
return {
57+
...state,
58+
inspections: [...inspections],
59+
};
60+
}

packages/common/src/state/actions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export * from './updatedOnePricing';
1010
export * from './updatedOneInspectionAdditionalData';
1111
export * from './createdOneDamage';
1212
export * from './deletedOneDamage';
13+
export * from './gotOneInspectionPdf';

packages/common/src/state/actions/monkAction.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export enum MonkActionType {
4646
* Clear and reset the state.
4747
*/
4848
RESET_STATE = 'reset_state',
49+
/**
50+
* An inspection PDF has been fetched from the API.
51+
*/
52+
GOT_ONE_INSPECTION_PDF = 'got_one_inspection_pdf',
4953
}
5054

5155
/**

packages/common/src/state/reducer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import {
2222
isCreatedOneDamageAction,
2323
deletedOneDamage,
2424
isDeletedOneDamageAction,
25+
isGotOneInspectionPdfAction,
26+
gotOneInspectionPdf,
2527
} from './actions';
2628
import { MonkState } from './state';
2729

@@ -62,5 +64,8 @@ export function monkReducer(state: MonkState, action: MonkAction): MonkState {
6264
if (isDeletedOneDamageAction(action)) {
6365
return deletedOneDamage(state, action);
6466
}
67+
if (isGotOneInspectionPdfAction(action)) {
68+
return gotOneInspectionPdf(state, action);
69+
}
6570
return state;
6671
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {
2+
createEmptyMonkState,
3+
MonkActionType,
4+
isGotOneInspectionPdfAction,
5+
gotOneInspectionPdf,
6+
MonkGotOneInspectionPdfAction,
7+
} from '../../../src';
8+
import { Inspection } from '@monkvision/types';
9+
10+
const action: MonkGotOneInspectionPdfAction = {
11+
type: MonkActionType.GOT_ONE_INSPECTION_PDF,
12+
payload: {
13+
inspectionId: 'inspections-test-111111',
14+
pdfUrl: 'pdf-url-test',
15+
},
16+
};
17+
18+
describe('gotOneInspectionPdf action handlers', () => {
19+
describe('Action matcher', () => {
20+
it('should return true if the action has the proper type', () => {
21+
expect(isGotOneInspectionPdfAction({ type: MonkActionType.GOT_ONE_INSPECTION_PDF })).toBe(
22+
true,
23+
);
24+
});
25+
26+
it('should return false if the action does not have the proper type', () => {
27+
expect(isGotOneInspectionPdfAction({ type: MonkActionType.RESET_STATE })).toBe(false);
28+
});
29+
});
30+
31+
describe('Action handler', () => {
32+
it('should return a new state', () => {
33+
const state = createEmptyMonkState();
34+
expect(Object.is(gotOneInspectionPdf(state, action), state)).toBe(false);
35+
});
36+
37+
it('should update inspection in the state', () => {
38+
const state = createEmptyMonkState();
39+
state.inspections.push({
40+
id: 'inspections-test-111111',
41+
} as Inspection);
42+
const newState = gotOneInspectionPdf(state, action);
43+
expect(newState.inspections).toContainEqual({
44+
id: action.payload.inspectionId,
45+
pdfUrl: action.payload.pdfUrl,
46+
});
47+
});
48+
});
49+
});

packages/common/test/state/reducer.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ jest.mock('../../src/state/actions', () => ({
1010
isDeletedOneDamageAction: jest.fn(() => false),
1111
isUpdatedOneInspectionAdditionalDataAction: jest.fn(() => false),
1212
isUpdatedVehicleAction: jest.fn(() => false),
13+
isGotOneInspectionPdfAction: jest.fn(() => false),
1314
createdOneImage: jest.fn(() => null),
1415
gotOneInspection: jest.fn(() => null),
1516
resetState: jest.fn(() => null),
@@ -21,6 +22,7 @@ jest.mock('../../src/state/actions', () => ({
2122
deletedOneDamage: jest.fn(() => null),
2223
updatedOneInspectionAdditionalData: jest.fn(() => null),
2324
updatedVehicle: jest.fn(() => null),
25+
gotOneInspectionPdf: jest.fn(() => null),
2426
}));
2527

2628
import {
@@ -33,6 +35,7 @@ import {
3335
deletedOneDamage,
3436
updatedOneInspectionAdditionalData,
3537
updatedVehicle,
38+
gotOneInspectionPdf,
3639
isCreatedOneImageAction,
3740
isGotOneInspectionAction,
3841
isResetStateAction,
@@ -44,6 +47,7 @@ import {
4447
isDeletedOneDamageAction,
4548
isUpdatedOneInspectionAdditionalDataAction,
4649
isUpdatedVehicleAction,
50+
isGotOneInspectionPdfAction,
4751
MonkAction,
4852
monkReducer,
4953
MonkState,
@@ -66,6 +70,7 @@ const actions = [
6670
handler: updatedOneInspectionAdditionalData,
6771
},
6872
{ matcher: isUpdatedVehicleAction, handler: updatedVehicle },
73+
{ matcher: isGotOneInspectionPdfAction, handler: gotOneInspectionPdf },
6974
] as unknown as { matcher: jest.Mock; handler: jest.Mock; noParams?: boolean }[];
7075

7176
describe('Monk state reducer', () => {

packages/network/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,32 @@ Gets the count of inspections that match the given filters.
238238
|-----------|--------------------------|-----------------------------|----------|
239239
| options | GetAllInspectionsOptions | The options of the request. | ✔️ |
240240

241+
### getPdf
242+
```typescript
243+
import { MonkApi } from '@monkvision/network';
244+
245+
MonkApi.getPdf(options, apiConfig, dispatch);
246+
```
247+
248+
Gets the PDF url of an inspection.
249+
250+
| Parameter | Type | Description | Required |
251+
|-----------|---------------|-----------------------------|----------|
252+
| options | GetPdfOptions | The options of the request. | ✔️ |
253+
254+
### uploadPdf
255+
```typescript
256+
import { MonkApi } from '@monkvision/network';
257+
258+
MonkApi.uploadPdf(options, apiConfig, dispatch);
259+
```
260+
261+
Upload a new PDF to an inspection.
262+
263+
| Parameter | Type | Description | Required |
264+
|-----------|------------------|-----------------------------|----------|
265+
| options | UploadPdfOptions | The options of the request. | ✔️ |
266+
241267
# React Tools
242268
In order to simply integrate the Monk Api requests into your React app, you can make use of the `useMonkApi` hook. This
243269
custom hook returns a custom version of the `MonkApi` object described in the section above, in which the requests do

packages/network/src/api/api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { getLiveConfig } from './liveConfigs';
1111
import { updateInspectionVehicle } from './vehicle';
1212
import { createPricing, deletePricing, updatePricing } from './pricing';
1313
import { createDamage, deleteDamage } from './damage';
14+
import { getPdf, uploadPdf } from './pdf';
1415

1516
/**
1617
* Object regrouping the different API requests available to communicate with the API using the `@monkvision/network`
@@ -32,4 +33,6 @@ export const MonkApi = {
3233
updatePricing,
3334
createDamage,
3435
deleteDamage,
36+
uploadPdf,
37+
getPdf,
3538
};

packages/network/src/api/damage/requests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export interface CreateDamageOptions {
3333
/**
3434
* Create a new damage with the given options. See the `CreateDamageOptions` interface for more details.
3535
*
36-
* @param options The options of the inspection.
36+
* @param options The options of the request.
3737
* @param config The API config.
3838
* @param [dispatch] Optional MonkState dispatch function that you can pass if you want this request to handle React
3939
* state management for you.
@@ -103,7 +103,7 @@ export interface DeleteDamageOptions {
103103
/**
104104
* Delete a damage with the given options. See the `DeleteDamageOptions` interface for more details.
105105
*
106-
* @param options The options of the inspection.
106+
* @param options The options of the request.
107107
* @param config The API config.
108108
* @param [dispatch] Optional MonkState dispatch function that you can pass if you want this request to handle React
109109
* state management for you.

packages/network/src/api/error.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ export enum MonkNetworkError {
2323
* authorization to perform the request.
2424
*/
2525
INSUFFICIENT_AUTHORIZATION = 'InsufficientAuthorization',
26+
/**
27+
* The PDF requested is not available.
28+
*/
29+
UNAVAILABLE_PDF = 'UnavailablePdf',
2630
}
2731

2832
function getErrorMessage(name: string): string | null {
@@ -35,6 +39,8 @@ function getErrorMessage(name: string): string | null {
3539
return 'Authentication token is expired.';
3640
case MonkNetworkError.INSUFFICIENT_AUTHORIZATION:
3741
return 'User does not have the proper authorization grants to perform this request.';
42+
case MonkNetworkError.UNAVAILABLE_PDF:
43+
return 'The PDF requested is not available.';
3844
default:
3945
return null;
4046
}
@@ -60,6 +66,9 @@ function getErrorName(status: number, message: string): MonkNetworkError | null
6066
if (status === 401 && message.includes('Token is expired')) {
6167
return MonkNetworkError.EXPIRED_TOKEN;
6268
}
69+
if (status === 422 && message.includes('PDF has not been required to be generated')) {
70+
return MonkNetworkError.UNAVAILABLE_PDF;
71+
}
6372
// TODO : Also check conditions for MonkNetworkError.INSUFFICIENT_AUTHORIZATION.
6473
return null;
6574
}

0 commit comments

Comments
 (0)