Skip to content

Commit

Permalink
feat(tags): enable tags to be set in the stasharr settings (#52)
Browse files Browse the repository at this point in the history
Allows users to set which tags will be associated with studios, scenes, and performers when they are
added to Whisparr using Stasharr.

fix #49
  • Loading branch information
enymawse authored Dec 3, 2024
1 parent a496415 commit ca8e446
Show file tree
Hide file tree
Showing 21 changed files with 121 additions and 103 deletions.
2 changes: 1 addition & 1 deletion src/builder/PerformerPayloadBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class PerformerPayloadBuilder {
};
}

setTags(tags: string[]) {
setTags(tags: number[]) {
this.payload.tags = tags;
return this;
}
Expand Down
6 changes: 6 additions & 0 deletions src/builder/ScenePayloadBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ export class ScenePayloadBuilder {
monitored: true,
addOptions: { searchForMovie: true },
qualityProfileId: 0,
tags: [],
};
}

setTags(tags: number[]) {
this.payload.tags = tags;
return this;
}

setTitle(title: string) {
this.payload.title = title;
return this;
Expand Down
2 changes: 1 addition & 1 deletion src/builder/StudioPayloadBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class StudioPayloadBuilder {
};
}

setTags(tags: string[]) {
setTags(tags: number[]) {
this.payload.tags = tags;
return this;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/scene/header/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Details = (props: { config: Config; stashId: string }) => {
const [qualityProfiles] = createResource(
props,
async (p: { config: Config }) => {
return WhisparrService.getQualityProfiles(p.config);
return WhisparrService.qualityProfiles(p.config);
},
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Stasharr } from '../enums/Stasharr';
import { useSettings } from '../contexts/useSettings';
import { Stasharr } from '../../enums/Stasharr';
import { useSettings } from '../../contexts/useSettings';

const DomainInput = () => {
const { store, setStore } = useSettings();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Stasharr } from '../enums/Stasharr';
import { Stasharr } from '../../enums/Stasharr';

const NavbarLink = () => (
<a
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Stasharr } from '../enums/Stasharr';
import { useSettings } from '../contexts/useSettings';
import { Stasharr } from '../../enums/Stasharr';
import { useSettings } from '../../contexts/useSettings';

const ProtocolSwitch = () => {
const { store, setStore } = useSettings();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { For } from 'solid-js';
import { useSettings } from '../contexts/useSettings';
import { useSettings } from '../../contexts/useSettings';
import { Form } from 'solid-bootstrap';
import { Whisparr } from '../types/whisparr';
import { Stasharr } from '../enums/Stasharr';
import { Whisparr } from '../../types/whisparr';
import { Stasharr } from '../../enums/Stasharr';

const QualityProfileSelect = (props: {
qualityProfiles: Whisparr.QualityProfile[] | undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { For } from 'solid-js';
import { useSettings } from '../contexts/useSettings';
import { useSettings } from '../../contexts/useSettings';
import { Form } from 'solid-bootstrap';
import { Whisparr } from '../types/whisparr';
import { Stasharr } from '../enums/Stasharr';
import { Whisparr } from '../../types/whisparr';
import { Stasharr } from '../../enums/Stasharr';

const RootFolderPathSelect = (props: {
rootFolderPaths: Whisparr.RootFolder[] | undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { For } from 'solid-js';
import { useSettings } from '../contexts/useSettings';
import { useSettings } from '../../contexts/useSettings';
import { Form } from 'solid-bootstrap';
import { Stasharr } from '../enums/Stasharr';
import { Stasharr } from '../../enums/Stasharr';

const SearchOnAddSelect = () => {
const { store, setStore } = useSettings();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import {
import { Modal, Button, Alert } from 'solid-bootstrap';
import ProtocolSwitch from './ProtocolSwitch';
import DomainInput from './DomainInput';
import WhisparrApiKeyInput from './ApiKeyInput';
import WhisparrApiKeyInput from '../ApiKeyInput';
import { createStore } from 'solid-js/store';
import { Config } from '../models/Config';
import WhisparrService from '../service/WhisparrService';
import { SettingsContext } from '../contexts/useSettings';
import { Config } from '../../models/Config';
import WhisparrService from '../../service/WhisparrService';
import { SettingsContext } from '../../contexts/useSettings';
import QualityProfileSelect from './QualityProfile';
import { parseInt } from 'lodash';
import RootFolderPathSelect from './RootFolderPath';
import SearchOnAddSelect from './SearchOnAdd';
import { Stasharr } from '../enums/Stasharr';
import { Stasharr } from '../../enums/Stasharr';
import Tags from './Tags';

function SettingsModal(props: { config: Config }) {
const [show, setShow] = createSignal(false);
Expand Down Expand Up @@ -93,6 +94,7 @@ function SettingsModal(props: { config: Config }) {
<QualityProfileSelect qualityProfiles={qualityProfiles()} />
<RootFolderPathSelect rootFolderPaths={rootFolderPaths()} />
<SearchOnAddSelect />
<Tags />
</Show>
</Modal.Body>
<Modal.Footer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useSettings } from '../contexts/useSettings';
import { Stasharr } from '../enums/Stasharr';
import { useSettings } from '../../contexts/useSettings';
import { Stasharr } from '../../enums/Stasharr';

const StashInstance = () => {
const { store, setStore } = useSettings();
Expand Down
60 changes: 60 additions & 0 deletions src/components/settings/Tags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Form } from 'solid-bootstrap';
import { useSettings } from '../../contexts/useSettings';
import { Stasharr } from '../../enums/Stasharr';
import { createMemo, createResource, For } from 'solid-js';
import { Config } from '../../models/Config';
import WhisparrService from '../../service/WhisparrService';
import { parseInt } from 'lodash';

const Tags = () => {
const { store, setStore } = useSettings();

const reactiveStore = createMemo(
() => new Config(store.protocol, store.domain, store.whisparrApiKey),
);

const [tags] = createResource(reactiveStore, async (s) => {
if (!s.domain || !s.whisparrApiKey) return [];
return WhisparrService.tags(s) || [];
});

const handleTagsChange = (
// eslint-disable-next-line no-undef
selectedOptions: HTMLCollectionOf<HTMLOptionElement>,
) => {
if (selectedOptions.length === 0) setStore('tags', []);
let tags: number[] = [];
for (let i = 0; i < selectedOptions.length; i++) {
const option = selectedOptions.item(i);
if (option) tags.push(parseInt(option.value, 10));
}
setStore('tags', tags);
};
return (
<div class="input-group mb-3">
<label class="input-group-text">Tags</label>
<Form.Select
aria-label="Tags select"
multiple={true}
onChange={(e) => handleTagsChange(e.target.selectedOptions)}
// value={store.tags.map((tag) => tag + '')}
id={Stasharr.ID.Modal.Tags}
data-bs-toggle="tooltip"
data-bs-title="Enter tags to be associated with the scenes, studios, and performers added via Stasharr."
>
<For each={tags()}>
{(tag) => (
<option
value={tag.id}
selected={store.tags.filter((t) => t === tag.id).length > 0}
>
{tag.label}
</option>
)}
</For>
</Form.Select>
</div>
);
};

export default Tags;
2 changes: 1 addition & 1 deletion src/controller/NavbarController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render } from 'solid-js/web';
import SettingsModal from '../components/SettingsModal';
import SettingsModal from '../components/settings/SettingsModal';
import { Config } from '../models/Config';
import { BaseController } from './BaseController';
import { StashDB } from '../enums/StashDB';
Expand Down
2 changes: 2 additions & 0 deletions src/enums/Stasharr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const qualityProfile = `${stasharrPrefix}-qualityProfile`;
const rootFolderPath = `${stasharrPrefix}-rootFolderPath`;
const searchOnAdd = `${stasharrPrefix}-searchOnAdd`;
const stashDomain = `${stasharrPrefix}-stashDomain`;
const tags = `${stasharrPrefix}-tags`;
const headerDetails = `${stasharrPrefix}-headerDetails`;
const whisparrCardButton = `whisparr-card-button`;

Expand All @@ -45,6 +46,7 @@ export const Stasharr = {
RootFolderPath: rootFolderPath,
SearchOnAdd: searchOnAdd,
StashDomain: stashDomain,
Tags: tags,
},
},
DOMSelector: {
Expand Down
1 change: 1 addition & 0 deletions src/models/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class Config {
rootFolderPath: string = '';
searchForNewMovie: boolean = true;
stashDomain: string = 'http://localhost:9999';
tags: number[] = [];

constructor(protocol?: boolean, domain?: string, whisparrApiKey?: string) {
if (protocol) this.protocol = protocol;
Expand Down
1 change: 1 addition & 0 deletions src/service/PerformerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export default class PerformerService extends ServiceBase {
.setQualityProfileId(config.qualityProfile)
.setRootFolderPath(config.rootFolderPath)
.setSearchOnAdd(config.searchForNewMovie)
.setTags(config.tags)
.build();
const response = await ServiceBase.request(
config,
Expand Down
1 change: 1 addition & 0 deletions src/service/SceneService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export default class SceneService extends ServiceBase {
.setQualityProfileId(config.qualityProfile)
.setRootFolderPath(config.rootFolderPath)
.setSearchForMovie(config.searchForNewMovie)
.setTags(config.tags)
.build();
let response;
try {
Expand Down
1 change: 1 addition & 0 deletions src/service/StudioService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export default class StudioService extends ServiceBase {
.setQualityProfileId(config.qualityProfile)
.setRootFolderPath(config.rootFolderPath)
.setSearchOnAdd(config.searchForNewMovie)
.setTags(config.tags)
.build();
const response = await ServiceBase.request(
config,
Expand Down
86 changes: 12 additions & 74 deletions src/service/WhisparrService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,6 @@ export default class WhisparrService extends ServiceBase {
}
}

static async getQualityProfiles(
config: Config,
): Promise<Whisparr.QualityProfile[]> {
const endpoint = 'qualityProfile';
const response = await ServiceBase.request(
config,
endpoint,
'GET',
undefined,
{
'Content-Type': 'application/json',
},
)
.then((response) => response.response)
.then((json) => {
return json as Whisparr.QualityProfile[];
});
return response;
}

static async qualityProfiles(
config: Config,
): Promise<null | Whisparr.QualityProfile[]> {
Expand All @@ -95,60 +75,6 @@ export default class WhisparrService extends ServiceBase {
return response.response as Whisparr.QualityProfile[];
}

static async getQualityProfilesForSelectMenu(
config: Config,
): Promise<{ id: number; name: string }[]> {
let options: { id: number; name: string }[] = [];
await WhisparrService.getQualityProfiles(config).then(
(response: Whisparr.QualityProfile[]) => {
response.forEach((qualityProfile) => {
options.push({
id: qualityProfile.id,
name: qualityProfile.name,
});
});
},
);
return options;
}

static async getRootFolderPathsForSelectMenu(
config: Config,
): Promise<{ id: number; name: string }[]> {
let options: { id: number; name: string }[] = [];

await WhisparrService.getRootFolders(config).then(
(response: Whisparr.RootFolder[]) => {
response.forEach((rootFolder) => {
options.push({
id: rootFolder.id,
name: rootFolder.path,
});
});
},
);

return options;
}

static async getRootFolders(config: Config): Promise<Whisparr.RootFolder[]> {
const endpoint = 'rootFolder';
const response = await ServiceBase.request(
config,
endpoint,
'GET',
undefined,
{
'Content-Type': 'application/json',
},
)
.then((response) => response.response)
.then((json) => {
return json as Whisparr.RootFolder[];
});
return response;
}

static async rootFolderPaths(
config: Config,
): Promise<null | Whisparr.RootFolder[]> {
Expand All @@ -162,4 +88,16 @@ export default class WhisparrService extends ServiceBase {
}
return response.response as Whisparr.RootFolder[];
}

static async tags(config: Config): Promise<Whisparr.Tag[] | null> {
const endpoint = 'tag';
let response;
try {
response = await ServiceBase.request(config, endpoint, 'GET', undefined);
} catch (e) {
console.log('Error getting Tags: ', e);
return null;
}
return response.response as Whisparr.Tag[];
}
}
Loading

0 comments on commit ca8e446

Please sign in to comment.