install prettier
This commit is contained in:
parent
2662c78080
commit
9e2961421d
57 changed files with 2367 additions and 1162 deletions
10
.eslintrc
10
.eslintrc
|
|
@ -2,14 +2,8 @@
|
|||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"env": { "node": true },
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended"],
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/api-request.md
vendored
2
.github/ISSUE_TEMPLATE/api-request.md
vendored
|
|
@ -4,7 +4,6 @@ about: Suggest a new API to be added to this plugin.
|
|||
title: ''
|
||||
labels: API request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Name**
|
||||
|
|
@ -16,6 +15,5 @@ A link to their API documentation
|
|||
**What does the API do/offer**
|
||||
A short description of what data the API offers
|
||||
|
||||
|
||||
- [ ] Is the API free to use
|
||||
- [ ] Does the API require authentication
|
||||
|
|
|
|||
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -4,7 +4,6 @@ about: Create a report to help us improve
|
|||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
- [ ] The Plugin is up to date
|
||||
|
|
@ -15,6 +14,7 @@ A clear and concise description of what the bug is.
|
|||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
|
|
@ -27,6 +27,7 @@ A clear and concise description of what you expected to happen.
|
|||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Occurs on**
|
||||
|
||||
- [ ] Windows
|
||||
- [ ] macOS
|
||||
- [ ] Linux
|
||||
|
|
|
|||
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -4,7 +4,6 @@ about: Suggest an idea for this project
|
|||
title: ''
|
||||
labels: feature request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
|
|
|||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
|
@ -4,7 +4,7 @@ on:
|
|||
push:
|
||||
# Sequence of patterns matched against refs/tags
|
||||
tags:
|
||||
- "*" # Push events to matching any tag format, i.e. 1.0, 20.15.10
|
||||
- '*' # Push events to matching any tag format, i.e. 1.0, 20.15.10
|
||||
|
||||
env:
|
||||
PLUGIN_NAME: obsidian-media-db-plugin # Change this to the name of your plugin-id folder
|
||||
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "14.x" # You might need to adjust this value to your own version
|
||||
node-version: '14.x' # You might need to adjust this value to your own version
|
||||
- name: Build
|
||||
id: build
|
||||
run: |
|
||||
|
|
|
|||
5
.prettierignore
Normal file
5
.prettierignore
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/lib
|
||||
node_modules
|
||||
package-lock.json
|
||||
data.json
|
||||
main.js
|
||||
7
.prettierrc.json
Normal file
7
.prettierrc.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"printWidth": 180,
|
||||
"useTabs": true,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
30
README.md
30
README.md
|
|
@ -3,18 +3,23 @@
|
|||
A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.
|
||||
|
||||
### Features
|
||||
|
||||
#### Search by Title
|
||||
|
||||
Search a movie, series, anime, game, music release or wiki article by its name across multiple APIs.
|
||||
|
||||
#### Search by ID
|
||||
|
||||
Allows you to search by an ID that varies from API to API. Concrete information on this feature can be found in the description of the individual APIs.
|
||||
|
||||
#### Templates
|
||||
|
||||
The plugin allows you to set a template note that gets added to the end of any note created by this plugin.
|
||||
The plugin also offers simple "template tgs". E.g. if the template includes `{{ title }}`, it will be replaced by the title of the movie, show or game.
|
||||
Note that "template tags" are surrounded with two curly braces and that the spaces inside the curly braces are important.
|
||||
|
||||
For arrays there are two special ways of displaying them.
|
||||
|
||||
- using `{{ LIST:variable_name }}` will result in
|
||||
```
|
||||
- element 1
|
||||
|
|
@ -32,40 +37,48 @@ Available variables that can be used in template tags are the same variables fro
|
|||
I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates).
|
||||
|
||||
#### Metadata field customization
|
||||
|
||||
Allows you to rename the metadata fields this plugin generates through mappings.
|
||||
|
||||
A mapping has to follow this syntax `[origional property name] -> [new property name]`.
|
||||
Multiple mappings are separated by a new line.
|
||||
So e.g.:
|
||||
|
||||
```
|
||||
title -> name
|
||||
year -> releaseYear
|
||||
```
|
||||
|
||||
#### Bulk Import
|
||||
|
||||
The plugin allows you to import your preexisting media collection and upgrade them to Media DB entries.
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
The preexisting media notes must be inside a folder in your vault.
|
||||
For the plugin to be able to query them they need one metadata field that is used as the title the piece of media is searched by.
|
||||
This can be achieved by for example using a `csv` import plugin to import an existing list from outside of obsidian.
|
||||
|
||||
##### Importing
|
||||
|
||||
To start the import process, right-click on the folder and select the `Import folder as Media DB entries` option.
|
||||
Then specify the API to search, if the current note content and metadata should be appended to the Media DB entry and the name of the metadata field that contains the title of the piece of media.
|
||||
|
||||
Then the plugin will go through every file in the folder and prompt you to select from the search results.
|
||||
|
||||
##### Post import
|
||||
|
||||
After all files have been imported or the import was canceled, you will find the new entries as well as an error report that contains any errors or skipped/canceled files in the folder specified in the setting of the plugin.
|
||||
|
||||
### How to install
|
||||
|
||||
**The plugin is now released, so it can be installed directly through obsidian's plugin installer.**
|
||||
|
||||
Alternatively, you can manually download the zip archive from the latest release here on GitHub.
|
||||
After downloading, extract the archive into the `.obsidian/plugins` folder in your vault.
|
||||
|
||||
The folder structure should look like this:
|
||||
|
||||
```
|
||||
[path to your vault]
|
||||
|_ .obsidian
|
||||
|
|
@ -76,8 +89,8 @@ The folder structure should look like this:
|
|||
|_ styles.css
|
||||
```
|
||||
|
||||
|
||||
### How to use
|
||||
|
||||
(pictures are coming)
|
||||
|
||||
Once you have installed this plugin, you will find a database icon in the left ribbon.
|
||||
|
|
@ -88,6 +101,7 @@ After clicking search, a new popup will open prompting you to select from the se
|
|||
Now you select the result you want and the plugin will cast it's magic and create a new note in your vault, that contains the metadata of the selected search result.
|
||||
|
||||
### Currently supported media types
|
||||
|
||||
- movies (including specials)
|
||||
- series (including OVAs)
|
||||
- games
|
||||
|
|
@ -95,8 +109,9 @@ Now you select the result you want and the plugin will cast it's magic and creat
|
|||
- wiki articles
|
||||
|
||||
### Currently supported APIs:
|
||||
|
||||
| Name | Description | Supported formats | Authentification | Rate limiting | SFW filter support |
|
||||
|------------------------------------------------------|---------------------------------------------------------------------------------------------------|--------------------------------|------------------------------------------------------------------------------|--------------------------------|--------------------|
|
||||
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------- | ------------------------------ | ------------------ |
|
||||
| [Jikan](https://jikan.moe/) | Jikan is an API that uses [My Anime List](https://myanimelist.net) and offers metadata for anime. | series, movies, specials, OVAs | No | 60 per minute and 3 per second | Yes |
|
||||
| [OMDb](https://www.omdbapi.com/) | OMDb is an API that offers metadata for movie, series and games. | series, movies, games | Yes, you can get a free key here [here](https://www.omdbapi.com/apikey.aspx) | 1000 per day | No |
|
||||
| [MusicBrainz](https://musicbrainz.org/) | MusicBrainz is an API that offers information about music releases. | music releases | No | 50 per second | No |
|
||||
|
|
@ -104,12 +119,14 @@ Now you select the result you want and the plugin will cast it's magic and creat
|
|||
| [Steam](https://store.steampowered.com/) | The Steam API offers information on all steam games. | games | No | 10000 per day | No |
|
||||
|
||||
#### Notes
|
||||
|
||||
- [Jikan](https://jikan.moe/)
|
||||
- sometimes the api is very slow, this is normal
|
||||
- you need to use the title the anime has on [My Anime List](https://myanimelist.net), which is in most cases the japanese title
|
||||
- e.g. instead of "Demon Slayer" you have to search "Kimetsu no Yaiba"
|
||||
|
||||
#### Search by ID
|
||||
|
||||
- [Jikan](https://jikan.moe/)
|
||||
- the ID you need is the ID of the anime on [My Anime List](https://myanimelist.net)
|
||||
- you can find this ID in the URL
|
||||
|
|
@ -127,36 +144,45 @@ Now you select the result you want and the plugin will cast it's magic and creat
|
|||
- e.g. for "Factorio" the URL looks like this `https://store.steampowered.com/app/427520/Factorio/` so the ID is `427520`
|
||||
|
||||
### Problems, unexpected behavior or improvement suggestions?
|
||||
|
||||
You are more than welcome to open an issue on [GitHub](https://github.com/mProjectsCode/obsidian-media-db-plugin/issues).
|
||||
|
||||
### Changelog
|
||||
|
||||
#### 0.3.2
|
||||
|
||||
- Added Board Game Geek API (documentation pending)
|
||||
- More information in the search results
|
||||
- various fixes
|
||||
|
||||
#### 0.3.1
|
||||
|
||||
- various fixes
|
||||
|
||||
#### 0.3.0
|
||||
|
||||
- Added bulk import. Import a folder of media notes as Media DB entries (thanks to [PaperOrb](https://github.com/PaperOrb) on GitHub for their input and for helping me test this feature)
|
||||
- Added a custom result select modal that allows you to select multiple results at once
|
||||
- Fixed a bug where the note creation would fail when the metadata included a field with the values `null` or `undefined`
|
||||
|
||||
#### 0.2.1
|
||||
|
||||
- fixed a small bug with the initial selection of an API in the ID search modal
|
||||
|
||||
#### 0.2.0
|
||||
|
||||
- Added the option to rename metadata fields through property mappings
|
||||
- fixed note creation falling, when the folder set in the settings did not exist
|
||||
|
||||
### Contributions
|
||||
|
||||
Thank you for wanting to contribute to this project.
|
||||
|
||||
Contributions are always welcome. If you have an idea, feel free to open a feature request under the issue tab or even create a pull request.
|
||||
|
||||
### Credits
|
||||
|
||||
Credits go to:
|
||||
|
||||
- https://github.com/anpigon/obsidian-book-search-plugin for some inspiration and the idea to make this plugin
|
||||
- https://github.com/liamcain/obsidian-periodic-notes for 99% of `Suggest.ts` and `FolderSuggest.ts`
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { RequestUrlParam, RequestUrlResponse } from "obsidian";
|
||||
import { RequestUrlParam, RequestUrlResponse } from 'obsidian';
|
||||
|
||||
export function requestUrl(request: RequestUrlParam): Promise<RequestUrlResponse> {
|
||||
return fetch(request.url, {
|
||||
method: request.method,
|
||||
headers: request.headers,
|
||||
body: request.body,
|
||||
}).then(async (response) => {
|
||||
}).then(async response => {
|
||||
if (response.status >= 400 && request.throw) {
|
||||
throw new Error(`Request failed, ${response.status}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ import builtins from 'builtin-modules';
|
|||
import esbuildSvelte from 'esbuild-svelte';
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = (process.argv[2] === 'production');
|
||||
const prod = process.argv[2] === 'production';
|
||||
|
||||
esbuild.build({
|
||||
esbuild
|
||||
.build({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
|
|
@ -43,7 +43,8 @@ esbuild.build({
|
|||
'@codemirror/text',
|
||||
'@codemirror/tooltip',
|
||||
'@codemirror/view',
|
||||
...builtins],
|
||||
...builtins,
|
||||
],
|
||||
format: 'cjs',
|
||||
watch: !prod,
|
||||
target: 'es2016',
|
||||
|
|
@ -57,4 +58,5 @@ esbuild.build({
|
|||
preprocess: sveltePreprocess(),
|
||||
}),
|
||||
],
|
||||
}).catch(() => process.exit(1));
|
||||
})
|
||||
.catch(() => process.exit(1));
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
module.exports = {
|
||||
"roots": [
|
||||
"<rootDir>/src",
|
||||
"<rootDir>"
|
||||
],
|
||||
"testMatch": [
|
||||
"**/__tests__/**/*.+(ts|tsx|js)",
|
||||
"**/?(*.)+(spec|test).+(ts|tsx|js)"
|
||||
],
|
||||
"transform": {
|
||||
"^.+\\.(ts|tsx)$": "ts-jest"
|
||||
roots: ['<rootDir>/src', '<rootDir>'],
|
||||
testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'],
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx)$': 'ts-jest',
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
|||
26
package-lock.json
generated
26
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "obsidian-media-db-plugin",
|
||||
"version": "0.3.2",
|
||||
"version": "0.4.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-media-db-plugin",
|
||||
"version": "0.3.2",
|
||||
"version": "0.4.1",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"ts-node": "^10.8.1",
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
"jest": "^28.1.2",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"obsidian": "latest",
|
||||
"prettier": "2.7.1",
|
||||
"svelte": "^3.50.1",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"ts-jest": "^28.0.5",
|
||||
|
|
@ -4353,6 +4354,21 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-format": {
|
||||
"version": "28.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz",
|
||||
|
|
@ -8623,6 +8639,12 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-format": {
|
||||
"version": "28.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json",
|
||||
"test": "jest"
|
||||
"test": "jest",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Moritz Jung",
|
||||
|
|
@ -29,7 +30,8 @@
|
|||
"svelte-preprocess": "^4.10.7",
|
||||
"ts-jest": "^28.0.5",
|
||||
"tslib": "2.3.1",
|
||||
"typescript": "4.4.4"
|
||||
"typescript": "4.4.4",
|
||||
"prettier": "2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ts-node": "^10.8.1",
|
||||
|
|
|
|||
|
|
@ -42,13 +42,15 @@ export class BoardGameGeekAPI extends APIModel {
|
|||
const title = boardgame.querySelector('name')!.textContent!;
|
||||
const year = boardgame.querySelector('yearpublished')?.textContent ?? '';
|
||||
|
||||
ret.push(new BoardGameModel({
|
||||
ret.push(
|
||||
new BoardGameModel({
|
||||
dataSource: this.apiName,
|
||||
id,
|
||||
title,
|
||||
englishTitle: title,
|
||||
year,
|
||||
} as BoardGameModel));
|
||||
} as BoardGameModel)
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -97,6 +99,5 @@ export class BoardGameGeekAPI extends APIModel {
|
|||
} as BoardGameModel);
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,33 +43,39 @@ export class MALAPI extends APIModel {
|
|||
for (const result of data.data) {
|
||||
const type = this.typeMappings.get(result.type?.toLowerCase());
|
||||
if (type === undefined) {
|
||||
ret.push(new MovieModel({
|
||||
ret.push(
|
||||
new MovieModel({
|
||||
subType: '',
|
||||
title: result.title,
|
||||
englishTitle: result.title_english ?? result.title,
|
||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||
dataSource: this.apiName,
|
||||
id: result.mal_id,
|
||||
} as MovieModel));
|
||||
} as MovieModel)
|
||||
);
|
||||
}
|
||||
if (type === 'movie' || type === 'special') {
|
||||
ret.push(new MovieModel({
|
||||
ret.push(
|
||||
new MovieModel({
|
||||
subType: type,
|
||||
title: result.title,
|
||||
englishTitle: result.title_english ?? result.title,
|
||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||
dataSource: this.apiName,
|
||||
id: result.mal_id,
|
||||
} as MovieModel));
|
||||
} as MovieModel)
|
||||
);
|
||||
} else if (type === 'series' || type === 'ova') {
|
||||
ret.push(new SeriesModel({
|
||||
ret.push(
|
||||
new SeriesModel({
|
||||
subType: type,
|
||||
title: result.title,
|
||||
englishTitle: result.title_english ?? result.title,
|
||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||
dataSource: this.apiName,
|
||||
id: result.mal_id,
|
||||
} as SeriesModel));
|
||||
} as SeriesModel)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +114,7 @@ export class MALAPI extends APIModel {
|
|||
image: result.images?.jpg?.image_url ?? '',
|
||||
|
||||
released: true,
|
||||
premiere: (new Date(result.aired?.from)).toLocaleDateString() ?? 'unknown',
|
||||
premiere: new Date(result.aired?.from).toLocaleDateString() ?? 'unknown',
|
||||
|
||||
userData: {
|
||||
watched: false,
|
||||
|
|
@ -137,7 +143,7 @@ export class MALAPI extends APIModel {
|
|||
image: result.images?.jpg?.image_url ?? '',
|
||||
|
||||
released: true,
|
||||
premiere: (new Date(result.aired?.from)).toLocaleDateString() ?? 'unknown',
|
||||
premiere: new Date(result.aired?.from).toLocaleDateString() ?? 'unknown',
|
||||
|
||||
userData: {
|
||||
watched: false,
|
||||
|
|
@ -165,8 +171,8 @@ export class MALAPI extends APIModel {
|
|||
image: result.images?.jpg?.image_url ?? '',
|
||||
|
||||
released: true,
|
||||
airedFrom: (new Date(result.aired?.from)).toLocaleDateString() ?? 'unknown',
|
||||
airedTo: (new Date(result.aired?.to)).toLocaleDateString() ?? 'unknown',
|
||||
airedFrom: new Date(result.aired?.from).toLocaleDateString() ?? 'unknown',
|
||||
airedTo: new Date(result.aired?.to).toLocaleDateString() ?? 'unknown',
|
||||
airing: result.airing,
|
||||
|
||||
userData: {
|
||||
|
|
|
|||
|
|
@ -41,18 +41,20 @@ export class MusicBrainzAPI extends APIModel {
|
|||
let ret: MediaTypeModel[] = [];
|
||||
|
||||
for (const result of data['release-groups']) {
|
||||
ret.push(new MusicReleaseModel({
|
||||
ret.push(
|
||||
new MusicReleaseModel({
|
||||
type: 'musicRelease',
|
||||
title: result.title,
|
||||
englishTitle: result.title,
|
||||
year: (new Date(result['first-release-date'])).getFullYear().toString(),
|
||||
year: new Date(result['first-release-date']).getFullYear().toString(),
|
||||
dataSource: this.apiName,
|
||||
url: '',
|
||||
id: result.id,
|
||||
|
||||
artists: result['artist-credit'].map((a: any) => a.name),
|
||||
subType: result['primary-type'],
|
||||
} as MusicReleaseModel));
|
||||
} as MusicReleaseModel)
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -81,7 +83,7 @@ export class MusicBrainzAPI extends APIModel {
|
|||
type: 'musicRelease',
|
||||
title: result.title,
|
||||
englishTitle: result.title,
|
||||
year: (new Date(result['first-release-date'])).getFullYear().toString(),
|
||||
year: new Date(result['first-release-date']).getFullYear().toString(),
|
||||
dataSource: this.apiName,
|
||||
url: '',
|
||||
id: result.id,
|
||||
|
|
|
|||
|
|
@ -56,32 +56,38 @@ export class OMDbAPI extends APIModel {
|
|||
continue;
|
||||
}
|
||||
if (type === 'movie') {
|
||||
ret.push(new MovieModel({
|
||||
ret.push(
|
||||
new MovieModel({
|
||||
type: type,
|
||||
title: result.Title,
|
||||
englishTitle: result.Title,
|
||||
year: result.Year,
|
||||
dataSource: this.apiName,
|
||||
id: result.imdbID,
|
||||
} as MovieModel));
|
||||
} as MovieModel)
|
||||
);
|
||||
} else if (type === 'series') {
|
||||
ret.push(new SeriesModel({
|
||||
ret.push(
|
||||
new SeriesModel({
|
||||
type: type,
|
||||
title: result.Title,
|
||||
englishTitle: result.Title,
|
||||
year: result.Year,
|
||||
dataSource: this.apiName,
|
||||
id: result.imdbID,
|
||||
} as SeriesModel));
|
||||
} as SeriesModel)
|
||||
);
|
||||
} else if (type === 'game') {
|
||||
ret.push(new GameModel({
|
||||
ret.push(
|
||||
new GameModel({
|
||||
type: type,
|
||||
title: result.Title,
|
||||
englishTitle: result.Title,
|
||||
year: result.Year,
|
||||
dataSource: this.apiName,
|
||||
id: result.imdbID,
|
||||
} as GameModel));
|
||||
} as GameModel)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +136,7 @@ export class OMDbAPI extends APIModel {
|
|||
image: result.Poster ?? '',
|
||||
|
||||
released: true,
|
||||
premiere: (new Date(result.Released)).toLocaleDateString() ?? 'unknown',
|
||||
premiere: new Date(result.Released).toLocaleDateString() ?? 'unknown',
|
||||
|
||||
userData: {
|
||||
watched: false,
|
||||
|
|
@ -159,7 +165,7 @@ export class OMDbAPI extends APIModel {
|
|||
|
||||
released: true,
|
||||
airing: false,
|
||||
airedFrom: (new Date(result.Released)).toLocaleDateString() ?? 'unknown',
|
||||
airedFrom: new Date(result.Released).toLocaleDateString() ?? 'unknown',
|
||||
airedTo: 'unknown',
|
||||
|
||||
userData: {
|
||||
|
|
@ -185,7 +191,7 @@ export class OMDbAPI extends APIModel {
|
|||
image: result.Poster ?? '',
|
||||
|
||||
released: true,
|
||||
releaseDate: (new Date(result.Released)).toLocaleDateString() ?? 'unknown',
|
||||
releaseDate: new Date(result.Released).toLocaleDateString() ?? 'unknown',
|
||||
|
||||
userData: {
|
||||
played: false,
|
||||
|
|
|
|||
|
|
@ -52,14 +52,16 @@ export class SteamAPI extends APIModel {
|
|||
let ret: MediaTypeModel[] = [];
|
||||
|
||||
for (const result of filteredData) {
|
||||
ret.push(new GameModel({
|
||||
ret.push(
|
||||
new GameModel({
|
||||
type: MediaType.Game,
|
||||
title: result.name,
|
||||
englishTitle: result.name,
|
||||
year: '',
|
||||
dataSource: this.apiName,
|
||||
id: result.appid,
|
||||
} as GameModel));
|
||||
} as GameModel)
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -98,7 +100,7 @@ export class SteamAPI extends APIModel {
|
|||
type: MediaType.Game,
|
||||
title: result.name,
|
||||
englishTitle: result.name,
|
||||
year: (new Date(result.release_date.date)).getFullYear().toString(),
|
||||
year: new Date(result.release_date.date).getFullYear().toString(),
|
||||
dataSource: this.apiName,
|
||||
url: `https://store.steampowered.com/app/${result.steam_appid}`,
|
||||
id: result.steam_appid,
|
||||
|
|
@ -108,7 +110,7 @@ export class SteamAPI extends APIModel {
|
|||
image: result.header_image ?? '',
|
||||
|
||||
released: !result.release_date?.comming_soon,
|
||||
releaseDate: (new Date(result.release_date?.date)).toLocaleDateString() ?? 'unknown',
|
||||
releaseDate: new Date(result.release_date?.date).toLocaleDateString() ?? 'unknown',
|
||||
|
||||
userData: {
|
||||
played: false,
|
||||
|
|
@ -117,6 +119,5 @@ export class SteamAPI extends APIModel {
|
|||
} as GameModel);
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,14 +33,16 @@ export class WikipediaAPI extends APIModel {
|
|||
let ret: MediaTypeModel[] = [];
|
||||
|
||||
for (const result of data.query.search) {
|
||||
ret.push(new WikiModel({
|
||||
ret.push(
|
||||
new WikiModel({
|
||||
type: 'wiki',
|
||||
title: result.title,
|
||||
englishTitle: result.title,
|
||||
year: '',
|
||||
dataSource: this.apiName,
|
||||
id: result.pageid,
|
||||
} as WikiModel));
|
||||
} as WikiModel)
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -70,7 +72,7 @@ export class WikipediaAPI extends APIModel {
|
|||
id: result.pageid,
|
||||
|
||||
wikiUrl: result.fullurl,
|
||||
lastUpdated: (new Date(result.touched)).toLocaleDateString() ?? 'unknown',
|
||||
lastUpdated: new Date(result.touched).toLocaleDateString() ?? 'unknown',
|
||||
length: result.length,
|
||||
|
||||
userData: {},
|
||||
|
|
|
|||
52
src/main.ts
52
src/main.ts
|
|
@ -47,12 +47,11 @@ export default class MediaDbPlugin extends Plugin {
|
|||
this.mediaTypeManager.updateTemplates(this.settings);
|
||||
|
||||
// add icon to the left ribbon
|
||||
const ribbonIconEl = this.addRibbonIcon('database', 'Add new Media DB entry', (evt: MouseEvent) =>
|
||||
this.createEntryWithAdvancedSearchModal(),
|
||||
);
|
||||
const ribbonIconEl = this.addRibbonIcon('database', 'Add new Media DB entry', (evt: MouseEvent) => this.createEntryWithAdvancedSearchModal());
|
||||
ribbonIconEl.addClass('obsidian-media-db-plugin-ribbon-class');
|
||||
|
||||
this.registerEvent(this.app.workspace.on('file-menu', (menu, file) => {
|
||||
this.registerEvent(
|
||||
this.app.workspace.on('file-menu', (menu, file) => {
|
||||
if (file instanceof TFolder) {
|
||||
menu.addItem(item => {
|
||||
item.setTitle('Import folder as Media DB entries')
|
||||
|
|
@ -60,7 +59,8 @@ export default class MediaDbPlugin extends Plugin {
|
|||
.onClick(() => this.createEntriesFromFolder(file));
|
||||
});
|
||||
}
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
// register command to open search modal
|
||||
this.addCommand({
|
||||
|
|
@ -129,8 +129,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
* - maybe custom link syntax
|
||||
*/
|
||||
async createLinkWithSearchModal() {
|
||||
|
||||
let apiSearchResults: MediaTypeModel[] = await this.modalHelper.openAdvancedSearchModal({}, async (advancedSearchModalData) => {
|
||||
let apiSearchResults: MediaTypeModel[] = await this.modalHelper.openAdvancedSearchModal({}, async advancedSearchModalData => {
|
||||
return await this.apiManager.query(advancedSearchModalData.query, advancedSearchModalData.apis);
|
||||
});
|
||||
|
||||
|
|
@ -138,7 +137,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
return;
|
||||
}
|
||||
|
||||
const selectResults: MediaTypeModel[] = await this.modalHelper.openSelectModal({elements: apiSearchResults, multiSelect: false}, async (selectModalData) => {
|
||||
const selectResults: MediaTypeModel[] = await this.modalHelper.openSelectModal({ elements: apiSearchResults, multiSelect: false }, async selectModalData => {
|
||||
return await this.queryDetails(selectModalData.selected);
|
||||
});
|
||||
|
||||
|
|
@ -158,7 +157,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
|
||||
async createEntryWithSearchModal() {
|
||||
let types: string[] = [];
|
||||
let apiSearchResults: MediaTypeModel[] = await this.modalHelper.openSearchModal({}, async (searchModalData) => {
|
||||
let apiSearchResults: MediaTypeModel[] = await this.modalHelper.openSearchModal({}, async searchModalData => {
|
||||
types = searchModalData.types;
|
||||
const apis = this.apiManager.apis.filter(x => x.hasTypeOverlap(searchModalData.types)).map(x => x.apiName);
|
||||
return await this.apiManager.query(searchModalData.query, apis);
|
||||
|
|
@ -176,14 +175,14 @@ export default class MediaDbPlugin extends Plugin {
|
|||
let proceed: boolean;
|
||||
|
||||
while (!proceed) {
|
||||
selectResults = await this.modalHelper.openSelectModal({elements: apiSearchResults}, async (selectModalData) => {
|
||||
selectResults = await this.modalHelper.openSelectModal({ elements: apiSearchResults }, async selectModalData => {
|
||||
return await this.queryDetails(selectModalData.selected);
|
||||
});
|
||||
if (!selectResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
proceed = await this.modalHelper.openPreviewModal({elements: selectResults}, async (previewModalData) => {
|
||||
proceed = await this.modalHelper.openPreviewModal({ elements: selectResults }, async previewModalData => {
|
||||
return previewModalData.confirmed;
|
||||
});
|
||||
}
|
||||
|
|
@ -192,7 +191,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
}
|
||||
|
||||
async createEntryWithAdvancedSearchModal() {
|
||||
let apiSearchResults: MediaTypeModel[] = await this.modalHelper.openAdvancedSearchModal({}, async (advancedSearchModalData) => {
|
||||
let apiSearchResults: MediaTypeModel[] = await this.modalHelper.openAdvancedSearchModal({}, async advancedSearchModalData => {
|
||||
return await this.apiManager.query(advancedSearchModalData.query, advancedSearchModalData.apis);
|
||||
});
|
||||
|
||||
|
|
@ -205,14 +204,14 @@ export default class MediaDbPlugin extends Plugin {
|
|||
let proceed: boolean;
|
||||
|
||||
while (!proceed) {
|
||||
selectResults = await this.modalHelper.openSelectModal({elements: apiSearchResults}, async (selectModalData) => {
|
||||
selectResults = await this.modalHelper.openSelectModal({ elements: apiSearchResults }, async selectModalData => {
|
||||
return await this.queryDetails(selectModalData.selected);
|
||||
});
|
||||
if (!selectResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
proceed = await this.modalHelper.openPreviewModal({elements: selectResults}, async (previewModalData) => {
|
||||
proceed = await this.modalHelper.openPreviewModal({ elements: selectResults }, async previewModalData => {
|
||||
return previewModalData.confirmed;
|
||||
});
|
||||
}
|
||||
|
|
@ -225,14 +224,14 @@ export default class MediaDbPlugin extends Plugin {
|
|||
let proceed: boolean;
|
||||
|
||||
while (!proceed) {
|
||||
idSearchResult = await this.modalHelper.openIdSearchModal({}, async (idSearchModalData) => {
|
||||
idSearchResult = await this.modalHelper.openIdSearchModal({}, async idSearchModalData => {
|
||||
return await this.apiManager.queryDetailedInfoById(idSearchModalData.query, idSearchModalData.api);
|
||||
});
|
||||
if (!idSearchResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
proceed = await this.modalHelper.openPreviewModal({elements: [idSearchResult]}, async (previewModalData) => {
|
||||
proceed = await this.modalHelper.openPreviewModal({ elements: [idSearchResult] }, async previewModalData => {
|
||||
return previewModalData.confirmed;
|
||||
});
|
||||
}
|
||||
|
|
@ -284,7 +283,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
return fileContent;
|
||||
}
|
||||
|
||||
async attachFile(fileMetadata: any, fileContent: string, fileToAttach?: TFile): Promise<{ fileMetadata: any, fileContent: string }> {
|
||||
async attachFile(fileMetadata: any, fileContent: string, fileToAttach?: TFile): Promise<{ fileMetadata: any; fileContent: string }> {
|
||||
if (!fileToAttach) {
|
||||
return { fileMetadata: fileMetadata, fileContent: fileContent };
|
||||
}
|
||||
|
|
@ -301,7 +300,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
return { fileMetadata: fileMetadata, fileContent: fileContent };
|
||||
}
|
||||
|
||||
async attachTemplate(fileMetadata: any, fileContent: string, template: string): Promise<{ fileMetadata: any, fileContent: string }> {
|
||||
async attachTemplate(fileMetadata: any, fileContent: string, template: string): Promise<{ fileMetadata: any; fileContent: string }> {
|
||||
if (!template) {
|
||||
return { fileMetadata: fileMetadata, fileContent: fileContent };
|
||||
}
|
||||
|
|
@ -428,17 +427,16 @@ export default class MediaDbPlugin extends Plugin {
|
|||
} else {
|
||||
await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachTemplate: true, folder: activeFile.parent, openNote: true });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async createEntriesFromFolder(folder: TFolder) {
|
||||
const erroredFiles: { filePath: string, error: string }[] = [];
|
||||
const erroredFiles: { filePath: string; error: string }[] = [];
|
||||
let canceled: boolean = false;
|
||||
|
||||
const {selectedAPI, titleFieldName, appendContent} = await new Promise<{ selectedAPI: string, titleFieldName: string, appendContent: boolean }>((resolve, reject) => {
|
||||
new MediaDbFolderImportModal(this.app, this, ((selectedAPI: string, titleFieldName: string, appendContent: boolean) => {
|
||||
const { selectedAPI, titleFieldName, appendContent } = await new Promise<{ selectedAPI: string; titleFieldName: string; appendContent: boolean }>((resolve, reject) => {
|
||||
new MediaDbFolderImportModal(this.app, this, (selectedAPI: string, titleFieldName: string, appendContent: boolean) => {
|
||||
resolve({ selectedAPI, titleFieldName, appendContent });
|
||||
})).open();
|
||||
}).open();
|
||||
});
|
||||
|
||||
for (const child of folder.children) {
|
||||
|
|
@ -507,7 +505,7 @@ export default class MediaDbPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async createErroredFilesReport(erroredFiles: { filePath: string, error: string }[]): Promise<void> {
|
||||
async createErroredFilesReport(erroredFiles: { filePath: string; error: string }[]): Promise<void> {
|
||||
const title = `bulk import error report ${dateTimeToString(new Date())}`;
|
||||
const filePath = `${this.settings.folder.replace(/\/$/, '')}/${title}.md`;
|
||||
|
||||
|
|
@ -528,9 +526,11 @@ export default class MediaDbPlugin extends Plugin {
|
|||
let newPropertyMappings: PropertyMappingModel[] = [];
|
||||
for (const defaultPropertyMappingModel of defaultSettings.propertyMappingModels) {
|
||||
let newPropertyMappingModel: PropertyMappingModel = loadedSettings.propertyMappingModels.find(x => x.type === defaultPropertyMappingModel.type);
|
||||
if (newPropertyMappingModel === undefined) { // if the propertyMappingModel exists in the default settings but not the loaded settings, add it
|
||||
if (newPropertyMappingModel === undefined) {
|
||||
// if the propertyMappingModel exists in the default settings but not the loaded settings, add it
|
||||
newPropertyMappings.push(defaultPropertyMappingModel);
|
||||
} else { // if the propertyMappingModel also exists in the loaded settings, add it from there
|
||||
} else {
|
||||
// if the propertyMappingModel also exists in the loaded settings, add it from there
|
||||
let newProperties: PropertyMapping[] = [];
|
||||
|
||||
for (const defaultProperty of defaultPropertyMappingModel.properties) {
|
||||
|
|
|
|||
|
|
@ -9,14 +9,13 @@ export class MediaDbAdvancedSearchModal extends Modal {
|
|||
query: string;
|
||||
isBusy: boolean;
|
||||
title: string;
|
||||
selectedApis: { name: string, selected: boolean }[];
|
||||
selectedApis: { name: string; selected: boolean }[];
|
||||
|
||||
searchBtn: ButtonComponent;
|
||||
|
||||
submitCallback?: (res: AdvancedSearchModalData) => void;
|
||||
closeCallback?: (err?: Error) => void;
|
||||
|
||||
|
||||
constructor(plugin: MediaDbPlugin, advancedSearchModalOptions: AdvancedSearchModalOptions) {
|
||||
advancedSearchModalOptions = Object.assign({}, ADVANCED_SEARCH_MODAL_DEFAULT_OPTIONS, advancedSearchModalOptions);
|
||||
super(plugin.app);
|
||||
|
|
@ -99,7 +98,7 @@ export class MediaDbAdvancedSearchModal extends Modal {
|
|||
const apiToggleComponent = new ToggleComponent(apiToggleComponentWrapper);
|
||||
apiToggleComponent.setTooltip(api.apiName);
|
||||
apiToggleComponent.setValue(this.selectedApis.find(x => x.name === api.apiName).selected);
|
||||
apiToggleComponent.onChange((value) => {
|
||||
apiToggleComponent.onChange(value => {
|
||||
this.selectedApis.find(x => x.name === api.apiName).selected = value;
|
||||
});
|
||||
apiToggleComponentWrapper.appendChild(apiToggleComponent.toggleEl);
|
||||
|
|
@ -129,5 +128,4 @@ export class MediaDbAdvancedSearchModal extends Modal {
|
|||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ export class MediaDbFolderImportModal extends Modal {
|
|||
}
|
||||
apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl);
|
||||
|
||||
|
||||
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
||||
contentEl.createEl('h3', { text: 'Append note content to Media DB entry.' });
|
||||
|
||||
|
|
@ -54,10 +53,9 @@ export class MediaDbFolderImportModal extends Modal {
|
|||
|
||||
const appendContentToggle = new ToggleComponent(appendContentToggleElementWrapper);
|
||||
appendContentToggle.setValue(false);
|
||||
appendContentToggle.onChange(value => this.appendContent = value);
|
||||
appendContentToggle.onChange(value => (this.appendContent = value));
|
||||
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.' });
|
||||
|
||||
|
|
@ -65,8 +63,8 @@ export class MediaDbFolderImportModal extends Modal {
|
|||
const titleFieldNameComponent = new TextComponent(contentEl);
|
||||
titleFieldNameComponent.inputEl.style.width = '100%';
|
||||
titleFieldNameComponent.setPlaceholder(placeholder);
|
||||
titleFieldNameComponent.onChange(value => this.titleFieldName = value);
|
||||
titleFieldNameComponent.inputEl.addEventListener('keydown', (ke) => {
|
||||
titleFieldNameComponent.onChange(value => (this.titleFieldName = value));
|
||||
titleFieldNameComponent.inputEl.addEventListener('keydown', ke => {
|
||||
if (ke.key === 'Enter') {
|
||||
this.submit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ export class MediaDbIdSearchModal extends Modal {
|
|||
submitCallback?: (res: IdSearchModalData, err?: Error) => void;
|
||||
closeCallback?: (err?: Error) => void;
|
||||
|
||||
|
||||
constructor(plugin: MediaDbPlugin, idSearchModalOptions: IdSearchModalOptions) {
|
||||
idSearchModalOptions = Object.assign({}, ID_SEARCH_MODAL_DEFAULT_OPTIONS, idSearchModalOptions);
|
||||
super(plugin.app);
|
||||
|
|
@ -114,5 +113,4 @@ export class MediaDbIdSearchModal extends Modal {
|
|||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,13 @@ export class MediaDbSearchModal extends Modal {
|
|||
query: string;
|
||||
isBusy: boolean;
|
||||
title: string;
|
||||
selectedTypes: { name: string, selected: boolean }[];
|
||||
selectedTypes: { name: string; selected: boolean }[];
|
||||
|
||||
searchBtn: ButtonComponent;
|
||||
|
||||
submitCallback?: (res: SearchModalData) => void;
|
||||
closeCallback?: (err?: Error) => void;
|
||||
|
||||
|
||||
constructor(plugin: MediaDbPlugin, searchModalOptions: SearchModalOptions) {
|
||||
searchModalOptions = Object.assign({}, SEARCH_MODAL_DEFAULT_OPTIONS, searchModalOptions);
|
||||
super(plugin.app);
|
||||
|
|
@ -106,7 +105,7 @@ export class MediaDbSearchModal extends Modal {
|
|||
const apiToggleComponent = new ToggleComponent(apiToggleComponentWrapper);
|
||||
apiToggleComponent.setTooltip(unCamelCase(mediaType));
|
||||
apiToggleComponent.setValue(this.selectedTypes.find(x => x.name === mediaType).selected);
|
||||
apiToggleComponent.onChange((value) => {
|
||||
apiToggleComponent.onChange(value => {
|
||||
this.selectedTypes.find(x => x.name === mediaType).selected = value;
|
||||
});
|
||||
apiToggleComponentWrapper.appendChild(apiToggleComponent.toggleEl);
|
||||
|
|
@ -136,5 +135,4 @@ export class MediaDbSearchModal extends Modal {
|
|||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ export class MediaDbSearchResultModal extends SelectModal<MediaTypeModel> {
|
|||
closeCallback: (err?: Error) => void;
|
||||
skipCallback: () => void;
|
||||
|
||||
|
||||
constructor(plugin: MediaDbPlugin, selectModalOptions: SelectModalOptions) {
|
||||
selectModalOptions = Object.assign({}, SELECT_MODAL_OPTIONS_DEFAULT, selectModalOptions);
|
||||
super(plugin.app, selectModalOptions.elements, selectModalOptions.multiSelect);
|
||||
|
|
@ -62,7 +61,6 @@ export class MediaDbSearchResultModal extends SelectModal<MediaTypeModel> {
|
|||
}
|
||||
|
||||
onClose() {
|
||||
|
||||
this.closeCallback();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ export abstract class SelectModal<T> extends Modal {
|
|||
elements: T[];
|
||||
selectModalElements: SelectModalElement<T>[];
|
||||
|
||||
|
||||
protected constructor(app: App, elements: T[], allowMultiSelect: boolean = true) {
|
||||
super(app);
|
||||
this.allowMultiSelect = allowMultiSelect;
|
||||
|
|
@ -34,18 +33,18 @@ export abstract class SelectModal<T> extends Modal {
|
|||
this.elements = elements;
|
||||
this.selectModalElements = [];
|
||||
|
||||
this.scope.register([], 'ArrowUp', (evt) => {
|
||||
this.scope.register([], 'ArrowUp', evt => {
|
||||
this.highlightUp();
|
||||
evt.preventDefault();
|
||||
});
|
||||
this.scope.register([], 'ArrowDown', (evt) => {
|
||||
this.scope.register([], 'ArrowDown', evt => {
|
||||
this.highlightDown();
|
||||
evt.preventDefault();
|
||||
});
|
||||
this.scope.register([], 'ArrowRight', () => {
|
||||
this.activateHighlighted();
|
||||
});
|
||||
this.scope.register([], ' ', (evt) => {
|
||||
this.scope.register([], ' ', evt => {
|
||||
if (this.elementWrapper && this.elementWrapper === document.activeElement) {
|
||||
this.activateHighlighted();
|
||||
evt.preventDefault();
|
||||
|
|
@ -171,5 +170,4 @@ export abstract class SelectModal<T> extends Modal {
|
|||
|
||||
return this.selectModalElements.filter(x => x.id === nextId).first();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,5 +83,4 @@ export class SelectModalElement<T> {
|
|||
this.element.removeClass(cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {MediaTypeModel} from './MediaTypeModel';
|
|||
import { mediaDbTag, migrateObject } from '../utils/Utils';
|
||||
import { MediaType } from '../utils/MediaType';
|
||||
|
||||
|
||||
export class BoardGameModel extends MediaTypeModel {
|
||||
genres: string[];
|
||||
onlineRating: number;
|
||||
|
|
@ -15,7 +14,6 @@ export class BoardGameModel extends MediaTypeModel {
|
|||
personalRating: number;
|
||||
};
|
||||
|
||||
|
||||
constructor(obj: any = {}) {
|
||||
super();
|
||||
|
||||
|
|
@ -48,5 +46,4 @@ export class BoardGameModel extends MediaTypeModel {
|
|||
getSummary(): string {
|
||||
return this.englishTitle + ' (' + this.year + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {MediaTypeModel} from './MediaTypeModel';
|
|||
import { mediaDbTag, migrateObject } from '../utils/Utils';
|
||||
import { MediaType } from '../utils/MediaType';
|
||||
|
||||
|
||||
export class GameModel extends MediaTypeModel {
|
||||
genres: string[];
|
||||
onlineRating: number;
|
||||
|
|
@ -16,7 +15,6 @@ export class GameModel extends MediaTypeModel {
|
|||
personalRating: number;
|
||||
};
|
||||
|
||||
|
||||
constructor(obj: any = {}) {
|
||||
super();
|
||||
|
||||
|
|
@ -50,5 +48,4 @@ export class GameModel extends MediaTypeModel {
|
|||
getSummary(): string {
|
||||
return this.englishTitle + ' (' + this.year + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ export abstract class MediaTypeModel {
|
|||
|
||||
userData: object;
|
||||
|
||||
|
||||
protected constructor() {
|
||||
this.type = undefined;
|
||||
this.subType = undefined;
|
||||
|
|
@ -41,5 +40,4 @@ export abstract class MediaTypeModel {
|
|||
delete copy.userData;
|
||||
return copy;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {MediaTypeModel} from './MediaTypeModel';
|
|||
import { mediaDbTag, migrateObject } from '../utils/Utils';
|
||||
import { MediaType } from '../utils/MediaType';
|
||||
|
||||
|
||||
export class MovieModel extends MediaTypeModel {
|
||||
genres: string[];
|
||||
producer: string;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {MediaTypeModel} from './MediaTypeModel';
|
|||
import { mediaDbTag, migrateObject } from '../utils/Utils';
|
||||
import { MediaType } from '../utils/MediaType';
|
||||
|
||||
|
||||
export class MusicReleaseModel extends MediaTypeModel {
|
||||
type: string;
|
||||
subType: string;
|
||||
|
|
@ -50,8 +49,7 @@ export class MusicReleaseModel extends MediaTypeModel {
|
|||
|
||||
getSummary(): string {
|
||||
let summary = this.title + ' (' + this.year + ')';
|
||||
if (this.artists.length > 0)
|
||||
summary += ' - ' + this.artists.join(', ');
|
||||
if (this.artists.length > 0) summary += ' - ' + this.artists.join(', ');
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {MediaTypeModel} from './MediaTypeModel';
|
|||
import { mediaDbTag, migrateObject } from '../utils/Utils';
|
||||
import { MediaType } from '../utils/MediaType';
|
||||
|
||||
|
||||
export class SeriesModel extends MediaTypeModel {
|
||||
type: string;
|
||||
subType: string;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {MediaTypeModel} from './MediaTypeModel';
|
|||
import { mediaDbTag, migrateObject } from '../utils/Utils';
|
||||
import { MediaType } from '../utils/MediaType';
|
||||
|
||||
|
||||
export class WikiModel extends MediaTypeModel {
|
||||
type: string;
|
||||
subType: string;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ export class PropertyMapper {
|
|||
// @ts-ignore
|
||||
newObj[propertyMapping.newProperty] = value;
|
||||
} else if (propertyMapping.mapping === PropertyMappingOption.Remove) {
|
||||
|
||||
} else if (propertyMapping.mapping === PropertyMappingOption.Default) {
|
||||
// @ts-ignore
|
||||
newObj[key] = value;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export class PropertyMappingModel {
|
|||
this.properties = properties ?? [];
|
||||
}
|
||||
|
||||
validate(): { res: boolean, err?: Error } {
|
||||
validate(): { res: boolean; err?: Error } {
|
||||
console.debug(`MDB | validated property mappings for ${this.type}`);
|
||||
|
||||
// check properties
|
||||
|
|
@ -43,7 +43,9 @@ export class PropertyMappingModel {
|
|||
// two or more properties are mapped to the same property
|
||||
return {
|
||||
res: false,
|
||||
err: new PropertyMappingNameConflictError(`Multiple remapped properties (${propertiesWithSameTarget.map(x => x.toString()).toString()}) may not share the same name.`),
|
||||
err: new PropertyMappingNameConflictError(
|
||||
`Multiple remapped properties (${propertiesWithSameTarget.map(x => x.toString()).toString()}) may not share the same name.`
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -93,7 +95,7 @@ export class PropertyMapping {
|
|||
this.locked = locked ?? false;
|
||||
}
|
||||
|
||||
validate(): { res: boolean, err?: Error } {
|
||||
validate(): { res: boolean; err?: Error } {
|
||||
// locked property may only be default
|
||||
if (this.locked) {
|
||||
if (this.mapping === PropertyMappingOption.Remove) {
|
||||
|
|
|
|||
|
|
@ -8,38 +8,35 @@ import {PropertyMapping, PropertyMappingModel, PropertyMappingOption} from './Pr
|
|||
import { MEDIA_TYPES } from '../utils/MediaTypeManager';
|
||||
import { MediaTypeModel } from '../models/MediaTypeModel';
|
||||
|
||||
|
||||
export interface MediaDbPluginSettings {
|
||||
folder: string,
|
||||
OMDbKey: string,
|
||||
sfwFilter: boolean,
|
||||
folder: string;
|
||||
OMDbKey: string;
|
||||
sfwFilter: boolean;
|
||||
useCustomYamlStringifier: boolean;
|
||||
templates: boolean,
|
||||
templates: boolean;
|
||||
|
||||
movieTemplate: string;
|
||||
seriesTemplate: string;
|
||||
gameTemplate: string;
|
||||
wikiTemplate: string;
|
||||
musicReleaseTemplate: string;
|
||||
boardgameTemplate: string;
|
||||
|
||||
movieTemplate: string,
|
||||
seriesTemplate: string,
|
||||
gameTemplate: string,
|
||||
wikiTemplate: string,
|
||||
musicReleaseTemplate: string,
|
||||
boardgameTemplate: string,
|
||||
movieFileNameTemplate: string;
|
||||
seriesFileNameTemplate: string;
|
||||
gameFileNameTemplate: string;
|
||||
wikiFileNameTemplate: string;
|
||||
musicReleaseFileNameTemplate: string;
|
||||
boardgameFileNameTemplate: string;
|
||||
|
||||
movieFileNameTemplate: string,
|
||||
seriesFileNameTemplate: string,
|
||||
gameFileNameTemplate: string,
|
||||
wikiFileNameTemplate: string,
|
||||
musicReleaseFileNameTemplate: string,
|
||||
boardgameFileNameTemplate: string,
|
||||
|
||||
moviePropertyConversionRules: string,
|
||||
seriesPropertyConversionRules: string,
|
||||
gamePropertyConversionRules: string,
|
||||
wikiPropertyConversionRules: string,
|
||||
musicReleasePropertyConversionRules: string,
|
||||
boardgamePropertyConversionRules: string,
|
||||
|
||||
propertyMappingModels: PropertyMappingModel[],
|
||||
moviePropertyConversionRules: string;
|
||||
seriesPropertyConversionRules: string;
|
||||
gamePropertyConversionRules: string;
|
||||
wikiPropertyConversionRules: string;
|
||||
musicReleasePropertyConversionRules: string;
|
||||
boardgamePropertyConversionRules: string;
|
||||
|
||||
propertyMappingModels: PropertyMappingModel[];
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
||||
|
|
@ -89,9 +86,7 @@ export function getDefaultSettings(plugin: MediaDbPlugin): MediaDbPluginSettings
|
|||
const propertyMappingModel: PropertyMappingModel = new PropertyMappingModel(mediaType);
|
||||
|
||||
for (const key of Object.keys(metadataObj)) {
|
||||
propertyMappingModel.properties.push(
|
||||
new PropertyMapping(key, '', PropertyMappingOption.Default, lockedPropertyMappings.contains(key)),
|
||||
);
|
||||
propertyMappingModel.properties.push(new PropertyMapping(key, '', PropertyMappingOption.Default, lockedPropertyMappings.contains(key)));
|
||||
}
|
||||
|
||||
propertyMappingModels.push(propertyMappingModel);
|
||||
|
|
@ -145,8 +140,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
|||
.setName('SFW filter')
|
||||
.setDesc('Only shows SFW results for APIs that offer filtering.')
|
||||
.addToggle(cb => {
|
||||
cb.setValue(this.plugin.settings.sfwFilter)
|
||||
.onChange(data => {
|
||||
cb.setValue(this.plugin.settings.sfwFilter).onChange(data => {
|
||||
this.plugin.settings.sfwFilter = data;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
|
|
@ -156,8 +150,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
|||
.setName('YAML formatter')
|
||||
.setDesc('Add optional quotation marks around strings in the metadata block.')
|
||||
.addToggle(cb => {
|
||||
cb.setValue(this.plugin.settings.useCustomYamlStringifier)
|
||||
.onChange(data => {
|
||||
cb.setValue(this.plugin.settings.useCustomYamlStringifier).onChange(data => {
|
||||
this.plugin.settings.useCustomYamlStringifier = data;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
|
|
@ -167,14 +160,12 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
|||
.setName('Resolve {{ tags }} in templates')
|
||||
.setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.')
|
||||
.addToggle(cb => {
|
||||
cb.setValue(this.plugin.settings.templates)
|
||||
.onChange(data => {
|
||||
cb.setValue(this.plugin.settings.templates).onChange(data => {
|
||||
this.plugin.settings.templates = data;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
containerEl.createEl('h3', { text: 'Template Settings' });
|
||||
// region templates
|
||||
new Setting(containerEl)
|
||||
|
|
@ -350,7 +341,6 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
|||
Don't forget to save your changes using the save button for each individual category.
|
||||
</p>`;
|
||||
|
||||
|
||||
new PropertyMappingModelsComponent({
|
||||
target: this.containerEl,
|
||||
props: {
|
||||
|
|
@ -374,7 +364,5 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
|||
});
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ export class FolderSuggest extends TextInputSuggest<TFolder> {
|
|||
const lowerCaseInputStr = inputStr.toLowerCase();
|
||||
|
||||
abstractFiles.forEach((folder: TAbstractFile) => {
|
||||
if (
|
||||
folder instanceof TFolder &&
|
||||
folder.path.toLowerCase().contains(lowerCaseInputStr)
|
||||
) {
|
||||
if (folder instanceof TFolder && folder.path.toLowerCase().contains(lowerCaseInputStr)) {
|
||||
folders.push(folder);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,27 +16,23 @@ export class Suggest<T> {
|
|||
this.containerEl = containerEl;
|
||||
|
||||
containerEl.on('click', '.suggestion-item', this.onSuggestionClick.bind(this));
|
||||
containerEl.on(
|
||||
'mousemove',
|
||||
'.suggestion-item',
|
||||
this.onSuggestionMouseover.bind(this),
|
||||
);
|
||||
containerEl.on('mousemove', '.suggestion-item', this.onSuggestionMouseover.bind(this));
|
||||
|
||||
scope.register([], 'ArrowUp', (event) => {
|
||||
scope.register([], 'ArrowUp', event => {
|
||||
if (!event.isComposing) {
|
||||
this.setSelectedItem(this.selectedItem - 1, true);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
scope.register([], 'ArrowDown', (event) => {
|
||||
scope.register([], 'ArrowDown', event => {
|
||||
if (!event.isComposing) {
|
||||
this.setSelectedItem(this.selectedItem + 1, true);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
scope.register([], 'Enter', (event) => {
|
||||
scope.register([], 'Enter', event => {
|
||||
if (!event.isComposing) {
|
||||
this.useSelectedItem(event);
|
||||
return false;
|
||||
|
|
@ -61,7 +57,7 @@ export class Suggest<T> {
|
|||
this.containerEl.empty();
|
||||
const suggestionEls: HTMLDivElement[] = [];
|
||||
|
||||
values.forEach((value) => {
|
||||
values.forEach(value => {
|
||||
const suggestionEl = this.containerEl.createDiv('suggestion-item');
|
||||
this.owner.renderSuggestion(value, suggestionEl);
|
||||
suggestionEls.push(suggestionEl);
|
||||
|
|
|
|||
|
|
@ -17,16 +17,9 @@ import WikipediaMockResponse from './ResponseMocks/WikipediaMockResponse.json';
|
|||
enableFetchMocks();
|
||||
export let apiMock: OMDbAPI | MALAPI | LocGovAPI | MusicBrainzAPI | SteamAPI | WikipediaAPI;
|
||||
|
||||
describe.each(
|
||||
[
|
||||
{name: OMDbAPI},
|
||||
{name: MALAPI},
|
||||
{name: LocGovAPI},
|
||||
{name: MusicBrainzAPI},
|
||||
{name: SteamAPI},
|
||||
{name: WikipediaAPI},
|
||||
],
|
||||
)('$name.name', ({name: parameterizedApi}) => {
|
||||
describe.each([{ name: OMDbAPI }, { name: MALAPI }, { name: LocGovAPI }, { name: MusicBrainzAPI }, { name: SteamAPI }, { name: WikipediaAPI }])(
|
||||
'$name.name',
|
||||
({ name: parameterizedApi }) => {
|
||||
beforeAll(() => {
|
||||
let settingsMock: MediaDbPluginSettings = {} as MediaDbPluginSettings;
|
||||
let pluginMock = {} as MediaDbPlugin;
|
||||
|
|
@ -107,4 +100,5 @@ describe.each(
|
|||
await expect(apiMock.searchByTitle('Hooking Season Playtest')).resolves.toEqual(ret);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import MediaDbPlugin from '../main';
|
|||
export class TestAPI extends APIModel {
|
||||
plugin: MediaDbPlugin;
|
||||
|
||||
|
||||
constructor(plugin: MediaDbPlugin) {
|
||||
super();
|
||||
|
||||
|
|
@ -16,7 +15,6 @@ export class TestAPI extends APIModel {
|
|||
this.types = [];
|
||||
}
|
||||
|
||||
|
||||
async getById(id: string): Promise<MediaTypeModel> {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,73 +13,83 @@ import WikipediaMockResponse from './ResponseMocks/WikipediaMockResponse.json';
|
|||
export function setWikipediaResponseMock() {
|
||||
let ret = [];
|
||||
let wikiresponse = WikipediaMockResponse.query.search[0];
|
||||
ret.push(new WikiModel({
|
||||
ret.push(
|
||||
new WikiModel({
|
||||
type: 'wiki',
|
||||
title: wikiresponse.title,
|
||||
englishTitle: wikiresponse.title,
|
||||
year: '',
|
||||
dataSource: apiMock.apiName,
|
||||
id: wikiresponse.pageid,
|
||||
}));
|
||||
})
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function setOMDbResponseMock() {
|
||||
let ret = [];
|
||||
let omdbresponse = OMDBMockMovie.Search[0];
|
||||
ret.push(new MovieModel({
|
||||
ret.push(
|
||||
new MovieModel({
|
||||
type: 'wiki',
|
||||
title: omdbresponse.Title,
|
||||
englishTitle: omdbresponse.Title,
|
||||
year: omdbresponse.Year,
|
||||
dataSource: apiMock.apiName,
|
||||
id: omdbresponse.imdbID,
|
||||
}));
|
||||
})
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function setMALResponseMock() {
|
||||
let ret = [];
|
||||
let result = MALMockMovie.data[0];
|
||||
ret.push(new MovieModel({
|
||||
ret.push(
|
||||
new MovieModel({
|
||||
type: result.type,
|
||||
title: result.title,
|
||||
englishTitle: result.title_english,
|
||||
year: result.aired.prop.from.year,
|
||||
dataSource: apiMock.apiName,
|
||||
id: result.mal_id,
|
||||
}));
|
||||
})
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function setSteamResponseMock() {
|
||||
let ret = [];
|
||||
let steamResponse = SteamAPIResponseMock.applist.apps[0];
|
||||
ret.push(new GameModel({
|
||||
ret.push(
|
||||
new GameModel({
|
||||
type: MediaType.Game,
|
||||
title: steamResponse.name,
|
||||
englishTitle: steamResponse.name,
|
||||
year: '',
|
||||
dataSource: apiMock.apiName,
|
||||
id: steamResponse.appid,
|
||||
}));
|
||||
})
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function setMusicBrainzResponseMock() {
|
||||
let ret = [];
|
||||
let result = MusicBrainzResponseMock['release-groups'][0];
|
||||
ret.push(new MusicReleaseModel({
|
||||
ret.push(
|
||||
new MusicReleaseModel({
|
||||
type: 'musicRelease',
|
||||
title: result.title,
|
||||
englishTitle: result.title,
|
||||
year: (new Date(result['first-release-date'])).getFullYear().toString(),
|
||||
year: new Date(result['first-release-date']).getFullYear().toString(),
|
||||
dataSource: apiMock.apiName,
|
||||
url: '',
|
||||
id: result.id,
|
||||
|
||||
artists: result['artist-credit'].map((a: any) => a.name),
|
||||
subType: result['primary-type'],
|
||||
} as MusicReleaseModel));
|
||||
} as MusicReleaseModel)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
1185
src/utils/IconList.ts
Normal file
1185
src/utils/IconList.ts
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -16,8 +16,7 @@ export class MediaTypeManager {
|
|||
mediaFileNameTemplateMap: Map<MediaType, string>;
|
||||
mediaTemplateMap: Map<MediaType, string>;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
constructor() {}
|
||||
|
||||
updateTemplates(settings: MediaDbPluginSettings) {
|
||||
this.mediaFileNameTemplateMap = new Map<MediaType, string>();
|
||||
|
|
@ -48,7 +47,10 @@ export class MediaTypeManager {
|
|||
return '';
|
||||
}
|
||||
|
||||
const templateFile: TFile = app.vault.getFiles().filter((f: TFile) => f.name === templateFileName).first();
|
||||
const templateFile: TFile = app.vault
|
||||
.getFiles()
|
||||
.filter((f: TFile) => f.name === templateFileName)
|
||||
.first();
|
||||
|
||||
if (!templateFile) {
|
||||
return '';
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {MediaDbPreviewModal} from 'src/modals/MediaDbPreviewModal';
|
|||
import { CreateNoteOptions } from './Utils';
|
||||
import { MediaDbSearchModal } from '../modals/MediaDbSearchModal';
|
||||
|
||||
|
||||
export enum ModalResultCode {
|
||||
SUCCESS,
|
||||
SKIP,
|
||||
|
|
@ -22,9 +21,9 @@ export enum ModalResultCode {
|
|||
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
|
||||
*/
|
||||
export interface SearchModalResult {
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR,
|
||||
data?: SearchModalData,
|
||||
error?: Error,
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
|
||||
data?: SearchModalData;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -33,9 +32,9 @@ export interface SearchModalResult {
|
|||
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
|
||||
*/
|
||||
export interface AdvancedSearchModalResult {
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR,
|
||||
data?: AdvancedSearchModalData,
|
||||
error?: Error,
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
|
||||
data?: AdvancedSearchModalData;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -44,9 +43,9 @@ export interface AdvancedSearchModalResult {
|
|||
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
|
||||
*/
|
||||
export interface IdSearchModalResult {
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR,
|
||||
data?: IdSearchModalData,
|
||||
error?: Error,
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
|
||||
data?: IdSearchModalData;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -55,9 +54,9 @@ export interface IdSearchModalResult {
|
|||
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
|
||||
*/
|
||||
export interface SelectModalResult {
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.SKIP | ModalResultCode.ERROR,
|
||||
data?: SelectModalData,
|
||||
error?: Error,
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.SKIP | ModalResultCode.ERROR;
|
||||
data?: SelectModalData;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,9 +65,9 @@ export interface SelectModalResult {
|
|||
* On {@link ModalResultCode.ERROR} this contains a reference to that error.
|
||||
*/
|
||||
export interface PreviewModalResult {
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR,
|
||||
data?: PreviewModalData,
|
||||
error?: Error,
|
||||
code: ModalResultCode.SUCCESS | ModalResultCode.CLOSE | ModalResultCode.ERROR;
|
||||
data?: PreviewModalData;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -77,8 +76,8 @@ export interface PreviewModalResult {
|
|||
* - types: the selected APIs
|
||||
*/
|
||||
export interface SearchModalData {
|
||||
query: string,
|
||||
types: string[],
|
||||
query: string;
|
||||
types: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,8 +86,8 @@ export interface SearchModalData {
|
|||
* - apis: the selected APIs
|
||||
*/
|
||||
export interface AdvancedSearchModalData {
|
||||
query: string,
|
||||
apis: string[],
|
||||
query: string;
|
||||
apis: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -97,8 +96,8 @@ export interface AdvancedSearchModalData {
|
|||
* - apis: the selected APIs
|
||||
*/
|
||||
export interface IdSearchModalData {
|
||||
query: string,
|
||||
api: string,
|
||||
query: string;
|
||||
api: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -106,7 +105,7 @@ export interface IdSearchModalData {
|
|||
* - selected: the selected items
|
||||
*/
|
||||
export interface SelectModalData {
|
||||
selected: MediaTypeModel[],
|
||||
selected: MediaTypeModel[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -114,7 +113,7 @@ export interface SelectModalData {
|
|||
* - confirmed: whether the selected element has been confirmed
|
||||
*/
|
||||
export interface PreviewModalData {
|
||||
confirmed: boolean,
|
||||
confirmed: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,9 +123,9 @@ export interface PreviewModalData {
|
|||
* - prefilledSearchString: prefilled query
|
||||
*/
|
||||
export interface SearchModalOptions {
|
||||
modalTitle?: string,
|
||||
preselectedTypes?: string[],
|
||||
prefilledSearchString?: string,
|
||||
modalTitle?: string;
|
||||
preselectedTypes?: string[];
|
||||
prefilledSearchString?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,9 +135,9 @@ export interface SearchModalOptions {
|
|||
* - prefilledSearchString: prefilled query
|
||||
*/
|
||||
export interface AdvancedSearchModalOptions {
|
||||
modalTitle?: string,
|
||||
preselectedAPIs?: string[],
|
||||
prefilledSearchString?: string,
|
||||
modalTitle?: string;
|
||||
preselectedAPIs?: string[];
|
||||
prefilledSearchString?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -148,9 +147,9 @@ export interface AdvancedSearchModalOptions {
|
|||
* - prefilledSearchString: prefilled query
|
||||
*/
|
||||
export interface IdSearchModalOptions {
|
||||
modalTitle?: string,
|
||||
preselectedAPI?: string,
|
||||
prefilledSearchString?: string,
|
||||
modalTitle?: string;
|
||||
preselectedAPI?: string;
|
||||
prefilledSearchString?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,10 +160,10 @@ export interface IdSearchModalOptions {
|
|||
* - skipButton: whether to add a skip button to the modal
|
||||
*/
|
||||
export interface SelectModalOptions {
|
||||
modalTitle?: string,
|
||||
elements?: MediaTypeModel[],
|
||||
multiSelect?: boolean,
|
||||
skipButton?: boolean,
|
||||
modalTitle?: string;
|
||||
elements?: MediaTypeModel[];
|
||||
multiSelect?: boolean;
|
||||
skipButton?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -173,9 +172,9 @@ export interface SelectModalOptions {
|
|||
* - elements: the elements to preview
|
||||
*/
|
||||
export interface PreviewModalOptions {
|
||||
modalTitle?: string,
|
||||
elements?: MediaTypeModel[],
|
||||
createNoteOptions?: CreateNoteOptions,
|
||||
modalTitle?: string;
|
||||
elements?: MediaTypeModel[];
|
||||
createNoteOptions?: CreateNoteOptions;
|
||||
}
|
||||
|
||||
export const SEARCH_MODAL_DEFAULT_OPTIONS: SearchModalOptions = {
|
||||
|
|
@ -215,7 +214,6 @@ export const PREVIEW_MODAL_DEFAULT_OPTIONS: PreviewModalOptions = {
|
|||
export class ModalHelper {
|
||||
plugin: MediaDbPlugin;
|
||||
|
||||
|
||||
constructor(plugin: MediaDbPlugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
|
@ -228,7 +226,7 @@ export class ModalHelper {
|
|||
* @param searchModalOptions the options for the modal, see {@link SEARCH_MODAL_DEFAULT_OPTIONS}
|
||||
* @returns the user input or nothing and a reference to the modal.
|
||||
*/
|
||||
async createSearchModal(searchModalOptions: SearchModalOptions): Promise<{ searchModalResult: SearchModalResult, searchModal: MediaDbSearchModal }> {
|
||||
async createSearchModal(searchModalOptions: SearchModalOptions): Promise<{ searchModalResult: SearchModalResult; searchModal: MediaDbSearchModal }> {
|
||||
const modal = new MediaDbSearchModal(this.plugin, searchModalOptions);
|
||||
const res: SearchModalResult = await new Promise((resolve, reject) => {
|
||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||
|
|
@ -254,7 +252,7 @@ export class ModalHelper {
|
|||
*/
|
||||
async openSearchModal(searchModalOptions: SearchModalOptions, submitCallback: (searchModalData: SearchModalData) => Promise<MediaTypeModel[]>): Promise<MediaTypeModel[]> {
|
||||
const { searchModalResult, searchModal } = await this.createSearchModal(searchModalOptions);
|
||||
console.debug(`MDB | searchModal closed with code ${searchModalResult.code}`)
|
||||
console.debug(`MDB | searchModal closed with code ${searchModalResult.code}`);
|
||||
|
||||
if (searchModalResult.code === ModalResultCode.ERROR) {
|
||||
// there was an error in the modal itself
|
||||
|
|
@ -290,7 +288,9 @@ export class ModalHelper {
|
|||
* @param advancedSearchModalOptions the options for the modal, see {@link ADVANCED_SEARCH_MODAL_DEFAULT_OPTIONS}
|
||||
* @returns the user input or nothing and a reference to the modal.
|
||||
*/
|
||||
async createAdvancedSearchModal(advancedSearchModalOptions: AdvancedSearchModalOptions): Promise<{ advancedSearchModalResult: AdvancedSearchModalResult, advancedSearchModal: MediaDbAdvancedSearchModal }> {
|
||||
async createAdvancedSearchModal(
|
||||
advancedSearchModalOptions: AdvancedSearchModalOptions
|
||||
): Promise<{ advancedSearchModalResult: AdvancedSearchModalResult; advancedSearchModal: MediaDbAdvancedSearchModal }> {
|
||||
const modal = new MediaDbAdvancedSearchModal(this.plugin, advancedSearchModalOptions);
|
||||
const res: AdvancedSearchModalResult = await new Promise((resolve, reject) => {
|
||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||
|
|
@ -314,9 +314,12 @@ export class ModalHelper {
|
|||
* @param submitCallback the callback that gets executed after the modal has been submitted, but after it has been closed
|
||||
* @returns the user input or nothing and a reference to the modal.
|
||||
*/
|
||||
async openAdvancedSearchModal(advancedSearchModalOptions: AdvancedSearchModalOptions, submitCallback: (advancedSearchModalData: AdvancedSearchModalData) => Promise<MediaTypeModel[]>): Promise<MediaTypeModel[]> {
|
||||
async openAdvancedSearchModal(
|
||||
advancedSearchModalOptions: AdvancedSearchModalOptions,
|
||||
submitCallback: (advancedSearchModalData: AdvancedSearchModalData) => Promise<MediaTypeModel[]>
|
||||
): Promise<MediaTypeModel[]> {
|
||||
const { advancedSearchModalResult, advancedSearchModal } = await this.createAdvancedSearchModal(advancedSearchModalOptions);
|
||||
console.debug(`MDB | advencedSearchModal closed with code ${advancedSearchModalResult.code}`)
|
||||
console.debug(`MDB | advencedSearchModal closed with code ${advancedSearchModalResult.code}`);
|
||||
|
||||
if (advancedSearchModalResult.code === ModalResultCode.ERROR) {
|
||||
// there was an error in the modal itself
|
||||
|
|
@ -352,7 +355,7 @@ export class ModalHelper {
|
|||
* @param idSearchModalOptions the options for the modal, see {@link ID_SEARCH_MODAL_DEFAULT_OPTIONS}
|
||||
* @returns the user input or nothing and a reference to the modal.
|
||||
*/
|
||||
async createIdSearchModal(idSearchModalOptions: IdSearchModalOptions): Promise<{ idSearchModalResult: IdSearchModalResult, idSearchModal: MediaDbIdSearchModal }> {
|
||||
async createIdSearchModal(idSearchModalOptions: IdSearchModalOptions): Promise<{ idSearchModalResult: IdSearchModalResult; idSearchModal: MediaDbIdSearchModal }> {
|
||||
const modal = new MediaDbIdSearchModal(this.plugin, idSearchModalOptions);
|
||||
const res: IdSearchModalResult = await new Promise((resolve, reject) => {
|
||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||
|
|
@ -376,9 +379,12 @@ export class ModalHelper {
|
|||
* @param submitCallback the callback that gets executed after the modal has been submitted, but after it has been closed
|
||||
* @returns the user input or nothing and a reference to the modal.
|
||||
*/
|
||||
async openIdSearchModal(idSearchModalOptions: IdSearchModalOptions, submitCallback: (idSearchModalData: IdSearchModalData) => Promise<MediaTypeModel>): Promise<MediaTypeModel> {
|
||||
async openIdSearchModal(
|
||||
idSearchModalOptions: IdSearchModalOptions,
|
||||
submitCallback: (idSearchModalData: IdSearchModalData) => Promise<MediaTypeModel>
|
||||
): Promise<MediaTypeModel> {
|
||||
const { idSearchModalResult, idSearchModal } = await this.createIdSearchModal(idSearchModalOptions);
|
||||
console.debug(`MDB | idSearchModal closed with code ${idSearchModalResult.code}`)
|
||||
console.debug(`MDB | idSearchModal closed with code ${idSearchModalResult.code}`);
|
||||
|
||||
if (idSearchModalResult.code === ModalResultCode.ERROR) {
|
||||
// there was an error in the modal itself
|
||||
|
|
@ -414,7 +420,7 @@ export class ModalHelper {
|
|||
* @param selectModalOptions the options for the modal, see {@link SELECT_MODAL_OPTIONS_DEFAULT}
|
||||
* @returns the user input or nothing and a reference to the modal.
|
||||
*/
|
||||
async createSelectModal(selectModalOptions: SelectModalOptions): Promise<{ selectModalResult: SelectModalResult, selectModal: MediaDbSearchResultModal }> {
|
||||
async createSelectModal(selectModalOptions: SelectModalOptions): Promise<{ selectModalResult: SelectModalResult; selectModal: MediaDbSearchResultModal }> {
|
||||
const modal = new MediaDbSearchResultModal(this.plugin, selectModalOptions);
|
||||
const res: SelectModalResult = await new Promise((resolve, reject) => {
|
||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||
|
|
@ -441,7 +447,7 @@ export class ModalHelper {
|
|||
*/
|
||||
async openSelectModal(selectModalOptions: SelectModalOptions, submitCallback: (selectModalData: SelectModalData) => Promise<MediaTypeModel[]>): Promise<MediaTypeModel[]> {
|
||||
const { selectModalResult, selectModal } = await this.createSelectModal(selectModalOptions);
|
||||
console.debug(`MDB | selectModal closed with code ${selectModalResult.code}`)
|
||||
console.debug(`MDB | selectModal closed with code ${selectModalResult.code}`);
|
||||
|
||||
if (selectModalResult.code === ModalResultCode.ERROR) {
|
||||
// there was an error in the modal itself
|
||||
|
|
@ -474,7 +480,7 @@ export class ModalHelper {
|
|||
}
|
||||
}
|
||||
|
||||
async createPreviewModal(previewModalOptions: PreviewModalOptions): Promise<{ previewModalResult: PreviewModalResult, previewModal: MediaDbPreviewModal }> {
|
||||
async createPreviewModal(previewModalOptions: PreviewModalOptions): Promise<{ previewModalResult: PreviewModalResult; previewModal: MediaDbPreviewModal }> {
|
||||
//todo: handle attachFile for existing files
|
||||
const modal = new MediaDbPreviewModal(this.plugin, previewModalOptions);
|
||||
const res: PreviewModalResult = await new Promise((resolve, reject) => {
|
||||
|
|
@ -493,7 +499,7 @@ export class ModalHelper {
|
|||
|
||||
async openPreviewModal(previewModalOptions: PreviewModalOptions, submitCallback: (previewModalData: PreviewModalData) => Promise<boolean>): Promise<boolean> {
|
||||
const { previewModalResult, previewModal } = await this.createPreviewModal(previewModalOptions);
|
||||
console.debug(`MDB | previewModal closed with code ${previewModalResult.code}`)
|
||||
console.debug(`MDB | previewModal closed with code ${previewModalResult.code}`);
|
||||
|
||||
if (previewModalResult.code === ModalResultCode.ERROR) {
|
||||
// there was an error in the modal itself
|
||||
|
|
@ -521,4 +527,3 @@ export class ModalHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -6,14 +6,12 @@
|
|||
}
|
||||
|
||||
.media-db-plugin-list-toggle {
|
||||
|
||||
}
|
||||
|
||||
.media-db-plugin-list-text-wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
.media-db-plugin-list-text {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"svelte",
|
||||
"node",
|
||||
"jest"
|
||||
],
|
||||
"types": ["svelte", "node", "jest"],
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
|
|
@ -17,14 +13,7 @@
|
|||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
]
|
||||
"lib": ["DOM", "ES5", "ES6", "ES7"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
||||
// read minAppVersion from manifest.json and bump version to target version
|
||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
let manifest = JSON.parse(readFileSync('manifest.json', 'utf8'));
|
||||
const { minAppVersion } = manifest;
|
||||
manifest.version = targetVersion;
|
||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||
writeFileSync('manifest.json', JSON.stringify(manifest, null, '\t'));
|
||||
|
||||
// update versions.json with target version and minAppVersion from manifest.json
|
||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
||||
let versions = JSON.parse(readFileSync('versions.json', 'utf8'));
|
||||
versions[targetVersion] = minAppVersion;
|
||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
||||
writeFileSync('versions.json', JSON.stringify(versions, null, '\t'));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue