ui-soxo-bootstrap-core 2.6.40-dev.17 → 2.6.40

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 (27) hide show
  1. package/DEVELOPER_GUIDE.md +9 -38
  2. package/core/components/index.js +11 -2
  3. package/core/components/landing-api/landing-api.js +5 -165
  4. package/core/lib/components/global-header/global-header.js +77 -20
  5. package/core/lib/components/index.js +2 -2
  6. package/core/lib/components/sidemenu/sidemenu.js +147 -66
  7. package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +24 -91
  8. package/core/lib/models/menus/components/menu-add/menu-add.js +2 -2
  9. package/core/lib/modules/generic/generic-list/ExportReactCSV.js +8 -334
  10. package/core/lib/modules/generic/generic-list/generic-list.scss +0 -34
  11. package/core/models/core-scripts/core-scripts.js +1 -22
  12. package/core/models/menus/components/menu-add/menu-add.js +4 -31
  13. package/core/models/menus/components/menu-lists/menu-lists.js +12 -75
  14. package/core/models/menus/menus.js +1 -29
  15. package/core/models/roles/components/role-add/role-add.js +169 -54
  16. package/core/models/roles/components/role-list/role-list.js +0 -20
  17. package/core/models/roles/roles.js +0 -3
  18. package/core/models/users/components/assign-role/assign-role.js +8 -23
  19. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +5 -202
  20. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +0 -73
  21. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +35 -56
  22. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +0 -1
  23. package/package.json +1 -1
  24. package/core/components/license-management/license-alert.js +0 -97
  25. package/core/models/roles/components/role-add/menu-label.js +0 -14
  26. package/core/models/roles/components/role-add/menu-tree.js +0 -127
  27. package/core/modules/reporting/components/reporting-dashboard/reporting-table.js +0 -519
@@ -6,62 +6,24 @@
6
6
  * @param {Array<{ label: string, key: string }>} [headers] - Optional column headers and field mappings.
7
7
  * @param {string} [fileName='Report.xlsx'] - Optional name for the downloaded Excel file.
8
8
  */
9
-
10
- import React, { useState } from 'react';
9
+
10
+ import React from 'react';
11
11
  // Import XLSX library to handle Excel file creation
12
12
  import * as XLSX from 'xlsx';
13
- import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
14
13
  // import * as XLSX from 'xlsx-js-style';
15
14
  // import * as XLSX from 'xlsx-js-style';
16
15
  // Import saveAs from file-saver to trigger file download in browser
17
16
  import { saveAs } from 'file-saver';
18
- import { Button, Dropdown, Form, Input, Menu, Modal, Radio, message } from 'antd';
19
- import { DownOutlined, FileExcelFilled, FilePdfFilled, MailFilled, DownloadOutlined } from '@ant-design/icons';
17
+ import { Button } from 'antd';
20
18
  import { Trans } from 'react-i18next';
21
- import { CoreScripts } from '../../../../models';
22
- import './generic-list.scss';
23
-
24
- const normalizeScriptId = (value) => {
25
- if (value === undefined || value === null || value === '') return value;
26
-
27
- const numberValue = Number(value);
28
- return Number.isNaN(numberValue) ? value : numberValue;
29
- };
30
-
31
- const getRecipients = (value) => {
32
- if (Array.isArray(value)) return value.filter(Boolean);
33
-
34
- return String(value || '')
35
- .split(/[\n,;]+/)
36
- .map((email) => email.trim())
37
- .filter(Boolean);
38
- };
39
-
40
-
41
- export const ExportReactCSV = ({
42
- csvData,
43
- headers,
44
- fileName,
45
- pdfFileName,
46
- title,
47
- format = 'excel',
48
- buttonText,
49
- dropdown = false,
50
- onSendReportToMail,
51
- scriptId,
52
- inputParameters,
53
- }) => {
54
- const [mailModalVisible, setMailModalVisible] = useState(false);
55
- const [sendingMail, setSendingMail] = useState(false);
56
- const [selectedFormat, setSelectedFormat] = useState('excel');
57
- const [mailForm] = Form.useForm();
58
19
 
20
+ export const ExportReactCSV = ({ csvData, headers, fileName,title }) => {
59
21
  /**
60
22
  * exportToExcel function
61
23
  * Triggered on button click, generates and downloads an Excel file
62
24
  */
63
25
 
64
- const exportToExcel = (downloadFileName) => {
26
+ const exportToExcel = () => {
65
27
  // if (!csvData?.length) return;
66
28
 
67
29
  let worksheet;
@@ -113,302 +75,14 @@ export const ExportReactCSV = ({
113
75
  const blob = new Blob([excelBuffer], {
114
76
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
115
77
  });
116
- const flName = downloadFileName || fileName || 'Report.xlsx';
78
+ const flName = fileName || 'Report.xlsx';
117
79
  // Trigger download using file-saver
118
80
  saveAs(blob, flName);
119
81
  };
120
-
121
- const exportToPdf = async (downloadFileName) => {
122
- const pdfDoc = await PDFDocument.create();
123
- const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
124
- const boldFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
125
- const pageSize = [842, 595];
126
- const margin = 30;
127
- const rowHeight = 20;
128
- const titleHeight = 38;
129
- const fontSize = 8;
130
- const headerFontSize = 8;
131
- const headersToUse = headers?.length
132
- ? headers
133
- : Object.keys(csvData?.[0] || {}).map((key) => ({ label: key, key }));
134
- const availableWidth = pageSize[0] - margin * 2;
135
- const columnWidth = headersToUse.length ? availableWidth / headersToUse.length : availableWidth;
136
- let page;
137
- let y;
138
-
139
- const sanitizeValue = (value) => {
140
- if (value === undefined || value === null) return '';
141
- if (typeof value === 'object') return JSON.stringify(value);
142
- return String(value);
143
- };
144
-
145
- const fitText = (text, width, textFont, size) => {
146
- const sanitizedText = sanitizeValue(text);
147
- if (textFont.widthOfTextAtSize(sanitizedText, size) <= width) return sanitizedText;
148
-
149
- let fittedText = sanitizedText;
150
- while (fittedText.length && textFont.widthOfTextAtSize(`${fittedText}...`, size) > width) {
151
- fittedText = fittedText.slice(0, -1);
152
- }
153
- return fittedText ? `${fittedText}...` : '';
154
- };
155
-
156
- const addPage = () => {
157
- page = pdfDoc.addPage(pageSize);
158
- y = pageSize[1] - margin;
159
-
160
- page.drawText(title || 'Report', {
161
- x: margin,
162
- y,
163
- size: 14,
164
- font: boldFont,
165
- color: rgb(0.1, 0.1, 0.1),
166
- });
167
-
168
- y -= titleHeight;
169
-
170
- headersToUse.forEach((header, index) => {
171
- const x = margin + index * columnWidth;
172
- page.drawRectangle({
173
- x,
174
- y: y - 5,
175
- width: columnWidth,
176
- height: rowHeight,
177
- color: rgb(0.92, 0.94, 0.96),
178
- borderColor: rgb(0.72, 0.75, 0.78),
179
- borderWidth: 0.5,
180
- });
181
- page.drawText(fitText(header.label, columnWidth - 8, boldFont, headerFontSize), {
182
- x: x + 4,
183
- y: y + 1,
184
- size: headerFontSize,
185
- font: boldFont,
186
- color: rgb(0.1, 0.1, 0.1),
187
- });
188
- });
189
-
190
- y -= rowHeight;
191
- };
192
-
193
- addPage();
194
-
195
- (csvData || []).forEach((row) => {
196
- if (y < margin + rowHeight) addPage();
197
-
198
- headersToUse.forEach((header, index) => {
199
- const x = margin + index * columnWidth;
200
- page.drawRectangle({
201
- x,
202
- y: y - 5,
203
- width: columnWidth,
204
- height: rowHeight,
205
- color: row.isSummaryRow ? rgb(0.97, 0.97, 0.97) : rgb(1, 1, 1),
206
- borderColor: rgb(0.82, 0.84, 0.86),
207
- borderWidth: 0.5,
208
- });
209
- page.drawText(fitText(row[header.key], columnWidth - 8, row.isSummaryRow ? boldFont : font, fontSize), {
210
- x: x + 4,
211
- y: y + 1,
212
- size: fontSize,
213
- font: row.isSummaryRow ? boldFont : font,
214
- color: rgb(0.12, 0.12, 0.12),
215
- });
216
- });
217
-
218
- y -= rowHeight;
219
- });
220
-
221
- const pdfBytes = await pdfDoc.save();
222
- const blob = new Blob([pdfBytes], { type: 'application/pdf' });
223
- const flName = downloadFileName || pdfFileName || fileName || 'Report.pdf';
224
- saveAs(blob, flName);
225
- };
226
-
227
- const handleDownloadMenuClick = ({ key }) => {
228
- if (key === 'excel') {
229
- exportToExcel(fileName);
230
- return;
231
- }
232
-
233
- if (key === 'pdf') {
234
- exportToPdf(pdfFileName);
235
- return;
236
- }
237
-
238
- if (key === 'mail') {
239
- setMailModalVisible(true);
240
- }
241
- };
242
-
243
- const handleMailModalClose = () => {
244
- setMailModalVisible(false);
245
- mailForm.resetFields();
246
- setSelectedFormat('excel');
247
- };
248
-
249
- const handleFormatToggle = (value) => {
250
- const nextValue = selectedFormat === value ? null : value;
251
- setSelectedFormat(nextValue);
252
- mailForm.setFieldsValue({ format: nextValue });
253
- };
254
-
255
- // const handleSendReportToMail = async (values) => {
256
- // setSendingMail(true);
257
-
258
- // try {
259
- // const mailFormat = values.format || selectedFormat || 'excel';
260
- // const isBoth = mailFormat === 'both';
261
- // const payload = {
262
- // script_id: normalizeScriptId(scriptId),
263
- // input_parameters: inputParameters || {},
264
- // is_pdf: mailFormat === 'pdf' || isBoth,
265
- // is_excel: mailFormat === 'excel' || isBoth,
266
- // is_both: isBoth,
267
- // recipients: getRecipients(values.email),
268
- // };
269
- // const data = onSendReportToMail
270
- // ? await onSendReportToMail(payload)
271
- // : await CoreScripts.sentToReportMail(payload);
272
-
273
- // if (data?.success === false) throw data;
274
-
275
- // message.success(data?.message || 'Report mail sent successfully');
276
- // handleMailModalClose();
277
- // } catch (error) {
278
- // message.error(error?.message || 'Unable to send report mail');
279
- // } finally {
280
- // setSendingMail(false);
281
- // }
282
- // };
283
-
284
- const downloadMenu = (
285
- <Menu className="export-download-menu" onClick={handleDownloadMenuClick}>
286
- <Menu.Item
287
- key="excel"
288
- icon={<FileExcelFilled className="export-download-menu__icon export-download-menu__icon--excel" />}
289
- >
290
- Download Excel Sheet
291
- </Menu.Item>
292
- <Menu.Item
293
- key="pdf"
294
- icon={<FilePdfFilled className="export-download-menu__icon export-download-menu__icon--pdf" />}
295
- >
296
- Download PDF
297
- </Menu.Item>
298
- {/* <Menu.Item
299
- key="mail"
300
- icon={<MailFilled className="export-download-menu__icon export-download-menu__icon--mail" />}
301
- >
302
- Send report to mail
303
- </Menu.Item> */}
304
- </Menu>
305
- );
306
-
307
- const isPdf = format === 'pdf';
308
- const handleExportButtonClick = () => {
309
- if (isPdf) {
310
- exportToPdf();
311
- return;
312
- }
313
-
314
- exportToExcel();
315
- };
316
-
317
- if (dropdown) {
318
- return (
319
- <>
320
- <Dropdown overlay={downloadMenu} trigger={['click']} placement="bottomRight">
321
- <Button type="primary" size="small" className="export-download-button">
322
- <Trans i18nKey={buttonText || 'Download'} /> <DownloadOutlined className="export-download-button__icon" />
323
- </Button>
324
- </Dropdown>
325
- {/*
326
- <Modal
327
- title="Send report to mail"
328
- open={mailModalVisible}
329
- onCancel={handleMailModalClose}
330
- footer={null}
331
- destroyOnClose
332
- width={460}
333
- >
334
- <Form
335
- form={mailForm}
336
- layout="vertical"
337
- initialValues={{ format: 'excel' }}
338
- onFinish={handleSendReportToMail}
339
- >
340
- <Form.Item
341
- name="format"
342
- style={{ marginBottom: 16 }}
343
- rules={[
344
- {
345
- validator: () =>
346
- selectedFormat
347
- ? Promise.resolve()
348
- : Promise.reject(new Error('Please select a format')),
349
- },
350
- ]}
351
- >
352
- <div
353
- className="export-mail-format-options"
354
- style={{ display: 'flex', alignItems: 'center', columnGap: 24 }}
355
- >
356
- <Radio
357
- checked={selectedFormat === 'excel'}
358
- style={{ marginRight: 0 }}
359
- onClick={() => handleFormatToggle('excel')}
360
- >
361
- Excel
362
- </Radio>
363
- <Radio
364
- checked={selectedFormat === 'pdf'}
365
- style={{ marginRight: 0 }}
366
- onClick={() => handleFormatToggle('pdf')}
367
- >
368
- PDF
369
- </Radio>
370
- <Radio
371
- checked={selectedFormat === 'both'}
372
- style={{ marginRight: 0 }}
373
- onClick={() => handleFormatToggle('both')}
374
- >
375
- Both
376
- </Radio>
377
- </div>
378
- </Form.Item>
379
-
380
- <Form.Item
381
- name="email"
382
- label="EMAIL ID"
383
- rules={[
384
- { required: true, message: 'Please enter email id' },
385
- { type: 'email', message: 'Please enter a valid email id' },
386
- ]}
387
- >
388
- <Input placeholder="Enter Mail Id" />
389
- </Form.Item>
390
-
391
- <Form.Item
392
- name="remarks"
393
- label="REMARKS"
394
- rules={[{ required: true, message: 'Please enter remarks' }]}
395
- >
396
- <Input.TextArea placeholder="Enter Remarks" rows={4} />
397
- </Form.Item>
398
-
399
- <Button type="primary" htmlType="submit" loading={sendingMail}>
400
- Send
401
- </Button>
402
- </Form>
403
- </Modal> */}
404
- </>
405
- );
406
- }
407
-
408
82
  // Render an Ant Design Button that triggers the Excel export
409
83
  return (
410
- <Button type="secondary" size="small" onClick={handleExportButtonClick} className="export-download-button">
411
- <Trans i18nKey={buttonText || (isPdf ? 'PDF Download' : 'Download')} /> <DownloadOutlined className="export-download-button__icon" />
84
+ <Button type="secondary" size="small" onClick={exportToExcel}>
85
+ <Trans i18nKey="Download" />
412
86
  </Button>
413
87
  );
414
88
  };
@@ -32,37 +32,3 @@
32
32
  }
33
33
  }
34
34
  }
35
-
36
- .export-download-button {
37
- &.ant-btn-primary {
38
- background: #2f80ed;
39
- border-color: #2f80ed;
40
- color: #fff;
41
-
42
- &:hover,
43
- &:focus {
44
- background: #1c7ed6;
45
- border-color: #1c7ed6;
46
- color: #fff;
47
- }
48
- }
49
- }
50
-
51
- .export-download-menu {
52
- &__icon {
53
- font-size: 16px;
54
- vertical-align: -0.15em;
55
-
56
- &--excel {
57
- color: #18a058;
58
- }
59
-
60
- &--pdf {
61
- color: #e03131;
62
- }
63
-
64
- &--mail {
65
- color: #1c7ed6;
66
- }
67
- }
68
- }
@@ -69,6 +69,7 @@ class CoreScript extends Base {
69
69
  // Settings db pointer
70
70
  if (!dbPtr) dbPtr = localStorage.db_ptr;
71
71
  return ApiUtils.post({
72
+ // baseUrl: 'http://localhost:8002/dev/',
72
73
  url: `core-scripts/dashboardquery/${id}`,
73
74
  formBody,
74
75
  headers: {
@@ -79,14 +80,6 @@ class CoreScript extends Base {
79
80
  });
80
81
  };
81
82
 
82
- // sentToReportMail = (formBody) => {
83
- // return ApiUtils.post({
84
- // baseUrl: 'http://localhost:8002/dev/',
85
- // url: `core-scripts/send-to-report-mail`,
86
- // formBody,
87
- // });
88
- // };
89
-
90
83
  /**
91
84
  *Updating user details
92
85
  * @returns
@@ -98,20 +91,6 @@ class CoreScript extends Base {
98
91
  });
99
92
  };
100
93
 
101
- getCorescript = (formBody,dbPtr) => {
102
-
103
- if (!dbPtr) dbPtr = localStorage.db_ptr;
104
- return ApiUtils.post({
105
- // baseUrl: 'http://localhost:8002/dev/',
106
- url: `core-scripts/get-core-script`,
107
- headers: {
108
- 'Content-Type': 'application/json',
109
- Authorization: 'Bearer ' + localStorage.access_token,
110
- db_ptr: dbPtr,
111
- },
112
- formBody,
113
- });
114
- };
115
94
  getQuery = (formBody) => {
116
95
  return ApiUtils.post({
117
96
  url: `core-scripts/execute-script-api`,
@@ -116,13 +116,6 @@ const MenuAdd = ({ model, callback, edit, history, formContent, match, additiona
116
116
  values.step = formContent.step || step;
117
117
  }
118
118
 
119
- // Cleared selects come back as undefined; send null so the backend clears them
120
- ['model_id', 'page_id', 'header_id'].forEach((field) => {
121
- if (values[field] === undefined) {
122
- values[field] = null;
123
- }
124
- });
125
-
126
119
  if (values.attributes && typeof values === 'object') {
127
120
  values = {
128
121
  ...values,
@@ -190,7 +183,7 @@ const MenuAdd = ({ model, callback, edit, history, formContent, match, additiona
190
183
  {/* Model */}
191
184
  <Form.Item label="Models" name={'model_id'}>
192
185
  {/* <ReferenceSelect value={model.id} label={model.name} model={Models} /> */}
193
- <Select showSearch style={{ width: '100%' }} placeholder="Select a Page" optionFilterProp="label" allowClear>
186
+ <Select showSearch style={{ width: '100%' }} placeholder="Select a Page" optionFilterProp="label">
194
187
  {models.map((model, key) => (
195
188
  <Option key={key} label={model.name} value={model.id}>
196
189
  {model.name}
@@ -205,7 +198,7 @@ const MenuAdd = ({ model, callback, edit, history, formContent, match, additiona
205
198
  <Form.Item label="Pages" name={'page_id'}>
206
199
  {/* <ReferenceSelect value={pages.id} label={pages.name} model={Pages} /> */}
207
200
 
208
- <Select showSearch optionFilterProp="children" style={{ width: '100%' }} allowClear>
201
+ <Select showSearch optionFilterProp="children" style={{ width: '100%' }}>
209
202
  {pages.map((model, key) => (
210
203
  <Option key={key} value={model.id}>
211
204
  {model.name}
@@ -236,33 +229,13 @@ const MenuAdd = ({ model, callback, edit, history, formContent, match, additiona
236
229
  {/* Pages Ends */}
237
230
 
238
231
  {/* Path */}
239
- <Form.Item
240
- name="path"
241
- label="Path"
242
- rules={[
243
- { required: true, message: 'Path is required' },
244
- {
245
- pattern: /^\//,
246
- message: 'Path must start with /',
247
- },
248
- ]}
249
- >
232
+ <Form.Item name="path" label="Path" rules={[{ required: true, message: 'Path is required' }]}>
250
233
  <Input placeholder="Enter path" />
251
234
  </Form.Item>
252
235
  {/* Path Ends */}
253
236
 
254
237
  {/* Route */}
255
- <Form.Item
256
- name="route"
257
- label="Route"
258
- rules={[
259
- { required: false, message: 'Route is required' },
260
- {
261
- pattern: /^\//,
262
- message: 'Route must start with /',
263
- },
264
- ]}
265
- >
238
+ <Form.Item name="route" label="Route" rules={[{ required: true, message: 'Route is required' }]}>
266
239
  <Input placeholder="Enter route" />
267
240
  </Form.Item>
268
241
  {/* Route Ends */}