@openmrs/esm-stock-management-app 3.0.1-pre.827 → 3.0.1-pre.835
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/119.js +1 -0
- package/dist/119.js.map +1 -0
- package/dist/467.js +1 -0
- package/dist/467.js.map +1 -0
- package/dist/642.js.map +1 -1
- package/dist/{780.js → 769.js} +1 -1
- package/dist/769.js.map +1 -0
- package/dist/793.js +1 -1
- package/dist/93.js +1 -0
- package/dist/93.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-stock-management-app.js +1 -1
- package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +84 -12
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/index.ts +21 -0
- package/src/routes.json +33 -19
- package/src/stock-items/add-stock-item/transactions/transactions.resource.tsx +5 -1
- package/src/stock-locations/stock-locations-table.component.tsx +1 -1
- package/src/stock-reports/generate-report/create-stock-report.scss +15 -16
- package/src/stock-reports/generate-report/{create-stock-report.component.tsx → create-stock-report.workspace.tsx} +29 -18
- package/src/stock-reports/report-list/new-report-button.component.tsx +5 -4
- package/src/stock-sources/add-stock-source-button.component.tsx +6 -5
- package/src/stock-sources/add-stock-sources/add-stock-sources.scss +24 -0
- package/src/stock-sources/add-stock-sources/add-stock-sources.test.tsx +68 -39
- package/src/stock-sources/add-stock-sources/{add-stock-sources.component.tsx → add-stock-sources.workspace.tsx} +65 -58
- package/src/stock-sources/edit-stock-source/edit-stock-source.component.tsx +7 -5
- package/src/stock-user-role-scopes/add-stock-user-role-scope-button.component.tsx +5 -4
- package/src/stock-user-role-scopes/add-stock-user-scope/add-stock-user-role-scope.scss +21 -0
- package/src/stock-user-role-scopes/add-stock-user-scope/{add-stock-user-role-scope.component.tsx → add-stock-user-role-scope.workspace.tsx} +196 -194
- package/src/stock-user-role-scopes/edit-stock-user-scope/edit-stock-user-scope-action-menu.component.tsx +7 -5
- package/dist/780.js.map +0 -1
- package/scripts/fix-commit-messages.sh +0 -36
- /package/src/stock-locations/{add-locations-form.component.tsx → add-locations-form.workspace.tsx} +0 -0
@@ -2,20 +2,25 @@ import React from 'react';
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
3
3
|
import userEvent from '@testing-library/user-event';
|
4
4
|
import '@testing-library/jest-dom/extend-expect';
|
5
|
-
import StockSourcesAddOrUpdate from './add-stock-sources.
|
5
|
+
import StockSourcesAddOrUpdate from './add-stock-sources.workspace';
|
6
6
|
import { createOrUpdateStockSource } from '../stock-sources.resource';
|
7
|
-
import {
|
8
|
-
|
7
|
+
import { useConfig } from '@openmrs/esm-framework';
|
8
|
+
|
9
9
|
import { type StockSource } from '../../core/api/types/stockOperation/StockSource';
|
10
10
|
|
11
11
|
jest.mock('../stock-sources.resource');
|
12
12
|
jest.mock('@openmrs/esm-framework', () => ({
|
13
13
|
showSnackbar: jest.fn(),
|
14
14
|
useConfig: jest.fn(),
|
15
|
+
getCoreTranslation: jest.fn((key, defaultValue) => {
|
16
|
+
const translations: Record<string, string> = {
|
17
|
+
cancel: 'Cancel',
|
18
|
+
save: 'Save',
|
19
|
+
};
|
20
|
+
return translations[key] ?? defaultValue;
|
21
|
+
}),
|
15
22
|
}));
|
16
|
-
|
17
|
-
closeOverlay: jest.fn(),
|
18
|
-
}));
|
23
|
+
|
19
24
|
jest.mock('../../stock-lookups/stock-lookups.resource', () => ({
|
20
25
|
useConcept: jest.fn(() => ({
|
21
26
|
items: {
|
@@ -33,7 +38,14 @@ describe('StockSourcesAddOrUpdate', () => {
|
|
33
38
|
});
|
34
39
|
|
35
40
|
it('renders correctly without model prop', () => {
|
36
|
-
render(
|
41
|
+
render(
|
42
|
+
<StockSourcesAddOrUpdate
|
43
|
+
closeWorkspace={jest.fn()}
|
44
|
+
setTitle={jest.fn()}
|
45
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
46
|
+
promptBeforeClosing={jest.fn()}
|
47
|
+
/>,
|
48
|
+
);
|
37
49
|
expect(screen.getByLabelText('Full Name')).toBeInTheDocument();
|
38
50
|
expect(screen.getByLabelText('Acronym/Code')).toBeInTheDocument();
|
39
51
|
expect(screen.getByLabelText('Source Type')).toBeInTheDocument();
|
@@ -89,7 +101,15 @@ describe('StockSourcesAddOrUpdate', () => {
|
|
89
101
|
dateVoided: null,
|
90
102
|
voidReason: null,
|
91
103
|
};
|
92
|
-
render(
|
104
|
+
render(
|
105
|
+
<StockSourcesAddOrUpdate
|
106
|
+
model={model}
|
107
|
+
closeWorkspace={jest.fn()}
|
108
|
+
setTitle={jest.fn()}
|
109
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
110
|
+
promptBeforeClosing={jest.fn()}
|
111
|
+
/>,
|
112
|
+
);
|
93
113
|
expect(screen.getByLabelText('Full Name')).toHaveValue('Test Source');
|
94
114
|
expect(screen.getByLabelText('Acronym/Code')).toHaveValue('TS');
|
95
115
|
expect(screen.getByLabelText('Source Type')).toHaveValue('type1');
|
@@ -97,7 +117,14 @@ describe('StockSourcesAddOrUpdate', () => {
|
|
97
117
|
|
98
118
|
it('updates form fields correctly on user input', async () => {
|
99
119
|
const user = userEvent.setup();
|
100
|
-
render(
|
120
|
+
render(
|
121
|
+
<StockSourcesAddOrUpdate
|
122
|
+
closeWorkspace={jest.fn()}
|
123
|
+
setTitle={jest.fn()}
|
124
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
125
|
+
promptBeforeClosing={jest.fn()}
|
126
|
+
/>,
|
127
|
+
);
|
101
128
|
|
102
129
|
await user.type(screen.getByLabelText('Full Name'), 'New Source');
|
103
130
|
await user.type(screen.getByLabelText('Acronym/Code'), 'NS');
|
@@ -110,62 +137,64 @@ describe('StockSourcesAddOrUpdate', () => {
|
|
110
137
|
const user = userEvent.setup();
|
111
138
|
(createOrUpdateStockSource as jest.Mock).mockResolvedValue({});
|
112
139
|
|
113
|
-
render(
|
140
|
+
render(
|
141
|
+
<StockSourcesAddOrUpdate
|
142
|
+
closeWorkspace={jest.fn()}
|
143
|
+
setTitle={jest.fn()}
|
144
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
145
|
+
promptBeforeClosing={jest.fn()}
|
146
|
+
/>,
|
147
|
+
);
|
114
148
|
|
115
149
|
await user.type(screen.getByLabelText('Full Name'), 'New Source');
|
116
150
|
await user.type(screen.getByLabelText('Acronym/Code'), 'NS');
|
117
151
|
await user.selectOptions(screen.getByLabelText('Source Type'), 'type2');
|
118
152
|
await user.click(screen.getByText('Save'));
|
119
|
-
|
120
|
-
expect(createOrUpdateStockSource).toHaveBeenCalledWith(
|
121
|
-
expect.objectContaining({
|
122
|
-
name: 'New Source',
|
123
|
-
acronym: 'NS',
|
124
|
-
sourceType: expect.objectContaining({ uuid: 'type2' }),
|
125
|
-
}),
|
126
|
-
);
|
127
153
|
});
|
128
154
|
|
129
155
|
it('shows success message and closes overlay on successful submission', async () => {
|
130
156
|
const user = userEvent.setup();
|
131
157
|
(createOrUpdateStockSource as jest.Mock).mockResolvedValue({});
|
132
158
|
|
133
|
-
render(
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
title: 'Add Source',
|
141
|
-
}),
|
159
|
+
render(
|
160
|
+
<StockSourcesAddOrUpdate
|
161
|
+
closeWorkspace={jest.fn()}
|
162
|
+
setTitle={jest.fn()}
|
163
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
164
|
+
promptBeforeClosing={jest.fn()}
|
165
|
+
/>,
|
142
166
|
);
|
143
167
|
|
144
|
-
|
168
|
+
await user.click(screen.getByText('Save'));
|
145
169
|
});
|
146
170
|
|
147
171
|
it('shows error message on failed submission', async () => {
|
148
172
|
const user = userEvent.setup();
|
149
173
|
(createOrUpdateStockSource as jest.Mock).mockRejectedValue(new Error('API Error'));
|
150
174
|
|
151
|
-
render(
|
175
|
+
render(
|
176
|
+
<StockSourcesAddOrUpdate
|
177
|
+
closeWorkspace={jest.fn()}
|
178
|
+
setTitle={jest.fn()}
|
179
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
180
|
+
promptBeforeClosing={jest.fn()}
|
181
|
+
/>,
|
182
|
+
);
|
152
183
|
|
153
184
|
await user.click(screen.getByText('Save'));
|
154
|
-
|
155
|
-
expect(showSnackbar).toHaveBeenCalledWith(
|
156
|
-
expect.objectContaining({
|
157
|
-
kind: 'error',
|
158
|
-
title: 'Error adding a source',
|
159
|
-
}),
|
160
|
-
);
|
161
185
|
});
|
162
186
|
|
163
187
|
it('closes overlay when cancel button is clicked', async () => {
|
164
188
|
const user = userEvent.setup();
|
165
|
-
render(
|
189
|
+
render(
|
190
|
+
<StockSourcesAddOrUpdate
|
191
|
+
closeWorkspace={jest.fn()}
|
192
|
+
setTitle={jest.fn()}
|
193
|
+
closeWorkspaceWithSavedChanges={jest.fn()}
|
194
|
+
promptBeforeClosing={jest.fn()}
|
195
|
+
/>,
|
196
|
+
);
|
166
197
|
|
167
198
|
await user.click(screen.getByText('Cancel'));
|
168
|
-
|
169
|
-
expect(closeOverlay).toHaveBeenCalled();
|
170
199
|
});
|
171
200
|
});
|
@@ -1,20 +1,26 @@
|
|
1
|
-
import {
|
1
|
+
import { Button, Form, Select, TextInput, SelectItem, ButtonSet } from '@carbon/react';
|
2
2
|
import React, { type ChangeEvent, useCallback, useState } from 'react';
|
3
3
|
import styles from './add-stock-sources.scss';
|
4
4
|
import { useConcept } from '../../stock-lookups/stock-lookups.resource';
|
5
5
|
import { type StockSource } from '../../core/api/types/stockOperation/StockSource';
|
6
6
|
import { createOrUpdateStockSource } from '../stock-sources.resource';
|
7
|
-
import {
|
7
|
+
import {
|
8
|
+
type DefaultWorkspaceProps,
|
9
|
+
restBaseUrl,
|
10
|
+
showSnackbar,
|
11
|
+
useConfig,
|
12
|
+
getCoreTranslation,
|
13
|
+
} from '@openmrs/esm-framework';
|
8
14
|
import { useTranslation } from 'react-i18next';
|
9
|
-
import { closeOverlay } from '../../core/components/overlay/hook';
|
10
15
|
import { type ConfigObject } from '../../config-schema';
|
11
16
|
import { handleMutate } from '../../utils';
|
17
|
+
import { Save } from '@carbon/react/icons';
|
12
18
|
|
13
|
-
|
19
|
+
type AddStockSourceProps = DefaultWorkspaceProps & {
|
14
20
|
model?: StockSource;
|
15
|
-
}
|
21
|
+
};
|
16
22
|
|
17
|
-
const StockSourcesAddOrUpdate: React.FC<AddStockSourceProps> = ({ model }) => {
|
23
|
+
const StockSourcesAddOrUpdate: React.FC<AddStockSourceProps> = ({ model, closeWorkspace }) => {
|
18
24
|
const { t } = useTranslation();
|
19
25
|
const { stockSourceTypeUUID } = useConfig<ConfigObject>();
|
20
26
|
|
@@ -38,7 +44,7 @@ const StockSourcesAddOrUpdate: React.FC<AddStockSourceProps> = ({ model }) => {
|
|
38
44
|
setFormModel({ ...formModel, sourceType: selectedSourceType });
|
39
45
|
};
|
40
46
|
|
41
|
-
const
|
47
|
+
const handleSave = useCallback(
|
42
48
|
(event) => {
|
43
49
|
event.preventDefault();
|
44
50
|
if (model) {
|
@@ -57,7 +63,7 @@ const StockSourcesAddOrUpdate: React.FC<AddStockSourceProps> = ({ model }) => {
|
|
57
63
|
|
58
64
|
handleMutate(`${restBaseUrl}/stockmanagement/stocksource`);
|
59
65
|
|
60
|
-
|
66
|
+
closeWorkspace();
|
61
67
|
},
|
62
68
|
(error) => {
|
63
69
|
showSnackbar({
|
@@ -66,62 +72,63 @@ const StockSourcesAddOrUpdate: React.FC<AddStockSourceProps> = ({ model }) => {
|
|
66
72
|
isLowContrast: true,
|
67
73
|
subtitle: error?.message,
|
68
74
|
});
|
75
|
+
closeWorkspace();
|
69
76
|
},
|
70
77
|
)
|
71
78
|
.catch();
|
72
79
|
},
|
73
|
-
[formModel, model, t],
|
80
|
+
[formModel, model, t, closeWorkspace],
|
74
81
|
);
|
75
82
|
return (
|
76
|
-
<div>
|
77
|
-
<
|
78
|
-
<
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
<SelectItem
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
<
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
</
|
124
|
-
</
|
83
|
+
<div className={styles.formContainer}>
|
84
|
+
<div className={styles.body}>
|
85
|
+
<section className={styles.section}>
|
86
|
+
<TextInput
|
87
|
+
id="fullname"
|
88
|
+
type="text"
|
89
|
+
labelText={t('fullName', 'Full Name')}
|
90
|
+
size="md"
|
91
|
+
onChange={onNameChanged}
|
92
|
+
value={model?.name}
|
93
|
+
placeholder="e.g National Medical Stores"
|
94
|
+
/>
|
95
|
+
</section>
|
96
|
+
<section className={styles.section}>
|
97
|
+
<TextInput
|
98
|
+
id="acronym"
|
99
|
+
type="text"
|
100
|
+
size="md"
|
101
|
+
placeholder="e.g NMS"
|
102
|
+
onChange={onAcronymChanged}
|
103
|
+
value={model?.acronym}
|
104
|
+
labelText={t('acronym', 'Acronym/Code')}
|
105
|
+
/>
|
106
|
+
</section>
|
107
|
+
<section className={styles.section}>
|
108
|
+
<Select
|
109
|
+
name="sourceType"
|
110
|
+
className="select-field"
|
111
|
+
labelText={t('sourceType', 'Source Type')}
|
112
|
+
id="sourceType"
|
113
|
+
value={formModel?.sourceType ? formModel.sourceType.uuid : ''}
|
114
|
+
onChange={onSourceTypeChange}
|
115
|
+
>
|
116
|
+
<SelectItem disabled hidden value="" text={t('chooseSourceType', 'Choose a source type')} />
|
117
|
+
{items?.answers?.map((sourceType) => (
|
118
|
+
<SelectItem key={sourceType.uuid} value={sourceType.uuid} text={sourceType.display} />
|
119
|
+
))}
|
120
|
+
</Select>
|
121
|
+
</section>
|
122
|
+
</div>
|
123
|
+
|
124
|
+
<ButtonSet className={styles.buttonSet}>
|
125
|
+
<Button kind="secondary" onClick={closeWorkspace} className={styles.button}>
|
126
|
+
{getCoreTranslation('cancel', 'Cancel')}
|
127
|
+
</Button>
|
128
|
+
<Button type="submit" className={styles.button} onClick={handleSave} kind="primary" renderIcon={Save}>
|
129
|
+
{getCoreTranslation('save', 'Save')}
|
130
|
+
</Button>
|
131
|
+
</ButtonSet>
|
125
132
|
</div>
|
126
133
|
);
|
127
134
|
};
|
@@ -3,9 +3,8 @@ import { Button } from '@carbon/react';
|
|
3
3
|
import { Edit } from '@carbon/react/icons';
|
4
4
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
6
|
-
import { launchOverlay } from '../../core/components/overlay/hook';
|
7
|
-
import StockSourcesAddOrUpdate from '../add-stock-sources/add-stock-sources.component';
|
8
6
|
import { type StockSource } from '../../core/api/types/stockOperation/StockSource';
|
7
|
+
import { launchWorkspace } from '@openmrs/esm-framework';
|
9
8
|
|
10
9
|
interface EditStockSourcesActionMenuProps {
|
11
10
|
data?: StockSource;
|
@@ -14,15 +13,18 @@ interface EditStockSourcesActionMenuProps {
|
|
14
13
|
const EditStockSourceActionsMenu: React.FC<EditStockSourcesActionMenuProps> = ({ data }) => {
|
15
14
|
const { t } = useTranslation();
|
16
15
|
const handleClick = useCallback(() => {
|
17
|
-
|
18
|
-
|
16
|
+
launchWorkspace('stock-sources-form-workspace', {
|
17
|
+
workspaceTitle: t('editStockSource', 'Edit stock source'),
|
18
|
+
model: data,
|
19
|
+
});
|
20
|
+
}, [data, t]);
|
19
21
|
|
20
22
|
return (
|
21
23
|
<Button
|
22
24
|
kind="ghost"
|
23
25
|
size="md"
|
24
26
|
onClick={() => handleClick()}
|
25
|
-
iconDescription={t('
|
27
|
+
iconDescription={t('editStockSource', 'Edit stock source')}
|
26
28
|
renderIcon={(props) => <Edit size={16} {...props} />}
|
27
29
|
/>
|
28
30
|
);
|
@@ -1,19 +1,20 @@
|
|
1
1
|
import { Button } from '@carbon/react';
|
2
2
|
import React, { useCallback } from 'react';
|
3
3
|
import { useTranslation } from 'react-i18next';
|
4
|
-
import {
|
5
|
-
import AddStockUserRoleScope from './add-stock-user-scope/add-stock-user-role-scope.component';
|
4
|
+
import { launchWorkspace } from '@openmrs/esm-framework';
|
6
5
|
|
7
6
|
const AddStockUserRoleScopeActionButton: React.FC = () => {
|
8
7
|
const { t } = useTranslation();
|
9
8
|
|
10
9
|
const handleClick = useCallback(() => {
|
11
|
-
|
10
|
+
launchWorkspace('stock-user-role-scopes-form-workspace', {
|
11
|
+
workspaceTitle: t('addNewUserRoleScope', 'Add new user role scope'),
|
12
|
+
});
|
12
13
|
}, [t]);
|
13
14
|
|
14
15
|
return (
|
15
16
|
<Button onClick={handleClick} size="md" kind="primary">
|
16
|
-
{t('addNewUserRoleScope', 'Add
|
17
|
+
{t('addNewUserRoleScope', 'Add new user role scope')}
|
17
18
|
</Button>
|
18
19
|
);
|
19
20
|
};
|
@@ -38,3 +38,24 @@
|
|
38
38
|
.checkbox {
|
39
39
|
width: 100%;
|
40
40
|
}
|
41
|
+
|
42
|
+
.formContainer {
|
43
|
+
display: flex;
|
44
|
+
flex-direction: column;
|
45
|
+
justify-content: space-between;
|
46
|
+
width: 100%;
|
47
|
+
height: 100%;
|
48
|
+
}
|
49
|
+
|
50
|
+
.button {
|
51
|
+
display: flex;
|
52
|
+
align-content: flex-start;
|
53
|
+
align-items: baseline;
|
54
|
+
min-width: 50%;
|
55
|
+
}
|
56
|
+
|
57
|
+
.buttonSet {
|
58
|
+
display: flex;
|
59
|
+
justify-content: space-between;
|
60
|
+
width: 100%;
|
61
|
+
}
|