diff --git a/package.json b/package.json index 1edb8e6..aab4ff2 100644 --- a/package.json +++ b/package.json @@ -11,25 +11,25 @@ "author": "", "license": "MIT", "dependencies": { - "@ant-design/icons": "^6.0.0", - "@ant-design/pro-components": "^2.8.7", + "@ant-design/icons": "^6.1.0", + "@ant-design/pro-components": "^2.8.10", "umi-request": "^1.4.0" }, "devDependencies": { - "@types/luxon": "^3.6.2", + "@types/luxon": "^3.7.1", "@types/node": "^22.15.2", - "@types/react": "^19.1.2", - "@types/react-dom": "^19.1.2", - "@typescript-eslint/eslint-plugin": "8.31.0", - "@typescript-eslint/parser": "8.31.0", - "@vitejs/plugin-react": "^4.4.1", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.1", + "@typescript-eslint/eslint-plugin": "8.46.0", + "@typescript-eslint/parser": "8.46.0", + "@vitejs/plugin-react": "^5.0.4", "builtin-modules": "5.0.0", "husky": "^9", - "lint-staged": "^15.5.1", + "lint-staged": "^16.2.4", "obsidian": "latest", "obsidian-dataview": "^0.5.68", "tslib": "2.8.1", - "vite": "^6.3.3", + "vite": "7.1.5", "vite-plugin-css-injected-by-js": "^3.5.2" } } diff --git a/src/main.tsx b/src/main.tsx index f993b65..73cb744 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,7 @@ import {Plugin} from 'obsidian'; import ReactComponent from "./pages/ReactComponent"; import {Root} from 'react-dom/client'; +import {DashTableView, TableViewType} from "./pages/bases/DashTableView"; export default class QueryDashPlugin extends Plugin { @@ -14,6 +15,14 @@ export default class QueryDashPlugin extends Plugin { const reactComponent = new ReactComponent(container, source, this.app); ctx.addChild(reactComponent); }); + + this.registerBasesView(TableViewType, { + name: 'dash-table-view', + icon: 'lucide-graduation-cap', + factory: (controller, containerEl) => + new DashTableView(controller, containerEl) + }); + } onunload() { diff --git a/src/pages/bases/DashTableView.tsx b/src/pages/bases/DashTableView.tsx new file mode 100644 index 0000000..350f08e --- /dev/null +++ b/src/pages/bases/DashTableView.tsx @@ -0,0 +1,169 @@ +import {BasesView, QueryController} from 'obsidian'; +import {createRoot} from "react-dom/client"; +import React, {useEffect} from "react"; +import {ViewProps} from "../../models/ViewProps"; +import {ProColumns, ProTable} from "@ant-design/pro-components"; +import {ellipsisDisplay, formatValue} from "../GenerateColumns"; +import {getAPI} from "obsidian-dataview"; + +export const TableViewType = 'dash-table-view'; + +export class DashTableView extends BasesView { + readonly type = TableViewType; + private containerEl: HTMLElement; + + constructor(controller: QueryController, parentEl: HTMLElement) { + super(controller); + this.containerEl = parentEl.createDiv('bases-example-view-container'); + } + + public onDataUpdated(): void { + const {app} = this; + this.containerEl.empty(); + + console.log(this.data.data); + + const source = "table file.name , file.outlinks as \"links\" ,file.ctime as \"ctime\", \n" + + "file.mtime as \"mtime\" ,file.tags as \"tags\" from #clippings"; + const container = this.containerEl.createDiv(); + const root = createRoot(container); + root.render(); + } +} + +const TableView: React.FC = ({app, source}) => { + + const [columns, setColumns] = React.useState[]>([]); + const dv = getAPI(app); + + const createColumns = (headers: string[]) => { + let columns = []; + const firstColumn: ProColumns = { + dataIndex: 'index', + valueType: 'indexBorder', + title: 'index', + sorter: true, + }; + columns.push(firstColumn); + const dynamicColumns: ProColumns[] = headers.map((header) => { + return { + title: header, + dataIndex: header, + sorter: (a, b) => a[header]?.display?.toString()?.localeCompare(b[header]?.display?.toString()), + render: (_, record) => { + const {type, path, display} = record[header] || {}; + return ellipsisDisplay(display?.toString()); + } + }; + }); + columns.push(...dynamicColumns); + return columns; + } + + function parseTableResult(value: any, params: any): Array> { + const headers: string[] = value.headers; + // console.log("headers", headers); + // console.log("valueData", value); + + const rows: Array> = []; + + value.values.forEach((row: any, rowIndex: number) => { + const values: Record = {}; + headers.forEach((header, index) => { + const value = row[index]; + const resValue = formatValue(value); + values[header] = resValue; + }); + values['key'] = rowIndex; // Add a unique key for each row + rows.push(values); + }); + + delete params.current; + delete params.pageSize; + + // console.log("rowsData", rows); + // console.log("paramsData", params); + + const filteredData = rows.filter(item => { + return Object.keys(params).every(key => { + if (params[key]) { + // console.log("param1 key", key); + // If item[key] is empty, return false directly. + if (item[key]) { + // console.log("item[key]", item[key]); + return item[key].display.toString().toLowerCase().includes(params[key].toString().toLowerCase()); + } else { + return true; + } + } + return true; + }); + }); + + return filteredData; + } + + const executeTableQuery = async (dvApi: any, source: any, params: any) => { + const sql = source; + + const queryResult = await dvApi.query(sql); + + const tableData: any = parseTableResult(queryResult.value, params); + + const headers: string[] = queryResult.value.headers; + const columns = createColumns(headers); + + return {tableData: tableData, columns: columns}; + } + + useEffect(() => { + // console.log("source", source); + }, []); + + + return ( + record.key} + search={{ + labelWidth: 'auto', + }} + pagination={{ + showSizeChanger: true, + }} + headerTitle="TableView" + request={async (params, sort, filter) => { + // console.log('params:', params); + const response = await executeTableQuery(dv, source, params); + + const {tableData, columns} = response; + + setColumns(columns); + return Promise.resolve({ + data: tableData, + success: true, + total: tableData.length, + // columns: columns, + }); + }} + /> + ); +}; + +