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

Commit 5c539b6

Browse files
committed
Merge branch '592-fr-second-iteration-of-obsidian-projects'
2 parents e38db8e + e0c8c44 commit 5c539b6

File tree

1 file changed

+102
-6
lines changed

1 file changed

+102
-6
lines changed

src/api/obsidian-projects-api.ts

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
import { DB_ICONS } from "helpers/Constants";
1+
import { DB_ICONS, DEFAULT_COLUMN_CONFIG, InputType, SourceDataTypes } from "helpers/Constants";
22
import DBFolderPlugin from "main";
33

44
import {
55
DatabaseView,
66
} from 'DatabaseView';
77
import { LOGGER } from "services/Logger";
8-
import { DataQueryResult, ProjectView, ProjectViewProps } from "obsidian-projects-types";
8+
import { DataFieldType, DataQueryResult, ProjectView, ProjectViewProps } from "obsidian-projects-types";
99
import { resolve_tfile, resolve_tfolder } from "helpers/FileManagement";
1010
import { generateDbConfiguration, generateNewDatabase } from "helpers/CommandsHelper";
11+
import { LocalSettings } from "cdm/SettingsModel";
12+
import { DatabaseColumn } from "cdm/DatabaseModel";
13+
import { dbTrim } from "helpers/StylesHelper";
1114

15+
const projectsMetadataColumns = ["File", "name", "path"];
1216
class ProjectAPI extends ProjectView {
1317
private plugin: DBFolderPlugin;
1418
private view: DatabaseView;
@@ -32,24 +36,61 @@ class ProjectAPI extends ProjectView {
3236
}
3337

3438
async onData({ data }: DataQueryResult) {
35-
// Do nothing here
36-
// Data is handled by the database itself and will be updated automatically every time the view is opened
39+
const { fields } = data;
40+
const currentColumnsLength = Object
41+
.values(this.view.diskConfig.yaml.columns)
42+
.filter((column) => !column.isMetadata).length;
43+
const actualFields = fields
44+
.filter((field) => !projectsMetadataColumns.contains(field.name));
3745

46+
if (currentColumnsLength !== actualFields.length) {
47+
const newColumns: Record<string, DatabaseColumn> = {};
48+
actualFields.forEach((field, index) => {
49+
const { name, type } = field;
50+
/**
51+
* I can not use the view object here without make it a class variable
52+
* and I don't want to do that because I can not support multiple views
53+
*
54+
* Could we add the config to the data object? I can manage a map of views with that
55+
*/
56+
const inputType = this.mapperTypeToInputType(type);
57+
const key = dbTrim(name);
58+
const newColumn: DatabaseColumn = {
59+
input: inputType,
60+
accessorKey: key,
61+
key: key,
62+
id: key,
63+
label: name,
64+
position: index,
65+
config: {
66+
...DEFAULT_COLUMN_CONFIG,
67+
isInline: false
68+
},
69+
};
70+
newColumns[name] = newColumn;
3871

72+
});
73+
74+
this.view.diskConfig.yaml.columns = newColumns;
75+
await this.view.diskConfig.saveOnDisk();
76+
await this.view.reloadDatabase();
77+
}
3978
}
4079

4180
// onOpens is called whenever the user activates your view.
4281
//
4382
// `contentEl` HTML element where you can attach your view.
4483
// `config` JSON object with optional view configuration.
4584
// `saveConfig` Callback to save configuration changes.
46-
async onOpen({ contentEl, config, saveConfig, project, viewId }: ProjectViewProps) {
85+
async onOpen(projectView: ProjectViewProps) {
86+
const { contentEl, config, saveConfig, project, viewId } = projectView;
4787
const { path } = project;
4888
let filePath = config.filepath;
4989
if (!filePath) {
5090
const folder = resolve_tfolder(path);
91+
const customLocalSettings = this.generateLocalSettings(projectView);
5192
// If the config is empty, we need to create a Default
52-
const dbConfig = generateDbConfiguration(this.plugin.settings.local_settings);
93+
const dbConfig = generateDbConfiguration(customLocalSettings);
5394
await generateNewDatabase(dbConfig, folder, `${viewId}_db`, false);
5495
saveConfig({ filepath: `${path}/${viewId}_db.md` });
5596
}
@@ -65,6 +106,61 @@ class ProjectAPI extends ProjectView {
65106
async onClose() {
66107
LOGGER.debug("Closing project view ", this.getDisplayName());
67108
}
109+
110+
private generateLocalSettings(projectView: ProjectViewProps): LocalSettings {
111+
const { project } = projectView;
112+
const localSettings: LocalSettings = {
113+
...this.plugin.settings.local_settings,
114+
}
115+
if (project.dataview) {
116+
localSettings.source_destination_path = project.path;
117+
localSettings.source_data = SourceDataTypes.QUERY;
118+
/*
119+
* Check if the query contains FROM or from
120+
* then Split query to only get subtring from "from" to the end
121+
*/
122+
let query = "";
123+
const SOURCE_FLAG = "FROM";
124+
if (project.query?.contains(SOURCE_FLAG)) {
125+
query = project.query?.split(SOURCE_FLAG)[1];
126+
} else if (project.query?.contains(SOURCE_FLAG.toLowerCase())) {
127+
query = project.query?.split(SOURCE_FLAG.toLowerCase())[1];
128+
} else {
129+
// Handle error with default configuation
130+
localSettings.source_data = SourceDataTypes.CURRENT_FOLDER;
131+
LOGGER.error(`The query does not contain a ${SOURCE_FLAG} clause. Using current folder as source data`);
132+
}
133+
localSettings.source_form_result = `${SOURCE_FLAG} ${query}`;
134+
}
135+
136+
return localSettings;
137+
}
138+
139+
private mapperTypeToInputType(type: string): string {
140+
let inputType = "";
141+
switch (type) {
142+
case DataFieldType.String:
143+
case DataFieldType.Link:
144+
case DataFieldType.Unknown:
145+
inputType = InputType.TEXT;
146+
break;
147+
case DataFieldType.Number:
148+
inputType = InputType.NUMBER;
149+
break;
150+
case DataFieldType.Boolean:
151+
inputType = InputType.CHECKBOX;
152+
break;
153+
case DataFieldType.Date:
154+
inputType = InputType.CALENDAR;
155+
break;
156+
case DataFieldType.List:
157+
inputType = InputType.TAGS;
158+
break;
159+
default:
160+
inputType = InputType.TEXT;
161+
}
162+
return inputType;
163+
}
68164
}
69165

70166
export default ProjectAPI;

0 commit comments

Comments
 (0)