- added bando preview page;
- added bando form preview;
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -14,6 +14,7 @@
|
|||||||
"@emotion/styled": "11.13.0",
|
"@emotion/styled": "11.13.0",
|
||||||
"@wordpress/i18n": "^5.5.0",
|
"@wordpress/i18n": "^5.5.0",
|
||||||
"@wordpress/react-i18n": "^4.5.0",
|
"@wordpress/react-i18n": "^4.5.0",
|
||||||
|
"deep-object-diff": "^1.1.9",
|
||||||
"dompurify": "3.1.6",
|
"dompurify": "3.1.6",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"html-react-parser": "5.1.12",
|
"html-react-parser": "5.1.12",
|
||||||
@@ -6765,6 +6766,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
|
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/deep-object-diff": {
|
||||||
|
"version": "1.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz",
|
||||||
|
"integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA=="
|
||||||
|
},
|
||||||
"node_modules/deepmerge": {
|
"node_modules/deepmerge": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"@emotion/styled": "11.13.0",
|
"@emotion/styled": "11.13.0",
|
||||||
"@wordpress/i18n": "^5.5.0",
|
"@wordpress/i18n": "^5.5.0",
|
||||||
"@wordpress/react-i18n": "^4.5.0",
|
"@wordpress/react-i18n": "^4.5.0",
|
||||||
|
"deep-object-diff": "^1.1.9",
|
||||||
"dompurify": "3.1.6",
|
"dompurify": "3.1.6",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"html-react-parser": "5.1.12",
|
"html-react-parser": "5.1.12",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@@ -12,30 +12,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.appPageSection {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
color: var(--Black);
|
|
||||||
font-size: 21px;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: normal;
|
|
||||||
margin: 0 0 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.appPageSection__table {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.appTableHeader {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.appPage__pageHeader {
|
.appPage__pageHeader {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -67,6 +43,157 @@
|
|||||||
padding: 24px 0;
|
padding: 24px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.appPageSection__hr {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 0 0 30px;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
background-color: #E5E7EB;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: normal;
|
||||||
|
padding: 0 10px;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 9;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPage__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: var(--global-textColor);
|
||||||
|
font-size: 21px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: normal;
|
||||||
|
margin: 0 0 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection__withBorder {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 7px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 17px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--card-borderColor-color);
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
filter: grayscale(1);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: var(--global-textColor);
|
||||||
|
font-size: 21px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: normal;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
&.rowContent {
|
||||||
|
padding: 17px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection__hero {
|
||||||
|
display: flex;
|
||||||
|
height: 172px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection__preview {
|
||||||
|
padding: 17px 0;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
45deg,
|
||||||
|
transparent,
|
||||||
|
transparent 10px,
|
||||||
|
#f8d282 10px,
|
||||||
|
#f8d282 20px
|
||||||
|
);
|
||||||
|
|
||||||
|
.p-button {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection__row {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection__pMeta {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appPageSection__table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appTableHeader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.appPageSection__actions {
|
.appPageSection__actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
|||||||
@@ -27,7 +27,14 @@
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
border: 1px #DDD;
|
border: 1px #DDD;
|
||||||
background: var(--surface-50);
|
background: var(--surface-50);
|
||||||
box-shadow: 0px 0px 2px 1px rgba(0, 0, 0, 0.10);
|
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.10);
|
||||||
|
|
||||||
|
.dropzone {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 3px dashed #bdbdbd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.formBuilder__element {
|
.formBuilder__element {
|
||||||
@@ -36,11 +43,23 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border: 1px dashed var(--button-secondary-borderColor);
|
border: 1px solid var(--button-secondary-borderColor);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
|
|
||||||
|
.meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.formBuilder__aside {
|
.formBuilder__aside {
|
||||||
@@ -82,3 +101,16 @@
|
|||||||
.formBuilder__elementSettings {
|
.formBuilder__elementSettings {
|
||||||
width: 40rem;
|
width: 40rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.formElementSettings {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formElementSettings__field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
@@ -12,8 +12,7 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Montserrat';
|
font-family: 'Montserrat';
|
||||||
|
|
||||||
p, span, input, label:not(.p-error), textarea, a, li, h1, h2, h3, h4, h5, h6, div, th, td, button {
|
p, span:not(.p-button-label, .p-button-icon, .p-badge), input, label:not(.p-error), textarea, a, li, h1, h2, h3, h4, h5, h6, div, th, td {
|
||||||
font-family: 'Montserrat';
|
|
||||||
color: var(--global-textColor);
|
color: var(--global-textColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,6 +83,21 @@ body {
|
|||||||
> main {
|
> main {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0 24px 50px;
|
padding: 0 24px 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
> footer {
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 100px 0 0;
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-accordion {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-steps .p-steps-item.p-highlight .p-steps-number {
|
||||||
|
background: var(--theme-highlight-background);
|
||||||
|
color: var(--primary-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.mb-2 {
|
.mb-2 {
|
||||||
|
|||||||
@@ -3,10 +3,6 @@
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|
||||||
.appForm__field {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
--button-secondary-borderColor: #C79807;
|
--button-secondary-borderColor: #C79807;
|
||||||
--button-secondary-background: var(--menu-borderColor);
|
--button-secondary-background: var(--menu-borderColor);
|
||||||
--global-textColor: #4B5563;
|
--global-textColor: #4B5563;
|
||||||
|
--theme-highlight-background: #BADEBE;
|
||||||
|
--primary-text: #3B7C43;
|
||||||
|
|
||||||
--card-full-background-color-2: #EEC137;
|
--card-full-background-color-2: #EEC137;
|
||||||
--card-full-background-color-3: #FA8E42;
|
--card-full-background-color-3: #FA8E42;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const TextArea = ({
|
|||||||
fieldName,
|
fieldName,
|
||||||
label,
|
label,
|
||||||
control,
|
control,
|
||||||
|
rows = 4,
|
||||||
errors,
|
errors,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
config = {},
|
config = {},
|
||||||
@@ -24,6 +25,7 @@ const TextArea = ({
|
|||||||
rules={config}
|
rules={config}
|
||||||
render={({ field, fieldState }) => (
|
render={({ field, fieldState }) => (
|
||||||
<InputTextarea id={field.name}
|
<InputTextarea id={field.name}
|
||||||
|
rows={rows}
|
||||||
{...field}
|
{...field}
|
||||||
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
||||||
)}/>
|
)}/>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ const FormFieldRepeater = ({
|
|||||||
const newData = stateFieldData.map((o, i) => {
|
const newData = stateFieldData.map((o, i) => {
|
||||||
if (i === index) {
|
if (i === index) {
|
||||||
o.value = e.value;
|
o.value = e.value;
|
||||||
|
o.id = e.id;
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ const FormFieldRepeaterCriteria = ({
|
|||||||
if (i === index) {
|
if (i === index) {
|
||||||
o.value = targetedOption.value;
|
o.value = targetedOption.value;
|
||||||
o.score = targetedOption.score;
|
o.score = targetedOption.score;
|
||||||
|
o.id = targetedOption.id;
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
});
|
});
|
||||||
@@ -91,7 +92,7 @@ const FormFieldRepeaterCriteria = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storeFieldData = data[fieldName] ?? [];
|
const storeFieldData = data[fieldName] ?? [];
|
||||||
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }))
|
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }));
|
||||||
setStateFieldData(newData);
|
setStateFieldData(newData);
|
||||||
setThreshold(data['threshold'])
|
setThreshold(data['threshold'])
|
||||||
register(fieldName, config)
|
register(fieldName, config)
|
||||||
|
|||||||
@@ -40,17 +40,6 @@ const FormFieldRepeaterFaq = ({
|
|||||||
setStateFieldData([...stateFieldData, chosen]);
|
setStateFieldData([...stateFieldData, chosen]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const onInputChange = (e, index) => {
|
|
||||||
const { value } = e.target;
|
|
||||||
const newData = stateFieldData.map((o, i) => {
|
|
||||||
if (i === index) {
|
|
||||||
o.value = value;
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
})
|
|
||||||
setStateFieldData(newData);
|
|
||||||
}
|
|
||||||
|
|
||||||
const addNewItem = () => {
|
const addNewItem = () => {
|
||||||
const newItem = { id: 0, status: 'new', question: '', answer: '', visible: true };
|
const newItem = { id: 0, status: 'new', question: '', answer: '', visible: true };
|
||||||
setStateFieldData([...stateFieldData, newItem]);
|
setStateFieldData([...stateFieldData, newItem]);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const UnsavedChangesDetector = ({ initialData, getValuesFn }) => {
|
|||||||
const [initial] = useState(initialData);
|
const [initial] = useState(initialData);
|
||||||
|
|
||||||
const warnIfUnsavedChanges = useCallback((event) => {
|
const warnIfUnsavedChanges = useCallback((event) => {
|
||||||
const updatedData = getValuesFn()
|
const updatedData = getValuesFn();
|
||||||
const isEqual = equal(initial, updatedData);
|
const isEqual = equal(initial, updatedData);
|
||||||
|
|
||||||
if (!isEqual) {
|
if (!isEqual) {
|
||||||
|
|||||||
6
src/helpers/getDateFromISOstring.js
Normal file
6
src/helpers/getDateFromISOstring.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
const getDateFromISOstring = (value, options = {}) => {
|
||||||
|
const optionsMerged = options || { day: '2-digit', month: '2-digit', year: 'numeric', dateStyle: 'short' }
|
||||||
|
return Intl.DateTimeFormat('it-IT', optionsMerged).format(new Date(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getDateFromISOstring;
|
||||||
5
src/helpers/getNumberFormatted.js
Normal file
5
src/helpers/getNumberFormatted.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const getNumberFormatted = (value) => {
|
||||||
|
return Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getNumberFormatted;
|
||||||
11
src/helpers/getNumberWithCurrency.js
Normal file
11
src/helpers/getNumberWithCurrency.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const getNumberWithCurrency = (value, currency = 'EUR') => {
|
||||||
|
const formatter = Intl.NumberFormat('it-IT', {
|
||||||
|
style: 'currency',
|
||||||
|
currencyDisplay: 'symbol',
|
||||||
|
currency
|
||||||
|
})
|
||||||
|
|
||||||
|
return formatter.format(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getNumberWithCurrency;
|
||||||
@@ -48,6 +48,10 @@ const DefaultLayout = ({ children }) => {
|
|||||||
<AppSidebar/>
|
<AppSidebar/>
|
||||||
<main>
|
<main>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>{__('© 2024 Gepafin. Tutti i diritti riservati.', 'gepafin')}</p>
|
||||||
|
</footer>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const BandoEditFormActions = ({ openPreview, openPreviewEvaluation }) => {
|
|||||||
label={__('Salva bozza', 'gepafin')} icon="pi pi-save" iconPos="right"/>
|
label={__('Salva bozza', 'gepafin')} icon="pi pi-save" iconPos="right"/>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={true}
|
disabled={false}
|
||||||
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"/>
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
// end of temp data
|
// end of temp data
|
||||||
|
|
||||||
const openPreview = () => {
|
const openPreview = () => {
|
||||||
navigate('/bandi/preview/11');
|
navigate('/bandi/11/preview');
|
||||||
}
|
}
|
||||||
|
|
||||||
const openPreviewEvaluation = () => {
|
const openPreviewEvaluation = () => {
|
||||||
navigate('/bandi/preview-evaluation/11');
|
navigate('/bandi/11/preview-evaluation');
|
||||||
}
|
}
|
||||||
|
|
||||||
useImperativeHandle(
|
useImperativeHandle(
|
||||||
@@ -57,6 +57,9 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
},
|
},
|
||||||
getErrors: () => {
|
getErrors: () => {
|
||||||
return errors;
|
return errors;
|
||||||
|
},
|
||||||
|
getValues: () => {
|
||||||
|
return getValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [errors, isValid]);
|
}, [errors, isValid]);
|
||||||
@@ -106,6 +109,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
fieldName="descriptionLong"
|
fieldName="descriptionLong"
|
||||||
label={__('Descrizione completa', 'gepafin')}
|
label={__('Descrizione completa', 'gepafin')}
|
||||||
control={control}
|
control={control}
|
||||||
|
rows={7}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
defaultValue={values['descriptionLong']}
|
defaultValue={values['descriptionLong']}
|
||||||
config={{
|
config={{
|
||||||
@@ -199,6 +203,12 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
}}
|
}}
|
||||||
label={__('FAQ', 'gepafin')}/>
|
label={__('FAQ', 'gepafin')}/>
|
||||||
|
|
||||||
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
<div className="appPageSection__hr">
|
||||||
|
<span>{__('Azioni', 'gepafin')}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<BandoEditFormActions
|
<BandoEditFormActions
|
||||||
openPreview={openPreview}
|
openPreview={openPreview}
|
||||||
openPreviewEvaluation={openPreviewEvaluation}/>
|
openPreviewEvaluation={openPreviewEvaluation}/>
|
||||||
|
|||||||
@@ -60,9 +60,12 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
},
|
},
|
||||||
getErrors: () => {
|
getErrors: () => {
|
||||||
return errors;
|
return errors;
|
||||||
|
},
|
||||||
|
getValues: () => {
|
||||||
|
return getValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, [errors, isValid]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
trigger().then(() => clearErrors());
|
trigger().then(() => clearErrors());
|
||||||
@@ -135,7 +138,12 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button type="button" onClick={() => console.log(getValues())}>Check</button>
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
<div className="appPageSection__hr">
|
||||||
|
<span>{__('Azioni', 'gepafin')}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<BandoEditFormActions
|
<BandoEditFormActions
|
||||||
openPreview={openPreview}
|
openPreview={openPreview}
|
||||||
openPreviewEvaluation={openPreviewEvaluation}/>
|
openPreviewEvaluation={openPreviewEvaluation}/>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
//import equal from 'fast-deep-equal';
|
||||||
|
import { is, isNil } from 'ramda';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import getBandoLabel from '../../helpers/getBandoLabel';
|
import getBandoLabel from '../../helpers/getBandoLabel';
|
||||||
@@ -10,7 +12,9 @@ import { Steps } from 'primereact/steps';
|
|||||||
import BandoEditFormStep1 from './components/BandoEditFormStep1';
|
import BandoEditFormStep1 from './components/BandoEditFormStep1';
|
||||||
import BandoEditFormStep2 from './components/BandoEditFormStep2';
|
import BandoEditFormStep2 from './components/BandoEditFormStep2';
|
||||||
import { Messages } from 'primereact/messages';
|
import { Messages } from 'primereact/messages';
|
||||||
import { is, isNil } from 'ramda';
|
|
||||||
|
// TODO temp
|
||||||
|
import { bandoTest } from '../../tempData';
|
||||||
|
|
||||||
const BandoEdit = () => {
|
const BandoEdit = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -18,8 +22,8 @@ const BandoEdit = () => {
|
|||||||
const [activeStep, setActiveStep] = useState(0)
|
const [activeStep, setActiveStep] = useState(0)
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState({});
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [selectedTemplate, setSelectedTemplate] = useState(null);
|
//const [selectedTemplate, setSelectedTemplate] = useState(null);
|
||||||
const [templates, setTemplate] = useState(null);
|
//const [templates, setTemplate] = useState(null);
|
||||||
const formRef = useRef(null);
|
const formRef = useRef(null);
|
||||||
const stepErrorMsgs = useRef(null);
|
const stepErrorMsgs = useRef(null);
|
||||||
|
|
||||||
@@ -31,7 +35,11 @@ const BandoEdit = () => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
stepErrorMsgs.current.clear();
|
stepErrorMsgs.current.clear();
|
||||||
if (formRef.current.isFormValid()) {
|
const isFormValid = formRef.current.isFormValid();
|
||||||
|
//const values = formRef.current.getValues();
|
||||||
|
//const diffData = equal(values, data);
|
||||||
|
// TODO warn about unsaved data
|
||||||
|
if (isFormValid) {
|
||||||
goToStep(0)
|
goToStep(0)
|
||||||
} else {
|
} else {
|
||||||
stepErrorMsgs.current.show([
|
stepErrorMsgs.current.show([
|
||||||
@@ -50,7 +58,9 @@ const BandoEdit = () => {
|
|||||||
}
|
}
|
||||||
stepErrorMsgs.current.clear();
|
stepErrorMsgs.current.clear();
|
||||||
const isFormValid = formRef.current.isFormValid();
|
const isFormValid = formRef.current.isFormValid();
|
||||||
console.log('before go to step 1:', isFormValid)
|
//const values = formRef.current.getValues();
|
||||||
|
//const diffData = equal(values, data);
|
||||||
|
// TODO warn about unsaved data
|
||||||
if (isFormValid) {
|
if (isFormValid) {
|
||||||
goToStep(1);
|
goToStep(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -81,47 +91,7 @@ const BandoEdit = () => {
|
|||||||
status: 'draft',
|
status: 'draft',
|
||||||
name: ''
|
name: ''
|
||||||
}
|
}
|
||||||
: {
|
: bandoTest;
|
||||||
"name": "Innovazione digitale 2024",
|
|
||||||
"confidi": false,
|
|
||||||
"descriptionShort": "Supporto alle PMI per progetti di digitalizzazione e innovazione tecnologica.",
|
|
||||||
"descriptionLong": "Il bando \"Innovazione Digitale 2024\" mira a sostenere le PMI nell'adozione di tecnologie digitali innovative. I progetti finanziabili includono l'implementazione di soluzioni di intelligenza artificiale, blockchain, IoT, e altre tecnologie avanzate che possono migliorare la competitività delle imprese.",
|
|
||||||
"documentationRequested": "Documentazione richiesta*",
|
|
||||||
"dates": [
|
|
||||||
"2024-08-27T22:00:00.000Z",
|
|
||||||
"2024-10-29T23:00:00.000Z"
|
|
||||||
],
|
|
||||||
"amount": 0,
|
|
||||||
"amountMax": 0,
|
|
||||||
"aimedTo": [
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"value": "PMI con sede in Umbria",
|
|
||||||
"status": "existing"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"faq": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"question": "Question 1?",
|
|
||||||
"answer": "Lorem ipsum dolor",
|
|
||||||
"visible": true,
|
|
||||||
"status": "existing"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"documentation": [
|
|
||||||
/*{
|
|
||||||
createdDate: "2024-08-23T12:40:47.700350791",
|
|
||||||
description: null,
|
|
||||||
filePath: "https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/SCR-20240820-kiwn.pdf",
|
|
||||||
id: 10,
|
|
||||||
name: "SCR-20240820-kiwn.pdf",
|
|
||||||
updatedDate: "2024-08-23T12:40:47.700373894"
|
|
||||||
}*/
|
|
||||||
],
|
|
||||||
status: 'draft',
|
|
||||||
id: 11
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bandoId === 0) {
|
if (bandoId === 0) {
|
||||||
setData(data);
|
setData(data);
|
||||||
@@ -134,11 +104,11 @@ const BandoEdit = () => {
|
|||||||
|
|
||||||
setData(data);
|
setData(data);
|
||||||
|
|
||||||
const templates = [
|
/*const templates = [
|
||||||
{ name: 'Il mio template', value: 22 },
|
{ name: 'Il mio template', value: 22 },
|
||||||
{ name: 'Template #11', value: 11 },
|
{ name: 'Template #11', value: 11 },
|
||||||
];
|
];
|
||||||
setTemplate(templates);
|
setTemplate(templates);*/
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,34 @@ import { useParams, useNavigate } from 'react-router-dom';
|
|||||||
|
|
||||||
// components
|
// components
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
|
import { Dropdown } from 'primereact/dropdown';
|
||||||
|
|
||||||
const BandoForms = () => {
|
const BandoForms = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate()
|
||||||
|
const [templates, setTemplate] = useState(null);
|
||||||
|
const [selectedTemplate, setSelectedTemplate] = useState(null);
|
||||||
//const [data, setData] = useState({});
|
//const [data, setData] = useState({});
|
||||||
//const [isLoading, setIsLoading] = useState(true);
|
//const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
const doCreateNewForm = () => {
|
const doCreateNewForm = () => {
|
||||||
navigate('/bandi/11/forms/new');
|
navigate(`/bandi/${id}/forms/new`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const goToEditBando = () => {
|
||||||
|
navigate(`/bandi/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const parsed = parseInt(id)
|
const parsed = parseInt(id)
|
||||||
const bandoId = !isNaN(parsed) ? parsed : 0;
|
const bandoId = !isNaN(parsed) ? parsed : 0;
|
||||||
|
|
||||||
|
const templates = [
|
||||||
|
{ name: 'Il mio template', value: 22 },
|
||||||
|
{ name: 'Template #11', value: 11 },
|
||||||
|
];
|
||||||
|
setTemplate(templates);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
@@ -33,11 +46,53 @@ const BandoForms = () => {
|
|||||||
|
|
||||||
<div className="appPage__spacer"></div>
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
<div className="appPage__content">
|
||||||
<div className="appPageSection">
|
<div className="appPageSection">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={goToEditBando}
|
||||||
|
label={__('Modifica bando', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder disabled">
|
||||||
|
<h2>{__('Usa un template', 'gepafin')}</h2>
|
||||||
|
<div className="row">
|
||||||
|
<p>{__('Scegli tra i template predefiniti e personalizzali', 'gepafin')}</p>
|
||||||
|
<Dropdown
|
||||||
|
id="template"
|
||||||
|
disabled={true}
|
||||||
|
value={selectedTemplate}
|
||||||
|
onChange={(e) => setSelectedTemplate(e.value)}
|
||||||
|
options={templates}
|
||||||
|
optionLabel="name"
|
||||||
|
placeholder={__('Seleziona template', 'gepafin')}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Crea un nuovo Form da Zero', 'gepafin')}</h2>
|
||||||
|
<div className="row">
|
||||||
|
<p>{__('Inizia con un form completamente vuoto e personalizzabil', 'gepafin')}</p>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={doCreateNewForm}
|
onClick={doCreateNewForm}
|
||||||
label={__('Crea/modifica form', 'gepafin')}/>
|
label={__('Crea form', 'gepafin')}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder disabled">
|
||||||
|
<h2>{__('Modifica Form esistente', 'gepafin')}</h2>
|
||||||
|
<div className="row">
|
||||||
|
<p>{__('Continua a lavorare su un form precedentemente salvato', 'gepafin')}</p>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
disabled={true}
|
||||||
|
onClick={doCreateNewForm}
|
||||||
|
label={__('Modifica', 'gepafin')}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
26
src/pages/BandoFormsEdit/components/BuilderDropzone/index.js
Normal file
26
src/pages/BandoFormsEdit/components/BuilderDropzone/index.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { useDrop } from 'react-dnd';
|
||||||
|
import { ItemTypes } from '../ItemTypes';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { storeSet } from '../../../../store';
|
||||||
|
|
||||||
|
const BuilderDropzone = () => {
|
||||||
|
const dropzoneRef = useRef();
|
||||||
|
|
||||||
|
const [, drop] = useDrop({
|
||||||
|
accept: ItemTypes.FIELD,
|
||||||
|
hover(item, monitor) {
|
||||||
|
storeSet.main.moveElement(-1, 0, item);
|
||||||
|
item.index = 0;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
drop(dropzoneRef);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={dropzoneRef} className="dropzone"></div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BuilderDropzone;
|
||||||
@@ -7,8 +7,10 @@ import { storeSet } from '../../../../store';
|
|||||||
|
|
||||||
// components
|
// components
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
|
import { Tag } from 'primereact/tag';
|
||||||
|
import BuilderElementProperLabel from '../BuilderElementProperLabel';
|
||||||
|
|
||||||
const BuilderElement = ({ id, name, label, index, move }) => {
|
const BuilderElement = ({ id, name, label, index }) => {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|
||||||
const [{ handlerId }, drop] = useDrop({
|
const [{ handlerId }, drop] = useDrop({
|
||||||
@@ -74,17 +76,31 @@ const BuilderElement = ({ id, name, label, index, move }) => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const move = (dragIndex, hoverIndex, item) => {
|
||||||
|
storeSet.main.moveElement(dragIndex, hoverIndex, item);
|
||||||
|
}
|
||||||
|
|
||||||
const openSettings = (id) => {
|
const openSettings = (id) => {
|
||||||
storeSet.main.activeElement(id);
|
storeSet.main.activeElement(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const remove = (id) => {
|
||||||
|
storeSet.main.removeElement(id);
|
||||||
|
}
|
||||||
|
|
||||||
const opacity = isDragging ? 0 : 1;
|
const opacity = isDragging ? 0 : 1;
|
||||||
drag(drop(ref));
|
drag(drop(ref));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="formBuilder__element" style={{ opacity }} data-handler-id={handlerId}>
|
<div ref={ref} className="formBuilder__element" style={{ opacity }} data-handler-id={handlerId}>
|
||||||
{label}
|
<div className="meta">
|
||||||
<Button icon="pi pi-cog" onClick={() => openSettings(id)} outlined />
|
<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>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ItemTypes } from '../ItemTypes';
|
|||||||
import uniqid from '../../../../helpers/uniqid';
|
import uniqid from '../../../../helpers/uniqid';
|
||||||
|
|
||||||
|
|
||||||
const BuilderElementItem = ({ dbId, name, label, move }) => {
|
const BuilderElementItem = ({ dbId, name, label }) => {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|
||||||
const [{ isDragging }, drag] = useDrag(() => ({
|
const [{ isDragging }, drag] = useDrag(() => ({
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import { head } from 'ramda';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { useStore } from '../../../../store';
|
||||||
|
|
||||||
|
const BuilderElementProperLabel = ({ id, defaultLabel }) => {
|
||||||
|
const elements = useStore().main.formElements();
|
||||||
|
const [label, setLabel] = useState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const element = head(elements.filter(o => o.id === id));
|
||||||
|
const setting = head(element.settings.filter(o => o.name === 'label'));
|
||||||
|
if (setting.value) {
|
||||||
|
setLabel(setting.value);
|
||||||
|
} else {
|
||||||
|
setLabel(defaultLabel);
|
||||||
|
}
|
||||||
|
}, [elements]);
|
||||||
|
|
||||||
|
return label
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BuilderElementProperLabel;
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { head } from 'ramda';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { klona } from 'klona';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { storeSet, useStore } from '../../../../store';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import { InputText } from 'primereact/inputtext';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import { Tag } from 'primereact/tag';
|
||||||
|
|
||||||
|
const BuilderElementSettings = () => {
|
||||||
|
const elements = useStore().main.elements();
|
||||||
|
const activeElement = useStore().main.activeElement();
|
||||||
|
const [activeElementData, setActiveElementData] = useState({});
|
||||||
|
const [settings, setSettings] = useState([]);
|
||||||
|
|
||||||
|
const onChange = (value, name) => {
|
||||||
|
const newSettings = settings
|
||||||
|
.map(o => {
|
||||||
|
if (o.name === name) {
|
||||||
|
o.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return o;
|
||||||
|
});
|
||||||
|
|
||||||
|
setSettings(newSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveSettings = () => {
|
||||||
|
activeElementData.settings = settings;
|
||||||
|
const newElements = elements.map(o => o.id === activeElementData.id ? activeElementData : o);
|
||||||
|
storeSet.main.elements(newElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const chosen = head(elements.filter(o => o.id === activeElement));
|
||||||
|
if (chosen) {
|
||||||
|
setActiveElementData(klona(chosen));
|
||||||
|
setSettings(klona(chosen.settings));
|
||||||
|
} else {
|
||||||
|
setActiveElementData({});
|
||||||
|
setSettings([]);
|
||||||
|
}
|
||||||
|
}, [activeElement])
|
||||||
|
|
||||||
|
return (activeElementData
|
||||||
|
? <div className="formElementSettings">
|
||||||
|
<Tag value={activeElementData.name} severity="info"/>
|
||||||
|
{settings
|
||||||
|
? settings.map((o) => <div className="formElementSettings__field" key={o.name}>
|
||||||
|
<label htmlFor={o.name}>{o.name}</label>
|
||||||
|
<InputText id={o.name} aria-describedby={`${o.name}-help`}
|
||||||
|
value={o.value}
|
||||||
|
onChange={(e) => onChange(e.target.value, o.name)}/>
|
||||||
|
</div>) : null}
|
||||||
|
|
||||||
|
<Button label={__('Salva', 'gepafin')} onClick={saveSettings}/>
|
||||||
|
</div>
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BuilderElementSettings;
|
||||||
@@ -1,38 +1,22 @@
|
|||||||
import React, { useCallback, useState, useEffect } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { head, isEmpty } from 'ramda';
|
import { isEmpty } from 'ramda';
|
||||||
|
|
||||||
// store
|
// store
|
||||||
import { storeGet, storeSet, useStore } from '../../../../store';
|
import { storeSet, useStore } from '../../../../store';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import BuilderElement from '../BuilderElement';
|
import BuilderElement from '../BuilderElement';
|
||||||
import BuilderElementItem from '../BuilderElementItem';
|
import BuilderElementItem from '../BuilderElementItem';
|
||||||
import { Sidebar } from 'primereact/sidebar';
|
import { Sidebar } from 'primereact/sidebar';
|
||||||
|
import BuilderElementSettings from '../BuilderElementSettings';
|
||||||
|
import BuilderDropzone from '../BuilderDropzone';
|
||||||
|
|
||||||
const FormBuilder = () => {
|
const FormBuilder = () => {
|
||||||
const [fields, setFields] = useState([]);
|
const elements = useStore().main.formElements();
|
||||||
const [items, setItems] = useState([]);
|
const elementItems = useStore().main.elementItems();
|
||||||
const activeElement = useStore().main.activeElement();
|
const activeElement = useStore().main.activeElement();
|
||||||
|
|
||||||
const moveField = useCallback((dragIndex, hoverIndex, item) => {
|
|
||||||
setFields((prevFields) => {
|
|
||||||
if (dragIndex === -1) {
|
|
||||||
const configs = storeGet.main.elementItems();
|
|
||||||
const itemCfg = head(configs.filter(o => o.id === item.dbId));
|
|
||||||
const newItem = {
|
|
||||||
...itemCfg,
|
|
||||||
id: item.id,
|
|
||||||
dbId: item.dbId
|
|
||||||
}
|
|
||||||
return prevFields.toSpliced(hoverIndex, 0, newItem);
|
|
||||||
} else {
|
|
||||||
let newFields = prevFields.toSpliced(dragIndex, 1);
|
|
||||||
return newFields.toSpliced(hoverIndex, 0, prevFields[dragIndex]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const renderField = useCallback((field, index) => {
|
const renderField = useCallback((field, index) => {
|
||||||
return (
|
return (
|
||||||
<BuilderElement
|
<BuilderElement
|
||||||
@@ -41,26 +25,17 @@ const FormBuilder = () => {
|
|||||||
id={field.id}
|
id={field.id}
|
||||||
label={field.label}
|
label={field.label}
|
||||||
name={field.name}
|
name={field.name}
|
||||||
move={moveField}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
const renderItem = useCallback((item) => {
|
||||||
const elements = storeGet.main.elements();
|
|
||||||
const elementItems = storeGet.main.elementItems();
|
|
||||||
setFields(elements);
|
|
||||||
setItems(elementItems);
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const renderItem = useCallback((item, index) => {
|
|
||||||
return (
|
return (
|
||||||
<BuilderElementItem
|
<BuilderElementItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
dbId={item.id}
|
dbId={item.id}
|
||||||
label={item.label}
|
label={item.label}
|
||||||
name={item.name}
|
name={item.name}
|
||||||
move={moveField}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}, []);
|
}, []);
|
||||||
@@ -73,21 +48,21 @@ 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>
|
||||||
<p>
|
{!isEmpty(activeElement) ? <BuilderElementSettings/> : null}
|
||||||
Form fields here
|
|
||||||
</p>
|
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
<div className="formBuilder">
|
<div className="formBuilder">
|
||||||
<div className="formBuilder__main">
|
<div className="formBuilder__main">
|
||||||
<h2>{__('Trascina qui gli elementi del Form', 'gepafin')}</h2>
|
<h2>{__('Trascina qui gli elementi del Form', 'gepafin')}</h2>
|
||||||
<div className="formBuilder__content">
|
<div className="formBuilder__content">
|
||||||
{fields.map((field, i) => renderField(field, i))}
|
{!isEmpty(elements)
|
||||||
|
? elements.map((field, i) => renderField(field, i))
|
||||||
|
: <BuilderDropzone/>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="formBuilder__aside">
|
<div className="formBuilder__aside">
|
||||||
<h2>{__('Elementi del Form', 'gepafin')}</h2>
|
<h2>{__('Elementi del Form', 'gepafin')}</h2>
|
||||||
<ul className="formBuilder__list">
|
<ul className="formBuilder__list">
|
||||||
{items.map((item) => renderItem(item))}
|
{elementItems.map((item) => renderItem(item))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,31 +1,37 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { DndProvider } from 'react-dnd'
|
import { DndProvider } from 'react-dnd';
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend'
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
|
import { klona } from 'klona';
|
||||||
|
|
||||||
// store
|
// store
|
||||||
import { storeSet } from '../../store';
|
import { storeSet, storeGet } from '../../store';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import FormBuilder from './components/FormBuilder';
|
import FormBuilder from './components/FormBuilder';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
|
|
||||||
|
// TODO temp
|
||||||
|
import { formData, elementItems } from '../../tempData';
|
||||||
|
import { InputText } from 'primereact/inputtext';
|
||||||
|
|
||||||
const BandoFormsEdit = () => {
|
const BandoFormsEdit = () => {
|
||||||
const { id, formId } = useParams();
|
const { id, formId } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [formName, setFormName] = useState('');
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
navigate('/bandi/11/forms');
|
navigate(`/bandi/${id}/forms`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const doSave = () => {
|
const doSave = () => {
|
||||||
console.log('doSave');
|
console.log('doSave', storeGet.main.formElements());
|
||||||
}
|
}
|
||||||
|
|
||||||
const openPreview = () => {
|
const openPreview = () => {
|
||||||
console.log('openPreview');
|
navigate(`/bandi/${id}/forms/${formId}/preview`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const doPublish = () => {
|
const doPublish = () => {
|
||||||
@@ -39,38 +45,9 @@ const BandoFormsEdit = () => {
|
|||||||
//const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
|
//const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
|
||||||
|
|
||||||
// 1. TODO get builder content data from API
|
// 1. TODO get builder content data from API
|
||||||
const elements = [
|
storeSet.main.formLabel(formData.label);
|
||||||
{
|
const elements = klona(formData.content);
|
||||||
id: 'a123456',
|
storeSet.main.formElements(elements);
|
||||||
name: 'textinput',
|
|
||||||
dbId: 1,
|
|
||||||
label: 'Full Name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'a456789',
|
|
||||||
name: 'textarea',
|
|
||||||
dbId: 2,
|
|
||||||
label: 'Bio',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
const elementItems = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'textinput',
|
|
||||||
label: 'Text Input'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'textarea',
|
|
||||||
label: 'Text Area'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3, // DB id
|
|
||||||
name: 'piva',
|
|
||||||
label: 'P.IVA'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
storeSet.main.elements(elements);
|
|
||||||
storeSet.main.elementItems(elementItems);
|
storeSet.main.elementItems(elementItems);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|
||||||
@@ -87,9 +64,21 @@ const BandoFormsEdit = () => {
|
|||||||
|
|
||||||
<div className="appPage__spacer"></div>
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
<div className="appForm__field">
|
||||||
|
<label htmlFor="label">{__('Form label', 'gepafin')}</label>
|
||||||
|
<InputText
|
||||||
|
id="label"
|
||||||
|
value={formName}
|
||||||
|
placeholder={__('Nome della forma', 'gepafin')}
|
||||||
|
onChange={(e) => setFormName(e.target.value)}
|
||||||
|
aria-describedby="label-help"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
<div className="appPageSection">
|
<div className="appPageSection">
|
||||||
<DndProvider backend={HTML5Backend}>
|
<DndProvider backend={HTML5Backend}>
|
||||||
{!isLoading ? <FormBuilder/>: null}
|
{!isLoading ? <FormBuilder/> : null}
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -106,7 +95,6 @@ const BandoFormsEdit = () => {
|
|||||||
outlined
|
outlined
|
||||||
label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/>
|
label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/>
|
||||||
<Button
|
<Button
|
||||||
disabled={true}
|
|
||||||
outlined
|
outlined
|
||||||
onClick={openPreview}
|
onClick={openPreview}
|
||||||
label={__('Visualizza Anteprima Beneficiario', 'gepafin')} icon="pi pi-image" iconPos="right"/>
|
label={__('Visualizza Anteprima Beneficiario', 'gepafin')} icon="pi pi-image" iconPos="right"/>
|
||||||
|
|||||||
121
src/pages/BandoFormsPreview/index.js
Normal file
121
src/pages/BandoFormsPreview/index.js
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
import { bandoTest, formData } from '../../tempData';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import getNumberWithCurrency from '../../helpers/getNumberWithCurrency';
|
||||||
|
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import { Skeleton } from 'primereact/skeleton';
|
||||||
|
import { Accordion } from 'primereact/accordion';
|
||||||
|
import { AccordionTab } from 'primereact/accordion';
|
||||||
|
import { InputTextarea } from 'primereact/inputtextarea';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { is, isNil } from 'ramda';
|
||||||
|
import FormField from '../../components/FormField';
|
||||||
|
|
||||||
|
const BandoFormsPreview = () => {
|
||||||
|
const { id, formId } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [bando, setBando] = useState({});
|
||||||
|
const [data, setData] = useState({});
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors, isValid },
|
||||||
|
setValue,
|
||||||
|
register,
|
||||||
|
trigger,
|
||||||
|
getValues,
|
||||||
|
clearErrors
|
||||||
|
} = useForm({defaultValues: {}, mode: 'onChange'});
|
||||||
|
const values = getValues();
|
||||||
|
|
||||||
|
const onSubmit = (formData) => {
|
||||||
|
console.log('onSubmit', formData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closePreview = () => {
|
||||||
|
navigate(`/bandi/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//const parsed = parseInt(id)
|
||||||
|
//const bandoId = !isNaN(parsed) ? parsed : 0;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const data = formData;
|
||||||
|
setData(data);
|
||||||
|
|
||||||
|
const bandoData = bandoTest;
|
||||||
|
setBando(bandoData);
|
||||||
|
|
||||||
|
setIsLoading(false)
|
||||||
|
}, 3000);
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="appPage">
|
||||||
|
{!isLoading
|
||||||
|
? <div className="appPage__pageHeader">
|
||||||
|
<h1>{sprintf(__('Domanda per il Bando: %s', 'gepafin'), bando.name)}</h1>
|
||||||
|
</div>
|
||||||
|
: <>
|
||||||
|
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||||
|
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
||||||
|
</>}
|
||||||
|
|
||||||
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
|
{!isLoading
|
||||||
|
? <div className="appPage__content">
|
||||||
|
<div className="appPageSection__preview">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={closePreview}
|
||||||
|
label={__('Chiudi Anteprima', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
{data.content.map(o => <FormField
|
||||||
|
key={o.id}
|
||||||
|
type={o.name}
|
||||||
|
fieldName={`field_${o.id}`}
|
||||||
|
label={o.label}
|
||||||
|
control={control}
|
||||||
|
errors={errors}
|
||||||
|
defaultValue={values[`field_${o.id}`]}
|
||||||
|
/>)}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div className="appPageSection__preview">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={closePreview}
|
||||||
|
label={__('Chiudi Anteprima', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
</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 BandoFormsPreview;
|
||||||
@@ -1,56 +1,52 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Skeleton } from 'primereact/skeleton';
|
import { bandoTest } from '../../tempData';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import getNumberWithCurrency from '../../helpers/getNumberWithCurrency';
|
||||||
|
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
|
import { Skeleton } from 'primereact/skeleton';
|
||||||
|
import { Accordion } from 'primereact/accordion';
|
||||||
|
import { AccordionTab } from 'primereact/accordion';
|
||||||
|
import { InputTextarea } from 'primereact/inputtextarea';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
|
||||||
const BandoView = () => {
|
const BandoView = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState({});
|
||||||
|
const [newQuestion, setNewQuestion] = useState({});
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
|
const closePreview = () => {
|
||||||
|
navigate(`/bandi/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const scaricaBando = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const scaricaModulistica = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitQuestion = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveToFavourites = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//const parsed = parseInt(id)
|
//const parsed = parseInt(id)
|
||||||
//const bandoId = !isNaN(parsed) ? parsed : 0;
|
//const bandoId = !isNaN(parsed) ? parsed : 0;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const data = {
|
const data = bandoTest;
|
||||||
name: 'Bando Innovazione 2024',
|
|
||||||
descriptionShort: 'Supporto alle PMI per progetti di digitalizzazione e innovazione tecnologica.',
|
|
||||||
descriptionLong: 'Il bando "Innovazione Digitale 2024" mira a sostenere le PMI nell\'adozione di tecnologie digitali innovative. I progetti finanziabili includono l\'implementazione di soluzioni di intelligenza artificiale, blockchain, IoT, e altre tecnologie avanzate che possono migliorare la competitività delle imprese.',
|
|
||||||
dates: [ "2024-08-20T22:00:00.000Z", "2024-08-28T22:00:00.000Z" ],
|
|
||||||
amount: 10000000,
|
|
||||||
amountMax: 2000,
|
|
||||||
aimedTo: [
|
|
||||||
{ id: 11, value: 'PMI con sede in Umbria' },
|
|
||||||
{ id: 12, value: 'Almeno 2 anni di attività' },
|
|
||||||
{ id: 15, value: 'Fatturato annuo non superiore a € 50 milioni' }
|
|
||||||
],
|
|
||||||
documentationRequested: 'Some text',
|
|
||||||
threshold: 12,
|
|
||||||
criteria: [
|
|
||||||
{ id: 15, value: 'Innovatività del progetto', score: 9 },
|
|
||||||
{ id: 16, value: 'Impatto sulla competitività dell\'azienda', score: 3 },
|
|
||||||
{ id: 17, value: 'Sostenibilità economico-finanziaria', score: 5 }
|
|
||||||
],
|
|
||||||
faq: [
|
|
||||||
{id: 2, question: 'È possibile presentare più di un progetto?', answer: 'No, ogni azienda può presentare un solo progetto per questo bando.'}
|
|
||||||
],
|
|
||||||
checklist: [
|
|
||||||
{ id: 9, value: 'Requisiti di ammissibilità soddisfatti' },
|
|
||||||
{ id: 21, value: 'Documentazione completa' }
|
|
||||||
],
|
|
||||||
docs: [
|
|
||||||
{id: 12, url: '#', name: 'file_name'}
|
|
||||||
],
|
|
||||||
images: [
|
|
||||||
{id: 15, url: '#', name: 'file_name'}
|
|
||||||
],
|
|
||||||
status: 'draft',
|
|
||||||
id: 11,
|
|
||||||
created: '2024-08-07T00:00:00+00:00'
|
|
||||||
}
|
|
||||||
setData(data);
|
setData(data);
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}, 3000);
|
}, 3000);
|
||||||
@@ -63,7 +59,7 @@ const BandoView = () => {
|
|||||||
<h1>{data.name}</h1>
|
<h1>{data.name}</h1>
|
||||||
<p>
|
<p>
|
||||||
{__('Data:', 'gepafin')}
|
{__('Data:', 'gepafin')}
|
||||||
<span>{data.created}</span>
|
<span>{getDateFromISOstring(data.createdDate)}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
: <>
|
: <>
|
||||||
@@ -74,11 +70,176 @@ const BandoView = () => {
|
|||||||
<div className="appPage__spacer"></div>
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
{!isLoading
|
{!isLoading
|
||||||
? <>
|
? <div className="appPage__content">
|
||||||
<div className="appPageSection">
|
<div className="appPageSection__preview">
|
||||||
Preview beneficiario
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={closePreview}
|
||||||
|
label={__('Chiudi Anteprima', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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 className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Descrizione breve', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<p>{data.descriptionShort}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__row">
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Importo totale', 'gepafin')}</span>
|
||||||
|
<span>{getNumberWithCurrency(data.amount)}</span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Importo massimo per progetto', 'gepafin')}</span>
|
||||||
|
<span>{getNumberWithCurrency(data.amountMax)}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Data apertura', 'gepafin')}</span>
|
||||||
|
<span></span>
|
||||||
|
</p>
|
||||||
|
<p className="appPageSection__pMeta">
|
||||||
|
<span>{__('Data chiusura', 'gepafin')}</span>
|
||||||
|
<span></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Descrizione dettagliata', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<p>{data.descriptionLong}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Requisiti di Partecipazione', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<ul>
|
||||||
|
{data.aimedTo.map((o, i) => <li key={i}>
|
||||||
|
{o.value}
|
||||||
|
</li>)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Documentazione Richiesta', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<p>{data.documentationRequested}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Criteri di Valutazione', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<ul>
|
||||||
|
{data.criteria.map((o, i) => <li key={i}>
|
||||||
|
{`${o.value} ${sprintf(__('(%d punti)'), o.score)}`}
|
||||||
|
</li>)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Allegati', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<ul>
|
||||||
|
{data.documentation.map((o, i) => <li key={i}>
|
||||||
|
<a href={o.filePath} target="_blank" rel="noreferrer">{o.name}</a>
|
||||||
|
</li>)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection">
|
||||||
|
<h2>{__('FAQ', 'gepafin')}</h2>
|
||||||
|
<Accordion>
|
||||||
|
{data.faq.map((o, i) => <AccordionTab key={i} header={o.question}>
|
||||||
|
<p>
|
||||||
|
{o.answer}
|
||||||
|
</p>
|
||||||
|
</AccordionTab>)}
|
||||||
|
</Accordion>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection">
|
||||||
|
<h2>{__('Non hai trovato la risposta che cercavi?', 'gepafin')}</h2>
|
||||||
|
<div className="appForm__field">
|
||||||
|
<label htmlFor="newQuestion">{__('Fai una domanda', 'gepafin')}</label>
|
||||||
|
<InputTextarea
|
||||||
|
id="newQuestion"
|
||||||
|
rows={7}
|
||||||
|
value={newQuestion}
|
||||||
|
placeholder={__('Digita qui la tua domanda', 'gepafin')}
|
||||||
|
onChange={(e) => setNewQuestion(e.target.value)}
|
||||||
|
aria-describedby="newQuestion-help"/>
|
||||||
|
<small id="newQuestion-help">
|
||||||
|
{__('Riceverai una notifica quando ti risponderemo', 'gepafin')}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection">
|
||||||
|
<h2>{__('Download Documenti', 'gepafin')}</h2>
|
||||||
|
<div className="appPageSection__actions">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={scaricaBando}
|
||||||
|
label={__('Scarica Bando Completo', 'gepafin')}
|
||||||
|
icon="pi pi-download" iconPos="right"/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={scaricaModulistica}
|
||||||
|
label={__('Scarica Modulistica', 'gepafin')}
|
||||||
|
icon="pi pi-download" iconPos="right"/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
disabled={true}
|
||||||
|
onClick={submitQuestion}
|
||||||
|
label={__('Presenta Domanda', 'gepafin')}
|
||||||
|
icon="pi pi-save" iconPos="right"/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
disabled={true}
|
||||||
|
onClick={saveToFavourites}
|
||||||
|
label={__('Aggiungi a Preferiti', 'gepafin')}
|
||||||
|
icon="pi pi-heart" iconPos="left"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__withBorder">
|
||||||
|
<h2>{__('Contatti per Assistenza', 'gepafin')}</h2>
|
||||||
|
<div className="row rowContent">
|
||||||
|
<p>Email: bandi@gepafin.it</p>
|
||||||
|
<p>Telefono: +39 075 123 4567</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection__preview">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={closePreview}
|
||||||
|
label={__('Chiudi Anteprima', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
: <>
|
: <>
|
||||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||||
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
|
||||||
|
|||||||
@@ -11,17 +11,19 @@ import BandoEdit from './pages/BandoEdit';
|
|||||||
import BandoView from './pages/BandoView';
|
import BandoView from './pages/BandoView';
|
||||||
import BandoFormsEdit from './pages/BandoFormsEdit';
|
import BandoFormsEdit from './pages/BandoFormsEdit';
|
||||||
import BandoForms from './pages/BandoForms';
|
import BandoForms from './pages/BandoForms';
|
||||||
|
import BandoFormsPreview from './pages/BandoFormsPreview';
|
||||||
|
|
||||||
const routes = () => (
|
const routes = () => (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<ProtectedRoute/>}>
|
<Route element={<ProtectedRoute/>}>
|
||||||
<Route path="/" element={<DefaultLayout><Dashboard/></DefaultLayout>}/>
|
<Route path="/" element={<DefaultLayout><Dashboard/></DefaultLayout>}/>
|
||||||
<Route path="/bandi" element={<DefaultLayout><Bandi/></DefaultLayout>}/>
|
<Route path="/bandi" element={<DefaultLayout><Bandi/></DefaultLayout>}/>
|
||||||
<Route path="/bandi/preview/:id" element={<DefaultLayout><BandoView/></DefaultLayout>}/>
|
|
||||||
<Route path="/bandi/preview-evaluation/:id" element={<DefaultLayout><BandoView/></DefaultLayout>}/>
|
|
||||||
<Route path="/bandi/:id" element={<DefaultLayout><BandoEdit/></DefaultLayout>}/>
|
<Route path="/bandi/:id" element={<DefaultLayout><BandoEdit/></DefaultLayout>}/>
|
||||||
|
<Route path="/bandi/:id/preview" element={<DefaultLayout><BandoView/></DefaultLayout>}/>
|
||||||
|
<Route path="/bandi/:id/preview-evaluation" element={<DefaultLayout><BandoView/></DefaultLayout>}/>
|
||||||
<Route path="/bandi/:id/forms" element={<DefaultLayout><BandoForms/></DefaultLayout>}/>
|
<Route path="/bandi/:id/forms" element={<DefaultLayout><BandoForms/></DefaultLayout>}/>
|
||||||
<Route path="/bandi/:id/forms/:formId" element={<DefaultLayout><BandoFormsEdit/></DefaultLayout>}/>
|
<Route path="/bandi/:id/forms/:formId" element={<DefaultLayout><BandoFormsEdit/></DefaultLayout>}/>
|
||||||
|
<Route path="/bandi/:id/forms/:formId/preview" element={<DefaultLayout><BandoFormsPreview/></DefaultLayout>}/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/login" element={<Login/>}/>
|
<Route exact path="/login" element={<Login/>}/>
|
||||||
{/*<Route exact path="/forgot-password" element={<ForgotPassword/>}/>*/}
|
{/*<Route exact path="/forgot-password" element={<ForgotPassword/>}/>*/}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
|
import { head } from 'ramda';
|
||||||
|
|
||||||
export const actionsAlpha = (set, get, api) => ({
|
export const actionsAlpha = (set, get, api) => ({
|
||||||
setAsyncRequest: () => {
|
setAsyncRequest: () => {
|
||||||
@@ -19,5 +19,28 @@ export const actionsBeta = (set, get, api) => ({
|
|||||||
doLogout: () => {
|
doLogout: () => {
|
||||||
set.userData({});
|
set.userData({});
|
||||||
set.token('');
|
set.token('');
|
||||||
|
},
|
||||||
|
removeElement: (id) => {
|
||||||
|
const elements = get.formElements();
|
||||||
|
const newElements = elements.filter(o => o.id !== id);
|
||||||
|
set.formElements(newElements);
|
||||||
|
},
|
||||||
|
moveElement: (dragIndex, hoverIndex, item) => {
|
||||||
|
const prevFields = get.formElements();
|
||||||
|
if (dragIndex === -1) {
|
||||||
|
const configs = get.elementItems();
|
||||||
|
const itemCfg = head(configs.filter(o => o.id === item.dbId));
|
||||||
|
const newItem = {
|
||||||
|
...itemCfg,
|
||||||
|
id: item.id,
|
||||||
|
dbId: item.dbId
|
||||||
|
}
|
||||||
|
const newElements = prevFields.toSpliced(hoverIndex, 0, newItem);
|
||||||
|
set.formElements(newElements);
|
||||||
|
} else {
|
||||||
|
let newFields = prevFields.toSpliced(dragIndex, 1);
|
||||||
|
const newElements = newFields.toSpliced(hoverIndex, 0, prevFields[dragIndex]);
|
||||||
|
set.formElements(newElements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ const initialStore = {
|
|||||||
// bando form
|
// bando form
|
||||||
bandoFormErrors: {},
|
bandoFormErrors: {},
|
||||||
// form builder
|
// form builder
|
||||||
elements: [],
|
formId: '',
|
||||||
|
formLabel: '',
|
||||||
|
formElements: [],
|
||||||
elementItems: [],
|
elementItems: [],
|
||||||
activeElement: ''
|
activeElement: ''
|
||||||
}
|
}
|
||||||
|
|||||||
330
src/tempData.js
Normal file
330
src/tempData.js
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
export const bandoTest = {
|
||||||
|
"name": "Innovazione digitale 2024",
|
||||||
|
"confidi": false,
|
||||||
|
"descriptionShort": "Supporto alle PMI per progetti di digitalizzazione e innovazione tecnologica.",
|
||||||
|
"descriptionLong": "Il bando \"Innovazione Digitale 2024\" mira a sostenere le PMI nell'adozione di tecnologie digitali innovative. I progetti finanziabili includono l'implementazione di soluzioni di intelligenza artificiale, blockchain, IoT, e altre tecnologie avanzate che possono migliorare la competitività delle imprese.",
|
||||||
|
"documentationRequested": "Documentazione richiesta*",
|
||||||
|
"dates": [
|
||||||
|
"2024-08-27T22:00:00.000Z",
|
||||||
|
"2024-10-29T23:00:00.000Z"
|
||||||
|
],
|
||||||
|
"amount": 10000,
|
||||||
|
"amountMax": 2500,
|
||||||
|
"aimedTo": [
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"value": "PMI con sede in Umbria",
|
||||||
|
"status": "existing"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faq": [
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"question": "Question 1?",
|
||||||
|
"answer": "Lorem ipsum dolor",
|
||||||
|
"visible": true,
|
||||||
|
"status": "existing"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
status: 'draft',
|
||||||
|
id: 11,
|
||||||
|
createdDate: "2024-08-07T08:14:07.849Z",
|
||||||
|
updatedDate: "2024-08-07T08:14:07.849Z",
|
||||||
|
"documentation":[
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"name":"SCR-20240820-kiwn.pdf",
|
||||||
|
"filePath":"https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/SCR-20240820-kiwn.pdf",
|
||||||
|
"description":null,
|
||||||
|
"createdDate":"2024-08-26T06:51:11.800799252",
|
||||||
|
"updatedDate":"2024-08-26T06:51:11.800826092"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"criteria":[
|
||||||
|
{
|
||||||
|
"id":null,
|
||||||
|
"value":"Innovatività del progetto",
|
||||||
|
"status":"new",
|
||||||
|
"score":9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":null,
|
||||||
|
"value":"Impatto sulla competitività dell'azienda",
|
||||||
|
"status":"new",
|
||||||
|
"score":3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":null,
|
||||||
|
"value":"Sostenibilità economico-finanziaria",
|
||||||
|
"status":"new",
|
||||||
|
"score":5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"threshold":11,
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"name":"photo-1618245318763-a15156d6b23c.avif",
|
||||||
|
"filePath":"https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/photo-1618245318763-a15156d6b23c.avif",
|
||||||
|
"description":null,
|
||||||
|
"createdDate":"2024-08-26T07:28:16.954763338",
|
||||||
|
"updatedDate":"2024-08-26T07:28:16.954843237"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checklist":[
|
||||||
|
{
|
||||||
|
"id":null,
|
||||||
|
"value":"Innovatività del progetto",
|
||||||
|
"status":"new"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":null,
|
||||||
|
"value":"Some new check",
|
||||||
|
"status":"new"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":null,
|
||||||
|
"value":"Check #2",
|
||||||
|
"status":"new"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formData = {
|
||||||
|
id: 15,
|
||||||
|
label: 'La forma per Innovazione digitale 2024',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
"id": "aec5ee1885",
|
||||||
|
"name": "textinput",
|
||||||
|
"label": "Text Input",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"value": "Text input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "placeholder",
|
||||||
|
"value": "Placeholder text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": {
|
||||||
|
"isRequired": false,
|
||||||
|
"minLength": null,
|
||||||
|
"maxLength": null,
|
||||||
|
"pattern": null,
|
||||||
|
"custom": null
|
||||||
|
},
|
||||||
|
"dbId": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "a730f1f4d0",
|
||||||
|
"name": "textarea",
|
||||||
|
"label": "Text Area",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"value": "Text area"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "placeholder",
|
||||||
|
"value": "Placeholder text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": {
|
||||||
|
"isRequired": false,
|
||||||
|
"minLength": null,
|
||||||
|
"maxLength": null,
|
||||||
|
"pattern": null,
|
||||||
|
"custom": null
|
||||||
|
},
|
||||||
|
"dbId": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aa8746a7c3",
|
||||||
|
"name": "textinput",
|
||||||
|
"label": "P.IVA",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"value": "P.IVA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "placeholder",
|
||||||
|
"value": "Insert p.iva number"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": {
|
||||||
|
"isRequired": true,
|
||||||
|
"minLength": null,
|
||||||
|
"maxLength": null,
|
||||||
|
"pattern": null,
|
||||||
|
"custom": "isValidVAT"
|
||||||
|
},
|
||||||
|
"dbId": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ae3dde17cd",
|
||||||
|
"name": "radio",
|
||||||
|
"label": "Radio Input",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"value": "Radio input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "options",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"name": "opt1",
|
||||||
|
"label": "Opt1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": {
|
||||||
|
"isRequired": false,
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"custom": null
|
||||||
|
},
|
||||||
|
"dbId": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "abf838016f",
|
||||||
|
"name": "textinput",
|
||||||
|
"label": "Number Input",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"value": "Number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "placeholder",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": {
|
||||||
|
"isRequired": false,
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": null,
|
||||||
|
"custom": null
|
||||||
|
},
|
||||||
|
"dbId": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
export const elementItems = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'textinput',
|
||||||
|
label: 'Text Input',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Text input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "placeholder",
|
||||||
|
value: "Placeholder text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: false,
|
||||||
|
minLength: null,
|
||||||
|
maxLength: null,
|
||||||
|
pattern: null,
|
||||||
|
custom: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'textarea',
|
||||||
|
label: 'Text Area',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Text area"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "placeholder",
|
||||||
|
value: "Placeholder text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: false,
|
||||||
|
minLength: null,
|
||||||
|
maxLength: null,
|
||||||
|
pattern: null,
|
||||||
|
custom: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'textinput',
|
||||||
|
label: 'Number Input',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "placeholder",
|
||||||
|
value: ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: false,
|
||||||
|
min: null,
|
||||||
|
max: null,
|
||||||
|
pattern: null,
|
||||||
|
custom: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: 'textinput',
|
||||||
|
label: 'P.IVA',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "P.IVA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "placeholder",
|
||||||
|
value: "Insert p.iva number"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: true,
|
||||||
|
minLength: null,
|
||||||
|
maxLength: null,
|
||||||
|
pattern: null,
|
||||||
|
custom: 'isValidVAT'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: 'radio',
|
||||||
|
label: 'Radio Input',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Radio input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "options",
|
||||||
|
value: [
|
||||||
|
{ name: "opt1", label: "Opt1" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: false,
|
||||||
|
min: null,
|
||||||
|
max: null,
|
||||||
|
custom: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -4000,6 +4000,11 @@ deep-is@^0.1.3, deep-is@~0.1.3:
|
|||||||
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
|
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
|
||||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||||
|
|
||||||
|
deep-object-diff@^1.1.9:
|
||||||
|
version "1.1.9"
|
||||||
|
resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz"
|
||||||
|
integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==
|
||||||
|
|
||||||
deepmerge@^4.2.2, deepmerge@^4.3.0:
|
deepmerge@^4.2.2, deepmerge@^4.3.0:
|
||||||
version "4.3.1"
|
version "4.3.1"
|
||||||
resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz"
|
resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user