Merge pull request #207 from Spydarlee/batch-import-by-id
Allow batch / folder import by id as well as title
This commit is contained in:
commit
9941f14008
3 changed files with 133 additions and 70 deletions
43
src/main.ts
43
src/main.ts
|
|
@ -26,6 +26,7 @@ import type { SearchModalOptions } from './utils/ModalHelper';
|
|||
import { ModalHelper, ModalResultCode } from './utils/ModalHelper';
|
||||
import type { CreateNoteOptions } from './utils/Utils';
|
||||
import { dateTimeToString, markdownTable, replaceIllegalFileNameCharactersInString, unCamelCase, hasTemplaterPlugin, useTemplaterPluginInFile } from './utils/Utils';
|
||||
import { BulkImportLookupMethod } from 'src/utils/BulkImportLookupMethod';
|
||||
|
||||
export type Metadata = Record<string, unknown>;
|
||||
|
||||
|
|
@ -561,9 +562,14 @@ export default class MediaDbPlugin extends Plugin {
|
|||
const erroredFiles: { filePath: string; error: string }[] = [];
|
||||
let canceled: boolean = false;
|
||||
|
||||
const { selectedAPI, titleFieldName, appendContent } = await new Promise<{ selectedAPI: string; titleFieldName: string; appendContent: boolean }>(resolve => {
|
||||
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, titleFieldName: string, appendContent: boolean) => {
|
||||
resolve({ selectedAPI, titleFieldName, appendContent });
|
||||
const { selectedAPI, lookupMethod, fieldName, appendContent } = await new Promise<{
|
||||
selectedAPI: string;
|
||||
lookupMethod: string;
|
||||
fieldName: string;
|
||||
appendContent: boolean;
|
||||
}>(resolve => {
|
||||
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => {
|
||||
resolve({ selectedAPI, lookupMethod, fieldName, appendContent });
|
||||
}).open();
|
||||
});
|
||||
|
||||
|
|
@ -576,16 +582,27 @@ export default class MediaDbPlugin extends Plugin {
|
|||
}
|
||||
|
||||
const metadata = this.getMetadataFromFileCache(file);
|
||||
const lookupValue = metadata[fieldName];
|
||||
|
||||
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` });
|
||||
if (!lookupValue || typeof lookupValue !== 'string') {
|
||||
erroredFiles.push({ filePath: file.path, error: `metadata field '${fieldName}' not found, empty, or not a string` });
|
||||
continue;
|
||||
} else if (lookupMethod === BulkImportLookupMethod.ID) {
|
||||
try {
|
||||
const model = await this.apiManager.queryDetailedInfoById(lookupValue, selectedAPI);
|
||||
if (model) {
|
||||
await this.createMediaDbNotes([model], appendContent ? file : undefined);
|
||||
} else {
|
||||
erroredFiles.push({ filePath: file.path, error: `Failed to query API with id: ${lookupValue}` });
|
||||
}
|
||||
} catch (e) {
|
||||
erroredFiles.push({ filePath: file.path, error: `${e}` });
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (lookupMethod === BulkImportLookupMethod.TITLE) {
|
||||
let results: MediaTypeModel[] = [];
|
||||
try {
|
||||
results = await this.apiManager.query(title, [selectedAPI]);
|
||||
results = await this.apiManager.query(lookupValue, [selectedAPI]);
|
||||
} catch (e) {
|
||||
erroredFiles.push({ filePath: file.path, error: `${e}` });
|
||||
continue;
|
||||
|
|
@ -595,7 +612,11 @@ export default class MediaDbPlugin extends Plugin {
|
|||
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 '${lookupValue}'`,
|
||||
});
|
||||
|
||||
if (selectModalResult.code === ModalResultCode.ERROR) {
|
||||
erroredFiles.push({ filePath: file.path, error: selectModalResult.error.message });
|
||||
|
|
@ -625,6 +646,10 @@ export default class MediaDbPlugin extends Plugin {
|
|||
await this.createMediaDbNotes(detailedResults, appendContent ? file : undefined);
|
||||
|
||||
selectModal.close();
|
||||
} else {
|
||||
erroredFiles.push({ filePath: file.path, error: `invalid lookup type` });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,30 @@
|
|||
import type { App, ButtonComponent } from 'obsidian';
|
||||
import { DropdownComponent, Modal, Setting, TextComponent, ToggleComponent } from 'obsidian';
|
||||
import type MediaDbPlugin from '../main';
|
||||
import type { APIModel } from 'src/api/APIModel';
|
||||
import { BulkImportLookupMethod } from 'src/utils/BulkImportLookupMethod';
|
||||
|
||||
export class MediaDbFolderImportModal extends Modal {
|
||||
plugin: MediaDbPlugin;
|
||||
onSubmit: (selectedAPI: string, titleFieldName: string, appendContent: boolean) => void;
|
||||
onSubmit: (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => void;
|
||||
selectedApi: string;
|
||||
searchBtn?: ButtonComponent;
|
||||
titleFieldName: string;
|
||||
lookupMethod: string;
|
||||
fieldName: string;
|
||||
appendContent: boolean;
|
||||
|
||||
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, titleFieldName: string, appendContent: boolean) => void) {
|
||||
constructor(app: App, plugin: MediaDbPlugin, onSubmit: (selectedAPI: string, lookupMethod: string, fieldName: string, appendContent: boolean) => void) {
|
||||
super(app);
|
||||
this.plugin = plugin;
|
||||
this.onSubmit = onSubmit;
|
||||
this.selectedApi = plugin.apiManager.apis[0].apiName;
|
||||
this.titleFieldName = '';
|
||||
this.lookupMethod = BulkImportLookupMethod.TITLE;
|
||||
this.fieldName = '';
|
||||
this.appendContent = false;
|
||||
}
|
||||
|
||||
submit(): void {
|
||||
this.onSubmit(this.selectedApi, this.titleFieldName, this.appendContent);
|
||||
this.onSubmit(this.selectedApi, this.lookupMethod, this.fieldName, this.appendContent);
|
||||
this.close();
|
||||
}
|
||||
|
||||
|
|
@ -29,21 +33,19 @@ export class MediaDbFolderImportModal extends Modal {
|
|||
|
||||
contentEl.createEl('h2', { text: 'Import folder as Media DB entries' });
|
||||
|
||||
const apiSelectorWrapper = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
|
||||
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.createDropdownEl(
|
||||
contentEl,
|
||||
'API to search',
|
||||
(value: string) => {
|
||||
this.selectedApi = value;
|
||||
});
|
||||
for (const api of this.plugin.apiManager.apis) {
|
||||
apiSelectorComponent.addOption(api.apiName, api.apiName);
|
||||
}
|
||||
apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl);
|
||||
},
|
||||
this.plugin.apiManager.apis.map((api: APIModel) => {
|
||||
return { value: api.apiName, display: api.apiName };
|
||||
}),
|
||||
);
|
||||
|
||||
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 appendContentToggleTextWrapper = appendContentToggleElementWrapper.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
|
||||
|
|
@ -60,19 +62,38 @@ export class MediaDbFolderImportModal extends Modal {
|
|||
appendContentToggleComponentWrapper.appendChild(appendContentToggle.toggleEl);
|
||||
|
||||
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: 'Media lookup method' });
|
||||
contentEl.createEl('p', {
|
||||
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 placeholder = 'title';
|
||||
const titleFieldNameComponent = new TextComponent(contentEl);
|
||||
titleFieldNameComponent.inputEl.style.width = '100%';
|
||||
titleFieldNameComponent.setPlaceholder(placeholder);
|
||||
titleFieldNameComponent.onChange(value => (this.titleFieldName = value));
|
||||
titleFieldNameComponent.inputEl.addEventListener('keydown', ke => {
|
||||
this.createDropdownEl(
|
||||
contentEl,
|
||||
'Lookup media by',
|
||||
(value: string) => {
|
||||
this.lookupMethod = value;
|
||||
},
|
||||
[
|
||||
{ value: BulkImportLookupMethod.TITLE, display: 'Title' },
|
||||
{ value: BulkImportLookupMethod.ID, display: 'ID' },
|
||||
],
|
||||
);
|
||||
|
||||
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
||||
|
||||
const fieldNameWrapperEl = contentEl.createEl('div', { cls: 'media-db-plugin-list-wrapper' });
|
||||
const fieldNameLabelWrapperEl = fieldNameWrapperEl.createEl('div', { cls: 'media-db-plugin-list-text-wrapper' });
|
||||
fieldNameLabelWrapperEl.createEl('span', { text: 'Using the property named', cls: 'media-db-plugin-list-text' });
|
||||
|
||||
const fieldNameComponent = new TextComponent(fieldNameWrapperEl);
|
||||
fieldNameComponent.setPlaceholder('title / id');
|
||||
fieldNameComponent.onChange(value => (this.fieldName = value));
|
||||
fieldNameComponent.inputEl.addEventListener('keydown', ke => {
|
||||
if (ke.key === 'Enter') {
|
||||
this.submit();
|
||||
}
|
||||
});
|
||||
contentEl.appendChild(titleFieldNameComponent.inputEl);
|
||||
contentEl.appendChild(fieldNameWrapperEl);
|
||||
|
||||
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
||||
|
||||
|
|
@ -93,6 +114,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 {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
|
|
|
|||
4
src/utils/BulkImportLookupMethod.ts
Normal file
4
src/utils/BulkImportLookupMethod.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export enum BulkImportLookupMethod {
|
||||
ID = 'id',
|
||||
TITLE = 'title',
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue