Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.

Commit 8053c8f

Browse files
committed
refactor from string to Literal dataview of all inputs.
Calendar working
1 parent 03aa0a3 commit 8053c8f

File tree

13 files changed

+104
-60
lines changed

13 files changed

+104
-60
lines changed

src/cdm/FolderModel.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import NoteInfo from "services/NoteInfo";
77
import { TFile } from "obsidian";
88
import { DatabaseColumn } from "cdm/DatabaseModel";
99
import { Column } from "react-table";
10+
import { Literal } from "obsidian-dataview/lib/data-model/value";
1011

1112
export type Group = Parameter | Parameters | FolderModel | Models;
1213
type Parameter = {
@@ -42,7 +43,7 @@ export interface TableColumn {
4243
accessor: any;
4344
minWidth?: number;
4445
width?: number;
45-
dataType?: string;
46+
dataType: string;
4647
options?: RowSelectOption[];
4748
Cell?: any;
4849
getHeaderProps?: any;
@@ -56,7 +57,7 @@ export interface TableColumn {
5657
export type RowDataType = {
5758
id: number,
5859
note: NoteInfo,
59-
[key: string]: RowType
60+
[key: string]: Literal | NoteInfo
6061
}
6162

6263
export type TableDataType = {

src/components/Cell.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@ export default function DefaultCell(cellProperties: Cell) {
3838
/** Note info of current Cell */
3939
const note: NoteInfo = (cellProperties.row.original as any).note;
4040
/** state of cell value */
41-
const [value, setValue] = useState({ value: initialValue, update: false });
41+
const [contextValue, setContextValue] = useState({
42+
value: initialValue,
43+
update: false,
44+
});
4245
/** state for keeping the timeout to trigger the editior */
4346
const [editNoteTimeout, setEditNoteTimeout] = useState(null);
4447
/** states for selector option */
4548
LOGGER.debug(
46-
`<=> Cell.rendering dataType: ${dataType}. value: ${value.value}`
49+
`<=> Cell.rendering dataType: ${dataType}. value: ${contextValue.value}`
4750
);
4851

4952
const handleKeyDown = (event: any) => {
@@ -58,7 +61,7 @@ export default function DefaultCell(cellProperties: Cell) {
5861
clearTimeout(editNoteTimeout);
5962
}
6063
// first update the input text as user type
61-
setValue({ value: event.target.value, update: false });
64+
setContextValue({ value: event.target.value, update: false });
6265
// initialize a setimeout by wrapping in our editNoteTimeout so that we can clear it out using clearTimeout
6366
setEditNoteTimeout(
6467
setTimeout(() => {
@@ -85,14 +88,14 @@ export default function DefaultCell(cellProperties: Cell) {
8588
/** Plain text option */
8689
case DataTypes.TEXT:
8790
return (cellProperties.column as any).isMetadata ? (
88-
<span className="data-input">{value.value.toString()}</span>
91+
<span className="data-input">{contextValue.value.toString()}</span>
8992
) : (
9093
<ContentEditable
91-
html={(value.value && value.value.toString()) || ""}
94+
html={(contextValue.value && contextValue.value.toString()) || ""}
9295
onChange={handleOnChange}
9396
onKeyDown={handleKeyDown}
9497
onBlur={() =>
95-
setValue((old) => ({ value: old.value, update: true }))
98+
setContextValue((old) => ({ value: old.value, update: true }))
9699
}
97100
className="data-input"
98101
/>
@@ -101,10 +104,10 @@ export default function DefaultCell(cellProperties: Cell) {
101104
case DataTypes.NUMBER:
102105
return (
103106
<ContentEditable
104-
html={(value.value && value.value.toString()) || ""}
107+
html={(contextValue.value && contextValue.value.toString()) || ""}
105108
onChange={handleOnChange}
106109
onBlur={() =>
107-
setValue((old) => ({ value: old.value, update: true }))
110+
setContextValue((old) => ({ value: old.value, update: true }))
108111
}
109112
className="data-input text-align-right"
110113
/>
@@ -127,7 +130,7 @@ export default function DefaultCell(cellProperties: Cell) {
127130
/** Selector option */
128131
case DataTypes.SELECT:
129132
return (
130-
<CellContext.Provider value={{ value, setValue }}>
133+
<CellContext.Provider value={{ contextValue, setContextValue }}>
131134
<PopperSelectPortal
132135
dispatch={dataDispatch}
133136
row={cellProperties.row}
@@ -141,10 +144,11 @@ export default function DefaultCell(cellProperties: Cell) {
141144
/** Calendar option */
142145
case DataTypes.CALENDAR:
143146
return (
144-
<CellContext.Provider value={{ value, setValue }}>
147+
<CellContext.Provider value={{ contextValue, setContextValue }}>
145148
<CalendarPortal
146149
intialState={(cellProperties as any).initialState}
147150
column={cellProperties.column as unknown as TableColumn}
151+
cellProperties={cellProperties}
148152
/>
149153
</CellContext.Provider>
150154
);

src/components/Columns.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ function parseDatabaseToTableColumn(
7676
const tableColumn: TableColumn = {
7777
...(databaseColumn as Partial<TableColumn>),
7878
id: columnKey,
79+
dataType: databaseColumn.input,
7980
position: databaseColumn.position ?? index,
8081
key: databaseColumn.key ?? columnKey,
8182
label: databaseColumn.label,

src/components/HeaderMenu.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,7 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
243243
});
244244
setExpanded(false);
245245
setkeyState(newKey);
246-
columnWidthState.widthRecord[newKey] = getColumnWidthStyle(
247-
rows,
248-
newKey,
249-
labelState
250-
);
246+
columnWidthState.widthRecord[newKey] = getColumnWidthStyle(rows, column);
251247

252248
/*
253249
To adjust column settings to the new key, we need to update the order
@@ -296,8 +292,7 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
296292
const columnLabel = `New Column ${columnNumber}`;
297293
columnWidthState.widthRecord[columnName] = getColumnWidthStyle(
298294
rows,
299-
columnName,
300-
columnLabel
295+
column
301296
);
302297
setColumnWidthState(columnWidthState);
303298
return { name: columnName, position: wantedPosition, label: columnLabel };
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
import { Literal } from "obsidian-dataview/lib/data-model/value";
12
import React from "react";
23

34
export type CellDataType = {
4-
value: string;
5+
value: Literal;
56
update: boolean;
67
};
78

89
type CellContextType = {
9-
value: CellDataType;
10-
setValue: (value: CellDataType) => void;
10+
contextValue: CellDataType;
11+
setContextValue: (value: CellDataType) => void;
1112
};
1213
export const CellContext = React.createContext<CellContextType | null>(null); //exporting context object

src/components/portals/CalendarPortal.tsx

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,55 @@
11
import { TableColumn, TableDataType } from "cdm/FolderModel";
22
import { CellContext } from "components/contexts/CellContext";
3-
import { StyleVariables } from "helpers/Constants";
3+
import { ActionTypes, StyleVariables } from "helpers/Constants";
44
import React, { useContext, useState } from "react";
55
import Calendar from "react-calendar";
66
import ReactDOM from "react-dom";
77
import { DateTime } from "luxon";
88
import { usePopper } from "react-popper";
9+
import { Cell } from "react-table";
10+
import NoteInfo from "services/NoteInfo";
911

1012
type CalendarProps = {
1113
intialState: TableDataType;
1214
column: TableColumn;
15+
cellProperties: Cell;
1316
};
1417
const CalendarPortal = (calendarProps: CalendarProps) => {
15-
const { column } = calendarProps;
18+
const { column, cellProperties } = calendarProps;
19+
const dataDispatch = (cellProperties as any).dataDispatch;
1620
const [showCalendar, setShowCalendar] = useState(false);
1721
// Selector reference state
1822
const [calendarRef, setCalendarRef] = useState(null);
1923
// Selector popper state
2024
const [selectPop, setSelectPop] = useState(null);
2125
const { styles, attributes } = usePopper(calendarRef, selectPop);
2226
/** state of cell value */
23-
const { value, setValue } = useContext(CellContext);
27+
const { contextValue, setContextValue } = useContext(CellContext);
2428

25-
let initialDate = new Date();
26-
if (DateTime.isDateTime(value.value)) {
27-
initialDate = DateTime.fromFormat(value.value, "yyyy-MM-dd").toJSDate();
28-
}
29-
const [calendarState, setCalendarState] = useState(initialDate);
29+
/** Note info of current Cell */
30+
const note: NoteInfo = (cellProperties.row.original as any).note;
31+
32+
const [calendarState, setCalendarState] = useState(
33+
DateTime.isDateTime(contextValue.value)
34+
? contextValue.value.toJSDate()
35+
: new Date()
36+
);
3037

3138
function handleCalendarChange(date: Date) {
39+
const newValue = DateTime.fromJSDate(date);
40+
// save on disk
41+
dataDispatch({
42+
type: ActionTypes.UPDATE_CELL,
43+
file: note.getFile(),
44+
key: (cellProperties.column as any).key,
45+
value: DateTime.fromJSDate(date).toFormat("yyyy-MM-dd"),
46+
row: cellProperties.row,
47+
columnId: (cellProperties.column as any).id,
48+
});
3249
setCalendarState(date);
3350
setShowCalendar(false);
34-
setValue({
35-
value: DateTime.fromJSDate(date).toFormat("yyyy-MM-dd"),
51+
setContextValue({
52+
value: newValue,
3653
update: true,
3754
});
3855
}
@@ -57,7 +74,7 @@ const CalendarPortal = (calendarProps: CalendarProps) => {
5774
padding: "0.5rem",
5875
background: StyleVariables.BACKGROUND_SECONDARY,
5976
}}
60-
onBlur={() => setShowCalendar(false)}
77+
onMouseLeave={() => setShowCalendar(false)}
6178
>
6279
<Calendar onChange={handleCalendarChange} value={calendarState} />
6380
</div>
@@ -69,8 +86,13 @@ const CalendarPortal = (calendarProps: CalendarProps) => {
6986
className="data-input calendar"
7087
ref={setCalendarRef}
7188
onClick={handlerOnClick}
89+
onBlur={() => setShowCalendar(false)}
7290
>
73-
<span>{value.value}</span>
91+
<span>
92+
{DateTime.isDateTime(contextValue.value)
93+
? contextValue.value.toFormat("yyyy-MM-dd")
94+
: ""}
95+
</span>
7496
</div>
7597
{showCalendar &&
7698
ReactDOM.createPortal(

src/components/portals/PopperSelectPortal.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { CellContext } from "components/contexts/CellContext";
1111
const PopperSelectPortal = (popperProps: PopperProps) => {
1212
const { dispatch, row, column, columns, note, state } = popperProps;
1313
/** state of cell value */
14-
const { value, setValue } = useContext(CellContext);
14+
const { contextValue, setContextValue } = useContext(CellContext);
1515
// Selector reference state
1616
const [selectRef, setSelectRef] = useState(null);
1717
const [showSelect, setShowSelect] = useState(false);
@@ -31,7 +31,7 @@ const PopperSelectPortal = (popperProps: PopperProps) => {
3131
}
3232

3333
function handleOptionClick(option: { label: string; backgroundColor?: any }) {
34-
setValue({ value: option.label, update: true });
34+
setContextValue({ value: option.label, update: true });
3535
setShowSelect(false);
3636
// save on disk & move file if its configured on the column
3737
dispatch({
@@ -78,7 +78,7 @@ const PopperSelectPortal = (popperProps: PopperProps) => {
7878

7979
function getColor() {
8080
const match = (column as any).options.find(
81-
(option: { label: any }) => option.label === value.value
81+
(option: { label: any }) => option.label === contextValue.value
8282
);
8383
return (match && match.backgroundColor) || grey(200);
8484
}
@@ -170,8 +170,11 @@ const PopperSelectPortal = (popperProps: PopperProps) => {
170170
className="cell-padding d-flex cursor-default align-items-center flex-1"
171171
onClick={() => setShowSelect(true)}
172172
>
173-
{value.value && (
174-
<Relationship value={value.value} backgroundColor={getColor()} />
173+
{contextValue.value && (
174+
<Relationship
175+
value={contextValue.value}
176+
backgroundColor={getColor()}
177+
/>
175178
)}
176179
</div>
177180
{domReady

src/components/reducers/DatabaseDispatch.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ export function databaseReducer(state: TableDataType, action: ActionType) {
268268
...state.columns.slice(0, leftIndex),
269269
{
270270
...TableColumnsTemplate,
271+
dataType: newLeftColumn.input,
271272
id: newLeftColumn.accessor,
272273
label: newLeftColumn.label,
273274
key: newLeftColumn.key,
@@ -306,6 +307,7 @@ export function databaseReducer(state: TableDataType, action: ActionType) {
306307
...state.columns.slice(0, rightIndex + 1),
307308
{
308309
...TableColumnsTemplate,
310+
dataType: newRIghtColumn.input,
309311
id: newRIghtColumn.accessor,
310312
label: newRIghtColumn.label,
311313
key: newRIghtColumn.key,
Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
11
import { TableColumn } from "cdm/FolderModel";
22
import { ColumnWidthState } from "cdm/StyleModel";
3-
import { MetadataColumns, WidthVariables } from "helpers/Constants";
3+
import { DataTypes, MetadataColumns, WidthVariables } from "helpers/Constants";
44
import { getNormalizedPath } from "helpers/VaultManagement";
5+
import { DateTime } from "luxon";
56
import { Row } from "react-table";
67

7-
export const getColumnWidthStyle = (rows: Array<Row<object>>, accessor: string, headerText: string, customMaxWidth?: number): number => {
8+
export const getColumnWidthStyle = (rows: Array<Row<object>>, column: TableColumn, customMaxWidth?: number): number => {
89
const maxWidth = (customMaxWidth ?? 400)
910

1011
const cellLength = Math.max(
11-
...rows.map((row: any) => lengthOfNormalizeCellValue(row, accessor)),
12-
headerText.length, WidthVariables.ICON_SPACING
12+
...rows.map((row: any) => lengthOfNormalizeCellValue(row, column)),
13+
column.label.length, WidthVariables.ICON_SPACING
1314
)
1415
return Math.min(maxWidth, cellLength * WidthVariables.MAGIC_SPACING)
1516
}
1617

17-
const lengthOfNormalizeCellValue = (row: any, accessor: string): number => {
18-
const value = (`${row.original[accessor]}` || '');
19-
switch (accessor) {
20-
case MetadataColumns.FILE:
21-
return getNormalizedPath(value).alias.length
18+
/**
19+
* Obtain length of a cell value in function of its type and render strategy
20+
* @param row
21+
* @param column
22+
* @returns
23+
*/
24+
const lengthOfNormalizeCellValue = (row: any, column: TableColumn): number => {
25+
const value = (`${row.original[column.key]}` || '');
26+
let result = 0;
27+
switch (column.dataType) {
28+
case DataTypes.MARKDOWN:
29+
result = getNormalizedPath(value).alias.length
30+
break;
31+
case DataTypes.CALENDAR:
32+
result = DateTime.isDateTime(value) ? value.toFormat('yyyy-MM-dd').length : 0
33+
break;
34+
default:
35+
result = value.length
2236
}
23-
return value.length
37+
return result
2438
}
2539

2640
export const getColumnsWidthStyle = (rows: Array<Row<object>>, columns: TableColumn[]): ColumnWidthState => {
2741
const columnWidthStyle: ColumnWidthState = {
2842
widthRecord: {}
2943
}
3044
columns.forEach((column: TableColumn) => {
31-
columnWidthStyle.widthRecord[column.id] = getColumnWidthStyle(rows, column.key, column.label);
45+
columnWidthStyle.widthRecord[column.id] = getColumnWidthStyle(rows, column);
3246
})
3347
return columnWidthStyle
3448
}

src/helpers/Constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ export const MetadataDatabaseColumns = Object.freeze({
8888

8989
export const TableColumnsTemplate: Partial<TableColumn> =
9090
{
91-
dataType: DataTypes.TEXT,
9291
isMetadata: false,
9392
skipPersist: false,
9493
isInline: false,

0 commit comments

Comments
 (0)