- fixed blue cell color after removing dynamic tag;
This commit is contained in:
@@ -24,6 +24,11 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
|||||||
const isRestoringRef = useRef(false);
|
const isRestoringRef = useRef(false);
|
||||||
const mousePos = useRef({ x: 0, y: 0 });
|
const mousePos = useRef({ x: 0, y: 0 });
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
|
const taggedCellsRef = useRef(new Set());
|
||||||
|
const saveTimerRef = useRef(null);
|
||||||
|
const setDataFnRef = useRef(setDataFn);
|
||||||
|
|
||||||
|
useEffect(() => { setDataFnRef.current = setDataFn; }, [setDataFn]);
|
||||||
|
|
||||||
const insertFieldTag = (ids, type, field) => {
|
const insertFieldTag = (ids, type, field) => {
|
||||||
const api = univerAPIRef.current;
|
const api = univerAPIRef.current;
|
||||||
@@ -63,7 +68,24 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
|||||||
univerRef.current = univer;
|
univerRef.current = univer;
|
||||||
univerAPIRef.current = univerAPI;
|
univerAPIRef.current = univerAPI;
|
||||||
|
|
||||||
// Restore tag cells whose display value was overwritten by raw tag on blur
|
// Initialise tagged-cell tracking from the loaded workbook data
|
||||||
|
const initialTagged = new Set();
|
||||||
|
if (workbookData?.sheets) {
|
||||||
|
const sid = workbookData.sheetOrder?.[0];
|
||||||
|
const sd = sid ? workbookData.sheets[sid] : Object.values(workbookData.sheets)[0];
|
||||||
|
if (sd?.cellData) {
|
||||||
|
Object.entries(sd.cellData).forEach(([r, row]) =>
|
||||||
|
Object.entries(row).forEach(([c, cell]) => {
|
||||||
|
if (typeof cell.f === 'string' && TAG_RE.test(cell.f))
|
||||||
|
initialTagged.add(`${r}:${c}`);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
taggedCellsRef.current = initialTagged;
|
||||||
|
|
||||||
|
// Restore tag cells whose display value was overwritten by raw tag on blur;
|
||||||
|
// also clear background for cells whose tag formula was removed.
|
||||||
const restoreTagCells = () => {
|
const restoreTagCells = () => {
|
||||||
if (isRestoringRef.current) return;
|
if (isRestoringRef.current) return;
|
||||||
const wb = univerAPIRef.current?.getActiveWorkbook();
|
const wb = univerAPIRef.current?.getActiveWorkbook();
|
||||||
@@ -76,6 +98,25 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
|||||||
const sheetData = sheetId ? saved.sheets[sheetId] : Object.values(saved.sheets)[0];
|
const sheetData = sheetId ? saved.sheets[sheetId] : Object.values(saved.sheets)[0];
|
||||||
if (!sheetData?.cellData) return;
|
if (!sheetData?.cellData) return;
|
||||||
|
|
||||||
|
// Build set of cells that currently have a tag formula
|
||||||
|
const currentlyTagged = new Set();
|
||||||
|
Object.entries(sheetData.cellData).forEach(([r, row]) =>
|
||||||
|
Object.entries(row).forEach(([c, cell]) => {
|
||||||
|
if (typeof cell.f === 'string' && TAG_RE.test(cell.f))
|
||||||
|
currentlyTagged.add(`${r}:${c}`);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Cells that lost their tag formula → need background reset
|
||||||
|
const cellsToDecolor = [];
|
||||||
|
for (const key of taggedCellsRef.current) {
|
||||||
|
if (!currentlyTagged.has(key)) {
|
||||||
|
const [r, c] = key.split(':').map(Number);
|
||||||
|
cellsToDecolor.push({ r, c });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cells whose displayed value was overwritten by raw formula text → restore
|
||||||
const restorations = [];
|
const restorations = [];
|
||||||
Object.entries(sheetData.cellData).forEach(([r, row]) => {
|
Object.entries(sheetData.cellData).forEach(([r, row]) => {
|
||||||
Object.entries(row).forEach(([c, cell]) => {
|
Object.entries(row).forEach(([c, cell]) => {
|
||||||
@@ -94,21 +135,33 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (restorations.length === 0) return;
|
if (restorations.length === 0 && cellsToDecolor.length === 0) {
|
||||||
|
taggedCellsRef.current = currentlyTagged;
|
||||||
|
return;
|
||||||
|
}
|
||||||
isRestoringRef.current = true;
|
isRestoringRef.current = true;
|
||||||
restorations.forEach(({ r, c, v, f }) => {
|
restorations.forEach(({ r, c, v, f }) => {
|
||||||
sheet.getRange(r, c, 1, 1).setValues([[{ v, f }]]);
|
sheet.getRange(r, c, 1, 1).setValues([[{ v, f }]]);
|
||||||
});
|
});
|
||||||
|
cellsToDecolor.forEach(({ r, c }) => {
|
||||||
|
sheet.getRange(r, c, 1, 1).setBackground('');
|
||||||
|
});
|
||||||
isRestoringRef.current = false;
|
isRestoringRef.current = false;
|
||||||
|
taggedCellsRef.current = currentlyTagged;
|
||||||
};
|
};
|
||||||
|
|
||||||
let restoreTimer;
|
let restoreTimer;
|
||||||
|
|
||||||
// Disable adding new sheets; also schedule tag-cell restoration after each command
|
// Disable adding new sheets; auto-save on every command; schedule tag restoration
|
||||||
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => {
|
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => {
|
||||||
if (event.id === 'sheet.command.insert-sheet') {
|
if (event.id === 'sheet.command.insert-sheet') {
|
||||||
event.cancel = true;
|
event.cancel = true;
|
||||||
}
|
}
|
||||||
|
clearTimeout(saveTimerRef.current);
|
||||||
|
saveTimerRef.current = setTimeout(() => {
|
||||||
|
const wb = univerAPIRef.current?.getActiveWorkbook();
|
||||||
|
if (wb) setDataFnRef.current(name, wb.save());
|
||||||
|
}, 300);
|
||||||
clearTimeout(restoreTimer);
|
clearTimeout(restoreTimer);
|
||||||
restoreTimer = setTimeout(restoreTagCells, 80);
|
restoreTimer = setTimeout(restoreTagCells, 80);
|
||||||
});
|
});
|
||||||
@@ -179,6 +232,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
|||||||
initializeUniver(workbook);
|
initializeUniver(workbook);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
clearTimeout(saveTimerRef.current);
|
||||||
if (univerRef.current) {
|
if (univerRef.current) {
|
||||||
univerRef.current.dispose();
|
univerRef.current.dispose();
|
||||||
univerRef.current = null;
|
univerRef.current = null;
|
||||||
@@ -187,6 +241,22 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
|||||||
};
|
};
|
||||||
}, []); // run once on mount
|
}, []); // run once on mount
|
||||||
|
|
||||||
|
// Flush workbook data to parent immediately when the user clicks outside the spreadsheet.
|
||||||
|
// This runs in the capture phase — before the clicked element's own handler — so the
|
||||||
|
// parent's store is up to date by the time any outer "Salva" button handler reads it.
|
||||||
|
useEffect(() => {
|
||||||
|
const container = containerRef.current;
|
||||||
|
if (!container) return;
|
||||||
|
const flushOnExternalClick = (e) => {
|
||||||
|
if (container.contains(e.target)) return;
|
||||||
|
clearTimeout(saveTimerRef.current);
|
||||||
|
const wb = univerAPIRef.current?.getActiveWorkbook();
|
||||||
|
if (wb) setDataFnRef.current(name, wb.save());
|
||||||
|
};
|
||||||
|
document.addEventListener('click', flushOnExternalClick, true);
|
||||||
|
return () => document.removeEventListener('click', flushOnExternalClick, true);
|
||||||
|
}, [name]); // name is stable ('template')
|
||||||
|
|
||||||
// Prevent page scroll while hovering over the spreadsheet
|
// Prevent page scroll while hovering over the spreadsheet
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = containerRef.current;
|
const el = containerRef.current;
|
||||||
|
|||||||
@@ -73,7 +73,11 @@ const BuilderElementSettings = ({ closeSettingsFn, callStatus, context }) => {
|
|||||||
|
|
||||||
const saveSettings = () => {
|
const saveSettings = () => {
|
||||||
let newActiveElementData = klona(activeElementData);
|
let newActiveElementData = klona(activeElementData);
|
||||||
newActiveElementData = wrap(newActiveElementData).set(['settings'], settings).value();
|
// Prefer the store value over React state: child components (e.g. ElementSettingSpreadsheet)
|
||||||
|
// write to the store synchronously, but React state updates are batched and may lag behind
|
||||||
|
// when saveSettings is called in the same event as the last setDataFn call.
|
||||||
|
const latestSettings = storeGet('chosenFieldSettings') || settings;
|
||||||
|
newActiveElementData = wrap(newActiveElementData).set(['settings'], latestSettings).value();
|
||||||
newActiveElementData = wrap(newActiveElementData).set(['validators'], validators).value();
|
newActiveElementData = wrap(newActiveElementData).set(['validators'], validators).value();
|
||||||
newActiveElementData = wrap(newActiveElementData).set(['dynamicData'], dynamicData).value();
|
newActiveElementData = wrap(newActiveElementData).set(['dynamicData'], dynamicData).value();
|
||||||
newActiveElementData = wrap(newActiveElementData).set(['criteria'], criteria).value();
|
newActiveElementData = wrap(newActiveElementData).set(['criteria'], criteria).value();
|
||||||
|
|||||||
Reference in New Issue
Block a user