Merge pull request #28 from Kitzanos/master-sync/07-12-2024

Master sync/07 12 2024
This commit is contained in:
Vitalii Kiiko
2025-01-07 08:57:04 +01:00
committed by GitHub
32 changed files with 777 additions and 80 deletions

1
.env
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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 {

View 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;
}

View File

@@ -5,11 +5,15 @@
display: grid; display: grid;
align-items: stretch; align-items: stretch;
/*grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));*/ /*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; gap: 1rem;
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 {

View File

@@ -44,4 +44,5 @@
@import "./components/error404.scss"; @import "./components/error404.scss";
@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";

View File

@@ -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';

View File

@@ -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';

View File

@@ -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;

View File

@@ -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;

View 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;

View 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;

View File

@@ -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') {

View File

@@ -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>
@@ -46,4 +45,4 @@ const AppTopbar = () => {
) )
} }
export default AppTopbar; export default AppTopbar;

View File

@@ -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 {

View File

@@ -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') {

View File

@@ -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)}/>

View File

@@ -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"/>
</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"/> iconPos="right"/>
: <Button severity="info" label={__('Mostra', 'gepafin')} icon="pi pi-eye" size="small"
iconPos="right"/>}
</Link> </Link>
} }
const header = renderHeader(); const header = renderHeader();

View File

@@ -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')}
/> />

View File

@@ -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>
) )

View File

@@ -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>

View File

@@ -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,26 +411,19 @@ 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
<h3>{__('Documenti Richiesti', 'gepafin')}</h3> className="appPageSection__emailTemplate">{getEmailTemplateForSoccorso(data.emailTemplate, data.note)}</div>
<ol className="appPageSection__list"> </div>
{data.formFields <div className="appPageSection">
? data.formFields.map((o, i) => <li key={o.fieldId} <h3>{__('Documenti Richiesti', 'gepafin')}</h3>
style={{ flexDirection: 'row' }}> <ol className="appPageSection__list">
<span>{o.label}</span> {data.formFields
</li>) : null} ? data.formFields.map((o, i) => <li key={o.fieldId}
</ol> style={{ flexDirection: 'row' }}>
</div> <span>{o.label}</span>
<div> </li>) : null}
<h3>{__('Note e spiegazioni', 'gepafin')}</h3> </ol>
<div className="appPageSection__withBorder grey ql-editor"
style={{ minHeight: '200px' }}>
{renderHtmlContent(data.note)}
</div>
</div>
</div>
</div> </div>
<div className="appPageSection"> <div className="appPageSection">

View 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;

View File

@@ -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,22 +154,22 @@ 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>
) )
} }
export default AllUsersTable; export default AllUsersTable;

View File

@@ -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/>}/>

View File

@@ -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);
}; };

View File

@@ -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);
}; };
} }

View 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']
]);
};
}

View File

@@ -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);
}; };

View File

@@ -214,6 +214,10 @@ export const elementItems = [
{ {
name: "mime", name: "mime",
value: [] value: []
},
{
name: "isDelegation",
value: false
} }
], ],
validators: { validators: {