summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormorpheus65535 <[email protected]>2024-09-25 15:33:08 -0400
committerGitHub <[email protected]>2024-09-25 15:33:08 -0400
commitc11bdf34fadd49ea39cc73e471cc9a3075e492f4 (patch)
tree3b78449ed6652c3a1cac688a2f1fa11dead756cc
parent9d8d995d3af15c9955764487cb75edca340d1e17 (diff)
downloadbazarr-c11bdf34fadd49ea39cc73e471cc9a3075e492f4.tar.gz
bazarr-c11bdf34fadd49ea39cc73e471cc9a3075e492f4.zip
Fixed duplicate IDs in languages profile itemsv1.4.5-beta.5
-rw-r--r--bazarr/app/database.py29
-rw-r--r--bazarr/main.py4
-rw-r--r--bazarr/utilities/health.py21
-rw-r--r--frontend/src/Router/index.tsx2
-rw-r--r--frontend/src/pages/Settings/Languages/table.tsx44
5 files changed, 94 insertions, 6 deletions
diff --git a/bazarr/app/database.py b/bazarr/app/database.py
index 3780befea..b931c5f0f 100644
--- a/bazarr/app/database.py
+++ b/bazarr/app/database.py
@@ -528,3 +528,32 @@ def upgrade_languages_profile_hi_values():
.values({"items": json.dumps(items)})
.where(TableLanguagesProfiles.profileId == languages_profile.profileId)
)
+
+
+def fix_languages_profiles_with_duplicate_ids():
+ languages_profiles = database.execute(
+ select(TableLanguagesProfiles.profileId, TableLanguagesProfiles.items, TableLanguagesProfiles.cutoff)).all()
+ for languages_profile in languages_profiles:
+ if languages_profile.cutoff:
+ # ignore profiles that have a cutoff set
+ continue
+ languages_profile_ids = []
+ languages_profile_has_duplicate = False
+ languages_profile_items = json.loads(languages_profile.items)
+ for items in languages_profile_items:
+ if items['id'] in languages_profile_ids:
+ languages_profile_has_duplicate = True
+ break
+ else:
+ languages_profile_ids.append(items['id'])
+
+ if languages_profile_has_duplicate:
+ item_id = 0
+ for items in languages_profile_items:
+ item_id += 1
+ items['id'] = item_id
+ database.execute(
+ update(TableLanguagesProfiles)
+ .values({"items": json.dumps(languages_profile_items)})
+ .where(TableLanguagesProfiles.profileId == languages_profile.profileId)
+ )
diff --git a/bazarr/main.py b/bazarr/main.py
index 8fe9a43fd..c86f5a7b4 100644
--- a/bazarr/main.py
+++ b/bazarr/main.py
@@ -35,7 +35,8 @@ else:
# there's missing embedded packages after a commit
check_if_new_update()
-from app.database import System, database, update, migrate_db, create_db_revision, upgrade_languages_profile_hi_values # noqa E402
+from app.database import (System, database, update, migrate_db, create_db_revision, upgrade_languages_profile_hi_values,
+ fix_languages_profiles_with_duplicate_ids) # noqa E402
from app.notifier import update_notifier # noqa E402
from languages.get_languages import load_language_in_db # noqa E402
from app.signalr_client import sonarr_signalr_client, radarr_signalr_client # noqa E402
@@ -50,6 +51,7 @@ if args.create_db_revision:
else:
migrate_db(app)
upgrade_languages_profile_hi_values()
+ fix_languages_profiles_with_duplicate_ids()
configure_proxy_func()
diff --git a/bazarr/utilities/health.py b/bazarr/utilities/health.py
index 36b1625f1..c1d3a6a3d 100644
--- a/bazarr/utilities/health.py
+++ b/bazarr/utilities/health.py
@@ -1,7 +1,9 @@
# coding=utf-8
+import json
+
from app.config import settings
-from app.database import TableShowsRootfolder, TableMoviesRootfolder, database, select
+from app.database import TableShowsRootfolder, TableMoviesRootfolder, TableLanguagesProfiles, database, select
from app.event_handler import event_stream
from .path_mappings import path_mappings
from sonarr.rootfolder import check_sonarr_rootfolder
@@ -47,4 +49,21 @@ def get_health_issues():
health_issues.append({'object': path_mappings.path_replace_movie(item.path),
'issue': item.error})
+ # get languages profiles duplicate ids issues when there's a cutoff set
+ languages_profiles = database.execute(
+ select(TableLanguagesProfiles.items, TableLanguagesProfiles.name, TableLanguagesProfiles.cutoff)).all()
+ for languages_profile in languages_profiles:
+ if not languages_profile.cutoff:
+ # ignore profiles that don't have a cutoff set
+ continue
+ languages_profile_ids = []
+ for items in json.loads(languages_profile.items):
+ if items['id'] in languages_profile_ids:
+ health_issues.append({'object': languages_profile.name,
+ 'issue': 'This languages profile has duplicate IDs. You need to edit this profile'
+ ' and make sure to select the proper cutoff if required.'})
+ break
+ else:
+ languages_profile_ids.append(items['id'])
+
return health_issues
diff --git a/frontend/src/Router/index.tsx b/frontend/src/Router/index.tsx
index d600fc87d..8ccea87f9 100644
--- a/frontend/src/Router/index.tsx
+++ b/frontend/src/Router/index.tsx
@@ -270,6 +270,7 @@ function useRoutes(): CustomRouteObject[] {
{
path: "status",
name: "Status",
+ badge: data?.status,
element: (
<Lazy>
<SystemStatusView></SystemStatusView>
@@ -309,6 +310,7 @@ function useRoutes(): CustomRouteObject[] {
data?.sonarr_signalr,
data?.radarr_signalr,
data?.announcements,
+ data?.status,
radarr,
sonarr,
],
diff --git a/frontend/src/pages/Settings/Languages/table.tsx b/frontend/src/pages/Settings/Languages/table.tsx
index 03971a5cc..5cfefdfa9 100644
--- a/frontend/src/pages/Settings/Languages/table.tsx
+++ b/frontend/src/pages/Settings/Languages/table.tsx
@@ -2,7 +2,7 @@ import { FunctionComponent, useCallback, useMemo } from "react";
import { Badge, Button, Group } from "@mantine/core";
import { faTrash, faWrench } from "@fortawesome/free-solid-svg-icons";
import { ColumnDef } from "@tanstack/react-table";
-import { cloneDeep } from "lodash";
+import { cloneDeep, includes, maxBy } from "lodash";
import { Action } from "@/components";
import {
anyCutoff,
@@ -79,10 +79,10 @@ const Table: FunctionComponent = () => {
}) => {
return (
<Group gap="xs" wrap="nowrap">
- {items.map((v) => {
+ {items.map((v, i) => {
const isCutoff = v.id === cutoff || cutoff === anyCutoff;
return (
- <ItemBadge key={v.id} cutoff={isCutoff} item={v}></ItemBadge>
+ <ItemBadge key={i} cutoff={isCutoff} item={v}></ItemBadge>
);
})}
</Group>
@@ -148,9 +148,45 @@ const Table: FunctionComponent = () => {
icon={faWrench}
c="gray"
onClick={() => {
+ const lastId = maxBy(profile.items, "id")?.id || 0;
+
+ // We once had an issue on the past where there were duplicated
+ // item ids that needs to become unique upon editing.
+ const sanitizedProfile = {
+ ...cloneDeep(profile),
+ items: profile.items.reduce(
+ (acc, value) => {
+ const { ids, duplicatedIds, items } = acc;
+
+ // We once had an issue on the past where there were duplicated
+ // item ids that needs to become unique upon editing.
+ if (includes(ids, value.id)) {
+ duplicatedIds.push(value.id);
+ items.push({
+ ...value,
+ id: lastId + duplicatedIds.length,
+ });
+
+ return acc;
+ }
+
+ ids.push(value.id);
+ items.push(value);
+
+ return acc;
+ },
+ {
+ ids: [] as number[],
+ duplicatedIds: [] as number[],
+ items: [] as typeof profile.items,
+ },
+ ).items,
+ tag: profile.tag || undefined,
+ };
+
modals.openContextModal(ProfileEditModal, {
languages,
- profile: cloneDeep(profile),
+ profile: sanitizedProfile,
onComplete: updateProfile,
});
}}