@visns-studio/visns-components 5.0.0 → 5.0.1-8.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 (37) hide show
  1. package/package.json +3 -1
  2. package/src/components/crm/AsyncSelect.jsx +121 -15
  3. package/src/components/crm/DataGrid.jsx +26 -5
  4. package/src/components/crm/Field.jsx +174 -148
  5. package/src/components/crm/Form.jsx +46 -33
  6. package/src/components/crm/MultiSelect.jsx +96 -29
  7. package/src/components/crm/Navigation.jsx +2 -81
  8. package/src/components/crm/QrCode.jsx +12 -8
  9. package/src/components/crm/auth/Login.jsx +9 -1
  10. package/src/components/crm/auth/Profile.jsx +4 -2
  11. package/src/components/crm/auth/styles/Login.module.scss +52 -82
  12. package/src/components/crm/auth/styles/Profile.module.scss +150 -44
  13. package/src/components/crm/auth/styles/Reset.module.scss +55 -37
  14. package/src/components/crm/auth/styles/Verify.module.scss +55 -76
  15. package/src/components/crm/generic/GenericAuth.jsx +17 -6
  16. package/src/components/crm/generic/GenericDetail.jsx +509 -18
  17. package/src/components/crm/generic/GenericEditableTable.jsx +407 -0
  18. package/src/components/crm/generic/styles/AuditLog.module.scss +4 -37
  19. package/src/components/crm/generic/styles/AuditLogs.module.scss +0 -51
  20. package/src/components/crm/generic/styles/GenericDetail.module.scss +263 -193
  21. package/src/components/crm/generic/styles/GenericDynamic.module.scss +100 -198
  22. package/src/components/crm/generic/styles/GenericEditableTable.module.scss +178 -0
  23. package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +63 -96
  24. package/src/components/crm/generic/styles/GenericIndex.module.scss +46 -66
  25. package/src/components/crm/generic/styles/GenericMain.module.scss +7 -7
  26. package/src/components/crm/generic/styles/GenericSort.module.scss +0 -36
  27. package/src/components/crm/generic/styles/NotificationList.module.scss +1 -32
  28. package/src/components/crm/styles/Autocomplete.module.scss +12 -20
  29. package/src/components/crm/styles/DataGrid.module.scss +6 -89
  30. package/src/components/crm/styles/Field.module.scss +72 -42
  31. package/src/components/crm/styles/Form.module.scss +148 -379
  32. package/src/components/crm/styles/Navigation.module.scss +356 -501
  33. package/src/components/crm/styles/Notification.module.scss +1 -0
  34. package/src/components/crm/styles/QrCode.module.scss +4 -0
  35. package/src/components/crm/styles/SwitchAccount.module.scss +0 -1
  36. package/src/components/crm/styles/TableFilter.module.scss +2 -1
  37. package/src/components/styles/global.css +164 -34
package/package.json CHANGED
@@ -16,6 +16,7 @@
16
16
  "awesome-debounce-promise": "^2.1.0",
17
17
  "axios": "^1.7.7",
18
18
  "dayjs": "^1.11.13",
19
+ "fabric": "^6.5.4",
19
20
  "file-saver": "^2.0.5",
20
21
  "framer-motion": "^11.11.9",
21
22
  "html-react-parser": "^5.1.18",
@@ -26,6 +27,7 @@
26
27
  "numeral": "^2.0.6",
27
28
  "pluralize": "^8.0.0",
28
29
  "quill-image-uploader": "^1.3.0",
30
+ "react-big-calendar": "^1.17.1",
29
31
  "react-color": "^2.19.3",
30
32
  "react-confirm-alert": "^3.0.6",
31
33
  "react-copy-to-clipboard": "^5.1.0",
@@ -75,7 +77,7 @@
75
77
  "react-dom": "^17.0.0 || ^18.0.0"
76
78
  },
77
79
  "name": "@visns-studio/visns-components",
78
- "version": "5.0.0",
80
+ "version": "5.0.18.1",
79
81
  "description": "Various packages to assist in the development of our Custom Applications.",
80
82
  "main": "src/index.js",
81
83
  "files": [
@@ -1,11 +1,28 @@
1
- import React, { useEffect, useState, useCallback } from 'react';
1
+ import React, { useCallback } from 'react';
2
2
  import CustomFetch from './Fetch';
3
3
  import SelectList from './SelectList';
4
4
  import AsyncSelect from 'react-select/async';
5
+ import AsyncCreatableSelect from 'react-select/async-creatable';
5
6
  import { debounce } from 'lodash';
6
7
  import styles from './styles/AsyncSelect.module.scss';
8
+ import { components } from 'react-select';
9
+
10
+ // Custom Option component to add a second line of text
11
+ const CustomOption = (props) => (
12
+ <components.Option {...props}>
13
+ <div>
14
+ {props.data.label}
15
+ {props.data.description && props.data.description !== '' && (
16
+ <div style={{ fontSize: '0.85em', color: '#888' }}>
17
+ {props.data.description}
18
+ </div>
19
+ )}
20
+ </div>
21
+ </components.Option>
22
+ );
7
23
 
8
24
  function VisnsAsyncSelect({
25
+ className,
9
26
  fields = [],
10
27
  inputValue,
11
28
  onChange,
@@ -14,6 +31,7 @@ function VisnsAsyncSelect({
14
31
  placeholder,
15
32
  settings,
16
33
  style,
34
+ isCreatable = false, // New prop to toggle creatable functionality
17
35
  }) {
18
36
  const loadSuggestedOptions = useCallback(
19
37
  debounce((inputValue, callback) => {
@@ -31,7 +49,6 @@ function VisnsAsyncSelect({
31
49
  return new Promise((resolve, reject) => {
32
50
  let data = [];
33
51
 
34
- // Prepare payload
35
52
  let payload = {
36
53
  where: [
37
54
  {
@@ -41,38 +58,50 @@ function VisnsAsyncSelect({
41
58
  ],
42
59
  };
43
60
 
44
- // Check and set fields from settings if fields prop is null or empty
45
61
  if (fields && fields.length > 0) {
46
62
  payload.fields = fields;
47
63
  } else if (settings.fields && settings.fields.length > 0) {
48
64
  payload.fields = settings.fields;
49
65
  }
50
66
 
51
- // Check and set orderBy from settings if orderBy prop is null or empty
52
67
  if (orderBy) {
53
68
  payload.orderBy = orderBy;
54
69
  } else if (settings.orderBy) {
55
70
  payload.orderBy = settings.orderBy;
56
71
  }
57
72
 
58
- // Fetch data
59
73
  CustomFetch(
60
74
  settings.url,
61
75
  'POST',
62
76
  payload,
63
77
  function (result) {
64
78
  result.data.forEach((a) => {
79
+ let mainLabel = a.label || a[Object.keys(a)[0]];
80
+
81
+ if (settings.fields && settings.fields.length > 2) {
82
+ const additionalFields =
83
+ settings.fields.slice(2);
84
+ const additionalLabels = additionalFields
85
+ .filter(
86
+ (field) =>
87
+ field !== settings.descriptionKey
88
+ )
89
+ .map((field) => a[field] || '')
90
+ .join(' ');
91
+ mainLabel += ` ${additionalLabels}`;
92
+ }
93
+
65
94
  let _optionItem = {
66
95
  value: a.id,
67
- label: a.label,
96
+ label: mainLabel,
97
+ description: settings.descriptionKey
98
+ ? a[settings.descriptionKey]
99
+ : '',
68
100
  };
69
101
 
70
102
  Object.keys(a).forEach((b) => {
71
- if (b !== 'id') {
72
- _optionItem = {
73
- ..._optionItem,
74
- [b]: a[b],
75
- };
103
+ if (b !== 'id' && b !== 'label') {
104
+ _optionItem[b] = a[b];
76
105
  }
77
106
  });
78
107
 
@@ -87,17 +116,92 @@ function VisnsAsyncSelect({
87
116
  );
88
117
  });
89
118
  } else {
90
- return Promise.resolve([]); // Return empty array if input is less than 3 characters
119
+ return Promise.resolve([]);
91
120
  }
92
121
  };
93
122
 
123
+ const handleCreateOption = async (inputValue) => {
124
+ if (
125
+ settings.creatableConfig &&
126
+ settings.creatableConfig.url &&
127
+ settings.creatableConfig.method
128
+ ) {
129
+ let payload;
130
+ let firstNameField, lastNameField;
131
+
132
+ if (
133
+ settings.creatableConfig.type === 'name' &&
134
+ Array.isArray(settings.creatableConfig.fields)
135
+ ) {
136
+ [firstNameField, lastNameField] =
137
+ settings.creatableConfig.fields;
138
+
139
+ const nameParts = inputValue.trim().split(' ');
140
+ let firstname = '';
141
+ let lastname = '';
142
+
143
+ if (nameParts.length === 1) {
144
+ firstname = nameParts[0];
145
+ } else if (nameParts.length === 2) {
146
+ firstname = nameParts[0];
147
+ lastname = nameParts[1];
148
+ } else {
149
+ firstname = nameParts[0];
150
+ lastname = nameParts.slice(1).join(' ');
151
+ }
152
+
153
+ payload = {
154
+ [firstNameField || 'firstname']: firstname,
155
+ [lastNameField || 'lastname']: lastname,
156
+ };
157
+ } else {
158
+ payload = { label: inputValue };
159
+ }
160
+
161
+ const newOption = await CustomFetch(
162
+ settings.creatableConfig.url,
163
+ settings.creatableConfig.method,
164
+ payload
165
+ );
166
+
167
+ if (newOption && newOption.data && newOption.data.data) {
168
+ const newOptionData = newOption.data.data;
169
+ const option = {
170
+ value: newOptionData.id,
171
+ label:
172
+ settings.creatableConfig.type === 'name'
173
+ ? `${
174
+ newOptionData[firstNameField] ||
175
+ newOptionData.firstname
176
+ } ${
177
+ newOptionData[lastNameField] ||
178
+ newOptionData.lastname
179
+ }`
180
+ : newOptionData.label || inputValue,
181
+ description: settings.descriptionKey
182
+ ? newOptionData[settings.descriptionKey]
183
+ : 'Placeholder text for description',
184
+ ...newOptionData,
185
+ };
186
+
187
+ onChange(option, { action: 'create-option' }, settings.id); // Directly call onChange with new option
188
+ }
189
+ }
190
+ };
191
+
192
+ const SelectComponent = isCreatable ? AsyncCreatableSelect : AsyncSelect;
193
+
94
194
  return (
95
- <AsyncSelect
195
+ <SelectComponent
96
196
  isClearable
97
197
  cacheOptions
98
198
  loadOptions={loadSuggestedOptions}
99
199
  defaultOptions
100
- className={styles.visns__ms}
200
+ className={
201
+ className
202
+ ? `${styles.visns__ms} ${className}`
203
+ : styles.visns__ms
204
+ }
101
205
  onChange={(inputValue, action) => {
102
206
  onChange(inputValue, action, settings.id);
103
207
  }}
@@ -106,7 +210,9 @@ function VisnsAsyncSelect({
106
210
  onKeyDown(e);
107
211
  }
108
212
  }}
109
- components={{ SelectList }}
213
+ classNamePrefix="visns-select"
214
+ onCreateOption={isCreatable ? handleCreateOption : undefined}
215
+ components={{ Option: CustomOption }}
110
216
  styles={{
111
217
  menu: (styles) => ({
112
218
  ...styles,
@@ -14,6 +14,7 @@ import debounce from 'lodash.debounce';
14
14
  import moment from 'moment';
15
15
  import numeral from 'numeral';
16
16
  import Popup from 'reactjs-popup';
17
+ import 'reactjs-popup/dist/index.css';
17
18
  import parse from 'html-react-parser';
18
19
  import { saveAs } from 'file-saver';
19
20
  import NumberFilter from '@inovua/reactdatagrid-community/NumberFilter';
@@ -2381,12 +2382,32 @@ const DataGrid = forwardRef(
2381
2382
  data[column.id] &&
2382
2383
  data[column.id] !== ''
2383
2384
  ) {
2385
+ let content = String(
2386
+ data[column.id]
2387
+ );
2388
+
2389
+ // If removeFormat is true, strip HTML tags
2390
+ if (column.removeFormat) {
2391
+ content = content.replace(
2392
+ /<\/?[^>]+(>|$)/g,
2393
+ ''
2394
+ ); // Simple regex to strip HTML tags
2395
+ }
2396
+
2397
+ // If truncate has a value, limit content to specified number of characters
2398
+ if (column.truncate) {
2399
+ content =
2400
+ content.length >
2401
+ column.truncate
2402
+ ? content.substring(
2403
+ 0,
2404
+ column.truncate
2405
+ ) + '...'
2406
+ : content;
2407
+ }
2408
+
2384
2409
  return (
2385
- <span>
2386
- {parse(
2387
- String(data[column.id])
2388
- )}
2389
- </span>
2410
+ <span>{parse(content)}</span>
2390
2411
  );
2391
2412
  } else {
2392
2413
  return null;