update settings; fix some minor issues
This commit is contained in:
parent
abbf10cf3d
commit
97cf350a32
24 changed files with 882 additions and 950 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -36,4 +36,5 @@ exampleVault/.obsidian/plugins/obsidian-media-db-plugin/*
|
||||||
!exampleVault/.obsidian/plugins/obsidian-media-db-plugin/.hotreload
|
!exampleVault/.obsidian/plugins/obsidian-media-db-plugin/.hotreload
|
||||||
|
|
||||||
exampleVault/Media DB/*
|
exampleVault/Media DB/*
|
||||||
meta.txt
|
meta.txt
|
||||||
|
main.js
|
||||||
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
24
package.json
24
package.json
|
|
@ -26,26 +26,26 @@
|
||||||
"@happy-dom/global-registrator": "^18.0.1",
|
"@happy-dom/global-registrator": "^18.0.1",
|
||||||
"@lemons_dev/parsinom": "^0.0.12",
|
"@lemons_dev/parsinom": "^0.0.12",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@types/bun": "^1.2.19",
|
"@types/bun": "^1.3.7",
|
||||||
"builtin-modules": "^5.0.0",
|
"builtin-modules": "^5.0.0",
|
||||||
"esbuild": "^0.25.8",
|
"esbuild": "^0.25.12",
|
||||||
"esbuild-plugin-copy-watch": "^2.3.1",
|
"esbuild-plugin-copy-watch": "^2.3.1",
|
||||||
"esbuild-svelte": "^0.9.3",
|
"esbuild-svelte": "^0.9.4",
|
||||||
"eslint": "^9.32.0",
|
"eslint": "^9.39.2",
|
||||||
"eslint-plugin-import": "^2.32.0",
|
"eslint-plugin-import": "^2.32.0",
|
||||||
"eslint-plugin-only-warn": "^1.1.0",
|
"eslint-plugin-only-warn": "^1.1.0",
|
||||||
"iso-639-2": "^3.0.2",
|
"iso-639-2": "^3.0.2",
|
||||||
"obsidian": "latest",
|
"obsidian": "latest",
|
||||||
"openapi-fetch": "^0.14.0",
|
"openapi-fetch": "^0.14.1",
|
||||||
"openapi-typescript": "^7.8.0",
|
"openapi-typescript": "^7.10.1",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.8.1",
|
||||||
"prettier-plugin-svelte": "^3.4.0",
|
"prettier-plugin-svelte": "^3.4.1",
|
||||||
"string-argv": "^0.3.2",
|
"string-argv": "^0.3.2",
|
||||||
"svelte": "^5.38.0",
|
"svelte": "^5.48.5",
|
||||||
"svelte-check": "^4.3.1",
|
"svelte-check": "^4.3.5",
|
||||||
"svelte-preprocess": "^6.0.3",
|
"svelte-preprocess": "^6.0.3",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.39.0"
|
"typescript-eslint": "^8.54.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */
|
||||||
|
|
||||||
import createClient from 'openapi-fetch';
|
import createClient from 'openapi-fetch';
|
||||||
import type MediaDbPlugin from '../../main';
|
import type MediaDbPlugin from '../../main';
|
||||||
import type { MediaTypeModel } from '../../models/MediaTypeModel';
|
import type { MediaTypeModel } from '../../models/MediaTypeModel';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */
|
||||||
|
|
||||||
import createClient from 'openapi-fetch';
|
import createClient from 'openapi-fetch';
|
||||||
import type MediaDbPlugin from '../../main';
|
import type MediaDbPlugin from '../../main';
|
||||||
import type { MediaTypeModel } from '../../models/MediaTypeModel';
|
import type { MediaTypeModel } from '../../models/MediaTypeModel';
|
||||||
|
import { SeasonModel } from '../../models/SeasonModel';
|
||||||
import { MediaType } from '../../utils/MediaType';
|
import { MediaType } from '../../utils/MediaType';
|
||||||
import { APIModel } from '../APIModel';
|
import { APIModel } from '../APIModel';
|
||||||
import { SeasonModel } from '../../models/SeasonModel';
|
|
||||||
import type { paths } from '../schemas/TMDB';
|
import type { paths } from '../schemas/TMDB';
|
||||||
|
|
||||||
export class TMDBSeasonAPI extends APIModel {
|
export class TMDBSeasonAPI extends APIModel {
|
||||||
|
|
@ -82,7 +84,9 @@ export class TMDBSeasonAPI extends APIModel {
|
||||||
totalSeasons = detailsData.seasons.length;
|
totalSeasons = detailsData.seasons.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {
|
||||||
|
// Ignore errors and assume 0 seasons
|
||||||
|
}
|
||||||
|
|
||||||
ret.push(
|
ret.push(
|
||||||
new SeasonModel({
|
new SeasonModel({
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */
|
||||||
|
|
||||||
import createClient from 'openapi-fetch';
|
import createClient from 'openapi-fetch';
|
||||||
import type MediaDbPlugin from '../../main';
|
import type MediaDbPlugin from '../../main';
|
||||||
import type { MediaTypeModel } from '../../models/MediaTypeModel';
|
import type { MediaTypeModel } from '../../models/MediaTypeModel';
|
||||||
|
|
|
||||||
|
|
@ -257,4 +257,8 @@ export class VNDBAPI extends APIModel {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDisabledMediaTypes(): MediaType[] {
|
||||||
|
return this.plugin.settings.VNDBAPI_disabledMediaTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
src/main.ts
19
src/main.ts
|
|
@ -13,15 +13,14 @@ import { MusicBrainzAPI } from './api/apis/MusicBrainzAPI';
|
||||||
import { OMDbAPI } from './api/apis/OMDbAPI';
|
import { OMDbAPI } from './api/apis/OMDbAPI';
|
||||||
import { OpenLibraryAPI } from './api/apis/OpenLibraryAPI';
|
import { OpenLibraryAPI } from './api/apis/OpenLibraryAPI';
|
||||||
import { SteamAPI } from './api/apis/SteamAPI';
|
import { SteamAPI } from './api/apis/SteamAPI';
|
||||||
import { TMDBSeriesAPI } from './api/apis/TMDBSeriesAPI';
|
|
||||||
import { TMDBSeasonAPI } from './api/apis/TMDBSeasonAPI';
|
|
||||||
import { TMDBMovieAPI } from './api/apis/TMDBMovieAPI';
|
import { TMDBMovieAPI } from './api/apis/TMDBMovieAPI';
|
||||||
import { WikipediaAPI } from './api/apis/WikipediaAPI';
|
import { TMDBSeasonAPI } from './api/apis/TMDBSeasonAPI';
|
||||||
import { ComicVineAPI } from './api/apis/ComicVineAPI';
|
import { TMDBSeriesAPI } from './api/apis/TMDBSeriesAPI';
|
||||||
import { VNDBAPI } from './api/apis/VNDBAPI';
|
import { VNDBAPI } from './api/apis/VNDBAPI';
|
||||||
import { MediaDbFolderImportModal } from './modals/MediaDbFolderImportModal';
|
import { WikipediaAPI } from './api/apis/WikipediaAPI';
|
||||||
import { ConfirmOverwriteModal } from './modals/ConfirmOverwriteModal';
|
import { ConfirmOverwriteModal } from './modals/ConfirmOverwriteModal';
|
||||||
import { MediaDbSeasonSelectModal } from './modals/MediaDbSeasonSelectModal';
|
import type {SeasonSelectModalElement} from './modals/MediaDbSeasonSelectModal';
|
||||||
|
import { MediaDbSeasonSelectModal } from './modals/MediaDbSeasonSelectModal';
|
||||||
import type { MediaTypeModel } from './models/MediaTypeModel';
|
import type { MediaTypeModel } from './models/MediaTypeModel';
|
||||||
import { PropertyMapper } from './settings/PropertyMapper';
|
import { PropertyMapper } from './settings/PropertyMapper';
|
||||||
import { PropertyMapping, PropertyMappingModel } from './settings/PropertyMapping';
|
import { PropertyMapping, PropertyMappingModel } from './settings/PropertyMapping';
|
||||||
|
|
@ -271,7 +270,7 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
private async handleSeasonSelectModal(types: string[], selectResults: MediaTypeModel[]): Promise<boolean> {
|
private async handleSeasonSelectModal(types: string[], selectResults: MediaTypeModel[]): Promise<boolean> {
|
||||||
if (types.length === 1 && types[0] === 'season' && selectResults.length === 1 && selectResults[0].dataSource === 'TMDBSeasonAPI') {
|
if (types.length === 1 && types[0] === 'season' && selectResults.length === 1 && selectResults[0].dataSource === 'TMDBSeasonAPI') {
|
||||||
// Use static import for the modal
|
// Use static import for the modal
|
||||||
const tmdbSeasonAPI = this.apiManager.getApiByName('TMDBSeasonAPI') as import('./api/apis/TMDBSeasonAPI').TMDBSeasonAPI;
|
const tmdbSeasonAPI = this.apiManager.getApiByName('TMDBSeasonAPI') as TMDBSeasonAPI;
|
||||||
if (!tmdbSeasonAPI) {
|
if (!tmdbSeasonAPI) {
|
||||||
new Notice('TMDBSeasonAPI not found.');
|
new Notice('TMDBSeasonAPI not found.');
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -296,8 +295,8 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
true,
|
true,
|
||||||
seriesName,
|
seriesName,
|
||||||
);
|
);
|
||||||
const selectedSeasons: any[] = await new Promise(resolve => {
|
const selectedSeasons: SeasonSelectModalElement[] = await new Promise(resolve => {
|
||||||
modal.setSubmitCallback(resolve);
|
modal.setSubmitCb(resolve);
|
||||||
modal.open();
|
modal.open();
|
||||||
});
|
});
|
||||||
if (!selectedSeasons || selectedSeasons.length === 0) {
|
if (!selectedSeasons || selectedSeasons.length === 0) {
|
||||||
|
|
@ -309,7 +308,7 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
const orig = allSeasons.find(s => s.seasonNumber === season.season_number);
|
const orig = allSeasons.find(s => s.seasonNumber === season.season_number);
|
||||||
if (orig) {
|
if (orig) {
|
||||||
// Fetch full metadata using getById
|
// Fetch full metadata using getById
|
||||||
const tmdbSeasonAPI = this.apiManager.getApiByName('TMDBSeasonAPI') as import('./api/apis/TMDBSeasonAPI').TMDBSeasonAPI;
|
const tmdbSeasonAPI = this.apiManager.getApiByName('TMDBSeasonAPI') as TMDBSeasonAPI;
|
||||||
if (tmdbSeasonAPI) {
|
if (tmdbSeasonAPI) {
|
||||||
const fullMeta = await tmdbSeasonAPI.getById(orig.id);
|
const fullMeta = await tmdbSeasonAPI.getById(orig.id);
|
||||||
await this.createMediaDbNotes([fullMeta]);
|
await this.createMediaDbNotes([fullMeta]);
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,11 @@ export class MediaDbAdvancedSearchModal extends Modal {
|
||||||
this.isBusy = false;
|
this.isBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitCallback(submitCallback: (res: AdvancedSearchModalData) => void): void {
|
setSubmitCb(submitCallback: (res: AdvancedSearchModalData) => void): void {
|
||||||
this.submitCallback = submitCallback;
|
this.submitCallback = submitCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCloseCallback(closeCallback: (err?: Error) => void): void {
|
setCloseCb(closeCallback: (err?: Error) => void): void {
|
||||||
this.closeCallback = closeCallback;
|
this.closeCallback = closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,11 @@ export class MediaDbIdSearchModal extends Modal {
|
||||||
this.isBusy = false;
|
this.isBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitCallback(submitCallback: (res: IdSearchModalData, err?: Error) => void): void {
|
setSubmitCb(submitCallback: (res: IdSearchModalData, err?: Error) => void): void {
|
||||||
this.submitCallback = submitCallback;
|
this.submitCallback = submitCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCloseCallback(closeCallback: (err?: Error) => void): void {
|
setCloseCb(closeCallback: (err?: Error) => void): void {
|
||||||
this.closeCallback = closeCallback;
|
this.closeCallback = closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@ export class MediaDbPreviewModal extends Modal {
|
||||||
this.markdownComponent = new Component();
|
this.markdownComponent = new Component();
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitCallback(submitCallback: (previewModalData: PreviewModalData) => void): void {
|
setSubmitCb(submitCallback: (previewModalData: PreviewModalData) => void): void {
|
||||||
this.submitCallback = submitCallback;
|
this.submitCallback = submitCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCloseCallback(closeCallback: (err?: Error) => void): void {
|
setCloseCb(closeCallback: (err?: Error) => void): void {
|
||||||
this.closeCallback = closeCallback;
|
this.closeCallback = closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ export class MediaDbSearchModal extends Modal {
|
||||||
this.isBusy = false;
|
this.isBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitCallback(submitCallback: (res: SearchModalData) => void): void {
|
setSubmitCb(submitCallback: (res: SearchModalData) => void): void {
|
||||||
this.submitCallback = submitCallback;
|
this.submitCallback = submitCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCloseCallback(closeCallback: (err?: Error) => void): void {
|
setCloseCb(closeCallback: (err?: Error) => void): void {
|
||||||
this.closeCallback = closeCallback;
|
this.closeCallback = closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,11 @@ export class MediaDbSearchResultModal extends SelectModal<MediaTypeModel> {
|
||||||
this.sendCallback = false;
|
this.sendCallback = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitCallback(submitCallback: (res: SelectModalData) => void): void {
|
setSubmitCb(submitCallback: (res: SelectModalData) => void): void {
|
||||||
this.submitCallback = submitCallback;
|
this.submitCallback = submitCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCloseCallback(closeCallback: (err?: Error) => void): void {
|
setCloseCb(closeCallback: (err?: Error) => void): void {
|
||||||
this.closeCallback = closeCallback;
|
this.closeCallback = closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,11 @@ export class MediaDbSeasonSelectModal extends SelectModal<SeasonSelectModalEleme
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitCallback(cb: (selectedSeasons: SeasonSelectModalElement[]) => void): void {
|
setSubmitCb(cb: (selectedSeasons: SeasonSelectModalElement[]) => void): void {
|
||||||
this.submitCallback = cb;
|
this.submitCallback = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCloseCallback(cb: (err?: Error) => void): void {
|
setCloseCb(cb: (err?: Error) => void): void {
|
||||||
this.closeCallback = cb;
|
this.closeCallback = cb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export class SeasonModel extends MediaTypeModel {
|
||||||
|
|
||||||
migrateObject(this, obj, this);
|
migrateObject(this, obj, this);
|
||||||
|
|
||||||
if (!obj.hasOwnProperty('userData')) {
|
if (!Object.hasOwn(obj, 'userData')) {
|
||||||
migrateObject(this.userData, obj, this.userData);
|
migrateObject(this.userData, obj, this.userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,14 +124,16 @@ export class PropertyMapping {
|
||||||
if (!this.property || !containsOnlyLettersAndUnderscores(this.property)) {
|
if (!this.property || !containsOnlyLettersAndUnderscores(this.property)) {
|
||||||
return {
|
return {
|
||||||
res: false,
|
res: false,
|
||||||
err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": property may not be empty and only contain letters and underscores.`),
|
err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": property may not be empty and may only contain letters and underscores.`),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.newProperty || !containsOnlyLettersAndUnderscores(this.newProperty)) {
|
if (!this.newProperty || !containsOnlyLettersAndUnderscores(this.newProperty)) {
|
||||||
return {
|
return {
|
||||||
res: false,
|
res: false,
|
||||||
err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": new property may not be empty and only contain letters and underscores.`),
|
err: new PropertyMappingValidationError(
|
||||||
|
`Error in property mapping "${this.toString()}": new property may not be empty and may only contain letters and underscores.`,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { PropertyMappingModel, PropertyMappingOption, propertyMappingOptions } from './PropertyMapping';
|
import { PropertyMappingModel, PropertyMappingOption, propertyMappingOptions } from './PropertyMapping';
|
||||||
import { capitalizeFirstLetter } from '../utils/Utils';
|
import { capitalizeFirstLetter } from '../utils/Utils';
|
||||||
import Icon from './Icon.svelte';
|
import Icon from './Icon.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
model: PropertyMappingModel;
|
model: PropertyMappingModel;
|
||||||
save: (model: PropertyMappingModel) => void;
|
save: (model: PropertyMappingModel) => void;
|
||||||
|
|
@ -10,70 +10,39 @@
|
||||||
|
|
||||||
let { model, save }: Props = $props();
|
let { model, save }: Props = $props();
|
||||||
|
|
||||||
|
let unsavedChanges = $state(false);
|
||||||
|
// svelte-ignore state_referenced_locally
|
||||||
|
|
||||||
let validationResult: { res: boolean; err?: Error } | undefined = $derived(model.validate());
|
let validationResult: { res: boolean; err?: Error } | undefined = $derived(model.validate());
|
||||||
|
|
||||||
|
function onModelUpdate() {
|
||||||
|
unsavedChanges = true;
|
||||||
|
model = model.copy();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="media-db-plugin-property-mappings-model-container">
|
<div class="media-db-plugin-property-mappings-model-container">
|
||||||
<div class="setting-item-name">{capitalizeFirstLetter(model.type)}</div>
|
<div class="media-db-plugin-property-mappings-model-header">
|
||||||
|
<div class="setting-item-name">{capitalizeFirstLetter(model.type)}</div>
|
||||||
|
|
||||||
<table class="media-db-plugin-property-mappings-table">
|
<div class="media-db-plugin-property-mappings-model-actions">
|
||||||
<thead>
|
{#if unsavedChanges}
|
||||||
<tr>
|
<div class="media-db-plugin-property-mapping-unsaved-changes">Unsaved changes</div>
|
||||||
<th class="col-property">Property</th>
|
{/if}
|
||||||
<th class="col-mapping">Mapping</th>
|
|
||||||
<th class="col-new-name">New name</th>
|
|
||||||
<th class="col-wikilink">Wikilink</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{#each model.properties as property}
|
|
||||||
<tr>
|
|
||||||
<td class="col-property">
|
|
||||||
<code>{property.property}</code>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{#if property.locked}
|
<button
|
||||||
<td class="col-locked" colspan="3">
|
class="media-db-plugin-property-mappings-save-button {validationResult?.res ? 'mod-cta' : 'mod-muted'}"
|
||||||
<div class="media-db-plugin-property-binding-text">property cannot be remapped</div>
|
onclick={() => {
|
||||||
</td>
|
if (model.validate().res) {
|
||||||
{:else}
|
save(model);
|
||||||
<td class="col-mapping">
|
unsavedChanges = false;
|
||||||
<select
|
}
|
||||||
class="dropdown"
|
}}
|
||||||
bind:value={property.mapping}
|
>
|
||||||
onchange={() => {
|
Save
|
||||||
model = model.copy();
|
</button>
|
||||||
}}
|
</div>
|
||||||
>
|
</div>
|
||||||
{#each propertyMappingOptions as remappingOption}
|
|
||||||
<option value={remappingOption}>
|
|
||||||
{remappingOption}
|
|
||||||
</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="col-new-name">
|
|
||||||
{#if property.mapping === PropertyMappingOption.Map}
|
|
||||||
<div class="media-db-plugin-property-mapping-to">
|
|
||||||
<Icon iconName="arrow-right" />
|
|
||||||
<input class="media-db-plugin-property-mapping-input" type="text" spellcheck="false" bind:value={property.newProperty} />
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<span class="media-db-plugin-property-mapping-to-disabled">—</span>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="col-wikilink">
|
|
||||||
<label class="media-db-plugin-property-mapping-wikilink-label" title="Convert value to wikilink ([[value]])">
|
|
||||||
<input type="checkbox" bind:checked={property.wikilink} />
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{#if !validationResult?.res}
|
{#if !validationResult?.res}
|
||||||
<div class="media-db-plugin-property-mapping-validation">
|
<div class="media-db-plugin-property-mapping-validation">
|
||||||
|
|
@ -81,33 +50,169 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<div class="media-db-plugin-property-mappings-table-container">
|
||||||
class="media-db-plugin-property-mappings-save-button {validationResult?.res ? 'mod-cta' : 'mod-muted'}"
|
<table class="media-db-plugin-property-mappings-table">
|
||||||
onclick={() => {
|
<thead>
|
||||||
if (model.validate().res) save(model);
|
<tr>
|
||||||
}}
|
<th class="col-property">Property</th>
|
||||||
>
|
<th class="col-mapping">Mapping</th>
|
||||||
Save
|
<th class="col-new-name">New name</th>
|
||||||
</button>
|
<th class="col-wikilink">Wikilink</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each model.properties as property}
|
||||||
|
<tr>
|
||||||
|
<td class="col-property">
|
||||||
|
<code>{property.property}</code>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{#if property.locked}
|
||||||
|
<td class="col-locked" colspan="3">
|
||||||
|
<div class="media-db-plugin-property-binding-text">property cannot be remapped</div>
|
||||||
|
</td>
|
||||||
|
{:else}
|
||||||
|
<td class="col-mapping">
|
||||||
|
<select class="dropdown" bind:value={property.mapping} onchange={() => onModelUpdate()}>
|
||||||
|
{#each propertyMappingOptions as remappingOption}
|
||||||
|
<option value={remappingOption}>
|
||||||
|
{remappingOption}
|
||||||
|
</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="col-new-name">
|
||||||
|
{#if property.mapping === PropertyMappingOption.Map}
|
||||||
|
<div class="media-db-plugin-property-mapping-to">
|
||||||
|
<Icon iconName="arrow-right" />
|
||||||
|
<input
|
||||||
|
class="media-db-plugin-property-mapping-input"
|
||||||
|
type="text"
|
||||||
|
spellcheck="false"
|
||||||
|
bind:value={property.newProperty}
|
||||||
|
onchange={() => onModelUpdate()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<span class="media-db-plugin-property-mapping-to-disabled">—</span>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="col-wikilink">
|
||||||
|
<label class="media-db-plugin-property-mapping-wikilink-label" title="Convert value to wikilink ([[value]])">
|
||||||
|
<input type="checkbox" bind:checked={property.wikilink} onchange={() => onModelUpdate()} />
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Container */
|
||||||
|
.media-db-plugin-property-mappings-model-container {
|
||||||
|
margin-bottom: var(--size-4-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header and actions */
|
||||||
|
.media-db-plugin-property-mappings-model-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: var(--size-4-4);
|
||||||
|
gap: var(--size-4-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mappings-model-header .setting-item-name {
|
||||||
|
font-weight: var(--font-semibold);
|
||||||
|
font-size: var(--font-ui-medium);
|
||||||
|
color: var(--text-normal);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mappings-model-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--size-4-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mapping-unsaved-changes {
|
||||||
|
color: var(--text-warning);
|
||||||
|
font-size: var(--font-ui-small);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mappings-save-button {
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mappings-save-button.mod-muted {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validation error */
|
||||||
|
.media-db-plugin-property-mapping-validation {
|
||||||
|
color: var(--text-error);
|
||||||
|
background: rgba(var(--color-red-rgb), 0.1);
|
||||||
|
padding: var(--size-4-3) var(--size-4-4);
|
||||||
|
margin-bottom: var(--size-4-4);
|
||||||
|
border-left: 3px solid var(--text-error);
|
||||||
|
font-size: var(--font-ui-small);
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table container */
|
||||||
|
.media-db-plugin-property-mappings-table-container {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.media-db-plugin-property-mappings-table {
|
.media-db-plugin-property-mappings-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
table-layout: fixed; /* prevent overflow from wide cells */
|
font-size: var(--font-ui-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove excessive left padding and keep within container */
|
/* Table header */
|
||||||
.media-db-plugin-property-mappings-table th,
|
.media-db-plugin-property-mappings-table thead {
|
||||||
.media-db-plugin-property-mappings-table td {
|
|
||||||
padding: 2px 4px;
|
|
||||||
border-bottom: 1px solid var(--background-modifier-border);
|
border-bottom: 1px solid var(--background-modifier-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mappings-table th {
|
||||||
|
padding: var(--size-4-2) var(--size-4-3);
|
||||||
|
padding-left: 0;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: var(--font-semibold);
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: var(--font-ui-smaller);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table body */
|
||||||
|
.media-db-plugin-property-mappings-table tbody tr {
|
||||||
|
transition: background-color 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mappings-table td {
|
||||||
|
padding: var(--size-4-3) var(--size-4-3) var(--size-4-3) 0;
|
||||||
|
border-bottom: 1px solid var(--background-modifier-border-hover);
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* column widths */
|
.media-db-plugin-property-mappings-table tbody tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Column widths */
|
||||||
.col-property {
|
.col-property {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
@ -126,36 +231,66 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ensure inner controls don't push table wider than container */
|
.col-locked {
|
||||||
.media-db-plugin-property-mapping-to {
|
text-align: center;
|
||||||
display: flex;
|
font-style: italic;
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-input,
|
/* Property name styling */
|
||||||
|
.media-db-plugin-property-mappings-table code {
|
||||||
|
padding: var(--size-4-1) var(--size-4-2);
|
||||||
|
margin: 0;
|
||||||
|
background: var(--code-background);
|
||||||
|
color: var(--code-normal);
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
font-size: var(--font-ui-smaller);
|
||||||
|
font-family: var(--font-monospace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locked property text */
|
||||||
|
.media-db-plugin-property-binding-text {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: var(--font-ui-small);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dropdown select - use Obsidian defaults */
|
||||||
.media-db-plugin-property-mappings-table select.dropdown {
|
.media-db-plugin-property-mappings-table select.dropdown {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-wikilink-label {
|
/* Remap input */
|
||||||
display: inline-flex;
|
.media-db-plugin-property-mapping-to {
|
||||||
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: var(--size-4-2);
|
||||||
font-size: 0.95em;
|
min-width: 0;
|
||||||
cursor: pointer;
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mapping-input {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
font-family: var(--font-monospace);
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-to-disabled {
|
.media-db-plugin-property-mapping-to-disabled {
|
||||||
color: var(--text-muted);
|
color: var(--text-faint);
|
||||||
|
font-size: var(--font-ui-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* avoid extra left indentation from <pre> */
|
/* Wikilink checkbox */
|
||||||
.media-db-plugin-property-mappings-table code {
|
.media-db-plugin-property-mapping-wikilink-label {
|
||||||
padding: 0;
|
display: inline-flex;
|
||||||
margin: 0;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: var(--size-4-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-property-mapping-wikilink-label input[type='checkbox'] {
|
||||||
|
cursor: pointer;
|
||||||
|
width: var(--checkbox-size);
|
||||||
|
height: var(--checkbox-size);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,6 @@
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<pre>{JSON.stringify(models, null, 4)}</pre>
|
<pre>{JSON.stringify(models, null, 4)}</pre>
|
||||||
|
|
||||||
{ #each ICON_LIST as icon }
|
|
||||||
<p>
|
|
||||||
{icon} <Icon iconName="{icon}"/>
|
|
||||||
</p>
|
|
||||||
{/each}
|
|
||||||
-->
|
-->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -7,24 +7,25 @@ import { GameModel } from '../models/GameModel';
|
||||||
import type { MediaTypeModel } from '../models/MediaTypeModel';
|
import type { MediaTypeModel } from '../models/MediaTypeModel';
|
||||||
import { MovieModel } from '../models/MovieModel';
|
import { MovieModel } from '../models/MovieModel';
|
||||||
import { MusicReleaseModel } from '../models/MusicReleaseModel';
|
import { MusicReleaseModel } from '../models/MusicReleaseModel';
|
||||||
import { SeriesModel } from '../models/SeriesModel';
|
|
||||||
import { SeasonModel } from '../models/SeasonModel';
|
import { SeasonModel } from '../models/SeasonModel';
|
||||||
|
import { SeriesModel } from '../models/SeriesModel';
|
||||||
import { WikiModel } from '../models/WikiModel';
|
import { WikiModel } from '../models/WikiModel';
|
||||||
import type { MediaDbPluginSettings } from '../settings/Settings';
|
import type { MediaDbPluginSettings } from '../settings/Settings';
|
||||||
import { ILLEGAL_FILENAME_CHARACTERS } from './IllegalFilenameCharactersList';
|
import { ILLEGAL_FILENAME_CHARACTERS } from './IllegalFilenameCharactersList';
|
||||||
import { MediaType } from './MediaType';
|
import { MediaType } from './MediaType';
|
||||||
import { replaceTags } from './Utils';
|
import { replaceTags } from './Utils';
|
||||||
|
|
||||||
|
// All media types in alphabetical order
|
||||||
export const MEDIA_TYPES: MediaType[] = [
|
export const MEDIA_TYPES: MediaType[] = [
|
||||||
MediaType.Movie,
|
|
||||||
MediaType.Series,
|
|
||||||
MediaType.Season,
|
|
||||||
MediaType.ComicManga,
|
|
||||||
MediaType.Game,
|
|
||||||
MediaType.Wiki,
|
|
||||||
MediaType.MusicRelease,
|
|
||||||
MediaType.BoardGame,
|
MediaType.BoardGame,
|
||||||
MediaType.Book,
|
MediaType.Book,
|
||||||
|
MediaType.ComicManga,
|
||||||
|
MediaType.Game,
|
||||||
|
MediaType.Movie,
|
||||||
|
MediaType.MusicRelease,
|
||||||
|
MediaType.Series,
|
||||||
|
MediaType.Season,
|
||||||
|
MediaType.Wiki,
|
||||||
];
|
];
|
||||||
|
|
||||||
export class MediaTypeManager {
|
export class MediaTypeManager {
|
||||||
|
|
|
||||||
|
|
@ -236,8 +236,8 @@ export class ModalHelper {
|
||||||
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 modal = new MediaDbSearchModal(this.plugin, searchModalOptions);
|
||||||
const res: SearchModalResult = await new Promise(resolve => {
|
const res: SearchModalResult = await new Promise(resolve => {
|
||||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
modal.setSubmitCb(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||||
modal.setCloseCallback(err => {
|
modal.setCloseCb(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
resolve({ code: ModalResultCode.ERROR, error: err });
|
resolve({ code: ModalResultCode.ERROR, error: err });
|
||||||
}
|
}
|
||||||
|
|
@ -302,8 +302,8 @@ export class ModalHelper {
|
||||||
): Promise<{ advancedSearchModalResult: AdvancedSearchModalResult; advancedSearchModal: MediaDbAdvancedSearchModal }> {
|
): Promise<{ advancedSearchModalResult: AdvancedSearchModalResult; advancedSearchModal: MediaDbAdvancedSearchModal }> {
|
||||||
const modal = new MediaDbAdvancedSearchModal(this.plugin, advancedSearchModalOptions);
|
const modal = new MediaDbAdvancedSearchModal(this.plugin, advancedSearchModalOptions);
|
||||||
const res: AdvancedSearchModalResult = await new Promise(resolve => {
|
const res: AdvancedSearchModalResult = await new Promise(resolve => {
|
||||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
modal.setSubmitCb(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||||
modal.setCloseCallback(err => {
|
modal.setCloseCb(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
resolve({ code: ModalResultCode.ERROR, error: err });
|
resolve({ code: ModalResultCode.ERROR, error: err });
|
||||||
}
|
}
|
||||||
|
|
@ -366,8 +366,8 @@ export class ModalHelper {
|
||||||
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 modal = new MediaDbIdSearchModal(this.plugin, idSearchModalOptions);
|
||||||
const res: IdSearchModalResult = await new Promise(resolve => {
|
const res: IdSearchModalResult = await new Promise(resolve => {
|
||||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
modal.setSubmitCb(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||||
modal.setCloseCallback(err => {
|
modal.setCloseCb(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
resolve({ code: ModalResultCode.ERROR, error: err });
|
resolve({ code: ModalResultCode.ERROR, error: err });
|
||||||
}
|
}
|
||||||
|
|
@ -430,9 +430,9 @@ export class ModalHelper {
|
||||||
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 modal = new MediaDbSearchResultModal(this.plugin, selectModalOptions);
|
||||||
const res: SelectModalResult = await new Promise(resolve => {
|
const res: SelectModalResult = await new Promise(resolve => {
|
||||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
modal.setSubmitCb(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||||
modal.setSkipCallback(() => resolve({ code: ModalResultCode.SKIP }));
|
modal.setSkipCallback(() => resolve({ code: ModalResultCode.SKIP }));
|
||||||
modal.setCloseCallback(err => {
|
modal.setCloseCb(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
resolve({ code: ModalResultCode.ERROR, error: err });
|
resolve({ code: ModalResultCode.ERROR, error: err });
|
||||||
}
|
}
|
||||||
|
|
@ -493,8 +493,8 @@ export class ModalHelper {
|
||||||
//todo: handle attachFile for existing files
|
//todo: handle attachFile for existing files
|
||||||
const modal = new MediaDbPreviewModal(this.plugin, previewModalOptions);
|
const modal = new MediaDbPreviewModal(this.plugin, previewModalOptions);
|
||||||
const res: PreviewModalResult = await new Promise(resolve => {
|
const res: PreviewModalResult = await new Promise(resolve => {
|
||||||
modal.setSubmitCallback(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
modal.setSubmitCb(res => resolve({ code: ModalResultCode.SUCCESS, data: res }));
|
||||||
modal.setCloseCallback(err => {
|
modal.setCloseCb(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
resolve({ code: ModalResultCode.ERROR, error: err });
|
resolve({ code: ModalResultCode.ERROR, error: err });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
import type { App } from 'obsidian';
|
|
||||||
import type { SeasonSelectModalElement } from '../modals/MediaDbSeasonSelectModal';
|
|
||||||
import { MediaDbSeasonSelectModal } from '../modals/MediaDbSeasonSelectModal';
|
|
||||||
|
|
||||||
export async function openSeasonSelectModal(app: App, plugin: any, seasons: SeasonSelectModalElement[]): Promise<SeasonSelectModalElement[] | undefined> {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const modal = new MediaDbSeasonSelectModal(plugin, seasons, true);
|
|
||||||
modal.setSubmitCallback(selected => {
|
|
||||||
resolve(selected);
|
|
||||||
});
|
|
||||||
modal.setCloseCallback(() => {
|
|
||||||
resolve(undefined);
|
|
||||||
});
|
|
||||||
modal.open();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
51
styles.css
51
styles.css
|
|
@ -64,55 +64,6 @@ small.media-db-plugin-list-text {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* region property mappings */
|
|
||||||
.media-db-plugin-property-mappings-model-container {
|
|
||||||
border: 1px solid var(--background-modifier-border);
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 10px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mappings-container {
|
|
||||||
margin: 10px 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-element {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-element-property-name-wrapper {
|
|
||||||
min-width: 160px;
|
|
||||||
background: var(--background-modifier-form-field);
|
|
||||||
padding: 2px 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-element-property-name {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mappings-save-button {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-to {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-property-mapping-validation {
|
|
||||||
color: var(--text-error);
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-db-plugin-button:focus {
|
.media-db-plugin-button:focus {
|
||||||
/*outline: 1px solid white;*/
|
/*outline: 1px solid white;*/
|
||||||
}
|
}
|
||||||
|
|
@ -122,5 +73,3 @@ small.media-db-plugin-list-text {
|
||||||
border: var(--modal-border-width) solid var(--modal-border-color);
|
border: var(--modal-border-width) solid var(--modal-border-color);
|
||||||
padding: var(--size-4-4);
|
padding: var(--size-4-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* endregion */
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
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'));
|
|
||||||
const { minAppVersion } = manifest;
|
|
||||||
manifest.version = targetVersion;
|
|
||||||
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'));
|
|
||||||
versions[targetVersion] = minAppVersion;
|
|
||||||
writeFileSync('versions.json', JSON.stringify(versions, null, '\t'));
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue