Merge pull request #9 from Kitzanos/master-sync/18-11-2024

Master sync/18 11 2024
This commit is contained in:
Vitalii Kiiko
2024-11-19 09:46:47 +01:00
committed by GitHub
34 changed files with 453 additions and 188 deletions

View File

@@ -147,6 +147,7 @@
.appForm__fileUploadItemName { .appForm__fileUploadItemName {
color: var(--global-textColor); color: var(--global-textColor);
font-style: italic; font-style: italic;
text-align: left;
} }
.appForm__row { .appForm__row {

View File

@@ -372,9 +372,13 @@
.appPageSection__tableActions { .appPageSection__tableActions {
display: flex; display: flex;
gap: 24px; gap: 10px;
padding: 0; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
&.lessGap {
gap: 12px;
}
} }
.appPageSection__addToFavourites { .appPageSection__addToFavourites {
@@ -385,12 +389,18 @@
justify-content: center; justify-content: center;
border-radius: 50%; border-radius: 50%;
border: none; border: none;
background-color: var(--message-info-color); background-color: transparent;
color: white; color: var(--global-textColor);
padding: 0; padding: 0;
&:hover { &:hover {
cursor: pointer; cursor: pointer;
color: var(--message-info-color);
}
&[data-active="true"] {
background-color: var(--message-info-color);
color: white;
} }
&[disabled] { &[disabled] {

View File

@@ -118,6 +118,10 @@
user-select: none; user-select: none;
} }
.p-dropdown-panel {
max-width: 100%;
}
.p-inputgroup.flex-1 { .p-inputgroup.flex-1 {
align-items: center; align-items: center;
} }

View File

@@ -28,18 +28,17 @@ const Datepicker = ({
control={control} control={control}
defaultValue={defaultValue} defaultValue={defaultValue}
rules={config} rules={config}
render={({ field, fieldState }) => ( render={({ field, fieldState }) => (<Calendar id={field.name}
<Calendar id={field.name} disabled={disabled}
disabled={disabled} value={is(String, field.value) ? new Date(field.value) : field.value}
value={is(Date, field.value) ? field.value : null} onChange={(e) => field.onChange(e.value)}
onChange={(e) => field.onChange(e.value)} dateFormat="dd/mm/yy"
dateFormat="dd/mm/yy" hourFormat="24"
hourFormat="24" timeOnly={timeOnly}
timeOnly={timeOnly} showIcon
showIcon minDate={minDate}
minDate={minDate} maxDate={maxDate}
maxDate={maxDate} className={classNames({ 'p-invalid': fieldState.invalid })}/>
className={classNames({ 'p-invalid': fieldState.invalid })}/>
)}/> )}/>
{infoText ? <small>{infoText}</small> : null} {infoText ? <small>{infoText}</small> : null}
</>) </>)

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { classNames } from 'primereact/utils'; import { classNames } from 'primereact/utils';
import { Controller } from 'react-hook-form'; import { Controller } from 'react-hook-form';
import { is } from 'ramda'; import { is, isEmpty } from 'ramda';
import { InputNumber } from 'primereact/inputnumber'; import { InputNumber } from 'primereact/inputnumber';
@@ -23,6 +23,8 @@ const NumberInput = ({
disabled = false, disabled = false,
useGrouping = true useGrouping = true
}) => { }) => {
const minAttr = config.min ? config.min : min;
const maxAttr = config.max ? config.max : max;
const input = <Controller const input = <Controller
name={fieldName} name={fieldName}
control={control} control={control}
@@ -33,8 +35,8 @@ const NumberInput = ({
disabled={disabled} disabled={disabled}
value={field.value} value={field.value}
onValueChange={(e) => field.onChange(e.value)} onValueChange={(e) => field.onChange(e.value)}
min={min} min={minAttr}
max={max} max={maxAttr}
locale={locale} locale={locale}
useGrouping={useGrouping} useGrouping={useGrouping}
maxFractionDigits={!isNaN(parseInt(maxFractionDigits)) ? parseInt(maxFractionDigits) : 0} maxFractionDigits={!isNaN(parseInt(maxFractionDigits)) ? parseInt(maxFractionDigits) : 0}
@@ -45,6 +47,8 @@ const NumberInput = ({
<> <>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}> <label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null} {label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
{!isEmpty(minAttr) ? <span>(min. {minAttr})</span> : null}
{!isEmpty(maxAttr) ? <span>(max. {maxAttr})</span> : null}
</label> </label>
{inputgroup {inputgroup
? <div className="p-inputgroup"> ? <div className="p-inputgroup">

View File

@@ -73,6 +73,7 @@ const FormFieldRepeater = ({
const properField = (item, i) => { const properField = (item, i) => {
return !isNil(item.lookUpDataId) return !isNil(item.lookUpDataId)
? <Dropdown value={item.value} ? <Dropdown value={item.value}
filter
disabled={disabled} disabled={disabled}
onChange={(e) => selectItem(e, i)} onChange={(e) => selectItem(e, i)}
optionDisabled={(opt) => usedExistingValues().includes(opt.value)} optionDisabled={(opt) => usedExistingValues().includes(opt.value)}

View File

@@ -79,6 +79,7 @@ const FormFieldRepeaterCriteria = ({
const properField = (item, i) => { const properField = (item, i) => {
return !isNil(item.lookUpDataId) return !isNil(item.lookUpDataId)
? <Dropdown value={item.value} ? <Dropdown value={item.value}
filter
disabled={disabled} disabled={disabled}
onChange={(e) => selectItem(e, i)} onChange={(e) => selectItem(e, i)}
optionDisabled={(opt) => usedExistingValues().includes(opt.value)} optionDisabled={(opt) => usedExistingValues().includes(opt.value)}

View File

@@ -182,6 +182,7 @@ const FormFieldRepeaterFaq = ({
disabled={disabled} disabled={disabled}
icon="pi pi-plus" onClick={addNewItem}/> icon="pi pi-plus" onClick={addNewItem}/>
<Dropdown onChange={(e) => selectItem(e)} <Dropdown onChange={(e) => selectItem(e)}
filter
disabled={disabled} disabled={disabled}
optionDisabled={(opt) => usedExistingValues().includes(opt.title)} optionDisabled={(opt) => usedExistingValues().includes(opt.title)}
options={stateOptionsData} options={stateOptionsData}

View File

@@ -78,6 +78,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
icon: 'pi pi-sign-out', icon: 'pi pi-sign-out',
command: () => { command: () => {
storeSet.main.doLogout(); storeSet.main.doLogout();
window.location.reload();
}, },
enable: true enable: true
} }

View File

@@ -26,6 +26,7 @@ const UnsavedChangesDetector = ({ getValuesFn }) => {
} }
formData = wrap(formData).insert(['dates'], starDate, 0).value(); formData = wrap(formData).insert(['dates'], starDate, 0).value();
delete formData.startDate;
} }
if (formData.endDate) { if (formData.endDate) {
let endDate; let endDate;
@@ -38,6 +39,7 @@ const UnsavedChangesDetector = ({ getValuesFn }) => {
} }
formData = wrap(formData).insert(['dates'], endDate, 1).value(); formData = wrap(formData).insert(['dates'], endDate, 1).value();
delete formData.endDate;
} }
if (!isNil(formData.startTime)) { if (!isNil(formData.startTime)) {
if (!is(String, formData.startTime)) { if (!is(String, formData.startTime)) {
@@ -54,7 +56,7 @@ const UnsavedChangesDetector = ({ getValuesFn }) => {
const initial = storeGet.main.formInitialData(); const initial = storeGet.main.formInitialData();
const isEqual = equal(initial, formData); const isEqual = equal(initial, formData);
// TODO // debug
/*console.log('isEqual', isEqual, /*console.log('isEqual', isEqual,
initial, formData, initial, formData,
diff(initial, formData))*/ diff(initial, formData))*/

View File

@@ -14,3 +14,32 @@ export const mimeTypes = [
]; ];
export const defaultMaxFileSize = 314572800; // 314572800 = 300 Mb export const defaultMaxFileSize = 314572800; // 314572800 = 300 Mb
const dynamicDataForTextinput = [
{ 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' }
]
export const dynamicDataOptions = {
datepicker: [
{ label: 'user dateOfBirth', value: 'user.dateOfBirth' }
],
textinput: dynamicDataForTextinput,
textarea: dynamicDataForTextinput
}

View File

@@ -2,14 +2,18 @@ import React, { useState, useEffect} from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { is, uniq, isNil, isEmpty } from 'ramda'; import { is, uniq, isNil, isEmpty } from 'ramda';
import { wrap } from 'object-path-immutable'; import { wrap } from 'object-path-immutable';
import { useNavigate } from 'react-router-dom';
// store // store
import { storeSet, useStore } from '../../../../store'; import { storeGet, storeSet, useStore } from '../../../../store';
// tools // tools
import getBandoSeverity from '../../../../helpers/getBandoSeverity'; import getBandoSeverity from '../../../../helpers/getBandoSeverity';
import getBandoLabel from '../../../../helpers/getBandoLabel'; import getBandoLabel from '../../../../helpers/getBandoLabel';
import getDateFromISOstring from '../../../../helpers/getDateFromISOstring'; import getDateFromISOstring from '../../../../helpers/getDateFromISOstring';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
import getNumberWithCurrency from '../../../../helpers/getNumberWithCurrency';
import renderHtmlContent from '../../../../helpers/renderHtmlContent';
// api // api
import BandoService from '../../../../service/bando-service'; import BandoService from '../../../../service/bando-service';
@@ -20,11 +24,8 @@ import { Column } from 'primereact/column';
import { Dropdown } from 'primereact/dropdown'; import { Dropdown } from 'primereact/dropdown';
import { Tag } from 'primereact/tag'; import { Tag } from 'primereact/tag';
import ProperBandoLabel from '../../../../components/ProperBandoLabel'; import ProperBandoLabel from '../../../../components/ProperBandoLabel';
import getNumberWithCurrency from '../../../../helpers/getNumberWithCurrency';
import renderHtmlContent from '../../../../helpers/renderHtmlContent';
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
import { useNavigate } from 'react-router-dom'; import PreferredBandoService from '../../../../service/preferred-bando-service';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
const AllBandiAccordion = () => { const AllBandiAccordion = () => {
@@ -38,8 +39,10 @@ const AllBandiAccordion = () => {
useEffect(() => { useEffect(() => {
storeSet.main.setAsyncRequest(); storeSet.main.setAsyncRequest();
BandoService.getBandi(getCallback, errGetCallbacks); BandoService.getBandi(getCallback, errGetCallbacks, [
}, []); ['companyId', chosenCompanyId]
]);
}, [chosenCompanyId]);
const getCallback = (data) => { const getCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
@@ -93,21 +96,68 @@ const AllBandiAccordion = () => {
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />; return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />;
}; };
/*const addToFavourites = () => { const addToFavourites = (id, preferredId) => {
console.log('addToFavourites'); const companyId = storeGet.main.chosenCompanyId()
}*/ const data = {
companyId,
callId: id
}
if (preferredId && preferredId !== 0) {
PreferredBandoService.deleteFromPreferred(preferredId, (data) => removeFavCallback(data, id), errToggleFavCallback);
} else {
PreferredBandoService.addToPreferred(data, addFavCallback, errToggleFavCallback);
}
}
const removeFavCallback = (data, id) => {
if (data.status === 'SUCCESS') {
const newItems = items.map((o) => {
if (o.id === id) {
return {
...o,
preferredCallId: null
}
} else {
return o;
}
});
setItems(newItems)
}
}
const addFavCallback = (data) => {
if (data.status === 'SUCCESS') {
const newItems = items.map((o) => {
if (o.id === data.data.callId) {
return {
...o,
preferredCallId: data.data.id
}
} else {
return o;
}
});
setItems(newItems)
}
}
const errToggleFavCallback = (data) => {
set404FromErrorResponse(data);
}
const goToBandoPage = (id) => { const goToBandoPage = (id) => {
navigate(`/bandi/${id}`) navigate(`/bandi/${id}`)
} }
/*const actionsBodyTemplate = (rowData) => { const actionsBodyTemplate = (rowData) => {
return <div className="appPageSection__tableActions"> return <div className="appPageSection__tableActions">
<button type="button" className="appPageSection__addToFavourites" onClick={addToFavourites} disabled={true}> <button type="button"
className="appPageSection__addToFavourites"
data-active={!isNil(rowData.preferredCallId)}
onClick={() => addToFavourites(rowData.id, rowData.preferredCallId)}>
<i className="pi pi-heart" style={{ fontSize: '1rem' }}></i> <i className="pi pi-heart" style={{ fontSize: '1rem' }}></i>
</button> </button>
</div> </div>
}*/ }
const rowExpansionTemplate = (data) => { const rowExpansionTemplate = (data) => {
return ( return (
@@ -150,10 +200,12 @@ const AllBandiAccordion = () => {
<Column header={__('Importo totale', 'gepafin')} filterField="amount" <Column header={__('Importo totale', 'gepafin')} filterField="amount"
style={{ minWidth: '10rem' }} body={amountBodyTemplate} sortable/> style={{ minWidth: '10rem' }} body={amountBodyTemplate} sortable/>
<Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }} <Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }}
style={{ width: '120px' }} body={statusBodyTemplate} filter sortable style={{ width: '8rem' }} body={statusBodyTemplate} filter sortable
filterElement={statusFilterTemplate}/> filterElement={statusFilterTemplate}/>
{/*<Column header={__('Azioni', 'gepafin')} {!isEmpty(chosenCompanyId) && chosenCompanyId !== 0
body={actionsBodyTemplate}/>*/} ? <Column header={__('Azioni', 'gepafin')}
style={{ width: '8rem' }}
body={actionsBodyTemplate}/> : null}
</DataTable> </DataTable>
</div> </div>
) )

View File

@@ -1,12 +1,13 @@
import React from 'react'; import React from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { Link, useNavigate } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { isEmpty } from 'ramda';
// store
import { useStore } from '../../store';
// components // components
import AllBandiAccordion from './components/AllBandiAccordion'; import AllBandiAccordion from './components/AllBandiAccordion';
import { Button } from 'primereact/button';
import { isEmpty } from 'ramda';
import { useStore } from '../../store';
const BandiBeneficiario = () => { const BandiBeneficiario = () => {
const chosenCompanyId = useStore().main.chosenCompanyId(); const chosenCompanyId = useStore().main.chosenCompanyId();

View File

@@ -5,27 +5,29 @@ import { isNil } from 'ramda';
// components // components
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
const BandoEditFormActions = ({ id, openPreview, openPreviewEvaluation, submitFn }) => { const BandoEditFormActions = ({ id, openPreview, submitFn, status }) => {
return ( return (
<div className="appPageSection"> <div className="appPageSection">
<div className="appPageSection__actions"> <div className="appPageSection__actions">
<Button <Button
type="button" type="button"
onClick={submitFn} onClick={submitFn}
label={__('Salva bozza', 'gepafin')} icon="pi pi-save" iconPos="right"/> label={status === 'PUBLISH'
? __('Modifica', 'gepafin')
: __('Salva bozza', 'gepafin')} icon="pi pi-save" iconPos="right"/>
<Button <Button
type="button" type="button"
disabled={isNil(id)} disabled={isNil(id)}
outlined outlined
onClick={openPreview} onClick={openPreview}
label={__('Anteprima beneficiario', 'gepafin')} icon="pi pi-eye" iconPos="right"/> label={__('Anteprima beneficiario', 'gepafin')} icon="pi pi-eye" iconPos="right"/>
<Button {/*<Button
type="button" type="button"
disabled={true} disabled={true}
outlined outlined
onClick={openPreviewEvaluation} onClick={openPreviewEvaluation}
label={__('Anteprima pre-istruttoria', 'gepafin')} icon="pi pi-eye" label={__('Anteprima pre-istruttoria', 'gepafin')} icon="pi pi-eye"
iconPos="right"/> iconPos="right"/>*/}
</div> </div>
</div> </div>
) )

View File

@@ -27,7 +27,7 @@ import { storeSet } from '../../../../store';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse'; import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
import getTimeParsedFromString from '../../../../helpers/getTimeParsedFromString'; import getTimeParsedFromString from '../../../../helpers/getTimeParsedFromString';
const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, status }, ref) { const BandoEditFormStep1 = forwardRef(function ({ initialData, setInitialData, getFormErrors, status }, ref) {
const navigate = useNavigate(); const navigate = useNavigate();
const [aimedToOptions, setAimedToOptions] = useState([]); const [aimedToOptions, setAimedToOptions] = useState([]);
const [faqOptions, setFaqOptions] = useState([]); const [faqOptions, setFaqOptions] = useState([]);
@@ -86,7 +86,6 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
formData.startTime = tzAwareDate.toISOString().substring(11, 16); formData.startTime = tzAwareDate.toISOString().substring(11, 16);
} }
} }
if (!isNil(formData.endTime)) { if (!isNil(formData.endTime)) {
if (!is(String, formData.endTime)) { if (!is(String, formData.endTime)) {
const tzAwareDate = new TZDate(formData.endTime, 'Europe/Berlin'); const tzAwareDate = new TZDate(formData.endTime, 'Europe/Berlin');
@@ -112,7 +111,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',
summary: '', summary: '',
detail: __('Il bando è stato aggiornato corretamente!', 'gepafin') detail: __('Il bando è stato aggiornato correttamente!', 'gepafin')
}); });
} }
const values = getValues(); const values = getValues();
@@ -120,6 +119,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
navigate(`/bandi/${data.data.id}`); navigate(`/bandi/${data.data.id}`);
} else { } else {
setFormInitialData(data.data); setFormInitialData(data.data);
setInitialData(data.data);
} }
} }
} }
@@ -176,8 +176,13 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
const shouldDisableField = () => { const shouldDisableField = (fieldName) => {
return values.status === 'PUBLISH' return values.status === 'PUBLISH' &&
![
'descriptionShort', 'descriptionLong', 'documentationRequested', 'threshold',
'aimedTo', 'criteria', 'docs', 'checklist', 'faq', 'amount', 'amountMin', 'amountMax',
'email', 'phoneNumber', 'checkList', 'images'
].includes(fieldName)
} }
useImperativeHandle( useImperativeHandle(
@@ -239,7 +244,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<UnsavedChangesDetector getValuesFn={getValues}/> <UnsavedChangesDetector getValuesFn={getValues}/>
<FormField <FormField
type="switch" type="switch"
disabled={shouldDisableField()} disabled={shouldDisableField('confidi')}
fieldName="confidi" fieldName="confidi"
label={__('Bando Confidi', 'gepafin')} label={__('Bando Confidi', 'gepafin')}
control={control} control={control}
@@ -251,7 +256,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="textinput" type="textinput"
disabled={shouldDisableField()} disabled={shouldDisableField('name')}
fieldName="name" fieldName="name"
label={__('Titolo del Bando', 'gepafin')} label={__('Titolo del Bando', 'gepafin')}
control={control} control={control}
@@ -262,7 +267,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="wysiwyg" type="wysiwyg"
disabled={shouldDisableField()} disabled={shouldDisableField('descriptionShort')}
fieldName="descriptionShort" fieldName="descriptionShort"
label={__('Descrizione breve', 'gepafin')} label={__('Descrizione breve', 'gepafin')}
control={control} control={control}
@@ -275,7 +280,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="wysiwyg" type="wysiwyg"
disabled={shouldDisableField()} disabled={shouldDisableField('descriptionLong')}
fieldName="descriptionLong" fieldName="descriptionLong"
label={__('Descrizione completa', 'gepafin')} label={__('Descrizione completa', 'gepafin')}
control={control} control={control}
@@ -291,7 +296,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormFieldRepeater <FormFieldRepeater
data={values['aimedTo']} data={values['aimedTo']}
disabled={shouldDisableField()} disabled={shouldDisableField('aimedTo')}
setDataFn={setValue} setDataFn={setValue}
fieldName="aimedTo" fieldName="aimedTo"
options={aimedToOptions} options={aimedToOptions}
@@ -310,7 +315,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="wysiwyg" type="wysiwyg"
disabled={shouldDisableField()} disabled={shouldDisableField('documentationRequested')}
fieldName="documentationRequested" fieldName="documentationRequested"
label={__('Documentazione richiesta', 'gepafin')} label={__('Documentazione richiesta', 'gepafin')}
control={control} control={control}
@@ -334,7 +339,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<div className="appForm__cols"> <div className="appForm__cols">
<FormField <FormField
type="datepicker" type="datepicker"
disabled={shouldDisableField()} disabled={shouldDisableField('startDate')}
fieldName="startDate" fieldName="startDate"
label={__('Data di inizio', 'gepafin')} label={__('Data di inizio', 'gepafin')}
control={control} control={control}
@@ -345,7 +350,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="datepicker" type="datepicker"
disabled={shouldDisableField()} disabled={shouldDisableField('endDate')}
fieldName="endDate" fieldName="endDate"
label={__('Data di fine', 'gepafin')} label={__('Data di fine', 'gepafin')}
control={control} control={control}
@@ -358,7 +363,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<div className="appForm__cols"> <div className="appForm__cols">
<FormField <FormField
type="datepicker" type="datepicker"
disabled={shouldDisableField()} disabled={shouldDisableField('startTime')}
fieldName="startTime" fieldName="startTime"
label={__('Ora di inizio', 'gepafin')} label={__('Ora di inizio', 'gepafin')}
control={control} control={control}
@@ -370,7 +375,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="datepicker" type="datepicker"
disabled={shouldDisableField()} disabled={shouldDisableField('endTime')}
fieldName="endTime" fieldName="endTime"
label={__('Ora di fine', 'gepafin')} label={__('Ora di fine', 'gepafin')}
control={control} control={control}
@@ -384,7 +389,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<div className="appForm__cols"> <div className="appForm__cols">
<FormField <FormField
type="numberinput" type="numberinput"
disabled={shouldDisableField()} disabled={shouldDisableField('amount')}
fieldName="amount" fieldName="amount"
label={__('Dotazione del Bando', 'gepafin')} label={__('Dotazione del Bando', 'gepafin')}
control={control} control={control}
@@ -397,7 +402,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="numberinput" type="numberinput"
disabled={shouldDisableField()} disabled={shouldDisableField('amountMin')}
fieldName="amountMin" fieldName="amountMin"
label={__('Importo minimo per Progetto', 'gepafin')} label={__('Importo minimo per Progetto', 'gepafin')}
control={control} control={control}
@@ -410,7 +415,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="numberinput" type="numberinput"
disabled={shouldDisableField()} disabled={shouldDisableField('amountMax')}
fieldName="amountMax" fieldName="amountMax"
label={__('Importo massimo per Progetto', 'gepafin')} label={__('Importo massimo per Progetto', 'gepafin')}
control={control} control={control}
@@ -425,7 +430,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<div className="appForm__cols"> <div className="appForm__cols">
<FormField <FormField
type="textinput" type="textinput"
disabled={shouldDisableField()} disabled={shouldDisableField('email')}
fieldName="email" fieldName="email"
label={__('Email', 'gepafin')} label={__('Email', 'gepafin')}
control={control} control={control}
@@ -441,7 +446,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="textinput" type="textinput"
disabled={shouldDisableField()} disabled={shouldDisableField('phoneNumber')}
fieldName="phoneNumber" fieldName="phoneNumber"
label={__('Telefono', 'gepafin')} label={__('Telefono', 'gepafin')}
control={control} control={control}
@@ -457,6 +462,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
<FormFieldRepeaterFaq <FormFieldRepeaterFaq
data={values['faq']} data={values['faq']}
disabled={shouldDisableField('faq')}
setDataFn={setValue} setDataFn={setValue}
fieldName="faq" fieldName="faq"
options={faqOptions} options={faqOptions}

View File

@@ -24,7 +24,7 @@ import getTimeParsedFromString from '../../../../helpers/getTimeParsedFromString
import { mimeTypes } from '../../../../configData'; import { mimeTypes } from '../../../../configData';
import { wrap } from 'object-path-immutable'; import { wrap } from 'object-path-immutable';
const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, status }, ref) { const BandoEditFormStep2 = forwardRef(function ({ initialData, setInitialData, getFormErrors, status }, ref) {
const navigate = useNavigate(); const navigate = useNavigate();
const [criteriaOptions, setCriteriaOptions] = useState([]); const [criteriaOptions, setCriteriaOptions] = useState([]);
const [checklistOptions, setChecklistOptions] = useState([]); const [checklistOptions, setChecklistOptions] = useState([]);
@@ -104,11 +104,11 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',
summary: '', summary: '',
detail: __('Il bando è stato aggiornato corretamente!', 'gepafin') detail: __('Il bando è stato aggiornato correttamente!', 'gepafin')
}); });
const newFormData = {...formInitialData, ...data.data}; const newFormData = {...formInitialData, ...data.data};
setFormInitialData(newFormData); setFormInitialData(newFormData);
storeSet.main.formInitialData(newFormData); setInitialData(newFormData);
} }
} }
@@ -206,8 +206,13 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
} }
}, []); }, []);
const shouldDisableField = () => { const shouldDisableField = (fieldName) => {
return values.status === 'PUBLISH' return values.status === 'PUBLISH' &&
![
'descriptionShort', 'descriptionLong', 'documentationRequested', 'threshold',
'aimedTo', 'criteria', 'docs', 'checklist', 'faq', 'amount', 'amountMin', 'amountMax',
'email', 'phoneNumber', 'checkList', 'images'
].includes(fieldName)
} }
const acceptAllFormats = () => { const acceptAllFormats = () => {
@@ -219,7 +224,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
<UnsavedChangesDetector getValuesFn={getValues}/> <UnsavedChangesDetector getValuesFn={getValues}/>
<FormFieldRepeaterCriteria <FormFieldRepeaterCriteria
data={values} data={values}
disabled={shouldDisableField()} disabled={shouldDisableField('criteria')}
setDataFn={setValue} setDataFn={setValue}
fieldName="criteria" fieldName="criteria"
options={criteriaOptions} options={criteriaOptions}
@@ -238,7 +243,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="fileuploadasync" type="fileuploadasync"
disabled={shouldDisableField()} disabled={shouldDisableField('docs')}
setDataFn={setValue} setDataFn={setValue}
fieldName="docs" fieldName="docs"
label={__('Documentazione', 'gepafin')} label={__('Documentazione', 'gepafin')}
@@ -257,7 +262,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
<FormField <FormField
type="fileuploadasync" type="fileuploadasync"
disabled={shouldDisableField()} disabled={shouldDisableField('images')}
setDataFn={setValue} setDataFn={setValue}
fieldName="images" fieldName="images"
label={__('Immagine del Bando', 'gepafin')} label={__('Immagine del Bando', 'gepafin')}
@@ -273,7 +278,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
<FormFieldRepeater <FormFieldRepeater
data={values['checkList']} data={values['checkList']}
disabled={shouldDisableField()} disabled={shouldDisableField('checkList')}
setDataFn={setValue} setDataFn={setValue}
fieldName="checkList" fieldName="checkList"
options={checklistOptions} options={checklistOptions}

View File

@@ -288,9 +288,11 @@ const BandoEdit = () => {
{!isEmpty(data) {!isEmpty(data)
? <> ? <>
{activeStep === 0 {activeStep === 0
? <BandoEditFormStep1 initialData={data} ref={formRef} status={data.status}/> : null} ? <BandoEditFormStep1 initialData={data} setInitialData={setData} ref={formRef} status={data.status}/>
: null}
{activeStep === 1 {activeStep === 1
? <BandoEditFormStep2 initialData={data} ref={formRef} status={data.status}/> : null} ? <BandoEditFormStep2 initialData={data} setInitialData={setData} ref={formRef} status={data.status}/>
: null}
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Crea o modifica il Form compilabile dal Beneficiario', 'gepafin')}</h2> <h2>{__('Crea o modifica il Form compilabile dal Beneficiario', 'gepafin')}</h2>

View File

@@ -112,7 +112,7 @@ const BandoFlowEdit = () => {
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',
summary: '', summary: '',
detail: __('Il flusso è stato aggiornato corretamente!', 'gepafin') detail: __('Il flusso è stato aggiornato correttamente!', 'gepafin')
}); });
} }
} }

View File

@@ -91,7 +91,7 @@ const BandoForms = () => {
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',
summary: '', summary: '',
detail: __('Il form è stato aggiornato corretamente!', 'gepafin') detail: __('Il form è stato aggiornato correttamente!', 'gepafin')
}); });
} }
@@ -235,7 +235,7 @@ const BandoForms = () => {
outlined outlined
disabled={!selectedForm} disabled={!selectedForm}
onClick={goToEditForm} onClick={goToEditForm}
label={'PUBLISH' === bandoStatus ? __('Mostra', 'gepafin') : __('Modifica', 'gepafin')} label={__('Modifica', 'gepafin')}
icon="pi pi-cog" iconPos="right"/> icon="pi pi-cog" iconPos="right"/>
</div> </div>
</div> </div>

View File

@@ -11,7 +11,7 @@ import { Button } from 'primereact/button';
import { Tag } from 'primereact/tag'; import { Tag } from 'primereact/tag';
import BuilderElementProperLabel from '../BuilderElementProperLabel'; import BuilderElementProperLabel from '../BuilderElementProperLabel';
const BuilderElement = ({ id, name, label, index }) => { const BuilderElement = ({ id, name, label, index, bandoStatus }) => {
const draggingElementId = useStore().main.draggingElementId(); const draggingElementId = useStore().main.draggingElementId();
const ref = useRef(null); const ref = useRef(null);
@@ -109,28 +109,10 @@ const BuilderElement = ({ id, name, label, index }) => {
</div> </div>
<div className="actions"> <div className="actions">
<Button icon="pi pi-cog" onClick={() => openSettings(id)} outlined severity="info"/> <Button icon="pi pi-cog" onClick={() => openSettings(id)} outlined severity="info"/>
<Button icon="pi pi-trash" onClick={() => remove(id)} outlined severity="danger"/> <Button icon="pi pi-trash" disabled={bandoStatus === 'PUBLISH'} onClick={() => remove(id)} outlined severity="danger"/>
</div> </div>
</div> </div>
) )
/*return (
<div ref={ref} className="formBuilder__element" style={{ opacity }} data-handler-id={handlerId}>
{draggingId === id
? <div className="formBuilder__elementNew"></div>
: <>
<div className="meta">
<Tag value={name} severity="info"/>
<BuilderElementProperLabel id={id} defaultLabel={label}/>
</div>
<div className="actions">
<Button icon="pi pi-cog" onClick={() => openSettings(id)} outlined severity="info"/>
<Button icon="pi pi-trash" onClick={() => remove(id)} outlined severity="danger"/>
</div>
</>
}
</div>
)*/
} }
export default BuilderElement; export default BuilderElement;

View File

@@ -11,7 +11,7 @@ import { Editor } from 'primereact/editor';
import { mimeTypes } from '../../../../../../configData'; import { mimeTypes } from '../../../../../../configData';
import ElementSettingTableColumns from '../ElementSettingTableColumns'; import ElementSettingTableColumns from '../ElementSettingTableColumns';
const ElementSetting = ({ setting, changeFn, updateDataFn }) => { const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
const settingLabels = { const settingLabels = {
label: __('Label', 'gepafin'), label: __('Label', 'gepafin'),
@@ -48,6 +48,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
return <ElementSettingRepeater return <ElementSettingRepeater
value={is(Array, setting.value) ? setting.value : []} value={is(Array, setting.value) ? setting.value : []}
name={setting.name} name={setting.name}
bandoStatus={bandoStatus}
setDataFn={updateDataFn}/> setDataFn={updateDataFn}/>
} else if (setting.name === 'mime') { } else if (setting.name === 'mime') {
return <MultiSelect return <MultiSelect
@@ -75,6 +76,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
return <ElementSettingTableColumns return <ElementSettingTableColumns
value={is(Object, setting.value) ? setting.value : {}} value={is(Object, setting.value) ? setting.value : {}}
name={setting.name} name={setting.name}
bandoStatus={bandoStatus}
setDataFn={updateDataFn}/> setDataFn={updateDataFn}/>
} else { } else {
return <InputText id={setting.name} aria-describedby={`${setting.name}-help`} return <InputText id={setting.name} aria-describedby={`${setting.name}-help`}

View File

@@ -11,7 +11,8 @@ import uniqid from '../../../../../../helpers/uniqid';
const ElementSettingRepeater = ({ const ElementSettingRepeater = ({
value, value,
name, name,
setDataFn setDataFn,
bandoStatus
}) => { }) => {
const [stateFieldData, setStateFieldData] = useState([]); const [stateFieldData, setStateFieldData] = useState([]);
@@ -53,10 +54,10 @@ const ElementSettingRepeater = ({
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem"> {stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
<div className="p-inputgroup flex-1"> <div className="p-inputgroup flex-1">
{properField(o, i)} {properField(o, i)}
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/> <Button icon="pi pi-times" disabled={bandoStatus === 'PUBLISH'} className="p-button-danger" onClick={() => removeItem(i)}/>
</div> </div>
</div>)} </div>)}
<Button type="button" outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/> <Button type="button" disabled={bandoStatus === 'PUBLISH'} outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/>
</div> </div>
) )
} }

View File

@@ -14,7 +14,8 @@ import uniqid from '../../../../../../helpers/uniqid';
const ElementSettingTableColumns = ({ const ElementSettingTableColumns = ({
value, value,
name, name,
setDataFn setDataFn,
bandoStatus
}) => { }) => {
const [stateFieldData, setStateFieldData] = useState([]); const [stateFieldData, setStateFieldData] = useState([]);
const [rowsData, setRowsData] = useState([]); const [rowsData, setRowsData] = useState([]);
@@ -34,7 +35,7 @@ const ElementSettingTableColumns = ({
.reduce((acc, cur) => { .reduce((acc, cur) => {
acc[cur.name] = '' acc[cur.name] = ''
return acc; return acc;
}, {}); }, {});
setRowsData([...rowsData, obj]); setRowsData([...rowsData, obj]);
} }
@@ -87,7 +88,10 @@ const ElementSettingTableColumns = ({
<InputText value={item.label} onInput={(e) => onInputChange(e, i)}/> <InputText value={item.label} onInput={(e) => onInputChange(e, i)}/>
<div className="flex-1"> <div className="flex-1">
<span>{__('Predefinito?', 'gepafin')}</span> <span>{__('Predefinito?', 'gepafin')}</span>
<InputSwitch checked={item.predefined} onChange={(e) => setChecked(e.value, i)}/> <InputSwitch
checked={item.predefined}
disabled={bandoStatus === 'PUBLISH'}
onChange={(e) => setChecked(e.value, i)}/>
</div> </div>
</> </>
} }
@@ -118,10 +122,10 @@ const ElementSettingTableColumns = ({
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem"> {stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
<div className="p-inputgroup flex-1"> <div className="p-inputgroup flex-1">
{properField(o, i)} {properField(o, i)}
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/> <Button icon="pi pi-times" disabled={bandoStatus === 'PUBLISH'} className="p-button-danger" onClick={() => removeItem(i)}/>
</div> </div>
</div>)} </div>)}
<Button type="button" outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/> <Button type="button" disabled={bandoStatus === 'PUBLISH'} outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/>
</div> </div>
{stateFieldData {stateFieldData
.filter(o => o.predefined) .filter(o => o.predefined)
@@ -133,12 +137,16 @@ const ElementSettingTableColumns = ({
return <div key={k} className="formElementSettings__repeaterItem"> return <div key={k} className="formElementSettings__repeaterItem">
<div className="p-inputgroup flex-1"> <div className="p-inputgroup flex-1">
{properSubField(c, k, o.name)} {properSubField(c, k, o.name)}
<Button icon="pi pi-times" className="p-button-danger" <Button icon="pi pi-times"
disabled={bandoStatus === 'PUBLISH'}
className="p-button-danger"
onClick={() => removeRow(k)}/> onClick={() => removeRow(k)}/>
</div> </div>
</div> </div>
})} })}
<Button type="button" outlined <Button type="button"
outlined
disabled={bandoStatus === 'PUBLISH'}
label={__('Aggiungi una righa', 'gepafin')} label={__('Aggiungi una righa', 'gepafin')}
onClick={addNewRow}/> onClick={addNewRow}/>
</div> </div>

View File

@@ -16,8 +16,9 @@ import { InputSwitch } from 'primereact/inputswitch';
import ElementSetting from './components/ElementSetting'; import ElementSetting from './components/ElementSetting';
import { Dropdown } from 'primereact/dropdown'; import { Dropdown } from 'primereact/dropdown';
import { MultiSelect } from 'primereact/multiselect'; import { MultiSelect } from 'primereact/multiselect';
import { dynamicDataOptions } from '../../../../configData';
const BuilderElementSettings = ({ closeSettingsFn }) => { const BuilderElementSettings = ({ closeSettingsFn, bandoStatus }) => {
const elements = useStore().main.formElements(); const elements = useStore().main.formElements();
const activeElement = useStore().main.activeElement(); const activeElement = useStore().main.activeElement();
const criteriaOptions = useStore().main.bandoCriteria(); const criteriaOptions = useStore().main.bandoCriteria();
@@ -162,10 +163,11 @@ const BuilderElementSettings = ({ closeSettingsFn }) => {
? settings.map((o) => <ElementSetting ? settings.map((o) => <ElementSetting
key={o.name} key={o.name}
setting={o} setting={o}
bandoStatus={bandoStatus}
changeFn={onChange} changeFn={onChange}
updateDataFn={onUpdateOptions}/>) updateDataFn={onUpdateOptions}/>)
: null} : null}
{['textinput', 'datepicker'].includes(activeElementData.name) {!isNil(dynamicDataOptions[activeElementData.name])
? <div className="formElementSettings__field"> ? <div className="formElementSettings__field">
<label htmlFor="dynamicData">{__('Dati dinamici', 'gepafin')}</label> <label htmlFor="dynamicData">{__('Dati dinamici', 'gepafin')}</label>
<Dropdown <Dropdown

View File

@@ -13,7 +13,7 @@ import BuilderElementSettings from '../BuilderElementSettings';
import BuilderDropzone from '../BuilderDropzone'; import BuilderDropzone from '../BuilderDropzone';
import BlockingOverlay from '../../../../components/BlockingOverlay'; import BlockingOverlay from '../../../../components/BlockingOverlay';
const FormBuilder = () => { const FormBuilder = ({ bandoStatus }) => {
const elements = useStore().main.formElements(); const elements = useStore().main.formElements();
const elementItems = useStore().main.elementItems(); const elementItems = useStore().main.elementItems();
const activeElement = useStore().main.activeElement(); const activeElement = useStore().main.activeElement();
@@ -27,9 +27,10 @@ const FormBuilder = () => {
id={field.id} id={field.id}
label={field.label} label={field.label}
name={field.name} name={field.name}
bandoStatus={bandoStatus}
/> />
) )
}, []); }, [bandoStatus]);
const renderItem = useCallback((item) => { const renderItem = useCallback((item) => {
return ( return (
@@ -57,7 +58,7 @@ const FormBuilder = () => {
<> <>
<Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} className="formBuilder__elementSettings"> <Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} className="formBuilder__elementSettings">
<h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2> <h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2>
{!isEmpty(activeElement) ? <BuilderElementSettings closeSettingsFn={closeSettings}/> : null} {!isEmpty(activeElement) ? <BuilderElementSettings closeSettingsFn={closeSettings} bandoStatus={bandoStatus}/> : null}
</Sidebar> </Sidebar>
<div className="formBuilder"> <div className="formBuilder">
<div className="formBuilder__main"> <div className="formBuilder__main">

View File

@@ -123,7 +123,7 @@ const BandoFormsEdit = () => {
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',
summary: '', summary: '',
detail: __('Il form è stato aggiornato corretamente!', 'gepafin') detail: __('Il form è stato aggiornato correttamente!', 'gepafin')
}); });
} }
} }
@@ -210,7 +210,6 @@ const BandoFormsEdit = () => {
} }
const errFormDeleteCallback = (data) => { const errFormDeleteCallback = (data) => {
console.log('errFormDeleteCallback', data)
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
@@ -223,7 +222,6 @@ const BandoFormsEdit = () => {
} }
const errGetElementItemsCallbacks = (data) => { const errGetElementItemsCallbacks = (data) => {
console.log('errGetElementItemsCallbacks', data)
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
@@ -246,9 +244,9 @@ const BandoFormsEdit = () => {
const getBandoCallback = (data) => { const getBandoCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
setBandoStatus(data.data.status);
const criteria = pathOr([], ['data', 'criteria'], data); const criteria = pathOr([], ['data', 'criteria'], data);
const criteriaOptions = criteria.map(o => ({value: o.id, label: o.value})); const criteriaOptions = criteria.map(o => ({value: o.id, label: o.value}));
console.log('criteriaOptions', criteriaOptions);
storeSet.main.bandoCriteria(criteriaOptions); storeSet.main.bandoCriteria(criteriaOptions);
} }
} }
@@ -319,7 +317,7 @@ const BandoFormsEdit = () => {
<div className="appPageSection"> <div className="appPageSection">
<DndProvider backend={HTML5Backend}> <DndProvider backend={HTML5Backend}>
<FormBuilder/> <FormBuilder bandoStatus={bandoStatus}/>
</DndProvider> </DndProvider>
</div> </div>
@@ -334,7 +332,7 @@ const BandoFormsEdit = () => {
label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/> label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/>
<Button <Button
onClick={() => doSave()} onClick={() => doSave()}
disabled={isAsyncRequest || 'PUBLISH' === bandoStatus} disabled={isAsyncRequest}
label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/> label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/>
<Button <Button
outlined outlined

View File

@@ -5,7 +5,7 @@ import { is, isEmpty, isNil } from 'ramda';
import "quill/dist/quill.core.css"; import "quill/dist/quill.core.css";
// store // store
import { storeSet, useStore } from '../../store'; import { storeGet, storeSet, useStore } from '../../store';
// tools // tools
import getNumberWithCurrency from '../../helpers/getNumberWithCurrency'; import getNumberWithCurrency from '../../helpers/getNumberWithCurrency';
@@ -28,6 +28,7 @@ import { Message } from 'primereact/message';
import { Toast } from 'primereact/toast'; import { Toast } from 'primereact/toast';
import { Editor } from 'primereact/editor'; import { Editor } from 'primereact/editor';
import { Dialog } from 'primereact/dialog'; import { Dialog } from 'primereact/dialog';
import PreferredBandoService from '../../service/preferred-bando-service';
const BandoViewBeneficiario = () => { const BandoViewBeneficiario = () => {
const isAsyncRequest = useStore().main.isAsyncRequest(); const isAsyncRequest = useStore().main.isAsyncRequest();
@@ -246,14 +247,55 @@ const BandoViewBeneficiario = () => {
const header = renderHeader(); const header = renderHeader();
useEffect(() => { const addToFavourites = () => {
const companyId = storeGet.main.chosenCompanyId();
const bandoId = getBandoId(); const bandoId = getBandoId();
storeSet.main.setAsyncRequest(); const formdData = {
BandoService.getBando(bandoId, getBandoCallback, errGetBandoCallback); companyId,
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [ callId: bandoId
['callId', bandoId], }
['companyId', chosenCompanyId]
]) if (data.preferredCallId && data.preferredCallId !== 0) {
PreferredBandoService.deleteFromPreferred(data.preferredCallId, removeFavCallback, errToggleFavCallback);
} else {
PreferredBandoService.addToPreferred(formdData, addFavCallback, errToggleFavCallback);
}
}
const removeFavCallback = (resp) => {
if (resp.status === 'SUCCESS') {
const newData = {
...data,
preferredCallId: null
}
setData(newData);
}
}
const addFavCallback = (resp) => {
if (resp.status === 'SUCCESS') {
const newData = {
...data,
preferredCallId: resp.data.id
}
setData(newData);
}
}
const errToggleFavCallback = (data) => {
set404FromErrorResponse(data);
}
useEffect(() => {
if (!isEmpty(chosenCompanyId) && chosenCompanyId !== 0) {
const bandoId = getBandoId();
storeSet.main.setAsyncRequest();
BandoService.getBando(bandoId, getBandoCallback, errGetBandoCallback, [
['companyId', chosenCompanyId]
]);
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [
['callId', bandoId],
['companyId', chosenCompanyId]
]);
}
}, [id, chosenCompanyId]); }, [id, chosenCompanyId]);
return ( return (
@@ -443,14 +485,15 @@ const BandoViewBeneficiario = () => {
onClick={submitApplication} onClick={submitApplication}
label={submitBtnLabel()} label={submitBtnLabel()}
icon={submitBtnIcon()} iconPos="right"/> icon={submitBtnIcon()} iconPos="right"/>
{/*<Button <Button
type="button" type="button"
outlined outlined={isNil(data.preferredCallId)}
rounded rounded
disabled={true} onClick={addToFavourites}
onClick={saveToFavourites} label={isNil(data.preferredCallId)
label={__('Aggiungi a preferiti', 'gepafin')} ? __('Aggiungi a preferiti', 'gepafin')
icon="pi pi-heart" iconPos="left"/>*/} : __('Rimuovi dai preferiti', 'gepafin')}
icon="pi pi-heart" iconPos="left"/>
</div> </div>
</div> </div>

View File

@@ -1,10 +1,10 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { uniq, isEmpty } from 'ramda'; import { uniq, isEmpty, isNil } from 'ramda';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
// store // store
import { storeSet, useStore } from '../../../../store'; import { storeGet, useStore } from '../../../../store';
// api // api
import BandoService from '../../../../service/bando-service'; import BandoService from '../../../../service/bando-service';
@@ -19,6 +19,8 @@ import { InputIcon } from 'primereact/inputicon';
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
import { Calendar } from 'primereact/calendar'; import { Calendar } from 'primereact/calendar';
import ProperBandoLabel from '../../../../components/ProperBandoLabel'; import ProperBandoLabel from '../../../../components/ProperBandoLabel';
import PreferredBandoService from '../../../../service/preferred-bando-service';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
const LatestBandiTable = () => { const LatestBandiTable = () => {
@@ -30,9 +32,11 @@ const LatestBandiTable = () => {
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
storeSet.main.setAsyncRequest(); setLoading(true);
BandoService.getBandi(getCallback, errGetCallbacks); BandoService.getBandi(getCallback, errGetCallbacks, [
}, []); ['companyId', chosenCompanyId]
]);
}, [chosenCompanyId]);
const getCallback = (data) => { const getCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
@@ -41,12 +45,64 @@ const LatestBandiTable = () => {
setStatuses(uniq(data.data.map(o => o.status))) setStatuses(uniq(data.data.map(o => o.status)))
initFilters(); initFilters();
} }
storeSet.main.unsetAsyncRequest(); setLoading(false);
} }
const errGetCallbacks = (data) => { const errGetCallbacks = (data) => {
console.log('errGetCallbacks', data) set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest(); setLoading(false);
}
const addToFavourites = (id, preferredId) => {
const companyId = storeGet.main.chosenCompanyId()
const data = {
companyId,
callId: id
}
setLoading(true);
if (preferredId && preferredId !== 0) {
PreferredBandoService.deleteFromPreferred(preferredId, (data) => removeFavCallback(data, id), errToggleFavCallback);
} else {
PreferredBandoService.addToPreferred(data, addFavCallback, errToggleFavCallback);
}
}
const removeFavCallback = (data, id) => {
if (data.status === 'SUCCESS') {
const newItems = items.map((o) => {
if (o.id === id) {
return {
...o,
preferredCallId: null
}
} else {
return o;
}
});
setItems(newItems)
}
setLoading(false);
}
const addFavCallback = (data) => {
if (data.status === 'SUCCESS') {
const newItems = items.map((o) => {
if (o.id === data.data.callId) {
return {
...o,
preferredCallId: data.data.id
}
} else {
return o;
}
});
setItems(newItems)
}
setLoading(false);
}
const errToggleFavCallback = (data) => {
set404FromErrorResponse(data);
setLoading(false);
} }
const getFormattedData = (data) => { const getFormattedData = (data) => {
@@ -83,9 +139,18 @@ const LatestBandiTable = () => {
const initFilters = () => { const initFilters = () => {
setFilters({ setFilters({
global: { value: null, matchMode: FilterMatchMode.CONTAINS }, global: { value: null, matchMode: FilterMatchMode.CONTAINS },
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] }, name: {
start_date: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] }, operator: FilterOperator.AND,
end_date: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] }, 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 }] } status: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }
}); });
setGlobalFilterValue(''); setGlobalFilterValue('');
@@ -94,10 +159,12 @@ const LatestBandiTable = () => {
const renderHeader = () => { const renderHeader = () => {
return ( return (
<div className="appTableHeader"> <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"> <IconField iconPosition="left">
<InputIcon className="pi pi-search" /> <InputIcon className="pi pi-search"/>
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} /> <InputText value={globalFilterValue} onChange={onGlobalFilterChange}
placeholder={__('Cerca', 'gepafin')}/>
</IconField> </IconField>
</div> </div>
); );
@@ -112,7 +179,8 @@ const LatestBandiTable = () => {
}; };
const dateFilterTemplate = (options) => { 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 statusBodyTemplate = (rowData) => { const statusBodyTemplate = (rowData) => {
@@ -120,10 +188,17 @@ const LatestBandiTable = () => {
}; };
const actionsBodyTemplate = (rowData) => { const actionsBodyTemplate = (rowData) => {
return <Link to={`/bandi/${rowData.id}`}> return <div className="appPageSection__tableActions">
<Button severity="info" label={__('Partecipa', 'gepafin')} icon="pi pi-arrow-right" size="small" <button type="button"
iconPos="right"/> className="appPageSection__addToFavourites"
</Link> data-active={!isNil(rowData.preferredCallId)}
onClick={() => addToFavourites(rowData.id, rowData.preferredCallId)}>
<i className="pi pi-heart" style={{ fontSize: '1rem' }}></i>
</button>
<Link to={`/bandi/${rowData.id}`}>
<Button severity="info" label={__('Partecipa', 'gepafin')} icon="pi pi-arrow-right" size="small"
iconPos="right"/>
</Link></div>
} }
const header = renderHeader(); const header = renderHeader();
@@ -136,7 +211,8 @@ const LatestBandiTable = () => {
header={header} header={header}
emptyMessage={__('Nessun dato disponibile', 'gepafin')} emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}> onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')} <Column field="name" header={__('Nome Bando', 'gepafin')} filter
filterPlaceholder={__('Cerca il nome', 'gepafin')}
style={{ minWidth: '8rem' }}/> style={{ minWidth: '8rem' }}/>
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date" <Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
style={{ minWidth: '8rem' }} style={{ minWidth: '8rem' }}

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { uniq, is } from 'ramda'; import { uniq, is, isEmpty } from 'ramda';
// tools // tools
import getBandoLabel from '../../../../helpers/getBandoLabel'; import getBandoLabel from '../../../../helpers/getBandoLabel';
@@ -36,11 +36,13 @@ const MyLatestSubmissionsTable = () => {
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
setLocalAsyncRequest(true); if (!isEmpty(chosenCompanyId) && chosenCompanyId !== 0) {
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [ setLocalAsyncRequest(true);
['companyId', chosenCompanyId], ApplicationService.getApplications(getApplCallback, errGetApplCallback, [
['statuses', ['DRAFT', 'AWAITING', 'READY']] ['companyId', chosenCompanyId],
]) ['statuses', ['DRAFT', 'AWAITING', 'READY']]
]);
}
}, [chosenCompanyId]); }, [chosenCompanyId]);
const getApplCallback = (data) => { const getApplCallback = (data) => {

View File

@@ -329,6 +329,10 @@ const DomandaEditPreInstructor = () => {
</p> </p>
</div> </div>
<div className="appPageSection">
</div>
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Punteggi di valutazione', 'gepafin')}</h2> <h2>{__('Punteggi di valutazione', 'gepafin')}</h2>
{data.criteria {data.criteria

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect} from 'react'; import React, { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { is, uniq } from 'ramda'; import { is, uniq } from 'ramda';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@@ -31,7 +31,7 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
useEffect(() => { useEffect(() => {
setLocalAsyncRequest(true); setLocalAsyncRequest(true);
ApplicationService.getApplications(getCallback, errGetCallbacks, [ ApplicationService.getApplications(getCallback, errGetCallbacks, [
['statuses', 'SUBMIT'] ['statuses', ['SUBMIT', 'EVALUATION', 'SOCCORSO']]
]); ]);
}, [updaterString]); }, [updaterString]);
@@ -101,10 +101,12 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
const renderHeader = () => { const renderHeader = () => {
return ( return (
<div className="appTableHeader"> <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"> <IconField iconPosition="left">
<InputIcon className="pi pi-search" /> <InputIcon className="pi pi-search"/>
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder={__('Cerca', 'gepafin')} /> <InputText value={globalFilterValue} onChange={onGlobalFilterChange}
placeholder={__('Cerca', 'gepafin')}/>
</IconField> </IconField>
</div> </div>
); );
@@ -119,7 +121,8 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
}; };
const dateFilterTemplate = (options) => { 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 statusBodyTemplate = (rowData) => { const statusBodyTemplate = (rowData) => {
@@ -127,19 +130,25 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
}; };
const actionsBodyTemplate = (rowData) => { const actionsBodyTemplate = (rowData) => {
return openDialogFn return <div className="appPageSection__tableActions lessGap">
? <Button severity="info" {openDialogFn
onClick={() => openDialogFn(rowData.id)} ? <Button severity="info"
label={__('Assegnare', 'gepafin')} onClick={() => openDialogFn(rowData.id)}
icon="pi pi-pencil" size="small" iconPos="right" /> label={__('Assegnare', 'gepafin')}
: <Link to={'/domande'}> icon="pi pi-pencil" size="small" iconPos="right"/>
<Button severity="info" label={__('Gestire', 'gepafin')} size="small" /> : <Link to={'/domande'}>
<Button severity="info" label={__('Gestire', 'gepafin')} size="small"/>
</Link>}
<Link to={`/domande/${rowData.id}`}>
<Button severity="info" label={__('Anteprima', 'gepafin')} icon="pi pi-eye" size="small"
iconPos="right"/>
</Link> </Link>
</div>
} }
const header = renderHeader(); const header = renderHeader();
return( return (
<div className="appPageSection__table"> <div className="appPageSection__table">
<DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id" <DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
filters={filters} filters={filters}
@@ -162,9 +171,9 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
style={{ minWidth: '8rem' }} style={{ minWidth: '8rem' }}
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/> body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
<Column field="status" header={__('Stato', 'gepafin')} <Column field="status" header={__('Stato', 'gepafin')}
style={{ minWidth: '8rem' }} body={statusBodyTemplate} /> style={{ minWidth: '8rem' }} body={statusBodyTemplate}/>
{/*<Column header={__('Azioni', 'gepafin')} <Column header={__('Azioni', 'gepafin')}
body={actionsBodyTemplate}/>*/} body={actionsBodyTemplate}/>
</DataTable> </DataTable>
</div> </div>
) )

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { is, uniq } from 'ramda'; import { is, isEmpty, uniq } from 'ramda';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
// store // store
@@ -36,11 +36,13 @@ const BeneficiarioDomandeTable = () => {
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
setLocalAsyncRequest(true); if (!isEmpty(chosenCompanyId) && chosenCompanyId !== 0) {
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [ setLocalAsyncRequest(true);
['companyId', chosenCompanyId], ApplicationService.getApplications(getApplCallback, errGetApplCallback, [
['statuses', ['SOCCORSO', 'APPROVED', 'REJECTED', 'EVALUATION']] ['companyId', chosenCompanyId],
]) ['statuses', ['SOCCORSO', 'APPROVED', 'REJECTED', 'EVALUATION', 'SUBMIT']]
]);
}
}, [chosenCompanyId]); }, [chosenCompanyId]);
const getApplCallback = (data) => { const getApplCallback = (data) => {

View File

@@ -4,12 +4,12 @@ const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
export default class BandoService { export default class BandoService {
static getBandi = (callback, errCallback) => { static getBandi = (callback, errCallback, queryParams) => {
NetworkService.get(`${API_BASE_URL}/call`, callback, errCallback); NetworkService.get(`${API_BASE_URL}/call`, callback, errCallback, queryParams);
}; };
static getBando = (id, callback, errCallback) => { static getBando = (id, callback, errCallback, queryParams) => {
NetworkService.get(`${API_BASE_URL}/call/${id}`, callback, errCallback); NetworkService.get(`${API_BASE_URL}/call/${id}`, callback, errCallback, queryParams);
}; };
static validateBando = (id, callback, errCallback) => { static validateBando = (id, callback, errCallback) => {

View File

@@ -0,0 +1,14 @@
import { NetworkService } from './network-service';
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
export default class PreferredBandoService {
static addToPreferred = (body, callback, errCallback) => {
NetworkService.post(`${API_BASE_URL}/beneficiaryPreferredCall`, body, callback, errCallback);
};
static deleteFromPreferred = (id, callback, errCallback) => {
NetworkService.delete(`${API_BASE_URL}/beneficiaryPreferredCall/${id}`, {}, callback, errCallback);
};
}