- udpated spreadsheet form field functionality;
This commit is contained in:
@@ -70,9 +70,6 @@ const Table = ({
|
||||
setColumns(newColumns);
|
||||
}, [columnsCfg, disabled]);
|
||||
|
||||
useEffect(() => {
|
||||
setTableValue(rowsCfg);
|
||||
}, [rowsCfg]);
|
||||
|
||||
useEffect(() => {
|
||||
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
||||
@@ -102,16 +99,19 @@ const Table = ({
|
||||
setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
|
||||
}, [tableColumns]);
|
||||
|
||||
// Saved data (defaultValue) takes priority over template defaults (rowsCfg).
|
||||
// Using a single effect for both so the second render caused by rowsCfg changing
|
||||
// doesn't overwrite the saved data that was just loaded from the API.
|
||||
useEffect(() => {
|
||||
if (!equal(tableValue, defaultValue)) {
|
||||
setTableValue(defaultValue);
|
||||
const next = (defaultValue && !isEmpty(defaultValue)) ? defaultValue : rowsCfg;
|
||||
if (!equal(tableValue, next)) {
|
||||
setTableValue(next);
|
||||
}
|
||||
}, [defaultValue]);
|
||||
}, [rowsCfg, defaultValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
useEffect(() => {
|
||||
setTableValue(defaultValue);
|
||||
register(fieldName, properConfig(config));
|
||||
}, []);
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -61,6 +61,7 @@ const Spreadsheet = ({ fieldName, label, errors = {}, defaultValue, setDataFn, t
|
||||
const isRestoringRef = useRef(false);
|
||||
const tagCellMapRef = useRef({});
|
||||
const reinitializeRef = useRef(null);
|
||||
const initializedFromSavedRef = useRef(false);
|
||||
const fileInputRef = useRef(null);
|
||||
const addSheetsFileInputRef = useRef(null);
|
||||
|
||||
@@ -173,6 +174,7 @@ const Spreadsheet = ({ fieldName, label, errors = {}, defaultValue, setDataFn, t
|
||||
};
|
||||
|
||||
const initialData = parseWorkbook(defaultValue) || templateData || { name: 'Sheet' };
|
||||
initializedFromSavedRef.current = !!parseWorkbook(defaultValue);
|
||||
doInit(initialData);
|
||||
reinitializeRef.current = doInit;
|
||||
|
||||
@@ -186,6 +188,17 @@ const Spreadsheet = ({ fieldName, label, errors = {}, defaultValue, setDataFn, t
|
||||
};
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// If the component mounted before saved data was available (reset() cleared form values),
|
||||
// reinitialize univerjs once when the valid saved workbook arrives via defaultValue.
|
||||
useEffect(() => {
|
||||
if (initializedFromSavedRef.current) return; // already showing saved data
|
||||
if (!reinitializeRef.current) return; // init useEffect hasn't run yet
|
||||
const parsedDefault = parseWorkbook(defaultValue);
|
||||
if (!parsedDefault) return; // still no valid workbook
|
||||
initializedFromSavedRef.current = true; // prevent re-triggering on user edits
|
||||
reinitializeRef.current(parsedDefault);
|
||||
}, [defaultValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
useEffect(() => {
|
||||
const el = containerRef.current;
|
||||
if (!el) return;
|
||||
|
||||
@@ -116,10 +116,6 @@ const Table = ({
|
||||
setColumns(newColumns);
|
||||
}, [columnsCfg, disabled]);
|
||||
|
||||
useEffect(() => {
|
||||
setRows(rowsCfg);
|
||||
}, [rowsCfg]);
|
||||
|
||||
useEffect(() => {
|
||||
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
||||
let rowsData = pathOr([], ['rowsData'], tableColumns);
|
||||
@@ -147,16 +143,19 @@ const Table = ({
|
||||
setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
|
||||
}, [tableColumns, shouldDisableNewRows]);
|
||||
|
||||
// Saved data (defaultValue) takes priority over template defaults (rowsCfg).
|
||||
// Using a single effect for both so the second render caused by rowsCfg changing
|
||||
// doesn't overwrite the saved data that was just loaded from the API.
|
||||
useEffect(() => {
|
||||
if (!equal(rows, defaultValue)) {
|
||||
setRows(defaultValue);
|
||||
const next = (defaultValue && !isEmpty(defaultValue)) ? defaultValue : rowsCfg;
|
||||
if (!equal(rows, next)) {
|
||||
setRows(next);
|
||||
}
|
||||
}, [defaultValue]);
|
||||
}, [rowsCfg, defaultValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
useEffect(() => {
|
||||
setRows(defaultValue);
|
||||
register(fieldName, properConfig(config));
|
||||
}, []);
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -89,31 +89,31 @@ export const createSpreadsheetValidator = (gepafin) => (workbookValue) => {
|
||||
};
|
||||
|
||||
export const nonEmptyTables = (v = [], tableCfg = []) => {
|
||||
// table stores a plain array; criteria_table stores { rows: [...], total: N }
|
||||
const rows = is(Array, v) ? v : (v && is(Array, v.rows) ? v.rows : []);
|
||||
const colsCfg = pathOr([], ['stateFieldData'], tableCfg);
|
||||
const nonPredefinedCells = colsCfg
|
||||
.filter(o => !o.predefined)
|
||||
.map(o => o.name);
|
||||
let isTableValid = true;
|
||||
let atLeastOneCellFilled = false
|
||||
let atLeastOneCellFilled = false;
|
||||
|
||||
if (is(Array, v)) {
|
||||
// eslint-disable-next-line array-callback-return
|
||||
v.map((row) => {
|
||||
if (isEmpty(row)) {
|
||||
isTableValid = false;
|
||||
} else {
|
||||
// eslint-disable-next-line array-callback-return
|
||||
nonPredefinedCells.map((k) => {
|
||||
if (isNil(row[k]) || isEmpty(row[k])) {
|
||||
isTableValid = atLeastOneCellFilled;
|
||||
} else {
|
||||
atLeastOneCellFilled = true;
|
||||
isTableValid = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line array-callback-return
|
||||
rows.map((row) => {
|
||||
if (isEmpty(row)) {
|
||||
isTableValid = false;
|
||||
} else {
|
||||
// eslint-disable-next-line array-callback-return
|
||||
nonPredefinedCells.map((k) => {
|
||||
if (isNil(row[k]) || isEmpty(row[k])) {
|
||||
isTableValid = atLeastOneCellFilled;
|
||||
} else {
|
||||
atLeastOneCellFilled = true;
|
||||
isTableValid = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return is(Array, v) ? v.length >= 1 && isTableValid : false;
|
||||
return rows.length >= 1 && isTableValid;
|
||||
}
|
||||
@@ -401,7 +401,7 @@ const BandoApplication = () => {
|
||||
}, formDataInitial);
|
||||
}
|
||||
|
||||
reset();
|
||||
reset(formDataInitial);
|
||||
setFormInitialData(formDataInitial);
|
||||
}
|
||||
storeSet('unsetAsyncRequest');
|
||||
@@ -743,8 +743,10 @@ const BandoApplication = () => {
|
||||
|
||||
const validations = Object.keys(o.validators).reduce((acc, cur) => {
|
||||
if (o.validators[cur]) {
|
||||
if (['min', 'max', 'minLength', 'maxLength', 'maxSize'].includes(cur)) {
|
||||
if (['minLength', 'maxLength', 'maxSize'].includes(cur)) {
|
||||
acc[cur] = parseInt(o.validators[cur]);
|
||||
} else if (['min', 'max'].includes(cur)) {
|
||||
acc[cur] = parseFloat(o.validators[cur]);
|
||||
} else if ('pattern' === cur) {
|
||||
acc[cur] = new RegExp(o.validators[cur]);
|
||||
} else if ('isRequired' === cur) {
|
||||
|
||||
@@ -225,7 +225,17 @@ const BuilderElementSettings = ({ closeSettingsFn, callStatus, context }) => {
|
||||
value={validators[k]}
|
||||
onChange={(e) => onChangeValidator(e.target.value, k)}/>
|
||||
</div> : null}
|
||||
{numberBasedValidatorFields.includes(k) && !isNil(validators[k])
|
||||
{['min', 'max'].includes(k) && !isNil(validators[k])
|
||||
? <div className="formElementSettings__field">
|
||||
<label htmlFor={k}>{k}</label>
|
||||
<InputText id={k}
|
||||
aria-describedby={`${k}-help`}
|
||||
value={validators[k]}
|
||||
keyfilter="num"
|
||||
placeholder="0"
|
||||
onChange={(e) => onChangeValidator(e.target.value, k)}/>
|
||||
</div> : null}
|
||||
{['minLength', 'maxLength'].includes(k) && !isNil(validators[k])
|
||||
? <div className="formElementSettings__field">
|
||||
<label htmlFor={k}>{k}</label>
|
||||
<InputText id={k}
|
||||
|
||||
Reference in New Issue
Block a user