diff --git a/frontend/src/System/Backup/BackupRow.js b/frontend/src/System/Backup/BackupRow.js
index ad63544e3..dbc557c62 100644
--- a/frontend/src/System/Backup/BackupRow.js
+++ b/frontend/src/System/Backup/BackupRow.js
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import IconButton from 'Components/Link/IconButton';
-import Link from 'Components/Link/Link';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
@@ -65,7 +64,6 @@ class BackupRow extends Component {
id,
type,
name,
- path,
size,
time
} = this.props;
@@ -98,12 +96,7 @@ class BackupRow extends Component {
-
- {name}
-
+ {name}
@@ -155,7 +148,6 @@ BackupRow.propTypes = {
id: PropTypes.number.isRequired,
type: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
- path: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
time: PropTypes.string.isRequired,
onDeleteBackupPress: PropTypes.func.isRequired
diff --git a/frontend/src/System/Backup/Backups.js b/frontend/src/System/Backup/Backups.js
index ede2f97f6..b1ba15082 100644
--- a/frontend/src/System/Backup/Backups.js
+++ b/frontend/src/System/Backup/Backups.js
@@ -73,6 +73,7 @@ class Backups extends Component {
isPopulated,
error,
items,
+ location,
backupExecuting,
onBackupPress,
onDeleteBackupPress
@@ -101,6 +102,12 @@ class Backups extends Component {
+
+ {translate('BackupFilesLocation', {
+ location
+ })}
+
+
{
isFetching && !isPopulated &&
@@ -115,7 +122,7 @@ class Backups extends Component {
{
noBackups &&
-
+
{translate('NoBackupsAreAvailable')}
}
@@ -132,7 +139,6 @@ class Backups extends Component {
id,
type,
name,
- path,
size,
time
} = item;
@@ -143,7 +149,6 @@ class Backups extends Component {
id={id}
type={type}
name={name}
- path={path}
size={size}
time={time}
onDeleteBackupPress={onDeleteBackupPress}
@@ -171,6 +176,7 @@ Backups.propTypes = {
isPopulated: PropTypes.bool.isRequired,
error: PropTypes.object,
items: PropTypes.array.isRequired,
+ location: PropTypes.string.isRequired,
backupExecuting: PropTypes.bool.isRequired,
onBackupPress: PropTypes.func.isRequired,
onDeleteBackupPress: PropTypes.func.isRequired
diff --git a/frontend/src/System/Backup/BackupsConnector.js b/frontend/src/System/Backup/BackupsConnector.js
index 1353b6196..3565f1fd0 100644
--- a/frontend/src/System/Backup/BackupsConnector.js
+++ b/frontend/src/System/Backup/BackupsConnector.js
@@ -11,21 +11,24 @@ import Backups from './Backups';
function createMapStateToProps() {
return createSelector(
(state) => state.system.backups,
+ (state) => state.system.status.item,
createCommandExecutingSelector(commandNames.BACKUP),
- (backups, backupExecuting) => {
+ (backups, status, backupExecuting) => {
const {
isFetching,
isPopulated,
error,
items
} = backups;
+ const { backupFolder } = status;
return {
isFetching,
isPopulated,
error,
items,
- backupExecuting
+ backupExecuting,
+ location: backupFolder
};
}
);
diff --git a/src/NzbDrone.Core/Backup/BackupCommand.cs b/src/NzbDrone.Core/Backup/BackupCommand.cs
index 1f5550e59..83d3d0044 100644
--- a/src/NzbDrone.Core/Backup/BackupCommand.cs
+++ b/src/NzbDrone.Core/Backup/BackupCommand.cs
@@ -4,18 +4,7 @@ namespace NzbDrone.Core.Backup
{
public class BackupCommand : Command
{
- public BackupType Type
- {
- get
- {
- if (Trigger == CommandTrigger.Scheduled)
- {
- return BackupType.Scheduled;
- }
-
- return BackupType.Manual;
- }
- }
+ public BackupType Type => Trigger == CommandTrigger.Scheduled ? BackupType.Scheduled : BackupType.Manual;
public override bool SendUpdatesToClient => true;
diff --git a/src/NzbDrone.Core/Backup/BackupService.cs b/src/NzbDrone.Core/Backup/BackupService.cs
index e45370214..db463a1f9 100644
--- a/src/NzbDrone.Core/Backup/BackupService.cs
+++ b/src/NzbDrone.Core/Backup/BackupService.cs
@@ -105,12 +105,12 @@ namespace NzbDrone.Core.Backup
if (_diskProvider.FolderExists(folder))
{
backups.AddRange(GetBackupFiles(folder).Select(b => new Backup
- {
- Name = Path.GetFileName(b),
- Type = backupType,
- Size = _diskProvider.GetFileSize(b),
- Time = _diskProvider.FileGetLastWrite(b)
- }));
+ {
+ Name = Path.GetFileName(b),
+ Type = backupType,
+ Size = _diskProvider.GetFileSize(b),
+ Time = _diskProvider.FileGetLastWrite(b)
+ }));
}
}
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 78b8557e7..02a05677b 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -142,6 +142,7 @@
"AutomaticSearch": "Automatic Search",
"AutomaticUpdatesDisabledDocker": "Automatic updates are not directly supported when using the Docker update mechanism. You will need to update the container image outside of {appName} or use a script",
"Backup": "Backup",
+ "BackupFilesLocation": "Backup files are located in: {location}",
"BackupFolderHelpText": "Relative paths will be under {appName}'s AppData directory",
"BackupIntervalHelpText": "Interval between automatic backups",
"BackupNow": "Backup Now",
@@ -248,8 +249,8 @@
"ConnectionLost": "Connection Lost",
"ConnectionLostReconnect": "{appName} will try to connect automatically, or you can click reload below.",
"ConnectionLostToBackend": "{appName} has lost its connection to the backend and will need to be reloaded to restore functionality.",
- "Connections": "Connections",
"ConnectionSettingsUrlBaseHelpText": "Adds a prefix to the {connectionName} url, such as {url}",
+ "Connections": "Connections",
"Continuing": "Continuing",
"ContinuingOnly": "Continuing Only",
"ContinuingSeriesDescription": "More episodes/another season is expected",
@@ -280,8 +281,8 @@
"CustomFormats": "Custom Formats",
"CustomFormatsLoadError": "Unable to load Custom Formats",
"CustomFormatsSettings": "Custom Formats Settings",
- "CustomFormatsSettingsTriggerInfo": "A Custom Format will be applied to a release or file when it matches at least one of each of the different condition types chosen.",
"CustomFormatsSettingsSummary": "Custom Formats and Settings",
+ "CustomFormatsSettingsTriggerInfo": "A Custom Format will be applied to a release or file when it matches at least one of each of the different condition types chosen.",
"CustomFormatsSpecificationFlag": "Flag",
"CustomFormatsSpecificationLanguage": "Language",
"CustomFormatsSpecificationMaximumSize": "Maximum Size",
@@ -410,16 +411,16 @@
"DownloadClientAriaSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Aria2 location",
"DownloadClientCheckNoneAvailableHealthCheckMessage": "No download client is available",
"DownloadClientCheckUnableToCommunicateWithHealthCheckMessage": "Unable to communicate with {downloadClientName}. {errorMessage}",
+ "DownloadClientDelugeSettingsDirectory": "Download Directory",
+ "DownloadClientDelugeSettingsDirectoryCompleted": "Move When Completed Directory",
+ "DownloadClientDelugeSettingsDirectoryCompletedHelpText": "Optional location to move completed downloads to, leave blank to use the default Deluge location",
+ "DownloadClientDelugeSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Deluge location",
"DownloadClientDelugeSettingsUrlBaseHelpText": "Adds a prefix to the deluge json url, see {url}",
"DownloadClientDelugeTorrentStateError": "Deluge is reporting an error",
"DownloadClientDelugeValidationLabelPluginFailure": "Configuration of label failed",
"DownloadClientDelugeValidationLabelPluginFailureDetail": "{appName} was unable to add the label to {clientName}.",
"DownloadClientDelugeValidationLabelPluginInactive": "Label plugin not activated",
"DownloadClientDelugeValidationLabelPluginInactiveDetail": "You must have the Label plugin enabled in {clientName} to use categories.",
- "DownloadClientDelugeSettingsDirectory": "Download Directory",
- "DownloadClientDelugeSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Deluge location",
- "DownloadClientDelugeSettingsDirectoryCompleted": "Move When Completed Directory",
- "DownloadClientDelugeSettingsDirectoryCompletedHelpText": "Optional location to move completed downloads to, leave blank to use the default Deluge location",
"DownloadClientDownloadStationProviderMessage": "{appName} is unable to connect to Download Station if 2-Factor Authentication is enabled on your DSM account",
"DownloadClientDownloadStationSettingsDirectoryHelpText": "Optional shared folder to put downloads into, leave blank to use the default Download Station location",
"DownloadClientDownloadStationValidationApiVersion": "Download Station API version not supported, should be at least {requiredVersion}. It supports from {minVersion} to {maxVersion}",
@@ -866,12 +867,12 @@
"ImportListsSimklSettingsUserListTypePlanToWatch": "Plan To Watch",
"ImportListsSimklSettingsUserListTypeWatching": "Watching",
"ImportListsSonarrSettingsApiKeyHelpText": "API Key of the {appName} instance to import from",
- "ImportListsSonarrSettingsSyncSeasonMonitoring": "Sync Season Monitoring",
- "ImportListsSonarrSettingsSyncSeasonMonitoringHelpText": "Sync season monitoring from {appName} instance, if enabled 'Monitor' will be ignored",
"ImportListsSonarrSettingsFullUrl": "Full URL",
"ImportListsSonarrSettingsFullUrlHelpText": "URL, including port, of the {appName} instance to import from",
"ImportListsSonarrSettingsQualityProfilesHelpText": "Quality Profiles from the source instance to import from",
"ImportListsSonarrSettingsRootFoldersHelpText": "Root Folders from the source instance to import from",
+ "ImportListsSonarrSettingsSyncSeasonMonitoring": "Sync Season Monitoring",
+ "ImportListsSonarrSettingsSyncSeasonMonitoringHelpText": "Sync season monitoring from {appName} instance, if enabled 'Monitor' will be ignored",
"ImportListsSonarrSettingsTagsHelpText": "Tags from the source instance to import from",
"ImportListsSonarrValidationInvalidUrl": "{appName} URL is invalid, are you missing a URL base?",
"ImportListsTraktSettingsAdditionalParameters": "Additional Parameters",
@@ -1789,7 +1790,6 @@
"SelectSeries": "Select Series",
"SendAnonymousUsageData": "Send Anonymous Usage Data",
"Series": "Series",
- "SeriesFootNote": "Optionally control truncation to a maximum number of bytes including ellipsis (`...`). Truncating from the end (e.g. `{Series Title:30}`) or the beginning (e.g. `{Series Title:-30}`) are both supported.",
"SeriesAndEpisodeInformationIsProvidedByTheTVDB": "Series and episode information is provided by TheTVDB.com. [Please consider supporting them]({url}) .",
"SeriesCannotBeFound": "Sorry, that series cannot be found.",
"SeriesDetailsCountEpisodeFiles": "{episodeFileCount} episode files",
@@ -1803,6 +1803,7 @@
"SeriesFolderFormat": "Series Folder Format",
"SeriesFolderFormatHelpText": "Used when adding a new series or moving series via the series editor",
"SeriesFolderImportedTooltip": "Episode imported from series folder",
+ "SeriesFootNote": "Optionally control truncation to a maximum number of bytes including ellipsis (`...`). Truncating from the end (e.g. `{Series Title:30}`) or the beginning (e.g. `{Series Title:-30}`) are both supported.",
"SeriesID": "Series ID",
"SeriesIndexFooterContinuing": "Continuing (All episodes downloaded)",
"SeriesIndexFooterDownloading": "Downloading (One or more episodes)",
diff --git a/src/Sonarr.Api.V3/System/Backup/BackupController.cs b/src/Sonarr.Api.V3/System/Backup/BackupController.cs
index bb2554c03..10f3bfeaa 100644
--- a/src/Sonarr.Api.V3/System/Backup/BackupController.cs
+++ b/src/Sonarr.Api.V3/System/Backup/BackupController.cs
@@ -40,7 +40,6 @@ namespace Sonarr.Api.V3.System.Backup
{
Id = GetBackupId(b),
Name = b.Name,
- Path = $"/backup/{b.Type.ToString().ToLower()}/{b.Name}",
Size = b.Size,
Type = b.Type,
Time = b.Time
diff --git a/src/Sonarr.Api.V3/System/Backup/BackupResource.cs b/src/Sonarr.Api.V3/System/Backup/BackupResource.cs
index 25ff1f2bf..1838b1c2b 100644
--- a/src/Sonarr.Api.V3/System/Backup/BackupResource.cs
+++ b/src/Sonarr.Api.V3/System/Backup/BackupResource.cs
@@ -7,7 +7,6 @@ namespace Sonarr.Api.V3.System.Backup
public class BackupResource : RestResource
{
public string Name { get; set; }
- public string Path { get; set; }
public BackupType Type { get; set; }
public long Size { get; set; }
public DateTime Time { get; set; }
diff --git a/src/Sonarr.Api.V3/System/SystemController.cs b/src/Sonarr.Api.V3/System/SystemController.cs
index 80d177cfb..7c2fa130a 100644
--- a/src/Sonarr.Api.V3/System/SystemController.cs
+++ b/src/Sonarr.Api.V3/System/SystemController.cs
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Internal;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
+using NzbDrone.Core.Backup;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Lifecycle;
@@ -27,6 +28,7 @@ namespace Sonarr.Api.V3.System
private readonly EndpointDataSource _endpointData;
private readonly DfaGraphWriter _graphWriter;
private readonly DuplicateEndpointDetector _detector;
+ private readonly IBackupService _backupService;
public SystemController(IAppFolderInfo appFolderInfo,
IRuntimeInfo runtimeInfo,
@@ -38,7 +40,8 @@ namespace Sonarr.Api.V3.System
IDeploymentInfoProvider deploymentInfoProvider,
EndpointDataSource endpoints,
DfaGraphWriter graphWriter,
- DuplicateEndpointDetector detector)
+ DuplicateEndpointDetector detector,
+ IBackupService backupService)
{
_appFolderInfo = appFolderInfo;
_runtimeInfo = runtimeInfo;
@@ -51,6 +54,7 @@ namespace Sonarr.Api.V3.System
_endpointData = endpoints;
_graphWriter = graphWriter;
_detector = detector;
+ _backupService = backupService;
}
[HttpGet("status")]
@@ -69,6 +73,7 @@ namespace Sonarr.Api.V3.System
IsUserInteractive = RuntimeInfo.IsUserInteractive,
StartupPath = _appFolderInfo.StartUpFolder,
AppData = _appFolderInfo.GetAppDataPath(),
+ BackupFolder = _backupService.GetBackupFolder(),
OsName = _osInfo.Name,
OsVersion = _osInfo.Version,
IsNetCore = true,
diff --git a/src/Sonarr.Api.V3/System/SystemResource.cs b/src/Sonarr.Api.V3/System/SystemResource.cs
index 53f35921e..2210b9209 100644
--- a/src/Sonarr.Api.V3/System/SystemResource.cs
+++ b/src/Sonarr.Api.V3/System/SystemResource.cs
@@ -18,6 +18,7 @@ namespace Sonarr.Api.V3.System
public bool IsUserInteractive { get; set; }
public string StartupPath { get; set; }
public string AppData { get; set; }
+ public string BackupFolder { get; set; }
public string OsName { get; set; }
public string OsVersion { get; set; }
public bool IsNetCore { get; set; }
diff --git a/src/Sonarr.Http/Frontend/Mappers/BackupFileMapper.cs b/src/Sonarr.Http/Frontend/Mappers/BackupFileMapper.cs
deleted file mode 100644
index 17027aeab..000000000
--- a/src/Sonarr.Http/Frontend/Mappers/BackupFileMapper.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.IO;
-using NLog;
-using NzbDrone.Common.Disk;
-using NzbDrone.Core.Backup;
-
-namespace Sonarr.Http.Frontend.Mappers
-{
- public class BackupFileMapper : StaticResourceMapperBase
- {
- private readonly IBackupService _backupService;
-
- public BackupFileMapper(IBackupService backupService, IDiskProvider diskProvider, Logger logger)
- : base(diskProvider, logger)
- {
- _backupService = backupService;
- }
-
- public override string Map(string resourceUrl)
- {
- var path = resourceUrl.Replace("/backup/", "").Replace('/', Path.DirectorySeparatorChar);
-
- return Path.Combine(_backupService.GetBackupFolder(), path);
- }
-
- public override bool CanHandle(string resourceUrl)
- {
- return resourceUrl.StartsWith("/backup/") && BackupService.BackupFileRegex.IsMatch(resourceUrl);
- }
- }
-}