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

Commit 5ef85ff

Browse files
committed
Merge branch '17-fr-image-column-type'
2 parents 87d8438 + 0c18caa commit 5ef85ff

File tree

8 files changed

+114
-31
lines changed

8 files changed

+114
-31
lines changed

src/cdm/DatabaseModel.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { RowType } from "cdm/RowTypeModel"
22
import { Literal } from "obsidian-dataview/lib/data-model/value";
3+
import { Cell } from "react-table";
34
import { LocalSettings } from "Settings"
5+
import { TableColumn, TableDataType } from "cdm/FolderModel";
46

57
/** database column */
68
export interface DatabaseColumn {
@@ -44,4 +46,10 @@ export type FilterCondition = {
4446
export type OptionSelect = {
4547
label: string;
4648
backgroundColor: string;
47-
}
49+
}
50+
51+
export type CalendarProps = {
52+
intialState: TableDataType;
53+
column: TableColumn;
54+
cellProperties: Cell;
55+
};

src/components/Cell.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { CellContext } from "components/contexts/CellContext";
99
import { c } from "helpers/StylesHelper";
1010
import CalendarPortal from "./portals/CalendarPortal";
1111
import { TableColumn } from "cdm/FolderModel";
12+
import CalendarTimePortal from "./portals/CalendarTimePortal";
1213

1314
export default function DefaultCell(cellProperties: Cell) {
1415
const dataDispatch = (cellProperties as any).dataDispatch;
@@ -75,8 +76,8 @@ export default function DefaultCell(cellProperties: Cell) {
7576
};
7677

7778
const handlerEditableOnBlur = (event: any) => {
78-
setDirtyCell(false);
7979
setContextValue((event) => ({ value: event.value, update: true }));
80+
setDirtyCell(false);
8081
};
8182

8283
// onChange handler
@@ -107,16 +108,13 @@ export default function DefaultCell(cellProperties: Cell) {
107108
row: cellProperties.row,
108109
columnId: (cellProperties.column as any).id,
109110
});
110-
setDirtyCell(false);
111111
}
112112

113113
function getCellElement() {
114114
switch (dataType) {
115115
/** Plain text option */
116116
case DataTypes.TEXT:
117-
return (cellProperties.column as any).isMetadata ? (
118-
<span className="data-input">{contextValue.value.toString()}</span>
119-
) : dirtyCell ? (
117+
return dirtyCell ? (
120118
<input
121119
value={(contextValue.value && contextValue.value.toString()) || ""}
122120
onChange={handleOnChange}
@@ -156,9 +154,13 @@ export default function DefaultCell(cellProperties: Cell) {
156154
/** Calendar with time option */
157155
case DataTypes.CALENDAR_TIME:
158156
return (
159-
<span className="data-input calendar-time">
160-
{contextValue.value.toString()}
161-
</span>
157+
<CellContext.Provider value={{ contextValue, setContextValue }}>
158+
<CalendarTimePortal
159+
intialState={(cellProperties as any).initialState}
160+
column={cellProperties.column as unknown as TableColumn}
161+
cellProperties={cellProperties}
162+
/>
163+
</CellContext.Provider>
162164
);
163165

164166
/** Selector option */

src/components/HeaderMenu.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { DatabaseHeaderProps } from "cdm/FolderModel";
2-
import { ActionTypes, DataTypes, StyleVariables } from "helpers/Constants";
2+
import {
3+
ActionTypes,
4+
DataTypes,
5+
MetadataLabels,
6+
StyleVariables,
7+
} from "helpers/Constants";
38
import { dbTrim, c } from "helpers/StylesHelper";
49
import ArrowUpIcon from "components/img/ArrowUp";
510
import ArrowDownIcon from "components/img/ArrowDown";
@@ -9,6 +14,7 @@ import TrashIcon from "components/img/Trash";
914
import TextIcon from "components/img/Text";
1015
import MultiIcon from "components/img/Multi";
1116
import HashIcon from "components/img/Hash";
17+
import CalendarTimeIcon from "components/img/CalendarTime";
1218
import CalendarIcon from "components/img/CalendarIcon";
1319
import AdjustmentsIcon from "components/img/AdjustmentsIcon";
1420
import React, { useContext, useEffect, useState } from "react";
@@ -214,6 +220,19 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
214220
icon: <CalendarIcon />,
215221
label: DataTypes.CALENDAR,
216222
},
223+
{
224+
onClick: (e: any) => {
225+
dispatch({
226+
type: ActionTypes.UPDATE_COLUMN_TYPE,
227+
columnId: column.id,
228+
dataType: DataTypes.CALENDAR_TIME,
229+
});
230+
setShowType(false);
231+
setExpanded(false);
232+
},
233+
icon: <CalendarTimeIcon />,
234+
label: MetadataLabels.CALENDAR_TIME,
235+
},
217236
];
218237

219238
const typePopper = usePopper(typeReferenceElement, typePopperElement, {
@@ -468,9 +487,7 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
468487
control={
469488
<Switch
470489
checked={isInline}
471-
onChange={(event) => {
472-
handleChangeToggleInlineFrontmatter(event);
473-
}}
490+
onChange={handleChangeToggleInlineFrontmatter}
474491
/>
475492
}
476493
label="Inline"

src/components/portals/CalendarPortal.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
import { TableColumn, TableDataType } from "cdm/FolderModel";
21
import { CellContext } from "components/contexts/CellContext";
32
import { ActionTypes } from "helpers/Constants";
43
import React, { useContext, useState } from "react";
54
import { DateTime } from "luxon";
6-
import { Cell } from "react-table";
75
import DatePicker from "react-datepicker";
86
import NoteInfo from "services/NoteInfo";
97
import { Portal } from "@material-ui/core";
8+
import { CalendarProps } from "cdm/DatabaseModel";
109

11-
type CalendarProps = {
12-
intialState: TableDataType;
13-
column: TableColumn;
14-
cellProperties: Cell;
15-
};
1610
const CalendarPortal = (calendarProps: CalendarProps) => {
1711
const { column, cellProperties } = calendarProps;
1812
const dataDispatch = (cellProperties as any).dataDispatch;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { CellContext } from "components/contexts/CellContext";
2+
import { ActionTypes } from "helpers/Constants";
3+
import React, { useContext, useState } from "react";
4+
import { DateTime } from "luxon";
5+
import DatePicker from "react-datepicker";
6+
import NoteInfo from "services/NoteInfo";
7+
import { Portal } from "@material-ui/core";
8+
import { CalendarProps } from "cdm/DatabaseModel";
9+
10+
const CalendarTimePortal = (calendarProps: CalendarProps) => {
11+
const { column, cellProperties } = calendarProps;
12+
const dataDispatch = (cellProperties as any).dataDispatch;
13+
// Selector reference state
14+
15+
// Selector popper state
16+
/** state of cell value */
17+
const { contextValue, setContextValue } = useContext(CellContext);
18+
19+
/** Note info of current Cell */
20+
const note: NoteInfo = (cellProperties.row.original as any).note;
21+
const [calendarState, setCalendarState] = useState(
22+
DateTime.isDateTime(contextValue.value)
23+
? contextValue.value.toJSDate()
24+
: null
25+
);
26+
27+
function handleCalendarChange(date: Date) {
28+
const newValue = DateTime.fromJSDate(date);
29+
// save on disk
30+
dataDispatch({
31+
type: ActionTypes.UPDATE_CELL,
32+
file: note.getFile(),
33+
key: column.key,
34+
value: DateTime.fromJSDate(date).toFormat("yyyy-MM-dd"),
35+
row: cellProperties.row,
36+
columnId: column.id,
37+
});
38+
39+
setCalendarState(date);
40+
setContextValue({
41+
value: newValue,
42+
update: true,
43+
});
44+
}
45+
46+
const CalendarContainer = (containerProps: any) => {
47+
const el = document.getElementById("popper-container");
48+
return <Portal container={el}>{containerProps.children}</Portal>;
49+
};
50+
51+
return column.isMetadata ? (
52+
<span className="data-input calendar-time">
53+
{(contextValue.value as DateTime).toFormat("yyyy-MM-dd h:mm a")}
54+
</span>
55+
) : (
56+
<div className="data-input calendar-time">
57+
<DatePicker
58+
dateFormat="yyyy-MM-dd h:mm aa"
59+
selected={calendarState}
60+
onChange={handleCalendarChange}
61+
popperContainer={CalendarContainer}
62+
timeInputLabel="Time:"
63+
showTimeInput
64+
placeholderText="Pick a moment..."
65+
/>
66+
</div>
67+
);
68+
};
69+
70+
export default CalendarTimePortal;

src/components/reducers/DatabaseDispatch.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export function databaseReducer(state: TableDataType, action: ActionType) {
213213
* - TEXT
214214
* - NUMBER
215215
* - CALENDAR
216+
* - CALENDAR_TIME
216217
*/
217218
return update(state, {
218219
skipReset: { $set: true },

src/helpers/Constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const MetadataLabels = Object.freeze({
4141
ADD_COLUMN: '+',
4242
CREATED: 'Created',
4343
MODIFIED: 'Modified',
44+
CALENDAR_TIME: 'Calendar time',
4445
});
4546

4647
export const MetadataDatabaseColumns = Object.freeze({

src/services/DataviewService.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,8 @@ class DataviewProxy {
6666
// Check empty or undefined literals
6767
switch (dataTypeDst) {
6868
case DataTypes.CALENDAR:
69-
parsedLiteral = this.parseToCalendar(wrapped);
70-
break;
7169
case DataTypes.CALENDAR_TIME:
72-
parsedLiteral = this.parseToCalendarTime(wrapped);
70+
parsedLiteral = this.parseToCalendar(wrapped);
7371
break;
7472
case DataTypes.NUMBER:
7573
parsedLiteral = wrapped.type === 'number' ? literal : Number(literal);
@@ -107,14 +105,6 @@ class DataviewProxy {
107105
return null;
108106
}
109107
}
110-
111-
private parseToCalendarTime(literal: WrappedLiteral): Literal {
112-
if (literal.type === 'string') {
113-
return DateTime.fromISO(literal.value);
114-
} else {
115-
return literal.value;
116-
}
117-
}
118108
}
119109

120110
export const DataviewService = DataviewProxy.getInstance();

0 commit comments

Comments
 (0)