Skip to content

Commit 4798f11

Browse files
committed
Refactor bulk folder import logic to better switch between title and id lookup methods
1 parent a10f9ec commit 4798f11

File tree

2 files changed

+63
-56
lines changed

2 files changed

+63
-56
lines changed

src/main.ts

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -621,14 +621,14 @@ export default class MediaDbPlugin extends Plugin {
621621
const erroredFiles: { filePath: string; error: string }[] = [];
622622
let canceled: boolean = false;
623623

624-
const { selectedAPI, titleFieldName, idFieldName, appendContent } = await new Promise<{
624+
const { selectedAPI, lookupMethod, fieldName, appendContent } = await new Promise<{
625625
selectedAPI: string;
626-
titleFieldName: string;
627-
idFieldName: string;
626+
lookupMethod: string;
627+
fieldName: string;
628628
appendContent: boolean;
629629
}>(resolve => {
630-
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => {
631-
resolve({ selectedAPI, titleFieldName, idFieldName, appendContent });
630+
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => {
631+
resolve({ selectedAPI, lookupMethod, fieldName, appendContent });
632632
}).open();
633633
});
634634

@@ -641,32 +641,27 @@ export default class MediaDbPlugin extends Plugin {
641641
}
642642

643643
const metadata = this.getMetadataFromFileCache(file);
644+
const lookupValue = metadata[fieldName];
644645

645-
// Querying by ID takes priority, doesn't require user to select from multiple matches
646-
const id = metadata[idFieldName];
647-
if (id && typeof id === 'string') {
646+
if (!lookupValue || typeof lookupValue !== 'string') {
647+
erroredFiles.push({ filePath: file.path, error: `metadata field '${fieldName}' not found, empty, or not a string` });
648+
continue;
649+
} else if (lookupMethod == 'id') {
648650
try {
649-
const model = await this.apiManager.queryDetailedInfoById(id, selectedAPI);
651+
const model = await this.apiManager.queryDetailedInfoById(lookupValue, selectedAPI);
650652
if (model) {
651653
await this.createMediaDbNotes([model], appendContent ? file : undefined);
652654
} else {
653-
erroredFiles.push({ filePath: file.path, error: `Failed to query API with id: ${id}` });
655+
erroredFiles.push({ filePath: file.path, error: `Failed to query API with id: ${lookupValue}` });
654656
}
655657
} catch (e) {
656658
erroredFiles.push({ filePath: file.path, error: `${e}` });
657659
continue;
658660
}
659-
} else {
660-
// Query API with title instead, requires user to select best match
661-
const title = metadata[titleFieldName];
662-
if (!title || typeof title !== 'string') {
663-
erroredFiles.push({ filePath: file.path, error: `metadata field '${titleFieldName}' not found, empty, or not a string` });
664-
continue;
665-
}
666-
661+
} else if (lookupMethod == 'title') {
667662
let results: MediaTypeModel[] = [];
668663
try {
669-
results = await this.apiManager.query(title, [selectedAPI]);
664+
results = await this.apiManager.query(lookupValue, [selectedAPI]);
670665
} catch (e) {
671666
erroredFiles.push({ filePath: file.path, error: `${e}` });
672667
continue;
@@ -679,7 +674,7 @@ export default class MediaDbPlugin extends Plugin {
679674
const { selectModalResult, selectModal } = await this.modalHelper.createSelectModal({
680675
elements: results,
681676
skipButton: true,
682-
modalTitle: `Results for '${title}'`,
677+
modalTitle: `Results for '${lookupValue}'`,
683678
});
684679

685680
if (selectModalResult.code === ModalResultCode.ERROR) {

src/modals/MediaDbFolderImportModal.ts

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
import type { App, ButtonComponent } from 'obsidian';
22
import { DropdownComponent, Modal, Setting, TextComponent, ToggleComponent } from 'obsidian';
33
import type MediaDbPlugin from '../main';
4+
import type { APIModel } from 'src/api/APIModel';
45

56
export class MediaDbFolderImportModal extends Modal {
67
plugin: MediaDbPlugin;
7-
onSubmit: (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => void;
8+
onSubmit: (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => void;
89
selectedApi: string;
910
searchBtn?: ButtonComponent;
10-
titleFieldName: string;
11-
idFieldName: string;
11+
lookupMethod: string;
12+
fieldName: string;
1213
appendContent: boolean;
1314

14-
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => void) {
15+
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => void) {
1516
super(app);
1617
this.plugin = plugin;
1718
this.onSubmit = onSubmit;
1819
this.selectedApi = plugin.apiManager.apis[0].apiName;
19-
this.titleFieldName = '';
20-
this.idFieldName = '';
20+
this.lookupMethod = '';
21+
this.fieldName = '';
2122
this.appendContent = false;
2223
}
2324

2425
submit(): void {
25-
this.onSubmit(this.selectedApi, this.titleFieldName, this.idFieldName, this.appendContent);
26+
this.onSubmit(this.selectedApi, this.lookupMethod, this.fieldName, this.appendContent);
2627
this.close();
2728
}
2829

@@ -31,18 +32,14 @@ export class MediaDbFolderImportModal extends Modal {
3132

3233
contentEl.createEl('h2', { text: 'Import folder as Media DB entries' });
3334

34-
const apiSelectorWrapper = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
35-
const apiSelectorTextWrapper = apiSelectorWrapper.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
36-
apiSelectorTextWrapper.createEl('span', { text: 'API to search', cls: 'media-db-plugin-list-text' });
37-
38-
const apiSelectorComponent = new DropdownComponent(apiSelectorWrapper);
39-
apiSelectorComponent.onChange((value: string) => {
35+
const onAPIChange = (value: string) => {
4036
this.selectedApi = value;
37+
};
38+
const apiOptions = this.plugin.apiManager.apis.map((api: APIModel) => {
39+
return { value: api.apiName, display: api.apiName };
4140
});
42-
for (const api of this.plugin.apiManager.apis) {
43-
apiSelectorComponent.addOption(api.apiName, api.apiName);
44-
}
45-
apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl);
41+
42+
this.createDropdownEl(contentEl, 'API to search', onAPIChange, apiOptions);
4643

4744
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
4845
contentEl.createEl('h3', { text: 'Append note content to Media DB entry?' });
@@ -62,33 +59,35 @@ export class MediaDbFolderImportModal extends Modal {
6259
appendContentToggleComponentWrapper.appendChild(appendContentToggle.toggleEl);
6360

6461
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
65-
contentEl.createEl('h3', { text: "Name of 'title' metadata field to use in API query." });
66-
67-
const placeholder = 'title';
68-
const titleFieldNameComponent = new TextComponent(contentEl);
69-
titleFieldNameComponent.inputEl.style.width = '100%';
70-
titleFieldNameComponent.setPlaceholder(placeholder);
71-
titleFieldNameComponent.onChange(value => (this.titleFieldName = value));
72-
titleFieldNameComponent.inputEl.addEventListener('keydown', ke => {
73-
if (ke.key === 'Enter') {
74-
this.submit();
75-
}
62+
contentEl.createEl('h3', { text: 'Media lookup method' });
63+
contentEl.createEl('p', {
64+
text: 'Choose whether to search the API by title (can return multiple results) or lookup directly using an ID (returns at most one result), and specify the name of the frontmatter property which contains the title or ID of the media.',
7665
});
77-
contentEl.appendChild(titleFieldNameComponent.inputEl);
66+
67+
const onlookupMethodChange = (value: string) => {
68+
this.lookupMethod = value;
69+
};
70+
const lookupMethodOptions = [
71+
{ value: 'title', display: 'Title' },
72+
{ value: 'id', display: 'ID' },
73+
];
74+
this.createDropdownEl(contentEl, 'Lookup media by', onlookupMethodChange, lookupMethodOptions);
7875

7976
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
80-
contentEl.createEl('h3', { text: "Name of 'id' metadata field to use in API query (if present, will be used instead of title)." });
8177

82-
const idFieldNameComponent = new TextComponent(contentEl);
83-
idFieldNameComponent.inputEl.style.width = '100%';
84-
idFieldNameComponent.setPlaceholder('id');
85-
idFieldNameComponent.onChange(value => (this.idFieldName = value));
86-
idFieldNameComponent.inputEl.addEventListener('keydown', ke => {
78+
const fieldNameWrapperEl = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
79+
const fieldNameLabelWrapperEl = fieldNameWrapperEl.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
80+
fieldNameLabelWrapperEl.createEl('span', { text: 'Using the property named', cls: 'media-db-plugin-list-text' });
81+
82+
const fieldNameComponent = new TextComponent(fieldNameWrapperEl);
83+
fieldNameComponent.setPlaceholder('title / id');
84+
fieldNameComponent.onChange(value => (this.fieldName = value));
85+
fieldNameComponent.inputEl.addEventListener('keydown', ke => {
8786
if (ke.key === 'Enter') {
8887
this.submit();
8988
}
9089
});
91-
contentEl.appendChild(idFieldNameComponent.inputEl);
90+
contentEl.appendChild(fieldNameWrapperEl);
9291

9392
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
9493

@@ -109,6 +108,19 @@ export class MediaDbFolderImportModal extends Modal {
109108
});
110109
}
111110

111+
createDropdownEl(parentEl: HTMLElement, label: string, onChange: { (value: string): void }, options: { value: string; display: string }[]): void {
112+
const wrapperEl = parentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
113+
const labelWrapperEl = wrapperEl.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
114+
labelWrapperEl.createEl('span', { text: label, cls: 'media-db-plugin-list-text' });
115+
116+
const dropDownComponent = new DropdownComponent(wrapperEl);
117+
dropDownComponent.onChange(onChange);
118+
for (const option of options) {
119+
dropDownComponent.addOption(option.value, option.display);
120+
}
121+
wrapperEl.appendChild(dropDownComponent.selectEl);
122+
}
123+
112124
onClose(): void {
113125
const { contentEl } = this;
114126
contentEl.empty();

0 commit comments

Comments
 (0)