Merge branch 'develop' into master-sync/07-12-2024
This commit is contained in:
@@ -218,6 +218,7 @@
|
||||
|
||||
.appPageSection__pMeta {
|
||||
margin-bottom: 1em;
|
||||
break-inside: avoid;
|
||||
|
||||
span:nth-of-type(1) {
|
||||
max-width: 30%;
|
||||
@@ -435,6 +436,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.appPageSection__emailTemplate {
|
||||
> div {
|
||||
max-width: 100%!important;
|
||||
> div {
|
||||
max-width: 100%!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.appPageSection {
|
||||
&.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;
|
||||
}
|
||||
@@ -5,11 +5,15 @@
|
||||
display: grid;
|
||||
align-items: stretch;
|
||||
/*grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));*/
|
||||
grid-template-columns: repeat(2, minmax(220px,1fr));
|
||||
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
container-name: big-badges-grid;
|
||||
container-type: inline-size;
|
||||
|
||||
&.grid-small {
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
.statsBigBadges__grid .statsBigBadges__gridItem span {
|
||||
|
||||
@@ -44,4 +44,5 @@
|
||||
@import "./components/error404.scss";
|
||||
@import "./components/myTable.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';
|
||||
|
||||
// store
|
||||
import { useStore, storeSet, storeGet } from '../../store';
|
||||
import { useStore, storeSet } from '../../store';
|
||||
|
||||
// nodes
|
||||
import NodeInitialForm from './components/NodeInitialForm';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { isEmpty, isNil } from 'ramda';
|
||||
import { isNil } from 'ramda';
|
||||
|
||||
// components
|
||||
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) => {
|
||||
if (data && data.status === 'NOT_FOUND') {
|
||||
|
||||
@@ -8,9 +8,9 @@ import LogoIcon from '../../../../icons/LogoIcon';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Badge } from 'primereact/badge';
|
||||
import { Button } from 'primereact/button';
|
||||
import TopBarProfileMenu from '../../../../components/TopBarProfileMenu';
|
||||
import NotificationsSidebar from '../../../../components/NotificationsSidebar';
|
||||
|
||||
const AppTopbar = () => {
|
||||
const menuLeft = useRef(null);
|
||||
@@ -24,14 +24,13 @@ const AppTopbar = () => {
|
||||
<InputIcon className="pi pi-search"> </InputIcon>
|
||||
<InputText v-model="value1" placeholder={__('Cerca', 'gepafin')} disabled={true}/>
|
||||
</IconField>
|
||||
<i className="pi pi-bell p-overlay-badge topBar__icon">
|
||||
<Badge value="0"></Badge>
|
||||
</i>
|
||||
<NotificationsSidebar/>
|
||||
<i className="pi pi-envelope topBar__icon"></i>
|
||||
{/*<i className="pi pi-envelope p-overlay-badge topBar__icon">
|
||||
<Badge severity="danger"></Badge>
|
||||
</i>*/}
|
||||
<Button
|
||||
type="button"
|
||||
className="topBar__profileBtn"
|
||||
outlined
|
||||
onClick={(event) => menuLeft.current.toggle(event)} aria-controls="topBar_profileMenu" aria-haspopup>
|
||||
@@ -46,4 +45,4 @@ const AppTopbar = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default AppTopbar;
|
||||
export default AppTopbar;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { isEmpty, head } from 'ramda';
|
||||
import { klona } from 'klona';
|
||||
@@ -29,6 +29,7 @@ const AddCompany = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const infoMsgs = useRef(null);
|
||||
const [, debouncedPivaValue, setInputPiva] = useDebounce('', 1000);
|
||||
const [vatCheckResponse, setVatCheckResponse] = useState({});
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -54,14 +55,19 @@ const AddCompany = () => {
|
||||
address: '',
|
||||
companyName: ''
|
||||
}
|
||||
setVatCheckResponse({});
|
||||
Object.keys(formData).map(k => setValue(k, formData[k]));
|
||||
}
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
infoMsgs.current.clear();
|
||||
storeSet.main.setAsyncRequest();
|
||||
const submitData = {
|
||||
...formData,
|
||||
vatCheckResponse
|
||||
}
|
||||
|
||||
CompanyService.createCompany(formData, updateCallback, updateError);
|
||||
CompanyService.createCompany(submitData, updateCallback, updateError);
|
||||
};
|
||||
|
||||
const updateCallback = (data) => {
|
||||
@@ -109,7 +115,7 @@ const AddCompany = () => {
|
||||
|
||||
const checkVatCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const resp = data.data.data;
|
||||
const resp = data.data.vatCheckResponse.data;
|
||||
if (!isEmpty(resp)) {
|
||||
const {
|
||||
cap, cf, denominazione, piva, indirizzo, comune, dettaglio: { pec }
|
||||
@@ -126,6 +132,7 @@ const AddCompany = () => {
|
||||
companyName: denominazione
|
||||
}
|
||||
Object.keys(formData).map(k => setValue(k, formData[k]));
|
||||
setVatCheckResponse(data.data.vatCheckResponse);
|
||||
}
|
||||
//setData(getFormattedBandiData(data.data));
|
||||
} else {
|
||||
|
||||
@@ -39,7 +39,7 @@ const BandoApplicationPreview = () => {
|
||||
const [formData, setFormData] = useState([]);
|
||||
const [formInitialData, setFormInitialData] = useState(null);
|
||||
const [bandoTitle, setBandoTitle] = useState('');
|
||||
const [bandoId, setBandoId] = useState(0);
|
||||
const [, setBandoId] = useState(0);
|
||||
const [formId, setFormId] = useState('');
|
||||
const [totalSteps, setTotalSteps] = useState(0);
|
||||
const [applicationStatus, setApplicationStatus] = useState('');
|
||||
@@ -86,8 +86,8 @@ const BandoApplicationPreview = () => {
|
||||
ApplicationService.validateApplication(applId, {}, validateApplicationCallback, errValidateApplicationCallback);
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
};
|
||||
/*const onSubmit = () => {
|
||||
};*/
|
||||
|
||||
const validateApplicationCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
|
||||
@@ -19,6 +19,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
|
||||
placeholder: __('Segnaposto', 'gepafin'),
|
||||
step: __('Numero Decimali', 'gepafin'),
|
||||
isRequestedAmount: __('Importo richiesto', 'gepafin'),
|
||||
isDelegation: __('Delega', 'gepafin'),
|
||||
options: __('Opzioni', 'gepafin'),
|
||||
mime: __('Tipo di file', 'gepafin'),
|
||||
text: __('Testo formattato', 'gepafin'),
|
||||
@@ -80,7 +81,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
|
||||
name={setting.name}
|
||||
bandoStatus={bandoStatus}
|
||||
setDataFn={updateDataFn}/>
|
||||
} else if (setting.name === 'isRequestedAmount') {
|
||||
} else if (['isRequestedAmount', 'isDelegation'].includes(setting.name)) {
|
||||
return <InputSwitch
|
||||
checked={setting.value}
|
||||
onChange={(e) => changeFn(e.value, setting.name)}/>
|
||||
|
||||
@@ -57,6 +57,23 @@ const MyLatestSubmissionsTable = () => {
|
||||
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) => {
|
||||
return [...(data || [])].map((d) => {
|
||||
d.callEndDate = new Date(d.callEndDate);
|
||||
@@ -130,7 +147,8 @@ const MyLatestSubmissionsTable = () => {
|
||||
const statusFilterTemplate = (options) => {
|
||||
return <Dropdown value={options.value} options={statuses}
|
||||
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/>;
|
||||
};
|
||||
|
||||
@@ -143,13 +161,24 @@ const MyLatestSubmissionsTable = () => {
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return <Link to={`/imieibandi/${rowData.id}`}>
|
||||
{'DRAFT' === rowData.status
|
||||
? <Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small"
|
||||
return 'DRAFT' === rowData.status
|
||||
? <div className="appPageSection__tableActions lessGap">
|
||||
<Link to={`/imieibandi/${rowData.id}`}>
|
||||
<Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small"
|
||||
iconPos="right"/>
|
||||
</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"/>
|
||||
: <Button severity="info" label={__('Mostra', 'gepafin')} icon="pi pi-eye" size="small"
|
||||
iconPos="right"/>}
|
||||
</Link>
|
||||
|
||||
}
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
@@ -138,7 +138,7 @@ const RepeaterFields = ({
|
||||
className="fieldsRepeater__addNew"
|
||||
outlined
|
||||
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}
|
||||
label={__('Aggiungi nuovo file', 'gepafin')}
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isEmpty, pathOr, head } from 'ramda';
|
||||
import { klona } from 'klona';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import emailjs from '@emailjs/browser';
|
||||
//import emailjs from '@emailjs/browser';
|
||||
//import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
@@ -27,7 +27,7 @@ import { InputText } from 'primereact/inputtext';
|
||||
import { Toast } from 'primereact/toast';
|
||||
//import getFormatedFileSizeText from '../../helpers/getFormatedFileSizeText';
|
||||
//import { defaultMaxFileSize } from '../../configData';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
//import { Dialog } from 'primereact/dialog';
|
||||
import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup';
|
||||
|
||||
const ProfileCompany = () => {
|
||||
@@ -38,7 +38,7 @@ const ProfileCompany = () => {
|
||||
const [formInitialData, setFormInitialData] = useState({});
|
||||
const [delegaData, setDelegaData] = useState({});
|
||||
//const [delega, setDelega] = useState([]);
|
||||
const [isVisibleRemoveDialog, setIsVisibleRemoveDialog] = useState(false);
|
||||
//const [isVisibleRemoveDialog, setIsVisibleRemoveDialog] = useState(false);
|
||||
const { delegaFirstName = '', delegaLastName = '', delegaCodiceFiscale = '' } = delegaData;
|
||||
const toast = useRef(null);
|
||||
//const navigate = useNavigate();
|
||||
@@ -212,22 +212,22 @@ const ProfileCompany = () => {
|
||||
defaultFocus: 'reject',
|
||||
acceptClassName: 'p-button-danger',
|
||||
accept: () => {
|
||||
doRemoveCompany();
|
||||
doRemoveCompanyAPI();
|
||||
},
|
||||
reject: () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const headerRemoveDialog = () => {
|
||||
/*const headerRemoveDialog = () => {
|
||||
return <span>{__('Rimuovi azienda', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const hideRemoveDialog = () => {
|
||||
setIsVisibleRemoveDialog(false);
|
||||
}
|
||||
}*/
|
||||
|
||||
const doRemoveCompany = () => {
|
||||
/*const doRemoveCompany = () => {
|
||||
const userData = storeGet.main.userData();
|
||||
let chosenCompany = {};
|
||||
|
||||
@@ -251,13 +251,13 @@ const ProfileCompany = () => {
|
||||
publicKey: 'TPWwaPLM2dDuEIa10'
|
||||
}
|
||||
).then(() => {
|
||||
/*if (toast.current) {
|
||||
/!*if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: __('La richiesta è stata inviata!', 'gepafin')
|
||||
});
|
||||
}*/
|
||||
}*!/
|
||||
setIsVisibleRemoveDialog(true);
|
||||
})
|
||||
.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();
|
||||
CompanyService.deleteCompany(formInitialData.id, deleteCompanyCallback, errDeleteCompanyCallback)
|
||||
}
|
||||
@@ -289,6 +288,8 @@ const ProfileCompany = () => {
|
||||
if (!isEmpty(newCompanies)) {
|
||||
const newChosenCompanyId = newCompanies[0].id;
|
||||
storeSet.main.chosenCompanyId(newChosenCompanyId);
|
||||
} else {
|
||||
storeSet.main.chosenCompanyId(0);
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
@@ -297,7 +298,7 @@ const ProfileCompany = () => {
|
||||
const errDeleteCompanyCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}*/
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const newFormData = klona(formInitialData);
|
||||
@@ -622,15 +623,15 @@ const ProfileCompany = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
{/*<Dialog
|
||||
visible={isVisibleRemoveDialog}
|
||||
modal
|
||||
header={headerRemoveDialog}
|
||||
/*footer={footerRemoveDialog}*/
|
||||
footer={footerRemoveDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideRemoveDialog}>
|
||||
<p>Abbiamo preso in carica la tua richiesta a breve l'azienda sarà rimossa dal tuo profilo</p>
|
||||
</Dialog>
|
||||
</Dialog>*/}
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -17,7 +17,6 @@ import ApplicationService from '../../service/application-service';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
@@ -27,6 +26,7 @@ import { Dialog } from 'primereact/dialog';
|
||||
import FormField from '../../components/FormField';
|
||||
import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications';
|
||||
import { Editor } from 'primereact/editor';
|
||||
import getEmailTemplateForSoccorso from '../../helpers/getStrippedHtmlBodyTags';
|
||||
|
||||
const SoccorsoEditBeneficiario = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
@@ -327,10 +327,7 @@ const SoccorsoEditBeneficiario = () => {
|
||||
? <div className="appPageSection">
|
||||
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
||||
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
||||
<div className="appPageSection__withBorder grey ql-editor"
|
||||
style={{ minHeight: '100px' }}>
|
||||
{renderHtmlContent(data.note)}
|
||||
</div>
|
||||
<div>{getEmailTemplateForSoccorso(data.emailTemplate, data.note)}</div>
|
||||
</div> : null}
|
||||
|
||||
{data.id
|
||||
@@ -440,7 +437,7 @@ const SoccorsoEditBeneficiario = () => {
|
||||
outlined
|
||||
onClick={goToArchivePage}
|
||||
label={__('Indietro', 'gepafin')}
|
||||
icon="pi pi-times" iconPos="right"/>
|
||||
icon="pi pi-arrow-left" iconPos="left"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@ import AmendmentsService from '../../service/amendments-service';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
||||
import getEmailTemplateForSoccorso from '../../helpers/getStrippedHtmlBodyTags';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
@@ -411,26 +411,19 @@ const SoccorsoEditPreInstructor = () => {
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
||||
<div className="appPageSection columns">
|
||||
<div>
|
||||
<h3>{__('Documenti Richiesti', 'gepafin')}</h3>
|
||||
<ol className="appPageSection__list">
|
||||
{data.formFields
|
||||
? data.formFields.map((o, i) => <li key={o.fieldId}
|
||||
style={{ flexDirection: 'row' }}>
|
||||
<span>{o.label}</span>
|
||||
</li>) : null}
|
||||
</ol>
|
||||
</div>
|
||||
<div>
|
||||
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
||||
<div className="appPageSection__withBorder grey ql-editor"
|
||||
style={{ minHeight: '200px' }}>
|
||||
{renderHtmlContent(data.note)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
||||
<div
|
||||
className="appPageSection__emailTemplate">{getEmailTemplateForSoccorso(data.emailTemplate, data.note)}</div>
|
||||
</div>
|
||||
<div className="appPageSection">
|
||||
<h3>{__('Documenti Richiesti', 'gepafin')}</h3>
|
||||
<ol className="appPageSection__list">
|
||||
{data.formFields
|
||||
? data.formFields.map((o, i) => <li key={o.fieldId}
|
||||
style={{ flexDirection: 'row' }}>
|
||||
<span>{o.label}</span>
|
||||
</li>) : null}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
|
||||
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 ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import translationStrings from '../../../../translationStringsForComponents';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const AllUsersTable = () => {
|
||||
const users = useStore().main.users();
|
||||
@@ -125,12 +126,16 @@ const AllUsersTable = () => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>;
|
||||
};
|
||||
|
||||
/*const actionsBodyTemplate = (rowData) => {
|
||||
/!*return <Link to={`/utenti/${rowData.id}`}>
|
||||
<Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small" iconPos="right"/>
|
||||
</Link>*!/
|
||||
return null;
|
||||
}*/
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return <Link to={`/utenti/${rowData.id}`}>
|
||||
<Button
|
||||
severity="info"
|
||||
label={__('Attività', 'gepafin')}
|
||||
icon="pi pi-eye"
|
||||
size="small"
|
||||
iconPos="right"/>
|
||||
</Link>
|
||||
}
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
@@ -149,22 +154,22 @@ const AllUsersTable = () => {
|
||||
filter sortable
|
||||
field="email"
|
||||
filterPlaceholder={__('Cerca per email', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
style={{ minWidth: '10rem' }}/>
|
||||
<Column body={roleBodyTemplate} header={__('Ruolo', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate}
|
||||
filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Ultimo accesso', 'gepafin')}
|
||||
filterField="lastLogin" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '7rem' }}
|
||||
body={dateLastAccessBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
{/*<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>*/}
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AllUsersTable;
|
||||
export default AllUsersTable;
|
||||
|
||||
@@ -39,6 +39,7 @@ import BandoApplicationPreview from './pages/BandoApplicationPreview';
|
||||
import BandiPreferredBeneficiario from './pages/BandiPreferredBeneficiario';
|
||||
import DomandeInstructorManager from './pages/DomandeInstructorManager';
|
||||
import DomandaEditInstructorManager from './pages/DomandaEditInstructorManager';
|
||||
import UserActivity from './pages/UserActivity';
|
||||
|
||||
const routes = ({ role, chosenCompanyId }) => {
|
||||
|
||||
@@ -177,6 +178,12 @@ const routes = ({ role, chosenCompanyId }) => {
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_INSTRUCTOR_MANAGER' === role ? <PageNotFound/> : null}
|
||||
</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 exact path="/reset-password" element={<ResetPassword/>}/>
|
||||
<Route exact path="/login" element={<Login/>}/>
|
||||
|
||||
@@ -48,6 +48,10 @@ export default class ApplicationService {
|
||||
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) => {
|
||||
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) => {
|
||||
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);
|
||||
};
|
||||
|
||||
static getUser = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/user/${id}`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static updateUser = (id, body, callback, errCallback) => {
|
||||
NetworkService.put(`${API_BASE_URL}/user/${id}`, body, callback, errCallback);
|
||||
};
|
||||
|
||||
@@ -214,6 +214,10 @@ export const elementItems = [
|
||||
{
|
||||
name: "mime",
|
||||
value: []
|
||||
},
|
||||
{
|
||||
name: "isDelegation",
|
||||
value: false
|
||||
}
|
||||
],
|
||||
validators: {
|
||||
|
||||
Reference in New Issue
Block a user