Merge pull request #5 from Kitzanos/master-sync/11-11-2024
Master sync/11 11 2024
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
"@date-fns/tz": "1.1.2",
|
||||
"@emailjs/browser": "^4.4.1",
|
||||
"@emotion/styled": "11.13.0",
|
||||
"@tanstack/react-table": "8.20.5",
|
||||
"@number-flow/react": "0.2.0",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@wordpress/i18n": "5.8.0",
|
||||
"@wordpress/react-i18n": "4.8.0",
|
||||
"@xyflow/react": "12.3.1",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
width: 100%;
|
||||
}
|
||||
.appForm__field {
|
||||
position: relative;
|
||||
@@ -10,6 +11,11 @@
|
||||
gap: 14px;
|
||||
padding: 5px 0;
|
||||
width: 100%;
|
||||
|
||||
&.row {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
|
||||
@@ -88,6 +88,18 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
|
||||
&.columns {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
width: 100%;
|
||||
|
||||
/*> div {
|
||||
max-width: 50%;
|
||||
}*/
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: var(--global-textColor);
|
||||
@@ -98,11 +110,27 @@
|
||||
margin: 0 0 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: var(--global-textColor);
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +145,10 @@
|
||||
container-name: section_with_border;
|
||||
container-type: inline-size;
|
||||
|
||||
&.grey {
|
||||
border-color: var(--table-border-color)
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
filter: grayscale(1);
|
||||
opacity: 0.8;
|
||||
@@ -149,14 +181,101 @@
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
ul {
|
||||
ul, ol {
|
||||
padding-left: 1rem;
|
||||
|
||||
li {
|
||||
color: var(--global-textColor);
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--global-textColor);
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.columns {
|
||||
gap: 2em;
|
||||
column-count: 2;
|
||||
column-width: 4em;
|
||||
display: block;
|
||||
padding-bottom: 0;
|
||||
|
||||
.appPageSection__pMeta {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.appPageSection__list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
|
||||
> li {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid var(--button-secondary-borderColor);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
|
||||
&.row {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.appPageSection__checklist {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.appPageSection__iconActions {
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.appPageSection__message {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
background: rgba(255, 242, 226, 0.7);
|
||||
border-style: solid;
|
||||
border-width: 0 0 0 6px;
|
||||
padding: 1.25rem 1.75rem;
|
||||
border-radius: 6px;
|
||||
|
||||
&.warning {
|
||||
color: var(--message-warning-color);
|
||||
border-color: var(--message-warning-color);
|
||||
}
|
||||
|
||||
&.info {
|
||||
color: var(--message-info-color);
|
||||
border-color: var(--message-info-color);
|
||||
}
|
||||
|
||||
.summary {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
@container section_with_border (max-width: 600px) {
|
||||
@@ -215,6 +334,10 @@
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
span:nth-of-type(2) {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.appPageSection__table {
|
||||
@@ -269,4 +392,12 @@
|
||||
&[disabled] {
|
||||
background-color: var(--message-info-background);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.appPageSection {
|
||||
&.columns {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/assets/scss/components/evaluation.scss
Normal file
41
src/assets/scss/components/evaluation.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
.criterionRelatedData {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
padding: 0 0 10px 0;
|
||||
|
||||
> h3 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.criterionRelatedData__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 7px;
|
||||
padding: 10px;
|
||||
background-color: #f5f5f5;
|
||||
font-size: 14px;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding-left: 15px;
|
||||
|
||||
li a {
|
||||
text-decoration: underline;
|
||||
color: var(--global-textColor);
|
||||
}
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid var(--table-border-color);
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,19 @@ body {
|
||||
margin: 0;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
|
||||
p, span:not(.p-button-label, .p-button-icon, .p-badge, .p-message-detail, .p-highlight, .p-inline-message-text),
|
||||
input, label:not(.p-error), textarea, a, li, h1, h2, h3, h4, h5, h6, div:not(.p-inline-message, .p-toast-detail), th, td {
|
||||
/*p, span:not(.p-button-label, .p-button-icon, .p-badge, .p-message-detail, .p-message-summary, .p-highlight, .p-inline-message-text, .p-tag, .p-tag-icon),
|
||||
input:not(.p-checkbox-input),
|
||||
label:not(.p-error), textarea, a, li, h1, h2, h3, h4, h5, h6, div:not(.p-inline-message, .p-toast-detail, .p-checkbox-box), th, td,
|
||||
:not(svg, path, .p-button, .p-button > span, .statsBigBadges__gridItem > span, number-flow, .p-paginator-page, .p-badge) {
|
||||
color: var(--global-textColor);
|
||||
}*/
|
||||
|
||||
h2, h3, p, label, .appPageSection__hr, li {
|
||||
color: var(--global-textColor);
|
||||
}
|
||||
|
||||
textarea {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +97,12 @@ img {
|
||||
color: white;
|
||||
}
|
||||
|
||||
svg {
|
||||
path {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--menuitem-active-color);
|
||||
}
|
||||
|
||||
@@ -113,16 +113,15 @@
|
||||
background-color: rgba(255,255,255,0.3)
|
||||
}
|
||||
|
||||
.p-inputgroup {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.p-accordion-header-text, .p-accordion-content {
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.p-inputgroup.flex-1 {
|
||||
align-items: center;
|
||||
}
|
||||
.flex-1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
39
src/assets/scss/components/myTable.scss
Normal file
39
src/assets/scss/components/myTable.scss
Normal file
@@ -0,0 +1,39 @@
|
||||
.myTable {
|
||||
border-spacing: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.myThead {
|
||||
th {
|
||||
text-align: left;
|
||||
padding: 1rem 1rem;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-width: 0 0 1px 0;
|
||||
font-weight: 700;
|
||||
color: #374151;
|
||||
background: #f9fafb;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
.myTbody {
|
||||
td {
|
||||
text-align: left;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-width: 0 0 1px 0;
|
||||
padding: 1rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.myTfoot {
|
||||
td {
|
||||
text-align: left;
|
||||
padding: 1rem 1rem;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-width: 0 0 1px 0;
|
||||
font-weight: 700;
|
||||
color: #374151;
|
||||
background: #f9fafb;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
--table-border-color: #B7B7B7B2;
|
||||
--message-error-background: #ffdbdb;
|
||||
--message-error-color: #C2504D;
|
||||
--message-warning-color: #cc8925;
|
||||
--message-info-background: rgba(183, 183, 183, 0.7);
|
||||
--message-info-color: #3B82F6;
|
||||
|
||||
@@ -40,4 +41,6 @@
|
||||
@import "./components/misc.scss";
|
||||
@import "./components/login.scss";
|
||||
@import "./components/flowBuilder.scss";
|
||||
@import "./components/error404.scss";
|
||||
@import "./components/error404.scss";
|
||||
@import "./components/myTable.scss";
|
||||
@import "./components/evaluation.scss";
|
||||
@@ -55,7 +55,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
|
||||
command: () => {
|
||||
navigate('/profilo-aziendale')
|
||||
},
|
||||
enable: !intersection(permissions, ['MANAGE_TENDERS']).length && companies.length > 0
|
||||
enable: intersection(permissions, ['APPLY_CALLS']).length && companies.length > 0
|
||||
},
|
||||
{
|
||||
label: __('Seleziona azienda', 'gepafin'),
|
||||
@@ -67,7 +67,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
|
||||
command: () => {
|
||||
navigate('/agguingi-azienda')
|
||||
},
|
||||
enable: !intersection(permissions, ['MANAGE_TENDERS']).length
|
||||
enable: intersection(permissions, ['APPLY_CALLS']).length
|
||||
},
|
||||
{
|
||||
separator: true,
|
||||
@@ -86,7 +86,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
|
||||
const switchCompany = (id) => {
|
||||
if (chosenCompanyId !== id) {
|
||||
storeSet.main.chosenCompanyId(id);
|
||||
console.log('set company 2', id)
|
||||
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
|
||||
@@ -2,17 +2,62 @@ import { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import equal from 'fast-deep-equal';
|
||||
//import { diff } from 'deep-object-diff';
|
||||
import { klona } from 'klona';
|
||||
import { TZDate } from '@date-fns/tz';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
import { is, isNil } from 'ramda';
|
||||
|
||||
// store
|
||||
import { storeGet } from '../../store';
|
||||
|
||||
const UnsavedChangesDetector = ({ getValuesFn }) => {
|
||||
const warnIfUnsavedChanges = (event) => {
|
||||
const formData = getValuesFn();
|
||||
let formData = klona(getValuesFn());
|
||||
formData.dates = [];
|
||||
|
||||
if (formData.startDate) {
|
||||
let starDate;
|
||||
|
||||
if (is(String, formData.startDate)) {
|
||||
starDate = formData.startDate;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(formData.startDate, 'Europe/Berlin');
|
||||
starDate = tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
|
||||
formData = wrap(formData).insert(['dates'], starDate, 0).value();
|
||||
}
|
||||
if (formData.endDate) {
|
||||
let endDate;
|
||||
|
||||
if (is(String, formData.endDate)) {
|
||||
endDate = formData.endDate;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(formData.endDate, 'Europe/Berlin');
|
||||
endDate = tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
|
||||
formData = wrap(formData).insert(['dates'], endDate, 1).value();
|
||||
}
|
||||
if (!isNil(formData.startTime)) {
|
||||
if (!is(String, formData.startTime)) {
|
||||
const tzAwareDate = new TZDate(formData.startTime, 'Europe/Berlin');
|
||||
formData.startTime = tzAwareDate.toISOString().substring(11, 16);
|
||||
}
|
||||
}
|
||||
if (!isNil(formData.endTime)) {
|
||||
if (!is(String, formData.endTime)) {
|
||||
const tzAwareDate = new TZDate(formData.endTime, 'Europe/Berlin');
|
||||
formData.endTime = tzAwareDate.toISOString().substring(11, 16);
|
||||
}
|
||||
}
|
||||
const initial = storeGet.main.formInitialData();
|
||||
|
||||
const isEqual = equal(initial, formData);
|
||||
// TODO
|
||||
//console.log('isEqual', isEqual, initial, formData, diff(initial, formData))
|
||||
/*console.log('isEqual', isEqual,
|
||||
initial, formData,
|
||||
diff(initial, formData))*/
|
||||
if (!isEqual) {
|
||||
event.returnValue = __('You have unsaved changes. If you proceed, they will be lost.', 'gepafin');
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ const getBandoLabel = (status) => {
|
||||
case 'READY':
|
||||
return __('Pronto', 'gepafin');
|
||||
|
||||
case 'SOCCORSO':
|
||||
return __('Soccorso', 'gepafin');
|
||||
|
||||
case 'DRAFT':
|
||||
return __('Bozza', 'gepafin');
|
||||
|
||||
@@ -38,6 +41,9 @@ const getBandoLabel = (status) => {
|
||||
case 'EXPIRED':
|
||||
return __('Scaduto', 'gepafin');
|
||||
|
||||
case 'CLOSE':
|
||||
return __('Chiuso', 'gepafin');
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ const getBandoSeverity = (status) => {
|
||||
case 'READY':
|
||||
return 'info';
|
||||
|
||||
case 'SOCCORSO':
|
||||
return 'warning';
|
||||
|
||||
case 'DRAFT':
|
||||
return 'warning';
|
||||
|
||||
@@ -36,6 +39,9 @@ const getBandoSeverity = (status) => {
|
||||
case 'EXPIRED':
|
||||
return 'closed';
|
||||
|
||||
case 'CLOSE':
|
||||
return 'closed';
|
||||
|
||||
default:
|
||||
return 'info';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import parse from 'html-react-parser';
|
||||
import { isNil } from 'ramda';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
const renderHtmlContent = (content = '') => !isNil(content) ? parse(content) : '';
|
||||
const renderHtmlContent = (content = '') => {
|
||||
const clean = DOMPurify.sanitize(content);
|
||||
return !isNil(clean) ? parse(clean) : '';
|
||||
}
|
||||
|
||||
export default renderHtmlContent;
|
||||
20
src/icons/HelpIcon/index.js
Normal file
20
src/icons/HelpIcon/index.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
const HelpIcon = () => {
|
||||
return <svg width="15" height="14" viewBox="0 0 15 14" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g clipPath="url(#clip0_1665_1656)">
|
||||
<path
|
||||
d="M7.50129 14C6.53308 14 5.62302 13.8163 4.7711 13.4488C3.91919 13.0814 3.17818 12.5827 2.54805 11.9529C1.91793 11.323 1.41903 10.5823 1.05134 9.73074C0.683781 8.87919 0.5 7.96938 0.5 7.00129C0.5 6.03308 0.683719 5.12302 1.05116 4.2711C1.4186 3.41919 1.91725 2.67818 2.54713 2.04805C3.17701 1.41793 3.91772 0.919026 4.76926 0.551342C5.62081 0.183781 6.53062 0 7.49871 0C8.46692 0 9.37698 0.183719 10.2289 0.551158C11.0808 0.918596 11.8218 1.41725 12.4519 2.04713C13.0821 2.67701 13.581 3.41772 13.9487 4.26926C14.3162 5.12081 14.5 6.03062 14.5 6.99871C14.5 7.96692 14.3163 8.87698 13.9488 9.72889C13.5814 10.5808 13.0827 11.3218 12.4529 11.9519C11.823 12.5821 11.0823 13.081 10.2307 13.4487C9.37919 13.8162 8.46938 14 7.50129 14ZM5.36316 12.4895L6.44576 10.0238C5.98585 9.86147 5.58888 9.60977 5.25484 9.26874C4.92081 8.92758 4.66598 8.52747 4.49037 8.06842L1.99634 9.1C2.28359 9.88596 2.72195 10.5737 3.31142 11.1632C3.90089 11.7526 4.58481 12.1947 5.36316 12.4895ZM4.49037 5.93158C4.65665 5.47253 4.90816 5.07555 5.24489 4.74066C5.58163 4.40576 5.97719 4.15567 6.43158 3.99037L5.4 1.49634C4.60937 1.79587 3.91932 2.24037 3.32984 2.82984C2.74037 3.41932 2.29587 4.10937 1.99634 4.9L4.49037 5.93158ZM7.49834 9.09724C8.08045 9.09724 8.57579 8.8935 8.98437 8.48603C9.39295 8.07855 9.59724 7.58376 9.59724 7.00166C9.59724 6.41955 9.3935 5.92421 8.98603 5.51563C8.57855 5.10705 8.08376 4.90276 7.50166 4.90276C6.91955 4.90276 6.42421 5.1065 6.01563 5.51397C5.60705 5.92145 5.40276 6.41624 5.40276 6.99834C5.40276 7.58045 5.6065 8.07579 6.01397 8.48437C6.42145 8.89295 6.91624 9.09724 7.49834 9.09724ZM9.63684 12.4895C10.4105 12.1947 11.089 11.7557 11.6724 11.1724C12.2557 10.589 12.6947 9.91053 12.9895 9.13684L10.5238 8.05424C10.368 8.50862 10.1209 8.90302 9.78274 9.23742C9.44453 9.57182 9.05203 9.82923 8.60526 10.0096L9.63684 12.4895ZM10.5096 5.89474L12.9895 4.86316C12.6947 4.08947 12.2557 3.41096 11.6724 2.82763C11.089 2.2443 10.4105 1.80526 9.63684 1.51053L8.60526 4.01303C9.04258 4.18299 9.4242 4.43051 9.75013 4.75558C10.0761 5.08053 10.3292 5.46025 10.5096 5.89474Z"
|
||||
fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1665_1656">
|
||||
<rect width="14" height="14" fill="white"
|
||||
transform="translate(0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
}
|
||||
|
||||
export default HelpIcon;
|
||||
@@ -1,12 +1,13 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { intersection, is } from 'ramda';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
|
||||
// components
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import HelpIcon from '../../../../icons/HelpIcon';
|
||||
|
||||
const AppSidebar = () => {
|
||||
const permissions = useStore().main.getPermissions();
|
||||
@@ -41,32 +42,59 @@ const AppSidebar = () => {
|
||||
enable: intersection(permissions, ['VIEW_CALLS']).length
|
||||
},
|
||||
{
|
||||
label: __('Gestione Utenti', 'gepafin'),
|
||||
label: __('Gestione domande', 'gepafin'),
|
||||
icon: 'pi pi-file',
|
||||
href: '/domande',
|
||||
id: 5,
|
||||
enable: intersection(permissions, ['VIEW_USERS', 'MANAGE_USERS']).length
|
||||
},
|
||||
{
|
||||
label: __('Domande da valutare', 'gepafin'),
|
||||
icon: 'pi pi-calendar-clock',
|
||||
href: '/domande',
|
||||
id: 6,
|
||||
enable: intersection(permissions, ['EVALUATE_APPLICATIONS']).length
|
||||
},
|
||||
{
|
||||
label: __('Archivio domande', 'gepafin'),
|
||||
icon: 'pi pi-file',
|
||||
href: '/domande',
|
||||
id: 7,
|
||||
enable: intersection(permissions, ['APPLY_CALLS']).length
|
||||
},
|
||||
{
|
||||
label: __('Soccorso istruttorio', 'gepafin'),
|
||||
icon: <HelpIcon/>,
|
||||
href: '/soccorso-istruttorio',
|
||||
id: 8,
|
||||
enable: intersection(permissions, ['EVALUATE_APPLICATIONS']).length
|
||||
},
|
||||
{
|
||||
label: __('Gestione utenti', 'gepafin'),
|
||||
icon: 'pi pi-users',
|
||||
href: '/utenti',
|
||||
id: 5,
|
||||
enable: false
|
||||
//enable: intersection(permissions, ['VIEW_USERS', 'MANAGE_USERS']).length
|
||||
id: 9,
|
||||
enable: intersection(permissions, ['VIEW_USERS', 'MANAGE_USERS']).length
|
||||
},
|
||||
{
|
||||
label: __('Configurazione', 'gepafin'),
|
||||
icon: 'pi pi-cog',
|
||||
//href: '/configurazione',
|
||||
id: 6,
|
||||
id: 10,
|
||||
enable: false
|
||||
},
|
||||
{
|
||||
label: __('Report e Analisi', 'gepafin'),
|
||||
icon: 'pi pi-chart-bar',
|
||||
//href: '/stats',
|
||||
id: 7,
|
||||
id: 11,
|
||||
enable: false
|
||||
},
|
||||
{
|
||||
label: __('Log di Sistema', 'gepafin'),
|
||||
icon: 'pi pi-receipt',
|
||||
clickFn: () => {},
|
||||
id: 8,
|
||||
id: 12,
|
||||
enable: false
|
||||
}
|
||||
]
|
||||
@@ -78,11 +106,15 @@ const AppSidebar = () => {
|
||||
.map(o => <li key={o.id}>
|
||||
{o.href
|
||||
? <NavLink to={o.href}>
|
||||
<i className={o.icon}></i>
|
||||
{is(String, o.icon)
|
||||
? <i className={o.icon}></i>
|
||||
: o.icon}
|
||||
<span>{o.label}</span>
|
||||
</NavLink>
|
||||
: <button onClick={() => {}}>
|
||||
<i className={o.icon}></i>
|
||||
{is(String, o.icon)
|
||||
? <i className={o.icon}></i>
|
||||
: o.icon}
|
||||
<span>{o.label}</span>
|
||||
</button>}
|
||||
</li>)}
|
||||
|
||||
@@ -27,9 +27,10 @@ const AppTopbar = () => {
|
||||
<i className="pi pi-bell p-overlay-badge topBar__icon">
|
||||
<Badge value="0"></Badge>
|
||||
</i>
|
||||
<i className="pi pi-envelope p-overlay-badge topBar__icon">
|
||||
<i className="pi pi-envelope topBar__icon"></i>
|
||||
{/*<i className="pi pi-envelope p-overlay-badge topBar__icon">
|
||||
<Badge severity="danger"></Badge>
|
||||
</i>
|
||||
</i>*/}
|
||||
<Button
|
||||
className="topBar__profileBtn"
|
||||
outlined
|
||||
@@ -40,7 +41,7 @@ const AppTopbar = () => {
|
||||
<TopBarProfileMenu menuLeftRef={menuLeft}/>
|
||||
</div>
|
||||
|
||||
return(
|
||||
return (
|
||||
<Toolbar start={startContent} end={endContent} className="topBar"/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@ import React, { useState, useEffect} from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
|
||||
// store
|
||||
import { storeSet, storeGet } from '../../../../store';
|
||||
|
||||
// tools
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
@@ -31,12 +28,12 @@ import { Link } from 'react-router-dom';
|
||||
const AllBandiTable = () => {
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
storeSet.main.setAsyncRequest();
|
||||
setLocalAsyncRequest(true);
|
||||
BandoService.getBandi(getCallback, errGetCallbacks);
|
||||
}, []);
|
||||
|
||||
@@ -46,12 +43,11 @@ const AllBandiTable = () => {
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
console.log('errGetCallbacks', data)
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedBandiData = (data) => {
|
||||
@@ -98,9 +94,9 @@ const AllBandiTable = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (rowData) => {
|
||||
/*const nameBodyTemplate = (rowData) => {
|
||||
return <span>{rowData.name}</span>
|
||||
}
|
||||
}*/
|
||||
|
||||
const dateStartBodyTemplate = (rowData) => {
|
||||
return getDateFromISOstring(rowData.dates[0]);
|
||||
@@ -136,7 +132,7 @@ const AllBandiTable = () => {
|
||||
|
||||
return(
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={loading} dataKey="id"
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
@@ -144,15 +140,15 @@ const AllBandiTable = () => {
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateStartBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Data Scadenza', 'gepafin')} filterField="end_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate} filter
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} filter
|
||||
filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
|
||||
@@ -92,21 +92,21 @@ const AllBandiAccordion = () => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />;
|
||||
};
|
||||
|
||||
const addToFavourites = () => {
|
||||
/*const addToFavourites = () => {
|
||||
console.log('addToFavourites');
|
||||
}
|
||||
}*/
|
||||
|
||||
const goToBandoPage = (id) => {
|
||||
navigate(`/bandi/${id}`)
|
||||
}
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
/*const actionsBodyTemplate = (rowData) => {
|
||||
return <div className="appPageSection__tableActions">
|
||||
<button type="button" className="appPageSection__addToFavourites" onClick={addToFavourites} disabled={true}>
|
||||
<i className="pi pi-heart" style={{ fontSize: '1rem' }}></i>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
}*/
|
||||
|
||||
const rowExpansionTemplate = (data) => {
|
||||
return (
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import React from 'react';
|
||||
import { range } from 'ramda';
|
||||
//import { __ } from '@wordpress/i18n';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// components
|
||||
import { Steps } from 'primereact/steps';
|
||||
|
||||
const ApplicationSteps = ({ totalSteps = 0, activeStepIndex }) => {
|
||||
const rangeArr = range(1, totalSteps + 1);
|
||||
const items = rangeArr.map(() => ({ label: 'Passo' }));
|
||||
|
||||
/*// TODO update to using Steps after primereact is updated
|
||||
return(
|
||||
0 !== totalSteps
|
||||
? <span>{__('Passo', 'gepafin')}: {activeStepIndex + 1}</span>
|
||||
: null
|
||||
)*/
|
||||
const items = rangeArr.map(() => ({ label: __('Passo', 'gepafin') }));
|
||||
|
||||
return(
|
||||
0 !== totalSteps
|
||||
|
||||
@@ -326,10 +326,14 @@ const BandoApplication = () => {
|
||||
].includes(cur)) {
|
||||
acc.user[cur] = userData[cur];
|
||||
}
|
||||
if (['dateOfBirth'].includes(cur)) {
|
||||
acc.user[cur] = new Date(userData[cur]);
|
||||
}
|
||||
return acc;
|
||||
}, dynamicData);
|
||||
|
||||
if (data.data.applicationFormResponse.content) {
|
||||
// eslint-disable-next-line array-callback-return
|
||||
data.data.applicationFormResponse.content.map((o) => {
|
||||
if (o.dynamicData && !isEmpty(o.dynamicData)) {
|
||||
formDataInitial[o.id] = pathOr('', o.dynamicData.split('.'), dynamicData);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useForm } from 'react-hook-form';
|
||||
import { isEmpty, isNil, is } from 'ramda';
|
||||
import { klona } from 'klona';
|
||||
import { TZDate } from '@date-fns/tz';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
// components
|
||||
import FormField from '../../../../components/FormField';
|
||||
@@ -48,38 +49,36 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
const values = getValues();
|
||||
const toast = useRef(null);
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
/*if (!isNil(formData.dates) && formData.dates.length) {
|
||||
formData.dates = formData.dates.map(v => {
|
||||
if (is(String, v)) {
|
||||
return v;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(v, 'Europe/Berlin');
|
||||
return tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
if (!formData.id) {
|
||||
BandoService.createBando(formData, createCallback, errCreateCallback);
|
||||
} else {
|
||||
BandoService.updateBandoStep1(formData.id, formData, createCallback, errCreateCallback);
|
||||
}*/
|
||||
};
|
||||
const onSubmit = () => {};
|
||||
|
||||
const onSaveDraft = () => {
|
||||
trigger();
|
||||
const formData = getValues();
|
||||
if (!isNil(formData.dates) && formData.dates.length) {
|
||||
formData.dates = formData.dates.map(v => {
|
||||
if (is(String, v)) {
|
||||
return v;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(v, 'Europe/Berlin');
|
||||
return tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
});
|
||||
let formData = klona(getValues());
|
||||
formData.dates = [];
|
||||
|
||||
if (formData.startDate) {
|
||||
let starDate;
|
||||
|
||||
if (is(String, formData.startDate)) {
|
||||
starDate = formData.startDate;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(formData.startDate, 'Europe/Berlin');
|
||||
starDate = tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
|
||||
formData = wrap(formData).insert(['dates'], starDate, 0).value();
|
||||
}
|
||||
if (formData.endDate) {
|
||||
let endDate;
|
||||
|
||||
if (is(String, formData.endDate)) {
|
||||
endDate = formData.endDate;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(formData.endDate, 'Europe/Berlin');
|
||||
endDate = tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
|
||||
formData = wrap(formData).insert(['dates'], endDate, 1).value();
|
||||
}
|
||||
if (!isNil(formData.startTime)) {
|
||||
if (!is(String, formData.startTime)) {
|
||||
@@ -95,6 +94,9 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
}
|
||||
}
|
||||
|
||||
delete formData.startDate;
|
||||
delete formData.endDate;
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
if (!formData.id) {
|
||||
BandoService.createBando(formData, createCallback, errCreateCallback);
|
||||
@@ -106,11 +108,13 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
const createCallback = (data) => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
if (data.status === 'SUCCESS') {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: __('Il bando è stato aggiornato corretamente!', 'gepafin')
|
||||
});
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: __('Il bando è stato aggiornato corretamente!', 'gepafin')
|
||||
});
|
||||
}
|
||||
const values = getValues();
|
||||
if (!values.id && data.data.id) {
|
||||
navigate(`/bandi/${data.data.id}`);
|
||||
@@ -121,6 +125,13 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
}
|
||||
|
||||
const errCreateCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
@@ -193,7 +204,12 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
useEffect(() => {
|
||||
const newFormData = klona(formInitialData);
|
||||
if (!isNil(formInitialData.dates) && formInitialData.dates.length) {
|
||||
newFormData.dates = formInitialData.dates.map(v => is(String, v) ? new Date(v) : (v ? v : ''));
|
||||
if (newFormData.dates[0]) {
|
||||
newFormData.startDate = is(String, newFormData.dates[0]) ? new Date(newFormData.dates[0]) : (newFormData.dates[0] ? newFormData.dates[0] : '');
|
||||
}
|
||||
if (newFormData.dates[1]) {
|
||||
newFormData.endDate = is(String, newFormData.dates[1]) ? new Date(newFormData.dates[1]) : (newFormData.dates[1] ? newFormData.dates[1] : '');
|
||||
}
|
||||
}
|
||||
if (!isNil(formInitialData.startTime) && !isEmpty(formInitialData.startTime)) {
|
||||
newFormData.startTime = is(String, formInitialData.startTime)
|
||||
@@ -305,7 +321,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
}}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
{/*<FormField
|
||||
type="datepickerrange"
|
||||
disabled={shouldDisableField()}
|
||||
fieldName="dates"
|
||||
@@ -314,7 +330,30 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
errors={errors}
|
||||
defaultValue={values['dates']}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
/>
|
||||
/>*/}
|
||||
<div className="appForm__cols">
|
||||
<FormField
|
||||
type="datepicker"
|
||||
disabled={shouldDisableField()}
|
||||
fieldName="startDate"
|
||||
label={__('Data di inizio', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
defaultValue={values['startDate']}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
type="datepicker"
|
||||
disabled={shouldDisableField()}
|
||||
fieldName="endDate"
|
||||
label={__('Data di fine', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
defaultValue={values['endDate']}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="appForm__cols">
|
||||
<FormField
|
||||
|
||||
@@ -22,6 +22,7 @@ import LookupdataService from '../../../../service/lookupdata-service';
|
||||
import { storeSet } from '../../../../store';
|
||||
import getTimeParsedFromString from '../../../../helpers/getTimeParsedFromString';
|
||||
import { mimeTypes } from '../../../../configData';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, status }, ref) {
|
||||
const navigate = useNavigate();
|
||||
@@ -46,41 +47,36 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
//const step2Props = ['threshold', 'criteria', 'checkList', 'docs', 'images'];
|
||||
const toast = useRef(null);
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
/*if (!isNil(formData.dates) && formData.dates.length) {
|
||||
formData.dates = formData.dates.map(v => {
|
||||
if (is(String, v)) {
|
||||
return v;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(v, 'Europe/Berlin');
|
||||
return tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const forSubmit = Object.keys(formData).reduce((acc, cur) => {
|
||||
if (step2Props.includes(cur)) {
|
||||
acc[cur] = formData[cur];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
BandoService.updateBandoStep2(formData.id, forSubmit, createCallback, errCreateCallback);*/
|
||||
};
|
||||
const onSubmit = () => {};
|
||||
|
||||
const onSaveDraft = () => {
|
||||
trigger();
|
||||
const formData = getValues();
|
||||
if (!isNil(formData.dates) && formData.dates.length) {
|
||||
formData.dates = formData.dates.map(v => {
|
||||
if (is(String, v)) {
|
||||
return v;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(v, 'Europe/Berlin');
|
||||
return tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
});
|
||||
let formData = klona(getValues());
|
||||
formData.dates = [];
|
||||
|
||||
if (formData.startDate) {
|
||||
let starDate;
|
||||
|
||||
if (is(String, formData.startDate)) {
|
||||
starDate = formData.startDate;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(formData.startDate, 'Europe/Berlin');
|
||||
starDate = tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
|
||||
formData = wrap(formData).insert(['dates'], starDate, 0).value();
|
||||
}
|
||||
if (formData.endDate) {
|
||||
let endDate;
|
||||
|
||||
if (is(String, formData.endDate)) {
|
||||
endDate = formData.endDate;
|
||||
} else {
|
||||
const tzAwareDate = new TZDate(formData.endDate, 'Europe/Berlin');
|
||||
endDate = tzAwareDate.toISOString().substring(0, 19);
|
||||
}
|
||||
|
||||
formData = wrap(formData).insert(['dates'], endDate, 1).value();
|
||||
}
|
||||
if (!isNil(formData.startTime)) {
|
||||
if (!is(String, formData.startTime)) {
|
||||
@@ -88,7 +84,6 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
formData.startTime = tzAwareDate.toISOString().substring(11, 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isNil(formData.endTime)) {
|
||||
if (!is(String, formData.endTime)) {
|
||||
const tzAwareDate = new TZDate(formData.endTime, 'Europe/Berlin');
|
||||
@@ -96,6 +91,9 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
}
|
||||
}
|
||||
|
||||
delete formData.startDate;
|
||||
delete formData.endDate;
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
BandoService.updateBandoStep2(formData.id, formData, createCallback, errCreateCallback);
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@ const BandoEdit = () => {
|
||||
BandoService.validateBando(id, validateCallback, errValidateCallback);
|
||||
}
|
||||
|
||||
const validateCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setData({ ...data, status: data.data.status });
|
||||
const validateCallback = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
setData(resp.data);
|
||||
if (bandoMsgs.current) {
|
||||
bandoMsgs.current.show([
|
||||
{
|
||||
@@ -100,19 +100,26 @@ const BandoEdit = () => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errValidateCallback = (data) => {
|
||||
if (data.status === 'VALIDATION_ERROR') {
|
||||
const errValidateCallback = (resp) => {
|
||||
if (resp.status === 'VALIDATION_ERROR') {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
if (bandoMsgs.current) {
|
||||
bandoMsgs.current.show(data.data.map((v, i) => ({
|
||||
bandoMsgs.current.show(resp.data.map((v, i) => ({
|
||||
id: i,
|
||||
sticky: true, severity: 'error', summary: '',
|
||||
detail: v,
|
||||
closable: false
|
||||
})));
|
||||
}
|
||||
if (toast.current) {
|
||||
toast.current.show(resp.data.map((v, i) => ({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: v
|
||||
})));
|
||||
}
|
||||
} else {
|
||||
standardErrCallback(data);
|
||||
standardErrCallback(resp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +129,8 @@ const BandoEdit = () => {
|
||||
BandoService.updateBandoStatus(id, publishCallback, errPublishCallback, [['status', 'PUBLISH']]);
|
||||
}
|
||||
|
||||
const publishCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const publishCallback = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
if (bandoMsgs.current) {
|
||||
bandoMsgs.current.show([
|
||||
{
|
||||
@@ -141,26 +148,31 @@ const BandoEdit = () => {
|
||||
detail: __('Pubblicato!', 'gepafin')
|
||||
});
|
||||
}
|
||||
if (data.data.docs) {
|
||||
data.data.docs = data.data.docs
|
||||
if (resp.data.docs) {
|
||||
resp.data.docs = resp.data.docs
|
||||
.filter(o => o.source === 'CALL' && o.type === 'DOCUMENT');
|
||||
}
|
||||
setData(data.data);
|
||||
setData(resp.data);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errPublishCallback = (data) => {
|
||||
standardErrCallback(data);
|
||||
const errPublishCallback = (resp) => {
|
||||
standardErrCallback(resp);
|
||||
}
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (!isNil(data.data.dates) && data.data.dates.length) {
|
||||
data.data.dates = data.data.dates.map(v => is(String, v) ? new Date(v) : v);
|
||||
const getCallback = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
if (!isNil(resp.data.dates) && resp.data.dates.length) {
|
||||
if (resp.data.dates[0]) {
|
||||
resp.data.startDate = is(String, resp.data.dates[0]) ? new Date(resp.data.dates[0]) : (resp.data.dates[0] ? resp.data.dates[0] : '');
|
||||
}
|
||||
if (resp.data.dates[1]) {
|
||||
resp.data.endDate = is(String, resp.data.dates[1]) ? new Date(resp.data.dates[1]) : (resp.data.dates[1] ? resp.data.dates[1] : '');
|
||||
}
|
||||
}
|
||||
|
||||
if (data.data.status === 'READY_TO_PUBLISH') {
|
||||
if (resp.data.status === 'READY_TO_PUBLISH') {
|
||||
bandoMsgs.current.clear();
|
||||
bandoMsgs.current.show([
|
||||
{
|
||||
@@ -170,7 +182,7 @@ const BandoEdit = () => {
|
||||
closable: false
|
||||
}
|
||||
]);
|
||||
} else if (data.data.status === 'DRAFT') {
|
||||
} else if (resp.data.status === 'DRAFT') {
|
||||
if (bandoMsgs.current) {
|
||||
bandoMsgs.current.clear();
|
||||
bandoMsgs.current.show([
|
||||
@@ -183,26 +195,26 @@ const BandoEdit = () => {
|
||||
]);
|
||||
}
|
||||
}
|
||||
if (data.data.docs) {
|
||||
data.data.docs = data.data.docs
|
||||
if (resp.data.docs) {
|
||||
resp.data.docs = resp.data.docs
|
||||
.filter(o => o.source === 'CALL' && o.type === 'DOCUMENT');
|
||||
}
|
||||
setData(data.data);
|
||||
setData(resp.data);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
const errGetCallback = (resp) => {
|
||||
set404FromErrorResponse(resp);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const standardErrCallback = (data) => {
|
||||
if (bandoMsgs.current && data.message) {
|
||||
const standardErrCallback = (resp) => {
|
||||
if (bandoMsgs.current && resp.message) {
|
||||
bandoMsgs.current.show([
|
||||
{
|
||||
sticky: true, severity: 'error', summary: '',
|
||||
detail: data.message,
|
||||
detail: resp.message,
|
||||
closable: true
|
||||
}
|
||||
]);
|
||||
@@ -210,9 +222,9 @@ const BandoEdit = () => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getFormsCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setForms(data.data);
|
||||
const getFormsCallback = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
setForms(resp.data);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import { head, isEmpty, isNil } from 'ramda';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { klona } from 'klona';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../../../store';
|
||||
@@ -14,13 +15,17 @@ import { TabView, TabPanel } from 'primereact/tabview';
|
||||
import { InputSwitch } from 'primereact/inputswitch';
|
||||
import ElementSetting from './components/ElementSetting';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { MultiSelect } from 'primereact/multiselect';
|
||||
|
||||
const BuilderElementSettings = ({ closeSettings }) => {
|
||||
const BuilderElementSettings = ({ closeSettingsFn }) => {
|
||||
const elements = useStore().main.formElements();
|
||||
const activeElement = useStore().main.activeElement();
|
||||
const criteriaOptions = useStore().main.bandoCriteria();
|
||||
const [activeElementData, setActiveElementData] = useState({});
|
||||
const [settings, setSettings] = useState([]);
|
||||
const [validators, setValidators] = useState({});
|
||||
const [dynamicData, setDynamicData] = useState('');
|
||||
const [criteria, setCriteria] = useState([]);
|
||||
const numberBasedValidatorFields = ['min', 'max', 'minLength', 'maxLength'];
|
||||
const customValidationOptions = [
|
||||
{ value: 'isPIVA', label: 'isPIVA' },
|
||||
@@ -63,11 +68,14 @@ const BuilderElementSettings = ({ closeSettings }) => {
|
||||
}
|
||||
|
||||
const saveSettings = () => {
|
||||
activeElementData.settings = settings;
|
||||
activeElementData.validators = validators;
|
||||
const newElements = elements.map(o => o.id === activeElementData.id ? activeElementData : o);
|
||||
let newActiveElementData = klona(activeElementData);
|
||||
newActiveElementData = wrap(newActiveElementData).set(['settings'], settings).value();
|
||||
newActiveElementData = wrap(newActiveElementData).set(['validators'], validators).value();
|
||||
newActiveElementData = wrap(newActiveElementData).set(['dynamicData'], dynamicData).value();
|
||||
newActiveElementData = wrap(newActiveElementData).set(['criteria'], criteria).value();
|
||||
const newElements = elements.map(o => o.id === newActiveElementData.id ? newActiveElementData : o);
|
||||
storeSet.main.formElements(newElements);
|
||||
closeSettings();
|
||||
closeSettingsFn();
|
||||
}
|
||||
|
||||
const showField = (value, key) => {
|
||||
@@ -92,17 +100,56 @@ const BuilderElementSettings = ({ closeSettings }) => {
|
||||
setValidators(newValidators);
|
||||
}
|
||||
|
||||
const onChangeCriteriaData = (value) => {
|
||||
setCriteria(value);
|
||||
}
|
||||
|
||||
|
||||
const getDynamicDataOptions = (type) => {
|
||||
switch (type) {
|
||||
case 'datepicker' :
|
||||
return [
|
||||
{ label: 'user dateOfBirth', value: 'user.dateOfBirth' }
|
||||
]
|
||||
default :
|
||||
return [
|
||||
{ label: 'company name', value: 'company.companyName' },
|
||||
{ label: 'company piva', value: 'company.vatNumber' },
|
||||
{ label: 'company codiceFiscale', value: 'company.codiceFiscale' },
|
||||
{ label: 'company address', value: 'company.address' },
|
||||
{ label: 'company phoneNumber', value: 'company.phoneNumber' },
|
||||
{ label: 'company city', value: 'company.city' },
|
||||
{ label: 'company province', value: 'company.province' },
|
||||
{ label: 'company cap', value: 'company.cap' },
|
||||
{ label: 'company country', value: 'company.country' },
|
||||
{ label: 'company pec', value: 'company.pec' },
|
||||
{ label: 'company email', value: 'company.email' },
|
||||
{ label: 'company contactName', value: 'company.contactName' },
|
||||
{ label: 'company contactEmail', value: 'company.contactEmail' },
|
||||
{ label: 'user email', value: 'user.email' },
|
||||
{ label: 'user firstName', value: 'user.firstName' },
|
||||
{ label: 'user lastName', value: 'user.lastName' },
|
||||
{ label: 'user phoneNumber', value: 'user.phoneNumber' },
|
||||
{ label: 'user codiceFiscale', value: 'user.codiceFiscale' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const chosen = head(elements.filter(o => o.id === activeElement));
|
||||
|
||||
if (chosen) {
|
||||
setActiveElementData(klona(chosen));
|
||||
setSettings(klona(chosen.settings));
|
||||
setValidators(klona(chosen.validators))
|
||||
setValidators(klona(chosen.validators));
|
||||
setDynamicData(chosen.dynamicData ? chosen.dynamicData : '');
|
||||
setCriteria(chosen.criteria ? chosen.criteria : []);
|
||||
} else {
|
||||
setActiveElementData({});
|
||||
setSettings([]);
|
||||
setValidators({})
|
||||
setValidators({});
|
||||
setDynamicData('');
|
||||
setCriteria([]);
|
||||
}
|
||||
}, [activeElement]);
|
||||
|
||||
@@ -118,6 +165,18 @@ const BuilderElementSettings = ({ closeSettings }) => {
|
||||
changeFn={onChange}
|
||||
updateDataFn={onUpdateOptions}/>)
|
||||
: null}
|
||||
{['textinput', 'datepicker'].includes(activeElementData.name)
|
||||
? <div className="formElementSettings__field">
|
||||
<label htmlFor="dynamicData">{__('Dati dinamici', 'gepafin')}</label>
|
||||
<Dropdown
|
||||
id="dynamicData"
|
||||
value={dynamicData}
|
||||
onChange={(e) => setDynamicData(e.value)}
|
||||
options={getDynamicDataOptions(activeElementData.name)}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder={__('Scegli', 'gepafin')}/>
|
||||
</div> : null}
|
||||
</TabPanel>
|
||||
{!isEmpty(validators)
|
||||
? <TabPanel header={__('Validation', 'gepafin')}>
|
||||
@@ -172,6 +231,20 @@ const BuilderElementSettings = ({ closeSettings }) => {
|
||||
</div> : null}
|
||||
</div>) : null}
|
||||
</TabPanel> : null}
|
||||
<TabPanel header={__('Criteri', 'gepafin')}>
|
||||
<div className="formElementSettings__field">
|
||||
<label htmlFor="criteria">{__('Criteri di valutazione', 'gepafin')}</label>
|
||||
<MultiSelect
|
||||
id="criteria"
|
||||
value={criteria}
|
||||
onChange={(e) => onChangeCriteriaData(e.value)}
|
||||
options={criteriaOptions}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
display="chip"
|
||||
placeholder={__('Scegli', 'gepafin')}/>
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabView>
|
||||
|
||||
<Button label={__('Salva', 'gepafin')} onClick={saveSettings}/>
|
||||
|
||||
@@ -57,7 +57,7 @@ const FormBuilder = () => {
|
||||
<>
|
||||
<Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} className="formBuilder__elementSettings">
|
||||
<h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2>
|
||||
{!isEmpty(activeElement) ? <BuilderElementSettings closeSettings={closeSettings}/> : null}
|
||||
{!isEmpty(activeElement) ? <BuilderElementSettings closeSettingsFn={closeSettings}/> : null}
|
||||
</Sidebar>
|
||||
<div className="formBuilder">
|
||||
<div className="formBuilder__main">
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { klona } from 'klona';
|
||||
import { isEmpty } from 'ramda';
|
||||
import { isEmpty, pathOr } from 'ramda';
|
||||
|
||||
// store
|
||||
import { storeSet, storeGet, useStore } from '../../store';
|
||||
@@ -21,6 +21,7 @@ import { Messages } from 'primereact/messages';
|
||||
// api
|
||||
import FormsService from '../../service/forms-service';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import BandoService from '../../service/bando-service';
|
||||
|
||||
// TODO temp data
|
||||
//import { elementItems } from '../../tempData';
|
||||
@@ -243,7 +244,21 @@ const BandoFormsEdit = () => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getBandoCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const criteria = pathOr([], ['data', 'criteria'], data);
|
||||
const criteriaOptions = criteria.map(o => ({value: o.id, label: o.value}));
|
||||
console.log('criteriaOptions', criteriaOptions);
|
||||
storeSet.main.bandoCriteria(criteriaOptions);
|
||||
}
|
||||
}
|
||||
|
||||
const errGetBandoCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const bandoId = getBandoId();
|
||||
const parsedFormId = parseInt(formId)
|
||||
const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
|
||||
|
||||
@@ -254,11 +269,15 @@ const BandoFormsEdit = () => {
|
||||
storeSet.main.setAsyncRequest();
|
||||
FormsService.getFormById(bandoFormId, getFormCallback, errGetFormCallbacks);
|
||||
}
|
||||
if (bandoId) {
|
||||
BandoService.getBando(bandoId, getBandoCallback, errGetBandoCallback);
|
||||
}
|
||||
|
||||
return () => {
|
||||
storeSet.main.formId(0);
|
||||
storeSet.main.formLabel('');
|
||||
storeSet.main.formElements([]);
|
||||
storeSet.main.bandoCriteria([]);
|
||||
}
|
||||
}, [id, formId]);
|
||||
|
||||
|
||||
@@ -145,11 +145,11 @@ const BandoViewBeneficiario = () => {
|
||||
'isVisible': false
|
||||
}
|
||||
storeSet.main.setAsyncRequest();
|
||||
FaqItemService.addQuestion(id, obj, createCallBack, errCreateCallback, [['companyId', chosenCompanyId]])
|
||||
FaqItemService.addQuestion(id, obj, createQuestionBack, errCreateQuestionCallback, [['companyId', chosenCompanyId]])
|
||||
}
|
||||
}
|
||||
|
||||
const createCallBack = (data) => {
|
||||
const createQuestionBack = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setNewQuestion('');
|
||||
if (toast.current) {
|
||||
@@ -163,7 +163,7 @@ const BandoViewBeneficiario = () => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errCreateCallback = (data) => {
|
||||
const errCreateQuestionCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
@@ -262,10 +262,10 @@ const BandoViewBeneficiario = () => {
|
||||
{!isAsyncRequest && !isEmpty(data)
|
||||
? <div className="appPage__content">
|
||||
{!isEmpty(data.images)
|
||||
? <div><picture className="appPageSection__hero">
|
||||
? <picture className="appPageSection__hero">
|
||||
<source srcSet={data.images[0] ? data.images[0].filePath : ''}/>
|
||||
<img src={data.images[0] ? data.images[0].filePath : ''} alt={data.name}/>
|
||||
</picture></div> : null}
|
||||
</picture> : null}
|
||||
|
||||
<div className="appPageSection__withBorder">
|
||||
<h2>{__('Descrizione breve', 'gepafin')}</h2>
|
||||
@@ -408,7 +408,7 @@ const BandoViewBeneficiario = () => {
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Download Documenti', 'gepafin')}</h2>
|
||||
<div className="appPageSection__actions">
|
||||
{/* <Button
|
||||
{/* <Button
|
||||
type="button"
|
||||
disabled={true}
|
||||
outlined
|
||||
|
||||
@@ -2,13 +2,6 @@ import React, { useState, useEffect} from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { uniq } from 'ramda';
|
||||
|
||||
// tools
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
|
||||
// store
|
||||
import { storeSet } from '../../../../store';
|
||||
|
||||
// api
|
||||
import BandoService from '../../../../service/bando-service';
|
||||
|
||||
@@ -19,11 +12,8 @@ import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
@@ -31,44 +21,12 @@ import { Link } from 'react-router-dom';
|
||||
const LatestBandiTable = () => {
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// TODO
|
||||
/*const items = [
|
||||
{
|
||||
name: 'Bando Innovazione 2024',
|
||||
start_date: '2024-08-08T00:00:00+00:00',
|
||||
end_date: '2024-08-30T00:00:00+00:00',
|
||||
submissions: 24,
|
||||
status: 'PUBLISH',
|
||||
id: 11
|
||||
},
|
||||
{
|
||||
name: 'Bando Sostenibilità 2024',
|
||||
start_date: '2024-07-28T00:00:00+00:00',
|
||||
end_date: '2024-08-15T00:00:00+00:00',
|
||||
submissions: 35,
|
||||
status: 'PUBLISH',
|
||||
id: 9
|
||||
},
|
||||
{
|
||||
name: 'Bando A',
|
||||
start_date: '2024-06-28T00:00:00+00:00',
|
||||
end_date: '2024-06-15T00:00:00+00:00',
|
||||
submissions: 2,
|
||||
status: 'EXPIRED',
|
||||
id: 2
|
||||
}
|
||||
]
|
||||
setItems(getFormattedBandiData(items));
|
||||
setStatuses(uniq(items.map(o => o.status)))
|
||||
setLoading(false);
|
||||
initFilters();*/
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
setLocalAsyncRequest(true);
|
||||
BandoService.getBandi(getCallback, errGetCallbacks);
|
||||
}, []);
|
||||
|
||||
@@ -79,12 +37,11 @@ const LatestBandiTable = () => {
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
console.log('errGetCallbacks', data)
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedBandiData = (data) => {
|
||||
@@ -153,22 +110,10 @@ const LatestBandiTable = () => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
|
||||
};
|
||||
|
||||
const balanceFilterTemplate = (options) => {
|
||||
return <InputNumber value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} />;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const statusFilterTemplate = (options) => {
|
||||
return <Dropdown value={options.value} options={statuses} onChange={(e) => options.filterCallback(e.value, options.index)} itemTemplate={statusItemTemplate} placeholder="Select One" className="p-column-filter" showClear />;
|
||||
};
|
||||
|
||||
const statusItemTemplate = (option) => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />;
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return <Link to={`/bandi/${rowData.id}`}>
|
||||
<Button severity="info" label={__('Modifica', 'gepafin')} icon="pi pi-pencil" size="small" iconPos="right" />
|
||||
@@ -179,22 +124,22 @@ const LatestBandiTable = () => {
|
||||
|
||||
return(
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={loading} dataKey="id"
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name"
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateStartBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Data Scadenza', 'gepafin')} filterField="end_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate} />
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} />
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
|
||||
@@ -110,10 +110,10 @@ const LatestUsersActivityTable = () => {
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column header={__('Timestamp', 'gepafin')} filterField="date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="email" header={__('Utente', 'gepafin')} filter filterPlaceholder="Search by email"
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column field="action" header={__('Azione', 'gepafin')}/>
|
||||
<Column field="dettails" header={__('Dettagli', 'gepafin')}/>
|
||||
</DataTable>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { pathOr } from 'ramda';
|
||||
import NumberFlow from '@number-flow/react';
|
||||
|
||||
// store
|
||||
//import { storeSet } from '../../store';
|
||||
@@ -13,6 +14,8 @@ import DashboardService from '../../service/dashboard-service';
|
||||
import LatestBandiTable from './components/LatestBandiTable';
|
||||
//import LatestUsersActivityTable from './components/LatestUsersActivityTable';
|
||||
import { Button } from 'primereact/button';
|
||||
//import MyEvaluationsTable from '../DashboardPreInstructor/components/PreInstructorDomandeTable';
|
||||
import AllDomandeTable from '../Domande/components/AllDomandeTable';
|
||||
|
||||
const Dashboard = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -34,10 +37,6 @@ const Dashboard = () => {
|
||||
console.log('onGoToSettings')
|
||||
}*/
|
||||
|
||||
function formatToMillions(num) {
|
||||
return Math.abs(num) > 999 ? Math.sign(num)*((Math.abs(num)/1000000).toFixed(1)) + 'M' : Math.sign(num)*Math.abs(num)
|
||||
}
|
||||
|
||||
const getStatValue = (key, fallback = '') => {
|
||||
return pathOr(fallback, [key], mainStats);
|
||||
}
|
||||
@@ -67,27 +66,52 @@ const Dashboard = () => {
|
||||
<div className="statsBigBadges__grid">
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Bandi attivi', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfActiveCalls', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfActiveCalls', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Utenti registrati', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfResgisteredUsers', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfResgisteredUsers', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Domande in pre-istruttoria', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfSubmittedApplications', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfSubmittedApplications', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Domande in bozza', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfDraftApplications', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfDraftApplications', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Aziende', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfCompany', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfCompany', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Totale finanziamenti attivi', 'gepafin')}</span>
|
||||
<span>€{formatToMillions(getStatValue('totalActiveFinancing', 0))}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('totalActiveFinancing', 0)}
|
||||
format={{
|
||||
notation: 'compact',
|
||||
compactDisplay: 'short',
|
||||
roundingMode: 'trunc',
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
currencyDisplay: 'symbol'
|
||||
}}
|
||||
locales="en-US" /></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,10 +119,17 @@ const Dashboard = () => {
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Ultimi Bandi Pubblicati', 'gepafin')}</h2>
|
||||
<h2>{__('Ultimi bandi pubblicati', 'gepafin')}</h2>
|
||||
<LatestBandiTable/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Ultime domande pubblicate', 'gepafin')}</h2>
|
||||
<AllDomandeTable/>
|
||||
</div>
|
||||
|
||||
{/*<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { uniq } from 'ramda';
|
||||
|
||||
// tools
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { storeSet } from '../../../../store';
|
||||
@@ -19,13 +16,9 @@ import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
|
||||
const LatestBandiTable = () => {
|
||||
@@ -43,7 +36,7 @@ const LatestBandiTable = () => {
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const newItems = data.data.filter(o => o.status === 'PUBLISH');
|
||||
setItems(getFormattedBandiData(newItems));
|
||||
setItems(getFormattedData(newItems));
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
@@ -55,7 +48,7 @@ const LatestBandiTable = () => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getFormattedBandiData = (data) => {
|
||||
const getFormattedData = (data) => {
|
||||
return [...(data || [])].map((d) => {
|
||||
d.start_date = new Date(d.dates[0]);
|
||||
d.end_date = new Date(d.dates[1]);
|
||||
@@ -89,18 +82,9 @@ const LatestBandiTable = () => {
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
name: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
start_date: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
end_date: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
|
||||
start_date: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
|
||||
end_date: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
|
||||
status: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
@@ -109,12 +93,10 @@ const LatestBandiTable = () => {
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined
|
||||
onClick={clearFilter}/>
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined onClick={clearFilter} />
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon className="pi pi-search"/>
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange}
|
||||
placeholder={__('Cerca', 'gepafin')}/>
|
||||
<InputIcon className="pi pi-search" />
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} />
|
||||
</IconField>
|
||||
</div>
|
||||
);
|
||||
@@ -129,29 +111,13 @@ const LatestBandiTable = () => {
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999"/>;
|
||||
};
|
||||
|
||||
const balanceFilterTemplate = (options) => {
|
||||
return <InputNumber value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)}/>;
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const statusFilterTemplate = (options) => {
|
||||
return <Dropdown value={options.value} options={statuses}
|
||||
onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
itemTemplate={statusItemTemplate} placeholder="Select One" className="p-column-filter"
|
||||
showClear/>;
|
||||
};
|
||||
|
||||
const statusItemTemplate = (option) => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>;
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return rowData.confidi
|
||||
? <Link to={`/bandi/${rowData.id}`}>
|
||||
@@ -173,16 +139,16 @@ const LatestBandiTable = () => {
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name"
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateStartBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Data Scadenza', 'gepafin')} filterField="end_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate}/>
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} />
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { uniq } from 'ramda';
|
||||
import { uniq, is } from 'ramda';
|
||||
|
||||
// tools
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
|
||||
// api
|
||||
import ApplicationService from '../../../../service/application-service';
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
@@ -20,38 +26,36 @@ import { Calendar } from 'primereact/calendar';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import { Link } from 'react-router-dom';
|
||||
import ApplicationService from '../../../../service/application-service';
|
||||
import { storeSet, useStore } from '../../../../store';
|
||||
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
|
||||
|
||||
|
||||
const MyLatestSubmissionsTable = () => {
|
||||
const chosenCompanyId = useStore().main.chosenCompanyId();
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
storeSet.main.setAsyncRequest();
|
||||
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [['companyId', chosenCompanyId]])
|
||||
setLocalAsyncRequest(true);
|
||||
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [
|
||||
['companyId', chosenCompanyId],
|
||||
['statuses', ['DRAFT', 'SUBMIT', 'AWAITING', 'READY', 'DISCARD']]
|
||||
])
|
||||
}, [chosenCompanyId]);
|
||||
|
||||
const getApplCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (data.data.length) {
|
||||
if (is(Array, data.data)) {
|
||||
setItems(getFormattedBandiData(data.data));
|
||||
setStatuses(uniq(items.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetApplCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedBandiData = (data) => {
|
||||
@@ -165,26 +169,27 @@ const MyLatestSubmissionsTable = () => {
|
||||
|
||||
return (
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={isAsyncRequest} dataKey="id"
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder="Search by name"
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Ultima modifica', 'gepafin')} filterField="modifiedDate" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateModifyBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate} filter
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} filter
|
||||
filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Progressi', 'gepafin')}
|
||||
style={{ minWidth: '10rem' }} field="progress" body={progressBodyTemplate}/>
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
style={{ minWidth: '10rem' }}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { head, pathOr } from 'ramda';
|
||||
import NumberFlow from '@number-flow/react';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../store';
|
||||
@@ -57,15 +58,24 @@ const DashboardBeneficiario = () => {
|
||||
<div className="statsBigBadges__grid">
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Domande attive', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfApplications', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfApplications', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Bandi osservati', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfCalls', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfCalls', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Documenti da integrare', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfIntegratedDocuments', 0)}</span>
|
||||
<span><NumberFlow
|
||||
value={getStatValue('numberOfIntegratedDocuments', 0)}
|
||||
format={{ notation: 'compact' }}
|
||||
locales="it-IT" /></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
import React, { useState, useEffect} from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
|
||||
// api
|
||||
import AssignedApplicationService from '../../../../service/assigned-application-service';
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
|
||||
|
||||
const PreInstructorDomandeTable = () => {
|
||||
const userData = useStore().main.userData();
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalAsyncRequest(true);
|
||||
AssignedApplicationService.getAssignedApplications(getCallback, errGetCallbacks, [
|
||||
['userId', userData.id]
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setItems(getFormattedData(data.data));
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
return data.map((d) => {
|
||||
d.callEndDate = is(String, d.callEndDate) ? new Date(d.callEndDate) : (d.callEndDate ? d.callEndDate : '');
|
||||
d.submissionDate = is(String, d.submissionDate) ? new Date(d.submissionDate) : (d.submissionDate ? d.submissionDate : '');
|
||||
return d;
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (value) => {
|
||||
return value.toLocaleDateString('it-IT', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
initFilters();
|
||||
};
|
||||
|
||||
const onGlobalFilterChange = (e) => {
|
||||
const value = e.target.value;
|
||||
let _filters = { ...filters };
|
||||
|
||||
_filters['global'].value = value;
|
||||
|
||||
setFilters(_filters);
|
||||
setGlobalFilterValue(value);
|
||||
};
|
||||
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
callName: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
submissionDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
callEndDate : {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
}
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined onClick={clearFilter} />
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon className="pi pi-search" />
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} />
|
||||
</IconField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateAppliedBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.submissionDate);
|
||||
};
|
||||
|
||||
const dateEndBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.callEndDate);
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return <Link to={`/domande/${rowData.applicationId}`}>
|
||||
<Button severity="info" label={__('Valuta', 'gepafin')} icon="pi pi-eye" size="small" iconPos="right"/>
|
||||
</Link>
|
||||
}
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
return(
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="applicationId" header={__('ID domanda', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '6rem' }}/>
|
||||
<Column field="callName" header={__('Bando', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data ricezione', 'gepafin')} filterField="submissionDate" dataType="date"
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateAppliedBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date"
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} />
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PreInstructorDomandeTable;
|
||||
75
src/pages/DashboardPreInstructor/index.js
Normal file
75
src/pages/DashboardPreInstructor/index.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
//import { useStore } from '../../store';
|
||||
|
||||
// api
|
||||
//import DashboardService from '../../service/dashboard-service';
|
||||
|
||||
// components
|
||||
//import LatestBandiTable from './components/LatestBandiTable';
|
||||
//import MyLatestSubmissionsTable from './components/MyLatestSubmissionsTable';
|
||||
import { Button } from 'primereact/button';
|
||||
import PreInstructorDomandeTable from './components/PreInstructorDomandeTable';
|
||||
|
||||
const DashboardPreInstructor = () => {
|
||||
const navigate = useNavigate();
|
||||
//const [mainStats, setMainStats] = useState({});
|
||||
|
||||
const goToAllEvaluations = () => {
|
||||
navigate('/domande');
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Dashboard', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
{/*<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection statsBigBadges">
|
||||
<h2>{__('Panoramica di Sistema', 'gepafin')}</h2>
|
||||
<div className="statsBigBadges__grid">
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Domande attive', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfApplications', 0)}</span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Bandi osservati', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfCalls', 0)}</span>
|
||||
</div>
|
||||
<div className="statsBigBadges__gridItem">
|
||||
<span>{__('Documenti da integrare', 'gepafin')}</span>
|
||||
<span>{getStatValue('numberOfIntegratedDocuments', 0)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>*/}
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Coda di lavoro', 'gepafin')}</h2>
|
||||
<PreInstructorDomandeTable/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection__hr">
|
||||
<span>{__('Azioni rapide', 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
onClick={goToAllEvaluations}
|
||||
label={__('Tutte le domande', 'gepafin')} icon="pi pi-arrow-right" iconPos="right"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DashboardPreInstructor;
|
||||
353
src/pages/DomandaBeneficiario/index.js
Normal file
353
src/pages/DomandaBeneficiario/index.js
Normal file
@@ -0,0 +1,353 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { is, isEmpty, isNil } from 'ramda';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
|
||||
// api
|
||||
import AmendmentsService from '../../service/amendments-service';
|
||||
import CommunicationService from '../../service/communication-service';
|
||||
|
||||
// tools
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
||||
import uniqid from '../../helpers/uniqid';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import BlockingOverlay from '../../components/BlockingOverlay';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
|
||||
const DomandaBeneficiario = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState({});
|
||||
const [comms, setComms] = useState([]);
|
||||
const [isVisibleNewCommDialog, setIsVisibleNewCommDialog] = useState(false);
|
||||
const [newCommData, setNewCommData] = useState({});
|
||||
const [isLoadingCommunication, setIsLoadingCommunication] = useState(false);
|
||||
const [isVisibleEmailDialog, setIsVisibleEmailDialog] = useState(false);
|
||||
const toast = useRef(null);
|
||||
|
||||
const goToArchivePage = () => {
|
||||
navigate(`/domande`);
|
||||
}
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (data.data.length) {
|
||||
setData(getFormattedData(data.data[0]));
|
||||
CommunicationService.getCommsByAmendmentId(data.data[0].id, getCommsCallback, errGetCommsCallback);
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getCommsCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setComms(data.data.commentsList.map(o => getFormattedCommsData(o)));
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCommsCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
data.startDate = is(String, data.startDate) ? new Date(data.startDate) : (data.startDate ? data.startDate : '');
|
||||
data.expirationDate = is(String, data.expirationDate) ? new Date(data.expirationDate) : (data.expirationDate ? data.expirationDate : '');
|
||||
return data;
|
||||
};
|
||||
|
||||
const getFormattedCommsData = (data) => {
|
||||
data.id = isNil(data.id) ? uniqid('id') : data.id;
|
||||
data.commentedDate = is(String, data.commentedDate) ? new Date(data.commentedDate) : (data.commentedDate ? data.commentedDate : '');
|
||||
data.createdDate = is(String, data.createdDate) ? new Date(data.createdDate) : (data.createdDate ? data.createdDate : '');
|
||||
data.updatedDate = is(String, data.updatedDate) ? new Date(data.updatedDate) : (data.updatedDate ? data.updatedDate : '');
|
||||
return data;
|
||||
};
|
||||
|
||||
const headerNewComDialog = () => {
|
||||
return <span>{__('Aggiungi comunicazione', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const hideNewComDialog = () => {
|
||||
setIsVisibleNewCommDialog(false);
|
||||
setNewCommData({
|
||||
title: '',
|
||||
comment: ''
|
||||
});
|
||||
}
|
||||
|
||||
const footerNewComDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideNewComDialog} outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={isLoadingCommunication || isEmpty(newCommData.title) || isEmpty(newCommData.comment)}
|
||||
label={__('Invia', 'gepafin')} onClick={createCommunication}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const openNewCommDialog = () => {
|
||||
setIsVisibleNewCommDialog(true);
|
||||
setNewCommData({
|
||||
title: '',
|
||||
comment: ''
|
||||
});
|
||||
}
|
||||
|
||||
const updateNewCommData = (value, path) => {
|
||||
const newData = wrap(newCommData).set(path.split('.'), value).value();
|
||||
setNewCommData(newData);
|
||||
}
|
||||
|
||||
const createCommunication = () => {
|
||||
setIsLoadingCommunication(true);
|
||||
CommunicationService.createCommunication(data.id, newCommData, createCommunicationCallback, errCreateCommunicationCallback);
|
||||
}
|
||||
|
||||
const createCommunicationCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
setComms([...comms, getFormattedCommsData(data.data)])
|
||||
setIsVisibleNewCommDialog(false);
|
||||
}
|
||||
setIsLoadingCommunication(false);
|
||||
}
|
||||
|
||||
const errCreateCommunicationCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
setIsLoadingCommunication(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const parsedId = parseInt(id);
|
||||
const entityId = !isNaN(parsedId) ? parsedId : 0;
|
||||
|
||||
AmendmentsService.getSoccorsoByApplId(entityId, getCallback, errGetCallback, [
|
||||
['statuses', 'AWAITING']
|
||||
]);
|
||||
}, [id]);
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{sprintf(__('Soccorso Istruttorio: richiesta integrazione documenti per domanda #%s', 'gepafin'), id)}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
<Toast ref={toast}/>
|
||||
<BlockingOverlay shouldDisplay={isAsyncRequest}/>
|
||||
|
||||
<div className="appPageSection__row">
|
||||
<Button
|
||||
type="button"
|
||||
outlined
|
||||
onClick={goToArchivePage}
|
||||
label={__('Indietro', 'gepafin')}
|
||||
icon="pi pi-arrow-left" iconPos="left"/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPage__content">
|
||||
<div className="appPageSection__withBorder columns">
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('ID domanda', 'gepafin')}</span>
|
||||
<span>{data.applicationId}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Bando', 'gepafin')}</span>
|
||||
<span>{data.callName}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Beneficiario', 'gepafin')}</span>
|
||||
<span>{data.beneficiaryName}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Inizio', 'gepafin')}</span>
|
||||
<span>{getDateFromISOstring(data.startDate)}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Scadenza', 'gepafin')}</span>
|
||||
<span>{getDateFromISOstring(data.expirationDate)}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Stato', 'gepafin')}</span>
|
||||
<span>{getBandoLabel(data.status)}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
|
||||
<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">
|
||||
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
|
||||
<div className="appPageSection__withBorder grey ql-editor"
|
||||
style={{ minHeight: '200px' }}>
|
||||
{renderHtmlContent(data.note)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Comunicazioni', 'gepafin')}</h2>
|
||||
<table className="myTable">
|
||||
<thead className="myThead">
|
||||
<tr>
|
||||
<th style={{ width: 250 }}>{__('Data', 'gepafin')}</th>
|
||||
<th>{__('Comunicazione', 'gepafin')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="myTbody">
|
||||
{!isNil(comms) && !isEmpty(comms)
|
||||
? comms.map((o, i) => <tr key={o.id}>
|
||||
<td valign="top">
|
||||
{getDateFromISOstring(o.commentedDate)}
|
||||
</td>
|
||||
<td>
|
||||
<h3>{o.title}</h3>
|
||||
<p>{o.comment}</p>
|
||||
</td>
|
||||
</tr>)
|
||||
: <tr>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Button
|
||||
style={{ marginTop: 30 }}
|
||||
onClick={openNewCommDialog}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
type="button"
|
||||
label={__('Aggiungi Comunicazione', 'gepafin')}
|
||||
icon="pi pi-plus" iconPos="right"/>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection__message warning">
|
||||
<i className="pi pi-exclamation-triangle"></i>
|
||||
<span className="summary">{__('Attenzione', 'gepafin')}</span>
|
||||
<span>{__('Inviare la documentazione richiesta completa delle integrazioni esclusivamente via PEC. In caso contarrio l’integrazione non può essere ritenuta valida.', 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
type="button"
|
||||
disabled={isAsyncRequest}
|
||||
onClick={() => setIsVisibleEmailDialog(true)}
|
||||
label={__('Invia documenti via PEC', 'gepafin')}
|
||||
icon="pi pi-envelope" iconPos="right"/>
|
||||
<Button
|
||||
type="button"
|
||||
outlined
|
||||
onClick={goToArchivePage}
|
||||
disabled={isAsyncRequest}
|
||||
label={__('Chiudi', 'gepafin')}
|
||||
icon="pi pi-times" iconPos="right"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
visible={isVisibleNewCommDialog}
|
||||
modal
|
||||
header={headerNewComDialog}
|
||||
footer={footerNewComDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideNewComDialog}>
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newCommData.title) })}>
|
||||
{__('Titolo', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newCommData.title}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
invalid={isEmpty(newCommData.title)}
|
||||
onChange={(e) => updateNewCommData(e.target.value, 'title')}/>
|
||||
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newCommData.comment) })}>
|
||||
{__('Contenuto', 'gepafin')}*
|
||||
</label>
|
||||
<InputTextarea
|
||||
value={newCommData.comment}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
rows={5} cols={30}
|
||||
invalid={isEmpty(newCommData.comment)}
|
||||
onChange={(e) => updateNewCommData(e.target.value, 'comment')}/>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<Dialog
|
||||
header={__('Invia documenti via PEC', 'gepafin')}
|
||||
visible={isVisibleEmailDialog}
|
||||
style={{ width: '50vw' }}
|
||||
onHide={() => {if (!isVisibleEmailDialog) return; setIsVisibleEmailDialog(false); }}>
|
||||
<p className="m-0">
|
||||
{data.callEmail}
|
||||
</p>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default DomandaBeneficiario;
|
||||
564
src/pages/DomandaEditPreInstructor/index.js
Normal file
564
src/pages/DomandaEditPreInstructor/index.js
Normal file
@@ -0,0 +1,564 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { is, isEmpty, isNil, sum, pathOr, head } from 'ramda';
|
||||
import { klona } from 'klona';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
|
||||
// api
|
||||
import ApplicationEvaluationService from '../../service/application-evaluation-service';
|
||||
import AmendmentsService from '../../service/amendments-service';
|
||||
|
||||
// tools
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||
|
||||
// components
|
||||
import { Skeleton } from 'primereact/skeleton';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Checkbox } from 'primereact/checkbox';
|
||||
import { Editor } from 'primereact/editor';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
import BlockingOverlay from '../../components/BlockingOverlay';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import HelpIcon from '../../icons/HelpIcon';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
|
||||
const DomandaEditPreInstructor = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState({});
|
||||
const [isVisibleCriterionData, setIsVisibleCriterionData] = useState(0);
|
||||
const [criterionDataTitle, setCriterionDataTitle] = useState('');
|
||||
const [criterionDataContent, setCriterionDataContent] = useState('');
|
||||
const [isAdmissible, setIsAdmissible] = useState(false);
|
||||
const [connectedSoccorsoId, setConnectedSoccorsoId] = useState(0);
|
||||
const toast = useRef(null);
|
||||
|
||||
const goToEvaluationsPage = () => {
|
||||
navigate('/domande');
|
||||
}
|
||||
|
||||
const doNewSoccorso = () => {
|
||||
if (connectedSoccorsoId !== 0) {
|
||||
navigate(`/domande/${id}/soccorso/${connectedSoccorsoId}`);
|
||||
} else {
|
||||
|
||||
navigate(`/domande/${id}/aggiungi-soccorso/`);
|
||||
}
|
||||
}
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setData(getFormattedData(data.data));
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
data.submissionDate = is(String, data.submissionDate) ? new Date(data.submissionDate) : (data.submissionDate ? data.submissionDate : '');
|
||||
data.evaluationDate = is(String, data.evaluationDate) ? new Date(data.evaluationDate) : (data.evaluationDate ? data.evaluationDate : '');
|
||||
return data;
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<span className="ql-formats">
|
||||
<button className="ql-bold" aria-label="Bold"></button>
|
||||
<button className="ql-italic" aria-label="Italic"></button>
|
||||
<button className="ql-underline" aria-label="Underline"></button>
|
||||
<button className="ql-link" aria-label="Link"></button>
|
||||
<button className="ql-list" value="ordered"></button>
|
||||
<button className="ql-header" value="2"></button>
|
||||
<button className="ql-header" value="3"></button>
|
||||
<button className="ql-blockquote"></button>
|
||||
<button className="ql-list" value="bullet"></button>
|
||||
<button className="ql-indent" value="-1"></button>
|
||||
<button className="ql-indent" value="+1"></button>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
const updateEvaluationValue = (value, path, maxValue) => {
|
||||
let finalValue = value;
|
||||
|
||||
if (maxValue) {
|
||||
finalValue = value > maxValue ? maxValue : value;
|
||||
}
|
||||
|
||||
const newData = wrap(data).set(path.split('.'), finalValue).value();
|
||||
setData(newData);
|
||||
}
|
||||
|
||||
const doSaveDraft = () => {
|
||||
const formData = {
|
||||
criteria: klona(data.criteria),
|
||||
checklist: klona(data.checklist),
|
||||
files: klona(data.files),
|
||||
note: data.note
|
||||
}
|
||||
ApplicationEvaluationService.updateEvaluation(data.assignedApplicationId, formData, updateCallback, errUpdateCallback);
|
||||
}
|
||||
|
||||
const updateCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errUpdateCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const doApprove = () => {
|
||||
const formData = {
|
||||
status: 'APPROVED'
|
||||
}
|
||||
ApplicationEvaluationService.updateEvaluation(data.assignedApplicationId, formData, updateStatusCallback, errUpdateStatusCallback);
|
||||
}
|
||||
|
||||
const doReject = () => {
|
||||
const formData = {
|
||||
status: 'REJECTED'
|
||||
}
|
||||
ApplicationEvaluationService.updateEvaluation(data.assignedApplicationId, formData, updateStatusCallback, errUpdateStatusCallback);
|
||||
}
|
||||
|
||||
const updateStatusCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errUpdateStatusCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const displayCriterionData = (id) => {
|
||||
const criterion = head(data.criteria.filter(o => o.id === id));
|
||||
setCriterionDataTitle(criterion.label);
|
||||
const content = <div className="criterionRelatedData">
|
||||
<h3>{__('I campi correlati')}</h3>
|
||||
{criterion.criteriaMappedFields ? criterion.criteriaMappedFields.map(o => criteriaDataItem(o)) : null}
|
||||
</div>;
|
||||
setCriterionDataContent(content);
|
||||
setIsVisibleCriterionData(id);
|
||||
}
|
||||
|
||||
const criteriaDataItem = (item) => {
|
||||
let content = '';
|
||||
|
||||
if (is(String, item.fieldValue)) {
|
||||
content = item.fieldValue;
|
||||
} else if (item.fieldValue && item.fieldValue.length && !isNil(item.fieldValue[0].filePath)) {
|
||||
content = <ul>
|
||||
{item.fieldValue.map(o => <li key={o.id}>
|
||||
{o.filePath ? <a href={o.filePath}>{o.name}</a> : null}
|
||||
</li>)}
|
||||
</ul>;
|
||||
} else if (item.fieldValue && item.fieldValue.length && isNil(item.fieldValue[0].filePath)) {
|
||||
const th = Object.keys(item.fieldValue[0]);
|
||||
content = <table>
|
||||
<thead>
|
||||
<tr>
|
||||
{th.map(v => <th key={v}>{v}</th>)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{item.fieldValue.map((o, i) => <tr key={i}>
|
||||
{Object.values(o).map(v => <td key={v}>{v}</td>)}
|
||||
</tr>)}
|
||||
</tbody>
|
||||
</table>;
|
||||
}
|
||||
|
||||
return <div key={item.id} className="criterionRelatedData__item">
|
||||
<strong>{item.fieldLabel}</strong>
|
||||
{content}
|
||||
</div>
|
||||
}
|
||||
|
||||
const hideCriterionData = () => {
|
||||
setIsVisibleCriterionData(0);
|
||||
setCriterionDataTitle('');
|
||||
setCriterionDataContent('');
|
||||
}
|
||||
|
||||
const getAmendmentsCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (data.data.length) {
|
||||
setConnectedSoccorsoId(data.data[0].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errGetAmendmentsCallback = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const maxScore = pathOr(0, ['minScore'], data);
|
||||
const criteria = pathOr([], ['criteria'], data);
|
||||
const scoreSum = sum(criteria.map(o => o.score));
|
||||
|
||||
setIsAdmissible(scoreSum !== 0 && scoreSum >= maxScore);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
const parsed = parseInt(id)
|
||||
const entityId = !isNaN(parsed) ? parsed : 0;
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
ApplicationEvaluationService.getEvaluationByApplId(getCallback, errGetCallback, [
|
||||
['applicationId', entityId]
|
||||
]);
|
||||
AmendmentsService.getSoccorsoByApplId(entityId, getAmendmentsCallback, errGetAmendmentsCallback, [
|
||||
['statuses', 'AWAITING']
|
||||
]);
|
||||
}, [id]);
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Valuta domanda', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
<Toast ref={toast}/>
|
||||
<BlockingOverlay shouldDisplay={isAsyncRequest}/>
|
||||
|
||||
<div className="appPageSection__row">
|
||||
<Button
|
||||
type="button"
|
||||
outlined
|
||||
onClick={goToEvaluationsPage}
|
||||
label={__('Indietro', 'gepafin')}
|
||||
icon="pi pi-arrow-left" iconPos="left"/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
{!isAsyncRequest && !isEmpty(data)
|
||||
? <div className="appPage__content">
|
||||
<div className="appPageSection__withBorder columns">
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('ID domanda', 'gepafin')}</span>
|
||||
<span>{data.applicationId}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Bando', 'gepafin')}</span>
|
||||
<span>{data.callName}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Beneficiario', 'gepafin')}</span>
|
||||
<span>{data.beneficiary}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Data ricezione', 'gepafin')}</span>
|
||||
<span>{getDateFromISOstring(data.submissionDate)}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Scadenza Valutazione', 'gepafin')}</span>
|
||||
<span>{getDateFromISOstring(data.callEndDate)}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Stato', 'gepafin')}</span>
|
||||
<span>{getBandoLabel(data.applicationStatus)}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Punteggi di valutazione', 'gepafin')}</h2>
|
||||
{data.criteria
|
||||
? <table className="myTable">
|
||||
<thead className="myThead">
|
||||
<tr>
|
||||
<th>{__('Parametro', 'gepafin')}</th>
|
||||
<th style={{ width: 200 }}>{__('Punteggio', 'gepafin')}</th>
|
||||
<th style={{ width: 220 }}>{__('Stato', 'gepafin')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="myTbody">
|
||||
{data.criteria.map((o, i) => <tr key={o.id}>
|
||||
<td>{o.label}</td>
|
||||
<td>
|
||||
<div className="p-inputgroup">
|
||||
<InputNumber
|
||||
placeholder={__('Punteggio', 'gepafin')}
|
||||
keyfilter="int"
|
||||
value={o.score}
|
||||
max={o.maxScore}
|
||||
onChange={(e) => updateEvaluationValue(
|
||||
e.value,
|
||||
`criteria.${i}.score`,
|
||||
o.maxScore
|
||||
)}/>
|
||||
<span className="p-inputgroup-addon">
|
||||
/ {o.maxScore}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="appPageSection__iconActions">
|
||||
{!isEmpty(o.criteriaMappedFields)
|
||||
? <Button icon="pi pi-eye"
|
||||
rounded outlined severity="info"
|
||||
onClick={() => displayCriterionData(o.id)}
|
||||
aria-label={__('Mostra', 'gepafin')}/> : null}
|
||||
<Button icon="pi pi-thumbs-up" rounded outlined
|
||||
severity={!isNil(o.valid) && o.valid ? 'success' : 'secondary'}
|
||||
onClick={() => updateEvaluationValue(
|
||||
true,
|
||||
`criteria.${i}.valid`
|
||||
)}
|
||||
aria-label={__('Su', 'gepafin')}/>
|
||||
<Button icon="pi pi-thumbs-down" rounded outlined
|
||||
severity={!isNil(o.valid) && !o.valid ? 'danger' : 'secondary'}
|
||||
onClick={() => updateEvaluationValue(
|
||||
false,
|
||||
`criteria.${i}.valid`
|
||||
)}
|
||||
aria-label={__('Giu', 'gepafin')}/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>)}
|
||||
<tr>
|
||||
<td>{__('Punteggio:', 'gepafin')}</td>
|
||||
<td>{sum(data.criteria.map(o => o.score))}</td>
|
||||
<td>
|
||||
{isAdmissible
|
||||
? <Tag icon="pi pi-check" severity="success"
|
||||
value={__('Ammissibile')}></Tag> : null}
|
||||
{!isAdmissible
|
||||
? <Tag icon="pi pi-times" severity="warning"
|
||||
value={__('Inammissibile')}></Tag> : null}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot className="myTfoot">
|
||||
<tr>
|
||||
<td colSpan="3">{sprintf(__('Punteggio minimo per l\'ammissione: %d'), data.minScore)}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table> : null}
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Checklist Valutazione', 'gepafin')}</h2>
|
||||
<div className="appPageSection columns">
|
||||
<div>
|
||||
|
||||
<h3>{__('Lista', 'gepafin')}</h3>
|
||||
<div className="appPageSection__withBorder grey" style={{ marginBottom: '20px' }}>
|
||||
<div className="appPageSection__checklist">
|
||||
{data.checklist.map((o, i) => <div key={o.id}>
|
||||
<Checkbox
|
||||
inputId={`checklist_${o.id}`}
|
||||
onChange={(e) => updateEvaluationValue(
|
||||
e.checked,
|
||||
`checklist.${i}.valid`
|
||||
)}
|
||||
checked={o.valid}></Checkbox>
|
||||
<label htmlFor={`checklist_${o.id}`}>{o.label}</label>
|
||||
</div>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>{__('Note', 'gepafin')}</h3>
|
||||
<div>
|
||||
<Editor
|
||||
value={data.note}
|
||||
placeholder={__('Digita qui il messagio', 'gepafin')}
|
||||
headerTemplate={header}
|
||||
onTextChange={(e) => updateEvaluationValue(
|
||||
e.htmlValue,
|
||||
'note'
|
||||
)}
|
||||
style={{ height: 80 * 3, width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3>{__('Documenti allegati', 'gepafin')}</h3>
|
||||
<ol className="appPageSection__list">
|
||||
{data.files.map((o, i) => <li key={o.id}>
|
||||
<div className="appPageSection" style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}}>
|
||||
<span>{o.label}</span>
|
||||
<div className="appPageSection__iconActions">
|
||||
{o.fileDetail && o.fileDetail.length === 1
|
||||
? <Button icon="pi pi-eye" rounded
|
||||
onClick={() => window.open(o.fileDetail[0].filePath, '_blank').focus()}
|
||||
outlined severity="info"
|
||||
aria-label={__('Mostra', 'gepafin')}/> : null}
|
||||
<Button icon="pi pi-thumbs-up" rounded outlined
|
||||
severity={!isNil(o.valid) && o.valid ? 'success' : 'secondary'}
|
||||
onClick={() => updateEvaluationValue(
|
||||
true,
|
||||
`files.${i}.valid`
|
||||
)}
|
||||
aria-label={__('Su', 'gepafin')}/>
|
||||
<Button icon="pi pi-thumbs-down" rounded outlined
|
||||
severity={!isNil(o.valid) && !o.valid ? 'danger' : 'secondary'}
|
||||
onClick={() => updateEvaluationValue(
|
||||
false,
|
||||
`files.${i}.valid`
|
||||
)}
|
||||
aria-label={__('Giu', 'gepafin')}/>
|
||||
</div>
|
||||
</div>
|
||||
{o.fileDetail && o.fileDetail.length > 1
|
||||
? <ul style={{
|
||||
width: '100%',
|
||||
paddingLeft: '15px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '10px'
|
||||
}}>
|
||||
{o.fileDetail.map((k, i) => <li key={k.id} style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}}>
|
||||
<span>{k.name}</span>
|
||||
<div className="appPageSection__iconActions">
|
||||
<Button icon="pi pi-eye" rounded
|
||||
onClick={() => window.open(k.filePath, '_blank').focus()}
|
||||
outlined severity="info"
|
||||
aria-label={__('Mostra', 'gepafin')}/>
|
||||
</div>
|
||||
</li>)}
|
||||
</ul>
|
||||
: null}
|
||||
</li>)}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection__hr">
|
||||
<span>{__('Azioni rapide', 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!data.id}
|
||||
onClick={doNewSoccorso}
|
||||
outlined
|
||||
label={<>
|
||||
{__('Richiedi Soccorso Istruttorio', 'gepafin')}
|
||||
<i style={{ marginLeft: 7 }}>
|
||||
<HelpIcon/>
|
||||
</i>
|
||||
</>}
|
||||
/>
|
||||
{data.id
|
||||
? <Button
|
||||
type="button"
|
||||
onClick={doSaveDraft}
|
||||
outlined
|
||||
label={__('Salva bozza valutazione', 'gepafin')}
|
||||
icon="pi pi-save" iconPos="right"/>
|
||||
: <Button
|
||||
type="button"
|
||||
onClick={doSaveDraft}
|
||||
label={__('Crea valutazione', 'gepafin')}
|
||||
icon="pi pi-save" iconPos="right"/>}
|
||||
{data.id
|
||||
? <Button
|
||||
type="button"
|
||||
disabled={!isAdmissible}
|
||||
onClick={doApprove}
|
||||
label={__('Approva Domanda', 'gepafin')}
|
||||
icon="pi pi-check" iconPos="right"/> : null}
|
||||
{data.id
|
||||
? <Button
|
||||
type="button"
|
||||
onClick={doReject}
|
||||
label={__('Respingi Domanda', 'gepafin')}
|
||||
icon="pi pi-times" iconPos="right"/> : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
header={criterionDataTitle}
|
||||
visible={isVisibleCriterionData !== 0}
|
||||
style={{ width: '50vw' }}
|
||||
onHide={hideCriterionData}>
|
||||
{criterionDataContent}
|
||||
</Dialog>
|
||||
|
||||
</div>
|
||||
: <>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="4rem" className="mb-8"></Skeleton>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="4rem"></Skeleton>
|
||||
</>}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default DomandaEditPreInstructor;
|
||||
173
src/pages/Domande/components/AllDomandeTable/index.js
Normal file
173
src/pages/Domande/components/AllDomandeTable/index.js
Normal file
@@ -0,0 +1,173 @@
|
||||
import React, { useState, useEffect} from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
//import { storeSet, storeGet } from '../../../../store';
|
||||
|
||||
// api
|
||||
import ApplicationService from '../../../../service/application-service';
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
|
||||
|
||||
const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalAsyncRequest(true);
|
||||
ApplicationService.getApplications(getCallback, errGetCallbacks, [
|
||||
['statuses', 'SUBMIT']
|
||||
]);
|
||||
}, [updaterString]);
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setItems(getFormattedData(data.data));
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
return data.map((d) => {
|
||||
d.callEndDate = is(String, d.callEndDate) ? new Date(d.callEndDate) : (d.callEndDate ? d.callEndDate : '');
|
||||
d.modifiedDate = is(String, d.modifiedDate) ? new Date(d.modifiedDate) : (d.modifiedDate ? d.modifiedDate : '');
|
||||
d.submissionDate = is(String, d.submissionDate) ? new Date(d.submissionDate) : (d.submissionDate ? d.submissionDate : '');
|
||||
return d;
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (value) => {
|
||||
return value.toLocaleDateString('it-IT', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
initFilters();
|
||||
};
|
||||
|
||||
const onGlobalFilterChange = (e) => {
|
||||
const value = e.target.value;
|
||||
let _filters = { ...filters };
|
||||
|
||||
_filters['global'].value = value;
|
||||
|
||||
setFilters(_filters);
|
||||
setGlobalFilterValue(value);
|
||||
};
|
||||
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
callTitle: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
submissionDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
callEndDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
}
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined onClick={clearFilter} />
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon className="pi pi-search" />
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} />
|
||||
</IconField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateAppliedBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.submissionDate);
|
||||
};
|
||||
|
||||
const dateEndBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.callEndDate);
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return openDialogFn
|
||||
? <Button severity="info"
|
||||
onClick={() => openDialogFn(rowData.id)}
|
||||
label={__('Assegnare', 'gepafin')}
|
||||
icon="pi pi-pencil" size="small" iconPos="right" />
|
||||
: <Link to={'/domande'}>
|
||||
<Button severity="info" label={__('Gestire', 'gepafin')} size="small" />
|
||||
</Link>
|
||||
}
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
return(
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="id" header={__('ID domanda', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="callTitle" header={__('Bando', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column header={__('Data Ricezione', 'gepafin')}
|
||||
filterField="submissionDate" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
body={dateAppliedBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Scadenza', 'gepafin')}
|
||||
filterField="callEndDate" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate} />
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AllDomandeTable;
|
||||
178
src/pages/Domande/index.js
Normal file
178
src/pages/Domande/index.js
Normal file
@@ -0,0 +1,178 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { isEmpty } from 'ramda';
|
||||
|
||||
// api
|
||||
import UserService from '../../service/user-service';
|
||||
import AssignedApplicationService from '../../service/assigned-application-service';
|
||||
|
||||
// store
|
||||
import { storeSet } from '../../store';
|
||||
|
||||
// tools
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import uniqid from '../../helpers/uniqid';
|
||||
|
||||
// components
|
||||
import AllDomandeTable from './components/AllDomandeTable';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Button } from 'primereact/button';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
|
||||
const Domande = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isVisibleEditDialog, setIsVisibleEditDialog] = useState(false);
|
||||
const [roleId, setRoleId] = useState(0);
|
||||
const [users, setUsers] = useState([]);
|
||||
const [chosenUser, setChosenUser] = useState(0);
|
||||
const [chosenApplication, setChosenApplication] = useState(0);
|
||||
const [updaterString, setUpdaterString] = useState('');
|
||||
const toast = useRef(null);
|
||||
|
||||
const getRolesCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const roles = data.data
|
||||
.filter(o => ['ROLE_PRE_INSTRUCTOR'].includes(o.roleType));
|
||||
if (roles.length) {
|
||||
setRoleId(roles[0].id);
|
||||
}
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errGetRolesCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const getUsersCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const users = data.data
|
||||
.map(o => ({
|
||||
name: `${o.firstName} ${o.lastName} (${o.email})`,
|
||||
value: o.id
|
||||
}));
|
||||
setUsers(users);
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errGetUsersCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const headerEditDialog = () => {
|
||||
return <span>{__('Assign application', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const hideEditDialog = () => {
|
||||
setIsVisibleEditDialog(false);
|
||||
setChosenUser(0);
|
||||
setChosenApplication(0);
|
||||
}
|
||||
|
||||
const footerEditDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideEditDialog} outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={loading}
|
||||
label={__('Invia', 'gepafin')} onClick={saveEditDialog}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const openAssignDialog = (applId) => {
|
||||
setChosenApplication(applId)
|
||||
setIsVisibleEditDialog(true);
|
||||
}
|
||||
|
||||
const saveEditDialog = () => {
|
||||
if (chosenUser !== 0 && chosenApplication !== 0) {
|
||||
storeSet.main.setAsyncRequest();
|
||||
AssignedApplicationService.assignApplication(chosenApplication, assignApplCallback, errAssignApplCallback, [
|
||||
['userId', chosenUser]
|
||||
]);
|
||||
hideEditDialog();
|
||||
}
|
||||
}
|
||||
|
||||
const assignApplCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
setUpdaterString(uniqid());
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errAssignApplCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (roleId !== 0) {
|
||||
setLoading(true);
|
||||
UserService.getUsers(getUsersCallback, errGetUsersCallback, [['roleId', roleId]])
|
||||
}
|
||||
}, [roleId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisibleEditDialog) {
|
||||
setLoading(true);
|
||||
UserService.getRoles(getRolesCallback, errGetRolesCallback)
|
||||
}
|
||||
}, [isVisibleEditDialog]);
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Gestione domande', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<AllDomandeTable openDialogFn={openAssignDialog} updaterString={updaterString}/>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
visible={isVisibleEditDialog}
|
||||
modal
|
||||
header={headerEditDialog}
|
||||
footer={footerEditDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideEditDialog}>
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(chosenUser) || chosenUser === 0 || chosenApplication === 0 })}>
|
||||
{__('Pre-istruttore', 'gepafin')}*
|
||||
</label>
|
||||
<Dropdown
|
||||
value={chosenUser}
|
||||
invalid={isEmpty(chosenUser) || chosenUser === 0 || chosenApplication === 0}
|
||||
onChange={(e) => setChosenUser(e.value)}
|
||||
options={users}
|
||||
optionLabel="name"
|
||||
optionValue="value"/>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Domande;
|
||||
@@ -0,0 +1,193 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
|
||||
// api
|
||||
import ApplicationService from '../../../../service/application-service';
|
||||
|
||||
// tools
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { Tag } from 'primereact/tag';
|
||||
|
||||
|
||||
const BeneficiarioDomandeTable = () => {
|
||||
const chosenCompanyId = useStore().main.chosenCompanyId();
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalAsyncRequest(true);
|
||||
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [
|
||||
['companyId', chosenCompanyId],
|
||||
['statuses', ['SOCCORSO', 'APPROVED', 'REJECTED', 'EVALUATION']]
|
||||
])
|
||||
}, [chosenCompanyId]);
|
||||
|
||||
const getApplCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (is(Array, data.data)) {
|
||||
setItems(getFormattedBandiData(data.data));
|
||||
setStatuses(uniq(items.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
}
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetApplCallback = (data) => {
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedBandiData = (data) => {
|
||||
return [...(data || [])].map((d) => {
|
||||
d.callEndDate = new Date(d.callEndDate);
|
||||
d.modifiedDate = new Date(d.modifiedDate);
|
||||
d.submissionDate = new Date(d.submissionDate);
|
||||
|
||||
return d;
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (value) => {
|
||||
return value.toLocaleDateString('it-IT', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
initFilters();
|
||||
};
|
||||
|
||||
const onGlobalFilterChange = (e) => {
|
||||
const value = e.target.value;
|
||||
let _filters = { ...filters };
|
||||
|
||||
_filters['global'].value = value;
|
||||
|
||||
setFilters(_filters);
|
||||
setGlobalFilterValue(value);
|
||||
};
|
||||
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
callTitle: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
modifiedDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
callEndDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
}
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined
|
||||
onClick={clearFilter}/>
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon className="pi pi-search"/>
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange}
|
||||
placeholder={__('Cerca', 'gepafin')}/>
|
||||
</IconField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateSubmissionBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.submissionDate);
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999"/>;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const statusFilterTemplate = (options) => {
|
||||
return <Dropdown value={options.value} options={statuses}
|
||||
onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
itemTemplate={statusItemTemplate} placeholder="Select One" className="p-column-filter"
|
||||
showClear/>;
|
||||
};
|
||||
|
||||
const progressBodyTemplate = (options) => {
|
||||
return '-';
|
||||
};
|
||||
|
||||
const statusItemTemplate = (option) => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>;
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return rowData.status === 'SOCCORSO'
|
||||
? <Link to={`/domande/${rowData.id}`}>
|
||||
<Button severity="info" label={__('Dettagli', 'gepafin')} icon="pi pi-eye" size="small"
|
||||
iconPos="right"/>
|
||||
</Link> : null;
|
||||
}
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
return (
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="id" header={__('ID domanda', 'gepafin')} filter
|
||||
filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '6rem' }}/>
|
||||
<Column field="callTitle" header={__('Titolo bando', 'gepafin')} filter
|
||||
filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data di invio', 'gepafin')} filterField="submissionDate" dataType="date"
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateSubmissionBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} filter
|
||||
filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Esito', 'gepafin')}
|
||||
style={{ minWidth: '7rem' }} field="progress" body={progressBodyTemplate}/>
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BeneficiarioDomandeTable;
|
||||
23
src/pages/DomandeBeneficiario/index.js
Normal file
23
src/pages/DomandeBeneficiario/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// components
|
||||
import BeneficiarioDomandeTable from './components/BeneficiarioDomandeTable';
|
||||
|
||||
const DomandePreInstructor = () => {
|
||||
return(
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Archivio domande', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<BeneficiarioDomandeTable/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DomandePreInstructor;
|
||||
23
src/pages/DomandePreInstructor/index.js
Normal file
23
src/pages/DomandePreInstructor/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// components
|
||||
import PreInstructorDomandeTable from '../DashboardPreInstructor/components/PreInstructorDomandeTable';
|
||||
|
||||
const DomandePreInstructor = () => {
|
||||
return(
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Archivio domande', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<PreInstructorDomandeTable/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DomandePreInstructor;
|
||||
@@ -30,6 +30,10 @@ const LoginAdmin = () => {
|
||||
formState: { errors },
|
||||
} = useForm({ mode: 'onChange' });
|
||||
|
||||
const gotToResetPassword = () => {
|
||||
navigate('/reset-password');
|
||||
}
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
errorMsgs.current.clear();
|
||||
setLoading(true);
|
||||
@@ -67,10 +71,6 @@ const LoginAdmin = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const gotToResetPassword = () => {
|
||||
navigate('/reset-password');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(token)) {
|
||||
setLoading(true);
|
||||
|
||||
@@ -129,88 +129,7 @@ const Profile = () => {
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Consensi', 'gepafin')}</h2>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
disabled={true}
|
||||
fieldName="privacy"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Dichiaro di aver preso visione, prima dell\'accesso al portale https://bandi.gepafin.it, dell\' "Informativa Privacy" all\'interno dell\'Appendice 10 dell\'Avviso secondo il Regolamento UE 2016/679 relativo alla protezione delle persone fisiche con riguardo al trattamento dei dati personale, nonché alla libera circolazione di tali dati e che abroga la Direttiva 95/46 CE.', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
disabled={true}
|
||||
fieldName="terms"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Termini e condizioni', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
fieldName="marketing"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti promozione e vendita di prodotti e servizi della Gepafin, mediante modalità di contatto automatizzate (posta elettronica, PEC, messaggi tramite canali informatici, network ed applicazioni web) e tradizionali (come posta cartacea e chiamate telefoniche con operatore)', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
fieldName="offers"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Elaborazione, in forma elettronica, dei dati relativi ai rapporti e servizi forniti, per l’analisi di comportamenti e preferenze della clientela, da utilizzare a scopo commerciale, per la individuazione ed offerta di prodotti e servizi di suo interesse', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
fieldName="thirdParty"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Comunicazione dei miei dati ad altre società in ambito bancario, finanziario od assicurativo e enti pubblici che li tratteranno per invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti loro prodotti o servizi, mediante le modalità automatizzate e tradizionali di comunicazione sopra indicate', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Utenti Associati', 'gepafin')}</h2>
|
||||
<h2>{__('Impostazioni', 'gepafin')}</h2>
|
||||
<div className="appForm__cols">
|
||||
<FormField
|
||||
type="select"
|
||||
|
||||
288
src/pages/ProfileBeneficiario/index.js
Normal file
288
src/pages/ProfileBeneficiario/index.js
Normal file
@@ -0,0 +1,288 @@
|
||||
import React, { useMemo, useRef } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
|
||||
// components
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import FormField from '../../components/FormField';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
// api
|
||||
import UserService from '../../service/user-service';
|
||||
|
||||
// tools
|
||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||
|
||||
const ProfileBeneficiario = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const userData = useStore().main.userData();
|
||||
const toast = useRef(null);
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors }
|
||||
} = useForm({
|
||||
defaultValues: useMemo(() => {
|
||||
return userData;
|
||||
}, [userData]),
|
||||
mode: 'onChange'
|
||||
});
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
storeSet.main.setAsyncRequest();
|
||||
|
||||
UserService.updateUser(userData.id, formData, updateCallback, updateError);
|
||||
};
|
||||
|
||||
const updateCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
storeSet.main.userData(data.data);
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: __('L\'utente è stato aggiornato!', 'gepafin')
|
||||
});
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const updateError = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Profilo utente', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
<Toast ref={toast}/>
|
||||
|
||||
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Informazioni personali', 'gepafin')}</h2>
|
||||
<div className="appForm__cols">
|
||||
<FormField
|
||||
type="textinput"
|
||||
disabled={true}
|
||||
fieldName="firstName"
|
||||
label={__('Nome', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
placeholder="Francesco"
|
||||
/>
|
||||
|
||||
<FormField
|
||||
type="textinput"
|
||||
disabled={true}
|
||||
fieldName="lastName"
|
||||
label={__('Cognome', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
placeholder="Moli"
|
||||
/>
|
||||
|
||||
<FormField
|
||||
type="textinput"
|
||||
disabled={true}
|
||||
fieldName="codiceFiscale"
|
||||
label={__('Codice fiscale', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
placeholder="XXXXXXXX"
|
||||
/>
|
||||
</div>
|
||||
<div className="appForm__cols">
|
||||
<FormField
|
||||
type="textinput"
|
||||
fieldName="email"
|
||||
label={__('Email', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
placeholder="user@example.com"
|
||||
/>
|
||||
|
||||
<FormField
|
||||
type="textinput"
|
||||
fieldName="phoneNumber"
|
||||
label={__('Telefono', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
placeholder="1234567"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Consensi', 'gepafin')}</h2>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
disabled={true}
|
||||
fieldName="privacy"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Dichiaro di aver preso visione, prima dell\'accesso al portale https://bandi.gepafin.it, dell\' "Informativa Privacy" all\'interno dell\'Appendice 10 dell\'Avviso secondo il Regolamento UE 2016/679 relativo alla protezione delle persone fisiche con riguardo al trattamento dei dati personale, nonché alla libera circolazione di tali dati e che abroga la Direttiva 95/46 CE.', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
disabled={true}
|
||||
fieldName="terms"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Termini e condizioni', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
fieldName="marketing"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti promozione e vendita di prodotti e servizi della Gepafin, mediante modalità di contatto automatizzate (posta elettronica, PEC, messaggi tramite canali informatici, network ed applicazioni web) e tradizionali (come posta cartacea e chiamate telefoniche con operatore)', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
fieldName="offers"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Elaborazione, in forma elettronica, dei dati relativi ai rapporti e servizi forniti, per l’analisi di comportamenti e preferenze della clientela, da utilizzare a scopo commerciale, per la individuazione ed offerta di prodotti e servizi di suo interesse', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__switchFieldWrapper">
|
||||
<FormField
|
||||
type="switch"
|
||||
fieldName="thirdParty"
|
||||
label={''}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onLabel={''}
|
||||
offLabel={''}
|
||||
/>
|
||||
<div>
|
||||
{__('Comunicazione dei miei dati ad altre società in ambito bancario, finanziario od assicurativo e enti pubblici che li tratteranno per invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti loro prodotti o servizi, mediante le modalità automatizzate e tradizionali di comunicazione sopra indicate', 'gepafin')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Impostazioni', 'gepafin')}</h2>
|
||||
<div className="appForm__cols">
|
||||
<FormField
|
||||
type="select"
|
||||
disabled={true}
|
||||
fieldName="language"
|
||||
defaultValue={'it'}
|
||||
label={__('Lingua predefinita', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
options={[
|
||||
{ label: __('Italiano', 'gepafin'), name: 'it' }
|
||||
]}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
type="select"
|
||||
disabled={true}
|
||||
fieldName="timezone"
|
||||
defaultValue={'Europe/Rome'}
|
||||
label={__('Fuso Orario', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
options={[
|
||||
{ label: __('Europe/Rome', 'gepafin'), name: 'Europe/Rome' }
|
||||
]}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
type="select"
|
||||
disabled={true}
|
||||
fieldName="dateformat"
|
||||
defaultValue={'DD/MM/YY'}
|
||||
label={__('Formato Data', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
options={[
|
||||
{ label: __('DD/MM/YY', 'gepafin'), name: 'DD/MM/YY' }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Sicurezza', 'gepafin')}</h2>
|
||||
<div className="appForm__row">
|
||||
<label>{__('Ultimo accesso', 'gepafin')}</label>
|
||||
<span>{getDateFromISOstring(userData.lastLogin)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection__hr">
|
||||
<span>{__('Azioni rapide', 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
disabled={isAsyncRequest}
|
||||
label={__('Salva modifiche', 'gepafin')}
|
||||
icon="pi pi-check" iconPos="right"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default ProfileBeneficiario;
|
||||
@@ -3,6 +3,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { isEmpty } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// tools
|
||||
import AuthenticationService from '../../service/authentication-service';
|
||||
@@ -16,7 +17,10 @@ import LogoIcon from '../../icons/LogoIcon';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Messages } from 'primereact/messages';
|
||||
|
||||
const APP_HUB_ID = process.env.REACT_APP_HUB_ID;
|
||||
|
||||
const ResetPassword = () => {
|
||||
const navigate = useNavigate();
|
||||
const token = useStore().main.token();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [resetPassToken, setResetPassToken] = useState('');
|
||||
@@ -30,14 +34,23 @@ const ResetPassword = () => {
|
||||
setValue
|
||||
} = useForm({ mode: 'onChange' });
|
||||
|
||||
const gotToLoginAdmin = () => {
|
||||
navigate('/loginadmin');
|
||||
}
|
||||
|
||||
const onSubmit = (formData) => {
|
||||
errorMsgs.current.clear();
|
||||
setLoading(true);
|
||||
const request = {
|
||||
...formData
|
||||
...formData,
|
||||
hubUuid: APP_HUB_ID
|
||||
}
|
||||
|
||||
AuthenticationService.forgotPassword(request, getCallback, errCallback);
|
||||
if (request.token && !isEmpty(request.token)) {
|
||||
AuthenticationService.resetPassword(request, getCallback, errCallback);
|
||||
} else {
|
||||
AuthenticationService.forgotPassword(request, getCallback, errCallback);
|
||||
}
|
||||
};
|
||||
|
||||
const getCallback = (data) => {
|
||||
@@ -59,7 +72,7 @@ const ResetPassword = () => {
|
||||
errorMsgs.current.show([
|
||||
{
|
||||
sticky: true, severity: 'error', summary: '',
|
||||
detail: sprintf(__('%s', 'gepafin'), err),
|
||||
detail: sprintf(__('%s', 'gepafin'), err.message),
|
||||
closable: true
|
||||
}
|
||||
]);
|
||||
@@ -104,7 +117,7 @@ const ResetPassword = () => {
|
||||
? <input
|
||||
type="hidden"
|
||||
name="token"
|
||||
{...register('test', {
|
||||
{...register('token', {
|
||||
required: true
|
||||
})}
|
||||
/> : null}
|
||||
@@ -130,7 +143,7 @@ const ResetPassword = () => {
|
||||
type="textinput"
|
||||
inputtype="password"
|
||||
fieldName="confirmPassword"
|
||||
label={__('Conferma Password', 'gepafin')}
|
||||
label={__('Conferma password', 'gepafin')}
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{
|
||||
@@ -144,6 +157,10 @@ const ResetPassword = () => {
|
||||
<Button
|
||||
label={__('Invia', 'gepafin')}
|
||||
disabled={loading}/>
|
||||
|
||||
<Button
|
||||
label={__('Accedi', 'gepafin')}
|
||||
link onClick={gotToLoginAdmin}/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
300
src/pages/SoccorsoAddPreInstructor/index.js
Normal file
300
src/pages/SoccorsoAddPreInstructor/index.js
Normal file
@@ -0,0 +1,300 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { isEmpty } from 'ramda';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
|
||||
// api
|
||||
import AmendmentsService from '../../service/amendments-service';
|
||||
|
||||
// tools
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
|
||||
// components
|
||||
import { Skeleton } from 'primereact/skeleton';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Checkbox } from 'primereact/checkbox';
|
||||
import { Editor } from 'primereact/editor';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
import BlockingOverlay from '../../components/BlockingOverlay';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { InputSwitch } from 'primereact/inputswitch';
|
||||
|
||||
const SoccorsoEditPreInstructor = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const { id, evaluationId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState({});
|
||||
const [formData, setFormData] = useState({});
|
||||
const toast = useRef(null);
|
||||
|
||||
const goToEvaluationPage = () => {
|
||||
navigate(`/domande/${id}`);
|
||||
}
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
console.log(data.data)
|
||||
setData(data.data);
|
||||
setFormData(getFormattedFormData(data.data));
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getFormattedFormData = (data) => {
|
||||
let newData = {};
|
||||
newData.formFields = data.formFields;
|
||||
newData.responseDays = 10;
|
||||
newData.note = '';
|
||||
newData.isSendNotification = true;
|
||||
newData.isSendEmail = true;
|
||||
return newData;
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<span className="ql-formats">
|
||||
<button className="ql-bold" aria-label="Bold"></button>
|
||||
<button className="ql-italic" aria-label="Italic"></button>
|
||||
<button className="ql-underline" aria-label="Underline"></button>
|
||||
<button className="ql-link" aria-label="Link"></button>
|
||||
<button className="ql-list" value="ordered"></button>
|
||||
<button className="ql-header" value="2"></button>
|
||||
<button className="ql-header" value="3"></button>
|
||||
<button className="ql-blockquote"></button>
|
||||
<button className="ql-list" value="bullet"></button>
|
||||
<button className="ql-indent" value="-1"></button>
|
||||
<button className="ql-indent" value="+1"></button>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
const updateEvaluationValue = (value, path, maxValue) => {
|
||||
let finalValue = value;
|
||||
|
||||
if (maxValue) {
|
||||
finalValue = value > maxValue ? maxValue : value;
|
||||
}
|
||||
|
||||
const newData = wrap(formData).set(path.split('.'), finalValue).value();
|
||||
|
||||
setFormData(newData);
|
||||
}
|
||||
|
||||
const doCreate = () => {
|
||||
storeSet.main.setAsyncRequest();
|
||||
|
||||
AmendmentsService.createSoccorso(formData, createCallback, errCreateCallback, [
|
||||
['applicationEvaluationId', evaluationId]
|
||||
]);
|
||||
}
|
||||
|
||||
const createCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
setTimeout(() => {
|
||||
navigate(`/domande/${id}/soccorso/${data.data.id}`);
|
||||
}, 1000)
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errCreateCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const parsed = parseInt(evaluationId)
|
||||
const entityId = !isNaN(parsed) ? parsed : 0;
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
AmendmentsService.getSoccorsoByApplEvalId(entityId, getCallback, errGetCallback);
|
||||
}, [evaluationId]);
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Richiesta Integrazione Documentale', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
<Toast ref={toast}/>
|
||||
<BlockingOverlay shouldDisplay={isAsyncRequest}/>
|
||||
|
||||
<div className="appPageSection__row">
|
||||
<Button
|
||||
type="button"
|
||||
outlined
|
||||
onClick={goToEvaluationPage}
|
||||
label={__('Indietro', 'gepafin')}
|
||||
icon="pi pi-arrow-left" iconPos="left"/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
{!isAsyncRequest && !isEmpty(data)
|
||||
? <div className="appPage__content">
|
||||
<div className="appPageSection__withBorder column">
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('ID domanda', 'gepafin')}</span>
|
||||
<span>{data.applicationId}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Bando', 'gepafin')}</span>
|
||||
<span>{data.callName}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Beneficiario', 'gepafin')}</span>
|
||||
<span>{data.beneficiaryName}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection columns">
|
||||
<div>
|
||||
<h3>{__('Note', 'gepafin')}</h3>
|
||||
<div style={{marginBottom: '30px'}}>
|
||||
<Editor
|
||||
value={formData.note}
|
||||
placeholder={__('Digita qui il messagio', 'gepafin')}
|
||||
headerTemplate={header}
|
||||
onTextChange={(e) => updateEvaluationValue(
|
||||
e.htmlValue,
|
||||
'note'
|
||||
)}
|
||||
style={{ height: 80 * 3, width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3>{__('Tempo per la Risposta (giorni)', 'gepafin')}</h3>
|
||||
<div style={{marginBottom: '30px'}}>
|
||||
<InputNumber
|
||||
keyfilter="int"
|
||||
value={formData.responseDays}
|
||||
showButtons
|
||||
onChange={(e) => updateEvaluationValue(
|
||||
e.value,
|
||||
'responseDays',
|
||||
9999
|
||||
)}/>
|
||||
</div>
|
||||
|
||||
<h3>{__('Notifica', 'gepafin')}</h3>
|
||||
<div className="appPageSection__withBorder grey">
|
||||
<div className="appForm__field row">
|
||||
<InputSwitch
|
||||
inputId="notify_email"
|
||||
checked={formData.isSendEmail}
|
||||
onChange={(e) => updateEvaluationValue(
|
||||
e.value,
|
||||
'isSendEmail'
|
||||
)}/>
|
||||
<label htmlFor="notify_email">{__('Notifiche Email', 'gepafin')}</label>
|
||||
</div>
|
||||
<div className="appForm__field row">
|
||||
<InputSwitch
|
||||
inputId="notify_push"
|
||||
checked={formData.isSendNotification}
|
||||
onChange={(e) => updateEvaluationValue(
|
||||
e.value,
|
||||
'isSendNotification'
|
||||
)}/>
|
||||
<label htmlFor="notify_push">{__('Notifiche Push', 'gepafin')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{formData.formFields
|
||||
? <div>
|
||||
<h3>{__('Documenti da Integrare', 'gepafin')}</h3>
|
||||
<div className="appPageSection__withBorder grey">
|
||||
<div className="appPageSection__checklist">
|
||||
{formData.formFields.map((o, i) => <div key={o.fieldId}>
|
||||
<Checkbox
|
||||
inputId={`checklist_${o.fieldId}`}
|
||||
onChange={(e) => updateEvaluationValue(
|
||||
e.checked,
|
||||
`formFields.${i}.selected`
|
||||
)}
|
||||
checked={o.selected}></Checkbox>
|
||||
<label htmlFor={`checklist_${o.fieldId}`}>{o.label}</label>
|
||||
</div>)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection__message warning">
|
||||
<i className="pi pi-exclamation-triangle"></i>
|
||||
<span className="summary">{__('Attenzione', 'gepafin')}</span>
|
||||
<span>{__("L'invio della richiesta di integrazione sospenderà il termine di valutazione della domanda.", 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection__hr">
|
||||
<span>{__('Azioni', 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
type="button"
|
||||
outlined
|
||||
label={__('Anulla', 'gepafin')}
|
||||
icon="pi pi-times" iconPos="right"/>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={doCreate}
|
||||
label={__('Invia richiesta', 'gepafin')}
|
||||
icon="pi pi-check" iconPos="right"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
: <>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="4rem" className="mb-8"></Skeleton>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||
<Skeleton width="100%" height="4rem"></Skeleton>
|
||||
</>}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default SoccorsoEditPreInstructor;
|
||||
653
src/pages/SoccorsoEditPreInstructor/index.js
Normal file
653
src/pages/SoccorsoEditPreInstructor/index.js
Normal file
@@ -0,0 +1,653 @@
|
||||
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { is, isEmpty, isNil } from 'ramda';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
import { klona } from 'klona';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
|
||||
// api
|
||||
import AmendmentsService from '../../service/amendments-service';
|
||||
import CommunicationService from '../../service/communication-service';
|
||||
|
||||
// tools
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
||||
import uniqid from '../../helpers/uniqid';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import BlockingOverlay from '../../components/BlockingOverlay';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import FormField from '../../components/FormField';
|
||||
import { Editor } from 'primereact/editor';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
|
||||
const SoccorsoEditPreInstructor = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const { id, amendmentId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState({});
|
||||
const [comms, setComms] = useState([]);
|
||||
const [isVisibleNewCommDialog, setIsVisibleNewCommDialog] = useState(false);
|
||||
const [newCommData, setNewCommData] = useState({});
|
||||
const [isLoadingCommunication, setIsLoadingCommunication] = useState(false);
|
||||
const [isVisibleExtendTimeDialog, setIsVisibleExtendTimeDialog] = useState(false);
|
||||
const [extendedTime, setExtendedTime] = useState(3);
|
||||
const [isLoadingExtendingTime, setIsLoadingExtendingTime] = useState(false);
|
||||
const [isLoadingReminding, setIsLoadingReminding] = useState(false);
|
||||
const toast = useRef(null);
|
||||
const [formInitialData, setFormInitialData] = useState({});
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
setValue,
|
||||
register,
|
||||
trigger,
|
||||
getValues
|
||||
} = useForm({
|
||||
defaultValues: useMemo(() => {
|
||||
return formInitialData;
|
||||
}, [formInitialData]), mode: 'onChange'
|
||||
});
|
||||
|
||||
const goToEvaluationPage = () => {
|
||||
navigate(`/domande/${id}`);
|
||||
}
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setData(getFormattedData(data.data));
|
||||
const formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
|
||||
if (cur.fieldValue) {
|
||||
acc[cur.fieldId] = cur.fieldValue;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
setFormInitialData(formDataInitial);
|
||||
CommunicationService.getCommsByAmendmentId(data.data.id, getCommsCallback, errGetCommsCallback);
|
||||
}
|
||||
//storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getCommsCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setComms(data.data.commentsList.map(o => getFormattedCommsData(o)));
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetCommsCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
data.startDate = is(String, data.startDate) ? new Date(data.startDate) : (data.startDate ? data.startDate : '');
|
||||
data.expirationDate = is(String, data.expirationDate) ? new Date(data.expirationDate) : (data.expirationDate ? data.expirationDate : '');
|
||||
return data;
|
||||
};
|
||||
|
||||
const getFormattedCommsData = (data) => {
|
||||
data.id = isNil(data.id) ? uniqid('id') : data.id;
|
||||
data.commentedDate = is(String, data.commentedDate) ? new Date(data.commentedDate) : (data.commentedDate ? data.commentedDate : '');
|
||||
data.createdDate = is(String, data.createdDate) ? new Date(data.createdDate) : (data.createdDate ? data.createdDate : '');
|
||||
data.updatedDate = is(String, data.updatedDate) ? new Date(data.updatedDate) : (data.updatedDate ? data.updatedDate : '');
|
||||
return data;
|
||||
};
|
||||
|
||||
const headerNewComDialog = () => {
|
||||
return <span>{__('Aggiungi comunicazione', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const hideNewComDialog = () => {
|
||||
setIsVisibleNewCommDialog(false);
|
||||
setNewCommData({
|
||||
title: '',
|
||||
comment: ''
|
||||
});
|
||||
}
|
||||
|
||||
const footerNewComDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideNewComDialog} outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={isLoadingCommunication || isEmpty(newCommData.title) || isEmpty(newCommData.comment)}
|
||||
label={__('Invia', 'gepafin')} onClick={createCommunication}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const openNewCommDialog = () => {
|
||||
setIsVisibleNewCommDialog(true);
|
||||
setNewCommData({
|
||||
title: '',
|
||||
comment: ''
|
||||
});
|
||||
}
|
||||
|
||||
const updateNewCommData = (value, path) => {
|
||||
const newData = wrap(newCommData).set(path.split('.'), value).value();
|
||||
setNewCommData(newData);
|
||||
}
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<span className="ql-formats">
|
||||
<button className="ql-bold" aria-label="Bold"></button>
|
||||
<button className="ql-italic" aria-label="Italic"></button>
|
||||
<button className="ql-underline" aria-label="Underline"></button>
|
||||
<button className="ql-link" aria-label="Link"></button>
|
||||
<button className="ql-list" value="ordered"></button>
|
||||
<button className="ql-header" value="2"></button>
|
||||
<button className="ql-header" value="3"></button>
|
||||
<button className="ql-blockquote"></button>
|
||||
<button className="ql-list" value="bullet"></button>
|
||||
<button className="ql-indent" value="-1"></button>
|
||||
<button className="ql-indent" value="+1"></button>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
const updateNewAmendmentData = (value, path) => {
|
||||
const newData = wrap(data).set(path.split('.'), value).value();
|
||||
setData(newData);
|
||||
}
|
||||
|
||||
const createCommunication = () => {
|
||||
setIsLoadingCommunication(true);
|
||||
CommunicationService.createCommunication(amendmentId, newCommData, createCommunicationCallback, errCreateCommunicationCallback);
|
||||
}
|
||||
|
||||
const createCommunicationCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
setComms([...comms, getFormattedCommsData(data.data)])
|
||||
setIsVisibleNewCommDialog(false);
|
||||
}
|
||||
setIsLoadingCommunication(false);
|
||||
}
|
||||
|
||||
const errCreateCommunicationCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
setIsLoadingCommunication(false);
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
};
|
||||
|
||||
const doUpdateAmendment = () => {
|
||||
trigger();
|
||||
let formValues = klona(getValues());
|
||||
const newFormValues = Object.keys(formValues)
|
||||
.reduce((acc, cur) => {
|
||||
let fieldVal = formValues[cur];
|
||||
|
||||
fieldVal = isEmpty(fieldVal) ? null : fieldVal;
|
||||
fieldVal = is(Array, fieldVal) ? fieldVal.map(o => o.id).join(',') : null;
|
||||
|
||||
acc.push({
|
||||
'fieldId': cur,
|
||||
'fieldValue': fieldVal
|
||||
});
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const submitData = {
|
||||
updatedFormFields: newFormValues,
|
||||
}
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
AmendmentsService.updateSoccorso(amendmentId, submitData, updateAmendmentCallback, errUpdateAmendmentCallback);
|
||||
}
|
||||
|
||||
const updateAmendmentCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errUpdateAmendmentCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const doCloseAmendment = () => {
|
||||
const submitData = {
|
||||
internalNote: data.internalNote
|
||||
}
|
||||
storeSet.main.setAsyncRequest();
|
||||
AmendmentsService.closeSoccorso(amendmentId, submitData, closeAmendmentCallback, errCloseAmendmentCallback);
|
||||
}
|
||||
|
||||
const closeAmendmentCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
if (data.data.status) {
|
||||
updateNewAmendmentData(data.data.status, 'status')
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errCloseAmendmentCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const headerExtendRespDialog = () => {
|
||||
return <span>{__('Estendi scadenza', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const hideExtendRespDialog = () => {
|
||||
setIsVisibleExtendTimeDialog(false);
|
||||
}
|
||||
|
||||
const footerExtendRespDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideExtendRespDialog} outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={isLoadingExtendingTime || isEmpty(extendedTime)}
|
||||
label={__('Invia', 'gepafin')} onClick={doExtendTimeResponse}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const openExtendResponseTimeDialog = () => {
|
||||
setIsVisibleExtendTimeDialog(true);
|
||||
setExtendedTime(3);
|
||||
}
|
||||
|
||||
const doExtendTimeResponse = () => {
|
||||
setIsLoadingExtendingTime(true);
|
||||
AmendmentsService.extendSoccorso(amendmentId, extendedTime, extendCallback, errExtendCallback);
|
||||
}
|
||||
|
||||
const extendCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
setIsVisibleExtendTimeDialog(false);
|
||||
}
|
||||
setIsLoadingExtendingTime(false);
|
||||
}
|
||||
|
||||
const errExtendCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
setIsLoadingExtendingTime(false);
|
||||
}
|
||||
|
||||
const sendReminder = () => {
|
||||
setIsLoadingReminding(true);
|
||||
AmendmentsService.sendReminderForSoccorso(amendmentId, reminderCallback, errReminderCallback)
|
||||
}
|
||||
|
||||
const reminderCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
}
|
||||
setIsLoadingReminding(false);
|
||||
}
|
||||
|
||||
const errReminderCallback = (data) => {
|
||||
if (toast.current && data.message) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
setIsLoadingReminding(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const parsedSoccorsoId = parseInt(amendmentId);
|
||||
const soccorsoEntityId = !isNaN(parsedSoccorsoId) ? parsedSoccorsoId : 0;
|
||||
|
||||
AmendmentsService.getSoccorsoById(getCallback, errGetCallback, [['id', soccorsoEntityId]]);
|
||||
}, [amendmentId]);
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Soccorso Istruttorio - Dettagli', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
<Toast ref={toast}/>
|
||||
<BlockingOverlay shouldDisplay={isAsyncRequest}/>
|
||||
|
||||
<div className="appPageSection__row">
|
||||
<Button
|
||||
type="button"
|
||||
outlined
|
||||
onClick={goToEvaluationPage}
|
||||
label={__('Indietro', 'gepafin')}
|
||||
icon="pi pi-arrow-left" iconPos="left"/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPage__content">
|
||||
<div className="appPageSection__withBorder columns">
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('ID domanda', 'gepafin')}</span>
|
||||
<span>{data.applicationId}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Bando', 'gepafin')}</span>
|
||||
<span>{data.callName}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Beneficiario', 'gepafin')}</span>
|
||||
<span>{data.beneficiaryName}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Inizio', 'gepafin')}</span>
|
||||
<span>{getDateFromISOstring(data.startDate)}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Scadenza', 'gepafin')}</span>
|
||||
<span>{getDateFromISOstring(data.expirationDate)}</span>
|
||||
</p>
|
||||
<p className="appPageSection__pMeta">
|
||||
<span>{__('Stato', 'gepafin')}</span>
|
||||
<span>{getBandoLabel(data.status)}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Comunicazioni', 'gepafin')}</h2>
|
||||
<table className="myTable">
|
||||
<thead className="myThead">
|
||||
<tr>
|
||||
<th style={{ width: 250 }}>{__('Data', 'gepafin')}</th>
|
||||
<th>{__('Comunicazione', 'gepafin')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="myTbody">
|
||||
{!isNil(comms) && !isEmpty(comms)
|
||||
? comms.map((o, i) => <tr key={o.id}>
|
||||
<td valign="top">
|
||||
{getDateFromISOstring(o.commentedDate)}
|
||||
</td>
|
||||
<td>
|
||||
<h3>{o.title}</h3>
|
||||
<p>{o.comment}</p>
|
||||
</td>
|
||||
</tr>)
|
||||
: <tr>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Button
|
||||
style={{ marginTop: 30 }}
|
||||
onClick={openNewCommDialog}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
type="button"
|
||||
label={__('Aggiungi Comunicazione', 'gepafin')}
|
||||
icon="pi pi-plus" iconPos="right"/>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Documenti Ricevuti', 'gepafin')}</h2>
|
||||
|
||||
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
|
||||
{data.formFields
|
||||
? data.formFields.map((o, i) => {
|
||||
/*const thisField = head(test.updatedFormFields.filter(j => j.fieldId === o.fieldId));
|
||||
const value = pathOr({}, ['fieldValue'], thisField);
|
||||
console.log('value', value, o.fieldId);*/
|
||||
return <FormField
|
||||
key={o.fieldId}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
type="fileupload"
|
||||
setDataFn={setValue}
|
||||
fieldName={o.fieldId}
|
||||
label={o.label}
|
||||
control={control}
|
||||
errors={errors}
|
||||
defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []}
|
||||
accept={[]}
|
||||
doctype="document"
|
||||
register={register}
|
||||
sourceId={data.applicationId}
|
||||
source="application"
|
||||
multiple={true}
|
||||
/>
|
||||
}) : null}
|
||||
</form>
|
||||
|
||||
<Button
|
||||
style={{ marginTop: 30 }}
|
||||
type="button"
|
||||
disabled={data.status === 'CLOSE'}
|
||||
onClick={doUpdateAmendment}
|
||||
label={__('Aggiorna', 'gepafin')}/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection__hr">
|
||||
<span>{__('Azioni', 'gepafin')}</span>
|
||||
</div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={sendReminder}
|
||||
disabled={isLoadingReminding || data.status === 'CLOSE'}
|
||||
outlined
|
||||
label={__('Invia Sollecito', 'gepafin')}
|
||||
icon="pi pi-send"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={openExtendResponseTimeDialog}
|
||||
disabled={isLoadingExtendingTime || data.status === 'CLOSE'}
|
||||
outlined
|
||||
label={__('Estendi Scadenza', 'gepafin')}
|
||||
icon="pi pi-stopwatch"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={doCloseAmendment}
|
||||
disabled={isAsyncRequest || data.status === 'CLOSE'}
|
||||
label={__('Chiudi Soccorso Istruttorio', 'gepafin')}
|
||||
icon="pi pi-times" iconPos="right"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appForm__field" style={{ marginTop: '-40px' }}>
|
||||
<label>{__('Note Interne', 'gepafin')}</label>
|
||||
<div style={{position: 'relative'}}>
|
||||
<BlockingOverlay shouldDisplay={data.status === 'CLOSE'}/>
|
||||
<Editor
|
||||
value={data.internalNote}
|
||||
readOnly={data.status === 'CLOSE'}
|
||||
placeholder={__('Digita qui il messagio', 'gepafin')}
|
||||
headerTemplate={header}
|
||||
onTextChange={(e) => updateNewAmendmentData(
|
||||
e.htmlValue,
|
||||
'internalNote'
|
||||
)}
|
||||
style={{ height: 80 * 3, width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
visible={isVisibleNewCommDialog}
|
||||
modal
|
||||
header={headerNewComDialog}
|
||||
footer={footerNewComDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideNewComDialog}>
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newCommData.title) })}>
|
||||
{__('Titolo', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newCommData.title}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
invalid={isEmpty(newCommData.title)}
|
||||
onChange={(e) => updateNewCommData(e.target.value, 'title')}/>
|
||||
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newCommData.comment) })}>
|
||||
{__('Contenuto', 'gepafin')}*
|
||||
</label>
|
||||
<InputTextarea
|
||||
value={newCommData.comment}
|
||||
disabled={data.status === 'CLOSE'}
|
||||
rows={5} cols={30}
|
||||
invalid={isEmpty(newCommData.comment)}
|
||||
onChange={(e) => updateNewCommData(e.target.value, 'comment')}/>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<Dialog
|
||||
visible={isVisibleExtendTimeDialog}
|
||||
modal
|
||||
header={headerExtendRespDialog}
|
||||
footer={footerExtendRespDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideExtendRespDialog}>
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(extendedTime) })}>
|
||||
{__('Giorni', 'gepafin')}*
|
||||
</label>
|
||||
<InputNumber
|
||||
keyfilter="int"
|
||||
disabled={data.status === 'CLOSE'}
|
||||
value={extendedTime}
|
||||
showButtons
|
||||
onChange={(e) => setExtendedTime(e.value)}/>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default SoccorsoEditPreInstructor;
|
||||
@@ -0,0 +1,174 @@
|
||||
import React, { useState, useEffect} from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { storeGet } from '../../../../store';
|
||||
|
||||
// api
|
||||
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputIcon } from 'primereact/inputicon';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import AmendmentsService from '../../../../service/amendments-service';
|
||||
|
||||
|
||||
const PreInstructorSoccorsiTable = ({ openDialogFn }) => {
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const userData = storeGet.main.userData()
|
||||
setLocalAsyncRequest(true);
|
||||
AmendmentsService.getSoccorsoByPreInstructorId(userData.id, getCallback, errGetCallbacks);
|
||||
}, []);
|
||||
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setItems(getFormattedData(data.data));
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
setLocalAsyncRequest(false);
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
return data.map((d) => {
|
||||
d.startDate = is(String, d.startDate) ? new Date(d.startDate) : (d.startDate ? d.startDate : '');
|
||||
d.expirationDate = is(String, d.expirationDate) ? new Date(d.expirationDate) : (d.expirationDate ? d.expirationDate : '');
|
||||
return d;
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (value) => {
|
||||
return value.toLocaleDateString('it-IT', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
initFilters();
|
||||
};
|
||||
|
||||
const onGlobalFilterChange = (e) => {
|
||||
const value = e.target.value;
|
||||
let _filters = { ...filters };
|
||||
|
||||
_filters['global'].value = value;
|
||||
|
||||
setFilters(_filters);
|
||||
setGlobalFilterValue(value);
|
||||
};
|
||||
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
callName: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
beneficiaryName: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
startDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
expirationDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
}
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined onClick={clearFilter} />
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon className="pi pi-search" />
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} />
|
||||
</IconField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateStartBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.startDate);
|
||||
};
|
||||
|
||||
const dateExpirationBodyTemplate = (rowData) => {
|
||||
return formatDate(rowData.expirationDate);
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return <Link to={`/domande/${rowData.applicationId}/soccorso/${rowData.id}`}>
|
||||
<Button severity="info" label={__('Dettagli', 'gepafin')} size="small" />
|
||||
</Link>
|
||||
}
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
return(
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="applicationId" header={__('ID domanda', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '6rem' }}/>
|
||||
<Column field="callName" header={__('Bando', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column field="beneficiaryName" header={__('Beneficiario', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data Richiesta', 'gepafin')}
|
||||
filterField="startDate" dataType="date"
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateStartBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Scadenza', 'gepafin')}
|
||||
filterField="expirationDate" dataType="date"
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={dateExpirationBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
style={{ minWidth: '7rem' }} body={statusBodyTemplate} />
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PreInstructorSoccorsiTable;
|
||||
23
src/pages/SoccorsoIstruttorioPreInstructor/index.js
Normal file
23
src/pages/SoccorsoIstruttorioPreInstructor/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// components
|
||||
import PreInstructorSoccorsiTable from './components/PreInstructorSoccorsiTable';
|
||||
|
||||
const SoccorsoIstruttorioPreInstructor = () => {
|
||||
return(
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Soccorso Istruttorio', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<PreInstructorSoccorsiTable/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SoccorsoIstruttorioPreInstructor;
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useState, useEffect} from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import { uniq } from 'ramda';
|
||||
|
||||
// store
|
||||
import { storeSet, storeGet } from '../../../../store';
|
||||
import { useStore, storeSet } from '../../../../store';
|
||||
|
||||
// tools
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
@@ -11,7 +11,7 @@ import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../../../helpers/getDateFromISOstring';
|
||||
|
||||
// api
|
||||
import BandoService from '../../../../service/bando-service';
|
||||
import UserService from '../../../../service/user-service';
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
@@ -25,59 +25,37 @@ import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
|
||||
const AllUsersTable = () => {
|
||||
const [items, setItems] = useState(null);
|
||||
const users = useStore().main.users();
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
storeSet.main.setAsyncRequest();
|
||||
const sample = [
|
||||
{
|
||||
id: 11,
|
||||
name: 'Mario Rossi',
|
||||
email: 'mario.rossi@example.com',
|
||||
role: 'Beneficiario',
|
||||
status: 'active',
|
||||
last_access: '2024-08-01 10:30'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: 'Mario Rossi2',
|
||||
email: 'mario.rossi@example.com',
|
||||
role: 'Beneficiario',
|
||||
status: 'active',
|
||||
last_access: '2024-08-01 10:30'
|
||||
}
|
||||
];
|
||||
setItems(sample);
|
||||
//BandoService.getBandi(getCallback, errGetCallbacks);
|
||||
if (!loading) {
|
||||
setLoading(true);
|
||||
UserService.getUsers(getCallback, errGetCallbacks);
|
||||
}
|
||||
}, []);
|
||||
|
||||
/*const getCallback = (data) => {
|
||||
const getCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setItems(getFormattedBandiData(data.data));
|
||||
storeSet.main.users(getFormattedData(data.data));
|
||||
setStatuses(uniq(data.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
console.log('errGetCallbacks', data)
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}*/
|
||||
const errGetCallbacks = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
return data.map((d) => {
|
||||
d.last_access = is(String, d.last_access) ? new Date(d.last_access) : (d.last_access ? d.last_access : '');
|
||||
return d;
|
||||
});
|
||||
return data
|
||||
.filter(o => ['ROLE_SUPER_ADMIN', 'ROLE_PRE_INSTRUCTOR'].includes(o.role.roleType));
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
@@ -97,8 +75,14 @@ const AllUsersTable = () => {
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
|
||||
last_access: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
|
||||
name: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
lastLogin: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
status: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
@@ -107,21 +91,32 @@ const AllUsersTable = () => {
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined onClick={clearFilter} />
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined
|
||||
onClick={clearFilter}/>
|
||||
<IconField iconPosition="left">
|
||||
<InputIcon className="pi pi-search" />
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} />
|
||||
<InputIcon className="pi pi-search"/>
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange}
|
||||
placeholder={__('Cerca', 'gepafin')}/>
|
||||
</IconField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateLastAccessBodyTemplate = (rowData) => {
|
||||
return getDateFromISOstring(rowData.last_access);
|
||||
return getDateFromISOstring(rowData.lastLogin);
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999"/>;
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (rowData) => {
|
||||
return `${rowData.firstName} ${rowData.lastName}`;
|
||||
};
|
||||
|
||||
const roleBodyTemplate = (rowData) => {
|
||||
return rowData.role.roleName;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
@@ -129,43 +124,53 @@ const AllUsersTable = () => {
|
||||
};
|
||||
|
||||
const statusFilterTemplate = (options) => {
|
||||
return <Dropdown value={options.value} options={statuses} onChange={(e) => options.filterCallback(e.value, options.index)} itemTemplate={statusItemTemplate} placeholder="Select One" className="p-column-filter" showClear />;
|
||||
return <Dropdown value={options.value} options={statuses}
|
||||
onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
itemTemplate={statusItemTemplate} placeholder={__('Scegli uno', 'gepafin')}
|
||||
className="p-column-filter"
|
||||
showClear/>;
|
||||
};
|
||||
|
||||
const statusItemTemplate = (option) => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />;
|
||||
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>
|
||||
}
|
||||
/*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 header = renderHeader();
|
||||
|
||||
return(
|
||||
return (
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator showGridlines rows={10} loading={loading} dataKey="id"
|
||||
<DataTable value={users} paginator showGridlines rows={10} loading={loading} dataKey="id"
|
||||
filters={filters}
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="name" header={__('Nome utente', 'gepafin')} filter filterPlaceholder="Search by name"
|
||||
<Column body={nameBodyTemplate}
|
||||
header={__('Nome utente', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca per nome', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="email" header={__('Email', 'gepafin')} filter filterPlaceholder="Search by email"
|
||||
<Column field="email" header={__('Email', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca per email', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="role" header={__('Ruolo', 'gepafin')}
|
||||
<Column body={roleBodyTemplate} header={__('Ruolo', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate} filter
|
||||
filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Ultimo accesso', 'gepafin')} filterField="last_access" dataType="date"
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate}
|
||||
filter filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Ultimo accesso', 'gepafin')}
|
||||
filterField="lastLogin" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
body={dateLastAccessBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
{/*<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>*/}
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { isEmpty, isNil } from 'ramda';
|
||||
import { klona } from 'klona';
|
||||
|
||||
// store
|
||||
import { storeSet, storeGet } from '../../store';
|
||||
|
||||
// service
|
||||
import UserService from '../../service/user-service';
|
||||
|
||||
// tools
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import { isEmail } from '../../helpers/validators';
|
||||
|
||||
// components
|
||||
import AllUsersTable from './components/AllUsersTable';
|
||||
@@ -8,22 +19,25 @@ import { Button } from 'primereact/button';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import UserService from '../../service/user-service';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import { storeSet } from '../../store';
|
||||
import { klona } from 'klona';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
const APP_HUB_ID = process.env.REACT_APP_HUB_ID;
|
||||
|
||||
const Users = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isVisibleEditDialog, setIsVisibleEditDialog] = useState(false);
|
||||
const [newUserData, setNewUserData] = useState({
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
email: '',
|
||||
phoneNumber: '',
|
||||
role: ''
|
||||
password: '',
|
||||
confPassword: '',
|
||||
roleId: 0
|
||||
});
|
||||
const [roles, setRoles] = useState([]);
|
||||
const toast = useRef(null);
|
||||
|
||||
const onCreateNewUser = () => {
|
||||
setIsVisibleEditDialog(true);
|
||||
@@ -40,12 +54,52 @@ const Users = () => {
|
||||
lastName: '',
|
||||
email: '',
|
||||
phoneNumber: '',
|
||||
role: ''
|
||||
password: '',
|
||||
confPassword: '',
|
||||
roleId: 0
|
||||
});
|
||||
}
|
||||
|
||||
const saveEditDialog = () => {
|
||||
const emptyValues = Object.values(newUserData).filter(v => isEmpty(v));
|
||||
|
||||
if (isEmpty(emptyValues) && newUserData.password === newUserData.confPassword && !loading) {
|
||||
setLoading(true);
|
||||
const body = {
|
||||
...newUserData,
|
||||
hubUuid: APP_HUB_ID
|
||||
}
|
||||
|
||||
UserService.createUser(body, createUserCallback, errCreateUserCallback);
|
||||
}
|
||||
}
|
||||
|
||||
const createUserCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const users = storeGet.main.users();
|
||||
storeSet.main.users([data.data.user, ...users]);
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
}
|
||||
setLoading(false);
|
||||
hideEditDialog();
|
||||
}
|
||||
|
||||
const errCreateUserCallback = (data) => {
|
||||
setLoading(false);
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
summary: '',
|
||||
detail: data.message
|
||||
});
|
||||
}
|
||||
set404FromErrorResponse(data);
|
||||
}
|
||||
|
||||
const onChangeEditItem = (value, key) => {
|
||||
@@ -59,18 +113,20 @@ const Users = () => {
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideEditDialog} outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={isEmpty(newUserData)}
|
||||
disabled={isEmpty(newUserData) || loading}
|
||||
label={__('Salva', 'gepafin')} onClick={saveEditDialog}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const getRolesCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const roles = data.data.map(o => ({
|
||||
name: o.roleName,
|
||||
value: o.id
|
||||
}));
|
||||
setRoles(roles)
|
||||
const roles = data.data
|
||||
.filter(o => ['ROLE_SUPER_ADMIN', 'ROLE_PRE_INSTRUCTOR'].includes(o.roleType))
|
||||
.map(o => ({
|
||||
name: o.roleName,
|
||||
value: o.id
|
||||
}));
|
||||
setRoles(roles);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
@@ -80,19 +136,22 @@ const Users = () => {
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const isInvalidField = (data, key) => isEmpty(data[key]) || isNil(data[key])
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisibleEditDialog) {
|
||||
UserService.getRoles(getRolesCallback, errGetRolesCallback)
|
||||
}
|
||||
}, [isVisibleEditDialog]);
|
||||
|
||||
return(
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Gestione utenti', 'gepafin')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
<Toast ref={toast} />
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
@@ -101,7 +160,7 @@ const Users = () => {
|
||||
label={__('Crea nuovo')} icon="pi pi-plus" iconPos="right"/>
|
||||
</div>
|
||||
|
||||
<AllUsersTable doRefresh={true}/>
|
||||
<AllUsersTable/>
|
||||
|
||||
<Dialog
|
||||
visible={isVisibleEditDialog}
|
||||
@@ -113,38 +172,74 @@ const Users = () => {
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appForm__cols">
|
||||
<div className="appForm__field">
|
||||
<label className={classNames({ 'p-error': isEmpty(newUserData.firstName) || isNil(newUserData.firstName) })}>{__('Nome', 'gepafin')}*</label>
|
||||
<label
|
||||
className={classNames({ 'p-error': isInvalidField(newUserData, 'firstName') })}>
|
||||
{__('Nome', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newUserData.firstName}
|
||||
invalid={isEmpty(newUserData.firstName) || isNil(newUserData.firstName)}
|
||||
invalid={isInvalidField(newUserData, 'firstName')}
|
||||
onChange={(e) => onChangeEditItem(e.target.value, 'firstName')}/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label className={classNames({ 'p-error': isEmpty(newUserData.lastName) || isNil(newUserData.lastName) })}>{__('Cognome', 'gepafin')}*</label>
|
||||
<label
|
||||
className={classNames({ 'p-error': isInvalidField(newUserData, 'lastName') })}>
|
||||
{__('Cognome', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newUserData.lastName}
|
||||
invalid={isEmpty(newUserData.lastName) || isNil(newUserData.lastName)}
|
||||
invalid={isInvalidField(newUserData, 'lastName')}
|
||||
onChange={(e) => onChangeEditItem(e.target.value, 'lastName')}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="appForm__cols">
|
||||
<div className="appForm__field">
|
||||
<label className={classNames({ 'p-error': isEmpty(newUserData.email) || isNil(newUserData.email) })}>{__('Email', 'gepafin')}*</label>
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newUserData.email) || isNil(newUserData.email) || !isEmail(newUserData.email) })}>
|
||||
{__('Email', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newUserData.email}
|
||||
invalid={isEmpty(newUserData.email) || isNil(newUserData.email)}
|
||||
invalid={isEmpty(newUserData.email) || isNil(newUserData.email) || !isEmail(newUserData.email)}
|
||||
onChange={(e) => onChangeEditItem(e.target.value, 'email')}/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label className={classNames({ 'p-error': isEmpty(newUserData.phoneNumber) || isNil(newUserData.phoneNumber) })}>{__('Telefono', 'gepafin')}</label>
|
||||
<label
|
||||
className={classNames({ 'p-error': isInvalidField(newUserData, 'phoneNumber') })}>
|
||||
{__('Telefono', 'gepafin')}
|
||||
</label>
|
||||
<InputText value={newUserData.phoneNumber}
|
||||
invalid={isEmpty(newUserData.phoneNumber) || isNil(newUserData.phoneNumber)}
|
||||
keyfilter="int"
|
||||
invalid={isInvalidField(newUserData, 'phoneNumber')}
|
||||
onChange={(e) => onChangeEditItem(e.target.value, 'phoneNumber')}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="appForm__cols">
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newUserData.password) || isNil(newUserData.password) || newUserData.password !== newUserData.confPassword })}>
|
||||
{__('Password', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newUserData.password}
|
||||
invalid={isEmpty(newUserData.password) || isNil(newUserData.password) || newUserData.password !== newUserData.confPassword}
|
||||
onChange={(e) => onChangeEditItem(e.target.value, 'password')}/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newUserData.confPassword) || isNil(newUserData.confPassword) || newUserData.password !== newUserData.confPassword })}>
|
||||
{__('Conferma password', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newUserData.confPassword}
|
||||
invalid={isEmpty(newUserData.confPassword) || isNil(newUserData.confPassword) || newUserData.password !== newUserData.confPassword}
|
||||
onChange={(e) => onChangeEditItem(e.target.value, 'confPassword')}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label className={classNames({ 'p-error': isEmpty(newUserData.role) || isNil(newUserData.role) })}>{__('Ruolo', 'gepafin')}</label>
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newUserData.roleId) || isNil(newUserData.roleId) || newUserData.roleId === 0 })}>
|
||||
{__('Ruolo', 'gepafin')}*
|
||||
</label>
|
||||
<Dropdown
|
||||
value={newUserData.role}
|
||||
invalid={isEmpty(newUserData.role) || isNil(newUserData.role)}
|
||||
onChange={(e) => onChangeEditItem(e.value, 'role')}
|
||||
value={newUserData.roleId}
|
||||
invalid={isEmpty(newUserData.roleId) || isNil(newUserData.roleId) || newUserData.roleId === 0}
|
||||
onChange={(e) => onChangeEditItem(e.value, 'roleId')}
|
||||
options={roles}
|
||||
optionLabel="name"
|
||||
optionValue="value"/>
|
||||
|
||||
@@ -25,6 +25,16 @@ import ProfileCompany from './pages/ProfileCompany';
|
||||
import Users from './pages/Users';
|
||||
import AddCompany from './pages/AddCompany';
|
||||
import ResetPassword from './pages/ResetPassword';
|
||||
import DashboardPreInstructor from './pages/DashboardPreInstructor';
|
||||
import ProfileBeneficiario from './pages/ProfileBeneficiario';
|
||||
import Domande from './pages/Domande';
|
||||
import DomandePreInstructor from './pages/DomandePreInstructor';
|
||||
import DomandaEditPreInstructor from './pages/DomandaEditPreInstructor';
|
||||
import SoccorsoIstruttorioPreInstructor from './pages/SoccorsoIstruttorioPreInstructor';
|
||||
import SoccorsoEditPreInstructor from './pages/SoccorsoEditPreInstructor';
|
||||
import SoccorsoAddPreInstructor from './pages/SoccorsoAddPreInstructor';
|
||||
import DomandeBeneficiario from './pages/DomandeBeneficiario';
|
||||
import DomandaBeneficiario from './pages/DomandaBeneficiario';
|
||||
|
||||
const routes = ({ role, chosenCompanyId }) => {
|
||||
|
||||
@@ -34,62 +44,102 @@ const routes = ({ role, chosenCompanyId }) => {
|
||||
<Route path="/" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <Dashboard/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <DashboardBeneficiario/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <DashboardPreInstructor/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <Bandi/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <BandiBeneficiario/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoEdit/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <BandoViewBeneficiario/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/preview" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoView/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/preview-evaluation" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoView/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/forms" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoForms/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/forms/:formId" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoFormsEdit/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/forms/:formId/preview" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoFormsPreview/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/flow" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoFlowEdit/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/domande" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <Domande/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <DomandeBeneficiario/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <DomandePreInstructor/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/domande/:id/" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <DomandaBeneficiario/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <DomandaEditPreInstructor/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/domande/:id/aggiungi-soccorso" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <SoccorsoAddPreInstructor/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/domande/:id/soccorso/:amendmentId" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <SoccorsoEditPreInstructor/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/soccorso-istruttorio/" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <SoccorsoIstruttorioPreInstructor/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/imieibandi" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <Applications/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/imieibandi/:id/" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <BandoApplication/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/profilo" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <Profile/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <Profile/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <ProfileBeneficiario/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <Profile/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/profilo-aziendale" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role && chosenCompanyId > 0 ? <ProfileCompany/> : <PageNotFound/>}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/agguingi-azienda" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <AddCompany/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/utenti" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <Users/> : null}
|
||||
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
|
||||
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
|
||||
</DefaultLayout>}/>
|
||||
</Route>
|
||||
<Route exact path="/reset-password" element={<ResetPassword/>}/>
|
||||
|
||||
46
src/service/amendments-service.js
Normal file
46
src/service/amendments-service.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { NetworkService } from './network-service';
|
||||
|
||||
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||
|
||||
export default class AmendmentsService {
|
||||
|
||||
static getSoccorsoByApplEvalId = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/amendments/applicationEvaluation/${id}`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static getSoccorsoByApplId = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/amendments/application/${id}`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static getSoccorsoById = (callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/amendments`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static getSoccorsoByPreInstructorId = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/amendments/user/${id}`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static createSoccorso = (body, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${API_BASE_URL}/amendments`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static updateSoccorso = (id, body, callback, errCallback, queryParams) => {
|
||||
NetworkService.put(`${API_BASE_URL}/amendments/${id}`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static extendSoccorso = (id, days, callback, errCallback, queryParams) => {
|
||||
NetworkService.put(`${API_BASE_URL}/amendments/${id}/extendExpiration`, {}, callback, errCallback, [
|
||||
['extendedDays', days]
|
||||
]);
|
||||
};
|
||||
|
||||
static sendReminderForSoccorso = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${API_BASE_URL}/amendments/${id}/reminder`, {}, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static closeSoccorso = (id, body, callback, errCallback, queryParams) => {
|
||||
NetworkService.put(`${API_BASE_URL}/amendments`, body, callback, errCallback, [
|
||||
['id', id]
|
||||
]);
|
||||
};
|
||||
}
|
||||
14
src/service/application-evaluation-service.js
Normal file
14
src/service/application-evaluation-service.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NetworkService } from './network-service';
|
||||
|
||||
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||
|
||||
export default class ApplicationEvaluationService {
|
||||
|
||||
static getEvaluationByApplId = (callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/applicationEvaluation/application`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static updateEvaluation = (assignedApplicationId, body, callback, errCallback, queryParams) => {
|
||||
NetworkService.put(`${API_BASE_URL}/applicationEvaluation/${assignedApplicationId}`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
}
|
||||
14
src/service/assigned-application-service.js
Normal file
14
src/service/assigned-application-service.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NetworkService } from './network-service';
|
||||
|
||||
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||
|
||||
export default class AssignedApplicationService {
|
||||
|
||||
static getAssignedApplications = (callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/assignedApplication`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static assignApplication = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${API_BASE_URL}/assignedApplication/application/${id}`, {}, callback, errCallback, queryParams);
|
||||
};
|
||||
}
|
||||
14
src/service/communication-service.js
Normal file
14
src/service/communication-service.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NetworkService } from './network-service';
|
||||
|
||||
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||
|
||||
export default class CommunicationService {
|
||||
|
||||
static getCommsByAmendmentId = (id, callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/communication/${id}`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static createCommunication = (id, body, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${API_BASE_URL}/communication/${id}`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
}
|
||||
@@ -371,7 +371,8 @@ export class NetworkService {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + storeGet.main.getToken(),
|
||||
}
|
||||
},
|
||||
signal: AbortSignal.timeout(5000)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
|
||||
@@ -4,10 +4,18 @@ const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||
|
||||
export default class UserService {
|
||||
|
||||
static getUsers = (callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_BASE_URL}/user`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static updateUser = (id, body, callback, errCallback) => {
|
||||
NetworkService.put(`${API_BASE_URL}/user/${id}`, body, callback, errCallback);
|
||||
};
|
||||
|
||||
static createUser = (body, callback, errCallback) => {
|
||||
NetworkService.post(`${API_BASE_URL}/user`, body, callback, errCallback);
|
||||
};
|
||||
|
||||
static getRoles = (callback, errCallback) => {
|
||||
NetworkService.get(`${API_BASE_URL}/role`, callback, errCallback);
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ const initialStore = {
|
||||
token: '',
|
||||
companies: [],
|
||||
chosenCompanyId: 0,
|
||||
users: [],
|
||||
// bando form
|
||||
formInitialData: {},
|
||||
// form builder
|
||||
@@ -17,6 +18,7 @@ const initialStore = {
|
||||
elementItems: [],
|
||||
activeElement: '',
|
||||
draggingElementId: 0,
|
||||
bandoCriteria: [],
|
||||
// flow
|
||||
flowData: [],
|
||||
flowForms: [],
|
||||
|
||||
Reference in New Issue
Block a user