@visns-studio/visns-components 5.6.4 → 5.6.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
@@ -16,17 +16,17 @@
16
16
  "akar-icons": "^1.9.31",
17
17
  "array-move": "^4.0.0",
18
18
  "awesome-debounce-promise": "^2.1.0",
19
- "axios": "^1.8.4",
19
+ "axios": "^1.9.0",
20
20
  "browser-image-compression": "^2.0.2",
21
21
  "dayjs": "^1.11.13",
22
22
  "fabric": "^6.6.4",
23
23
  "file-saver": "^2.0.5",
24
- "framer-motion": "^12.7.4",
24
+ "framer-motion": "^12.9.2",
25
25
  "html-react-parser": "^5.2.3",
26
26
  "lodash": "^4.17.21",
27
27
  "lodash.debounce": "^4.0.8",
28
28
  "moment": "^2.30.1",
29
- "motion": "^12.7.4",
29
+ "motion": "^12.9.2",
30
30
  "numeral": "^2.0.6",
31
31
  "pluralize": "^8.0.0",
32
32
  "qrcode.react": "^4.2.0",
@@ -48,7 +48,7 @@
48
48
  "react-signature-pad-wrapper": "^4.1.0",
49
49
  "react-slugify": "^4.0.1",
50
50
  "react-sortable-hoc": "^2.0.0",
51
- "react-to-print": "^3.0.6",
51
+ "react-to-print": "^3.1.0",
52
52
  "react-toastify": "^11.0.5",
53
53
  "react-toggle": "^4.1.3",
54
54
  "react-tooltip": "^5.28.1",
@@ -62,7 +62,7 @@
62
62
  "validator": "^13.15.0",
63
63
  "vite": "^5.4.18",
64
64
  "yarn": "^1.22.22",
65
- "yet-another-react-lightbox": "^3.22.0"
65
+ "yet-another-react-lightbox": "^3.23.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@babel/core": "^7.26.10",
@@ -84,7 +84,7 @@
84
84
  "react-dom": "^17.0.0 || ^18.0.0"
85
85
  },
86
86
  "name": "@visns-studio/visns-components",
87
- "version": "5.6.4",
87
+ "version": "5.6.6",
88
88
  "description": "Various packages to assist in the development of our Custom Applications.",
89
89
  "main": "src/index.js",
90
90
  "files": [
@@ -1,5 +1,24 @@
1
1
  import '../../styles/global.css';
2
2
 
3
+ /**
4
+ * GenericDetail Component
5
+ *
6
+ * This component supports two editing modes:
7
+ * 1. Modal editing (default) - Opens a modal with the form when the edit button is clicked
8
+ * 2. In-place editing - Makes the existing interface editable when the edit button is clicked
9
+ *
10
+ * To enable in-place editing, add the `inPlaceEdit: true` property to the form object in the tab configuration.
11
+ * Example:
12
+ * {
13
+ * id: 'overview',
14
+ * type: 'overview',
15
+ * form: {
16
+ * inPlaceEdit: true,
17
+ * // other form properties
18
+ * }
19
+ * }
20
+ */
21
+
3
22
  import React, { useEffect, useRef, useState } from 'react';
4
23
  import { Link, useParams } from 'react-router-dom';
5
24
  import { Calendar, momentLocalizer } from 'react-big-calendar';
@@ -1833,104 +1852,225 @@ function GenericDetail({
1833
1852
  case 'overview':
1834
1853
  return (
1835
1854
  <>
1836
- <div className={styles.gridtxt}>
1837
- {activeTabConfig.sections.map(
1838
- (section, sectionIndex) => (
1839
- <React.Fragment
1840
- key={`section-${activeTabConfig.id}-${sectionIndex}`}
1841
- >
1842
- <div
1843
- className={
1844
- styles.gridtxt__header
1845
- }
1855
+ {/* Show the form in-place when editing is active */}
1856
+ {inPlaceEditing &&
1857
+ editingTabId === activeTabConfig.id &&
1858
+ activeTabConfig.form ? (
1859
+ <div
1860
+ className={`${styles.gridtxt} inPlaceEdit`}
1861
+ >
1862
+ <div
1863
+ className={
1864
+ styles.gridtxt__header
1865
+ }
1866
+ >
1867
+ <span>
1868
+ {activeTabConfig.title ||
1869
+ 'Edit'}
1870
+ </span>
1871
+ </div>
1872
+ <Form
1873
+ key={`form-inline-${activeTabConfig.id}`}
1874
+ columnId={routeParams[urlParam]}
1875
+ formSettings={
1876
+ activeTabConfig.form
1877
+ }
1878
+ formType="update"
1879
+ paramValue={
1880
+ routeParams[urlParam] ||
1881
+ null
1882
+ }
1883
+ style={
1884
+ userProfile?.settings
1885
+ ?.style || {}
1886
+ }
1887
+ updateForm={setFormData}
1888
+ type="inline"
1889
+ userProfile={userProfile}
1890
+ fetchTable={() => {
1891
+ handleReload();
1892
+ setInPlaceEditing(false);
1893
+ setEditingTabId(null);
1894
+ }}
1895
+ />
1896
+ </div>
1897
+ ) : (
1898
+ // Show the regular overview when not editing
1899
+ <div className={styles.gridtxt}>
1900
+ {activeTabConfig.sections.map(
1901
+ (section, sectionIndex) => (
1902
+ <React.Fragment
1903
+ key={`section-${activeTabConfig.id}-${sectionIndex}`}
1846
1904
  >
1847
- <span>
1848
- {section.title}
1849
- </span>
1850
- </div>
1851
- {section.content &&
1852
- section.content.length >
1853
- 0 && (
1854
- <ul
1855
- className={
1856
- styles.customer__overview
1857
- }
1858
- >
1859
- {section.content.map(
1860
- (
1861
- item,
1862
- itemKey
1863
- ) => (
1864
- <li
1865
- key={`li-${item.id}-${itemKey}`}
1866
- className={
1867
- item.size ===
1868
- 'full'
1869
- ? `${styles['fw-grid-item']} ${styles.notecolor}`
1870
- : null
1871
- }
1872
- >
1873
- <strong>
1874
- {item.label
1875
- ? `${item.label}:`
1876
- : null}
1877
- </strong>{' '}
1878
- {item
1879
- .href
1880
- ?.url &&
1881
- item
1882
- .href
1883
- ?.key ? (
1884
- <Link
1885
- to={`${
1886
- item
1887
- .href
1888
- .url
1889
- }${
1890
- data[
1905
+ <div
1906
+ className={
1907
+ styles.gridtxt__header
1908
+ }
1909
+ >
1910
+ <span>
1911
+ {section.title}
1912
+ </span>
1913
+ </div>
1914
+ {section.content &&
1915
+ section.content
1916
+ .length > 0 && (
1917
+ <ul
1918
+ className={
1919
+ styles.customer__overview
1920
+ }
1921
+ >
1922
+ {section.content.map(
1923
+ (
1924
+ item,
1925
+ itemKey
1926
+ ) => (
1927
+ <li
1928
+ key={`li-${item.id}-${itemKey}`}
1929
+ className={
1930
+ item.size ===
1931
+ 'full'
1932
+ ? `${styles['fw-grid-item']} ${styles.notecolor}`
1933
+ : null
1934
+ }
1935
+ >
1936
+ <strong>
1937
+ {item.label
1938
+ ? `${item.label}:`
1939
+ : null}
1940
+ </strong>{' '}
1941
+ {item
1942
+ .href
1943
+ ?.url &&
1944
+ item
1945
+ .href
1946
+ ?.key ? (
1947
+ <Link
1948
+ to={`${
1891
1949
  item
1892
1950
  .href
1893
- .key
1894
- ]
1895
- }`}
1896
- >
1897
- {renderValue(
1898
- item,
1899
- data
1900
- )}
1901
- </Link>
1902
- ) : (
1903
- <>
1904
- {renderValue(
1905
- item,
1906
- data
1907
- )}
1908
- </>
1909
- )}
1910
- </li>
1911
- )
1912
- )}
1913
- </ul>
1914
- )}
1915
- </React.Fragment>
1916
- )
1917
- )}
1918
- </div>
1951
+ .url
1952
+ }${
1953
+ data[
1954
+ item
1955
+ .href
1956
+ .key
1957
+ ]
1958
+ }`}
1959
+ >
1960
+ {renderValue(
1961
+ item,
1962
+ data
1963
+ )}
1964
+ </Link>
1965
+ ) : (
1966
+ <>
1967
+ {renderValue(
1968
+ item,
1969
+ data
1970
+ )}
1971
+ </>
1972
+ )}
1973
+ </li>
1974
+ )
1975
+ )}
1976
+ </ul>
1977
+ )}
1978
+ </React.Fragment>
1979
+ )
1980
+ )}
1981
+ </div>
1982
+ )}
1919
1983
 
1920
1984
  {activeTabConfig.form && (
1921
1985
  <div className={styles.polActions}>
1922
- {/* Always render the "Edit" button if activeTabConfig.form exists */}
1923
- <button
1924
- className={styles.btn}
1925
- onClick={() =>
1926
- modalOpen(
1927
- 'update',
1928
- routeParams[urlParam]
1929
- )
1930
- }
1931
- >
1932
- Edit
1933
- </button>
1986
+ {/* Render the "Edit" button if activeTabConfig.form exists */}
1987
+ {!inPlaceEditing ? (
1988
+ <button
1989
+ className={styles.btn}
1990
+ onClick={() => {
1991
+ if (
1992
+ activeTabConfig.form
1993
+ .inPlaceEdit
1994
+ ) {
1995
+ startInPlaceEditing(
1996
+ activeTabConfig.id
1997
+ );
1998
+ } else {
1999
+ modalOpen(
2000
+ 'update',
2001
+ routeParams[
2002
+ urlParam
2003
+ ]
2004
+ );
2005
+ }
2006
+ }}
2007
+ >
2008
+ Edit
2009
+ </button>
2010
+ ) : (
2011
+ editingTabId ===
2012
+ activeTabConfig.id && (
2013
+ <>
2014
+ <button
2015
+ className={
2016
+ styles.btn
2017
+ }
2018
+ onClick={
2019
+ cancelInPlaceEditing
2020
+ }
2021
+ style={{
2022
+ backgroundColor:
2023
+ '#fff0f0',
2024
+ color: '#d32f2f',
2025
+ border: '1px solid #ffcdd2',
2026
+ }}
2027
+ >
2028
+ Cancel
2029
+ </button>
2030
+ <button
2031
+ className={
2032
+ styles.btn
2033
+ }
2034
+ onClick={() => {
2035
+ // Find the form's save button and click it
2036
+ const saveButton =
2037
+ document.querySelector(
2038
+ `.inPlaceEdit .${styles.saveBtn}`
2039
+ );
2040
+ if (
2041
+ saveButton
2042
+ ) {
2043
+ saveButton.click();
2044
+ } else {
2045
+ // Fallback to any button with data-type="save"
2046
+ const fallbackButton =
2047
+ document.querySelector(
2048
+ `.inPlaceEdit button[data-type="save"]`
2049
+ );
2050
+ if (
2051
+ fallbackButton
2052
+ ) {
2053
+ fallbackButton.click();
2054
+ }
2055
+ }
2056
+
2057
+ // Reset the editing state
2058
+ setInPlaceEditing(
2059
+ false
2060
+ );
2061
+ setEditingTabId(
2062
+ null
2063
+ );
2064
+
2065
+ // Reload data
2066
+ handleReload();
2067
+ }}
2068
+ >
2069
+ Save
2070
+ </button>
2071
+ </>
2072
+ )
2073
+ )}
1934
2074
 
1935
2075
  {/* Check if sections contain "ocrTemplate" type and render the "Save" button under the same polActions */}
1936
2076
  {activeTabConfig.sections &&
@@ -2545,6 +2685,8 @@ function GenericDetail({
2545
2685
  const [formType, setFormType] = useState('');
2546
2686
  const [formId, setFormId] = useState(0);
2547
2687
  const [modalShow, setModalShow] = useState(false);
2688
+ const [inPlaceEditing, setInPlaceEditing] = useState(false);
2689
+ const [editingTabId, setEditingTabId] = useState(null);
2548
2690
 
2549
2691
  /** Modal Functions */
2550
2692
  const modalOpen = (formType, formId) => {
@@ -2557,6 +2699,19 @@ function GenericDetail({
2557
2699
  setModalShow(false);
2558
2700
  };
2559
2701
 
2702
+ /** In-place Editing Functions */
2703
+ const startInPlaceEditing = (tabId) => {
2704
+ setInPlaceEditing(true);
2705
+ setEditingTabId(tabId);
2706
+ setFormType('update');
2707
+ setFormId(routeParams[urlParam]);
2708
+ };
2709
+
2710
+ const cancelInPlaceEditing = () => {
2711
+ setInPlaceEditing(false);
2712
+ setEditingTabId(null);
2713
+ };
2714
+
2560
2715
  return (
2561
2716
  <>
2562
2717
  <div className={styles.grid}>