api scaffold

This commit is contained in:
mProjectsCode 2022-05-04 19:09:54 +02:00
parent ddcc767573
commit 96d74a7732
6 changed files with 128 additions and 60 deletions

30
src/api/APIManager.ts Normal file
View 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
View 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;
}
}

View file

@ -1,6 +1,7 @@
export interface APIResult {
export interface APIRequestResult {
title: string,
type: string,
description?: string,
apiName: string,
data: any,
}

27
src/api/apis/TestAPI.ts Normal file
View 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 '';
}
}

View file

@ -1,9 +1,12 @@
import {Plugin} from 'obsidian';
import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/settings';
import {MediaDbSearchModal} from './modals/MediaDbSearchModal';
import {APIManager} from './api/APIManager';
import {TestAPI} from './api/apis/TestAPI';
export default class MediaDbPlugin extends Plugin {
settings: MediaDbPluginSettings;
apiManager: APIManager;
async onload() {
await this.loadSettings();
@ -23,17 +26,22 @@ export default class MediaDbPlugin extends Plugin {
// register the settings tab
this.addSettingTab(new MediaDbSettingTab(this.app, this));
this.apiManager = new APIManager();
// register APIs
this.apiManager.registerAPI(new TestAPI());
}
async createMediaDbNote(): Promise<void> {
const data = await this.openMediaDbSearchModal();
console.log('Create new note or something...');
console.log('MDB | Create new note or something...');
console.log(data);
}
async openMediaDbSearchModal(): Promise<any> {
return new Promise(((resolve, reject) => {
new MediaDbSearchModal(this.app, (err, result) => {
new MediaDbSearchModal(this.app, this.apiManager, (err, result) => {
if (err) return reject(err);
resolve(result);
}).open();

View file

@ -1,22 +1,22 @@
import {App, ButtonComponent, SuggestModal} from 'obsidian';
import {APIResult} from '../api/APIResult';
import {sleep} from '../utils/utils';
import {App, SuggestModal} from 'obsidian';
import {APIRequestResult} from '../api/APIRequestResult';
import {APIManager} from '../api/APIManager';
export class MediaDbSearchModal extends SuggestModal<APIResult> {
export class MediaDbSearchModal extends SuggestModal<APIRequestResult> {
query: string;
hasChanged: boolean;
isBusy: boolean;
okBtn: ButtonComponent;
onChoose: (err: Error, result?: APIResult) => void;
apiManager: APIManager;
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);
this.apiManager = apiManager;
this.onChoose = onChoose;
this.isBusy = false;
}
async search(force: boolean = false): Promise<APIResult[]> {
async search(force: boolean = false): Promise<APIRequestResult[]> {
if (!this.query) {
return;
}
@ -25,72 +25,41 @@ export class MediaDbSearchModal extends SuggestModal<APIResult> {
this.isBusy = true;
const thisQuery: string = this.query;
console.log('query started with ' + thisQuery)
await sleep(1000); // TODO: replace with real api call
console.log('MDB | query started with ' + thisQuery);
const res = await this.apiManager.query(thisQuery);
// console.log(res)
// await sleep(1000);
if (this.query === thisQuery) {
this.isBusy = false;
return [ // TODO: replace with real api result
{title: thisQuery, type: 'movie', data: null} as APIResult,
{title: 'test2', type: 'series', data: {episodes: 24}} as APIResult,
];
return res;
// return [
// {title: thisQuery, type: 'movie', data: null} as APIRequestResult,
// {title: 'test2', type: 'series', data: {episodes: 24}} as APIRequestResult,
// ];
} else {
return await this.search(true);
}
}
}
async getSuggestions(query: string): Promise<APIResult[]> {
async getSuggestions(query: string): Promise<APIRequestResult[]> {
this.query = query;
return await this.search();
}
renderSuggestion(item: APIResult, el: HTMLElement): void {
renderSuggestion(item: APIRequestResult, el: HTMLElement): void {
el.createEl('div', {text: item.title});
el.createEl('small', {text: item.type});
}
onChooseSuggestion(item: APIResult, evt: MouseEvent | KeyboardEvent): void {
onChooseSuggestion(item: APIRequestResult, evt: MouseEvent | KeyboardEvent): void {
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();
}
*/
}