- styled asteriks sign;

- fixed issue with validation on registration page;
- fixed issue with inputnumber;
- fixed issue with editor field;;
- added editors for new faq item form;
- fixed displaying html as simple text;
- fixed saving company data after saving;
- added toast for edit bando form;
- improved edit forms form;
- fixed styles for various elements;
This commit is contained in:
Vitalii Kiiko
2024-10-04 11:31:47 +02:00
parent af52610b30
commit 7804a67fd2
36 changed files with 520 additions and 637 deletions

View File

@@ -65,7 +65,7 @@ const Checkboxes = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
{input}
{infoText ? <small>{infoText}</small> : null}

View File

@@ -20,7 +20,7 @@ const Datepicker = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
<Controller
name={fieldName}

View File

@@ -1,13 +1,16 @@
import React, { useEffect, useState, useRef } from 'react';
import { classNames } from 'primereact/utils';
import { head } from 'ramda'
import { __ } from '@wordpress/i18n';
import FileUploadService from '../../../../service/file-upload-service';
import { FileUpload } from 'primereact/fileupload';
import { __ } from '@wordpress/i18n';
import { Tag } from 'primereact/tag';
import { Button } from 'primereact/button';
import { mimeTypes } from '../../../../configData';
const Fileupload = ({
fieldName,
setDataFn,
@@ -17,7 +20,7 @@ const Fileupload = ({
defaultValue = [],
config = {},
infoText = null,
accept = 'image/*',
accept = ['image/*'],
doctype = 'images',
maxSize = 100000000,
emptyText = __('Trascina qui il tuo file', 'gepafin'),
@@ -119,6 +122,21 @@ const Fileupload = ({
});
}
const getPropeMimeLabels = (acceptFormats) => {
return acceptFormats
.map(v => {
const found = head(mimeTypes.filter(o => o.code === v));
let res = v;
if (found) {
res = found.name;
}
return res;
})
.join(', ');
}
useEffect(() => {
setStateFieldData(defaultValue);
register(fieldName, config)
@@ -126,7 +144,7 @@ const Fileupload = ({
useEffect(() => {
// eslint-disable-next-line no-useless-escape
setAcceptFormats(accept.replace(/\*/g, '.\*').replace(/,/g, '|'));
setAcceptFormats(accept.join(',').replace(/\*/g, '.\*').replace(/,/g, '|'));
}, [accept]);
useEffect(() => {
@@ -140,8 +158,8 @@ const Fileupload = ({
sourceId || sourceId === 0
? <>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{acceptFormats ? ' (' + acceptFormats.split('|').join(', ') + ')' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
{acceptFormats ? ' (' + getPropeMimeLabels(accept) + ')' : null}
</label>
<FileUpload
ref={inputRef}

View File

@@ -7,6 +7,8 @@ import FileUploadService from '../../../../service/file-upload-service';
import { FileUpload } from 'primereact/fileupload';
import { Tag } from 'primereact/tag';
import { Button } from 'primereact/button';
import { head } from 'ramda';
import { mimeTypes } from '../../../../configData';
const FileuploadAsync = ({
fieldName,
@@ -17,7 +19,7 @@ const FileuploadAsync = ({
defaultValue = [],
config = {},
infoText = null,
accept = 'image/*',
accept = ['image/*'],
doctype = 'images',
maxSize = 100000000,
emptyText = __('Trascina qui il tuo file', 'gepafin'),
@@ -121,6 +123,21 @@ const FileuploadAsync = ({
});
}
const getPropeMimeLabels = (acceptFormats) => {
return acceptFormats
.map(v => {
const found = head(mimeTypes.filter(o => o.code === v));
let res = v;
if (found) {
res = found.name;
}
return res;
})
.join(', ');
}
useEffect(() => {
setStateFieldData(defaultValue);
register(fieldName, config)
@@ -128,7 +145,7 @@ const FileuploadAsync = ({
useEffect(() => {
// eslint-disable-next-line no-useless-escape
setAcceptFormats(accept.replace(/\*/g, '.\*').replace(/,/g, '|'));
setAcceptFormats(accept.join(',').replace(/\*/g, '.\*').replace(/,/g, '|'));
}, [accept]);
useEffect(() => {
@@ -143,7 +160,7 @@ const FileuploadAsync = ({
? <>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{acceptFormats ? ' (' + acceptFormats.split('|').join(', ') + ')' : null}
{acceptFormats ? ' (' + getPropeMimeLabels(accept) + ')' : null}
</label>
<FileUpload
ref={inputRef}

View File

@@ -20,8 +20,9 @@ const NumberInput = ({
min,
max,
disabled = false,
useGrouping = true
useGrouping = false
}) => {
console.log('defaultValue', defaultValue);
const input = <Controller
name={fieldName}
control={control}
@@ -43,10 +44,10 @@ const NumberInput = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
{inputgroup
? <div className="p-inputgroup flex-1">
? <div className="p-inputgroup">
<span className="p-inputgroup-addon">
{icon}
</span>

View File

@@ -34,7 +34,7 @@ const Radio = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
{input}
{infoText ? <small>{infoText}</small> : null}

View File

@@ -36,10 +36,10 @@ const Select = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
{inputgroup
? <div className="p-inputgroup flex-1">
? <div className="p-inputgroup">
<span className="p-inputgroup-addon">
{icon}
</span>

View File

@@ -36,7 +36,7 @@ const Switch = ({
<>
<div className="appForm__row">
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] }, 'mr-8')}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
<div className="appForm__row">
{offLabel ? <span>{offLabel}</span> : null}

View File

@@ -0,0 +1,79 @@
import React from 'react';
import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
import { wrap } from 'object-path-immutable';
const RenderTable = ({ data, columns, setRowsFn }) => {
const table = useReactTable({
data,
columns,
defaultColumn: {
cell: ({ getValue, row: { index }, column: { id }, table }) => {
const initialValue = getValue();
const onBlur = (e) => {
table.options.meta?.updateData(index, id, e.target.value);
};
return (
<input
value={initialValue ? initialValue : ''}
onChange={(e) => table.options.meta?.updateData(index, id, e.target.value)}
onBlur={onBlur}
/>
);
},
},
getCoreRowModel: getCoreRowModel(),
meta: {
updateData: (rowIndex, columnId, value) => {
const newRowsData = wrap(data).set([rowIndex, columnId], value).value();
setRowsFn(newRowsData);
},
}
});
return (
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</>
)}
</th>
);
})}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => {
return (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => {
return (
<td key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
)
}
export default RenderTable

View File

@@ -1,17 +1,16 @@
import React, { useEffect, useState } from 'react';
import { classNames } from 'primereact/utils';
import { __ } from '@wordpress/i18n';
import {
useReactTable,
getCoreRowModel,
flexRender,
} from '@tanstack/react-table';
import { pathOr, isEmpty, isNil } from 'ramda';
import { wrap } from 'object-path-immutable';
//components
import { Button } from 'primereact/button';
import RenderTable from './RenderTable';
const Table = ({
fieldName,
setDataFn,
label,
register,
errors,
@@ -19,59 +18,46 @@ const Table = ({
defaultValue = [],
tableColumns = []
}) => {
const [stateFieldData, setStateFieldData] = useState([]);
const [rowsData, setRowsData] = useState([]);
const [rowsDataLength, setRowsDataLength] = useState(0);
const [rowIndexToDelete, rowRowIndexToDelete] = useState(null);
const [isDisabledNewRow, setIsDisabledNewRow] = useState(false);
const [columnsCfg, setColumnsCfg] = useState([]);
const [rowsCfg, setRowsCfg] = useState([]);
const [columns, setColumns] = useState([]);
const table = useReactTable({
data: rowsData,
columns,
defaultColumn: {
cell: ({ getValue, row: { index }, column: { id }, table }) => {
const initialValue = getValue();
const onBlur = (e) => {
table.options.meta?.updateData(index, id, e.target.value);
};
return (
<input
value={initialValue}
onChange={(e) => table.options.meta?.updateData(index, id, e.target.value)}
onBlur={onBlur}
/>
);
},
},
getCoreRowModel: getCoreRowModel(),
meta: {
updateData: (rowIndex, columnId, value) => {
const newRowsData = wrap(rowsData).set([rowIndex, columnId], value).value();
setRowsData(newRowsData);
},
},
debugTable: true,
});
const [rows, setRows] = useState([]);
const [shouldDisableNewRows, setShouldDisableNewRows] = useState(false);
const [rowIndexToDelete, rowRowIndexToDelete] = useState(null);
const addNewRow = () => {
const obj = stateFieldData
const obj = columnsCfg
.reduce((acc, cur) => {
acc[cur.name] = ''
return acc;
}, {});
setRowsData([...rowsData, obj]);
const newRowsData = [...rows, obj];
setRows(newRowsData);
setDataFn(fieldName, newRowsData, { shouldValidate: true });
}
const removeRow = (index) => {
rowRowIndexToDelete(index)
rowRowIndexToDelete(index);
}
useEffect(() => {
if (!isNil(rowIndexToDelete)) {
const newRowsData = wrap(rows).del([rowIndexToDelete]).value();
setRows(newRowsData);
setDataFn(fieldName, [...newRowsData], { shouldValidate: true });
}
rowRowIndexToDelete(null);
}, [rowIndexToDelete]);
const updateRows = (data) => {
setRows(data);
setDataFn(fieldName, data, { shouldValidate: true });
}
useEffect(() => {
let shouldDisableNewRows = false;
let columns = stateFieldData.map((o) => {
let newColumns = columnsCfg.map((o) => {
const item = {
accessorKey: o.name,
header: () => o.label,
@@ -88,10 +74,10 @@ const Table = ({
return item;
});
setIsDisabledNewRow(shouldDisableNewRows);
setShouldDisableNewRows(shouldDisableNewRows);
if (!shouldDisableNewRows && !isEmpty(columns)) {
columns.push({
if (!shouldDisableNewRows && !isEmpty(newColumns)) {
newColumns.push({
accessorKey: 'actions',
header: () => '',
footer: (props) => props.column.id,
@@ -104,20 +90,12 @@ const Table = ({
})
}
setColumns(columns);
}, [stateFieldData, rowsDataLength]);
setColumns(newColumns);
}, [columnsCfg]);
useEffect(() => {
setRowsDataLength(rowsData.length);
}, [rowsData]);
useEffect(() => {
if (!isNil(rowIndexToDelete)) {
const newRowsData = wrap(rowsData).del([rowIndexToDelete]).value();
setRowsData(newRowsData);
}
rowRowIndexToDelete(null);
}, [rowIndexToDelete]);
setRows(rowsCfg);
}, [rowsCfg]);
useEffect(() => {
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
@@ -128,60 +106,21 @@ const Table = ({
}, {});
let rowsData = pathOr([obj], ['rowsData'], tableColumns);
rowsData = isEmpty(rowsData) ? [obj] : rowsData;
setStateFieldData(stateFieldData);
setRowsData(rowsData);
setColumnsCfg(stateFieldData);
setRowsCfg(rowsData);
}, [tableColumns]);
useEffect(() => {
register(fieldName, config)
register(fieldName, config);
}, []);
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</>
)}
</th>
);
})}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => {
return (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => {
return (
<td key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
{!isDisabledNewRow && !isEmpty(columns)
<RenderTable columns={columns} data={rows} setRowsFn={updateRows}/>
{!isEmpty(columns) && !shouldDisableNewRows
? <div className="addNewTableRow" onClick={addNewRow}>{__('Aggiungi una righa', 'gepafin')}</div>
: null}
</>)

View File

@@ -17,7 +17,7 @@ const TextArea = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
<Controller
name={fieldName}

View File

@@ -37,10 +37,10 @@ const TextInput = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
{inputgroup
? <div className="p-inputgroup flex-1">
? <div className="p-inputgroup">
<span className="p-inputgroup-addon">
{icon}
</span>

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { classNames } from 'primereact/utils';
import { Controller } from 'react-hook-form';
import { Editor } from 'primereact/editor';
import BlockingOverlay from '../../../BlockingOverlay';
const Wysiwyg = ({
fieldName,
@@ -12,6 +13,7 @@ const Wysiwyg = ({
defaultValue,
config = {},
infoText = null,
placeholder={placeholder},
disabled = false
}) => {
@@ -36,8 +38,9 @@ const Wysiwyg = ({
return (
<>
<BlockingOverlay shouldDisplay={disabled}/>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
</label>
<Controller
name={fieldName}
@@ -50,6 +53,7 @@ const Wysiwyg = ({
readOnly={disabled}
{...field}
headerTemplate={header}
placeholder={placeholder}
onTextChange={(e) => field.onChange(e.htmlValue)}
style={{ height: 80 * rows }}
className={classNames({ 'p-invalid': fieldState.invalid })}