diff --git a/server/entity/OverrideRule.ts b/server/entity/OverrideRule.ts
index 394cc429..91d28768 100644
--- a/server/entity/OverrideRule.ts
+++ b/server/entity/OverrideRule.ts
@@ -26,6 +26,9 @@ class OverrideRule {
@Column({ nullable: true })
public language?: string;
+ @Column({ nullable: true })
+ public keywords?: string;
+
@ManyToMany(() => User)
@JoinTable()
public users: User[];
diff --git a/server/routes/overrideRule.ts b/server/routes/overrideRule.ts
index 6662189d..661e3c1c 100644
--- a/server/routes/overrideRule.ts
+++ b/server/routes/overrideRule.ts
@@ -29,6 +29,7 @@ overrideRuleRoutes.post<
{
genre?: string;
language?: string;
+ keywords?: string;
profileId?: number;
rootFolder?: string;
tags?: number[];
@@ -42,6 +43,7 @@ overrideRuleRoutes.post<
const rule = new OverrideRule({
genre: req.body.genre,
language: req.body.language,
+ keywords: req.body.keywords,
profileId: req.body.profileId,
rootFolder: req.body.rootFolder,
tags: req.body.tags,
@@ -49,9 +51,9 @@ overrideRuleRoutes.post<
sonarrServiceId: req.body.sonarrServiceId,
});
- const newIssue = await overrideRuleRepository.save(rule);
+ const newRule = await overrideRuleRepository.save(rule);
- return res.status(200).json(newIssue);
+ return res.status(200).json(newRule);
} catch (e) {
next({ status: 404, message: e.message });
}
@@ -63,6 +65,7 @@ overrideRuleRoutes.put<
{
genre?: string;
language?: string;
+ keywords?: string;
profileId?: number;
rootFolder?: string;
tags?: number[];
@@ -85,18 +88,45 @@ overrideRuleRoutes.put<
rule.genre = req.body.genre;
rule.language = req.body.language;
+ rule.keywords = req.body.keywords;
rule.profileId = req.body.profileId;
rule.rootFolder = req.body.rootFolder;
rule.tags = req.body.tags;
rule.radarrServiceId = req.body.radarrServiceId;
rule.sonarrServiceId = req.body.sonarrServiceId;
- const newIssue = await overrideRuleRepository.save(rule);
+ const newRule = await overrideRuleRepository.save(rule);
- return res.status(200).json(newIssue);
+ return res.status(200).json(newRule);
} catch (e) {
next({ status: 404, message: e.message });
}
});
+overrideRuleRoutes.delete<{ ruleId: string }, OverrideRule>(
+ '/:ruleId',
+ isAuthenticated(Permission.ADMIN),
+ async (req, res, next) => {
+ const overrideRuleRepository = getRepository(OverrideRule);
+
+ try {
+ const rule = await overrideRuleRepository.findOne({
+ where: {
+ id: Number(req.params.ruleId),
+ },
+ });
+
+ if (!rule) {
+ return next({ status: 404, message: 'Override Rule not found.' });
+ }
+
+ await overrideRuleRepository.remove(rule);
+
+ return res.status(200).json(rule);
+ } catch (e) {
+ next({ status: 404, message: e.message });
+ }
+ }
+);
+
export default overrideRuleRoutes;
diff --git a/src/components/Settings/OverrideRuleModal.tsx b/src/components/Settings/OverrideRule/OverrideRuleModal.tsx
similarity index 84%
rename from src/components/Settings/OverrideRuleModal.tsx
rename to src/components/Settings/OverrideRule/OverrideRuleModal.tsx
index 3220e87c..3aa1e668 100644
--- a/src/components/Settings/OverrideRuleModal.tsx
+++ b/src/components/Settings/OverrideRule/OverrideRuleModal.tsx
@@ -1,6 +1,6 @@
import Modal from '@app/components/Common/Modal';
import LanguageSelector from '@app/components/LanguageSelector';
-import { GenreSelector } from '@app/components/Selector';
+import { GenreSelector, KeywordSelector } from '@app/components/Selector';
import type { DVRTestResponse } from '@app/components/Settings/SettingsServices';
import useSettings from '@app/hooks/useSettings';
import globalMessages from '@app/i18n/globalMessages';
@@ -16,6 +16,15 @@ const messages = defineMessages('components.Settings.RadarrModal', {
createrule: 'New Override Rule',
editrule: 'Edit Override Rule',
create: 'Create rule',
+ conditions: 'Conditions',
+ conditionsDescription:
+ 'Specifies conditions before applying parameter changes. Each field must be validated for the rules to be applied (AND operation). A field is considered verified if any of its properties match (OR operation).',
+ settings: 'Settings',
+ settingsDescription:
+ 'Specifies which settings will be changed when the above conditions are met.',
+ genres: 'Genres',
+ languages: 'Languages',
+ keywords: 'Keywords',
rootfolder: 'Root Folder',
selectRootFolder: 'Select root folder',
qualityprofile: 'Quality Profile',
@@ -67,7 +76,7 @@ const OverrideRuleModal = ({
initialValues={{
genre: rule?.genre,
language: rule?.language,
- // keywords: [],
+ keywords: rule?.keywords,
profileId: rule?.profileId,
rootFolder: rule?.rootFolder,
tags: rule?.tags,
@@ -77,6 +86,7 @@ const OverrideRuleModal = ({
const submission = {
genre: values.genre || null,
language: values.language || null,
+ keywords: values.keywords || null,
profileId: Number(values.profileId) || null,
rootFolder: values.rootFolder || null,
tags: values.tags || null,
@@ -151,11 +161,14 @@ const OverrideRuleModal = ({
>
- Condition
+ {intl.formatMessage(messages.conditions)}
+
+ {intl.formatMessage(messages.conditionsDescription)}
+
@@ -180,7 +193,7 @@ const OverrideRuleModal = ({
@@ -193,6 +206,30 @@ const OverrideRuleModal = ({
}}
/>
+ {errors.language &&
+ touched.language &&
+ typeof errors.language === 'string' && (
+
{errors.language}
+ )}
+
+
+
+
+
+
+ {
+ setFieldValue(
+ 'keywords',
+ value?.map((v) => v.value).join(',')
+ );
+ }}
+ />
+
{errors.genre &&
touched.genre &&
typeof errors.genre === 'string' && (
@@ -201,8 +238,11 @@ const OverrideRuleModal = ({
- Settings
+ {intl.formatMessage(messages.settings)}
+
+ {intl.formatMessage(messages.settingsDescription)}
+