Allow batch / folder import by id as well as title

This commit is contained in:
Karn 2025-08-30 17:38:52 +01:00
parent 9fa7348ae9
commit a10f9ec609
2 changed files with 93 additions and 51 deletions

View file

@ -621,9 +621,14 @@ export default class MediaDbPlugin extends Plugin {
const erroredFiles: { filePath: string; error: string }[] = []; const erroredFiles: { filePath: string; error: string }[] = [];
let canceled: boolean = false; let canceled: boolean = false;
const { selectedAPI, titleFieldName, appendContent } = await new Promise<{ selectedAPI: string; titleFieldName: string; appendContent: boolean }>(resolve => { const { selectedAPI, titleFieldName, idFieldName, appendContent } = await new Promise<{
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, titleFieldName: string, appendContent: boolean) => { selectedAPI: string;
resolve({ selectedAPI, titleFieldName, appendContent }); titleFieldName: string;
idFieldName: string;
appendContent: boolean;
}>(resolve => {
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => {
resolve({ selectedAPI, titleFieldName, idFieldName, appendContent });
}).open(); }).open();
}); });
@ -637,6 +642,22 @@ export default class MediaDbPlugin extends Plugin {
const metadata = this.getMetadataFromFileCache(file); const metadata = this.getMetadataFromFileCache(file);
// Querying by ID takes priority, doesn't require user to select from multiple matches
const id = metadata[idFieldName];
if (id && typeof id === 'string') {
try {
const model = await this.apiManager.queryDetailedInfoById(id, selectedAPI);
if (model) {
await this.createMediaDbNotes([model], appendContent ? file : undefined);
} else {
erroredFiles.push({ filePath: file.path, error: `Failed to query API with id: ${id}` });
}
} catch (e) {
erroredFiles.push({ filePath: file.path, error: `${e}` });
continue;
}
} else {
// Query API with title instead, requires user to select best match
const title = metadata[titleFieldName]; const title = metadata[titleFieldName];
if (!title || typeof title !== 'string') { if (!title || typeof title !== 'string') {
erroredFiles.push({ filePath: file.path, error: `metadata field '${titleFieldName}' not found, empty, or not a string` }); erroredFiles.push({ filePath: file.path, error: `metadata field '${titleFieldName}' not found, empty, or not a string` });
@ -655,7 +676,11 @@ export default class MediaDbPlugin extends Plugin {
continue; continue;
} }
const { selectModalResult, selectModal } = await this.modalHelper.createSelectModal({ elements: results, skipButton: true, modalTitle: `Results for '${title}'` }); const { selectModalResult, selectModal } = await this.modalHelper.createSelectModal({
elements: results,
skipButton: true,
modalTitle: `Results for '${title}'`,
});
if (selectModalResult.code === ModalResultCode.ERROR) { if (selectModalResult.code === ModalResultCode.ERROR) {
erroredFiles.push({ filePath: file.path, error: selectModalResult.error.message }); erroredFiles.push({ filePath: file.path, error: selectModalResult.error.message });
@ -687,6 +712,7 @@ export default class MediaDbPlugin extends Plugin {
selectModal.close(); selectModal.close();
} }
} }
}
if (erroredFiles.length > 0) { if (erroredFiles.length > 0) {
await this.createErroredFilesReport(erroredFiles); await this.createErroredFilesReport(erroredFiles);

View file

@ -4,23 +4,25 @@ import type MediaDbPlugin from '../main';
export class MediaDbFolderImportModal extends Modal { export class MediaDbFolderImportModal extends Modal {
plugin: MediaDbPlugin; plugin: MediaDbPlugin;
onSubmit: (selectedAPI: string, titleFieldName: string, appendContent: boolean) => void; onSubmit: (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => void;
selectedApi: string; selectedApi: string;
searchBtn?: ButtonComponent; searchBtn?: ButtonComponent;
titleFieldName: string; titleFieldName: string;
idFieldName: string;
appendContent: boolean; appendContent: boolean;
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string, appendContent: boolean) => void) { constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => void) {
super(app); super(app);
this.plugin = plugin; this.plugin = plugin;
this.onSubmit = onSubmit; this.onSubmit = onSubmit;
this.selectedApi = plugin.apiManager.apis[0].apiName; this.selectedApi = plugin.apiManager.apis[0].apiName;
this.titleFieldName = ''; this.titleFieldName = '';
this.idFieldName = '';
this.appendContent = false; this.appendContent = false;
} }
submit(): void { submit(): void {
this.onSubmit(this.selectedApi, this.titleFieldName, this.appendContent); this.onSubmit(this.selectedApi, this.titleFieldName, this.idFieldName, this.appendContent);
this.close(); this.close();
} }
@ -43,7 +45,7 @@ export class MediaDbFolderImportModal extends Modal {
apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl); apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl);
contentEl.createDiv({ cls: 'media-db-plugin-spacer' }); contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
contentEl.createEl('h3', { text: 'Append note content to Media DB entry.' }); contentEl.createEl('h3', { text: 'Append note content to Media DB entry?' });
const appendContentToggleElementWrapper = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' }); const appendContentToggleElementWrapper = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
const appendContentToggleTextWrapper = appendContentToggleElementWrapper.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' }); const appendContentToggleTextWrapper = appendContentToggleElementWrapper.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
@ -60,7 +62,7 @@ export class MediaDbFolderImportModal extends Modal {
appendContentToggleComponentWrapper.appendChild(appendContentToggle.toggleEl); appendContentToggleComponentWrapper.appendChild(appendContentToggle.toggleEl);
contentEl.createDiv({ cls: 'media-db-plugin-spacer' }); contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
contentEl.createEl('h3', { text: 'The name of the metadata field that should be used as the title to query.' }); contentEl.createEl('h3', { text: "Name of 'title' metadata field to use in API query." });
const placeholder = 'title'; const placeholder = 'title';
const titleFieldNameComponent = new TextComponent(contentEl); const titleFieldNameComponent = new TextComponent(contentEl);
@ -74,6 +76,20 @@ export class MediaDbFolderImportModal extends Modal {
}); });
contentEl.appendChild(titleFieldNameComponent.inputEl); contentEl.appendChild(titleFieldNameComponent.inputEl);
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
contentEl.createEl('h3', { text: "Name of 'id' metadata field to use in API query (if present, will be used instead of title)." });
const idFieldNameComponent = new TextComponent(contentEl);
idFieldNameComponent.inputEl.style.width = '100%';
idFieldNameComponent.setPlaceholder('id');
idFieldNameComponent.onChange(value => (this.idFieldName = value));
idFieldNameComponent.inputEl.addEventListener('keydown', ke => {
if (ke.key === 'Enter') {
this.submit();
}
});
contentEl.appendChild(idFieldNameComponent.inputEl);
contentEl.createDiv({ cls: 'media-db-plugin-spacer' }); contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
new Setting(contentEl) new Setting(contentEl)