- added login page;
- added file upload; - added faq item edit modal;
This commit is contained in:
@@ -9,7 +9,7 @@ const Datepicker = ({
|
||||
label,
|
||||
control,
|
||||
errors,
|
||||
defaultValue,
|
||||
defaultValue = [],
|
||||
config = {},
|
||||
infoText = null,
|
||||
minDate = null,
|
||||
@@ -27,7 +27,7 @@ const Datepicker = ({
|
||||
rules={config}
|
||||
render={({ field, fieldState }) => (
|
||||
<Calendar id={field.name}
|
||||
value={field.value}
|
||||
value={field.value ?? []}
|
||||
onChange={(e) => field.onChange(e.value)}
|
||||
dateFormat="dd/mm/yy"
|
||||
mask="99/99/9999"
|
||||
|
||||
@@ -11,13 +11,15 @@ const DatepickerRange = ({
|
||||
label,
|
||||
control,
|
||||
errors,
|
||||
defaultValue,
|
||||
defaultValue = [],
|
||||
config = {},
|
||||
infoText = null,
|
||||
minDate = null,
|
||||
maxDate = null
|
||||
}) => {
|
||||
const datesDefaultValue = !isNil(defaultValue) && !isEmpty(defaultValue) && defaultValue.length ? defaultValue.map(v => new Date(v)) : [];
|
||||
const datesDefaultValue = !isNil(defaultValue) && defaultValue.length
|
||||
? defaultValue.map(v => new Date(v))
|
||||
: [];
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
@@ -31,12 +33,8 @@ const DatepickerRange = ({
|
||||
render={({ field, fieldState }) => (
|
||||
<Calendar id={field.name}
|
||||
value={field.value}
|
||||
onChange={(e) => {
|
||||
const formattedValues = e.value.map(d => d ? d.toISOString() : d);
|
||||
console.log('formattedValues', formattedValues);
|
||||
field.onChange(formattedValues)
|
||||
}}
|
||||
dateFormat="dd/mm/yy"
|
||||
onChange={field.onChange}
|
||||
|
||||
mask="99/99/9999"
|
||||
showIcon
|
||||
minDate={minDate}
|
||||
@@ -44,6 +42,7 @@ const DatepickerRange = ({
|
||||
selectionMode="range"
|
||||
readOnlyInput
|
||||
hideOnRangeSelection
|
||||
showButtonBar
|
||||
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
||||
)}/>
|
||||
{infoText ? <small>{infoText}</small> : null}
|
||||
|
||||
@@ -1,50 +1,133 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import FileUploadService from '../../../../service/file-upload-service';
|
||||
|
||||
import { FileUpload } from 'primereact/fileupload';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Button } from 'primereact/button';
|
||||
|
||||
const Fileupload = ({
|
||||
fieldName,
|
||||
setDataFn,
|
||||
label,
|
||||
control,
|
||||
errors,
|
||||
defaultValue,
|
||||
register,
|
||||
defaultValue = [],
|
||||
config = {},
|
||||
infoText = null,
|
||||
accept = 'image/*',
|
||||
api = '/api/upload',
|
||||
doctype = 'images',
|
||||
emptyText = __('Trascina qui il tuo file', 'gepafin'),
|
||||
chooseLabel = __('Aggiungi immagine', 'gepafin'),
|
||||
multiple = false
|
||||
multiple = false
|
||||
}) => {
|
||||
const [stateFieldData, setStateFieldData] = useState([]);
|
||||
const inputRef = useRef();
|
||||
|
||||
const customBase64Uploader = (event) => {
|
||||
const formData = new FormData()
|
||||
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()]]);
|
||||
};
|
||||
|
||||
const callback = (data) => {
|
||||
console.log('data', data);
|
||||
if (data.status === 'SUCCESS') {
|
||||
setStateFieldData(data.data);
|
||||
const files = inputRef.current.getFiles();
|
||||
inputRef.current.setUploadedFiles(files);
|
||||
inputRef.current.setFiles([]);
|
||||
}
|
||||
}
|
||||
|
||||
const errorCallback = (err) => {
|
||||
console.log('err', err);
|
||||
}
|
||||
|
||||
const itemTemplate = (file) => {
|
||||
return (
|
||||
<div className="appForm__fileUploadItem">
|
||||
<span className="appForm__fileUploadItemName">
|
||||
{file.name}
|
||||
</span>
|
||||
{file.id ? <Tag value={__('Caricato', 'gepafin')} severity="success"></Tag> : null}
|
||||
{!file.id ? <Tag value={__('In attesa', 'gepafin')} severity="warning"></Tag> : null}
|
||||
<Button icon="pi pi-times" severity="danger"
|
||||
aria-label={__('Anulla', 'gepafin')}
|
||||
onClick={() => onTemplateRemove(file)}/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const onTemplateRemove = (file) => {
|
||||
if (file.id) {
|
||||
FileUploadService.deleteFile(
|
||||
{},
|
||||
(data) => dCallback(data, file.id),
|
||||
dErrorCallback,
|
||||
[['id', file.id]]
|
||||
);
|
||||
} else {
|
||||
const files = inputRef.current.getFiles()
|
||||
const newFiles = files.filter(o => o.lastModified !== file.lastModified && o.name !== file.name);
|
||||
inputRef.current.setFiles(newFiles);
|
||||
}
|
||||
}
|
||||
|
||||
const dCallback = (data, id) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setStateFieldData(prevState => {
|
||||
const newFiles = prevState.filter(o => o.id !== id);
|
||||
inputRef.current.setUploadedFiles(newFiles);
|
||||
console.log('newFiles', newFiles);
|
||||
return newFiles;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const dErrorCallback = (err) => {
|
||||
console.log('err', err);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setStateFieldData(defaultValue);
|
||||
register(fieldName, config)
|
||||
}, []);
|
||||
|
||||
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>
|
||||
<Controller
|
||||
<FileUpload
|
||||
ref={inputRef}
|
||||
id={fieldName}
|
||||
name={fieldName}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
rules={config}
|
||||
render={({ field, fieldState }) => (
|
||||
<FileUpload
|
||||
id={field.name}
|
||||
name={`${field.name}[]`}
|
||||
url={api}
|
||||
multiple={multiple}
|
||||
accept={accept}
|
||||
maxFileSize={1000000}
|
||||
emptyTemplate={<p>{emptyText}</p>}
|
||||
chooseLabel={chooseLabel}
|
||||
cancelLabel={__('Cancella', 'gepafin')}
|
||||
uploadLabel={__('Carica', 'gepafin')}
|
||||
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
||||
)}/>
|
||||
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}
|
||||
{defaultValue ? <p>Uploaded:</p> : null}
|
||||
{defaultValue}
|
||||
</>)
|
||||
}
|
||||
|
||||
|
||||
49
src/components/FormField/components/Switch/index.js
Normal file
49
src/components/FormField/components/Switch/index.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { isNil, isEmpty } from 'ramda';
|
||||
|
||||
// components
|
||||
import { InputSwitch } from 'primereact/inputswitch';
|
||||
|
||||
const Switch = ({
|
||||
fieldName,
|
||||
label,
|
||||
control,
|
||||
errors,
|
||||
defaultValue,
|
||||
config = {},
|
||||
infoText = null,
|
||||
onLabel = '',
|
||||
offLabel = ''
|
||||
}) => {
|
||||
const properValue = !isNil(defaultValue) && !isEmpty(defaultValue) && defaultValue !== false;
|
||||
|
||||
const input = <Controller
|
||||
name={fieldName}
|
||||
control={control}
|
||||
defaultValue={properValue}
|
||||
rules={config}
|
||||
render={({ field, fieldState }) => (
|
||||
<InputSwitch
|
||||
checked={field.value}
|
||||
onChange={(e) => field.onChange(e.value)}
|
||||
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
||||
)}/>
|
||||
return (
|
||||
<>
|
||||
<div className="appForm__row">
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] }, 'mr-8')}>
|
||||
{label}{config.required ? '*' : null}
|
||||
</label>
|
||||
<div className="appForm__row">
|
||||
{offLabel ? <span>{offLabel}</span> : null}
|
||||
{input}
|
||||
{onLabel ? <span>{onLabel}</span> : null}
|
||||
</div>
|
||||
</div>
|
||||
{infoText ? <small>{infoText}</small> : null}
|
||||
</>)
|
||||
}
|
||||
|
||||
export default Switch;
|
||||
@@ -12,7 +12,9 @@ const TextInput = ({
|
||||
config = {},
|
||||
infoText = null,
|
||||
inputgroup = false,
|
||||
icon = null
|
||||
icon = null,
|
||||
placeholder = '',
|
||||
inputtype = 'text'
|
||||
}) => {
|
||||
const input = <Controller
|
||||
name={fieldName}
|
||||
@@ -22,6 +24,8 @@ const TextInput = ({
|
||||
render={({ field, fieldState }) => (
|
||||
<InputText id={field.name}
|
||||
{...field}
|
||||
type={inputtype}
|
||||
placeholder={placeholder}
|
||||
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
||||
)}/>
|
||||
return (
|
||||
|
||||
@@ -9,6 +9,7 @@ import Datepicker from './components/Datepicker';
|
||||
import DatepickerRange from './components/DatepickerRange';
|
||||
import Fileupload from './components/Fileupload';
|
||||
import NumberInput from './components/NumberInput';
|
||||
import Switch from './components/Switch';
|
||||
|
||||
const FormField = (props) => {
|
||||
const fields = {
|
||||
@@ -17,7 +18,8 @@ const FormField = (props) => {
|
||||
datepicker: Datepicker,
|
||||
datepickerrange: DatepickerRange,
|
||||
fileupload: Fileupload,
|
||||
numberinput: NumberInput
|
||||
numberinput: NumberInput,
|
||||
switch: Switch
|
||||
}
|
||||
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { isEmpty } from 'ramda';
|
||||
|
||||
// components
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Menu } from 'primereact/menu';
|
||||
@@ -14,7 +17,8 @@ const FormFieldRepeater = ({
|
||||
errors,
|
||||
register,
|
||||
label,
|
||||
infoText
|
||||
infoText,
|
||||
config = {}
|
||||
}) => {
|
||||
const forMenu = useRef(null);
|
||||
const [stateFieldData, setStateFieldData] = useState([]);
|
||||
@@ -23,14 +27,14 @@ const FormFieldRepeater = ({
|
||||
type: 'existing',
|
||||
label: __('Esistente', 'gepafin'),
|
||||
command: (data) => {
|
||||
setStateFieldData([...stateFieldData, {id: null, value: '', status: data.item.type}]);
|
||||
setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]);
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'new',
|
||||
label: __('Nuovo', 'gepafin'),
|
||||
command: (data) => {
|
||||
setStateFieldData([...stateFieldData, {id: null, value: '', status: data.item.type}]);
|
||||
setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]);
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -76,13 +80,13 @@ const FormFieldRepeater = ({
|
||||
|
||||
useEffect(() => {
|
||||
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);
|
||||
register(fieldName)
|
||||
register(fieldName, config);
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setDataFn(fieldName, [...stateFieldData]);
|
||||
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
|
||||
}, [stateFieldData])
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,7 +18,8 @@ const FormFieldRepeaterCriteria = ({
|
||||
errors,
|
||||
register,
|
||||
label,
|
||||
infoText
|
||||
infoText,
|
||||
config = {}
|
||||
}) => {
|
||||
const forMenu = useRef(null);
|
||||
const [stateFieldData, setStateFieldData] = useState([]);
|
||||
@@ -72,6 +73,7 @@ const FormFieldRepeaterCriteria = ({
|
||||
|
||||
const onThresholdChange = (value) => {
|
||||
setThreshold(value);
|
||||
setDataFn('threshold', value, { shouldValidate: true });
|
||||
}
|
||||
|
||||
const properField = (item, i) => {
|
||||
@@ -92,16 +94,19 @@ const FormFieldRepeaterCriteria = ({
|
||||
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }))
|
||||
setStateFieldData(newData);
|
||||
setThreshold(data['threshold'])
|
||||
register(fieldName)
|
||||
register(fieldName, config)
|
||||
register('threshold', {
|
||||
required: __('È obbligatorio', 'gepafin')
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setDataFn(fieldName, [...stateFieldData]);
|
||||
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
|
||||
}, [stateFieldData])
|
||||
|
||||
return (
|
||||
<div className={classNames(['appForm__field', 'formfieldrepeater'])}>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] || errors['threshold'] })}>
|
||||
{label}
|
||||
</label>
|
||||
<div className="appForm__oneCol">
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { isEmpty } from 'ramda';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { Accordion, AccordionTab } from 'primereact/accordion';
|
||||
import { ToggleButton } from 'primereact/togglebutton';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
|
||||
const FormFieldRepeaterFaq = ({
|
||||
data,
|
||||
@@ -15,17 +20,24 @@ const FormFieldRepeaterFaq = ({
|
||||
errors,
|
||||
register,
|
||||
label,
|
||||
infoText
|
||||
config = {},
|
||||
setError,
|
||||
clearErrors
|
||||
}) => {
|
||||
const [stateFieldData, setStateFieldData] = useState([]);
|
||||
const [question, setQuestion] = useState('');
|
||||
const [answer, setAnswer] = useState('');
|
||||
const [editDataIndex, setEditDataIndex] = useState(null);
|
||||
const [isVisibleEditDialog, setIsVisibleEditDialog] = useState(false);
|
||||
|
||||
const removeItem = (index) => {
|
||||
const newData = stateFieldData.toSpliced(index, 1);
|
||||
setStateFieldData(newData);
|
||||
}
|
||||
|
||||
const selectItem = () => {
|
||||
setStateFieldData([...stateFieldData, { id: 0, status: 'new', question: '', answer: '', visible: true }]);
|
||||
const selectItem = (e) => {
|
||||
const chosen = {...e.value};
|
||||
setStateFieldData([...stateFieldData, chosen]);
|
||||
}
|
||||
|
||||
const onInputChange = (e, index) => {
|
||||
@@ -40,7 +52,8 @@ const FormFieldRepeaterFaq = ({
|
||||
}
|
||||
|
||||
const addNewItem = () => {
|
||||
|
||||
const newItem = { id: 0, status: 'new', question: '', answer: '', visible: true };
|
||||
setStateFieldData([...stateFieldData, newItem]);
|
||||
}
|
||||
|
||||
const setChecked = (e, index) => {
|
||||
@@ -56,7 +69,53 @@ const FormFieldRepeaterFaq = ({
|
||||
|
||||
const editItem = (e, index) => {
|
||||
e.stopPropagation();
|
||||
console.log('editItem')
|
||||
setQuestion(stateFieldData[index].question);
|
||||
setAnswer(stateFieldData[index].answer);
|
||||
setEditDataIndex(index);
|
||||
setIsVisibleEditDialog(true);
|
||||
}
|
||||
|
||||
const hideEditDialog = () => {
|
||||
setIsVisibleEditDialog(false);
|
||||
setQuestion('');
|
||||
setAnswer('');
|
||||
setEditDataIndex(null);
|
||||
}
|
||||
|
||||
const onChangeEditItem = (value, key) => {
|
||||
if (key === 'question') {
|
||||
setQuestion(value);
|
||||
} else {
|
||||
setAnswer(value)
|
||||
}
|
||||
}
|
||||
|
||||
const saveEditDialog = () => {
|
||||
const newData = stateFieldData.map((o, i) => {
|
||||
if (i === editDataIndex) {
|
||||
o.question = question;
|
||||
o.answer = answer;
|
||||
return o
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
});
|
||||
setStateFieldData(newData);
|
||||
setIsVisibleEditDialog(false);
|
||||
setQuestion('');
|
||||
setAnswer('');
|
||||
setEditDataIndex(null);
|
||||
}
|
||||
|
||||
const headerEditDialog = () => {
|
||||
return <span>{__('Aggiungi/modifica FAQ', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const footerEditDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideEditDialog} outlined />
|
||||
<Button type="button" label={__('Salva', 'gepafin')} onClick={saveEditDialog} />
|
||||
</div>
|
||||
}
|
||||
|
||||
const usedExistingValues = stateFieldData
|
||||
@@ -67,11 +126,11 @@ const FormFieldRepeaterFaq = ({
|
||||
const storeFieldData = data[fieldName] ?? [];
|
||||
const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' }))
|
||||
setStateFieldData(newData);
|
||||
register(fieldName)
|
||||
register(fieldName, config)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setDataFn(fieldName, [...stateFieldData]);
|
||||
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
|
||||
}, [stateFieldData])
|
||||
|
||||
return (
|
||||
@@ -102,7 +161,8 @@ const FormFieldRepeaterFaq = ({
|
||||
</div>
|
||||
<div className="appForm__faqTabItem">
|
||||
<Button icon="pi pi-pencil" severity="success"
|
||||
aria-label="Edit" onClick={(e) => editItem(e, i)}/>
|
||||
aria-label="Edit"
|
||||
onClick={(e) => editItem(e, i)}/>
|
||||
<Button icon="pi pi-times" severity="danger"
|
||||
aria-label="Cancel"
|
||||
onClick={() => removeItem(i)}/>
|
||||
@@ -115,6 +175,21 @@ const FormFieldRepeaterFaq = ({
|
||||
</p>
|
||||
</AccordionTab>)}
|
||||
</Accordion>
|
||||
<Dialog
|
||||
visible={isVisibleEditDialog}
|
||||
modal header={headerEditDialog}
|
||||
footer={footerEditDialog}
|
||||
style={{ maxWidth: '50rem' }}
|
||||
onHide={hideEditDialog}>
|
||||
<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} />
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
//Navigate,
|
||||
Outlet } from 'react-router-dom';
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../store';
|
||||
|
||||
// tools
|
||||
//import AuthenticationService from '../../service/authentication-service';
|
||||
import AuthenticationService from '../../service/authentication-service';
|
||||
|
||||
const ProtectedRoute = () => {
|
||||
// we need this to track existance of the token
|
||||
const token = useStore().main.token();
|
||||
|
||||
/*if (!AuthenticationService.wasLoggedIn()) {
|
||||
if (!AuthenticationService.wasLoggedIn()) {
|
||||
return (<Navigate to={'/login'} replace/>);
|
||||
}
|
||||
|
||||
@@ -18,10 +21,10 @@ const ProtectedRoute = () => {
|
||||
|
||||
if (!AuthenticationService.isLoggedIn()) {
|
||||
return (<Navigate to={'/login?redirectReason=auth_required'} replace/>);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*if (window.location.pathname === '/') {
|
||||
return (<Navigate to={'/dashboard'} replace/>);
|
||||
return (<Navigate to={'/'} replace/>);
|
||||
}*/
|
||||
|
||||
return <Outlet/>;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React, { useRef } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// store
|
||||
import { storeSet } from '../../store';
|
||||
|
||||
// components
|
||||
import { Menu } from 'primereact/menu';
|
||||
import { Avatar } from 'primereact/avatar';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
const TopBarProfileMenu = ({ menuLeftRef }) => {
|
||||
const toast = useRef();
|
||||
|
||||
let items = [
|
||||
{
|
||||
@@ -36,13 +37,12 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
|
||||
label: __('Logout', 'gepafin'),
|
||||
icon: 'pi pi-sign-out',
|
||||
command: () => {
|
||||
console.log('logout')
|
||||
storeSet.main.doLogout();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return <>
|
||||
<Toast ref={toast}/>
|
||||
<Menu model={items} popup ref={menuLeftRef} id="topBar_profileMenu" className="topBar__menuProfile"/>
|
||||
</>
|
||||
}
|
||||
|
||||
34
src/components/UnsavedChangesDetector/index.js
Normal file
34
src/components/UnsavedChangesDetector/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import equal from 'fast-deep-equal';
|
||||
|
||||
// tools
|
||||
|
||||
const UnsavedChangesDetector = ({ initialData, getValuesFn }) => {
|
||||
const [initial] = useState(initialData);
|
||||
|
||||
const warnIfUnsavedChanges = useCallback((event) => {
|
||||
const updatedData = getValuesFn()
|
||||
const isEqual = equal(initial, updatedData);
|
||||
|
||||
if (!isEqual) {
|
||||
event.returnValue = __('You have unsaved changes. If you proceed, they will be lost.', 'gepafin');
|
||||
}
|
||||
|
||||
return event.returnValue;
|
||||
}, [initial])
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('beforeunload', (e) => {
|
||||
warnIfUnsavedChanges(e);
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeunload', (e) => {
|
||||
warnIfUnsavedChanges(e);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
}
|
||||
|
||||
export default UnsavedChangesDetector;
|
||||
Reference in New Issue
Block a user