diff --git a/manifest.json b/manifest.json index 70266ad..4aec6e9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "querydash", "name": "QueryDash", - "version": "1.0.4", + "version": "1.0.6", "minAppVersion": "1.8.0", "description": "Refer to Dataview and add search, sorting, and pagination functions, just like Notion.", "author": "lwx", diff --git a/src/components/EditableTable.tsx b/src/components/EditableTable.tsx new file mode 100644 index 0000000..7f6d392 --- /dev/null +++ b/src/components/EditableTable.tsx @@ -0,0 +1,244 @@ +import {PlusOutlined} from '@ant-design/icons'; +import type {ActionType, ProColumns} from '@ant-design/pro-components'; +import { + EditableProTable, + ProCard, + ProFormField, +} from '@ant-design/pro-components'; +import type {InputRef} from 'antd'; +import {Button, Form, Input, Space, Tag} from 'antd'; +import React, {useRef, useState} from 'react'; + +const waitTime = (time: number = 100) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(true); + }, time); + }); +}; + +const TagList: React.FC<{ + value?: { + key: string; + label: string; + }[]; + onChange?: ( + value: { + key: string; + label: string; + }[], + ) => void; +}> = ({value, onChange}) => { + const ref = useRef(null); + const [newTags, setNewTags] = useState< + { + key: string; + label: string; + }[] + >([]); + const [inputValue, setInputValue] = useState(''); + + const handleInputChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + + const handleInputConfirm = () => { + let tempsTags = [...(value || [])]; + if ( + inputValue && + tempsTags.filter((tag) => tag.label === inputValue).length === 0 + ) { + tempsTags = [ + ...tempsTags, + {key: `new-${tempsTags.length}`, label: inputValue}, + ]; + } + onChange?.(tempsTags); + setNewTags([]); + setInputValue(''); + }; + + return ( + + {(value || []).concat(newTags).map((item) => ( + {item.label} + ))} + + + ); +}; + +type DataSourceType = { + id: React.Key; + title?: string; + labels?: { + key: string; + label: string; + }[]; + state?: string; + created_at?: number; + children?: DataSourceType[]; +}; + +const defaultData: DataSourceType[] = [ + { + id: 624748504, + title: '活动名称一', + labels: [{key: 'woman', label: '川妹子'}], + state: 'open', + created_at: 1590486176000, + }, + { + id: 624691229, + title: '活动名称二', + labels: [{key: 'man', label: '西北汉子'}], + state: 'closed', + created_at: 1590481162000, + }, +]; + +const columns: ProColumns[] = [ + { + title: '活动名称', + dataIndex: 'title', + formItemProps: { + rules: [ + { + required: true, + message: '此项为必填项', + }, + ], + }, + width: '30%', + }, + { + title: '状态', + key: 'state', + dataIndex: 'state', + valueType: 'select', + valueEnum: { + all: {text: '全部', status: 'Default'}, + open: { + text: '未解决', + status: 'Error', + }, + closed: { + text: '已解决', + status: 'Success', + }, + }, + }, + { + title: '标签', + dataIndex: 'labels', + width: '20%', + formItemProps: { + rules: [ + { + required: true, + message: '此项为必填项', + }, + ], + }, + renderFormItem: (_, {isEditable}) => { + return isEditable ? : ; + }, + render: (_, row) => + row?.labels?.map((item) => {item.label}), + }, + { + title: '操作', + valueType: 'option', + width: 250, + render: (text, record, _, action) => [ + { + action?.startEditable?.(record.id); + }} + > + 编辑 + , + + 复制此项到末尾 + , + ], + }, +]; + +export default () => { + const actionRef = useRef(); + const [editableKeys, setEditableRowKeys] = useState([]); + const [dataSource, setDataSource] = useState([]); + const [form] = Form.useForm(); + return ( + <> + + rowKey="id" + scroll={{ + x: 960, + }} + actionRef={actionRef} + headerTitle="可编辑表格" + maxLength={5} + // 关闭默认的新建按钮 + recordCreatorProps={{ + position: 'top', + record: () => ({id: (Math.random() * 1000000).toFixed(0)}), + }} + columns={columns} + request={async () => ({ + data: defaultData, + total: 3, + success: true, + })} + value={dataSource} + onChange={setDataSource} + search={{ + labelWidth: 'auto', + }} + pagination={{ + pageSize: 5, + onChange: (page) => console.log(page), + }} + editable={{ + form, + editableKeys, + onSave: async () => { + await waitTime(2000); + }, + onChange: setEditableRowKeys, + actionRender: (row, config, dom) => [dom.save, dom.cancel], + }} + /> + + + + + ); +}; diff --git a/src/pages/kanbanview/KanbanView.tsx b/src/pages/kanbanview/KanbanView.tsx index 9b7f68b..24e5706 100644 --- a/src/pages/kanbanview/KanbanView.tsx +++ b/src/pages/kanbanview/KanbanView.tsx @@ -5,6 +5,7 @@ import {getAPI, STask} from "obsidian-dataview"; import {ViewProps} from "../../models/ViewProps"; import {TFile, Vault} from "obsidian"; import EditableText from "./EditableText"; +import EditableTable from "../../components/EditableTable"; const {Text, Link} = Typography; @@ -22,7 +23,7 @@ const KanbanView: React.FC = ({app, source}) => { leaf.openFile(file); } }} - > + > = ({app, source}) => { }, [app]); return ( - - {columns.map((column) => ( - - {column.items.map((item: any, index: number) => ( - <> - - - - onChange(e.target.checked, item.text, item)} - checked={item.checked} - /> - - - { - console.log("保存的新文本:", newText); - onChange(item.checked, newText, item); - }} - /> - - - - - ))} - - ))} - + <> + + + + {columns.map((column) => ( + + {column.items.map((item: any, index: number) => ( + <> + + + + onChange(e.target.checked, item.text, item)} + checked={item.checked} + /> + + + { + console.log("保存的新文本:", newText); + onChange(item.checked, newText, item); + }} + /> + + + + + ))} + + ))} + + ); };