Merge branch 'main' into feat/add-ocr-capabilities

This commit is contained in:
perf3ct
2025-07-16 17:54:32 +00:00
25 changed files with 635 additions and 324 deletions

2
.nvmrc
View File

@@ -1 +1 @@
22.17.0
22.17.1

View File

@@ -38,7 +38,7 @@
"@playwright/test": "1.54.1",
"@stylistic/eslint-plugin": "5.1.0",
"@types/express": "5.0.3",
"@types/node": "22.16.3",
"@types/node": "22.16.4",
"@types/yargs": "17.0.33",
"@vitest/coverage-v8": "3.2.4",
"eslint": "9.31.0",

View File

@@ -66,6 +66,10 @@
border-bottom-color: var(--col-header-arrow-inactive-color);
}
.tabulator div.tabulator-header .tabulator-frozen.tabulator-frozen-left {
margin-left: var(--cell-editing-border-width);
}
.tabulator div.tabulator-header .tabulator-col,
.tabulator div.tabulator-header .tabulator-frozen.tabulator-frozen-left {
background: var(--col-header-background-color);
@@ -111,6 +115,10 @@
/* Cell */
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left {
margin-right: var(--cell-editing-border-width);
}
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left,
.tabulator-row .tabulator-cell {
border-right-color: transparent;
@@ -139,6 +147,15 @@
color: var(--cell-editing-text-color);
}
.tabulator .tree-collapse,
.tabulator .tree-expand {
color: var(--row-text-color);
}
.tabulator-data-tree-branch {
visibility: hidden;
}
/* Checkbox cells */
.tabulator .tabulator-cell:has(svg),

View File

@@ -4,6 +4,7 @@
@import url(./pages.css);
@import url(./ribbon.css);
@import url(./notes/text.css);
@import url(./notes/collections/table.css);
@font-face {
font-family: "Inter";

View File

@@ -0,0 +1,13 @@
:root .tabulator {
--col-header-hover-background-color: var(--hover-item-background-color);
--col-header-arrow-active-color: var(--active-item-text-color);
--col-header-arrow-inactive-color: var(--main-border-color);
--row-moving-background-color: var(--more-accented-background-color);
--cell-editable-hover-outline-color: var(--input-focus-outline-color);
--cell-editing-border-color: var(--input-focus-outline-color);
--cell-editing-background-color: var(--input-background-color);
--cell-editing-text-color: var(--input-text-color);
}

View File

@@ -0,0 +1,32 @@
import { t } from "i18next";
import attributes from "../../../services/attributes";
import froca from "../../../services/froca";
import server from "../../../services/server";
import toast from "../../../services/toast";
import ws from "../../../services/ws";
export async function renameColumn(parentNoteId: string, type: "label" | "relation", originalName: string, newName: string) {
const bulkActionNote = await froca.getNote("_bulkAction");
if (!bulkActionNote) {
console.warn("Bulk action note not found");
return;
}
if (type === "label") {
attributes.setLabel("_bulkAction", "action", JSON.stringify({
name: "renameLabel",
oldLabelName: originalName,
newLabelName: newName
}));
await server.post("bulk-action/execute", {
noteIds: [ parentNoteId ],
includeDescendants: true
});
await ws.waitForMaxKnownEntityChangeId();
toast.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
} else {
console.warn("Renaming relation columns is not supported yet");
return;
}
}

View File

@@ -5,15 +5,18 @@ import Component from "../../../components/component";
import { CommandListenerData, EventData } from "../../../components/app_context";
import attributes from "../../../services/attributes";
import FNote from "../../../entities/fnote";
import { renameColumn } from "./bulk_actions";
export default class TableColumnEditing extends Component {
private attributeDetailWidget: AttributeDetailWidget;
private newAttributePosition?: number;
private api: Tabulator;
private newAttribute?: Attribute;
private parentNote: FNote;
private newAttribute?: Attribute;
private newAttributePosition?: number;
private existingAttributeToEdit?: Attribute;
constructor($parent: JQuery<HTMLElement>, parentNote: FNote, api: Tabulator) {
super();
const parentComponent = glob.getComponentByEl($parent[0]);
@@ -28,9 +31,12 @@ export default class TableColumnEditing extends Component {
addNewTableColumnCommand({ referenceColumn, columnToEdit, direction }: EventData<"addNewTableColumn">) {
let attr: Attribute | undefined;
this.existingAttributeToEdit = undefined;
if (columnToEdit) {
attr = this.getAttributeFromField(columnToEdit.getField());
console.log("Built ", attr);
if (attr) {
this.existingAttributeToEdit = { ...attr };
}
}
if (!attr) {
@@ -70,8 +76,21 @@ export default class TableColumnEditing extends Component {
return;
}
const { name, value } = this.newAttribute;
const { name, type, value } = this.newAttribute;
this.api.blockRedraw();
if (this.existingAttributeToEdit && this.existingAttributeToEdit.name !== name) {
const oldName = this.existingAttributeToEdit.name.split(":")[1];
const newName = name.split(":")[1];
await renameColumn(this.parentNote.noteId, type, oldName, newName);
}
attributes.setLabel(this.parentNote.noteId, name, value);
if (this.existingAttributeToEdit) {
attributes.removeOwnedLabelByName(this.parentNote, this.existingAttributeToEdit.name);
}
this.api.restoreRedraw();
}
getNewAttributePosition() {
@@ -79,7 +98,9 @@ export default class TableColumnEditing extends Component {
}
resetNewAttributePosition() {
this.newAttributePosition = 0;
this.newAttribute = undefined;
this.newAttributePosition = undefined;
this.existingAttributeToEdit = undefined;
}
getFAttributeFromField(field: string) {

View File

@@ -78,4 +78,34 @@ describe("restoreExistingData", () => {
expect(restored[1].field).toBe("noteId");
expect(restored[2].field).toBe("newColumn");
});
it("supports a rename", () => {
const newDefs: ColumnDefinition[] = [
{ field: "title", title: "Title", editor: "input" },
{ field: "noteId", title: "Note ID", visible: false },
{ field: "newColumn", title: "New Column", editor: "input" }
];
const oldDefs: ColumnDefinition[] = [
{ field: "title", title: "Title", width: 300, visible: true },
{ field: "noteId", title: "Note ID", width: 200, visible: true },
{ field: "oldColumn", title: "New Column", editor: "input" }
];
const restored = restoreExistingData(newDefs, oldDefs);
expect(restored.length).toBe(3);
});
it("doesn't alter the existing order", () => {
const newDefs: ColumnDefinition[] = [
{ title: "#", headerSort: false, hozAlign: "center", resizable: false, frozen: true, rowHandle: false },
{ field: "noteId", title: "Note ID", visible: false },
{ field: "title", title: "Title", editor: "input", width: 400 }
]
const oldDefs: ColumnDefinition[] = [
{ title: "#", headerSort: false, hozAlign: "center", resizable: false, rowHandle: false },
{ field: "noteId", title: "Note ID", visible: false },
{ field: "title", title: "Title", editor: "input", width: 400 }
];
const restored = restoreExistingData(newDefs, oldDefs);
expect(restored).toStrictEqual(newDefs);
});
});

View File

@@ -99,12 +99,16 @@ export function restoreExistingData(newDefs: ColumnDefinition[], oldDefs: Column
newDefs.map(def => [def.field!, def])
);
const existingColumns = oldDefs
.map(item => {
return {
...newItemsByField.get(item.field!),
width: item.width,
visible: item.visible,
};
.filter(item => (item.field && newItemsByField.has(item.field!)) || item.title === "#")
.map(oldItem => {
const data = newItemsByField.get(oldItem.field!)!;
if (oldItem.width) {
data.width = oldItem.width;
}
if (oldItem.visible) {
data.visible = oldItem.visible;
}
return data;
}) as ColumnDefinition[];
// 2. Determine new columns.

View File

@@ -82,6 +82,7 @@ function showColumnContextMenu(_e: UIEvent, column: ColumnComponent, tabulator:
{
title: t("table_view.add-column-to-the-left"),
uiIcon: "bx bx-horizontal-left",
enabled: !column.getDefinition().frozen,
handler: () => getParentComponent(e)?.triggerCommand("addNewTableColumn", {
referenceColumn: column
})
@@ -89,7 +90,9 @@ function showColumnContextMenu(_e: UIEvent, column: ColumnComponent, tabulator:
{
title: t("table_view.edit-column"),
uiIcon: "bx bx-edit",
enabled: !!column.getField() && column.getField() !== "title",
handler: () => getParentComponent(e)?.triggerCommand("addNewTableColumn", {
referenceColumn: column,
columnToEdit: column
})
},

View File

@@ -197,8 +197,8 @@ export default class TableView extends ViewMode<StateInfo> {
attr.type === "label" &&
(attr.name?.startsWith("label:") || attr.name?.startsWith("relation:")) &&
attributes.isAffecting(attr, this.parentNote))) {
console.log("Col update");
this.#manageColumnUpdate();
return await this.#manageRowsUpdate();
}
if (loadResults.getBranchRows().some(branch => branch.parentNoteId === this.parentNote.noteId || this.noteIds.includes(branch.parentNoteId ?? ""))

View File

@@ -19,6 +19,6 @@
},
"devDependencies": {
"dotenv": "17.2.0",
"electron": "37.2.1"
"electron": "37.2.2"
}
}

View File

@@ -17,7 +17,7 @@
"@types/electron-squirrel-startup": "1.0.2",
"@triliumnext/server": "workspace:*",
"copy-webpack-plugin": "13.0.0",
"electron": "37.2.1",
"electron": "37.2.2",
"@electron-forge/cli": "7.8.1",
"@electron-forge/maker-deb": "7.8.1",
"@electron-forge/maker-dmg": "7.8.1",

View File

@@ -12,7 +12,7 @@
"@triliumnext/desktop": "workspace:*",
"@types/fs-extra": "11.0.4",
"copy-webpack-plugin": "13.0.0",
"electron": "37.2.1",
"electron": "37.2.2",
"fs-extra": "11.3.0"
},
"nx": {

View File

@@ -60,13 +60,13 @@
"debounce": "2.2.0",
"debug": "4.4.1",
"ejs": "3.1.10",
"electron": "37.2.1",
"electron": "37.2.2",
"electron-debug": "4.1.0",
"electron-window-state": "5.0.3",
"escape-html": "1.0.3",
"express": "5.1.0",
"express-openid-connect": "^2.17.1",
"express-rate-limit": "7.5.1",
"express-rate-limit": "8.0.0",
"express-session": "1.18.1",
"file-uri-to-path": "2.0.0",
"fs-extra": "11.3.0",
@@ -89,7 +89,7 @@
"multer": "2.0.1",
"normalize-strings": "1.1.1",
"ollama": "0.5.16",
"openai": "5.9.0",
"openai": "5.9.2",
"rand-token": "1.0.1",
"safe-compare": "1.1.4",
"sanitize-filename": "1.6.3",

View File

@@ -43,7 +43,6 @@ interface MetricsData {
*/
function formatPrometheusMetrics(data: MetricsData): string {
const lines: string[] = [];
const timestamp = Math.floor(new Date(data.timestamp).getTime() / 1000);
// Helper function to add a metric
const addMetric = (name: string, value: number | null, help: string, type: string = 'gauge', labels: Record<string, string> = {}) => {
@@ -56,7 +55,7 @@ function formatPrometheusMetrics(data: MetricsData): string {
? `{${Object.entries(labels).map(([k, v]) => `${k}="${v}"`).join(',')}}`
: '';
lines.push(`${name}${labelStr} ${value} ${timestamp}`);
lines.push(`${name}${labelStr} ${value}`);
lines.push('');
};

View File

@@ -4,6 +4,9 @@ import bulkActionService from "../../services/bulk_actions.js";
function execute(req: Request) {
const { noteIds, includeDescendants } = req.body;
if (!Array.isArray(noteIds)) {
throw new Error("noteIds must be an array");
}
const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants);

View File

@@ -40,7 +40,7 @@
"@playwright/test": "^1.36.0",
"@triliumnext/server": "workspace:*",
"@types/express": "^5.0.0",
"@types/node": "22.16.3",
"@types/node": "22.16.4",
"@vitest/coverage-v8": "^3.0.5",
"@vitest/ui": "^3.0.0",
"chalk": "5.4.1",

View File

@@ -35,7 +35,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.36.0",
"@typescript-eslint/eslint-plugin": "~8.37.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",

View File

@@ -36,7 +36,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.36.0",
"@typescript-eslint/eslint-plugin": "~8.37.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",

View File

@@ -38,7 +38,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.36.0",
"@typescript-eslint/eslint-plugin": "~8.37.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",

View File

@@ -39,7 +39,7 @@
"@ckeditor/ckeditor5-dev-utils": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.36.0",
"@typescript-eslint/eslint-plugin": "~8.37.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",

View File

@@ -38,7 +38,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.36.0",
"@typescript-eslint/eslint-plugin": "~8.37.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",

View File

@@ -30,7 +30,7 @@
"@codemirror/lang-xml": "6.1.0",
"@codemirror/legacy-modes": "6.5.1",
"@codemirror/search": "6.5.11",
"@codemirror/view": "6.38.0",
"@codemirror/view": "6.38.1",
"@fsegurai/codemirror-theme-abcdef": "6.2.0",
"@fsegurai/codemirror-theme-abyss": "6.2.0",
"@fsegurai/codemirror-theme-android-studio": "6.2.0",

778
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff