@visns-studio/visns-components 4.7.4 → 4.7.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 +1 -1
- package/src/components/crm/Navigation.jsx +11 -0
- package/src/components/crm/SwitchAccount.jsx +138 -0
- package/src/components/crm/auth/styles/Profile.module.scss +24 -11
- package/src/components/crm/generic/GenericFormBuilder.jsx +11 -1
- package/src/components/crm/generic/NotificationList.jsx +36 -36
- package/src/components/crm/generic/styles/NotificationList.module.scss +19 -25
- package/src/components/crm/styles/SwitchAccount.module.scss +69 -0
package/package.json
CHANGED
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
76
76
|
},
|
|
77
77
|
"name": "@visns-studio/visns-components",
|
|
78
|
-
"version": "4.7.
|
|
78
|
+
"version": "4.7.6",
|
|
79
79
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
80
80
|
"main": "src/index.js",
|
|
81
81
|
"files": [
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
} from 'akar-icons';
|
|
44
44
|
import CustomFetch from './Fetch';
|
|
45
45
|
import Notification from './Notification';
|
|
46
|
+
import SwitchAccount from './SwitchAccount';
|
|
46
47
|
import styles from './styles/Navigation.module.scss';
|
|
47
48
|
|
|
48
49
|
const SearchComponent = ({
|
|
@@ -249,6 +250,16 @@ function Navigation({
|
|
|
249
250
|
<Notification setSystemAuth={setSystemAuth} />
|
|
250
251
|
</li>
|
|
251
252
|
);
|
|
253
|
+
} else if (n.id === 'switchAccount') {
|
|
254
|
+
return (
|
|
255
|
+
<li>
|
|
256
|
+
<SwitchAccount
|
|
257
|
+
setSystemAuth={setSystemAuth}
|
|
258
|
+
setting={n}
|
|
259
|
+
userProfile={userProfile}
|
|
260
|
+
/>
|
|
261
|
+
</li>
|
|
262
|
+
);
|
|
252
263
|
} else if (n.id === 'logout') {
|
|
253
264
|
const IconComponent = iconComponents[n.icon];
|
|
254
265
|
return (
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router-dom';
|
|
3
|
+
import { ArrowCycle, ChevronVertical } from 'akar-icons';
|
|
4
|
+
import CustomFetch from './Fetch';
|
|
5
|
+
import styles from './styles/SwitchAccount.module.scss';
|
|
6
|
+
|
|
7
|
+
function SwitchAccount({ setSystemAuth, setting, userProfile }) {
|
|
8
|
+
const navigate = useNavigate();
|
|
9
|
+
const wrapperRef = useRef(null);
|
|
10
|
+
const [data, setData] = useState([]);
|
|
11
|
+
const [show, setShow] = useState(false);
|
|
12
|
+
const [activeAccountId, setActiveAccountId] = useState(
|
|
13
|
+
localStorage.getItem('selectedAccountId') || null
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const ucfirst = (str) => {
|
|
17
|
+
if (!str) return str; // Return the string if it's empty or not a string
|
|
18
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const pluralise = (str) => {
|
|
22
|
+
if (!str) return str; // Return the string if it's empty or not a string
|
|
23
|
+
|
|
24
|
+
// Convert the string to lowercase
|
|
25
|
+
let lowerStr = str.toLowerCase();
|
|
26
|
+
|
|
27
|
+
// Check if the string is pluralized
|
|
28
|
+
if (!lowerStr.endsWith('s')) {
|
|
29
|
+
return lowerStr + 's';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return lowerStr;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const handleSelectAccount = (id) => {
|
|
36
|
+
localStorage.setItem('selectedAccountId', id);
|
|
37
|
+
setActiveAccountId(id); // Update the state with the selected account
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleClickOutside = useCallback((e) => {
|
|
41
|
+
if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
|
|
42
|
+
setShow(false);
|
|
43
|
+
}
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const toggleNotification = useCallback(() => {
|
|
47
|
+
setShow((prevShow) => !prevShow);
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
const fetchData = async () => {
|
|
51
|
+
try {
|
|
52
|
+
const res = await CustomFetch(
|
|
53
|
+
`/ajax/${pluralise(setting.model)}/table`,
|
|
54
|
+
'POST',
|
|
55
|
+
{}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
setData(res.data.data);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.info(error);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
fetchData();
|
|
66
|
+
|
|
67
|
+
document.addEventListener('mousedown', handleClickOutside, false);
|
|
68
|
+
|
|
69
|
+
return () => {
|
|
70
|
+
document.removeEventListener(
|
|
71
|
+
'mousedown',
|
|
72
|
+
handleClickOutside,
|
|
73
|
+
false
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
}, [handleClickOutside]);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div>
|
|
80
|
+
<a
|
|
81
|
+
href="#"
|
|
82
|
+
onClick={toggleNotification}
|
|
83
|
+
data-tooltip-id="system-tooltip"
|
|
84
|
+
data-tooltip-content={setting.label}
|
|
85
|
+
>
|
|
86
|
+
<ArrowCycle size={16} verticalAlign="middle" />
|
|
87
|
+
</a>
|
|
88
|
+
|
|
89
|
+
{show && (
|
|
90
|
+
<div ref={wrapperRef}>
|
|
91
|
+
{data.length > 0 ? (
|
|
92
|
+
<div className={styles.notibox}>
|
|
93
|
+
{data.map((item) => (
|
|
94
|
+
<div
|
|
95
|
+
className={styles['notibox-item']}
|
|
96
|
+
key={`item-${item.id}`}
|
|
97
|
+
>
|
|
98
|
+
{item[setting.labelKey]}
|
|
99
|
+
{parseInt(activeAccountId) ===
|
|
100
|
+
parseInt(item.id) ? (
|
|
101
|
+
<span className={styles.currentAccount}>
|
|
102
|
+
Current Active{' '}
|
|
103
|
+
{`${ucfirst(setting.model)} `}
|
|
104
|
+
</span>
|
|
105
|
+
) : (
|
|
106
|
+
<span
|
|
107
|
+
className={styles.switchBtn}
|
|
108
|
+
onClick={(e) => {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
|
|
111
|
+
handleSelectAccount(item.id);
|
|
112
|
+
}}
|
|
113
|
+
>
|
|
114
|
+
Select{' '}
|
|
115
|
+
{`${ucfirst(setting.model)} `}
|
|
116
|
+
<ChevronVertical
|
|
117
|
+
size={16}
|
|
118
|
+
fill="#20004d"
|
|
119
|
+
/>
|
|
120
|
+
</span>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
))}
|
|
124
|
+
</div>
|
|
125
|
+
) : (
|
|
126
|
+
<div className={styles.notibox}>
|
|
127
|
+
<div className={styles['notibox-item']}>
|
|
128
|
+
No {pluralise(setting.model)} available.
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export default SwitchAccount;
|
|
@@ -25,38 +25,51 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
25
25
|
align-items: flex-start;
|
|
26
26
|
flex-wrap: nowrap;
|
|
27
27
|
height: auto;
|
|
28
|
+
gap: 1rem;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
.grid__full {
|
|
31
32
|
width: 100%;
|
|
32
|
-
background:
|
|
33
|
+
background: var(--item-color);
|
|
33
34
|
border-radius: var(--br);
|
|
34
|
-
border: 1px solid var(--
|
|
35
|
+
border: 1px solid rgba(var(--item-color-rgb), 1.15);
|
|
35
36
|
box-sizing: border-box;
|
|
36
37
|
overflow: visible;
|
|
37
38
|
position: relative;
|
|
38
|
-
padding:
|
|
39
|
-
margin:
|
|
39
|
+
padding: 2px;
|
|
40
|
+
margin: 8px 0;
|
|
41
|
+
box-shadow: 0 4px 0 rgba(var(--primary-color-rgb), 0.05);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
.crmtitle {
|
|
43
45
|
border: none;
|
|
44
46
|
min-height: auto;
|
|
45
47
|
padding: 10px 20px;
|
|
46
|
-
margin:
|
|
47
|
-
background: var(--
|
|
48
|
+
margin: 0;
|
|
49
|
+
background: var(--tertiary-color);
|
|
48
50
|
border-radius: var(--br);
|
|
49
|
-
border: 1px solid var(--
|
|
51
|
+
border: 1px solid rgba(var(--item-color-rgb), 1.15);
|
|
50
52
|
position: relative;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
.crmtitle h1 {
|
|
54
56
|
font-weight: 700;
|
|
55
|
-
font-size: 1.
|
|
57
|
+
font-size: 1.45em;
|
|
56
58
|
margin: 0;
|
|
57
|
-
padding: 0.
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
padding: 0.65rem 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.crmtitle h1 a {
|
|
63
|
+
text-decoration: none;
|
|
64
|
+
color: rgba(var(--secondary-color-rgb), 1.1);
|
|
65
|
+
font-weight: 300;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.crmtitle h1 svg {
|
|
69
|
+
color: rgba(var(--primary-color-rgb), 0.25);
|
|
70
|
+
position: relative;
|
|
71
|
+
top: 2px;
|
|
72
|
+
margin: 0 0.25rem;
|
|
60
73
|
}
|
|
61
74
|
|
|
62
75
|
.grid__subrow {
|
|
@@ -54,10 +54,10 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
54
54
|
: []),
|
|
55
55
|
{ value: 'dynamicdata', label: 'Dynamic Data' },
|
|
56
56
|
{ value: 'file', label: 'File' },
|
|
57
|
-
{ value: 'plaintextheading', label: 'Heading' },
|
|
58
57
|
{ value: 'image', label: 'Image' },
|
|
59
58
|
{ value: 'number', label: 'Number' },
|
|
60
59
|
{ value: 'plaintext', label: 'Plain Text' },
|
|
60
|
+
{ value: 'plaintextheading', label: 'Heading' },
|
|
61
61
|
{ value: 'section', label: 'Section' },
|
|
62
62
|
{ value: 'signature', label: 'Signature' },
|
|
63
63
|
{ value: 'table_radio', label: 'Table (Radio)' },
|
|
@@ -1453,6 +1453,11 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
1453
1453
|
'checkbox',
|
|
1454
1454
|
'dropdown',
|
|
1455
1455
|
'dynamicdata',
|
|
1456
|
+
'file',
|
|
1457
|
+
'image',
|
|
1458
|
+
'plaintext',
|
|
1459
|
+
'plaintextheading',
|
|
1460
|
+
'section',
|
|
1456
1461
|
'signature',
|
|
1457
1462
|
'table',
|
|
1458
1463
|
].some(
|
|
@@ -1576,6 +1581,11 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
1576
1581
|
'checkbox',
|
|
1577
1582
|
'dropdown',
|
|
1578
1583
|
'dynamicdata',
|
|
1584
|
+
'file',
|
|
1585
|
+
'image',
|
|
1586
|
+
'plaintext',
|
|
1587
|
+
'plaintextheading',
|
|
1588
|
+
'section',
|
|
1579
1589
|
'signature',
|
|
1580
1590
|
'table',
|
|
1581
1591
|
].some(
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Table from '../DataGrid';
|
|
3
|
+
import styles from './styles/NotificationList.module.scss';
|
|
3
4
|
|
|
4
5
|
const NotificationList = () => {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const form = {
|
|
14
|
-
primaryKey: 'id',
|
|
15
|
-
url: '/ajax/notifications',
|
|
16
|
-
create: {},
|
|
17
|
-
update: {},
|
|
18
|
-
fields: [],
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const columns = [
|
|
22
|
-
{
|
|
23
|
-
id: 'data',
|
|
24
|
-
jsonData: 'label',
|
|
25
|
-
label: 'Label',
|
|
26
|
-
type: 'json',
|
|
6
|
+
const setting = {
|
|
7
|
+
ajaxSetting: {
|
|
8
|
+
url: '/ajax/user/notifications/table',
|
|
9
|
+
take: 25,
|
|
10
|
+
sortBy: 'id',
|
|
11
|
+
sort: 'desc',
|
|
12
|
+
where: [],
|
|
27
13
|
},
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
14
|
+
form: {
|
|
15
|
+
primaryKey: 'id',
|
|
16
|
+
url: '/ajax/user/notifications',
|
|
17
|
+
createDisable: true,
|
|
18
|
+
create: {},
|
|
19
|
+
update: {},
|
|
20
|
+
fields: [],
|
|
34
21
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
22
|
+
columns: [
|
|
23
|
+
{
|
|
24
|
+
id: 'data',
|
|
25
|
+
jsonData: 'label',
|
|
26
|
+
label: 'Label',
|
|
27
|
+
type: 'json',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'read_at',
|
|
31
|
+
label: 'Read At',
|
|
32
|
+
type: 'datetime',
|
|
33
|
+
minWidth: 200,
|
|
34
|
+
maxWidth: 200,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
settings: [],
|
|
38
|
+
};
|
|
39
39
|
return (
|
|
40
40
|
<div>
|
|
41
41
|
<div className={styles.grid}>
|
|
@@ -49,10 +49,10 @@ const NotificationList = () => {
|
|
|
49
49
|
<div className={styles.grid__row}>
|
|
50
50
|
<div className={styles.grid__full}>
|
|
51
51
|
<Table
|
|
52
|
-
ajaxSetting={ajaxSetting}
|
|
53
|
-
form={form}
|
|
54
|
-
columns={columns}
|
|
55
|
-
settings={settings}
|
|
52
|
+
ajaxSetting={setting.ajaxSetting}
|
|
53
|
+
form={setting.form}
|
|
54
|
+
columns={setting.columns}
|
|
55
|
+
settings={setting.settings}
|
|
56
56
|
/>
|
|
57
57
|
</div>
|
|
58
58
|
</div>
|
|
@@ -32,36 +32,30 @@
|
|
|
32
32
|
.crmtitle {
|
|
33
33
|
border: none;
|
|
34
34
|
min-height: auto;
|
|
35
|
-
padding:
|
|
35
|
+
padding: 10px 20px;
|
|
36
36
|
margin: 0;
|
|
37
|
-
background: var(--
|
|
37
|
+
background: var(--tertiary-color);
|
|
38
38
|
border-radius: var(--br);
|
|
39
39
|
border: 1px solid rgba(var(--item-color-rgb), 1.15);
|
|
40
40
|
position: relative;
|
|
41
|
-
|
|
42
|
-
align-items: center;
|
|
41
|
+
}
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
display: flex;
|
|
51
|
-
align-items: center;
|
|
52
|
-
gap: 0.25rem;
|
|
43
|
+
.crmtitle h1 {
|
|
44
|
+
font-weight: 700;
|
|
45
|
+
font-size: 1.45em;
|
|
46
|
+
margin: 0;
|
|
47
|
+
padding: 0.65rem 0;
|
|
48
|
+
}
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
.crmtitle h1 a {
|
|
51
|
+
text-decoration: none;
|
|
52
|
+
color: rgba(var(--secondary-color-rgb), 1.1);
|
|
53
|
+
font-weight: 300;
|
|
54
|
+
}
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
max-width: 15px;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
56
|
+
.crmtitle h1 svg {
|
|
57
|
+
color: rgba(var(--primary-color-rgb), 0.25);
|
|
58
|
+
position: relative;
|
|
59
|
+
top: 2px;
|
|
60
|
+
margin: 0 0.25rem;
|
|
67
61
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
.notibox {
|
|
2
|
+
background: #fff;
|
|
3
|
+
border: 1px solid var(--primary-color-lighter);
|
|
4
|
+
border-top-color: rgb(204, 204, 204);
|
|
5
|
+
border-right-color: rgb(204, 204, 204);
|
|
6
|
+
border-bottom-color: rgb(204, 204, 204);
|
|
7
|
+
border-left-color: rgb(204, 204, 204);
|
|
8
|
+
border-color: rgba(0, 0, 0, 0.2);
|
|
9
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
10
|
+
display: block;
|
|
11
|
+
opacity: 1;
|
|
12
|
+
outline: none;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
position: absolute;
|
|
15
|
+
padding: 6px;
|
|
16
|
+
border-radius: var(--br);
|
|
17
|
+
width: 550px;
|
|
18
|
+
overflow-y: scroll;
|
|
19
|
+
transform: translateX(-470px);
|
|
20
|
+
text-align: left;
|
|
21
|
+
color: var(--paragraph-color);
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
24
|
+
z-index: 999;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.notibox-item {
|
|
28
|
+
width: 100%;
|
|
29
|
+
display: block;
|
|
30
|
+
background: #f0f0f0;
|
|
31
|
+
border-radius: var(--br);
|
|
32
|
+
padding: 9px 36px 8px 6px;
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
margin-bottom: 4px;
|
|
35
|
+
position: relative;
|
|
36
|
+
|
|
37
|
+
span {
|
|
38
|
+
color: var(--paragraph-color);
|
|
39
|
+
font-size: 80%;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
> button {
|
|
43
|
+
position: absolute;
|
|
44
|
+
right: 6px;
|
|
45
|
+
top: 5px;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
padding: 0;
|
|
48
|
+
margin: 0;
|
|
49
|
+
outline: none;
|
|
50
|
+
background: none;
|
|
51
|
+
border: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.switchBtn {
|
|
55
|
+
float: right;
|
|
56
|
+
color: var(--paragraph-color);
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.currentAccount {
|
|
61
|
+
float: right;
|
|
62
|
+
color: darken(#f0f0f0, 25%);
|
|
63
|
+
line-height: 1.25;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.noti-read {
|
|
67
|
+
color: var(--primary-color);
|
|
68
|
+
}
|
|
69
|
+
}
|