- udpated spreadsheet form field functionality;
This commit is contained in:
@@ -70,9 +70,6 @@ const Table = ({
|
|||||||
setColumns(newColumns);
|
setColumns(newColumns);
|
||||||
}, [columnsCfg, disabled]);
|
}, [columnsCfg, disabled]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setTableValue(rowsCfg);
|
|
||||||
}, [rowsCfg]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
||||||
@@ -102,16 +99,19 @@ const Table = ({
|
|||||||
setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
|
setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
|
||||||
}, [tableColumns]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
if (!equal(tableValue, defaultValue)) {
|
const next = (defaultValue && !isEmpty(defaultValue)) ? defaultValue : rowsCfg;
|
||||||
setTableValue(defaultValue);
|
if (!equal(tableValue, next)) {
|
||||||
|
setTableValue(next);
|
||||||
}
|
}
|
||||||
}, [defaultValue]);
|
}, [rowsCfg, defaultValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTableValue(defaultValue);
|
|
||||||
register(fieldName, properConfig(config));
|
register(fieldName, properConfig(config));
|
||||||
}, []);
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const Spreadsheet = ({ fieldName, label, errors = {}, defaultValue, setDataFn, t
|
|||||||
const isRestoringRef = useRef(false);
|
const isRestoringRef = useRef(false);
|
||||||
const tagCellMapRef = useRef({});
|
const tagCellMapRef = useRef({});
|
||||||
const reinitializeRef = useRef(null);
|
const reinitializeRef = useRef(null);
|
||||||
|
const initializedFromSavedRef = useRef(false);
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
const addSheetsFileInputRef = 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' };
|
const initialData = parseWorkbook(defaultValue) || templateData || { name: 'Sheet' };
|
||||||
|
initializedFromSavedRef.current = !!parseWorkbook(defaultValue);
|
||||||
doInit(initialData);
|
doInit(initialData);
|
||||||
reinitializeRef.current = doInit;
|
reinitializeRef.current = doInit;
|
||||||
|
|
||||||
@@ -186,6 +188,17 @@ const Spreadsheet = ({ fieldName, label, errors = {}, defaultValue, setDataFn, t
|
|||||||
};
|
};
|
||||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
}, []); // 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(() => {
|
useEffect(() => {
|
||||||
const el = containerRef.current;
|
const el = containerRef.current;
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
|||||||
@@ -116,10 +116,6 @@ const Table = ({
|
|||||||
setColumns(newColumns);
|
setColumns(newColumns);
|
||||||
}, [columnsCfg, disabled]);
|
}, [columnsCfg, disabled]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setRows(rowsCfg);
|
|
||||||
}, [rowsCfg]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
||||||
let rowsData = pathOr([], ['rowsData'], tableColumns);
|
let rowsData = pathOr([], ['rowsData'], tableColumns);
|
||||||
@@ -147,16 +143,19 @@ const Table = ({
|
|||||||
setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
|
setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
|
||||||
}, [tableColumns, shouldDisableNewRows]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
if (!equal(rows, defaultValue)) {
|
const next = (defaultValue && !isEmpty(defaultValue)) ? defaultValue : rowsCfg;
|
||||||
setRows(defaultValue);
|
if (!equal(rows, next)) {
|
||||||
|
setRows(next);
|
||||||
}
|
}
|
||||||
}, [defaultValue]);
|
}, [rowsCfg, defaultValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setRows(defaultValue);
|
|
||||||
register(fieldName, properConfig(config));
|
register(fieldName, properConfig(config));
|
||||||
}, []);
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -89,31 +89,31 @@ export const createSpreadsheetValidator = (gepafin) => (workbookValue) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const nonEmptyTables = (v = [], tableCfg = []) => {
|
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 colsCfg = pathOr([], ['stateFieldData'], tableCfg);
|
||||||
const nonPredefinedCells = colsCfg
|
const nonPredefinedCells = colsCfg
|
||||||
.filter(o => !o.predefined)
|
.filter(o => !o.predefined)
|
||||||
.map(o => o.name);
|
.map(o => o.name);
|
||||||
let isTableValid = true;
|
let isTableValid = true;
|
||||||
let atLeastOneCellFilled = false
|
let atLeastOneCellFilled = false;
|
||||||
|
|
||||||
if (is(Array, v)) {
|
// eslint-disable-next-line array-callback-return
|
||||||
// eslint-disable-next-line array-callback-return
|
rows.map((row) => {
|
||||||
v.map((row) => {
|
if (isEmpty(row)) {
|
||||||
if (isEmpty(row)) {
|
isTableValid = false;
|
||||||
isTableValid = false;
|
} else {
|
||||||
} else {
|
// eslint-disable-next-line array-callback-return
|
||||||
// eslint-disable-next-line array-callback-return
|
nonPredefinedCells.map((k) => {
|
||||||
nonPredefinedCells.map((k) => {
|
if (isNil(row[k]) || isEmpty(row[k])) {
|
||||||
if (isNil(row[k]) || isEmpty(row[k])) {
|
isTableValid = atLeastOneCellFilled;
|
||||||
isTableValid = atLeastOneCellFilled;
|
} else {
|
||||||
} else {
|
atLeastOneCellFilled = true;
|
||||||
atLeastOneCellFilled = true;
|
isTableValid = true;
|
||||||
isTableValid = true;
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return is(Array, v) ? v.length >= 1 && isTableValid : false;
|
return rows.length >= 1 && isTableValid;
|
||||||
}
|
}
|
||||||
@@ -401,7 +401,7 @@ const BandoApplication = () => {
|
|||||||
}, formDataInitial);
|
}, formDataInitial);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset(formDataInitial);
|
||||||
setFormInitialData(formDataInitial);
|
setFormInitialData(formDataInitial);
|
||||||
}
|
}
|
||||||
storeSet('unsetAsyncRequest');
|
storeSet('unsetAsyncRequest');
|
||||||
@@ -743,8 +743,10 @@ const BandoApplication = () => {
|
|||||||
|
|
||||||
const validations = Object.keys(o.validators).reduce((acc, cur) => {
|
const validations = Object.keys(o.validators).reduce((acc, cur) => {
|
||||||
if (o.validators[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]);
|
acc[cur] = parseInt(o.validators[cur]);
|
||||||
|
} else if (['min', 'max'].includes(cur)) {
|
||||||
|
acc[cur] = parseFloat(o.validators[cur]);
|
||||||
} else if ('pattern' === cur) {
|
} else if ('pattern' === cur) {
|
||||||
acc[cur] = new RegExp(o.validators[cur]);
|
acc[cur] = new RegExp(o.validators[cur]);
|
||||||
} else if ('isRequired' === cur) {
|
} else if ('isRequired' === cur) {
|
||||||
|
|||||||
@@ -225,7 +225,17 @@ const BuilderElementSettings = ({ closeSettingsFn, callStatus, context }) => {
|
|||||||
value={validators[k]}
|
value={validators[k]}
|
||||||
onChange={(e) => onChangeValidator(e.target.value, k)}/>
|
onChange={(e) => onChangeValidator(e.target.value, k)}/>
|
||||||
</div> : null}
|
</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">
|
? <div className="formElementSettings__field">
|
||||||
<label htmlFor={k}>{k}</label>
|
<label htmlFor={k}>{k}</label>
|
||||||
<InputText id={k}
|
<InputText id={k}
|
||||||
|
|||||||
Reference in New Issue
Block a user