@digihmis/esm-administration-app 1.0.0 → 1.0.1

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.
Files changed (116) hide show
  1. package/package.json +1 -1
  2. package/release-version.js +4 -4
  3. package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.resource.ts +2 -1
  4. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-items.resource.ts +30 -7
  5. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-service.workspace.tsx +79 -107
  6. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/price.component.scss +16 -0
  7. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/price.component.tsx +30 -20
  8. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/schemas/form-schemas.ts +19 -14
  9. package/src/billing-management/billing-charge-items/billing-charge-items.component.tsx +26 -35
  10. package/src/billing-management/billing-charge-items/billing-charge-items.resource.ts +1 -1
  11. package/src/billing-management/billing-charge-items/type/index.ts +10 -10
  12. package/src/billing-management/billing-charge-items/utils/index.ts +32 -74
  13. package/src/billing-management/billing-payment-modes/billing-payment-modes.component.tsx +24 -166
  14. package/src/billing-management/billing-payment-modes/billing-payment-modes.resource.ts +24 -14
  15. package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-point.modal.tsx +1 -1
  16. package/src/billing-management/billing-payment-points/billing-payment-point.resource.ts +1 -1
  17. package/src/billing-management/billing-payment-points/billing-payment-point.scss +47 -0
  18. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.resource.ts +18 -23
  19. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-points.workspace.tsx +1 -1
  20. package/src/config-schema.ts +17 -0
  21. package/src/dashboard.meta.ts +8 -0
  22. package/src/document-branding/document-branding-workspace/document-branding.workspace.scss +34 -0
  23. package/src/document-branding/document-branding-workspace/document-branding.workspace.tsx +160 -0
  24. package/src/document-branding/document-branding.component.tsx +185 -0
  25. package/src/document-branding/document-branding.resource.ts +54 -0
  26. package/src/document-branding/document-branding.scss +69 -0
  27. package/src/index.ts +15 -9
  28. package/src/routes.json +34 -13
  29. package/dist/101.js +0 -1
  30. package/dist/101.js.map +0 -1
  31. package/dist/117.js +0 -1
  32. package/dist/117.js.map +0 -1
  33. package/dist/132.js +0 -1
  34. package/dist/132.js.map +0 -1
  35. package/dist/15.js +0 -1
  36. package/dist/15.js.map +0 -1
  37. package/dist/152.js +0 -1
  38. package/dist/152.js.map +0 -1
  39. package/dist/153.js +0 -1
  40. package/dist/153.js.map +0 -1
  41. package/dist/190.js +0 -1
  42. package/dist/190.js.map +0 -1
  43. package/dist/209.js +0 -1
  44. package/dist/209.js.map +0 -1
  45. package/dist/266.js +0 -1
  46. package/dist/266.js.map +0 -1
  47. package/dist/317.js +0 -1
  48. package/dist/317.js.map +0 -1
  49. package/dist/349.js +0 -1
  50. package/dist/349.js.map +0 -1
  51. package/dist/371.js +0 -1
  52. package/dist/371.js.map +0 -1
  53. package/dist/378.js +0 -1
  54. package/dist/378.js.map +0 -1
  55. package/dist/394.js +0 -1
  56. package/dist/394.js.map +0 -1
  57. package/dist/442.js +0 -1
  58. package/dist/442.js.map +0 -1
  59. package/dist/45.js +0 -1
  60. package/dist/45.js.map +0 -1
  61. package/dist/454.js +0 -1
  62. package/dist/454.js.map +0 -1
  63. package/dist/466.js +0 -1
  64. package/dist/466.js.map +0 -1
  65. package/dist/482.js +0 -1
  66. package/dist/482.js.map +0 -1
  67. package/dist/501.js +0 -1
  68. package/dist/501.js.map +0 -1
  69. package/dist/508.js +0 -1
  70. package/dist/508.js.map +0 -1
  71. package/dist/578.js +0 -1
  72. package/dist/578.js.map +0 -1
  73. package/dist/598.js +0 -1
  74. package/dist/598.js.map +0 -1
  75. package/dist/606.js +0 -1
  76. package/dist/606.js.map +0 -1
  77. package/dist/61.js +0 -1
  78. package/dist/61.js.map +0 -1
  79. package/dist/640.js +0 -1
  80. package/dist/640.js.map +0 -1
  81. package/dist/685.js +0 -1
  82. package/dist/685.js.map +0 -1
  83. package/dist/689.js +0 -1
  84. package/dist/689.js.map +0 -1
  85. package/dist/709.js +0 -1
  86. package/dist/709.js.map +0 -1
  87. package/dist/712.js +0 -1
  88. package/dist/712.js.map +0 -1
  89. package/dist/720.js +0 -1
  90. package/dist/720.js.map +0 -1
  91. package/dist/737.js +0 -12
  92. package/dist/737.js.map +0 -1
  93. package/dist/742.js +0 -1
  94. package/dist/742.js.map +0 -1
  95. package/dist/747.js +0 -1
  96. package/dist/747.js.map +0 -1
  97. package/dist/771.js +0 -1
  98. package/dist/771.js.map +0 -1
  99. package/dist/806.js +0 -1
  100. package/dist/806.js.map +0 -1
  101. package/dist/912.js +0 -1
  102. package/dist/912.js.map +0 -1
  103. package/dist/913.js +0 -1
  104. package/dist/913.js.map +0 -1
  105. package/dist/916.js +0 -15
  106. package/dist/916.js.map +0 -1
  107. package/dist/940.js +0 -1
  108. package/dist/940.js.map +0 -1
  109. package/dist/digihmis-esm-administration-app.js +0 -6
  110. package/dist/digihmis-esm-administration-app.js.buildmanifest.json +0 -1100
  111. package/dist/digihmis-esm-administration-app.js.map +0 -1
  112. package/dist/main.js +0 -17
  113. package/dist/main.js.map +0 -1
  114. package/dist/routes.json +0 -1
  115. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-item.workspace.tsx +0 -212
  116. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/stock-search.component.tsx +0 -107
@@ -0,0 +1,34 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+
4
+ .form {
5
+ display: flex;
6
+ flex-direction: column;
7
+ justify-content: space-between;
8
+ height: 100%;
9
+ }
10
+
11
+ .formContainer {
12
+ margin: layout.$spacing-05;
13
+ }
14
+
15
+ .tablet {
16
+ padding: layout.$spacing-06 layout.$spacing-05;
17
+ background-color: colors.$white;
18
+ }
19
+
20
+ .desktop {
21
+ padding: 0;
22
+ }
23
+
24
+ .logoPreview {
25
+ display: block;
26
+ max-height: 4rem;
27
+ max-width: 12rem;
28
+ margin-bottom: layout.$spacing-03;
29
+ object-fit: contain;
30
+ }
31
+
32
+ .loading {
33
+ margin: layout.$spacing-07;
34
+ }
@@ -0,0 +1,160 @@
1
+ import React, { useEffect } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, ButtonSet, Form, FormGroup, FileUploader, InlineLoading, Stack, TextArea, TextInput } from '@carbon/react';
4
+ import { Controller, useForm } from 'react-hook-form';
5
+ import classNames from 'classnames';
6
+ import { mutate } from 'swr';
7
+ import { type DefaultWorkspaceProps, ResponsiveWrapper, showSnackbar, useLayoutType } from '@openmrs/esm-framework';
8
+ import { facilityInfoUrl, type FacilityInfo, saveFacilityInfo, useFacilityInfo } from '../document-branding.resource';
9
+ import styles from './document-branding.workspace.scss';
10
+
11
+ const DocumentBrandingWorkspace: React.FC<DefaultWorkspaceProps> = ({
12
+ closeWorkspace,
13
+ closeWorkspaceWithSavedChanges,
14
+ promptBeforeClosing,
15
+ }) => {
16
+ const { t } = useTranslation();
17
+ const isTablet = useLayoutType() === 'tablet';
18
+ const { info, settingUuid, isLoading } = useFacilityInfo();
19
+
20
+ const { control, handleSubmit, reset, setValue, watch, formState: { isDirty, isSubmitting } } = useForm<FacilityInfo>({
21
+ defaultValues: {},
22
+ });
23
+
24
+ // Prefill once the stored value has loaded.
25
+ useEffect(() => {
26
+ if (!isLoading) {
27
+ reset(info);
28
+ }
29
+ // eslint-disable-next-line react-hooks/exhaustive-deps
30
+ }, [isLoading, settingUuid]);
31
+
32
+ useEffect(() => {
33
+ promptBeforeClosing(() => isDirty);
34
+ }, [isDirty, promptBeforeClosing]);
35
+
36
+ const logoData = watch('logoData');
37
+
38
+ const onLogo = (event: React.ChangeEvent<HTMLInputElement>) => {
39
+ const file = event.target.files?.[0];
40
+ if (!file) {
41
+ return;
42
+ }
43
+ const reader = new FileReader();
44
+ reader.onload = () => setValue('logoData', String(reader.result), { shouldDirty: true });
45
+ reader.readAsDataURL(file);
46
+ };
47
+
48
+ const onSubmit = async (data: FacilityInfo) => {
49
+ if (!settingUuid) {
50
+ showSnackbar({ kind: 'error', title: t('settingMissing', 'Print module setting not found — is it installed?') });
51
+ return;
52
+ }
53
+ try {
54
+ await saveFacilityInfo(settingUuid, data);
55
+ await mutate(facilityInfoUrl);
56
+ showSnackbar({ kind: 'success', isLowContrast: true, title: t('brandingSaved', 'Document letterhead saved') });
57
+ closeWorkspaceWithSavedChanges();
58
+ } catch (err) {
59
+ showSnackbar({
60
+ kind: 'error',
61
+ title: t('brandingError', 'Could not save the letterhead'),
62
+ subtitle: err?.responseBody?.error?.message ?? err?.message,
63
+ });
64
+ }
65
+ };
66
+
67
+ if (isLoading) {
68
+ return <InlineLoading className={styles.loading} description={t('loading', 'Loading…')} />;
69
+ }
70
+
71
+ return (
72
+ <Form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
73
+ <div className={styles.formContainer}>
74
+ <Stack gap={5}>
75
+ <Controller
76
+ name="facilityName"
77
+ control={control}
78
+ render={({ field }) => (
79
+ <ResponsiveWrapper>
80
+ <TextInput id="facilityName" labelText={t('facilityName', 'Facility name')} {...field} value={field.value ?? ''} />
81
+ </ResponsiveWrapper>
82
+ )}
83
+ />
84
+ <Controller
85
+ name="facilityTagline"
86
+ control={control}
87
+ render={({ field }) => (
88
+ <ResponsiveWrapper>
89
+ <TextInput id="facilityTagline" labelText={t('tagline', 'Tagline')} {...field} value={field.value ?? ''} />
90
+ </ResponsiveWrapper>
91
+ )}
92
+ />
93
+ <Controller
94
+ name="phone"
95
+ control={control}
96
+ render={({ field }) => (
97
+ <ResponsiveWrapper>
98
+ <TextInput id="phone" labelText={t('phone', 'Phone')} {...field} value={field.value ?? ''} />
99
+ </ResponsiveWrapper>
100
+ )}
101
+ />
102
+ <Controller
103
+ name="email"
104
+ control={control}
105
+ render={({ field }) => (
106
+ <ResponsiveWrapper>
107
+ <TextInput id="email" labelText={t('email', 'Email')} {...field} value={field.value ?? ''} />
108
+ </ResponsiveWrapper>
109
+ )}
110
+ />
111
+ <Controller
112
+ name="website"
113
+ control={control}
114
+ render={({ field }) => (
115
+ <ResponsiveWrapper>
116
+ <TextInput id="website" labelText={t('website', 'Website')} {...field} value={field.value ?? ''} />
117
+ </ResponsiveWrapper>
118
+ )}
119
+ />
120
+ <Controller
121
+ name="address"
122
+ control={control}
123
+ render={({ field }) => (
124
+ <ResponsiveWrapper>
125
+ <TextArea id="address" labelText={t('address', 'Address')} rows={2} {...field} value={field.value ?? ''} />
126
+ </ResponsiveWrapper>
127
+ )}
128
+ />
129
+
130
+ <FormGroup legendText={t('logo', 'Logo')}>
131
+ {logoData && <img src={logoData} alt={t('logoPreview', 'Logo preview')} className={styles.logoPreview} />}
132
+ <FileUploader
133
+ accept={['.png', '.jpg', '.jpeg']}
134
+ buttonLabel={t('uploadLogo', 'Upload logo')}
135
+ labelDescription={t('logoHint', 'PNG or JPG; shown top-left on documents.')}
136
+ filenameStatus="edit"
137
+ onChange={onLogo}
138
+ onDelete={() => setValue('logoData', undefined, { shouldDirty: true })}
139
+ />
140
+ </FormGroup>
141
+ </Stack>
142
+ </div>
143
+
144
+ <ButtonSet className={classNames({ [styles.tablet]: isTablet, [styles.desktop]: !isTablet })}>
145
+ <Button style={{ maxWidth: '50%' }} kind="secondary" onClick={() => closeWorkspace()}>
146
+ {t('cancel', 'Cancel')}
147
+ </Button>
148
+ <Button style={{ maxWidth: '50%' }} kind="primary" type="submit" disabled={isSubmitting || !isDirty}>
149
+ {isSubmitting ? (
150
+ <InlineLoading description={t('saving', 'Saving…')} />
151
+ ) : (
152
+ t('saveAndClose', 'Save & close')
153
+ )}
154
+ </Button>
155
+ </ButtonSet>
156
+ </Form>
157
+ );
158
+ };
159
+
160
+ export default DocumentBrandingWorkspace;
@@ -0,0 +1,185 @@
1
+ import React, { useMemo, useState } from 'react';
2
+ import {
3
+ Button,
4
+ DataTable,
5
+ DataTableSkeleton,
6
+ Layer,
7
+ Pagination,
8
+ Table,
9
+ TableBody,
10
+ TableCell,
11
+ TableContainer,
12
+ TableHead,
13
+ TableHeader,
14
+ TableRow,
15
+ Tile,
16
+ } from '@carbon/react';
17
+ import { Edit } from '@carbon/react/icons';
18
+ import { launchWorkspace, useLayoutType, useConfig, ErrorState } from '@openmrs/esm-framework';
19
+ import { useTranslation } from 'react-i18next';
20
+ import { CardHeader } from '@openmrs/esm-patient-common-lib';
21
+ import { type ConfigObject } from '../config-schema';
22
+ import { CustomPageHeader } from '../components/custom-page-header/custom-page-header.component';
23
+ import styles from './document-branding.scss';
24
+ import { useFacilityInfo } from './document-branding.resource';
25
+
26
+ /**
27
+ * Admin page for the document letterhead — the facility identity (name, tagline, contacts, address)
28
+ * and logo shown on every generated PDF. It lists the stored value and launches a workspace to edit it,
29
+ * writing to the print module's global property so no one has to hand-edit JSON.
30
+ */
31
+ const DocumentBrandingDashboard = () => {
32
+ const { t } = useTranslation();
33
+ const layout = useLayoutType();
34
+ const isTablet = layout === 'tablet';
35
+ const responsiveSize = isTablet ? 'lg' : 'sm';
36
+ const { documentBrandingIcon } = useConfig<ConfigObject>();
37
+
38
+ const { info, isLoading, error } = useFacilityInfo();
39
+
40
+ const headers = [
41
+ { key: 'field', header: t('field', 'Field') },
42
+ { key: 'value', header: t('value', 'Value') },
43
+ ];
44
+
45
+ const fields = useMemo(
46
+ () => [
47
+ { key: 'facilityName', label: t('facilityName', 'Facility name'), value: info.facilityName },
48
+ { key: 'facilityTagline', label: t('tagline', 'Tagline'), value: info.facilityTagline },
49
+ { key: 'phone', label: t('phone', 'Phone'), value: info.phone },
50
+ { key: 'email', label: t('email', 'Email'), value: info.email },
51
+ { key: 'website', label: t('website', 'Website'), value: info.website },
52
+ { key: 'address', label: t('address', 'Address'), value: info.address },
53
+ ],
54
+ [info, t],
55
+ );
56
+
57
+ const hasLogo = Boolean(info.logoData || info.logoPath);
58
+
59
+ const tableRows = useMemo(() => {
60
+ const rows = fields
61
+ .filter((field) => field.value)
62
+ .map((field) => ({ id: field.key, field: field.label, value: field.value as React.ReactNode }));
63
+ if (hasLogo) {
64
+ rows.push({
65
+ id: 'logo',
66
+ field: t('logo', 'Logo'),
67
+ value: (
68
+ <img
69
+ src={info.logoData ?? info.logoPath}
70
+ alt={t('logoPreview', 'Logo preview')}
71
+ className={styles.logoPreview}
72
+ />
73
+ ),
74
+ });
75
+ }
76
+ return rows;
77
+ }, [fields, hasLogo, info.logoData, info.logoPath, t]);
78
+
79
+ const hasBranding = tableRows.length > 0;
80
+
81
+ const [currentPage, setCurrentPage] = useState(1);
82
+ const [currentPageSize, setCurrentPageSize] = useState(10);
83
+ const pageSizes = [10, 20, 30, 40, 50];
84
+
85
+ const paginatedRows = useMemo(() => {
86
+ const startIndex = (currentPage - 1) * currentPageSize;
87
+ return tableRows.slice(startIndex, startIndex + currentPageSize);
88
+ }, [tableRows, currentPage, currentPageSize]);
89
+
90
+ const handleConfigure = () => {
91
+ launchWorkspace('document-branding-workspace', {
92
+ workspaceTitle: t('configureLetterhead', 'Configure letterhead'),
93
+ });
94
+ };
95
+
96
+ const renderBody = () => {
97
+ if (isLoading) {
98
+ return <DataTableSkeleton role="progressbar" compact={!isTablet} zebra />;
99
+ }
100
+ if (error) {
101
+ return <ErrorState error={error} headerTitle={t('facilityLetterhead', 'Facility letterhead')} />;
102
+ }
103
+ return (
104
+ <Layer>
105
+ <DataTable rows={paginatedRows} headers={headers} size={responsiveSize} useZebraStyles>
106
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps }) => (
107
+ <TableContainer>
108
+ <Table {...getTableProps()} aria-label={t('facilityLetterheadTable', 'Facility letterhead table')}>
109
+ <TableHead>
110
+ <TableRow>
111
+ {headers.map((header) => (
112
+ <TableHeader key={header.key} {...getHeaderProps({ header })}>
113
+ {header.header}
114
+ </TableHeader>
115
+ ))}
116
+ </TableRow>
117
+ </TableHead>
118
+ <TableBody>
119
+ {rows.map((row) => (
120
+ <TableRow key={row.id} {...getRowProps({ row })}>
121
+ {row.cells.map((cell) => (
122
+ <TableCell key={cell.id}>{cell.value}</TableCell>
123
+ ))}
124
+ </TableRow>
125
+ ))}
126
+ </TableBody>
127
+ </Table>
128
+ {!hasBranding ? (
129
+ <div className={styles.tileContainer}>
130
+ <Tile className={styles.tile}>
131
+ <div className={styles.tileContent}>
132
+ <p className={styles.content}>{t('noLetterhead', 'No Facility letterhead configured yet')}</p>
133
+ <p className={styles.emptyStateHelperText}>
134
+ {t(
135
+ 'noLetterheadHelp',
136
+ 'Add the facility name, contacts and logo to brand generated documents.',
137
+ )}
138
+ </p>
139
+ </div>
140
+ </Tile>
141
+ </div>
142
+ ) : null}
143
+ {hasBranding && (
144
+ <Pagination
145
+ forwardText={t('nextPage', 'Next page')}
146
+ backwardText={t('previousPage', 'Previous page')}
147
+ page={currentPage}
148
+ pageSize={currentPageSize}
149
+ pageSizes={pageSizes}
150
+ totalItems={tableRows.length}
151
+ className={styles.pagination}
152
+ onChange={({ pageSize, page }) => {
153
+ if (pageSize !== currentPageSize) {
154
+ setCurrentPageSize(pageSize);
155
+ setCurrentPage(1);
156
+ }
157
+ if (page !== currentPage) {
158
+ setCurrentPage(page);
159
+ }
160
+ }}
161
+ />
162
+ )}
163
+ </TableContainer>
164
+ )}
165
+ </DataTable>
166
+ </Layer>
167
+ );
168
+ };
169
+
170
+ return (
171
+ <>
172
+ <CustomPageHeader subTitle={t('facilityBranding', 'Facility branding')} iconSrc={documentBrandingIcon?.src} />
173
+ <div className={styles.section}>
174
+ <CardHeader title={t('facilityLetterhead', 'Facility letterhead')}>
175
+ <Button kind="ghost" renderIcon={(props) => <Edit size={16} {...props} />} onClick={handleConfigure}>
176
+ {hasBranding ? t('editLetterhead', 'Edit letterhead') : t('configureLetterhead', 'Configure letterhead')}
177
+ </Button>
178
+ </CardHeader>
179
+ {renderBody()}
180
+ </div>
181
+ </>
182
+ );
183
+ };
184
+
185
+ export default DocumentBrandingDashboard;
@@ -0,0 +1,54 @@
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+
4
+ /** The global property the print module reads for the document letterhead. */
5
+ export const facilityInfoGp = 'digihmisprint.facilityInformation';
6
+
7
+ /** SWR key for the stored letterhead — exported so the workspace can revalidate the dashboard after saving. */
8
+ export const facilityInfoUrl = `${restBaseUrl}/systemsetting/${facilityInfoGp}?v=custom:(uuid,value)`;
9
+
10
+ export interface FacilityInfo {
11
+ facilityName?: string;
12
+ facilityTagline?: string;
13
+ phone?: string;
14
+ email?: string;
15
+ website?: string;
16
+ address?: string;
17
+ /** Logo as a base64 / data-URI string (from the upload). */
18
+ logoData?: string;
19
+ /** Or a server file path, as an alternative to an uploaded logo. */
20
+ logoPath?: string;
21
+ }
22
+
23
+ /** The stored letterhead (parsed from the GP JSON) plus the setting uuid needed to save it. */
24
+ export const useFacilityInfo = () => {
25
+ const { data, error, isLoading, mutate } = useSWR<{ data: { uuid: string; value?: string } }>(
26
+ facilityInfoUrl,
27
+ openmrsFetch,
28
+ );
29
+ let info: FacilityInfo = {};
30
+ const raw = data?.data?.value;
31
+ if (raw) {
32
+ try {
33
+ info = JSON.parse(raw);
34
+ } catch {
35
+ info = {};
36
+ }
37
+ }
38
+ return { info, settingUuid: data?.data?.uuid, isLoading, error, mutate };
39
+ };
40
+
41
+ /** Save the letterhead back to the global property as JSON (dropping blank fields). */
42
+ export const saveFacilityInfo = (settingUuid: string, info: FacilityInfo) => {
43
+ const cleaned: Record<string, string> = {};
44
+ Object.entries(info).forEach(([key, value]) => {
45
+ if (value != null && String(value).trim() !== '') {
46
+ cleaned[key] = String(value).trim();
47
+ }
48
+ });
49
+ return openmrsFetch(`${restBaseUrl}/systemsetting/${settingUuid}`, {
50
+ method: 'POST',
51
+ headers: { 'Content-Type': 'application/json' },
52
+ body: { value: JSON.stringify(cleaned) },
53
+ });
54
+ };
@@ -0,0 +1,69 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@carbon/colors';
4
+
5
+ .dashboardContainer {
6
+ display: flex;
7
+ flex-direction: column;
8
+ }
9
+
10
+ .section {
11
+ margin-bottom: layout.$spacing-07;
12
+ padding: layout.$spacing-05;
13
+ background-color: colors.$gray-10;
14
+
15
+
16
+ &:last-child {
17
+ margin-bottom: 0;
18
+ }
19
+ }
20
+
21
+ .subhead {
22
+ @include type.type-style('body-01');
23
+ color: colors.$gray-70;
24
+ margin-bottom: layout.$spacing-05;
25
+ }
26
+
27
+ .logoPreview {
28
+ display: block;
29
+ max-height: 4rem;
30
+ max-width: 12rem;
31
+ margin-bottom: layout.$spacing-05;
32
+ object-fit: contain;
33
+ }
34
+
35
+ .tileContainer {
36
+ border-top: 1px solid colors.$gray-20;
37
+ padding: 3rem 0;
38
+ }
39
+
40
+ .tile {
41
+ margin: auto;
42
+ width: fit-content;
43
+ background: colors.$gray-20;
44
+ }
45
+
46
+ .tileContent {
47
+ display: flex;
48
+ flex-direction: column;
49
+ align-items: center;
50
+ }
51
+
52
+ .content {
53
+ @include type.type-style('heading-compact-02');
54
+ color: colors.$gray-70;
55
+ margin-bottom: layout.$spacing-03;
56
+ }
57
+
58
+ .emptyStateHelperText {
59
+ @include type.type-style('body-compact-01');
60
+ color: colors.$gray-70;
61
+ }
62
+
63
+ .pagination {
64
+ overflow: hidden;
65
+
66
+ &:global(.cds--pagination) {
67
+ border-top: none;
68
+ }
69
+ }
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import { createDashboardLink } from './left-panel/left-panel.component';
4
4
  import {
5
5
  bedManagementDashboardMeta,
6
6
  billingManagementDashboardMeta,
7
+ documentBrandingDashboardMeta,
7
8
  formBuilderDashboardMeta,
8
9
  locationManagementDashboardMeta,
9
10
  queueManagementDashboardMeta,
@@ -15,6 +16,7 @@ import BedManagementDashboard from './bed-management/bed-management.component';
15
16
  import FormBuilderDashboard from './form-builder/form-builder.component';
16
17
  import BillingManagementDashboard from './billing-management/billing-management.component';
17
18
  import SystemInfoDashboard from './system-info/system-info.component';
19
+ import DocumentBrandingDashboard from './document-branding/document-branding.component';
18
20
  import DeletePaymentModeModal from './billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal';
19
21
  import DeletePaymentPointModal from './billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-point.modal';
20
22
  import DeleteBillableServiceModal from './billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.modal';
@@ -35,6 +37,10 @@ export const bedLeftPanelLink = getSyncLifecycle(createDashboardLink(bedManageme
35
37
  export const formBuilderLeftPanelLink = getSyncLifecycle(createDashboardLink(formBuilderDashboardMeta), options);
36
38
  export const billingLeftPanelLink = getSyncLifecycle(createDashboardLink(billingManagementDashboardMeta), options);
37
39
  export const systemInfoLeftPanelLink = getSyncLifecycle(createDashboardLink(systemInfoDashboardMeta), options);
40
+ export const documentBrandingLeftPanelLink = getSyncLifecycle(
41
+ createDashboardLink(documentBrandingDashboardMeta),
42
+ options,
43
+ );
38
44
 
39
45
  export const queueManagementDashboard = getSyncLifecycle(QueueManagementDashboard, options);
40
46
  export const locationManagementDashboard = getSyncLifecycle(LocationManagementDashboard, options);
@@ -42,6 +48,7 @@ export const bedManagementDashboard = getSyncLifecycle(BedManagementDashboard, o
42
48
  export const formBuilderDashboard = getSyncLifecycle(FormBuilderDashboard, options);
43
49
  export const billingManagementDashboard = getSyncLifecycle(BillingManagementDashboard, options);
44
50
  export const systemInfoDashboard = getSyncLifecycle(SystemInfoDashboard, options);
51
+ export const documentBrandingDashboard = getSyncLifecycle(DocumentBrandingDashboard, options);
45
52
 
46
53
  // t('addNewQueueService', 'Add New Queue Service')
47
54
  export const addNewQueueServiceWorkspace = getAsyncLifecycle(
@@ -103,22 +110,21 @@ export const paymentPointWorkspace = getAsyncLifecycle(
103
110
  },
104
111
  );
105
112
 
106
- // t('addCommodityItem', 'Add Commodity Item')
107
- export const commodityForm = getAsyncLifecycle(
113
+ // t('addServiceItem', 'Add Charge Service')
114
+ export const billableServiceForm = getAsyncLifecycle(
108
115
  () =>
109
- import('./billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-item.workspace'),
116
+ import('./billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-service.workspace'),
110
117
  {
111
- featureName: 'billing-charge-item-workspace',
118
+ featureName: 'billing-charge-service-workspace',
112
119
  moduleName,
113
120
  },
114
121
  );
115
122
 
116
- // t('addServiceItem', 'Add Charge Service')
117
- export const billableServiceForm = getAsyncLifecycle(
118
- () =>
119
- import('./billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-service.workspace'),
123
+ // t('configureLetterhead', 'Configure letterhead')
124
+ export const documentBrandingWorkspace = getAsyncLifecycle(
125
+ () => import('./document-branding/document-branding-workspace/document-branding.workspace'),
120
126
  {
121
- featureName: 'billing-charge-service-workspace',
127
+ featureName: 'document-branding-workspace',
122
128
  moduleName,
123
129
  },
124
130
  );
package/src/routes.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.openmrs.org/routes.schema.json",
3
3
  "backendDependencies": {
4
4
  "fhir2": ">=1.2",
5
- "webservices.rest": "^2.24.0"
5
+ "webservices.rest": ">=2.24.0"
6
6
  },
7
7
  "extensions": [
8
8
  {
@@ -65,6 +65,16 @@
65
65
  "title": "Billing Management"
66
66
  }
67
67
  },
68
+ {
69
+ "name": "document-branding-dashboard-link",
70
+ "slot": "administration-dashboard-slot",
71
+ "component": "documentBrandingLeftPanelLink",
72
+ "meta": {
73
+ "name": "document-branding",
74
+ "slot": "document-branding-homepage-dashboard-slot",
75
+ "title": "Document Branding"
76
+ }
77
+ },
68
78
  {
69
79
  "name": "queue-management-dashboard-content",
70
80
  "slot": "queue-management-homepage-dashboard-slot",
@@ -94,10 +104,15 @@
94
104
  "name": "system-info-management-dashboard-content",
95
105
  "slot": "system-info-management-homepage-dashboard-slot",
96
106
  "component": "systemInfoDashboard"
107
+ },
108
+ {
109
+ "name": "document-branding-dashboard-content",
110
+ "slot": "document-branding-homepage-dashboard-slot",
111
+ "component": "documentBrandingDashboard"
97
112
  }
98
113
  ],
99
114
  "workspaces": [
100
- {
115
+ {
101
116
  "name": "service-queues-service-form",
102
117
  "title": "addNewQueueService",
103
118
  "component": "addNewQueueServiceWorkspace",
@@ -108,36 +123,42 @@
108
123
  "title": "addNewQueueServiceRoom",
109
124
  "component": "addNewQueueServiceRoomWorkspace",
110
125
  "type": "service-queues"
111
- },{
126
+ },
127
+ {
112
128
  "name": "add-location-workspace",
113
129
  "title": "addNewLocationWorkspace",
114
130
  "component": "addNewLocationWorkspace",
115
131
  "type": "location-management"
116
- },{
132
+ },
133
+ {
117
134
  "name": "search-location-workspace",
118
135
  "title": "searchLocationWorkspace",
119
136
  "component": "searchLocationWorkspace",
120
137
  "type": "location-management"
121
- },{
138
+ },
139
+ {
122
140
  "name": "payment-mode-workspace",
123
141
  "title": "paymentModeWorkspace",
124
142
  "component": "paymentModeWorkspace",
125
143
  "type": "billing-management"
126
- },{
144
+ },
145
+ {
127
146
  "name": "payment-point-workspace",
128
147
  "title": "paymentPointWorkspace",
129
148
  "component": "paymentPointWorkspace",
130
149
  "type": "billing-management"
131
- },{
150
+ },
151
+ {
132
152
  "name": "billing-charge-service-workspace",
133
153
  "title": "addServiceItem",
134
154
  "component": "billableServiceForm",
135
155
  "type": "billing-management"
136
- },{
137
- "name": "billing-charge-item-workspace",
138
- "title": "addCommodityItem",
139
- "component": "commodityForm",
140
- "type": "billing-management"
156
+ },
157
+ {
158
+ "name": "document-branding-workspace",
159
+ "title": "configureLetterhead",
160
+ "component": "documentBrandingWorkspace",
161
+ "type": "document-branding"
141
162
  }
142
163
  ],
143
164
  "modals": [
@@ -154,4 +175,4 @@
154
175
  "component": "deleteBillableService"
155
176
  }
156
177
  ]
157
- }
178
+ }