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

Commit 8b65595

Browse files
committed
commandhelper working!
1 parent fcf6ce0 commit 8b65595

File tree

4 files changed

+278
-36
lines changed

4 files changed

+278
-36
lines changed

src/commands/addDatabaseHelper/databaseHelperCreationModal.ts

Lines changed: 225 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
import { Modal } from "obsidian";
1+
import { LocalSettings } from "cdm/SettingsModel";
2+
import { generateDbConfiguration, generateNewDatabase } from "helpers/CommandsHelper";
3+
import { InputType, SourceDataTypes, StyleClasses } from "helpers/Constants";
4+
import { resolve_tfolder } from "helpers/FileManagement";
5+
import { generateDataviewTableQuery } from "helpers/QueryHelper";
6+
import { Modal, Notice, Setting, TFolder } from "obsidian";
7+
import { DataviewService } from "services/DataviewService";
8+
import { add_dropdown, add_setting_header } from "settings/SettingsComponents";
9+
import { FileSuggest } from "settings/suggesters/FileSuggester";
10+
import { FolderSuggest } from "settings/suggesters/FolderSuggester";
211

312
export class DatabaseHelperCreationModal extends Modal {
413
databaseHelperCreationModalManager: DatabaseHelperCreationModalManager;
5-
constructor() {
14+
local_settings: LocalSettings;
15+
constructor(local_settings: LocalSettings) {
616
super(app);
17+
this.local_settings = local_settings;
718
this.databaseHelperCreationModalManager = new DatabaseHelperCreationModalManager(this);
819
}
920
onOpen() {
@@ -20,11 +31,222 @@ export class DatabaseHelperCreationModal extends Modal {
2031

2132
export class DatabaseHelperCreationModalManager {
2233
databaseHelperCreationModal: DatabaseHelperCreationModal;
34+
destinationFolder = '/';
35+
databaseName = '';
2336
constructor(
2437
databaseHelperCreationModal: DatabaseHelperCreationModal,
2538
) {
2639
this.databaseHelperCreationModal = databaseHelperCreationModal;
40+
41+
2742
}
2843
constructUI(containerEl: HTMLElement) {
44+
add_setting_header(containerEl, "Database creator helper", 'h2');
45+
const helperBody = containerEl.createDiv();
46+
helperBody.addClass(StyleClasses.SETTINGS_MODAL_BODY);
47+
helperBody.setAttribute("id", StyleClasses.SETTINGS_MODAL_BODY);
48+
this.constructSettingBody(helperBody);
2949
}
30-
}
50+
51+
constructSettingBody(bodyElement: HTMLElement) {
52+
new Setting(bodyElement)
53+
.setName("Database name")
54+
.setDesc("Name of the database to create")
55+
.addText(text => {
56+
text.setPlaceholder("Database name")
57+
.setValue(this.databaseName)
58+
.onChange(async (value: string): Promise<void> => {
59+
this.databaseName = this.parseValueToThuthyYaml(value);
60+
});
61+
});
62+
63+
add_dropdown(
64+
bodyElement,
65+
'Select source',
66+
'Select from which source you want to create your custom database.',
67+
this.databaseHelperCreationModal.local_settings.source_data,
68+
{
69+
current_folder: SourceDataTypes.CURRENT_FOLDER,
70+
tag: SourceDataTypes.TAG,
71+
outgoing_link: SourceDataTypes.OUTGOING_LINK,
72+
incoming_link: SourceDataTypes.INCOMING_LINK,
73+
query: SourceDataTypes.QUERY,
74+
},
75+
async (value: string) => {
76+
this.databaseHelperCreationModal.local_settings.source_data = value;
77+
this.reset();
78+
}
79+
);
80+
switch (this.databaseHelperCreationModal.local_settings.source_data) {
81+
case SourceDataTypes.TAG:
82+
this.tagHandler(bodyElement);
83+
break;
84+
case SourceDataTypes.INCOMING_LINK:
85+
case SourceDataTypes.OUTGOING_LINK:
86+
this.outgoingAndIncomingHandler(bodyElement);
87+
break;
88+
case SourceDataTypes.QUERY:
89+
this.queryHandler(bodyElement);
90+
break;
91+
default:
92+
// do nothing
93+
}
94+
95+
new Setting(bodyElement)
96+
.setName('Select where to save your database')
97+
.setDesc('Select the destination of where you want to save your database.')
98+
.addSearch((cb) => {
99+
new FolderSuggest(
100+
cb.inputEl
101+
);
102+
cb.setPlaceholder("Example: path/to/folder")
103+
.setValue(this.destinationFolder)
104+
.onChange((value: string) => {
105+
this.destinationFolder = value;
106+
});
107+
});
108+
109+
new Setting(bodyElement)
110+
.setName('Submit')
111+
.setDesc('Close to cancel or submit to create your database.')
112+
.addButton((cb) => {
113+
cb.setButtonText('Close')
114+
.onClick(() => {
115+
this.databaseHelperCreationModal.close();
116+
});
117+
}).addButton((cb) => {
118+
cb.setButtonText('Create')
119+
.onClick(async () => {
120+
await this.createButtonHandler()
121+
});
122+
});
123+
}
124+
125+
reset() {
126+
const bodyElement = activeDocument.getElementById(StyleClasses.SETTINGS_MODAL_BODY);
127+
// remove all sections
128+
bodyElement.empty();
129+
this.constructSettingBody(bodyElement);
130+
}
131+
132+
async createButtonHandler() {
133+
try {
134+
const targetFolder = resolve_tfolder(this.destinationFolder);
135+
await generateNewDatabase(
136+
generateDbConfiguration(this.databaseHelperCreationModal.local_settings),
137+
targetFolder,
138+
this.databaseName
139+
);
140+
new Notice(`Database "${this.databaseName}" created in "${targetFolder.path}"`, 1500);
141+
} catch (e) {
142+
new Notice(`Error creating database "${this.databaseName}": ${e}`, 1500);
143+
}
144+
this.databaseHelperCreationModal.close();
145+
}
146+
147+
tagHandler(containerEl: HTMLElement) {
148+
const tagArray: Record<string, number> = (app.metadataCache as unknown as any).getTags();
149+
if (tagArray) {
150+
const tagRecords: Record<string, string> = {};
151+
// Order tagRecord by key (tag name)
152+
Object.entries(tagArray)
153+
.sort((a, b) => a[0].localeCompare(b[0]))
154+
.forEach(([key, value]) => {
155+
tagRecords[key] = `${key}(${value})`;
156+
});
157+
const source_form_promise = async (value: string): Promise<void> => {
158+
// update form result
159+
this.databaseHelperCreationModal.local_settings.source_form_result = value.slice(1);
160+
};
161+
162+
add_dropdown(
163+
containerEl,
164+
'Select a tag',
165+
'Select tag to get data from',
166+
`#${this.databaseHelperCreationModal.local_settings.source_form_result}`,
167+
tagRecords,
168+
source_form_promise
169+
);
170+
this.destinationFolderHandler(containerEl);
171+
}
172+
}
173+
174+
queryHandler(containerEl: HTMLElement) {
175+
const query_promise = async (value: string): Promise<void> => {
176+
// update settings
177+
this.databaseHelperCreationModal.local_settings.source_form_result = this.parseValueToThuthyYaml(value);
178+
};
179+
new Setting(containerEl)
180+
.setName('Dataview query')
181+
.setDesc('Enter a dataview query starting with FROM (the plugin autocomplete the query with TABLE & the column fields)')
182+
.addTextArea((textArea) => {
183+
textArea.setValue(this.databaseHelperCreationModal.local_settings.source_form_result);
184+
textArea.setPlaceholder('Write here your dataview query...');
185+
textArea.onChange(query_promise);
186+
}).addExtraButton((cb) => {
187+
cb.setIcon("check")
188+
.setTooltip("Validate query")
189+
.onClick(async (): Promise<void> => {
190+
const query = generateDataviewTableQuery(
191+
[],
192+
this.databaseHelperCreationModal.local_settings.source_form_result);
193+
if (query) {
194+
DataviewService.getDataviewAPI().tryQuery(query)
195+
.then(() => {
196+
new Notice(`Dataview query "${query}" is valid!`, 2000);
197+
})
198+
.catch((e) => {
199+
new Notice(`Dataview query "${query}" is invalid: ${e.message}`, 10000);
200+
});
201+
}
202+
});
203+
});
204+
this.destinationFolderHandler(containerEl);
205+
}
206+
207+
outgoingAndIncomingHandler(containerEl: HTMLElement) {
208+
const source_form_promise = async (value: string): Promise<void> => {
209+
// update form result
210+
this.databaseHelperCreationModal.local_settings.source_form_result = value;
211+
};
212+
new Setting(containerEl)
213+
.setName('Select a file')
214+
.setDesc('Select file from vault to be used as source of data.')
215+
.addSearch((cb) => {
216+
new FileSuggest(
217+
cb.inputEl,
218+
"/"
219+
);
220+
cb.setPlaceholder("Example: folder1/template_file")
221+
.setValue(this.databaseHelperCreationModal.local_settings.source_form_result)
222+
.onChange(source_form_promise);
223+
});
224+
this.destinationFolderHandler(containerEl);
225+
}
226+
227+
destinationFolderHandler(containerEl: HTMLElement) {
228+
const source_form_promise = async (value: string): Promise<void> => {
229+
// update settings
230+
this.databaseHelperCreationModal.local_settings.source_destination_path = value;
231+
};
232+
new Setting(containerEl)
233+
.setName('Select destination folder')
234+
.setDesc('Select the destination of new entries for this source')
235+
.addSearch((cb) => {
236+
new FolderSuggest(
237+
cb.inputEl
238+
);
239+
cb.setPlaceholder("Example: path/to/folder")
240+
.setValue(this.databaseHelperCreationModal.local_settings.source_destination_path)
241+
.onChange(source_form_promise);
242+
});
243+
}
244+
245+
parseValueToThuthyYaml(value: string): string {
246+
return DataviewService.parseLiteral(
247+
value,
248+
InputType.MARKDOWN,
249+
this.databaseHelperCreationModal.local_settings
250+
).toString();
251+
}
252+
}

src/helpers/CommandsHelper.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { LocalSettings } from "cdm/SettingsModel";
2+
import { Notice, TFile, TFolder } from "obsidian";
3+
import { LOGGER } from "services/Logger";
4+
import { DatabaseCore, DatabaseFrontmatterOptions, DEFAULT_SETTINGS, YAML_INDENT } from "helpers/Constants";
5+
6+
export async function generateNewDatabase(ddbbConfig: string, folder?: TFolder, ddbbName?: string) {
7+
const targetFolder = folder
8+
?? app.fileManager.getNewFileParent(
9+
app.workspace.getActiveFile()?.path || ''
10+
);
11+
12+
try {
13+
const database: TFile = await (
14+
app.fileManager as any
15+
).createNewMarkdownFile(targetFolder, ddbbName ?? 'Untitled database');
16+
17+
await app.vault.modify(
18+
database,
19+
DatabaseFrontmatterOptions.BASIC
20+
.concat('\n')
21+
.concat(ddbbConfig)
22+
.concat('\n')
23+
.concat('%%>')
24+
);
25+
await app.workspace.getMostRecentLeaf().setViewState({
26+
type: DatabaseCore.FRONTMATTER_KEY,
27+
state: { file: database.path },
28+
});
29+
} catch (e) {
30+
LOGGER.error('Error creating database folder:', e);
31+
new Notice(`Error creating database folder: ${e}`, 5000);
32+
}
33+
}
34+
35+
/**
36+
* Returns the default configuration for a database file.
37+
*/
38+
export function generateDbConfiguration(customLocalSettings: LocalSettings): string {
39+
const defaultConfig = [];
40+
defaultConfig.push("config:");
41+
Object.entries(DEFAULT_SETTINGS.local_settings).forEach(([key, value]) => {
42+
const defaultValue = customLocalSettings[key as keyof LocalSettings] !== undefined ? customLocalSettings[key as keyof LocalSettings] : value;
43+
defaultConfig.push(`${YAML_INDENT}${key}: ${defaultValue}`);
44+
});
45+
return defaultConfig.join('\n');
46+
}

src/helpers/Generators.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ export function useIMEInputProps() {
1919
const isComposingRef = useRef<boolean>(false);
2020

2121
return {
22-
// Note: these are lowercased because we use preact
23-
// See: https://github.com/preactjs/preact/issues/3003
2422
onCompositionStart: () => {
2523
isComposingRef.current = true;
2624
},

src/main.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import { PreviewDatabaseModeService } from 'services/MarkdownPostProcessorServic
3333
import { unmountComponentAtNode } from 'react-dom';
3434
import { isDatabaseNote } from 'helpers/VaultManagement';
3535
import { getParentWindow } from 'helpers/WindowElement';
36+
import { DatabaseHelperCreationModal } from 'commands/addDatabaseHelper/databaseHelperCreationModal';
37+
import { generateDbConfiguration, generateNewDatabase } from 'helpers/CommandsHelper';
3638

3739
interface WindowRegistry {
3840
viewMap: Map<string, DatabaseView>;
@@ -304,35 +306,6 @@ export default class DBFolderPlugin extends Plugin {
304306
viewStateReceivers: [],
305307
appRoot: el,
306308
});
307-
308-
//Preact.render(createApp(win, this), el);
309-
}
310-
311-
async newDatabase(folder?: TFolder) {
312-
const targetFolder = folder
313-
? folder
314-
: this.app.fileManager.getNewFileParent(
315-
this.app.workspace.getActiveFile()?.path || ''
316-
);
317-
318-
try {
319-
const database: TFile = await (
320-
this.app.fileManager as any
321-
).createNewMarkdownFile(targetFolder, 'Untitled database');
322-
323-
await app.vault.modify(
324-
database,
325-
DatabaseFrontmatterOptions.BASIC
326-
.concat('\n')
327-
.concat(this.defaultConfiguration())
328-
);
329-
await app.workspace.getMostRecentLeaf().setViewState({
330-
type: DatabaseCore.FRONTMATTER_KEY,
331-
state: { file: database.path },
332-
});
333-
} catch (e) {
334-
LOGGER.error('Error creating database folder:', e);
335-
}
336309
}
337310

338311
/**
@@ -359,7 +332,10 @@ export default class DBFolderPlugin extends Plugin {
359332
item
360333
.setTitle('New database folder')
361334
.setIcon(databaseIcon)
362-
.onClick(() => this.newDatabase(file));
335+
.onClick(() => generateNewDatabase(
336+
generateDbConfiguration(this.settings.local_settings),
337+
file
338+
));
363339
});
364340
return;
365341
}
@@ -423,7 +399,7 @@ export default class DBFolderPlugin extends Plugin {
423399
this.addCommand({
424400
id: 'create-new-database-folder',
425401
name: 'Create a new database table',
426-
callback: () => console.log('create new database folder'),
402+
callback: () => new DatabaseHelperCreationModal(this.settings.local_settings).open(),
427403
});
428404
}
429405
/**

0 commit comments

Comments
 (0)