api scaffold
This commit is contained in:
parent
ddcc767573
commit
96d74a7732
6 changed files with 128 additions and 60 deletions
30
src/api/APIManager.ts
Normal file
30
src/api/APIManager.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import {APIModel} from './APIModel';
|
||||||
|
import {APIRequestResult} from './APIRequestResult';
|
||||||
|
|
||||||
|
export class APIManager {
|
||||||
|
apis: APIModel[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.apis = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async query(query: string, types: string[] = []): Promise<APIRequestResult[]> {
|
||||||
|
console.log('MDB | api manager queried');
|
||||||
|
|
||||||
|
let res: APIRequestResult[] = [];
|
||||||
|
|
||||||
|
for (const api of this.apis) {
|
||||||
|
if (types.length === 0 || api.hasTypeOverlap(types)) {
|
||||||
|
const apiRes = await api.getByTitle(query);
|
||||||
|
// console.log(apiRes);
|
||||||
|
res = res.concat(apiRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerAPI(api: APIModel): void {
|
||||||
|
this.apis.push(api);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/api/APIModel.ts
Normal file
33
src/api/APIModel.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import {APIRequestResult} from './APIRequestResult';
|
||||||
|
|
||||||
|
export abstract class APIModel {
|
||||||
|
name: string;
|
||||||
|
types: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function should query the api and return a list of matches. The matches should be caped at 20.
|
||||||
|
*
|
||||||
|
* @param title the title to query for
|
||||||
|
*/
|
||||||
|
abstract getByTitle(title: string): Promise<APIRequestResult[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function should return the metadata corresponding to the api result. An implementation should check first, if the result is from this api.
|
||||||
|
*
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
abstract getMataDataFromResult(item: APIRequestResult): string;
|
||||||
|
|
||||||
|
hasType(type: string): boolean {
|
||||||
|
return this.types.contains(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTypeOverlap(types: string[]): boolean {
|
||||||
|
for (const type of types) {
|
||||||
|
if (this.hasType(type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
export interface APIResult {
|
export interface APIRequestResult {
|
||||||
title: string,
|
title: string,
|
||||||
type: string,
|
type: string,
|
||||||
description?: string,
|
description?: string,
|
||||||
|
apiName: string,
|
||||||
data: any,
|
data: any,
|
||||||
}
|
}
|
||||||
27
src/api/apis/TestAPI.ts
Normal file
27
src/api/apis/TestAPI.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {APIModel} from '../APIModel';
|
||||||
|
import {APIRequestResult} from '../APIRequestResult';
|
||||||
|
|
||||||
|
export class TestAPI extends APIModel {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.name = 'testAPI';
|
||||||
|
this.types = ['test'];
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByTitle(title: string): Promise<APIRequestResult[]> {
|
||||||
|
console.log(`MDB | api "${this.name}" queried`);
|
||||||
|
|
||||||
|
return [
|
||||||
|
{title: 'test1', type: this.types[0], apiName: this.name, data: {length: 126}} as APIRequestResult,
|
||||||
|
{title: 'test2', type: this.types[0], apiName: this.name, description: 'some test description', data: {}} as APIRequestResult,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getMataDataFromResult(item: APIRequestResult): string {
|
||||||
|
if (item.apiName !== this.name) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/main.ts
12
src/main.ts
|
|
@ -1,9 +1,12 @@
|
||||||
import {Plugin} from 'obsidian';
|
import {Plugin} from 'obsidian';
|
||||||
import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/settings';
|
import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/settings';
|
||||||
import {MediaDbSearchModal} from './modals/MediaDbSearchModal';
|
import {MediaDbSearchModal} from './modals/MediaDbSearchModal';
|
||||||
|
import {APIManager} from './api/APIManager';
|
||||||
|
import {TestAPI} from './api/apis/TestAPI';
|
||||||
|
|
||||||
export default class MediaDbPlugin extends Plugin {
|
export default class MediaDbPlugin extends Plugin {
|
||||||
settings: MediaDbPluginSettings;
|
settings: MediaDbPluginSettings;
|
||||||
|
apiManager: APIManager;
|
||||||
|
|
||||||
async onload() {
|
async onload() {
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
|
|
@ -23,17 +26,22 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
|
|
||||||
// register the settings tab
|
// register the settings tab
|
||||||
this.addSettingTab(new MediaDbSettingTab(this.app, this));
|
this.addSettingTab(new MediaDbSettingTab(this.app, this));
|
||||||
|
|
||||||
|
|
||||||
|
this.apiManager = new APIManager();
|
||||||
|
// register APIs
|
||||||
|
this.apiManager.registerAPI(new TestAPI());
|
||||||
}
|
}
|
||||||
|
|
||||||
async createMediaDbNote(): Promise<void> {
|
async createMediaDbNote(): Promise<void> {
|
||||||
const data = await this.openMediaDbSearchModal();
|
const data = await this.openMediaDbSearchModal();
|
||||||
console.log('Create new note or something...');
|
console.log('MDB | Create new note or something...');
|
||||||
console.log(data);
|
console.log(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async openMediaDbSearchModal(): Promise<any> {
|
async openMediaDbSearchModal(): Promise<any> {
|
||||||
return new Promise(((resolve, reject) => {
|
return new Promise(((resolve, reject) => {
|
||||||
new MediaDbSearchModal(this.app, (err, result) => {
|
new MediaDbSearchModal(this.app, this.apiManager, (err, result) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
resolve(result);
|
resolve(result);
|
||||||
}).open();
|
}).open();
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
import {App, ButtonComponent, SuggestModal} from 'obsidian';
|
import {App, SuggestModal} from 'obsidian';
|
||||||
import {APIResult} from '../api/APIResult';
|
import {APIRequestResult} from '../api/APIRequestResult';
|
||||||
import {sleep} from '../utils/utils';
|
import {APIManager} from '../api/APIManager';
|
||||||
|
|
||||||
export class MediaDbSearchModal extends SuggestModal<APIResult> {
|
export class MediaDbSearchModal extends SuggestModal<APIRequestResult> {
|
||||||
query: string;
|
query: string;
|
||||||
hasChanged: boolean;
|
|
||||||
isBusy: boolean;
|
isBusy: boolean;
|
||||||
okBtn: ButtonComponent;
|
apiManager: APIManager;
|
||||||
onChoose: (err: Error, result?: APIResult) => void;
|
onChoose: (err: Error, result?: APIRequestResult) => void;
|
||||||
|
|
||||||
constructor(app: App, onChoose?: (err: Error, result?: APIResult) => void) {
|
constructor(app: App, apiManager: APIManager, onChoose?: (err: Error, result?: APIRequestResult) => void) {
|
||||||
super(app);
|
super(app);
|
||||||
|
|
||||||
|
this.apiManager = apiManager;
|
||||||
this.onChoose = onChoose;
|
this.onChoose = onChoose;
|
||||||
this.isBusy = false;
|
this.isBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(force: boolean = false): Promise<APIResult[]> {
|
async search(force: boolean = false): Promise<APIRequestResult[]> {
|
||||||
if (!this.query) {
|
if (!this.query) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -25,72 +25,41 @@ export class MediaDbSearchModal extends SuggestModal<APIResult> {
|
||||||
this.isBusy = true;
|
this.isBusy = true;
|
||||||
const thisQuery: string = this.query;
|
const thisQuery: string = this.query;
|
||||||
|
|
||||||
console.log('query started with ' + thisQuery)
|
console.log('MDB | query started with ' + thisQuery);
|
||||||
await sleep(1000); // TODO: replace with real api call
|
|
||||||
|
const res = await this.apiManager.query(thisQuery);
|
||||||
|
|
||||||
|
// console.log(res)
|
||||||
|
|
||||||
|
// await sleep(1000);
|
||||||
|
|
||||||
if (this.query === thisQuery) {
|
if (this.query === thisQuery) {
|
||||||
this.isBusy = false;
|
this.isBusy = false;
|
||||||
return [ // TODO: replace with real api result
|
|
||||||
{title: thisQuery, type: 'movie', data: null} as APIResult,
|
return res;
|
||||||
{title: 'test2', type: 'series', data: {episodes: 24}} as APIResult,
|
|
||||||
];
|
// return [
|
||||||
|
// {title: thisQuery, type: 'movie', data: null} as APIRequestResult,
|
||||||
|
// {title: 'test2', type: 'series', data: {episodes: 24}} as APIRequestResult,
|
||||||
|
// ];
|
||||||
} else {
|
} else {
|
||||||
return await this.search(true);
|
return await this.search(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSuggestions(query: string): Promise<APIResult[]> {
|
async getSuggestions(query: string): Promise<APIRequestResult[]> {
|
||||||
this.query = query;
|
this.query = query;
|
||||||
|
|
||||||
return await this.search();
|
return await this.search();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSuggestion(item: APIResult, el: HTMLElement): void {
|
renderSuggestion(item: APIRequestResult, el: HTMLElement): void {
|
||||||
el.createEl('div', {text: item.title});
|
el.createEl('div', {text: item.title});
|
||||||
el.createEl('small', {text: item.type});
|
el.createEl('small', {text: item.type});
|
||||||
}
|
}
|
||||||
|
|
||||||
onChooseSuggestion(item: APIResult, evt: MouseEvent | KeyboardEvent): void {
|
onChooseSuggestion(item: APIRequestResult, evt: MouseEvent | KeyboardEvent): void {
|
||||||
this.onChoose(null, item);
|
this.onChoose(null, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
onOpen() {
|
|
||||||
const { contentEl } = this;
|
|
||||||
|
|
||||||
contentEl.createEl('h2', { text: 'Search Media DB' });
|
|
||||||
|
|
||||||
const placeholder = 'Search by title';
|
|
||||||
const textComponent = new TextComponent(contentEl);
|
|
||||||
|
|
||||||
textComponent.setPlaceholder(placeholder);
|
|
||||||
textComponent.onChange(value => (this.query = value));
|
|
||||||
|
|
||||||
textComponent.inputEl.addEventListener('keydown', this.submitCallback.bind(this));
|
|
||||||
textComponent.inputEl.style.width = '100%';
|
|
||||||
|
|
||||||
contentEl.appendChild(textComponent.inputEl);
|
|
||||||
textComponent.inputEl.focus();
|
|
||||||
|
|
||||||
const resultsComponent = new
|
|
||||||
|
|
||||||
new Setting(contentEl)
|
|
||||||
.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()))
|
|
||||||
.addButton(btn => {
|
|
||||||
return (this.okBtn = btn
|
|
||||||
.setButtonText('Ok')
|
|
||||||
.setCta()
|
|
||||||
.onClick(() => {
|
|
||||||
this.search();
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onClose() {
|
|
||||||
const { contentEl } = this;
|
|
||||||
contentEl.empty();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue