@visns-studio/visns-components 2.6.2 → 2.6.4

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.
@@ -0,0 +1,50 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <code_scheme name="Project" version="173">
3
+ <HTMLCodeStyleSettings>
4
+ <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
5
+ <option name="HTML_QUOTE_STYLE" value="Single" />
6
+ <option name="HTML_ENFORCE_QUOTES" value="true" />
7
+ </HTMLCodeStyleSettings>
8
+ <JSCodeStyleSettings version="0">
9
+ <option name="FORCE_SEMICOLON_STYLE" value="true" />
10
+ <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
11
+ <option name="USE_DOUBLE_QUOTES" value="false" />
12
+ <option name="FORCE_QUOTE_STYlE" value="true" />
13
+ <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
14
+ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
15
+ <option name="SPACES_WITHIN_IMPORTS" value="true" />
16
+ </JSCodeStyleSettings>
17
+ <TypeScriptCodeStyleSettings version="0">
18
+ <option name="FORCE_SEMICOLON_STYLE" value="true" />
19
+ <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
20
+ <option name="USE_DOUBLE_QUOTES" value="false" />
21
+ <option name="FORCE_QUOTE_STYlE" value="true" />
22
+ <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
23
+ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
24
+ <option name="SPACES_WITHIN_IMPORTS" value="true" />
25
+ </TypeScriptCodeStyleSettings>
26
+ <VueCodeStyleSettings>
27
+ <option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
28
+ <option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
29
+ </VueCodeStyleSettings>
30
+ <codeStyleSettings language="HTML">
31
+ <option name="SOFT_MARGINS" value="80" />
32
+ <indentOptions>
33
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
34
+ </indentOptions>
35
+ </codeStyleSettings>
36
+ <codeStyleSettings language="JavaScript">
37
+ <option name="SOFT_MARGINS" value="80" />
38
+ </codeStyleSettings>
39
+ <codeStyleSettings language="TypeScript">
40
+ <option name="SOFT_MARGINS" value="80" />
41
+ </codeStyleSettings>
42
+ <codeStyleSettings language="Vue">
43
+ <option name="SOFT_MARGINS" value="80" />
44
+ <indentOptions>
45
+ <option name="INDENT_SIZE" value="4" />
46
+ <option name="TAB_SIZE" value="4" />
47
+ </indentOptions>
48
+ </codeStyleSettings>
49
+ </code_scheme>
50
+ </component>
@@ -0,0 +1,5 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <state>
3
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
4
+ </state>
5
+ </component>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="PublishConfigData" serverName="Local Dev" />
4
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/visns-components.iml" filepath="$PROJECT_DIR$/.idea/visns-components.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
package/.idea/php.xml ADDED
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="MessDetectorOptionsConfiguration">
4
+ <option name="transferred" value="true" />
5
+ </component>
6
+ <component name="PHPCSFixerOptionsConfiguration">
7
+ <option name="transferred" value="true" />
8
+ </component>
9
+ <component name="PHPCodeSnifferOptionsConfiguration">
10
+ <option name="highlightLevel" value="WARNING" />
11
+ <option name="transferred" value="true" />
12
+ </component>
13
+ <component name="PhpStanOptionsConfiguration">
14
+ <option name="transferred" value="true" />
15
+ </component>
16
+ <component name="PsalmOptionsConfiguration">
17
+ <option name="transferred" value="true" />
18
+ </component>
19
+ </project>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$" />
5
+ <orderEntry type="inheritedJdk" />
6
+ <orderEntry type="sourceFolder" forTests="false" />
7
+ </component>
8
+ </module>
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Visns Components
2
+
3
+ A list of components that is used by the Visns Studio team on all their CRM and CMS Projects.
4
+
5
+ # Modules
6
+
7
+ There are multiple components that are shared between the CRM and CMS but there are also unique components for both the CRM and CMS
8
+
9
+ ## CRM
10
+
11
+ - Authentication UI
12
+ - Login
13
+ - Profile
14
+ - Reset
15
+ - Verify
16
+ - DataGrid
17
+ - Form
18
+ - Generic Pages
19
+ - Detail Page
20
+ - Index Page
21
+ - Notification Page
22
+
23
+ ## CMS
24
+
25
+ - DataGrid
26
+ - DropZone
27
+ - Field
28
+ - Form
29
+ - Generic Pages
30
+ - Detail Page
31
+ - Index Page
32
+ - Sorting Page
33
+
34
+ ## Shared
35
+
36
+ - Asynchronous React Select
37
+ - Autocomplete (Mapbox)
38
+ - Call Popup
39
+ - Download (Axios)
40
+ - Fetch (Axios)
41
+ - Loader
42
+ - Multi React Select
43
+ - Navigation / Header
44
+ - Notification
45
+ - Select
46
+ - Sub Navigati
47
+
48
+ # Usage
49
+
50
+ Detail list of the usage for each components.
51
+
52
+ ## CRM
53
+
54
+ ### DataGrid
55
+
56
+ #### Prop List
57
+
58
+ | Prop | Description | Default |
59
+ | ------------- | ----------- | ------- |
60
+ | ajaxSetting | | |
61
+ | columns | | |
62
+ | form | | |
63
+ | gridHeight | | |
64
+ | settings | | |
65
+ | setFilterData | | |
66
+ | setConfig | | |
67
+ | style | | |
@@ -1,11 +1,10 @@
1
- import React, { useEffect, useState, useCallback } from 'react';
1
+ import React, {useEffect, useState, 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 { debounce } from 'lodash';
5
+ import {debounce} from 'lodash';
6
6
 
7
- function VisnsAsyncSelect(props) {
8
- const { inputValue, onChange, settings, multi } = props;
7
+ function VisnsAsyncSelect({inputValue, onChange, settings}) {
9
8
 
10
9
  const loadSuggestedOptions = useCallback(
11
10
  debounce((inputValue, callback) => {
@@ -71,7 +70,7 @@ function VisnsAsyncSelect(props) {
71
70
  onChange={(inputValue, action) => {
72
71
  onChange(inputValue, action, settings.id);
73
72
  }}
74
- components={{ SelectList }}
73
+ components={{SelectList}}
75
74
  styles={{
76
75
  menu: (provided) => ({
77
76
  ...provided,
@@ -499,6 +499,24 @@ const DataGrid = forwardRef(
499
499
  return null; // Return null if neither search is enabled nor create is disabled
500
500
  };
501
501
 
502
+ const renderRowContextMenu = useCallback((menuProps, { rowProps }) => {
503
+ if (form && form.newTabUrl && form.newTabUrl !== '') {
504
+ menuProps.autoDismiss = true;
505
+ menuProps.items = [
506
+ {
507
+ label: 'Open Link in a New Tab',
508
+ onClick: () => {
509
+ window.open(
510
+ `${form.newTabUrl}${
511
+ rowProps.data[form.primaryKey]
512
+ }`
513
+ );
514
+ },
515
+ },
516
+ ];
517
+ }
518
+ }, []);
519
+
502
520
  const handleCoding = (c, data) => {
503
521
  const icons = [];
504
522
  const assetPath =
@@ -1384,14 +1402,9 @@ const DataGrid = forwardRef(
1384
1402
  ) {
1385
1403
  filterEditor = SelectFilter;
1386
1404
  filterEditorProps = {
1387
- multiple:
1388
- column.filter.operator === 'inlist'
1389
- ? true
1390
- : false,
1405
+ multiple: column.filter.operator === 'inlist',
1391
1406
  wrapMultiple:
1392
- column.filter.operator === 'inlist'
1393
- ? false
1394
- : true,
1407
+ column.filter.operator !== 'inlist',
1395
1408
  placeholder: column.filter.placeholder
1396
1409
  ? column.filter.placeholder
1397
1410
  : 'All Options',
@@ -1647,13 +1660,9 @@ const DataGrid = forwardRef(
1647
1660
  filterEditor = SelectFilter;
1648
1661
  filterEditorProps = {
1649
1662
  multiple:
1650
- column.filter.operator === 'inlist'
1651
- ? true
1652
- : false,
1663
+ column.filter.operator === 'inlist',
1653
1664
  wrapMultiple:
1654
- column.filter.operator === 'inlist'
1655
- ? false
1656
- : true,
1665
+ column.filter.operator !== 'inlist',
1657
1666
  placeholder: column.filter.placeholder
1658
1667
  ? column.filter.placeholder
1659
1668
  : 'All Options',
@@ -1913,6 +1922,7 @@ const DataGrid = forwardRef(
1913
1922
  onSortInfoChange={handleSort}
1914
1923
  onRenderRow={onRenderRow}
1915
1924
  pagination
1925
+ renderRowContextMenu={renderRowContextMenu}
1916
1926
  renderColumnContextMenu={renderColumnContextMenu}
1917
1927
  rowClassName="vs-datagrid--row"
1918
1928
  rowHeight={null}
@@ -1,13 +1,13 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { useParams, Link } from 'react-router-dom';
1
+ import React, {useEffect, useState} from 'react';
2
+ import {useParams, Link} from 'react-router-dom';
3
3
  import moment from 'moment';
4
4
  import parse from 'html-react-parser';
5
5
  import Popup from 'reactjs-popup';
6
- import { motion } from 'framer-motion';
6
+ import {motion} from 'framer-motion';
7
7
  import Dropzone from 'react-dropzone';
8
- import { confirmAlert } from 'react-confirm-alert';
8
+ import {confirmAlert} from 'react-confirm-alert';
9
9
  import truncate from 'truncate';
10
- import { CopyToClipboard } from 'react-copy-to-clipboard';
10
+ import {CopyToClipboard} from 'react-copy-to-clipboard';
11
11
  import {
12
12
  CircleCheck,
13
13
  CircleChevronRight,
@@ -22,17 +22,18 @@ import CustomFetch from '../Fetch';
22
22
  import Form from '../Form';
23
23
  import Table from '../DataGrid';
24
24
  import TableFilter from '../TableFilter';
25
- import { toast } from 'react-toastify';
25
+ import {toast} from 'react-toastify';
26
26
 
27
- function GenericDetail({ setting, urlParam, userProfile }) {
27
+ function GenericDetail({setting, urlParam, userProfile}) {
28
28
  const routeParams = useParams();
29
- const { filters, page, stages, tabs } = setting;
29
+ const {filters, page, stages, tabs} = setting;
30
30
 
31
31
  /** Fileupload states */
32
32
  const [files, setFiles] = useState([]);
33
33
  const [loadingProgress, setLoadingProgress] = useState(0);
34
34
 
35
35
  /** General States */
36
+ const [activeStage, setActiveStage] = useState('');
36
37
  const [config, setConfig] = useState({});
37
38
  const [data, setData] = useState({});
38
39
  const [dataReload, setDataReload] = useState(0);
@@ -41,32 +42,40 @@ function GenericDetail({ setting, urlParam, userProfile }) {
41
42
  const [windowHeight, setWindowHeight] = useState(window.innerHeight);
42
43
 
43
44
  /** General Functions */
44
- const handleStageUpdate = async (stage) => {
45
- const activeTab = subnav.find((s) => s.show === true);
46
-
47
- if (activeTab) {
48
- const activeTabConfig = tabs.find((t) => t.id === activeTab.id);
49
-
50
- if (
51
- activeTabConfig.stages.url &&
52
- activeTabConfig.stages.url !== '' &&
53
- activeTabConfig.stages.key &&
54
- activeTabConfig.stages.key !== '' &&
55
- activeTabConfig.stages.urlParam &&
56
- activeTabConfig.stages.urlParam !== ''
57
- ) {
58
- const url = `${activeTabConfig.stages.url}/${routeParams[urlParam]}`;
59
-
60
- const res = await CustomFetch(url, 'POST', {
61
- [activeTabConfig.stages.key]: stage.id,
62
- });
63
-
64
- if (res.data.error === '') {
65
- handleReload();
45
+ const handleStageUpdate = async (stage, type) => {
46
+ try {
47
+ const activeTab = subnav.find((s) => s.show === true);
48
+
49
+ if (activeTab) {
50
+ const activeTabConfig = tabs.find((t) => t.id === activeTab.id);
51
+
52
+ if (type === 'view') {
53
+ setActiveStage(stage.id);
66
54
  } else {
67
- toast.error(res.data.error);
55
+ if (
56
+ activeTabConfig.stages.url &&
57
+ activeTabConfig.stages.url !== '' &&
58
+ activeTabConfig.stages.key &&
59
+ activeTabConfig.stages.key !== '' &&
60
+ activeTabConfig.stages.urlParam &&
61
+ activeTabConfig.stages.urlParam !== ''
62
+ ) {
63
+ const url = `${activeTabConfig.stages.url}/${routeParams[urlParam]}`;
64
+
65
+ const res = await CustomFetch(url, 'POST', {
66
+ [activeTabConfig.stages.key]: stage.id,
67
+ });
68
+
69
+ if (res.data.error === '') {
70
+ handleReload();
71
+ } else {
72
+ toast.error(res.data.error);
73
+ }
74
+ }
68
75
  }
69
76
  }
77
+ } catch (error) {
78
+ console.error(error);
70
79
  }
71
80
  };
72
81
 
@@ -108,7 +117,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
108
117
  };
109
118
 
110
119
  const renderValue = (item, data) => {
111
- const { type, id, relation, relationKey, size, truncateLength } = item;
120
+ const {type, id, relation, relationKey, size, truncateLength} = item;
112
121
  const value =
113
122
  relation && relation.length > 0
114
123
  ? getValueFromData(data, [...relation], id)
@@ -132,8 +141,8 @@ function GenericDetail({ setting, urlParam, userProfile }) {
132
141
 
133
142
  return name !== '' && description !== '' && formattedDate !== ''
134
143
  ? parse(
135
- `<br /><p>${name} - ${formattedDate}</p><p>${description}</p>`
136
- )
144
+ `<br /><p>${name} - ${formattedDate}</p><p>${description}</p>`
145
+ )
137
146
  : null;
138
147
  };
139
148
 
@@ -281,7 +290,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
281
290
  <div className="progress">
282
291
  <motion.div
283
292
  className="progress__bar"
284
- initial={{ width: '0%' }}
293
+ initial={{width: '0%'}}
285
294
  animate={{
286
295
  width: loadingProgress + '%',
287
296
  }}
@@ -309,7 +318,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
309
318
  name: file.name,
310
319
  size: file.size,
311
320
  extension:
312
- response.extension,
321
+ response.extension,
313
322
  };
314
323
 
315
324
  CustomFetch(
@@ -330,7 +339,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
330
339
  });
331
340
  }}
332
341
  >
333
- {({ getRootProps, getInputProps }) => (
342
+ {({getRootProps, getInputProps}) => (
334
343
  <section className="dropzone__container">
335
344
  <div {...getRootProps()}>
336
345
  <input
@@ -421,7 +430,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
421
430
  routeParams[
422
431
  formField
423
432
  .urlParam
424
- ]
433
+ ]
425
434
  );
426
435
  }
427
436
  );
@@ -451,10 +460,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
451
460
  <div className="grid__full">
452
461
  {formConfig.stages.data.map(
453
462
  (stage) =>
454
- data[
455
- formConfig
456
- .stages.key
457
- ] === stage.id && (
463
+ parseInt(activeStage) === stage.id && (
458
464
  <React.Fragment
459
465
  key={`stage-form-${stage.id}`}
460
466
  >
@@ -479,7 +485,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
479
485
  columnId={
480
486
  routeParams[
481
487
  urlParam
482
- ]
488
+ ]
483
489
  }
484
490
  formSettings={
485
491
  stage.form
@@ -543,7 +549,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
543
549
  'update',
544
550
  routeParams[
545
551
  urlParam
546
- ]
552
+ ]
547
553
  )
548
554
  }
549
555
  >
@@ -567,7 +573,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
567
573
  </div>
568
574
  {section.content &&
569
575
  section.content.length >
570
- 0 && (
576
+ 0 && (
571
577
  <ul className="customer__overview">
572
578
  {section.content.map(
573
579
  (
@@ -701,21 +707,21 @@ function GenericDetail({ setting, urlParam, userProfile }) {
701
707
  (field.type ===
702
708
  'multi-dropdown-ajax' ||
703
709
  field.type ===
704
- 'multi-dropdown')
710
+ 'multi-dropdown')
705
711
  ) {
706
712
  field.value = {
707
713
  value: routeParams[
708
714
  field.urlParam
709
- ],
715
+ ],
710
716
  label: data[
711
717
  field.relationName
712
- ],
718
+ ],
713
719
  };
714
720
  } else {
715
721
  field.value =
716
722
  routeParams[
717
723
  field.urlParam
718
- ];
724
+ ];
719
725
  }
720
726
  }
721
727
 
@@ -756,6 +762,21 @@ function GenericDetail({ setting, urlParam, userProfile }) {
756
762
  }
757
763
  }, [subnav, tabs, routeParams]);
758
764
 
765
+
766
+ useEffect(() => {
767
+ if (tabs && tabs.length > 0 && data && data.id) {
768
+ const activeTab = subnav.find((s) => s.show === true);
769
+
770
+ if (activeTab) {
771
+ const activeTabConfig = tabs.find((t) => t.id === activeTab.id);
772
+
773
+ if (activeTabConfig.stages && activeTabConfig.stages.key) {
774
+ setActiveStage(data[activeTabConfig.stages.key]);
775
+ }
776
+ }
777
+ }
778
+ }, [data, tabs]);
779
+
759
780
  useEffect(() => {
760
781
  if (routeParams[urlParam] && routeParams[urlParam] > 0) {
761
782
  CustomFetch(
@@ -829,7 +850,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
829
850
  >
830
851
  {page && page.title ? page.title : null}
831
852
  </Link>{' '}
832
- <CircleChevronRight strokeWidth={2} size={18} />{' '}
853
+ <CircleChevronRight strokeWidth={2} size={18}/>{' '}
833
854
  {data && data[page.titleKey]
834
855
  ? data[page.titleKey]
835
856
  : null}
@@ -870,7 +891,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
870
891
  onClick={(e) => {
871
892
  e.preventDefault();
872
893
 
873
- handleStageUpdate(stage);
894
+ handleStageUpdate(stage, stages.type);
874
895
  }}
875
896
  >
876
897
  <a>
@@ -895,7 +916,7 @@ function GenericDetail({ setting, urlParam, userProfile }) {
895
916
  <div className="grid">
896
917
  <div className="grid__subrow">
897
918
  <div className="grid__subnav">
898
- <TableFilter filters={subnav} setFilters={setSubnav} />
919
+ <TableFilter filters={subnav} setFilters={setSubnav}/>
899
920
  </div>
900
921
  <div className="grid__subcontent">
901
922
  {config ? renderContent() : null}
package/package.json CHANGED
@@ -44,7 +44,7 @@
44
44
  "react-dom": "^17.0.1"
45
45
  },
46
46
  "name": "@visns-studio/visns-components",
47
- "version": "2.6.2",
47
+ "version": "2.6.4",
48
48
  "description": "Various packages to assist in the development of our Custom Applications.",
49
49
  "main": "index.js",
50
50
  "scripts": {