diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index 254a51d94..bf472a505 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -225,6 +225,7 @@ export class Gutter { const avID = blockElement.getAttribute("data-av-id"); const srcIDs = [Lute.NewNodeID()]; const previousID = event.altKey ? (rowElement.previousElementSibling.getAttribute("data-id") || "") : buttonElement.dataset.rowId; + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "insertAttrViewBlock", avID, @@ -232,12 +233,21 @@ export class Gutter { srcIDs, isDetached: true, blockID: id, + }, { + action: "doUpdateUpdated", + id, + data: newUpdated, }], [{ action: "removeAttrViewBlock", srcIDs, avID, + }, { + action: "doUpdateUpdated", + id, + data: blockElement.getAttribute("updated") }]); insertAttrViewBlockAnimation(protyle, blockElement, srcIDs, previousID, avID); + blockElement.setAttribute("updated", newUpdated); } else { avContextmenu(protyle, rowElement as HTMLElement, { x: gutterRect.left, @@ -812,6 +822,10 @@ export class Gutter { srcIDs: sourceIds, isDetached: false, blockID: listItemElement.dataset.blockId + }, { + action: "doUpdateUpdated", + id: listItemElement.dataset.blockId, + data: dayjs().format("YYYYMMDDHHmmss"), }], [{ action: "removeAttrViewBlock", srcIDs: sourceIds, @@ -1269,6 +1283,10 @@ export class Gutter { srcIDs: sourceIds, isDetached: false, blockID: listItemElement.dataset.blockId + }, { + action: "doUpdateUpdated", + id: listItemElement.dataset.blockId, + data: dayjs().format("YYYYMMDDHHmmss"), }], [{ action: "removeAttrViewBlock", srcIDs: sourceIds, diff --git a/app/src/protyle/header/openTitleMenu.ts b/app/src/protyle/header/openTitleMenu.ts index 9b1953dab..b496e0b23 100644 --- a/app/src/protyle/header/openTitleMenu.ts +++ b/app/src/protyle/header/openTitleMenu.ts @@ -63,6 +63,10 @@ export const openTitleMenu = (protyle: IProtyle, position: IPosition) => { srcIDs: sourceIds, isDetached: false, blockID: listItemElement.dataset.nodeId + }, { + action: "doUpdateUpdated", + id: listItemElement.dataset.nodeId, + data: dayjs().format("YYYYMMDDHHmmss"), }], [{ action: "removeAttrViewBlock", srcIDs: sourceIds, diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index 629ab4fe5..ffe991ba2 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -75,18 +75,28 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle } else if (type === "av-add-more") { const avID = blockElement.getAttribute("data-av-id"); const srcIDs = [Lute.NewNodeID()]; + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "insertAttrViewBlock", avID, srcIDs, isDetached: true, blockID: blockElement.dataset.nodeId, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: newUpdated, }], [{ action: "removeAttrViewBlock", srcIDs, avID, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: blockElement.getAttribute("updated") }]); insertAttrViewBlockAnimation(protyle, blockElement, srcIDs, undefined, avID); + blockElement.setAttribute("updated", newUpdated); event.preventDefault(); event.stopPropagation(); return true; @@ -145,6 +155,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle const avID = blockElement.getAttribute("data-av-id"); const srcIDs = [Lute.NewNodeID()]; const previousID = blockElement.querySelector(".av__row--util").previousElementSibling.getAttribute("data-id") || ""; + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "insertAttrViewBlock", avID, @@ -152,12 +163,21 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle srcIDs, isDetached: true, blockID: blockElement.dataset.nodeId, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: newUpdated, }], [{ action: "removeAttrViewBlock", srcIDs, avID, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: blockElement.getAttribute("updated") }]); insertAttrViewBlockAnimation(protyle, blockElement, srcIDs, previousID, avID); + blockElement.setAttribute("updated", newUpdated); event.preventDefault(); event.stopPropagation(); return true; diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts index 02825ec00..7273ded8a 100644 --- a/app/src/protyle/render/av/col.ts +++ b/app/src/protyle/render/av/col.ts @@ -11,6 +11,7 @@ import {focusBlock} from "../../util/selection"; import {toggleUpdateRelationBtn} from "./relation"; import {bindRollupData, getRollupHTML} from "./rollup"; import {Constants} from "../../../constants"; +import * as dayjs from "dayjs"; export const duplicateCol = (options: { protyle: IProtyle, @@ -19,7 +20,8 @@ export const duplicateCol = (options: { colId: string, newValue: string, icon: string - viewID: string + viewID: string, + blockElement: Element }) => { const id = Lute.NewNodeID(); const nameMatch = options.newValue.match(/^(.*) \((\d+)\)$/); @@ -28,6 +30,8 @@ export const duplicateCol = (options: { } else { options.newValue = `${options.newValue} (1)`; } + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); + const blockId = options.blockElement.getAttribute("data-node-id"); if (["select", "mSelect", "rollup"].includes(options.type)) { fetchPost("/api/av/renderAttributeView", { id: options.avID, @@ -54,10 +58,18 @@ export const duplicateCol = (options: { id, avID: options.avID, data: colOptions + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID: options.avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: options.blockElement.getAttribute("updated") }]); }); } else { @@ -69,14 +81,22 @@ export const duplicateCol = (options: { data: options.icon, id, previousID: options.colId, + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID: options.avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: options.blockElement.getAttribute("updated") }]); } addAttrViewColAnimation({ - blockElement: options.protyle.wysiwyg.element.querySelector(`[data-av-id="${options.avID}"]`), + blockElement: options.blockElement, protyle: options.protyle, type: options.type, name: options.newValue, @@ -84,6 +104,7 @@ export const duplicateCol = (options: { previousID: options.colId, id }); + options.blockElement.setAttribute("updated", newUpdated); }; export const getEditHTML = (options: { @@ -751,6 +772,7 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen label: window.siyuan.languages.duplicate, click() { duplicateCol({ + blockElement, viewID: blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW), protyle, type, @@ -766,10 +788,15 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen icon: "iconTrashcan", label: window.siyuan.languages.delete, click() { + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "removeAttrViewCol", id: colId, avID, + }, { + action: "doUpdateUpdated", + id: blockID, + data: newUpdated, }], [{ action: "addAttrViewCol", name: oldValue, @@ -777,8 +804,13 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen type: type, id: colId, previousID: cellElement.previousElementSibling?.getAttribute("data-col-id") || "", + }, { + action: "doUpdateUpdated", + id: blockID, + data: blockElement.getAttribute("updated") }]); removeAttrViewColAnimation(blockElement, colId); + blockElement.setAttribute("updated", newUpdated); } }); menu.addSeparator(); @@ -832,11 +864,13 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st if (typeof previousID === "undefined") { previousID = Array.from(blockElement.querySelectorAll(".av__row--header .av__cell")).pop().getAttribute("data-col-id"); } + const blockId = blockElement.getAttribute("data-node-id"); menu.addItem({ icon: "iconAlignLeft", label: window.siyuan.languages.text, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.text, @@ -844,10 +878,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "text", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -857,6 +899,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -864,6 +907,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.number, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.number, @@ -871,10 +915,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "number", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -884,6 +936,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -891,6 +944,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.select, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.select, @@ -898,10 +952,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "select", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -911,6 +973,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -918,6 +981,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.multiSelect, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.multiSelect, @@ -925,10 +989,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "mSelect", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -938,6 +1010,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -945,6 +1018,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.date, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.date, @@ -952,10 +1026,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "date", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -965,6 +1047,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -972,6 +1055,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.assets, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.assets, @@ -979,10 +1063,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "mAsset", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -992,6 +1084,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -999,6 +1092,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.checkbox, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.checkbox, @@ -1006,10 +1100,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "checkbox", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1019,6 +1121,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1026,6 +1129,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.link, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.link, @@ -1033,10 +1137,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "url", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1046,6 +1158,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1053,6 +1166,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.email, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.email, @@ -1060,10 +1174,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "email", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1073,6 +1195,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1080,6 +1203,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.phone, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.phone, @@ -1087,10 +1211,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "phone", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1100,6 +1232,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1107,6 +1240,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.template, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.template, @@ -1114,10 +1248,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "template", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1127,6 +1269,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1134,6 +1277,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.relation, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.relation, @@ -1141,10 +1285,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "relation", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1154,6 +1306,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1161,6 +1314,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.rollup, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.rollup, @@ -1168,10 +1322,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "rollup", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1181,6 +1343,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1188,6 +1351,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.createdTime, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.createdTime, @@ -1195,10 +1359,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "created", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1208,6 +1380,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); menu.addItem({ @@ -1215,6 +1388,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st label: window.siyuan.languages.updatedTime, click() { const id = Lute.NewNodeID(); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "addAttrViewCol", name: window.siyuan.languages.updatedTime, @@ -1222,10 +1396,18 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st type: "updated", id, previousID + }, { + action: "doUpdateUpdated", + id: blockId, + data: newUpdated, }], [{ action: "removeAttrViewCol", id, avID, + }, { + action: "doUpdateUpdated", + id: blockId, + data: blockElement.getAttribute("updated") }]); addAttrViewColAnimation({ blockElement: blockElement, @@ -1235,6 +1417,7 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st id, previousID }); + blockElement.setAttribute("updated", newUpdated); } }); return menu; diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index 4f229c57b..9321a8847 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -30,6 +30,7 @@ import {bindRelationEvent, getRelationHTML, openSearchAV, setRelationCell, updat import {bindRollupData, getRollupHTML, goSearchRollupCol} from "./rollup"; import {updateCellsValue} from "./cell"; import {openCalcMenu} from "./calc"; +import * as dayjs from "dayjs"; export const openMenuPanel = (options: { protyle: IProtyle, @@ -1008,6 +1009,7 @@ export const openMenuPanel = (options: { const colId = menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"); const colData = data.view.columns.find((item: IAVColumn) => item.id === colId); duplicateCol({ + blockElement: options.blockElement, protyle: options.protyle, type: colData.type, avID, @@ -1029,10 +1031,15 @@ export const openMenuPanel = (options: { return true; } }); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(options.protyle, [{ action: "removeAttrViewCol", id: colId, avID, + }, { + action: "doUpdateUpdated", + id: blockID, + data: newUpdated, }], [{ action: "addAttrViewCol", name: colData.name, @@ -1040,8 +1047,13 @@ export const openMenuPanel = (options: { type: colData.type, id: colId, previousID + }, { + action: "doUpdateUpdated", + id: blockID, + data: options.blockElement.getAttribute("updated") }]); removeAttrViewColAnimation(options.blockElement, colId); + options.blockElement.setAttribute("updated", newUpdated); avPanelElement.remove(); event.preventDefault(); event.stopPropagation(); diff --git a/app/src/protyle/render/av/row.ts b/app/src/protyle/render/av/row.ts index 9603aff69..d4f099b30 100644 --- a/app/src/protyle/render/av/row.ts +++ b/app/src/protyle/render/av/row.ts @@ -5,6 +5,7 @@ import {transaction} from "../../wysiwyg/transaction"; import {genCellValueByElement, getTypeByCellElement, popTextCell, renderCell, renderCellAttr} from "./cell"; import {fetchPost} from "../../../util/fetch"; import {showMessage} from "../../../dialog/message"; +import * as dayjs from "dayjs"; export const selectRow = (checkElement: Element, type: "toggle" | "select" | "unselect" | "unselectAll") => { const rowElement = hasClosestByClassName(checkElement, "av__row"); @@ -319,14 +320,25 @@ export const deleteRow = (blockElement: HTMLElement, protyle: IProtyle) => { blockID: blockElement.dataset.nodeId }); }); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); + undoOperations.push({ + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: blockElement.getAttribute("updated") + }); transaction(protyle, [{ action: "removeAttrViewBlock", srcIDs: blockIds, avID, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: newUpdated, }], undoOperations); rowElements.forEach(item => { item.remove(); }); stickyRow(blockElement, protyle.contentElement.getBoundingClientRect(), "all"); updateHeader(blockElement.querySelector(".av__row")); + blockElement.setAttribute("updated", newUpdated); }; diff --git a/app/src/protyle/util/editorCommonEvent.ts b/app/src/protyle/util/editorCommonEvent.ts index d0a1a97da..fd193793e 100644 --- a/app/src/protyle/util/editorCommonEvent.ts +++ b/app/src/protyle/util/editorCommonEvent.ts @@ -27,6 +27,7 @@ import {isBrowser} from "../../util/functions"; import {hideElements} from "../ui/hideElements"; import {insertAttrViewBlockAnimation} from "../render/av/row"; import {dragUpload} from "../render/av/asset"; +import * as dayjs from "dayjs"; const moveToNew = (protyle: IProtyle, sourceElements: Element[], targetElement: Element, newSourceElement: Element, isSameDoc: boolean, isBottom: boolean, isCopy: boolean) => { @@ -890,6 +891,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { }); transaction(protyle, doOperations, undoOperations); } else { + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "insertAttrViewBlock", avID, @@ -897,11 +899,20 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { srcIDs: sourceIds, isDetached: false, blockID: blockElement.dataset.nodeId + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: newUpdated, }], [{ action: "removeAttrViewBlock", srcIDs: sourceIds, avID, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: blockElement.getAttribute("updated") }]); + blockElement.setAttribute("updated", newUpdated); insertAttrViewBlockAnimation(protyle, blockElement, sourceIds, previousID); } } @@ -951,6 +962,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { previousID = targetElement.previousElementSibling?.getAttribute("data-id") || ""; } const avID = blockElement.getAttribute("data-av-id"); + const newUpdated = dayjs().format("YYYYMMDDHHmmss"); transaction(protyle, [{ action: "insertAttrViewBlock", avID, @@ -958,12 +970,21 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { srcIDs: ids, isDetached: false, blockID: blockElement.dataset.nodeId, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: newUpdated, }], [{ action: "removeAttrViewBlock", srcIDs: ids, avID, + }, { + action: "doUpdateUpdated", + id: blockElement.dataset.nodeId, + data: blockElement.getAttribute("updated") }]); insertAttrViewBlockAnimation(protyle, blockElement, ids, previousID); + blockElement.setAttribute("updated", newUpdated); } } else { for (let i = 0; i < ids.length; i++) {