@visns-studio/visns-components 5.1.4 → 5.1.6

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/package.json CHANGED
@@ -77,7 +77,7 @@
77
77
  "react-dom": "^17.0.0 || ^18.0.0"
78
78
  },
79
79
  "name": "@visns-studio/visns-components",
80
- "version": "5.1.4",
80
+ "version": "5.1.6",
81
81
  "description": "Various packages to assist in the development of our Custom Applications.",
82
82
  "main": "src/index.js",
83
83
  "files": [
@@ -150,6 +150,16 @@ function GenericDetail({
150
150
  }));
151
151
  };
152
152
 
153
+ const handleSelectedHeadingKey = (value, action, id) => {
154
+ setData((prevState) => ({
155
+ ...prevState,
156
+ [id]: {
157
+ ...prevState[id],
158
+ headingKey: value,
159
+ },
160
+ }));
161
+ };
162
+
153
163
  const handleSelectedOcrKey = (value, action, id) => {
154
164
  setOcrRowsSelected(value.value);
155
165
 
@@ -184,8 +194,10 @@ function GenericDetail({
184
194
  }
185
195
  };
186
196
 
187
- const handleOcrTemplateSave = async (id) => {
197
+ const handleOcrTemplateSave = async () => {
188
198
  try {
199
+ console.info(data);
200
+
189
201
  const res = await CustomFetch(
190
202
  `${activeTabConfig.form.url}/${data.id}`,
191
203
  'PUT',
@@ -529,8 +541,6 @@ function GenericDetail({
529
541
  return null;
530
542
  }
531
543
 
532
- console.info(lines);
533
-
534
544
  return (
535
545
  <>
536
546
  {lines.map((line, index) => (
@@ -639,6 +649,13 @@ function GenericDetail({
639
649
  ocrTemplateBuilder.selectedKey &&
640
650
  ocrTemplateBuilder.selectedKey.length > 0 && (
641
651
  <>
652
+ <h2
653
+ style={{
654
+ borderBottom: '1px solid grey',
655
+ }}
656
+ >
657
+ File Name Template
658
+ </h2>
642
659
  <strong>Selected Keys</strong>
643
660
  <MultiSelect
644
661
  className=""
@@ -666,6 +683,53 @@ function GenericDetail({
666
683
  onChange={handleOcrInputChange}
667
684
  name="dynamicFilename"
668
685
  />
686
+ <h2
687
+ style={{
688
+ paddingTop: '20px',
689
+ borderBottom: '1px solid grey',
690
+ }}
691
+ >
692
+ Folder Setting
693
+ </h2>
694
+ <strong>Watch Folder</strong>
695
+ <input
696
+ type="text"
697
+ name="watchFolder"
698
+ value={data?.content?.watchFolder || ''}
699
+ onChange={(e) => {
700
+ const { name, value } = e.target;
701
+
702
+ setData((prevState) => ({
703
+ ...prevState,
704
+ content: {
705
+ ...prevState.content,
706
+ [name]: value,
707
+ },
708
+ }));
709
+ }}
710
+ />
711
+
712
+ <br />
713
+ <br />
714
+ <strong>Destination Folder</strong>
715
+ <input
716
+ type="text"
717
+ name="destinationFolder"
718
+ value={
719
+ data?.content?.destinationFolder || ''
720
+ }
721
+ onChange={(e) => {
722
+ const { name, value } = e.target;
723
+
724
+ setData((prevState) => ({
725
+ ...prevState,
726
+ content: {
727
+ ...prevState.content,
728
+ [name]: value,
729
+ },
730
+ }));
731
+ }}
732
+ />
669
733
  </>
670
734
  )}
671
735
  </>
@@ -1,16 +1,93 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
2
+ import ReactDOM from 'react-dom';
2
3
  import debounce from 'lodash.debounce';
3
4
  import { toast } from 'react-toastify';
4
- import Popup from 'reactjs-popup';
5
5
  import { confirmAlert } from 'react-confirm-alert';
6
6
  import { TrashCan, ArrowUp, ArrowDown } from 'akar-icons';
7
+ import { CompactPicker } from 'react-color';
7
8
 
8
9
  import CustomFetch from '../Fetch';
9
- import Form from '../Form';
10
10
  import MultiSelect from '../MultiSelect';
11
11
 
12
12
  import 'react-confirm-alert/src/react-confirm-alert.css';
13
13
  import styles from './styles/GenericEditableTable.module.scss';
14
+ import { set } from 'lodash';
15
+
16
+ const ColourPicker = ({ value, columnId, keyCounter, onChange }) => {
17
+ const [colorPickerShow, setColorPickerShow] = useState(false);
18
+ const colorPickerRef = useRef(null);
19
+ const buttonRef = useRef(null); // Reference to the button for positioning
20
+ const popoverRef = useRef(null); // Reference to the popover
21
+
22
+ // Handle clicks outside of the color picker to close it
23
+ useEffect(() => {
24
+ const handleClickOutside = (event) => {
25
+ // Check if click is outside both the button and the popover
26
+ if (
27
+ popoverRef.current &&
28
+ !popoverRef.current.contains(event.target) &&
29
+ buttonRef.current &&
30
+ !buttonRef.current.contains(event.target)
31
+ ) {
32
+ setColorPickerShow(false); // Close the color picker
33
+ }
34
+ };
35
+
36
+ document.addEventListener('mousedown', handleClickOutside);
37
+ return () =>
38
+ document.removeEventListener('mousedown', handleClickOutside);
39
+ }, []);
40
+
41
+ const buttonRect = buttonRef.current
42
+ ? buttonRef.current.getBoundingClientRect()
43
+ : {}; // Get button position
44
+
45
+ return (
46
+ <div className={styles.cpicker}>
47
+ <div className={styles.cpicker__btn} ref={colorPickerRef}>
48
+ <button
49
+ ref={buttonRef} // Attach ref to the button
50
+ style={
51
+ value && value !== 'null' ? { background: value } : {}
52
+ }
53
+ onClick={(e) => {
54
+ e.preventDefault();
55
+ setColorPickerShow(!colorPickerShow); // Toggle visibility
56
+ }}
57
+ >
58
+ &#9744;
59
+ </button>
60
+
61
+ {colorPickerShow &&
62
+ ReactDOM.createPortal(
63
+ <div
64
+ ref={popoverRef} // Attach ref to the popover
65
+ className={styles.colour_popover}
66
+ style={{
67
+ position: 'absolute',
68
+ left: buttonRect.left, // Position it based on button's position
69
+ top: buttonRect.bottom + 5, // Position below the button with a small offset
70
+ zIndex: 9999,
71
+ }}
72
+ >
73
+ <div
74
+ className={styles.colour_cover}
75
+ onClick={() => setColorPickerShow(false)}
76
+ />
77
+ <CompactPicker
78
+ color={value || ''}
79
+ onChangeComplete={(color) => {
80
+ onChange(color.hex, columnId, keyCounter);
81
+ setColorPickerShow(false);
82
+ }}
83
+ />
84
+ </div>,
85
+ document.body // Render the popover inside the body
86
+ )}
87
+ </div>
88
+ </div>
89
+ );
90
+ };
14
91
 
15
92
  const GenericEditableTable = ({
16
93
  schedulingConfig,
@@ -93,6 +170,7 @@ const GenericEditableTable = ({
93
170
  };
94
171
 
95
172
  const handleFieldChange = (value, fieldId, keyCounter) => {
173
+ console.info('handleFieldChange', value, fieldId, keyCounter);
96
174
  setLocalData((prev) => {
97
175
  const updatedDetail = [...prev];
98
176
  updatedDetail[keyCounter] = {
@@ -178,6 +256,15 @@ const GenericEditableTable = ({
178
256
  if (!entry || !column) return null;
179
257
 
180
258
  switch (column.type) {
259
+ case 'colour':
260
+ return (
261
+ <ColourPicker
262
+ value={entry[column.id] || ''}
263
+ columnId={column.id}
264
+ keyCounter={keyCounter}
265
+ onChange={handleFieldChange}
266
+ />
267
+ );
181
268
  case 'currency':
182
269
  case 'number':
183
270
  return (
@@ -405,19 +492,24 @@ const GenericEditableTable = ({
405
492
  .reduce((sum, entry) => {
406
493
  // For each row, sum the values based on column.keys
407
494
  const subtotal =
408
- column.keys.reduce(
409
- (
410
- rowSum,
411
- key
412
- ) =>
413
- rowSum +
414
- (parseFloat(
415
- entry[
416
- key
417
- ]
418
- ) || 0),
419
- 0
420
- );
495
+ Array.isArray(
496
+ column.keys
497
+ ) // Ensure column.keys is an array
498
+ ? column.keys.reduce(
499
+ (
500
+ rowSum,
501
+ key
502
+ ) =>
503
+ rowSum +
504
+ (parseFloat(
505
+ entry[
506
+ key
507
+ ]
508
+ ) ||
509
+ 0),
510
+ 0
511
+ )
512
+ : 0; // Default to 0 if column.keys is not an array
421
513
  return sum + subtotal;
422
514
  }, 0)
423
515
  .toLocaleString('en-AU', {
@@ -197,3 +197,60 @@
197
197
  color: var(--primary-color); /* Set text color to primary color */
198
198
  border-top: 2px solid var(--primary-color); /* Add border top to separate subtotal row */
199
199
  }
200
+
201
+ .colour {
202
+ &__cover {
203
+ position: fixed;
204
+ top: 0;
205
+ right: 0;
206
+ bottom: 0;
207
+ left: 0;
208
+ }
209
+
210
+ &__popover {
211
+ position: absolute;
212
+ z-index: 9999;
213
+ left: 50%; /* Position to the center or adjust accordingly */
214
+ top: 50%; /* Adjust top based on your layout */
215
+ transform: translate(-50%, -50%); /* Center it */
216
+ }
217
+ }
218
+
219
+ .cpicker {
220
+ width: 100%;
221
+ display: flex;
222
+ flex-wrap: nowrap;
223
+ align-items: center;
224
+
225
+ &__btn {
226
+ flex: 1;
227
+
228
+ button {
229
+ width: 40px; /* Keep it compact */
230
+ height: 40px; /* Square button */
231
+ font-size: 1.5rem; /* Adjusted for a better icon size */
232
+ font-weight: 600;
233
+ color: #fff; /* White icon color */
234
+ background-color: #b0b0b0; /* Neutral grey base */
235
+ border: 2px solid #999; /* Light border for definition */
236
+ border-radius: 8px; /* Rounded corners */
237
+ cursor: pointer;
238
+ transition: all 0.3s ease; /* Smooth transition for hover effect */
239
+
240
+ &:hover {
241
+ background-color: #999; /* Darken the background on hover */
242
+ border-color: #666; /* Darken the border on hover */
243
+ }
244
+
245
+ &:focus {
246
+ outline: none; /* Remove default focus outline */
247
+ box-shadow: 0 0 0 2px rgba(72, 168, 58, 0.5); /* Custom focus outline */
248
+ }
249
+
250
+ &:active {
251
+ background-color: #888; /* Lighter grey on click */
252
+ transform: scale(0.98); /* Shrink on click */
253
+ }
254
+ }
255
+ }
256
+ }