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

Commit 0cb5b2d

Browse files
committed
Refactor to achive Literal support of dtaview
1 parent 8053c8f commit 0cb5b2d

File tree

9 files changed

+107
-90
lines changed

9 files changed

+107
-90
lines changed

src/DatabaseView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export class DatabaseView extends TextFileView implements HoverParent {
130130
const columns = await obtainColumnsFromFolder(yamlColumns);
131131
const rows = await adapterTFilesToRows(
132132
this.file.parent.path,
133+
columns,
133134
this.diskConfig.yaml.filters
134135
);
135136
// Define table properties

src/components/Cell.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { CellContext } from "components/contexts/CellContext";
1010
import { c } from "helpers/StylesHelper";
1111
import CalendarPortal from "./portals/CalendarPortal";
1212
import { TableColumn } from "cdm/FolderModel";
13+
import { DataviewService } from "services/DataviewService";
1314

1415
/**
1516
* Obtain the path of the file inside cellValue
@@ -129,6 +130,7 @@ export default function DefaultCell(cellProperties: Cell) {
129130
return <span ref={containerRef} className={`${c("md_cell")}`}></span>;
130131
/** Selector option */
131132
case DataTypes.SELECT:
133+
console.log("selector");
132134
return (
133135
<CellContext.Provider value={{ contextValue, setContextValue }}>
134136
<PopperSelectPortal

src/components/contexts/CellContext.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Literal } from "obsidian-dataview/lib/data-model/value";
22
import React from "react";
3+
import NoteInfo from "services/NoteInfo";
34

45
export type CellDataType = {
5-
value: Literal;
6+
value: Literal | NoteInfo;
67
update: boolean;
78
};
89

src/components/portals/CalendarPortal.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { TableColumn, TableDataType } from "cdm/FolderModel";
22
import { CellContext } from "components/contexts/CellContext";
3-
import { ActionTypes, StyleVariables } from "helpers/Constants";
3+
import { ActionTypes, DataTypes, 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";
99
import { Cell } from "react-table";
1010
import NoteInfo from "services/NoteInfo";
11+
import { DataviewService } from "services/DataviewService";
1112

1213
type CalendarProps = {
1314
intialState: TableDataType;
@@ -30,9 +31,12 @@ const CalendarPortal = (calendarProps: CalendarProps) => {
3031
const note: NoteInfo = (cellProperties.row.original as any).note;
3132

3233
const [calendarState, setCalendarState] = useState(
33-
DateTime.isDateTime(contextValue.value)
34-
? contextValue.value.toJSDate()
35-
: new Date()
34+
(
35+
DataviewService.parseLiteral(
36+
contextValue.value,
37+
DataTypes.CALENDAR
38+
) as DateTime
39+
).toJSDate()
3640
);
3741

3842
function handleCalendarChange(date: Date) {
@@ -89,9 +93,7 @@ const CalendarPortal = (calendarProps: CalendarProps) => {
8993
onBlur={() => setShowCalendar(false)}
9094
>
9195
<span>
92-
{DateTime.isDateTime(contextValue.value)
93-
? contextValue.value.toFormat("yyyy-MM-dd")
94-
: ""}
96+
{DataviewService.parseLiteral(contextValue.value, DataTypes.TEXT)}
9597
</span>
9698
</div>
9799
{showCalendar &&

src/components/reducers/DatabaseDispatch.tsx

Lines changed: 53 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { moveFile, updateRowFile } from "helpers/VaultManagement";
1515
import { randomColor } from "helpers/Colors";
1616
import { DatabaseColumn, RowDatabaseFields } from "cdm/DatabaseModel";
1717
import NoteInfo from "services/NoteInfo";
18+
import { DataviewService } from "services/DataviewService";
1819

1920
export function databaseReducer(state: TableDataType, action: ActionType) {
2021
LOGGER.debug(
@@ -151,55 +152,41 @@ export function databaseReducer(state: TableDataType, action: ActionType) {
151152
const typeIndex = state.columns.findIndex(
152153
(column) => column.id === action.columnId
153154
);
155+
/** Check if type is changed */
156+
if (state.columns[typeIndex].dataType === action.dataType) {
157+
return state;
158+
}
159+
/** If changed, then parsed information */
154160
// Update configuration on disk
155161
state.view.diskConfig.updateColumnProperties(action.columnId, {
156162
input: action.dataType,
157163
});
164+
// Parse data
165+
const parsedData = state.data.map((row: any) => ({
166+
...row,
167+
[action.columnId]: DataviewService.parseLiteral(
168+
row[action.columnId],
169+
action.dataType // Destination type to parse
170+
),
171+
}));
158172
// Update state
159173
switch (action.dataType) {
160-
case DataTypes.NUMBER:
161-
if (state.columns[typeIndex].dataType === DataTypes.NUMBER) {
162-
return state;
163-
} else {
164-
return {
165-
...state,
166-
columns: [
167-
...state.columns.slice(0, typeIndex),
168-
{ ...state.columns[typeIndex], dataType: action.dataType },
169-
...state.columns.slice(typeIndex + 1, state.columns.length),
170-
],
171-
data: state.data.map((row: any) => ({
172-
...row,
173-
[action.columnId]: isNaN(row[action.columnId])
174-
? ""
175-
: Number.parseInt(row[action.columnId]),
176-
})),
177-
};
178-
}
179174
case DataTypes.SELECT:
180-
if (state.columns[typeIndex].dataType === DataTypes.SELECT) {
181-
return {
182-
...state,
183-
columns: [
184-
...state.columns.slice(0, typeIndex),
185-
{ ...state.columns[typeIndex], dataType: action.dataType },
186-
...state.columns.slice(typeIndex + 1, state.columns.length),
187-
],
188-
skipReset: true,
189-
};
190-
} else {
191-
const options: any = [];
192-
state.data.forEach((row) => {
193-
if (row[action.columnId]) {
194-
options.push({
195-
label: row[action.columnId],
196-
backgroundColor: randomColor(),
197-
});
198-
}
199-
});
200-
return {
201-
...state,
202-
columns: [
175+
const options: any = [];
176+
// Generate selected options
177+
parsedData.forEach((row) => {
178+
if (row[action.columnId]) {
179+
options.push({
180+
label: row[action.columnId],
181+
backgroundColor: randomColor(),
182+
});
183+
}
184+
});
185+
// Update column to SELECT type
186+
return update(state, {
187+
skipReset: { $set: true },
188+
columns: {
189+
$set: [
203190
...state.columns.slice(0, typeIndex),
204191
{
205192
...state.columns[typeIndex],
@@ -208,39 +195,34 @@ export function databaseReducer(state: TableDataType, action: ActionType) {
208195
},
209196
...state.columns.slice(typeIndex + 1, state.columns.length),
210197
],
211-
skipReset: true,
212-
};
213-
}
214-
case DataTypes.TEXT:
215-
if (state.columns[typeIndex].dataType === DataTypes.TEXT) {
216-
return state;
217-
} else if (state.columns[typeIndex].dataType === DataTypes.SELECT) {
218-
return {
219-
...state,
220-
skipReset: true,
221-
columns: [
222-
...state.columns.slice(0, typeIndex),
223-
{ ...state.columns[typeIndex], dataType: action.dataType },
224-
...state.columns.slice(typeIndex + 1, state.columns.length),
225-
],
226-
};
227-
} else {
228-
return {
229-
...state,
230-
skipReset: true,
231-
columns: [
198+
},
199+
data: {
200+
$set: parsedData,
201+
},
202+
});
203+
default:
204+
/**
205+
* GENERIC update change
206+
* Update column dataType & parsed data
207+
* Aplied to:
208+
* - TEXT
209+
* - NUMBER
210+
* - CALENDAR
211+
*/
212+
console.log("GENERIC update change");
213+
return update(state, {
214+
skipReset: { $set: true },
215+
columns: {
216+
$set: [
232217
...state.columns.slice(0, typeIndex),
233218
{ ...state.columns[typeIndex], dataType: action.dataType },
234219
...state.columns.slice(typeIndex + 1, state.columns.length),
235220
],
236-
data: state.data.map((row) => ({
237-
...row,
238-
[action.columnId]: row[action.columnId] + "",
239-
})),
240-
};
241-
}
242-
default:
243-
return state;
221+
},
222+
data: {
223+
$set: parsedData,
224+
},
225+
});
244226
}
245227
/**
246228
* Add new column to the table to the left of the column with the given id

src/helpers/VaultManagement.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { RowDataType, NormalizedPath, TableDataType } from 'cdm/FolderModel';
1+
import { RowDataType, NormalizedPath, TableDataType, TableColumn } from 'cdm/FolderModel';
22
import { TFile } from 'obsidian';
33
import { ActionType } from 'react-table';
44
import { VaultManagerDB } from 'services/FileManagerService';
@@ -62,20 +62,23 @@ export function getNormalizedPath(path: string): NormalizedPath {
6262
* @param folderPath
6363
* @returns
6464
*/
65-
export async function adapterTFilesToRows(folderPath: string, filters?: FilterCondition[]): Promise<Array<RowDataType>> {
65+
export async function adapterTFilesToRows(folderPath: string, columns: TableColumn[], filters: FilterCondition[]): Promise<Array<RowDataType>> {
6666
LOGGER.debug(`=> adapterTFilesToRows. folderPath:${folderPath}`);
6767
const rows: Array<RowDataType> = [];
6868
let id = 0;
6969

7070
let folderFiles = DataviewService.getDataviewAPI().pages(`"${folderPath}"`)
7171
.where(p => !p[DatabaseCore.FRONTMATTER_KEY]);
72+
// Config filters asociated with the database
7273
if (filters) {
7374
folderFiles = folderFiles.where(p => DataviewService.filter(filters, p));
7475
}
75-
await Promise.all(folderFiles.map(async (page) => {
76+
77+
folderFiles.map(async (page) => {
7678
const noteInfo = new NoteInfo(page, ++id);
77-
rows.push(noteInfo.getRowDataType());
78-
}));
79+
rows.push(noteInfo.getRowDataType(columns));
80+
});
81+
7982
LOGGER.debug(`<= adapterTFilesToRows. number of rows:${rows.length}`);
8083
return rows;
8184
}

src/services/DataviewService.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { FilterCondition } from "cdm/DatabaseModel";
2-
import { getOperatorFilterValue, OperatorFilter } from "helpers/Constants";
2+
import { DataTypes, getOperatorFilterValue, OperatorFilter } from "helpers/Constants";
33
import { Notice } from "obsidian";
44
import { getAPI, isPluginEnabled } from "obsidian-dataview";
55
import { Literal } from "obsidian-dataview/lib/data-model/value";
66
import { DvAPIInterface } from "obsidian-dataview/lib/typings/api";
7+
import { DateTime } from "luxon";
8+
import NoteInfo from "./NoteInfo";
79
class DataviewProxy {
810

911
private static instance: DataviewProxy;
@@ -59,8 +61,24 @@ class DataviewProxy {
5961
}
6062
}
6163

62-
parseLiteral(literal: Literal): Literal {
63-
return literal;
64+
parseLiteral(literal: Literal | NoteInfo, dataTypeDst: string): Literal | NoteInfo {
65+
let parsedLiteral: Literal | NoteInfo;
66+
// Check empty or undefined literals
67+
switch (dataTypeDst) {
68+
case DataTypes.CALENDAR:
69+
// Check if original literal is a date. If not convert to current date
70+
parsedLiteral = DateTime.isDateTime(literal) ? literal : DateTime.now();
71+
break;
72+
case DataTypes.NUMBER:
73+
parsedLiteral = isNaN(literal as any) ? ""
74+
: Number.parseInt(literal as string);
75+
break;
76+
default:
77+
parsedLiteral = DateTime.isDateTime(literal) ? literal.toFormat("yyyy-MM-dd")
78+
: literal;
79+
80+
}
81+
return parsedLiteral;
6482
}
6583
/**
6684
* Singleton instance

src/services/NoteInfo.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { RowDataType } from "cdm/FolderModel";
1+
import { RowDataType, TableColumn } from "cdm/FolderModel";
22
import { MetadataColumns } from "helpers/Constants";
33
import { TFile } from "obsidian";
44
import { VaultManagerDB } from "services/FileManagerService";
55
import { DateTime } from "luxon";
6+
import { DataviewService } from "./DataviewService";
67
/**
78
* Keep info about a note and offer methods to manipulate it
89
*/
@@ -16,7 +17,7 @@ export default class NoteInfo {
1617
this.id = id;
1718
}
1819

19-
getRowDataType(): RowDataType {
20+
getRowDataType(columns: TableColumn[]): RowDataType {
2021
/** Mandatory fields */
2122
const aFile: RowDataType = {
2223
id: this.id,
@@ -26,11 +27,18 @@ export default class NoteInfo {
2627
aFile[MetadataColumns.FILE] = `${this.page.file.link.markdown()}`;
2728
aFile[MetadataColumns.CREATED] = this.page.file.ctime;
2829
aFile[MetadataColumns.MODIFIED] = this.page.file.mtime;
30+
2931
/** Optional fields */
3032
Object.keys(this.page).forEach(property => {
3133
const value = this.page[property];
3234
aFile[property] = value;
3335
});
36+
/** parse the data with the type of column */
37+
columns.forEach(column => {
38+
if (aFile[column.key] !== undefined) {
39+
aFile[column.key] = DataviewService.parseLiteral(aFile[column.key], column.dataType);
40+
}
41+
});
3442
return aFile;
3543
}
3644

src/settings/handlers/columns/RemoveFieldsWhenDeleteToggleHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class RemoveFieldsWhenDeleteToggleHandler extends AbstractSettingsHandler
2222
add_toggle(
2323
containerEl,
2424
this.settingTitle,
25-
"Enable/disable remove fields when delete a column",
25+
"Enable/disable remove fields when a column is deleted",
2626
local ? view.diskConfig.yaml.config.remove_field_when_delete_column : settingsManager.plugin.settings.local_settings.remove_field_when_delete_column,
2727
remove_fields_toggle_promise
2828
);

0 commit comments

Comments
 (0)