- saving progress;

This commit is contained in:
Vitalii Kiiko
2024-09-02 17:15:43 +02:00
parent d634e425e5
commit c15360faf0
41 changed files with 1531 additions and 356 deletions

View File

@@ -34,7 +34,7 @@ const DatepickerRange = ({
<Calendar id={field.name}
value={field.value}
onChange={field.onChange}
dateFormat="dd/mm/yy"
mask="99/99/9999"
showIcon
minDate={minDate}

View File

@@ -21,9 +21,11 @@ const Fileupload = ({
doctype = 'images',
emptyText = __('Trascina qui il tuo file', 'gepafin'),
chooseLabel = __('Aggiungi immagine', 'gepafin'),
multiple = false
multiple = false,
callId = 0
}) => {
const [stateFieldData, setStateFieldData] = useState([]);
const [acceptFormats, setAcceptFormats] = useState('');
const inputRef = useRef();
const customBase64Uploader = (event) => {
@@ -31,14 +33,10 @@ const Fileupload = ({
for (const file of event.files) {
formData.append('file', file)
}
/*for (const pair of formData.entries()) {
console.log(pair[0], pair[1]);
}*/
FileUploadService.uploadFile(formData, callback, errorCallback, [['documentType', doctype.toUpperCase()]]);
FileUploadService.uploadFile(callId, formData, callback, errorCallback, [['documentType', doctype.toUpperCase()]]);
};
const callback = (data) => {
console.log('data', data);
if (data.status === 'SUCCESS') {
setStateFieldData(data.data);
const files = inputRef.current.getFiles();
@@ -86,7 +84,6 @@ const Fileupload = ({
setStateFieldData(prevState => {
const newFiles = prevState.filter(o => o.id !== id);
inputRef.current.setUploadedFiles(newFiles);
console.log('newFiles', newFiles);
return newFiles;
});
}
@@ -96,39 +93,61 @@ const Fileupload = ({
console.log('err', err);
}
const onBeforeDrop = (e) => {
return validateFileInputType(e.dataTransfer.files);
}
const validateFileInputType = ( files ) => {
const MIMEtype = new RegExp( acceptFormats );
return Array.prototype.every.call( files, function passesAcceptedFormat( file ){
return MIMEtype.test( file.type );
} );
}
useEffect(() => {
setStateFieldData(defaultValue);
register(fieldName, config)
}, []);
useEffect(() => {
// eslint-disable-next-line no-useless-escape
setAcceptFormats(accept.replace( /\*/g, '.\*' ).replace( /,/g, '|' ));
}, [accept]);
useEffect(() => {
inputRef.current.setUploadedFiles(stateFieldData);
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
}, [stateFieldData])
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
</label>
<FileUpload
ref={inputRef}
id={fieldName}
name={fieldName}
url={'/document/uploadFile'}
multiple={multiple}
accept={accept}
maxFileSize={1000000}
emptyTemplate={<p>{emptyText}</p>}
chooseLabel={chooseLabel}
cancelLabel={__('Cancella', 'gepafin')}
uploadLabel={__('Carica', 'gepafin')}
className={classNames({ 'p-invalid': errors[fieldName] })}
itemTemplate={itemTemplate}
customUpload
uploadHandler={customBase64Uploader}/>
{infoText ? <small>{infoText}</small> : null}
</>)
callId && callId !== 0
? <>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{acceptFormats ? ' (' + acceptFormats.split('|').join(', ') + ')' : null}
</label>
<FileUpload
ref={inputRef}
id={fieldName}
name={fieldName}
url={'/document/uploadFile'}
multiple={multiple}
accept={accept}
maxFileSize={1000000}
emptyTemplate={<p>{emptyText}</p>}
chooseLabel={chooseLabel}
cancelLabel={__('Cancella', 'gepafin')}
uploadLabel={__('Carica', 'gepafin')}
className={classNames({ 'p-invalid': errors[fieldName] })}
itemTemplate={itemTemplate}
customUpload
onBeforeDrop={onBeforeDrop}
uploadHandler={customBase64Uploader}/>
{infoText ? <small>{infoText}</small> : null}
</>
: null
)
}
export default Fileupload;

View File

@@ -1,7 +1,7 @@
import React, { useRef, useEffect, useState } from 'react';
import React, { useRef, useEffect, useState, useCallback } from 'react';
import { classNames } from 'primereact/utils';
import { __ } from '@wordpress/i18n';
import { isEmpty } from 'ramda';
import { head, isNil, pluck } from 'ramda';
// components
import { InputText } from 'primereact/inputtext';
@@ -22,19 +22,20 @@ const FormFieldRepeater = ({
}) => {
const forMenu = useRef(null);
const [stateFieldData, setStateFieldData] = useState([]);
const [stateOptionsData, setStateOptionsData] = useState([]);
const menuItems = [
{
type: 'existing',
label: __('Esistente', 'gepafin'),
command: (data) => {
setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]);
setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: 0 }]);
}
},
{
type: 'new',
label: __('Nuovo', 'gepafin'),
command: (data) => {
setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]);
setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: null }]);
}
}
]
@@ -45,14 +46,14 @@ const FormFieldRepeater = ({
}
const selectItem = (e, index) => {
const newData = stateFieldData.map((o, i) => {
if (i === index) {
o.value = e.value;
o.id = e.id;
}
return o;
})
setStateFieldData(newData);
const targetedOption = head(stateOptionsData.filter(o => o.value === e.value));
if (targetedOption) {
const newData = stateFieldData.map((o, i) => {
return i === index ? targetedOption : o;
})
setStateFieldData(newData);
}
}
const onInputChange = (e, index) => {
@@ -67,24 +68,30 @@ const FormFieldRepeater = ({
}
const properField = (item, i) => {
return item.status === 'new'
? <InputText value={item.value} onInput={(e) => onInputChange(e, i)}/>
: <Dropdown value={item.value}
return !isNil(item.lookUpDataId)
? <Dropdown value={item.value}
onChange={(e) => selectItem(e, i)}
optionDisabled={(opt) => usedExistingValues.includes(opt.value)}
options={options} optionLabel="value"/>
optionDisabled={(opt) => usedExistingValues().includes(opt.value)}
options={stateOptionsData}
optionLabel="value"/>
: <InputText value={item.value} onInput={(e) => onInputChange(e, i)}/>
}
const usedExistingValues = stateFieldData
.filter(o => o.status === 'existing')
.map(o => o.value);
const usedExistingValues = useCallback(() => {
return stateFieldData
.filter(o => o.lookUpDataId > 0)
.map(o => o.value)
}, [stateFieldData]);
useEffect(() => {
const storeFieldData = data[fieldName] ?? [];
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }));
setStateFieldData(newData);
setStateFieldData(storeFieldData);
register(fieldName, config);
}, [])
}, []);
useEffect(() => {
setStateOptionsData([...options]);
}, [options]);
useEffect(() => {
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
@@ -100,7 +107,7 @@ const FormFieldRepeater = ({
{properField(o, i)}
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/>
</div>
{o.status === 'new' && infoText ? <small>{infoText}</small> : null}
{isNil(o.lookUpDataId) && infoText ? <small>{infoText}</small> : null}
</div>)}
<Menu model={menuItems} popup ref={forMenu} id="aimedForMenu"/>
<Button type="button" iconPos="right" label={__('Aggiungi', 'gepafin')}

View File

@@ -1,7 +1,7 @@
import React, { useRef, useEffect, useState } from 'react';
import React, { useRef, useEffect, useState, useCallback } from 'react';
import { classNames } from 'primereact/utils';
import { __ } from '@wordpress/i18n';
import { head } from 'ramda';
import { head, isNil, pluck } from 'ramda';
// components
import { InputText } from 'primereact/inputtext';
@@ -23,20 +23,21 @@ const FormFieldRepeaterCriteria = ({
}) => {
const forMenu = useRef(null);
const [stateFieldData, setStateFieldData] = useState([]);
const [stateOptionsData, setStateOptionsData] = useState([]);
const [threshold, setThreshold] = useState(0);
const menuItems = [
{
type: 'existing',
label: __('Esistente', 'gepafin'),
command: (data) => {
setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]);
setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: 0 }]);
}
},
{
type: 'new',
label: __('Nuovo', 'gepafin'),
command: (data) => {
setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]);
setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: null }]);
}
}
]
@@ -47,17 +48,12 @@ const FormFieldRepeaterCriteria = ({
}
const selectItem = (e, index) => {
const targetedOption = head(options.filter(o => o.value === e.value));
const targetedOption = head(stateOptionsData.filter(o => o.value === e.value));
if (targetedOption) {
const newData = stateFieldData.map((o, i) => {
if (i === index) {
o.value = targetedOption.value;
o.score = targetedOption.score;
o.id = targetedOption.id;
}
return o;
});
console.log('newData', newData)
return i === index ? targetedOption : o;
})
setStateFieldData(newData);
}
}
@@ -78,32 +74,38 @@ const FormFieldRepeaterCriteria = ({
}
const properField = (item, i) => {
return item.status === 'new'
? <InputText value={item.value} onInput={(e) => onInputChange(e.target.value, i, 'value')}/>
: <Dropdown value={item.value}
return !isNil(item.lookUpDataId)
? <Dropdown value={item.value}
onChange={(e) => selectItem(e, i)}
optionDisabled={(opt) => usedExistingValues.includes(opt.value)}
options={options} optionLabel="value"/>
optionDisabled={(opt) => usedExistingValues().includes(opt.value)}
options={stateOptionsData} optionLabel="value"/>
: <InputText value={item.value} onInput={(e) => onInputChange(e.target.value, i, 'value')}/>
}
const usedExistingValues = stateFieldData
.filter(o => o.status === 'existing')
.map(o => o.value);
const usedExistingValues = useCallback(() => {
return stateFieldData
.filter(o => o.lookUpDataId > 0)
.map(o => o.value)
}, [stateFieldData]);
useEffect(() => {
const storeFieldData = data[fieldName] ?? [];
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }));
setStateFieldData(newData);
setStateFieldData(storeFieldData);
setStateOptionsData([...options, ...storeFieldData]);
setThreshold(data['threshold'])
register(fieldName, config)
register('threshold', {
required: __('È obbligatorio', 'gepafin')
})
}, [])
}, []);
useEffect(() => {
setStateOptionsData([...options]);
}, [options]);
useEffect(() => {
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
}, [stateFieldData])
}, [stateFieldData]);
return (
<div className={classNames(['appForm__field', 'formfieldrepeater'])}>
@@ -126,7 +128,7 @@ const FormFieldRepeaterCriteria = ({
{properField(o, i)}
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/>
</div>
{o.status === 'new' && infoText ? <small>{infoText}</small> : null}
{isNil(o.lookUpDataId) && infoText ? <small>{infoText}</small> : null}
</div>
<div>
<label htmlFor="criterionMin">{__('Punteggio', 'gepafin')}</label>

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useCallback } from 'react';
import { classNames } from 'primereact/utils';
import { __ } from '@wordpress/i18n';
import { isEmpty } from 'ramda';
import { head } from 'ramda';
// components
import { Button } from 'primereact/button';
@@ -20,11 +20,10 @@ const FormFieldRepeaterFaq = ({
errors,
register,
label,
config = {},
setError,
clearErrors
config = {}
}) => {
const [stateFieldData, setStateFieldData] = useState([]);
const [stateOptionsData, setStateOptionsData] = useState([]);
const [question, setQuestion] = useState('');
const [answer, setAnswer] = useState('');
const [editDataIndex, setEditDataIndex] = useState(null);
@@ -36,12 +35,15 @@ const FormFieldRepeaterFaq = ({
}
const selectItem = (e) => {
const chosen = {...e.value};
setStateFieldData([...stateFieldData, chosen]);
const targetedOption = head(stateOptionsData.filter(o => o.question === e.value));
if (targetedOption) {
setStateFieldData([...stateFieldData, targetedOption]);
}
}
const addNewItem = () => {
const newItem = { id: 0, status: 'new', question: '', answer: '', visible: true };
const newItem = { id: null, lookUpDataId: null, question: '', response: '', visible: true };
setStateFieldData([...stateFieldData, newItem]);
}
@@ -49,7 +51,7 @@ const FormFieldRepeaterFaq = ({
e.preventDefault();
const newData = stateFieldData.map((o, i) => {
if (i === index) {
o.visible = e.value;
o.isVisible = e.value;
}
return o;
});
@@ -59,7 +61,7 @@ const FormFieldRepeaterFaq = ({
const editItem = (e, index) => {
e.stopPropagation();
setQuestion(stateFieldData[index].question);
setAnswer(stateFieldData[index].answer);
setAnswer(stateFieldData[index].response);
setEditDataIndex(index);
setIsVisibleEditDialog(true);
}
@@ -83,7 +85,7 @@ const FormFieldRepeaterFaq = ({
const newData = stateFieldData.map((o, i) => {
if (i === editDataIndex) {
o.question = question;
o.answer = answer;
o.response = answer;
return o
} else {
return o;
@@ -102,25 +104,31 @@ const FormFieldRepeaterFaq = ({
const footerEditDialog = () => {
return <div>
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideEditDialog} outlined />
<Button type="button" label={__('Salva', 'gepafin')} onClick={saveEditDialog} />
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideEditDialog} outlined/>
<Button type="button" label={__('Salva', 'gepafin')} onClick={saveEditDialog}/>
</div>
}
const usedExistingValues = stateFieldData
.filter(o => o.status === 'existing')
.map(o => o.question);
const usedExistingValues = useCallback(() => {
return stateFieldData
.filter(o => o.lookUpDataId)
.map(o => o.question)
}, [stateFieldData]);
useEffect(() => {
const storeFieldData = data[fieldName] ?? [];
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }))
setStateFieldData(newData);
setStateFieldData(storeFieldData);
setStateOptionsData([...options, ...storeFieldData]);
register(fieldName, config)
}, [])
}, []);
useEffect(() => {
setStateOptionsData([...options]);
}, [options]);
useEffect(() => {
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
}, [stateFieldData])
}, [stateFieldData]);
return (
<div className={classNames(['appForm__field', 'formfieldrepeater'])}>
@@ -131,8 +139,9 @@ const FormFieldRepeaterFaq = ({
<Button type="button" iconPos="left" label={__('Aggiungi', 'gepafin')}
icon="pi pi-plus" onClick={addNewItem}/>
<Dropdown onChange={(e) => selectItem(e)}
optionDisabled={(opt) => usedExistingValues.includes(opt.value)}
options={options} optionLabel="question"/>
optionDisabled={(opt) => usedExistingValues().includes(opt.value)}
options={stateOptionsData}
optionLabel="question"/>
</div>
<Accordion activeIndex={0}>
{stateFieldData.map((o, i) => <AccordionTab key={i}
@@ -144,7 +153,7 @@ const FormFieldRepeaterFaq = ({
offIcon="pi pi-eye-slash"
onLabel=""
offLabel=""
checked={o.visible}
checked={o.isVisible}
onChange={(e) => setChecked(e, i)}/>
{o.question}
</div>
@@ -160,7 +169,7 @@ const FormFieldRepeaterFaq = ({
}
>
<p className="m-0">
{o.answer}
{o.response}
</p>
</AccordionTab>)}
</Accordion>
@@ -170,14 +179,18 @@ const FormFieldRepeaterFaq = ({
footer={footerEditDialog}
style={{ maxWidth: '50rem' }}
onHide={hideEditDialog}>
<div className="appPage__spacer"></div>
<div className="appForm__field">
<label>{__('Titolo FAQ', 'gepafin')}</label>
<InputText value={question} onChange={(e) => onChangeEditItem(e.target.value, 'question')}/>
</div>
<div className="appForm__field">
<label>{__('Risposta', 'gepafin')}</label>
<InputTextarea value={answer} onChange={(e) => onChangeEditItem(e.target.value, 'answer')} rows={5} cols={30} />
<InputTextarea value={answer} onChange={(e) => onChangeEditItem(e.target.value, 'response')}
rows={5}
cols={30}/>
</div>
<div className="appPage__spacer"></div>
</Dialog>
</div>
)

View File

@@ -2,13 +2,14 @@ import React, { useRef } from 'react';
import { __ } from '@wordpress/i18n';
// store
import { storeSet } from '../../store';
import { storeSet, useTrackedStore } from '../../store';
// components
import { Menu } from 'primereact/menu';
import { Avatar } from 'primereact/avatar';
const TopBarProfileMenu = ({ menuLeftRef }) => {
const userData = useTrackedStore().main.userData();
let items = [
{
@@ -17,8 +18,8 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
<div className="topBar__menuProfileItem">
<Avatar image="https://primefaces.org/cdn/primereact/images/avatar/amyelsner.png" shape="circle" />
<div className="userInfo">
<span className="userName">Mario Rossi</span>
<span className="userEmail">mario.rossi@example.com</span>
<span className="userName">{`${userData.firstName} ${userData.lastName}`}</span>
<span className="userEmail">{userData.email}</span>
</div>
</div>
);

View File

@@ -5,7 +5,7 @@ import equal from 'fast-deep-equal';
// tools
const UnsavedChangesDetector = ({ initialData, getValuesFn }) => {
const [initial] = useState(initialData);
const [initial, setInitial] = useState(initialData);
const warnIfUnsavedChanges = useCallback((event) => {
const updatedData = getValuesFn();
@@ -16,7 +16,11 @@ const UnsavedChangesDetector = ({ initialData, getValuesFn }) => {
}
return event.returnValue;
}, [initial])
}, [initialData]);
useEffect(() => {
setInitial(initialData);
}, [initialData])
useEffect(() => {
window.addEventListener('beforeunload', (e) => {