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

Commit d6daca8

Browse files
committed
Merge branch '39-fr-select-a-file-as-template-and-create-the-columns-based-on-the-fields'
2 parents b7a6071 + 68495bd commit d6daca8

34 files changed

+346
-218
lines changed

src/DatabaseView.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DatabaseColumn } from "cdm/DatabaseModel";
2-
import { InitialState, TableDataType } from "cdm/FolderModel";
2+
import { InitialState, RowDataType, TableDataType } from "cdm/FolderModel";
33
import {
44
obtainColumnsFromFolder,
55
obtainMetadataColumns,
@@ -32,7 +32,7 @@ export class DatabaseView extends TextFileView implements HoverParent {
3232
hoverPopover: HoverPopover | null;
3333
tableContainer: HTMLDivElement | null = null;
3434
diskConfig: DatabaseInfo;
35-
35+
rows: Array<RowDataType>;
3636
constructor(leaf: WorkspaceLeaf, plugin: DBFolderPlugin) {
3737
super(leaf);
3838
this.plugin = plugin;
@@ -129,24 +129,22 @@ export class DatabaseView extends TextFileView implements HoverParent {
129129
);
130130
// Obtain base information about columns
131131
const columns = await obtainColumnsFromFolder(yamlColumns);
132-
const rows = await adapterTFilesToRows(
132+
this.rows = adapterTFilesToRows(
133133
this.file.parent.path,
134134
columns,
135135
this.diskConfig.yaml
136136
);
137-
const initialState: InitialState = obtainInitialState(columns, rows);
137+
const initialState: InitialState = obtainInitialState(columns, this.rows);
138138

139139
// Define table properties
140140
const tableProps: TableDataType = {
141141
columns: columns,
142142
shadowColumns: columns.filter((col) => col.skipPersist),
143-
data: rows,
144143
skipReset: false,
145144
view: this,
146145
stateManager: this.plugin.getStateManager(this.file),
147146
initialState: initialState,
148147
cellSize: this.diskConfig.yaml.config.cell_size,
149-
stickyFirstColumn: this.diskConfig.yaml.config.sticky_first_column
150148
};
151149

152150
// Render database

src/Settings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import DBFolderPlugin from 'main';
44
import { DatabaseView } from "DatabaseView";
55
import { LOGGER } from "services/Logger";
66
import { developer_settings_section } from "settings/DeveloperSection";
7-
import { columns_settings_section } from "settings/ColumnsSection";
7+
import columns_settings_section from "settings/ColumnsSection";
88
import { folder_settings_section } from "settings/FolderSection";
99
import { StyleClasses } from "helpers/Constants";
1010
import { SettingHandlerResponse } from "settings/handlers/AbstractSettingHandler";
@@ -79,7 +79,7 @@ export class SettingsManager {
7979
folder_settings_section(settingHandlerResponse);
8080
}
8181
/** Columns section */
82-
columns_settings_section(settingHandlerResponse);
82+
columns_settings_section.run(settingHandlerResponse);
8383
/** Media section */
8484
media_settings_section(settingHandlerResponse);
8585
/** Developer section */

src/cdm/FolderModel.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export interface TableColumn extends BaseColumn {
6767

6868
export type RowDataType = {
6969
id: number,
70-
note: NoteInfo,
70+
__note__: NoteInfo,
7171
[key: string]: Literal | NoteInfo
7272
}
7373

@@ -82,19 +82,17 @@ export type InitialState = {
8282
export type TableDataType = {
8383
columns: TableColumn[],
8484
shadowColumns: TableColumn[],
85-
data: Array<RowDataType>,
8685
skipReset: boolean,
8786
view: DatabaseView,
8887
stateManager: StateManager,
8988
dispatch?: Dispatch<any>,
9089
initialState?: InitialState,
9190
cellSize: string,
92-
stickyFirstColumn: boolean
9391
}
9492
export interface DatabaseHeaderProps {
9593
columns: any,
9694
data: any,
97-
initialState: TableDataType,
95+
tableData: TableDataType,
9896
defaultColumn: any,
9997
getSubRows: any,
10098
getRowId: any,

src/components/Cell.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default function DefaultCell(cellProperties: Cell) {
2424
/** Type of cell */
2525
const dataType = (cellProperties.column as any).dataType;
2626
/** Note info of current Cell */
27-
const note: NoteInfo = (cellProperties.row.original as any).note;
27+
const note: NoteInfo = (cellProperties.row.original as any).__note__;
2828
/** Ref to cell container */
2929
const containerCellRef = useRef<HTMLDivElement>();
3030
const editableMdRef = useRef<HTMLInputElement>();
@@ -38,8 +38,8 @@ export default function DefaultCell(cellProperties: Cell) {
3838
const [editNoteTimeout, setEditNoteTimeout] = useState(null);
3939
const [dirtyCell, setDirtyCell] = useState(false);
4040

41-
const initialState = (cellProperties as any)
42-
.initialState as unknown as TableDataType;
41+
const tableData = (cellProperties as any)
42+
.tableData as unknown as TableDataType;
4343
const column = cellProperties.column as unknown as TableColumn;
4444
/** states for selector option */
4545
LOGGER.debug(
@@ -58,8 +58,8 @@ export default function DefaultCell(cellProperties: Cell) {
5858
contextValue.value,
5959
false,
6060
taskRef.current,
61-
initialState.view,
62-
initialState.view.file.path
61+
tableData.view,
62+
tableData.view.file.path
6363
);
6464
break;
6565
case DataTypes.MARKDOWN:
@@ -81,7 +81,11 @@ export default function DefaultCell(cellProperties: Cell) {
8181
}, [editableMdRef, dirtyCell]);
8282

8383
useEffect(() => {
84-
if (!dirtyCell && containerCellRef.current !== undefined) {
84+
if (
85+
!dirtyCell &&
86+
containerCellRef.current !== undefined &&
87+
dataType !== DataTypes.MARKDOWN
88+
) {
8589
LOGGER.debug(
8690
`useEffect hooked with dirtyCell. Value:${contextValue.value}`
8791
);
@@ -195,7 +199,7 @@ export default function DefaultCell(cellProperties: Cell) {
195199
case DataTypes.CALENDAR:
196200
return (
197201
<CalendarPortal
198-
intialState={initialState}
202+
intialState={tableData}
199203
column={column}
200204
cellProperties={cellProperties}
201205
/>
@@ -205,7 +209,7 @@ export default function DefaultCell(cellProperties: Cell) {
205209
case DataTypes.CALENDAR_TIME:
206210
return (
207211
<CalendarTimePortal
208-
intialState={initialState}
212+
intialState={tableData}
209213
column={column}
210214
cellProperties={cellProperties}
211215
/>
@@ -221,7 +225,7 @@ export default function DefaultCell(cellProperties: Cell) {
221225
column={column}
222226
columns={columns}
223227
note={note}
224-
intialState={initialState}
228+
intialState={tableData}
225229
/>
226230
</CellContext.Provider>
227231
);
@@ -230,7 +234,7 @@ export default function DefaultCell(cellProperties: Cell) {
230234
return (
231235
<CellContext.Provider value={{ contextValue, setContextValue }}>
232236
<TagsPortal
233-
intialState={initialState}
237+
intialState={tableData}
234238
column={column}
235239
columns={columns}
236240
dispatch={dataDispatch}
@@ -246,7 +250,7 @@ export default function DefaultCell(cellProperties: Cell) {
246250
return (
247251
<CellContext.Provider value={{ contextValue, setContextValue }}>
248252
<CheckboxCell
249-
intialState={initialState}
253+
intialState={tableData}
250254
column={column}
251255
cellProperties={cellProperties}
252256
/>

src/components/Checkbox.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ type CheckboxProps = {
1111
cellProperties: Cell;
1212
};
1313
export function CheckboxCell(props: CheckboxProps) {
14-
const { intialState, column, cellProperties } = props;
14+
const { column, cellProperties } = props;
1515
const dataDispatch = (cellProperties as any).dataDispatch;
1616
/** Note info of current Cell */
17-
const note: NoteInfo = (cellProperties.row.original as any).note;
17+
const note: NoteInfo = (cellProperties.row.original as any).__note__;
1818
/** state of cell value */
1919
const { contextValue, setContextValue } = useContext(CellContext);
2020
const [checked, setChecked] = useState(contextValue.value === 1);

src/components/Columns.tsx

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import {
22
DataTypes,
3+
DEFAULT_COLUMN_CONFIG,
34
MaxCapacitiesDatabase,
45
MetadataColumns,
56
MetadataDatabaseColumns,
67
} from "helpers/Constants";
7-
import { TableColumn } from "cdm/FolderModel";
8+
import { RowDataType, TableColumn } from "cdm/FolderModel";
89
import { LOGGER } from "services/Logger";
910
import { DatabaseColumn } from "cdm/DatabaseModel";
1011
import { RowSelectOption } from "cdm/ComponentsModel";
1112
import { LocalSettings } from "cdm/SettingsModel";
1213
import { dbTrim } from "helpers/StylesHelper";
14+
import { TFile } from "obsidian";
15+
import { DataviewService } from "services/DataviewService";
16+
import { Literal } from "obsidian-dataview/lib/data-model/value";
1317

1418
/**
15-
* Add mandatory columns to the table
19+
* Add mandatory and configured metadata columns of the table
1620
* @param columns
1721
* @returns
1822
*/
@@ -63,6 +67,11 @@ export async function obtainMetadataColumns(
6367
return yamlColumns;
6468
}
6569

70+
/**
71+
* Given a record of columns of yaml file, return a record of columns of the table
72+
* @param databaseColumns
73+
* @returns
74+
*/
6675
export async function obtainColumnsFromFolder(
6776
databaseColumns: Record<string, DatabaseColumn>
6877
): Promise<TableColumn[]> {
@@ -82,6 +91,79 @@ export async function obtainColumnsFromFolder(
8291
return sortColumnsByPosition(columns);
8392
}
8493

94+
export async function obtainColumnsFromFile(
95+
file: TFile
96+
): Promise<Record<string, DatabaseColumn>> {
97+
const columns: Record<string, DatabaseColumn> = {};
98+
const propertiesOfFile = DataviewService.getDataviewAPI().page(file.path);
99+
// Check if propertiesOfFile is empty
100+
if (propertiesOfFile.length === 0) {
101+
return columns;
102+
}
103+
104+
Object.entries(propertiesOfFile).forEach(([key, value, index]) => {
105+
const input = getInputInFuctionOfLiteral(value);
106+
const newColumn: DatabaseColumn = {
107+
input: input,
108+
accessor: key,
109+
label: key,
110+
key: key,
111+
position: index,
112+
config: DEFAULT_COLUMN_CONFIG,
113+
};
114+
columns[key] = newColumn;
115+
});
116+
// remove metadata fields of dataview
117+
delete columns["file"];
118+
return columns;
119+
}
120+
121+
export function obtainColumnsFromRows(
122+
rows: RowDataType[]
123+
): Record<string, DatabaseColumn> {
124+
const columns: Record<string, DatabaseColumn> = {};
125+
// Obtain unique keys from source
126+
const keys = rows.reduce((acc, row) => {
127+
const keys = Object.keys(row);
128+
return [...acc, ...keys];
129+
}, [] as string[]);
130+
// Add keys to columns
131+
keys
132+
// Check metadata columns to not be added
133+
.filter((key) => !(key.startsWith("__") && key.endsWith("__")))
134+
.forEach((key, index) => {
135+
columns[key] = {
136+
input: DataTypes.TEXT,
137+
accessor: key,
138+
label: key,
139+
key: key,
140+
position: index,
141+
config: DEFAULT_COLUMN_CONFIG,
142+
};
143+
});
144+
145+
return columns;
146+
}
147+
148+
function getInputInFuctionOfLiteral(literal: Literal) {
149+
const wrappedLiteral = DataviewService.wrapLiteral(literal);
150+
let input = DataTypes.TEXT;
151+
switch (wrappedLiteral.type) {
152+
case DataTypes.NUMBER:
153+
input = DataTypes.NUMBER;
154+
break;
155+
case "date":
156+
input = DataTypes.CALENDAR;
157+
break;
158+
case "duration":
159+
input = DataTypes.CALENDAR_TIME;
160+
break;
161+
default:
162+
input = DataTypes.TEXT;
163+
}
164+
return input;
165+
}
166+
85167
function columnOptions(
86168
columnKey: string,
87169
index: number,

src/components/Header.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default function Header(headerProps: DatabaseHeaderProps) {
6262
// TODO : add a tooltip to the header
6363
const created: boolean = false;
6464
/** Properties of header */
65-
const { setSortBy, rows, initialState } = headerProps;
65+
const { setSortBy, rows, tableData } = headerProps;
6666
/** Column values */
6767
const { id, dataType, options, position } = headerProps.column;
6868
/** reducer asociated to database */
@@ -110,7 +110,7 @@ export default function Header(headerProps: DatabaseHeaderProps) {
110110

111111
function adjustWidthOfTheColumn(position: number) {
112112
let columnNumber =
113-
initialState.columns.length + 1 - initialState.shadowColumns.length;
113+
tableData.columns.length + 1 - tableData.shadowColumns.length;
114114
// Check if column name already exists
115115
while (
116116
headerProps.allColumns.find(

src/components/HeaderMenu.tsx

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
1-
import {
2-
ActionTypes,
3-
DataTypes,
4-
MetadataLabels,
5-
StyleVariables,
6-
} from "helpers/Constants";
1+
import { ActionTypes, StyleVariables } from "helpers/Constants";
72
import { dbTrim, c, getLabelHeader } from "helpers/StylesHelper";
8-
import HashIcon from "components/img/Hash";
9-
import CalendarTimeIcon from "components/img/CalendarTime";
10-
import CalendarIcon from "components/img/CalendarIcon";
113
import AdjustmentsIcon from "components/img/AdjustmentsIcon";
124
import React, { useContext, useEffect, useState } from "react";
135
import { Column } from "react-table";
@@ -34,7 +26,7 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
3426
labelState,
3527
setLabelState,
3628
} = headerMenuProps;
37-
const { column, rows, initialState } = headerMenuProps.headerProps;
29+
const { column, rows, tableData } = headerMenuProps.headerProps;
3830
const dispatch = (headerMenuProps.headerProps as any).dataDispatch;
3931
/** Column values */
4032
const [keyState, setkeyState] = useState(dbTrim(column.key));
@@ -169,24 +161,6 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
169161
persistLabelChange();
170162
}
171163

172-
function adjustWidthOfTheColumnsWhenAdd(wantedPosition: number) {
173-
let columnNumber =
174-
initialState.columns.length - initialState.shadowColumns.length;
175-
// Check if column name already exists
176-
while (
177-
headerMenuProps.headerProps.allColumns.find(
178-
(o: Column) => o.id === `newColumn${columnNumber}`
179-
)
180-
) {
181-
columnNumber++;
182-
}
183-
const columnId = `newColumn${columnNumber}`;
184-
const columnLabel = `New Column ${columnNumber}`;
185-
columnWidthState.widthRecord[columnId] = getColumnWidthStyle(rows, column);
186-
setColumnWidthState(columnWidthState);
187-
return { name: columnId, position: wantedPosition, label: columnLabel };
188-
}
189-
190164
return (
191165
<div>
192166
{expanded && (
@@ -323,10 +297,7 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
323297
<div
324298
className="menu-item sort-button"
325299
onClick={() => {
326-
new ColumnModal(
327-
initialState.view,
328-
headerMenuProps
329-
).open();
300+
new ColumnModal(tableData.view, headerMenuProps).open();
330301
setExpanded(false);
331302
}}
332303
>

0 commit comments

Comments
 (0)