Refactor bulk folder import logic to better switch between title and id lookup methods
This commit is contained in:
parent
a10f9ec609
commit
4798f1144b
2 changed files with 63 additions and 56 deletions
35
src/main.ts
35
src/main.ts
|
|
@ -621,14 +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, idFieldName, appendContent } = await new Promise<{
|
const { selectedAPI, lookupMethod, fieldName, appendContent } = await new Promise<{
|
||||||
selectedAPI: string;
|
selectedAPI: string;
|
||||||
titleFieldName: string;
|
lookupMethod: string;
|
||||||
idFieldName: string;
|
fieldName: string;
|
||||||
appendContent: boolean;
|
appendContent: boolean;
|
||||||
}>(resolve => {
|
}>(resolve => {
|
||||||
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => {
|
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => {
|
||||||
resolve({ selectedAPI, titleFieldName, idFieldName, appendContent });
|
resolve({ selectedAPI, lookupMethod, fieldName, appendContent });
|
||||||
}).open();
|
}).open();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -641,32 +641,27 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadata = this.getMetadataFromFileCache(file);
|
const metadata = this.getMetadataFromFileCache(file);
|
||||||
|
const lookupValue = metadata[fieldName];
|
||||||
|
|
||||||
// Querying by ID takes priority, doesn't require user to select from multiple matches
|
if (!lookupValue || typeof lookupValue !== 'string') {
|
||||||
const id = metadata[idFieldName];
|
erroredFiles.push({ filePath: file.path, error: `metadata field '${fieldName}' not found, empty, or not a string` });
|
||||||
if (id && typeof id === 'string') {
|
continue;
|
||||||
|
} else if (lookupMethod == 'id') {
|
||||||
try {
|
try {
|
||||||
const model = await this.apiManager.queryDetailedInfoById(id, selectedAPI);
|
const model = await this.apiManager.queryDetailedInfoById(lookupValue, selectedAPI);
|
||||||
if (model) {
|
if (model) {
|
||||||
await this.createMediaDbNotes([model], appendContent ? file : undefined);
|
await this.createMediaDbNotes([model], appendContent ? file : undefined);
|
||||||
} else {
|
} else {
|
||||||
erroredFiles.push({ filePath: file.path, error: `Failed to query API with id: ${id}` });
|
erroredFiles.push({ filePath: file.path, error: `Failed to query API with id: ${lookupValue}` });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
erroredFiles.push({ filePath: file.path, error: `${e}` });
|
erroredFiles.push({ filePath: file.path, error: `${e}` });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (lookupMethod == 'title') {
|
||||||
// Query API with title instead, requires user to select best match
|
|
||||||
const title = metadata[titleFieldName];
|
|
||||||
if (!title || typeof title !== 'string') {
|
|
||||||
erroredFiles.push({ filePath: file.path, error: `metadata field '${titleFieldName}' not found, empty, or not a string` });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let results: MediaTypeModel[] = [];
|
let results: MediaTypeModel[] = [];
|
||||||
try {
|
try {
|
||||||
results = await this.apiManager.query(title, [selectedAPI]);
|
results = await this.apiManager.query(lookupValue, [selectedAPI]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
erroredFiles.push({ filePath: file.path, error: `${e}` });
|
erroredFiles.push({ filePath: file.path, error: `${e}` });
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -679,7 +674,7 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
const { selectModalResult, selectModal } = await this.modalHelper.createSelectModal({
|
const { selectModalResult, selectModal } = await this.modalHelper.createSelectModal({
|
||||||
elements: results,
|
elements: results,
|
||||||
skipButton: true,
|
skipButton: true,
|
||||||
modalTitle: `Results for '${title}'`,
|
modalTitle: `Results for '${lookupValue}'`,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (selectModalResult.code === ModalResultCode.ERROR) {
|
if (selectModalResult.code === ModalResultCode.ERROR) {
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,29 @@
|
||||||
import type { App, ButtonComponent } from 'obsidian';
|
import type { App, ButtonComponent } from 'obsidian';
|
||||||
import { DropdownComponent, Modal, Setting, TextComponent, ToggleComponent } from 'obsidian';
|
import { DropdownComponent, Modal, Setting, TextComponent, ToggleComponent } from 'obsidian';
|
||||||
import type MediaDbPlugin from '../main';
|
import type MediaDbPlugin from '../main';
|
||||||
|
import type { APIModel } from 'src/api/APIModel';
|
||||||
|
|
||||||
export class MediaDbFolderImportModal extends Modal {
|
export class MediaDbFolderImportModal extends Modal {
|
||||||
plugin: MediaDbPlugin;
|
plugin: MediaDbPlugin;
|
||||||
onSubmit: (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => void;
|
onSubmit: (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => void;
|
||||||
selectedApi: string;
|
selectedApi: string;
|
||||||
searchBtn?: ButtonComponent;
|
searchBtn?: ButtonComponent;
|
||||||
titleFieldName: string;
|
lookupMethod: string;
|
||||||
idFieldName: string;
|
fieldName: string;
|
||||||
appendContent: boolean;
|
appendContent: boolean;
|
||||||
|
|
||||||
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string, idFieldName: string, appendContent: boolean) => void) {
|
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, lookupMethod: string, fieldName: 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.lookupMethod = '';
|
||||||
this.idFieldName = '';
|
this.fieldName = '';
|
||||||
this.appendContent = false;
|
this.appendContent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit(): void {
|
submit(): void {
|
||||||
this.onSubmit(this.selectedApi, this.titleFieldName, this.idFieldName, this.appendContent);
|
this.onSubmit(this.selectedApi, this.lookupMethod, this.fieldName, this.appendContent);
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,18 +32,14 @@ export class MediaDbFolderImportModal extends Modal {
|
||||||
|
|
||||||
contentEl.createEl('h2', { text: 'Import folder as Media DB entries' });
|
contentEl.createEl('h2', { text: 'Import folder as Media DB entries' });
|
||||||
|
|
||||||
const apiSelectorWrapper = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
|
const onAPIChange = (value: string) => {
|
||||||
const apiSelectorTextWrapper = apiSelectorWrapper.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
|
|
||||||
apiSelectorTextWrapper.createEl('span', { text: 'API to search', cls: 'media-db-plugin-list-text' });
|
|
||||||
|
|
||||||
const apiSelectorComponent = new DropdownComponent(apiSelectorWrapper);
|
|
||||||
apiSelectorComponent.onChange((value: string) => {
|
|
||||||
this.selectedApi = value;
|
this.selectedApi = value;
|
||||||
|
};
|
||||||
|
const apiOptions = this.plugin.apiManager.apis.map((api: APIModel) => {
|
||||||
|
return { value: api.apiName, display: api.apiName };
|
||||||
});
|
});
|
||||||
for (const api of this.plugin.apiManager.apis) {
|
|
||||||
apiSelectorComponent.addOption(api.apiName, api.apiName);
|
this.createDropdownEl(contentEl, 'API to search', onAPIChange, apiOptions);
|
||||||
}
|
|
||||||
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?' });
|
||||||
|
|
@ -62,33 +59,35 @@ 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: "Name of 'title' metadata field to use in API query." });
|
contentEl.createEl('h3', { text: 'Media lookup method' });
|
||||||
|
contentEl.createEl('p', {
|
||||||
const placeholder = 'title';
|
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.',
|
||||||
const titleFieldNameComponent = new TextComponent(contentEl);
|
|
||||||
titleFieldNameComponent.inputEl.style.width = '100%';
|
|
||||||
titleFieldNameComponent.setPlaceholder(placeholder);
|
|
||||||
titleFieldNameComponent.onChange(value => (this.titleFieldName = value));
|
|
||||||
titleFieldNameComponent.inputEl.addEventListener('keydown', ke => {
|
|
||||||
if (ke.key === 'Enter') {
|
|
||||||
this.submit();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
contentEl.appendChild(titleFieldNameComponent.inputEl);
|
|
||||||
|
const onlookupMethodChange = (value: string) => {
|
||||||
|
this.lookupMethod = value;
|
||||||
|
};
|
||||||
|
const lookupMethodOptions = [
|
||||||
|
{ value: 'title', display: 'Title' },
|
||||||
|
{ value: 'id', display: 'ID' },
|
||||||
|
];
|
||||||
|
this.createDropdownEl(contentEl, 'Lookup media by', onlookupMethodChange, lookupMethodOptions);
|
||||||
|
|
||||||
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
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);
|
const fieldNameWrapperEl = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
|
||||||
idFieldNameComponent.inputEl.style.width = '100%';
|
const fieldNameLabelWrapperEl = fieldNameWrapperEl.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
|
||||||
idFieldNameComponent.setPlaceholder('id');
|
fieldNameLabelWrapperEl.createEl('span', { text: 'Using the property named', cls: 'media-db-plugin-list-text' });
|
||||||
idFieldNameComponent.onChange(value => (this.idFieldName = value));
|
|
||||||
idFieldNameComponent.inputEl.addEventListener('keydown', ke => {
|
const fieldNameComponent = new TextComponent(fieldNameWrapperEl);
|
||||||
|
fieldNameComponent.setPlaceholder('title / id');
|
||||||
|
fieldNameComponent.onChange(value => (this.fieldName = value));
|
||||||
|
fieldNameComponent.inputEl.addEventListener('keydown', ke => {
|
||||||
if (ke.key === 'Enter') {
|
if (ke.key === 'Enter') {
|
||||||
this.submit();
|
this.submit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
contentEl.appendChild(idFieldNameComponent.inputEl);
|
contentEl.appendChild(fieldNameWrapperEl);
|
||||||
|
|
||||||
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
||||||
|
|
||||||
|
|
@ -109,6 +108,19 @@ export class MediaDbFolderImportModal extends Modal {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createDropdownEl(parentEl: HTMLElement, label: string, onChange: { (value: string): void }, options: { value: string; display: string }[]): void {
|
||||||
|
const wrapperEl = parentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
|
||||||
|
const labelWrapperEl = wrapperEl.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
|
||||||
|
labelWrapperEl.createEl('span', { text: label, cls: 'media-db-plugin-list-text' });
|
||||||
|
|
||||||
|
const dropDownComponent = new DropdownComponent(wrapperEl);
|
||||||
|
dropDownComponent.onChange(onChange);
|
||||||
|
for (const option of options) {
|
||||||
|
dropDownComponent.addOption(option.value, option.display);
|
||||||
|
}
|
||||||
|
wrapperEl.appendChild(dropDownComponent.selectEl);
|
||||||
|
}
|
||||||
|
|
||||||
onClose(): void {
|
onClose(): void {
|
||||||
const { contentEl } = this;
|
const { contentEl } = this;
|
||||||
contentEl.empty();
|
contentEl.empty();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue