-
+
\\^$.|?*+()[{ have special meanings and need escaping with a \\' }} />
+ {'More details'} {'Here'}
-
-
-
-
+ {'Regular expressions can be tested '}
+ Here
}
diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx
index b2c1208cb..734f5efab 100644
--- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx
+++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx
@@ -10,11 +10,11 @@ import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
-import Column from 'Components/Table/Column';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import useSelectState from 'Helpers/Hooks/useSelectState';
import { kinds } from 'Helpers/Props';
+import SortDirection from 'Helpers/Props/SortDirection';
import {
bulkDeleteDownloadClients,
bulkEditDownloadClients,
@@ -35,7 +35,7 @@ type OnSelectedChangeCallback = React.ComponentProps<
typeof ManageDownloadClientsModalRow
>['onSelectedChange'];
-const COLUMNS: Column[] = [
+const COLUMNS = [
{
name: 'name',
label: () => translate('Name'),
@@ -82,6 +82,8 @@ const COLUMNS: Column[] = [
interface ManageDownloadClientsModalContentProps {
onModalClose(): void;
+ sortKey?: string;
+ sortDirection?: SortDirection;
}
function ManageDownloadClientsModalContent(
diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js
index d50fb2385..2799af7d8 100644
--- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js
+++ b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js
@@ -292,7 +292,7 @@ function EditImportListModalContent(props) {
diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx
index 997d1b566..dbb394959 100644
--- a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx
+++ b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx
@@ -10,11 +10,11 @@ import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
-import Column from 'Components/Table/Column';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import useSelectState from 'Helpers/Hooks/useSelectState';
import { kinds } from 'Helpers/Props';
+import SortDirection from 'Helpers/Props/SortDirection';
import {
bulkDeleteIndexers,
bulkEditIndexers,
@@ -35,7 +35,7 @@ type OnSelectedChangeCallback = React.ComponentProps<
typeof ManageIndexersModalRow
>['onSelectedChange'];
-const COLUMNS: Column[] = [
+const COLUMNS = [
{
name: 'name',
label: () => translate('Name'),
@@ -82,6 +82,8 @@ const COLUMNS: Column[] = [
interface ManageIndexersModalContentProps {
onModalClose(): void;
+ sortKey?: string;
+ sortDirection?: SortDirection;
}
function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js
index dc91e4622..47e5dfcf1 100644
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js
+++ b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js
@@ -94,9 +94,9 @@ class RootFolder extends Component {
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js
index ee51799f2..383cf057b 100644
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js
+++ b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js
@@ -105,7 +105,7 @@ function EditNotificationModalContent(props) {
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js
index 0d1225a93..da1bf7f44 100644
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js
+++ b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js
@@ -87,9 +87,9 @@ function EditDelayProfileModalContent(props) {
{
!isFetching && !!error ?
-
- {translate('AddDelayProfileError')}
- :
+
+ {translate('UnableToAddANewQualityProfilePleaseTryAgain')}
+
:
null
}
@@ -186,7 +186,7 @@ function EditDelayProfileModalContent(props) {
{
id === 1 ?
- {translate('DefaultDelayProfileArtist')}
+ {translate('DefaultDelayProfileHelpText')}
:
@@ -196,7 +196,7 @@ function EditDelayProfileModalContent(props) {
type={inputTypes.TAG}
name="tags"
{...tags}
- helpText={translate('DelayProfileArtistTagsHelpText')}
+ helpText={translate('TagsHelpText')}
onChange={onInputChange}
/>
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js
index e1c695c42..c6c297c81 100644
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js
+++ b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js
@@ -119,7 +119,7 @@ function EditReleaseProfileModalContent(props) {
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.css b/frontend/src/Settings/Quality/Definition/QualityDefinition.css
index 860333725..e090428a1 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.css
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinition.css
@@ -24,19 +24,19 @@
height: 20px;
}
-.track {
+.bar {
top: 9px;
margin: 0 5px;
height: 3px;
background-color: var(--sliderAccentColor);
box-shadow: 0 0 0 #000;
- &:nth-child(3n + 1) {
+ &:nth-child(3n+1) {
background-color: #ddd;
}
}
-.thumb {
+.handle {
top: 1px;
z-index: 0 !important;
width: 18px;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts b/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts
index 9c9e8393a..2b92fb212 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts
@@ -1,6 +1,8 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
+ 'bar': string;
+ 'handle': string;
'kilobitsPerSecond': string;
'quality': string;
'qualityDefinition': string;
@@ -8,9 +10,7 @@ interface CssExports {
'sizeLimit': string;
'sizes': string;
'slider': string;
- 'thumb': string;
'title': string;
- 'track': string;
}
export const cssExports: CssExports;
export default cssExports;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.js b/frontend/src/Settings/Quality/Definition/QualityDefinition.js
index 48251abfb..7d8a78737 100644
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.js
+++ b/frontend/src/Settings/Quality/Definition/QualityDefinition.js
@@ -55,27 +55,6 @@ class QualityDefinition extends Component {
};
}
- //
- // Control
-
- trackRenderer(props, state) {
- return (
-
- );
- }
-
- thumbRenderer(props, state) {
- return (
-
- );
- }
-
//
// Listeners
@@ -195,7 +174,6 @@ class QualityDefinition extends Component {
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js
index 04302729b..2ab1e4a1c 100644
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js
+++ b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js
@@ -86,10 +86,10 @@ function EditSpecificationModalContent(props) {
-
+
-
+
}
diff --git a/frontend/src/Store/Actions/artistIndexActions.js b/frontend/src/Store/Actions/artistIndexActions.js
index 736502460..055e92662 100644
--- a/frontend/src/Store/Actions/artistIndexActions.js
+++ b/frontend/src/Store/Actions/artistIndexActions.js
@@ -151,7 +151,7 @@ export const defaultState = {
{
name: 'genres',
label: () => translate('Genres'),
- isSortable: true,
+ isSortable: false,
isVisible: false
},
{
diff --git a/frontend/src/Store/Actions/historyActions.js b/frontend/src/Store/Actions/historyActions.js
index 9d16d29c4..225698229 100644
--- a/frontend/src/Store/Actions/historyActions.js
+++ b/frontend/src/Store/Actions/historyActions.js
@@ -150,7 +150,7 @@ export const defaultState = {
},
{
key: 'importFailed',
- label: () => translate('ImportCompleteFailed'),
+ label: () => translate('ImportFailed'),
filters: [
{
key: 'eventType',
diff --git a/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts b/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts
index 414a451f5..baffd87ec 100644
--- a/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts
+++ b/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts
@@ -1,5 +1,4 @@
import { createSelector } from 'reselect';
-import AlbumAppState from 'App/State/AlbumAppState';
import AppState from 'App/State/AppState';
import Artist from 'Artist/Artist';
import { createArtistSelectorForHook } from './createArtistSelector';
@@ -8,7 +7,7 @@ function createArtistAlbumsSelector(artistId: number) {
return createSelector(
(state: AppState) => state.albums,
createArtistSelectorForHook(artistId),
- (albums: AlbumAppState, artist = {} as Artist) => {
+ (albums, artist = {} as Artist) => {
const { isFetching, isPopulated, error, items } = albums;
const filteredAlbums = items.filter(
diff --git a/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts b/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts
index fa60d936d..0acbd3997 100644
--- a/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts
+++ b/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts
@@ -1,14 +1,13 @@
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import Artist from 'Artist/Artist';
-import MetadataProfile from 'typings/MetadataProfile';
import { createArtistSelectorForHook } from './createArtistSelector';
function createArtistMetadataProfileSelector(artistId: number) {
return createSelector(
(state: AppState) => state.settings.metadataProfiles.items,
createArtistSelectorForHook(artistId),
- (metadataProfiles: MetadataProfile[], artist = {} as Artist) => {
+ (metadataProfiles, artist = {} as Artist) => {
return metadataProfiles.find((profile) => {
return profile.id === artist.metadataProfileId;
});
diff --git a/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts b/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts
index 67639919b..99325276f 100644
--- a/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts
+++ b/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts
@@ -1,14 +1,13 @@
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import Artist from 'Artist/Artist';
-import QualityProfile from 'typings/QualityProfile';
import { createArtistSelectorForHook } from './createArtistSelector';
function createArtistQualityProfileSelector(artistId: number) {
return createSelector(
(state: AppState) => state.settings.qualityProfiles.items,
createArtistSelectorForHook(artistId),
- (qualityProfiles: QualityProfile[], artist = {} as Artist) => {
+ (qualityProfiles, artist = {} as Artist) => {
return qualityProfiles.find(
(profile) => profile.id === artist.qualityProfileId
);
diff --git a/frontend/src/System/Logs/Files/LogFiles.js b/frontend/src/System/Logs/Files/LogFiles.js
index 5339a8590..83736c617 100644
--- a/frontend/src/System/Logs/Files/LogFiles.js
+++ b/frontend/src/System/Logs/Files/LogFiles.js
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Alert from 'Components/Alert';
+import Link from 'Components/Link/Link';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
@@ -77,16 +77,15 @@ class LogFiles extends Component {
- {translate('LogFilesLocation', {
- location
- })}
+ Log files are located in: {location}
- {currentLogView === 'Log Files' ? (
-
-
-
- ) : null}
+ {
+ currentLogView === 'Log Files' &&
+
+ The log level defaults to 'Info' and can be changed in General Settings
+
+ }
{
diff --git a/frontend/src/System/Updates/Updates.tsx b/frontend/src/System/Updates/Updates.tsx
index 300ab1f99..ef3d20288 100644
--- a/frontend/src/System/Updates/Updates.tsx
+++ b/frontend/src/System/Updates/Updates.tsx
@@ -270,7 +270,7 @@ function Updates() {
{generalSettingsError ? (
- {translate('FailedToFetchSettings')}
+ {translate('FailedToUpdateSettings')}
) : null}
diff --git a/frontend/src/Utilities/Date/getRelativeDate.ts b/frontend/src/Utilities/Date/getRelativeDate.js
similarity index 65%
rename from frontend/src/Utilities/Date/getRelativeDate.ts
rename to frontend/src/Utilities/Date/getRelativeDate.js
index 178d14fb7..812064272 100644
--- a/frontend/src/Utilities/Date/getRelativeDate.ts
+++ b/frontend/src/Utilities/Date/getRelativeDate.js
@@ -6,33 +6,15 @@ import isTomorrow from 'Utilities/Date/isTomorrow';
import isYesterday from 'Utilities/Date/isYesterday';
import translate from 'Utilities/String/translate';
-interface GetRelativeDateOptions {
- timeFormat?: string;
- includeSeconds?: boolean;
- timeForToday?: boolean;
-}
-
-function getRelativeDate(
- date: string | undefined,
- shortDateFormat: string,
- showRelativeDates: boolean,
- {
- timeFormat,
- includeSeconds = false,
- timeForToday = false,
- }: GetRelativeDateOptions = {}
-) {
+function getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds = false, timeForToday = false } = {}) {
if (!date) {
- return '';
+ return null;
}
const isTodayDate = isToday(date);
if (isTodayDate && timeForToday && timeFormat) {
- return formatTime(date, timeFormat, {
- includeMinuteZero: true,
- includeSeconds,
- });
+ return formatTime(date, timeFormat, { includeMinuteZero: true, includeSeconds });
}
if (!showRelativeDates) {
diff --git a/frontend/src/Utilities/String/translate.ts b/frontend/src/Utilities/String/translate.ts
index 5571ef6b0..98a0418ad 100644
--- a/frontend/src/Utilities/String/translate.ts
+++ b/frontend/src/Utilities/String/translate.ts
@@ -17,7 +17,7 @@ export async function fetchTranslations(): Promise {
translations = data.strings;
resolve(true);
- } catch {
+ } catch (error) {
resolve(false);
}
});
@@ -27,12 +27,6 @@ export default function translate(
key: string,
tokens: Record = {}
) {
- const { isProduction = true } = window.Lidarr;
-
- if (!isProduction && !(key in translations)) {
- console.warn(`Missing translation for key: ${key}`);
- }
-
const translation = translations[key] || key;
tokens.appName = 'Lidarr';
diff --git a/frontend/src/bootstrap.tsx b/frontend/src/bootstrap.tsx
index 9ecf27e0e..6a6d7fc67 100644
--- a/frontend/src/bootstrap.tsx
+++ b/frontend/src/bootstrap.tsx
@@ -1,6 +1,6 @@
import { createBrowserHistory } from 'history';
import React from 'react';
-import { createRoot } from 'react-dom/client';
+import { render } from 'react-dom';
import createAppStore from 'Store/createAppStore';
import App from './App/App';
@@ -9,8 +9,9 @@ import 'Diag/ConsoleApi';
export async function bootstrap() {
const history = createBrowserHistory();
const store = createAppStore(history);
- const container = document.getElementById('root');
- const root = createRoot(container!); // createRoot(container!) if you use TypeScript
- root.render();
+ render(
+ ,
+ document.getElementById('root')
+ );
}
diff --git a/frontend/src/index.ejs b/frontend/src/index.ejs
index a893149d5..5968082b4 100644
--- a/frontend/src/index.ejs
+++ b/frontend/src/index.ejs
@@ -33,7 +33,7 @@
sizes="16x16"
href="/Content/Images/Icons/favicon-16x16.png"
/>
-
+
diff --git a/frontend/src/index.ts b/frontend/src/index.ts
index 37e780919..36aed4c4b 100644
--- a/frontend/src/index.ts
+++ b/frontend/src/index.ts
@@ -14,32 +14,6 @@ window.Lidarr = await response.json();
__webpack_public_path__ = `${window.Lidarr.urlBase}/`;
/* eslint-enable no-undef, @typescript-eslint/ban-ts-comment */
-const error = console.error;
-
-// Monkey patch console.error to filter out some warnings from React
-// TODO: Remove this after the great TypeScript migration
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function logError(...parameters: any[]) {
- const filter = parameters.find((parameter) => {
- return (
- typeof parameter === 'string' &&
- (parameter.includes(
- 'Support for defaultProps will be removed from function components in a future major release'
- ) ||
- parameter.includes(
- 'findDOMNode is deprecated and will be removed in the next major release'
- ))
- );
- });
-
- if (!filter) {
- error(...parameters);
- }
-}
-
-console.error = logError;
-
const { bootstrap } = await import('./bootstrap');
await bootstrap();
diff --git a/frontend/src/login.html b/frontend/src/login.html
index 24d086959..113dc547b 100644
--- a/frontend/src/login.html
+++ b/frontend/src/login.html
@@ -11,11 +11,8 @@
-
-
+
+
@@ -36,11 +33,7 @@
sizes="16x16"
href="/Content/Images/Icons/favicon-16x16.png"
/>
-
+
-
+
@@ -63,7 +59,7 @@
body {
background-color: var(--pageBackground);
color: var(--textColor);
- font-family: 'Roboto', 'open sans', 'Helvetica Neue', Helvetica, Arial,
+ font-family: "Roboto", "open sans", "Helvetica Neue", Helvetica, Arial,
sans-serif;
}
@@ -213,7 +209,9 @@