Merge pull request #28 from Kitzanos/master-sync/07-12-2024
Master sync/07 12 2024
This commit is contained in:
1
.env
1
.env
@@ -1,6 +1,7 @@
|
|||||||
REACT_APP_TAB_TITLE=Gepafin
|
REACT_APP_TAB_TITLE=Gepafin
|
||||||
REACT_APP_API_EXECUTION_ADDRESS=https://api-dev-gepafin.memento.credit/v1
|
REACT_APP_API_EXECUTION_ADDRESS=https://api-dev-gepafin.memento.credit/v1
|
||||||
REACT_APP_API_ADDRESS=https://api-dev-gepafin.memento.credit
|
REACT_APP_API_ADDRESS=https://api-dev-gepafin.memento.credit
|
||||||
|
REACT_APP_API_ADDRESS_WS=https://api-dev-gepafin.memento.credit/wss
|
||||||
REACT_APP_LOGO_FILENAME=gepafin-logo.svg
|
REACT_APP_LOGO_FILENAME=gepafin-logo.svg
|
||||||
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
|
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
|
||||||
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
|
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
REACT_APP_TAB_TITLE=Gepafin
|
REACT_APP_TAB_TITLE=Gepafin
|
||||||
REACT_APP_API_EXECUTION_ADDRESS=https://api-dev-gepafin.memento.credit/v1
|
REACT_APP_API_EXECUTION_ADDRESS=https://api-dev-gepafin.memento.credit/v1
|
||||||
REACT_APP_API_ADDRESS=https://api-dev-gepafin.memento.credit
|
REACT_APP_API_ADDRESS=https://api-dev-gepafin.memento.credit
|
||||||
|
REACT_APP_API_ADDRESS_WS=https://api-dev-gepafin.memento.credit/wss
|
||||||
REACT_APP_LOGO_FILENAME=gepafin-logo.svg
|
REACT_APP_LOGO_FILENAME=gepafin-logo.svg
|
||||||
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
|
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
|
||||||
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
|
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
REACT_APP_TAB_TITLE=Gepafin
|
REACT_APP_TAB_TITLE=Gepafin
|
||||||
REACT_APP_API_EXECUTION_ADDRESS=https://bandi-api.gepafin.it/v1
|
REACT_APP_API_EXECUTION_ADDRESS=https://bandi-api.gepafin.it/v1
|
||||||
REACT_APP_API_ADDRESS=https://bandi-api.gepafin.it
|
REACT_APP_API_ADDRESS=https://bandi-api.gepafin.it
|
||||||
|
REACT_APP_API_ADDRESS_WS=https://bandi-api.gepafin.it/wss
|
||||||
REACT_APP_LOGO_FILENAME=gepafin-logo.svg
|
REACT_APP_LOGO_FILENAME=gepafin-logo.svg
|
||||||
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
|
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
|
||||||
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
|
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"@emotion/styled": "11.13.0",
|
"@emotion/styled": "11.13.0",
|
||||||
"@number-flow/react": "0.4.2",
|
"@number-flow/react": "0.4.2",
|
||||||
"@sentry/browser": "^8.42.0",
|
"@sentry/browser": "^8.42.0",
|
||||||
|
"@stomp/stompjs": "^7.0.0",
|
||||||
"@tanstack/react-table": "^8.20.5",
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@wordpress/i18n": "5.8.0",
|
"@wordpress/i18n": "5.8.0",
|
||||||
"@wordpress/react-i18n": "4.8.0",
|
"@wordpress/react-i18n": "4.8.0",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"react-hook-form": "7.53.0",
|
"react-hook-form": "7.53.0",
|
||||||
"react-router-dom": "6.26.2",
|
"react-router-dom": "6.26.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"sockjs-client": "^1.6.1",
|
||||||
"validate.js": "0.13.1",
|
"validate.js": "0.13.1",
|
||||||
"zustand": "4.5.4",
|
"zustand": "4.5.4",
|
||||||
"zustand-x": "3.0.4"
|
"zustand-x": "3.0.4"
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
|
|
||||||
.appPageSection__pMeta {
|
.appPageSection__pMeta {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
break-inside: avoid;
|
||||||
|
|
||||||
span:nth-of-type(1) {
|
span:nth-of-type(1) {
|
||||||
max-width: 30%;
|
max-width: 30%;
|
||||||
@@ -435,6 +436,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.appPageSection__emailTemplate {
|
||||||
|
> div {
|
||||||
|
max-width: 100%!important;
|
||||||
|
> div {
|
||||||
|
max-width: 100%!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
.appPageSection {
|
.appPageSection {
|
||||||
&.columns {
|
&.columns {
|
||||||
|
|||||||
55
src/assets/scss/components/notificationsSidebar.scss
Normal file
55
src/assets/scss/components/notificationsSidebar.scss
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
.notificationsIcon {
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsSidebar {
|
||||||
|
max-width: 360px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsSidebar__loading {
|
||||||
|
padding: 30px 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsSidebar__list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsSidebar__listItem {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 15px 0;
|
||||||
|
border-bottom: 1px solid #e7e7e7;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--primary-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsSidebar__listItemContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsSidebar__listItemChosen {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
container-name: big-badges-grid;
|
container-name: big-badges-grid;
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
|
|
||||||
|
&.grid-small {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.statsBigBadges__grid .statsBigBadges__gridItem span {
|
.statsBigBadges__grid .statsBigBadges__gridItem span {
|
||||||
|
|||||||
@@ -45,3 +45,4 @@
|
|||||||
@import "./components/myTable.scss";
|
@import "./components/myTable.scss";
|
||||||
@import "./components/evaluation.scss";
|
@import "./components/evaluation.scss";
|
||||||
@import "./components/fieldsRepeater.scss";
|
@import "./components/fieldsRepeater.scss";
|
||||||
|
@import "./components/notificationsSidebar.scss";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { isEmpty } from 'ramda';
|
|||||||
import '@xyflow/react/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
|
|
||||||
// store
|
// store
|
||||||
import { useStore, storeSet, storeGet } from '../../store';
|
import { useStore, storeSet } from '../../store';
|
||||||
|
|
||||||
// nodes
|
// nodes
|
||||||
import NodeInitialForm from './components/NodeInitialForm';
|
import NodeInitialForm from './components/NodeInitialForm';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { classNames } from 'primereact/utils';
|
import { classNames } from 'primereact/utils';
|
||||||
import { isEmpty, isNil } from 'ramda';
|
import { isNil } from 'ramda';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { Controller } from 'react-hook-form';
|
import { Controller } from 'react-hook-form';
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import getDateFromISOstring from '../../../../helpers/getDateFromISOstring';
|
||||||
|
|
||||||
|
const NotificationItem = ({ item, clickFn }) => {
|
||||||
|
const handleClick = () => {
|
||||||
|
clickFn(item.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className="notificationsSidebar__listItem" onClick={handleClick}>
|
||||||
|
<div className="notificationsSidebar__listItemContent">
|
||||||
|
{item.status === 'READ'
|
||||||
|
? <p>{item.title}</p>
|
||||||
|
: <strong>{item.title}</strong>}
|
||||||
|
<span>{getDateFromISOstring(item.createdDate)}</span>
|
||||||
|
</div>
|
||||||
|
<i className="pi pi-angle-right"></i>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationItem;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import getDateFromISOstring from '../../../../helpers/getDateFromISOstring';
|
||||||
|
|
||||||
|
const NotificationItemChosen = ({ item, closeFn, markReadFn }) => {
|
||||||
|
return (
|
||||||
|
<div className="notificationsSidebar__listItemChosen">
|
||||||
|
<Button
|
||||||
|
style={{marginBottom: '20px'}}
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={closeFn}
|
||||||
|
label={__('Indietro', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
<strong>{item.title}</strong>
|
||||||
|
<span>{getDateFromISOstring(item.createdDate)}</span>
|
||||||
|
{item.message}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style={{marginTop: '20px'}}
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={() => markReadFn(item.id)}
|
||||||
|
label={__('Letto', 'gepafin')}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationItemChosen;
|
||||||
277
src/components/NotificationsSidebar/index.js
Normal file
277
src/components/NotificationsSidebar/index.js
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { head, isEmpty, pathOr } from 'ramda';
|
||||||
|
import SockJS from 'sockjs-client';
|
||||||
|
import { Stomp } from '@stomp/stompjs';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { storeGet, useStore } from '../../store';
|
||||||
|
|
||||||
|
// api
|
||||||
|
import NotificationService from '../../service/notification-service';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import { Badge } from 'primereact/badge';
|
||||||
|
import { Sidebar } from 'primereact/sidebar';
|
||||||
|
import { TabPanel, TabView } from 'primereact/tabview';
|
||||||
|
import NotificationItem from './components/NotificationItem';
|
||||||
|
import NotificationItemChosen from './components/NotificationItemChosen';
|
||||||
|
|
||||||
|
const socketUrl = process.env.REACT_APP_API_ADDRESS_WS;
|
||||||
|
|
||||||
|
const NotificationsSidebar = () => {
|
||||||
|
const chosenCompanyId = useStore().main.chosenCompanyId();
|
||||||
|
const userData = useStore().main.userData();
|
||||||
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [notificationsVisible, setNotificationsVisible] = useState(false);
|
||||||
|
const [notifications, setNotifications] = useState([]);
|
||||||
|
const [notificationsRead, setNotificationsRead] = useState([]);
|
||||||
|
const [chosenMsg, setChosenMsg] = useState({});
|
||||||
|
const socket = useRef(null);
|
||||||
|
const stomp = useRef(null);
|
||||||
|
const [currentSubscription, setCurrentSubscription] = useState(null);
|
||||||
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
|
|
||||||
|
// Handle tab change
|
||||||
|
const handleTabChange = (e) => {
|
||||||
|
setActiveIndex(e.index);
|
||||||
|
fetchTabData(e.index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchTabData = (index) => {
|
||||||
|
setChosenMsg({});
|
||||||
|
|
||||||
|
if (0 === index) {
|
||||||
|
fetchMessages();
|
||||||
|
} else {
|
||||||
|
fetchMessages('READ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const chooseNotification = (id) => {
|
||||||
|
const properItems = activeIndex === 0 ? notifications : notificationsRead;
|
||||||
|
const chosen = head(properItems.filter(o => o.id === id));
|
||||||
|
if (chosen) {
|
||||||
|
setChosenMsg(chosen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeChosenMsg = () => {
|
||||||
|
setChosenMsg({});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchMessages = (status = 'UNREAD') => {
|
||||||
|
const chosenCompanyId = storeGet.main.chosenCompanyId();
|
||||||
|
const userData = storeGet.main.userData();
|
||||||
|
const role = pathOr('', ['role', 'roleType'], userData);
|
||||||
|
|
||||||
|
if (currentSubscription) {
|
||||||
|
//console.log('UNsubscribed')
|
||||||
|
currentSubscription.unsubscribe();
|
||||||
|
setCurrentSubscription(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData.id && chosenCompanyId !== 0 && role === 'ROLE_BENEFICIARY') {
|
||||||
|
setLoading(true);
|
||||||
|
NotificationService.getNotifications(
|
||||||
|
userData.id,
|
||||||
|
status === 'UNREAD' ? getNotifications : getNotificationsRead,
|
||||||
|
errGetNotifications,
|
||||||
|
[
|
||||||
|
['status', status],
|
||||||
|
['companyId', chosenCompanyId]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if (isConnected && socket.current) {
|
||||||
|
subscribeTo(`/topic/notifications_user_${userData.id}_company_${chosenCompanyId}`)
|
||||||
|
}
|
||||||
|
} else if (userData.id && role !== 'ROLE_BENEFICIARY') {
|
||||||
|
setLoading(true);
|
||||||
|
NotificationService.getNotifications(
|
||||||
|
userData.id,
|
||||||
|
status === 'UNREAD' ? getNotifications : getNotificationsRead,
|
||||||
|
errGetNotifications,
|
||||||
|
[
|
||||||
|
['status', status]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if (isConnected && socket.current) {
|
||||||
|
subscribeTo(`/topic/notifications_user_${userData.id}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getNotifications = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
setNotifications(resp.data);
|
||||||
|
}
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getNotificationsRead = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
setNotificationsRead(resp.data);
|
||||||
|
}
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const errGetNotifications = (resp) => {
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeNotificationRead = (id) => {
|
||||||
|
NotificationService.notificationMakeRead(id, makeReadCallback, makeReadErrorCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeReadCallback = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
if (0 === activeIndex) {
|
||||||
|
const msgs = notifications.map(o => o.id === resp.data.id ? resp.data : o);
|
||||||
|
setNotifications(msgs);
|
||||||
|
} else {
|
||||||
|
const msgs = notificationsRead.map(o => o.id === resp.data.id ? resp.data : o);
|
||||||
|
setNotificationsRead(msgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeReadErrorCallback = (resp) => {
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const connectWebSocket = () => {
|
||||||
|
socket.current = new SockJS(socketUrl);
|
||||||
|
stomp.current = Stomp.over(socket.current);
|
||||||
|
|
||||||
|
stomp.current.configure({
|
||||||
|
debug: function(str) {
|
||||||
|
//console.log(str);
|
||||||
|
},
|
||||||
|
reconnectDelay: 5000,
|
||||||
|
heartbeatIncoming: 20000,
|
||||||
|
heartbeatOutgoing: 20000
|
||||||
|
});
|
||||||
|
|
||||||
|
stomp.current.connect(
|
||||||
|
{},
|
||||||
|
() => {
|
||||||
|
//console.log('Websocket connected');
|
||||||
|
setIsConnected(true);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
//console.error('WebSocket Connection Error:', error);
|
||||||
|
setIsConnected(false);
|
||||||
|
setTimeout(connectWebSocket, 5000);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const subscribeTo = (topic) => {
|
||||||
|
const subscription = stomp.current.subscribe(
|
||||||
|
topic,
|
||||||
|
(message) => {
|
||||||
|
try {
|
||||||
|
const notification = JSON.parse(message.body);
|
||||||
|
setNotifications(prev => [notification, ...prev]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing notification:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
setCurrentSubscription(subscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchMessages();
|
||||||
|
}, [chosenCompanyId, userData.id, isConnected]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
connectWebSocket();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (currentSubscription) {
|
||||||
|
currentSubscription.unsubscribe();
|
||||||
|
setCurrentSubscription(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stomp.current) {
|
||||||
|
stomp.current.disconnect(() => {
|
||||||
|
//console.log('WebSocket Disconnected');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<i className="pi pi-bell p-overlay-badge topBar__icon notificationsIcon"
|
||||||
|
onClick={() => setNotificationsVisible(true)}>
|
||||||
|
<Badge value={notifications.filter(o => o.status === 'UNREAD').length}></Badge>
|
||||||
|
</i>
|
||||||
|
<Sidebar
|
||||||
|
className="notificationsSidebar"
|
||||||
|
position="left"
|
||||||
|
visible={notificationsVisible}
|
||||||
|
onHide={() => setNotificationsVisible(false)}>
|
||||||
|
<TabView activeIndex={activeIndex} onTabChange={handleTabChange}>
|
||||||
|
<TabPanel header={__('Da leggere', 'gepafin')}>
|
||||||
|
{loading
|
||||||
|
? <div className="notificationsSidebar__loading">
|
||||||
|
<i className="pi pi-spin pi-spinner" style={{ fontSize: '2rem' }}></i>
|
||||||
|
</div>
|
||||||
|
: !isEmpty(chosenMsg)
|
||||||
|
? <NotificationItemChosen
|
||||||
|
item={chosenMsg}
|
||||||
|
closeFn={closeChosenMsg}
|
||||||
|
markReadFn={makeNotificationRead}/>
|
||||||
|
: (notifications.length > 0
|
||||||
|
? <ul className="notificationsSidebar__list">
|
||||||
|
{notifications.map(o => <NotificationItem
|
||||||
|
key={o.id}
|
||||||
|
item={o}
|
||||||
|
clickFn={chooseNotification}/>)}
|
||||||
|
</ul>
|
||||||
|
: <div className="notificationsSidebar__loading">
|
||||||
|
<i className="pi pi-megaphone" style={{ fontSize: '2rem' }}></i>
|
||||||
|
{__('Vuoto', 'gepafin')}
|
||||||
|
</div>)}
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel header={__('Letti', 'gepafin')}>
|
||||||
|
{loading
|
||||||
|
? <div className="notificationsSidebar__loading">
|
||||||
|
<i className="pi pi-spin pi-spinner" style={{ fontSize: '2rem' }}></i>
|
||||||
|
</div>
|
||||||
|
: !isEmpty(chosenMsg)
|
||||||
|
? <NotificationItemChosen
|
||||||
|
item={chosenMsg}
|
||||||
|
closeFn={closeChosenMsg}
|
||||||
|
markReadFn={makeNotificationRead}/>
|
||||||
|
: (notificationsRead.length > 0
|
||||||
|
? <ul className="notificationsSidebar__list">
|
||||||
|
{notificationsRead.map(o => <NotificationItem
|
||||||
|
key={o.id}
|
||||||
|
item={o}
|
||||||
|
clickFn={chooseNotification}/>)}
|
||||||
|
</ul>
|
||||||
|
:
|
||||||
|
<div className="notificationsSidebar__loading">
|
||||||
|
<i className="pi pi-megaphone" style={{ fontSize: '2rem' }}></i>
|
||||||
|
{__('Vuoto', 'gepafin')}
|
||||||
|
</div>)}
|
||||||
|
</TabPanel>
|
||||||
|
</TabView>
|
||||||
|
</Sidebar>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationsSidebar;
|
||||||
28
src/helpers/getStrippedHtmlBodyTags.js
Normal file
28
src/helpers/getStrippedHtmlBodyTags.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import parse from 'html-react-parser';
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
|
const getEmailTemplateForSoccorso = (content = '', fallback = '') => {
|
||||||
|
const config = {
|
||||||
|
FORBID_TAGS: ['html', 'body'],
|
||||||
|
WHOLE_DOCUMENT: false,
|
||||||
|
RETURN_DOM: false,
|
||||||
|
RETURN_DOM_FRAGMENT: false,
|
||||||
|
RETURN_DOM_IMPORT: false,
|
||||||
|
FORCE_BODY: false,
|
||||||
|
ADD_TAGS: ['*'],
|
||||||
|
ADD_ATTR: ['*']
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const wrappedHtml = `<div>${content}</div>`;
|
||||||
|
const cleaned = DOMPurify.sanitize(wrappedHtml, config);
|
||||||
|
|
||||||
|
const tempDiv = document.createElement('div');
|
||||||
|
tempDiv.innerHTML = cleaned;
|
||||||
|
return parse(tempDiv.innerHTML);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('DOMPurify cleaning error:', error);
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getEmailTemplateForSoccorso;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { storeSet } from '../store';
|
//import { storeSet } from '../store';
|
||||||
|
|
||||||
const set404FromErrorResponse = (data) => {
|
const set404FromErrorResponse = (data) => {
|
||||||
if (data && data.status === 'NOT_FOUND') {
|
if (data && data.status === 'NOT_FOUND') {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import LogoIcon from '../../../../icons/LogoIcon';
|
|||||||
import { IconField } from 'primereact/iconfield';
|
import { IconField } from 'primereact/iconfield';
|
||||||
import { InputIcon } from 'primereact/inputicon';
|
import { InputIcon } from 'primereact/inputicon';
|
||||||
import { InputText } from 'primereact/inputtext';
|
import { InputText } from 'primereact/inputtext';
|
||||||
import { Badge } from 'primereact/badge';
|
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import TopBarProfileMenu from '../../../../components/TopBarProfileMenu';
|
import TopBarProfileMenu from '../../../../components/TopBarProfileMenu';
|
||||||
|
import NotificationsSidebar from '../../../../components/NotificationsSidebar';
|
||||||
|
|
||||||
const AppTopbar = () => {
|
const AppTopbar = () => {
|
||||||
const menuLeft = useRef(null);
|
const menuLeft = useRef(null);
|
||||||
@@ -24,14 +24,13 @@ const AppTopbar = () => {
|
|||||||
<InputIcon className="pi pi-search"> </InputIcon>
|
<InputIcon className="pi pi-search"> </InputIcon>
|
||||||
<InputText v-model="value1" placeholder={__('Cerca', 'gepafin')} disabled={true}/>
|
<InputText v-model="value1" placeholder={__('Cerca', 'gepafin')} disabled={true}/>
|
||||||
</IconField>
|
</IconField>
|
||||||
<i className="pi pi-bell p-overlay-badge topBar__icon">
|
<NotificationsSidebar/>
|
||||||
<Badge value="0"></Badge>
|
|
||||||
</i>
|
|
||||||
<i className="pi pi-envelope topBar__icon"></i>
|
<i className="pi pi-envelope topBar__icon"></i>
|
||||||
{/*<i className="pi pi-envelope p-overlay-badge topBar__icon">
|
{/*<i className="pi pi-envelope p-overlay-badge topBar__icon">
|
||||||
<Badge severity="danger"></Badge>
|
<Badge severity="danger"></Badge>
|
||||||
</i>*/}
|
</i>*/}
|
||||||
<Button
|
<Button
|
||||||
|
type="button"
|
||||||
className="topBar__profileBtn"
|
className="topBar__profileBtn"
|
||||||
outlined
|
outlined
|
||||||
onClick={(event) => menuLeft.current.toggle(event)} aria-controls="topBar_profileMenu" aria-haspopup>
|
onClick={(event) => menuLeft.current.toggle(event)} aria-controls="topBar_profileMenu" aria-haspopup>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { isEmpty, head } from 'ramda';
|
import { isEmpty, head } from 'ramda';
|
||||||
import { klona } from 'klona';
|
import { klona } from 'klona';
|
||||||
@@ -29,6 +29,7 @@ const AddCompany = () => {
|
|||||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||||
const infoMsgs = useRef(null);
|
const infoMsgs = useRef(null);
|
||||||
const [, debouncedPivaValue, setInputPiva] = useDebounce('', 1000);
|
const [, debouncedPivaValue, setInputPiva] = useDebounce('', 1000);
|
||||||
|
const [vatCheckResponse, setVatCheckResponse] = useState({});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
@@ -54,14 +55,19 @@ const AddCompany = () => {
|
|||||||
address: '',
|
address: '',
|
||||||
companyName: ''
|
companyName: ''
|
||||||
}
|
}
|
||||||
|
setVatCheckResponse({});
|
||||||
Object.keys(formData).map(k => setValue(k, formData[k]));
|
Object.keys(formData).map(k => setValue(k, formData[k]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = (formData) => {
|
const onSubmit = (formData) => {
|
||||||
infoMsgs.current.clear();
|
infoMsgs.current.clear();
|
||||||
storeSet.main.setAsyncRequest();
|
storeSet.main.setAsyncRequest();
|
||||||
|
const submitData = {
|
||||||
|
...formData,
|
||||||
|
vatCheckResponse
|
||||||
|
}
|
||||||
|
|
||||||
CompanyService.createCompany(formData, updateCallback, updateError);
|
CompanyService.createCompany(submitData, updateCallback, updateError);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateCallback = (data) => {
|
const updateCallback = (data) => {
|
||||||
@@ -109,7 +115,7 @@ const AddCompany = () => {
|
|||||||
|
|
||||||
const checkVatCallback = (data) => {
|
const checkVatCallback = (data) => {
|
||||||
if (data.status === 'SUCCESS') {
|
if (data.status === 'SUCCESS') {
|
||||||
const resp = data.data.data;
|
const resp = data.data.vatCheckResponse.data;
|
||||||
if (!isEmpty(resp)) {
|
if (!isEmpty(resp)) {
|
||||||
const {
|
const {
|
||||||
cap, cf, denominazione, piva, indirizzo, comune, dettaglio: { pec }
|
cap, cf, denominazione, piva, indirizzo, comune, dettaglio: { pec }
|
||||||
@@ -126,6 +132,7 @@ const AddCompany = () => {
|
|||||||
companyName: denominazione
|
companyName: denominazione
|
||||||
}
|
}
|
||||||
Object.keys(formData).map(k => setValue(k, formData[k]));
|
Object.keys(formData).map(k => setValue(k, formData[k]));
|
||||||
|
setVatCheckResponse(data.data.vatCheckResponse);
|
||||||
}
|
}
|
||||||
//setData(getFormattedBandiData(data.data));
|
//setData(getFormattedBandiData(data.data));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const BandoApplicationPreview = () => {
|
|||||||
const [formData, setFormData] = useState([]);
|
const [formData, setFormData] = useState([]);
|
||||||
const [formInitialData, setFormInitialData] = useState(null);
|
const [formInitialData, setFormInitialData] = useState(null);
|
||||||
const [bandoTitle, setBandoTitle] = useState('');
|
const [bandoTitle, setBandoTitle] = useState('');
|
||||||
const [bandoId, setBandoId] = useState(0);
|
const [, setBandoId] = useState(0);
|
||||||
const [formId, setFormId] = useState('');
|
const [formId, setFormId] = useState('');
|
||||||
const [totalSteps, setTotalSteps] = useState(0);
|
const [totalSteps, setTotalSteps] = useState(0);
|
||||||
const [applicationStatus, setApplicationStatus] = useState('');
|
const [applicationStatus, setApplicationStatus] = useState('');
|
||||||
@@ -86,8 +86,8 @@ const BandoApplicationPreview = () => {
|
|||||||
ApplicationService.validateApplication(applId, {}, validateApplicationCallback, errValidateApplicationCallback);
|
ApplicationService.validateApplication(applId, {}, validateApplicationCallback, errValidateApplicationCallback);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = () => {
|
/*const onSubmit = () => {
|
||||||
};
|
};*/
|
||||||
|
|
||||||
const validateApplicationCallback = (data) => {
|
const validateApplicationCallback = (data) => {
|
||||||
if (data.status === 'SUCCESS') {
|
if (data.status === 'SUCCESS') {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
|
|||||||
placeholder: __('Segnaposto', 'gepafin'),
|
placeholder: __('Segnaposto', 'gepafin'),
|
||||||
step: __('Numero Decimali', 'gepafin'),
|
step: __('Numero Decimali', 'gepafin'),
|
||||||
isRequestedAmount: __('Importo richiesto', 'gepafin'),
|
isRequestedAmount: __('Importo richiesto', 'gepafin'),
|
||||||
|
isDelegation: __('Delega', 'gepafin'),
|
||||||
options: __('Opzioni', 'gepafin'),
|
options: __('Opzioni', 'gepafin'),
|
||||||
mime: __('Tipo di file', 'gepafin'),
|
mime: __('Tipo di file', 'gepafin'),
|
||||||
text: __('Testo formattato', 'gepafin'),
|
text: __('Testo formattato', 'gepafin'),
|
||||||
@@ -80,7 +81,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
|
|||||||
name={setting.name}
|
name={setting.name}
|
||||||
bandoStatus={bandoStatus}
|
bandoStatus={bandoStatus}
|
||||||
setDataFn={updateDataFn}/>
|
setDataFn={updateDataFn}/>
|
||||||
} else if (setting.name === 'isRequestedAmount') {
|
} else if (['isRequestedAmount', 'isDelegation'].includes(setting.name)) {
|
||||||
return <InputSwitch
|
return <InputSwitch
|
||||||
checked={setting.value}
|
checked={setting.value}
|
||||||
onChange={(e) => changeFn(e.value, setting.name)}/>
|
onChange={(e) => changeFn(e.value, setting.name)}/>
|
||||||
|
|||||||
@@ -57,6 +57,23 @@ const MyLatestSubmissionsTable = () => {
|
|||||||
setLocalAsyncRequest(false);
|
setLocalAsyncRequest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDeleteApplication = (id) => {
|
||||||
|
setLocalAsyncRequest(true);
|
||||||
|
ApplicationService.deleteApplication(id, (resp) => delApplCallback(resp, id), errDelApplCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delApplCallback = (resp, id) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
const newItems = items.filter(o => o.id !== id);
|
||||||
|
setItems(newItems);
|
||||||
|
}
|
||||||
|
setLocalAsyncRequest(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const errDelApplCallback = (data) => {
|
||||||
|
setLocalAsyncRequest(false);
|
||||||
|
}
|
||||||
|
|
||||||
const getFormattedBandiData = (data) => {
|
const getFormattedBandiData = (data) => {
|
||||||
return [...(data || [])].map((d) => {
|
return [...(data || [])].map((d) => {
|
||||||
d.callEndDate = new Date(d.callEndDate);
|
d.callEndDate = new Date(d.callEndDate);
|
||||||
@@ -130,7 +147,8 @@ const MyLatestSubmissionsTable = () => {
|
|||||||
const statusFilterTemplate = (options) => {
|
const statusFilterTemplate = (options) => {
|
||||||
return <Dropdown value={options.value} options={statuses}
|
return <Dropdown value={options.value} options={statuses}
|
||||||
onChange={(e) => options.filterCallback(e.value, options.index)}
|
onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||||
itemTemplate={statusItemTemplate} placeholder={translationStrings.selectOneLabel} className="p-column-filter"
|
itemTemplate={statusItemTemplate} placeholder={translationStrings.selectOneLabel}
|
||||||
|
className="p-column-filter"
|
||||||
showClear/>;
|
showClear/>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,13 +161,24 @@ const MyLatestSubmissionsTable = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const actionsBodyTemplate = (rowData) => {
|
const actionsBodyTemplate = (rowData) => {
|
||||||
return <Link to={`/imieibandi/${rowData.id}`}>
|
return 'DRAFT' === rowData.status
|
||||||
{'DRAFT' === rowData.status
|
? <div className="appPageSection__tableActions lessGap">
|
||||||
? <Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small"
|
<Link to={`/imieibandi/${rowData.id}`}>
|
||||||
|
<Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small"
|
||||||
iconPos="right"/>
|
iconPos="right"/>
|
||||||
: <Button severity="info" label={__('Mostra', 'gepafin')} icon="pi pi-eye" size="small"
|
|
||||||
iconPos="right"/>}
|
|
||||||
</Link>
|
</Link>
|
||||||
|
<Button severity="danger"
|
||||||
|
onClick={() => handleDeleteApplication(rowData.id)}
|
||||||
|
label={__('Cancella', 'gepafin')}
|
||||||
|
icon="pi pi-trash"
|
||||||
|
size="small"
|
||||||
|
iconPos="right"/>
|
||||||
|
</div>
|
||||||
|
: <Link to={`/imieibandi/${rowData.id}`}>
|
||||||
|
<Button severity="info" label={__('Mostra', 'gepafin')} icon="pi pi-eye" size="small"
|
||||||
|
iconPos="right"/>
|
||||||
|
</Link>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const header = renderHeader();
|
const header = renderHeader();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ const RepeaterFields = ({
|
|||||||
className="fieldsRepeater__addNew"
|
className="fieldsRepeater__addNew"
|
||||||
outlined
|
outlined
|
||||||
type="button"
|
type="button"
|
||||||
disabled={watchFields && watchFields.filter(o => isEmpty(o.nameValue) || isEmpty(o.fileValue)).length > 0 || shouldDisable}
|
disabled={(watchFields && watchFields.filter(o => isEmpty(o.nameValue) || isEmpty(o.fileValue)).length > 0) || shouldDisable}
|
||||||
onClick={addNew}
|
onClick={addNew}
|
||||||
label={__('Aggiungi nuovo file', 'gepafin')}
|
label={__('Aggiungi nuovo file', 'gepafin')}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { isEmpty, pathOr, head } from 'ramda';
|
|||||||
import { klona } from 'klona';
|
import { klona } from 'klona';
|
||||||
import { wrap } from 'object-path-immutable';
|
import { wrap } from 'object-path-immutable';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import emailjs from '@emailjs/browser';
|
//import emailjs from '@emailjs/browser';
|
||||||
//import { useNavigate } from 'react-router-dom';
|
//import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
// store
|
// store
|
||||||
@@ -27,7 +27,7 @@ import { InputText } from 'primereact/inputtext';
|
|||||||
import { Toast } from 'primereact/toast';
|
import { Toast } from 'primereact/toast';
|
||||||
//import getFormatedFileSizeText from '../../helpers/getFormatedFileSizeText';
|
//import getFormatedFileSizeText from '../../helpers/getFormatedFileSizeText';
|
||||||
//import { defaultMaxFileSize } from '../../configData';
|
//import { defaultMaxFileSize } from '../../configData';
|
||||||
import { Dialog } from 'primereact/dialog';
|
//import { Dialog } from 'primereact/dialog';
|
||||||
import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup';
|
import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup';
|
||||||
|
|
||||||
const ProfileCompany = () => {
|
const ProfileCompany = () => {
|
||||||
@@ -38,7 +38,7 @@ const ProfileCompany = () => {
|
|||||||
const [formInitialData, setFormInitialData] = useState({});
|
const [formInitialData, setFormInitialData] = useState({});
|
||||||
const [delegaData, setDelegaData] = useState({});
|
const [delegaData, setDelegaData] = useState({});
|
||||||
//const [delega, setDelega] = useState([]);
|
//const [delega, setDelega] = useState([]);
|
||||||
const [isVisibleRemoveDialog, setIsVisibleRemoveDialog] = useState(false);
|
//const [isVisibleRemoveDialog, setIsVisibleRemoveDialog] = useState(false);
|
||||||
const { delegaFirstName = '', delegaLastName = '', delegaCodiceFiscale = '' } = delegaData;
|
const { delegaFirstName = '', delegaLastName = '', delegaCodiceFiscale = '' } = delegaData;
|
||||||
const toast = useRef(null);
|
const toast = useRef(null);
|
||||||
//const navigate = useNavigate();
|
//const navigate = useNavigate();
|
||||||
@@ -212,22 +212,22 @@ const ProfileCompany = () => {
|
|||||||
defaultFocus: 'reject',
|
defaultFocus: 'reject',
|
||||||
acceptClassName: 'p-button-danger',
|
acceptClassName: 'p-button-danger',
|
||||||
accept: () => {
|
accept: () => {
|
||||||
doRemoveCompany();
|
doRemoveCompanyAPI();
|
||||||
},
|
},
|
||||||
reject: () => {
|
reject: () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const headerRemoveDialog = () => {
|
/*const headerRemoveDialog = () => {
|
||||||
return <span>{__('Rimuovi azienda', 'gepafin')}</span>
|
return <span>{__('Rimuovi azienda', 'gepafin')}</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
const hideRemoveDialog = () => {
|
const hideRemoveDialog = () => {
|
||||||
setIsVisibleRemoveDialog(false);
|
setIsVisibleRemoveDialog(false);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
const doRemoveCompany = () => {
|
/*const doRemoveCompany = () => {
|
||||||
const userData = storeGet.main.userData();
|
const userData = storeGet.main.userData();
|
||||||
let chosenCompany = {};
|
let chosenCompany = {};
|
||||||
|
|
||||||
@@ -251,13 +251,13 @@ const ProfileCompany = () => {
|
|||||||
publicKey: 'TPWwaPLM2dDuEIa10'
|
publicKey: 'TPWwaPLM2dDuEIa10'
|
||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
/*if (toast.current) {
|
/!*if (toast.current) {
|
||||||
toast.current.show({
|
toast.current.show({
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
summary: '',
|
summary: '',
|
||||||
detail: __('La richiesta è stata inviata!', 'gepafin')
|
detail: __('La richiesta è stata inviata!', 'gepafin')
|
||||||
});
|
});
|
||||||
}*/
|
}*!/
|
||||||
setIsVisibleRemoveDialog(true);
|
setIsVisibleRemoveDialog(true);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -270,10 +270,9 @@ const ProfileCompany = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// TODO delete company functionality by API, ready to be shipped
|
const doRemoveCompanyAPI = () => {
|
||||||
/*const doRemoveCompanyAPI = () => {
|
|
||||||
storeSet.main.setAsyncRequest();
|
storeSet.main.setAsyncRequest();
|
||||||
CompanyService.deleteCompany(formInitialData.id, deleteCompanyCallback, errDeleteCompanyCallback)
|
CompanyService.deleteCompany(formInitialData.id, deleteCompanyCallback, errDeleteCompanyCallback)
|
||||||
}
|
}
|
||||||
@@ -289,6 +288,8 @@ const ProfileCompany = () => {
|
|||||||
if (!isEmpty(newCompanies)) {
|
if (!isEmpty(newCompanies)) {
|
||||||
const newChosenCompanyId = newCompanies[0].id;
|
const newChosenCompanyId = newCompanies[0].id;
|
||||||
storeSet.main.chosenCompanyId(newChosenCompanyId);
|
storeSet.main.chosenCompanyId(newChosenCompanyId);
|
||||||
|
} else {
|
||||||
|
storeSet.main.chosenCompanyId(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storeSet.main.unsetAsyncRequest();
|
storeSet.main.unsetAsyncRequest();
|
||||||
@@ -297,7 +298,7 @@ const ProfileCompany = () => {
|
|||||||
const errDeleteCompanyCallback = (data) => {
|
const errDeleteCompanyCallback = (data) => {
|
||||||
set404FromErrorResponse(data);
|
set404FromErrorResponse(data);
|
||||||
storeSet.main.unsetAsyncRequest();
|
storeSet.main.unsetAsyncRequest();
|
||||||
}*/
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newFormData = klona(formInitialData);
|
const newFormData = klona(formInitialData);
|
||||||
@@ -622,15 +623,15 @@ const ProfileCompany = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Dialog
|
{/*<Dialog
|
||||||
visible={isVisibleRemoveDialog}
|
visible={isVisibleRemoveDialog}
|
||||||
modal
|
modal
|
||||||
header={headerRemoveDialog}
|
header={headerRemoveDialog}
|
||||||
/*footer={footerRemoveDialog}*/
|
footer={footerRemoveDialog}
|
||||||
style={{ maxWidth: '600px', width: '100%' }}
|
style={{ maxWidth: '600px', width: '100%' }}
|
||||||
onHide={hideRemoveDialog}>
|
onHide={hideRemoveDialog}>
|
||||||
<p>Abbiamo preso in carica la tua richiesta a breve l'azienda sarà rimossa dal tuo profilo</p>
|
<p>Abbiamo preso in carica la tua richiesta a breve l'azienda sarà rimossa dal tuo profilo</p>
|
||||||
</Dialog>
|
</Dialog>*/}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import ApplicationService from '../../service/application-service';
|
|||||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
@@ -27,6 +26,7 @@ import { Dialog } from 'primereact/dialog';
|
|||||||
import FormField from '../../components/FormField';
|
import FormField from '../../components/FormField';
|
||||||
import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications';
|
import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications';
|
||||||
import { Editor } from 'primereact/editor';
|
import { Editor } from 'primereact/editor';
|
||||||
|
import getEmailTemplateForSoccorso from '../../helpers/getStrippedHtmlBodyTags';
|
||||||
|
|
||||||
const SoccorsoEditBeneficiario = () => {
|
const SoccorsoEditBeneficiario = () => {
|
||||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||||
@@ -327,10 +327,7 @@ const SoccorsoEditBeneficiario = () => {
|
|||||||
? <div className="appPageSection">
|
? <div className="appPageSection">
|
||||||
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
||||||
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
||||||
<div className="appPageSection__withBorder grey ql-editor"
|
<div>{getEmailTemplateForSoccorso(data.emailTemplate, data.note)}</div>
|
||||||
style={{ minHeight: '100px' }}>
|
|
||||||
{renderHtmlContent(data.note)}
|
|
||||||
</div>
|
|
||||||
</div> : null}
|
</div> : null}
|
||||||
|
|
||||||
{data.id
|
{data.id
|
||||||
@@ -440,7 +437,7 @@ const SoccorsoEditBeneficiario = () => {
|
|||||||
outlined
|
outlined
|
||||||
onClick={goToArchivePage}
|
onClick={goToArchivePage}
|
||||||
label={__('Indietro', 'gepafin')}
|
label={__('Indietro', 'gepafin')}
|
||||||
icon="pi pi-times" iconPos="right"/>
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import AmendmentsService from '../../service/amendments-service';
|
|||||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
import getEmailTemplateForSoccorso from '../../helpers/getStrippedHtmlBodyTags';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
@@ -411,8 +411,11 @@ const SoccorsoEditPreInstructor = () => {
|
|||||||
|
|
||||||
<div className="appPageSection">
|
<div className="appPageSection">
|
||||||
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
||||||
<div className="appPageSection columns">
|
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
||||||
<div>
|
<div
|
||||||
|
className="appPageSection__emailTemplate">{getEmailTemplateForSoccorso(data.emailTemplate, data.note)}</div>
|
||||||
|
</div>
|
||||||
|
<div className="appPageSection">
|
||||||
<h3>{__('Documenti Richiesti', 'gepafin')}</h3>
|
<h3>{__('Documenti Richiesti', 'gepafin')}</h3>
|
||||||
<ol className="appPageSection__list">
|
<ol className="appPageSection__list">
|
||||||
{data.formFields
|
{data.formFields
|
||||||
@@ -422,16 +425,6 @@ const SoccorsoEditPreInstructor = () => {
|
|||||||
</li>) : null}
|
</li>) : null}
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
|
||||||
<div className="appPageSection__withBorder grey ql-editor"
|
|
||||||
style={{ minHeight: '200px' }}>
|
|
||||||
{renderHtmlContent(data.note)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="appPageSection">
|
<div className="appPageSection">
|
||||||
<h2>{__('Comunicazioni', 'gepafin')}</h2>
|
<h2>{__('Comunicazioni', 'gepafin')}</h2>
|
||||||
|
|||||||
192
src/pages/UserActivity/index.js
Normal file
192
src/pages/UserActivity/index.js
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { isEmpty, pathOr } from 'ramda';
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
import NumberFlow from '@number-flow/react';
|
||||||
|
|
||||||
|
// service
|
||||||
|
import UserService from '../../service/user-service';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import { Toast } from 'primereact/toast';
|
||||||
|
import { Dropdown } from 'primereact/dropdown';
|
||||||
|
|
||||||
|
|
||||||
|
const UserActivity = () => {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const toast = useRef(null);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { id } = useParams();
|
||||||
|
const [user, setUser] = useState({});
|
||||||
|
const [roles, setRoles] = useState([]);
|
||||||
|
const [chosenRole, setChosenRole] = useState(0);
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
navigate(`/utenti`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserCallback = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
setUser(resp.data)
|
||||||
|
setChosenRole(resp.data.role?.id);
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const errGetUserCallback = (resp) => {
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getRolesCallback = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
setRoles(resp.data)
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const errGetRolesCallback = (resp) => {
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatValue = (key, fallback = 0) => {
|
||||||
|
return pathOr(fallback, [key], {});
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRoleUpdate = () => {
|
||||||
|
if (user.role?.id !== chosenRole) {
|
||||||
|
setLoading(true);
|
||||||
|
UserService.updateUser(user.id, {roleId: chosenRole}, updateRoleCallback, errUpdateRoleCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateRoleCallback = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
setUser(resp.data)
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const errUpdateRoleCallback = (resp) => {
|
||||||
|
set404FromErrorResponse(resp);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (id && !isEmpty(id)) {
|
||||||
|
setLoading(true);
|
||||||
|
UserService.getUser(id, getUserCallback, errGetUserCallback);
|
||||||
|
UserService.getRoles(getRolesCallback, errGetRolesCallback);
|
||||||
|
}
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="appPage">
|
||||||
|
<div className="appPage__pageHeader">
|
||||||
|
<h1>{__('Controllo attività utenti', 'gepafin')}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPage__spacer"></div>
|
||||||
|
<Toast ref={toast}/>
|
||||||
|
|
||||||
|
<div className="appPageSection">
|
||||||
|
<div className="appPageSection__actions">
|
||||||
|
<Button
|
||||||
|
onClick={goBack}
|
||||||
|
outlined
|
||||||
|
label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder columns">
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Nome utente', 'gepafin')}</span>
|
||||||
|
<span>{`${user.firstName} ${user.lastName}`}</span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Email', 'gepafin')}</span>
|
||||||
|
<span>{user.email}</span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Ruolo', 'gepafin')}</span>
|
||||||
|
<span>{user.role?.roleName}</span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Data registrazione', 'gepafin')}</span>
|
||||||
|
<span>{getDateFromISOstring(user.createdDate)}</span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Ultimo accesso', 'gepafin')}</span>
|
||||||
|
<span>{getDateFromISOstring(user.lastLogin)}</span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Stato account', 'gepafin')}</span>
|
||||||
|
<span>{user.status}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{['ROLE_PRE_INSTRUCTOR', 'ROLE_INSTRUCTOR_MANAGER'].includes(user.role?.roleType)
|
||||||
|
? <>
|
||||||
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
<div className="appPageSection">
|
||||||
|
<h3>{__('Cambia ruolo', 'gepafin')}</h3>
|
||||||
|
<div className="row">
|
||||||
|
<Dropdown
|
||||||
|
id="form"
|
||||||
|
disabled={isEmpty(roles) || loading}
|
||||||
|
value={chosenRole}
|
||||||
|
onChange={(e) => setChosenRole(e.value)}
|
||||||
|
options={roles.filter(o => [3, 5].includes(o.id)).map(o => ({ label: o.roleName, value: o.id }))}
|
||||||
|
optionLabel="label"
|
||||||
|
placeholder={__('Seleziona ruolo', 'gepafin')}/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
disabled={loading}
|
||||||
|
outlined
|
||||||
|
onClick={handleRoleUpdate}
|
||||||
|
label={__('Modifica', 'gepafin')}
|
||||||
|
icon="pi pi-cog" iconPos="right"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</> : null}
|
||||||
|
|
||||||
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
{/*<div className="appPageSection">
|
||||||
|
<h2>{__('Statistiche attività', 'gepafin')}</h2>
|
||||||
|
<div className="statsBigBadges__grid grid-small">
|
||||||
|
<div className="statsBigBadges__gridItem">
|
||||||
|
<span>{__('Login totali', 'gepafin')}</span>
|
||||||
|
<span>{<NumberFlow
|
||||||
|
value={getStatValue('numberOfActiveCalls', 0)}
|
||||||
|
format={{ notation: 'compact' }}
|
||||||
|
locales="it-IT"/>}</span>
|
||||||
|
</div>
|
||||||
|
<div className="statsBigBadges__gridItem">
|
||||||
|
<span>{__('Bandi gestiti', 'gepafin')}</span>
|
||||||
|
<span>{<NumberFlow
|
||||||
|
value={getStatValue('numberOfActiveCalls', 0)}
|
||||||
|
format={{ notation: 'compact' }}
|
||||||
|
locales="it-IT"/>}</span>
|
||||||
|
</div>
|
||||||
|
<div className="statsBigBadges__gridItem">
|
||||||
|
<span>{__('Domande processate', 'gepafin')}</span>
|
||||||
|
<span>{<NumberFlow
|
||||||
|
value={getStatValue('numberOfActiveCalls', 0)}
|
||||||
|
format={{ notation: 'compact' }}
|
||||||
|
locales="it-IT"/>}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>*/}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserActivity;
|
||||||
@@ -24,6 +24,7 @@ import { Calendar } from 'primereact/calendar';
|
|||||||
import { Tag } from 'primereact/tag';
|
import { Tag } from 'primereact/tag';
|
||||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||||
import translationStrings from '../../../../translationStringsForComponents';
|
import translationStrings from '../../../../translationStringsForComponents';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const AllUsersTable = () => {
|
const AllUsersTable = () => {
|
||||||
const users = useStore().main.users();
|
const users = useStore().main.users();
|
||||||
@@ -125,12 +126,16 @@ const AllUsersTable = () => {
|
|||||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>;
|
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*const actionsBodyTemplate = (rowData) => {
|
const actionsBodyTemplate = (rowData) => {
|
||||||
/!*return <Link to={`/utenti/${rowData.id}`}>
|
return <Link to={`/utenti/${rowData.id}`}>
|
||||||
<Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small" iconPos="right"/>
|
<Button
|
||||||
</Link>*!/
|
severity="info"
|
||||||
return null;
|
label={__('Attività', 'gepafin')}
|
||||||
}*/
|
icon="pi pi-eye"
|
||||||
|
size="small"
|
||||||
|
iconPos="right"/>
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
|
|
||||||
const header = renderHeader();
|
const header = renderHeader();
|
||||||
|
|
||||||
@@ -149,19 +154,19 @@ const AllUsersTable = () => {
|
|||||||
filter sortable
|
filter sortable
|
||||||
field="email"
|
field="email"
|
||||||
filterPlaceholder={__('Cerca per email', 'gepafin')}
|
filterPlaceholder={__('Cerca per email', 'gepafin')}
|
||||||
style={{ minWidth: '12rem' }}/>
|
style={{ minWidth: '10rem' }}/>
|
||||||
<Column body={roleBodyTemplate} header={__('Ruolo', 'gepafin')}
|
<Column body={roleBodyTemplate} header={__('Ruolo', 'gepafin')}
|
||||||
style={{ minWidth: '12rem' }}/>
|
style={{ minWidth: '8rem' }}/>
|
||||||
<Column field="status" header={__('Stato', 'gepafin')}
|
<Column field="status" header={__('Stato', 'gepafin')}
|
||||||
filterMenuStyle={{ width: '14rem' }}
|
filterMenuStyle={{ width: '14rem' }}
|
||||||
style={{ width: '120px' }} body={statusBodyTemplate}
|
style={{ width: '120px' }} body={statusBodyTemplate}
|
||||||
filterElement={statusFilterTemplate}/>
|
filterElement={statusFilterTemplate}/>
|
||||||
<Column header={__('Ultimo accesso', 'gepafin')}
|
<Column header={__('Ultimo accesso', 'gepafin')}
|
||||||
filterField="lastLogin" dataType="date"
|
filterField="lastLogin" dataType="date"
|
||||||
style={{ minWidth: '10rem' }}
|
style={{ minWidth: '7rem' }}
|
||||||
body={dateLastAccessBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
body={dateLastAccessBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||||
{/*<Column header={__('Azioni', 'gepafin')}
|
<Column header={__('Azioni', 'gepafin')}
|
||||||
body={actionsBodyTemplate}/>*/}
|
body={actionsBodyTemplate}/>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import BandoApplicationPreview from './pages/BandoApplicationPreview';
|
|||||||
import BandiPreferredBeneficiario from './pages/BandiPreferredBeneficiario';
|
import BandiPreferredBeneficiario from './pages/BandiPreferredBeneficiario';
|
||||||
import DomandeInstructorManager from './pages/DomandeInstructorManager';
|
import DomandeInstructorManager from './pages/DomandeInstructorManager';
|
||||||
import DomandaEditInstructorManager from './pages/DomandaEditInstructorManager';
|
import DomandaEditInstructorManager from './pages/DomandaEditInstructorManager';
|
||||||
|
import UserActivity from './pages/UserActivity';
|
||||||
|
|
||||||
const routes = ({ role, chosenCompanyId }) => {
|
const routes = ({ role, chosenCompanyId }) => {
|
||||||
|
|
||||||
@@ -177,6 +178,12 @@ const routes = ({ role, chosenCompanyId }) => {
|
|||||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||||
{'ROLE_INSTRUCTOR_MANAGER' === role ? <PageNotFound/> : null}
|
{'ROLE_INSTRUCTOR_MANAGER' === role ? <PageNotFound/> : null}
|
||||||
</DefaultLayout>}/>
|
</DefaultLayout>}/>
|
||||||
|
<Route path="/utenti/:id" element={<DefaultLayout>
|
||||||
|
{'ROLE_SUPER_ADMIN' === role ? <UserActivity/> : null}
|
||||||
|
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||||
|
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||||
|
{'ROLE_INSTRUCTOR_MANAGER' === role ? <PageNotFound/> : null}
|
||||||
|
</DefaultLayout>}/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/reset-password" element={<ResetPassword/>}/>
|
<Route exact path="/reset-password" element={<ResetPassword/>}/>
|
||||||
<Route exact path="/login" element={<Login/>}/>
|
<Route exact path="/login" element={<Login/>}/>
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ export default class ApplicationService {
|
|||||||
NetworkService.delete(`${API_BASE_URL}/application/${id}/signedDocument`, {}, callback, errCallback);
|
NetworkService.delete(`${API_BASE_URL}/application/${id}/signedDocument`, {}, callback, errCallback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static deleteApplication = (id, callback, errCallback) => {
|
||||||
|
NetworkService.delete(`${API_BASE_URL}/application/${id}`, {}, callback, errCallback);
|
||||||
|
};
|
||||||
|
|
||||||
static downloadCompleteZip = (id, callback, errCallback, queryParams) => {
|
static downloadCompleteZip = (id, callback, errCallback, queryParams) => {
|
||||||
NetworkService.getBlob(`${API_BASE_URL}/application/${id}/documents/zip`, callback, errCallback, queryParams);
|
NetworkService.getBlob(`${API_BASE_URL}/application/${id}/documents/zip`, callback, errCallback, queryParams);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,6 +37,6 @@ export default class CompanyService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static deleteCompany = (id, callback, errCallback) => {
|
static deleteCompany = (id, callback, errCallback) => {
|
||||||
NetworkService.delete(`${API_BASE_URL}/company/${id}`, {}, callback, errCallback);
|
NetworkService.delete(`${API_BASE_URL}/company/user/${id}`, {}, callback, errCallback);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/service/notification-service.js
Normal file
22
src/service/notification-service.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { NetworkService } from './network-service';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||||
|
|
||||||
|
export default class NotificationService {
|
||||||
|
|
||||||
|
static getNotifications = (id, callback, errCallback, queryParams) => {
|
||||||
|
NetworkService.get(`${API_BASE_URL}/notification/user/${id}`, callback, errCallback, queryParams);
|
||||||
|
};
|
||||||
|
|
||||||
|
static notificationMakeRead = (id, callback, errCallback) => {
|
||||||
|
NetworkService.put(`${API_BASE_URL}/notification/${id}`, {}, callback, errCallback, [
|
||||||
|
['status', 'READ']
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
static notificationMakeUnread = (id, callback, errCallback) => {
|
||||||
|
NetworkService.put(`${API_BASE_URL}/notification/${id}`, {}, callback, errCallback, [
|
||||||
|
['status', 'UNREAD']
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -8,6 +8,10 @@ export default class UserService {
|
|||||||
NetworkService.get(`${API_BASE_URL}/user`, callback, errCallback, queryParams);
|
NetworkService.get(`${API_BASE_URL}/user`, callback, errCallback, queryParams);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static getUser = (id, callback, errCallback, queryParams) => {
|
||||||
|
NetworkService.get(`${API_BASE_URL}/user/${id}`, callback, errCallback, queryParams);
|
||||||
|
};
|
||||||
|
|
||||||
static updateUser = (id, body, callback, errCallback) => {
|
static updateUser = (id, body, callback, errCallback) => {
|
||||||
NetworkService.put(`${API_BASE_URL}/user/${id}`, body, callback, errCallback);
|
NetworkService.put(`${API_BASE_URL}/user/${id}`, body, callback, errCallback);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -214,6 +214,10 @@ export const elementItems = [
|
|||||||
{
|
{
|
||||||
name: "mime",
|
name: "mime",
|
||||||
value: []
|
value: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "isDelegation",
|
||||||
|
value: false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
validators: {
|
validators: {
|
||||||
|
|||||||
Reference in New Issue
Block a user