Speed
diff --git a/src/views/Base/RunningJobs/__snapshots__/RunningJobs.test.js.snap b/src/views/Base/RunningJobs/__snapshots__/RunningJobs.test.js.snap
index 7c8fdc9e9..5d758161c 100644
--- a/src/views/Base/RunningJobs/__snapshots__/RunningJobs.test.js.snap
+++ b/src/views/Base/RunningJobs/__snapshots__/RunningJobs.test.js.snap
@@ -14,7 +14,7 @@ exports[`Running Jobs renders should match snapshot 1`] = `
}
>
-
- clickHandler(e, item)} id={"file" + itemIdx}>
- {Name}
-
-
+ clickHandler(e, item)}>
+ {" "}{Name}
{Size === -1 ? "-" : formatBytes(Size, 2)}
{modTime.toLocaleDateString()}
diff --git a/src/views/Explorer/FilesView/FilesView.js b/src/views/Explorer/FilesView/FilesView.js
index 7318432cc..3365ad2ac 100644
--- a/src/views/Explorer/FilesView/FilesView.js
+++ b/src/views/Explorer/FilesView/FilesView.js
@@ -1,15 +1,21 @@
import React from "react";
import axiosInstance from "../../../utils/API/API";
-import {Alert, Button, Col, Container, Row, Spinner, Table} from "reactstrap";
+import {Alert, Col, Container, Row, Spinner, Table} from "reactstrap";
import {DropTarget} from "react-dnd";
import FileComponent from "./FileComponent";
import {ItemTypes} from "./Constants";
import {toast} from "react-toastify";
-import {addColonAtLast, changeListVisibility, changeSearchFilter, isEmpty} from "../../../utils/Tools";
+import {
+ addColonAtLast,
+ changeListVisibility,
+ changeSearchFilter,
+ getSortCompareFunction,
+ isEmpty
+} from "../../../utils/Tools";
import {connect} from "react-redux";
import {getFiles} from "../../../actions/explorerActions";
import {compose} from "redux";
-import {changePath, navigateUp} from "../../../actions/explorerStateActions";
+import {changePath, changeSortFilter, navigateUp} from "../../../actions/explorerStateActions";
import LinkShareModal from "../../Base/LinkShareModal/LinkShareModal";
import ScrollableDiv from "../../Base/ScrollableDiv/ScrollableDiv";
import {FILES_VIEW_HEIGHT} from "../../../utils/Constants";
@@ -90,21 +96,21 @@ function renderOverlay() {
* */
// Provides the up button view in the files view
-function UpButtonComponent({upButtonHandle, gridMode}) {
- if (gridMode === "card") {
- return (
-
- upButtonHandle()}>Go Up
-
- )
- } else {
- return (
- upButtonHandle()} className={"pointer-cursor"}>
-
- Go Up...
- );
- }
-}
+// function UpButtonComponent({upButtonHandle, gridMode}) {
+// if (gridMode === "card") {
+// return (
+//
+// upButtonHandle()}>Go Up
+//
+// )
+// } else {
+// return (
+// upButtonHandle()} className={"pointer-cursor"}>
+//
+// Go Up...
+// );
+// }
+// }
/**
* FilesView component renders files in the file explorer.
@@ -122,6 +128,7 @@ class FilesView extends React.PureComponent {
showLinkShareModal: false,
generatedLink: "",
+
};
this.handleFileClick = this.handleFileClick.bind(this);
this.downloadHandle = this.downloadHandle.bind(this);
@@ -173,7 +180,7 @@ class FilesView extends React.PureComponent {
}
- getFilesList(showLoading = true) {
+ getFilesList() {
const {remoteName, remotePath} = this.props.currentPath;
this.props.getFiles(remoteName, remotePath);
@@ -257,11 +264,11 @@ class FilesView extends React.PureComponent {
updateHandler = () => {
- const {remoteName, remotePath} = this.props.currentPath;
- this.getFilesList(remoteName, remotePath);
+ // const {remoteName, remotePath} = this.props.currentPath;
+ this.getFilesList();
};
- dismissAlert = (e) => {
+ dismissAlert = (_) => {
this.setState({isDownloadProgress: false});
};
@@ -294,41 +301,48 @@ class FilesView extends React.PureComponent {
const {remoteName, remotePath} = this.props.currentPath;
// console.log(fsInfo, files);
if (fsInfo && !isEmpty(fsInfo)) {
- return files.map((item, idx) => {
+ return files.reduce((result, item) => {
let {ID, Name} = item;
- // Using fallback as fileName when the ID is not available (for local file system)
+ // Using fallback as fileName when the ID is not available (especially for local file system)
if (ID === undefined) {
ID = Name;
}
if (item.IsDir === isDir) {
- return (
-
-
-
-
-
+ result.push(
+
+
+
);
}
- return null;
- });
+ return result;
+ }, []);
}
};
+ applySortFilter = (sortFilter) => {
+ const {changeSortFilter, containerID} = this.props;
+
+ if (this.props.sortFilter === sortFilter) {
+ return changeSortFilter(containerID, sortFilter, (this.props.sortFilterAscending !== true));
+ } else {
+ return changeSortFilter(containerID, sortFilter, true);
+ }
+
+ };
+
render() {
const {isLoading, isDownloadProgress, downloadingItems, generatedLink, showLinkShareModal} = this.state;
- const {connectDropTarget, isOver, files, navigateUp, containerID, gridMode, canDrop} = this.props;
+ const {connectDropTarget, isOver, files, gridMode, canDrop, sortFilter, sortFilterAscending} = this.props;
const {remoteName} = this.props.currentPath;
- // console.log(this.props.searchQuery);
-
if (isLoading || !files) {
return ( Loading
);
} else {
@@ -350,9 +364,7 @@ class FilesView extends React.PureComponent {
renderElement = (
-
- navigateUp(containerID)} gridMode={gridMode}/>
-
+
Directories
@@ -376,45 +388,45 @@ class FilesView extends React.PureComponent {
)
} else {
-
-
+ let filterIconClass = "fa fa-lg fa-arrow-down";
+ if(sortFilterAscending){
+ filterIconClass = "fa fa-lg fa-arrow-up";
+ }
renderElement = (
+
-
-
+
- x
- Name
- Size
- Modified
+ this.applySortFilter("name")}>Name {sortFilter === "name" &&
+ }
+ this.applySortFilter("size")}>Size {sortFilter === "size" &&
+ }
+ this.applySortFilter("modified")}>Modified {sortFilter === "modified" &&
+ }
Actions
- navigateUp(containerID)} gridMode={gridMode}/>
{files.length > 0 ? (
-
Directories
{dirComponentMap}
-
- Files
-
-
-
+ Files
{fileComponentMap}
) :
-
Files
}
@@ -468,11 +480,15 @@ FilesView.defaultProps = defaultProps;
const mapStateToProps = (state, ownProps) => {
- const currentPath = state.explorer.currentPaths[ownProps.containerID];
- const visibilityFilter = state.explorer.visibilityFilters[ownProps.containerID];
- const gridMode = state.explorer.gridMode[ownProps.containerID];
- const searchQuery = state.explorer.searchQueries[ownProps.containerID];
- const loadImages = state.explorer.loadImages[ownProps.containerID];
+ const {currentPaths, visibilityFilters, gridMode, searchQueries, loadImages, sortFilters, sortFiltersAscending} = state.explorer;
+ const {containerID} = ownProps;
+ const currentPath = currentPaths[containerID];
+ const visibilityFilter = visibilityFilters[containerID];
+ const mgridMode = gridMode[containerID];
+ const searchQuery = searchQueries[containerID];
+ const mloadImages = loadImages[containerID];
+ const sortFilter = sortFilters[containerID];
+ const sortFilterAscending = sortFiltersAscending[containerID];
let fsInfo = {};
const {remoteName, remotePath} = currentPath;
@@ -481,7 +497,6 @@ const mapStateToProps = (state, ownProps) => {
const tempRemoteName = remoteName.split(':')[0];
if (state.remote.configs[tempRemoteName])
-
fsInfo = state.remote.configs[tempRemoteName];
}
@@ -492,29 +507,36 @@ const mapStateToProps = (state, ownProps) => {
if (files) {
files = files.files;
// Filter according to visibility filters
- if (visibilityFilter) {
+ if (visibilityFilter && visibilityFilter !== "") {
files = changeListVisibility(files, visibilityFilter);
}
- //Filter according to search query, if ny
+ //Filter according to search query, if any
if (searchQuery) {
files = changeSearchFilter(files, searchQuery);
}
+ files.sort(getSortCompareFunction(sortFilter, sortFilterAscending));
+
}
+ // Sort the files
+
+
return {
files,
currentPath,
fsInfo,
- gridMode,
+ gridMode: mgridMode,
searchQuery,
- loadImages
+ loadImages: mloadImages,
+ sortFilter,
+ sortFilterAscending
}
};
export default compose(
connect(
- mapStateToProps, {getFiles, navigateUp, changePath}
+ mapStateToProps, {getFiles, navigateUp, changePath, changeSortFilter}
),
DropTarget(ItemTypes.FILECOMPONENT, filesTarget, collect)
)(FilesView)
diff --git a/src/views/Explorer/RemoteExplorer/RemoteExplorer.js b/src/views/Explorer/RemoteExplorer/RemoteExplorer.js
index 1fb2d6dcf..f45d1dde7 100644
--- a/src/views/Explorer/RemoteExplorer/RemoteExplorer.js
+++ b/src/views/Explorer/RemoteExplorer/RemoteExplorer.js
@@ -1,106 +1,107 @@
import React from 'react';
-import {Card, CardBody, CardHeader} from "reactstrap";
-import RemotesList from "../RemotesList";
+import {Card, CardBody, Container} from "reactstrap";
import FilesView from "../FilesView/FilesView";
import {addColonAtLast} from "../../../utils/Tools";
import {connect} from "react-redux";
import * as PropTypes from 'prop-types';
import {
- changePath,
- changeRemoteName,
- changeRemotePath,
- createPath,
- navigateBack,
- navigateFwd,
- navigateUp
+ changePath,
+ changeRemoteName,
+ changeRemotePath,
+ createPath,
+ navigateBack,
+ navigateFwd,
+ navigateUp
} from "../../../actions/explorerStateActions";
import FileOperations from "../../Base/FileOperations/FileOperations";
import {PROP_CURRENT_PATH, PROP_FS_INFO} from "../../../utils/RclonePropTypes";
import ErrorBoundary from "../../../ErrorHandling/ErrorBoundary";
+import RemotesList from "../RemotesList";
class RemoteExplorer extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- remoteNameTemp: ""
- };
-
- this.updateRemoteName = this.updateRemoteName.bind(this);
- this.updateRemotePath = this.updateRemotePath.bind(this);
- }
-
-
- updateRemoteName(remoteName) {
- this.setState({remoteNameTemp: remoteName});
- }
-
- updateRemotePath(newRemotePath, IsDir, IsBucket) {
- const {remoteName} = this.props.currentPath;
-
- let updateRemoteName = "";
- let updateRemotePath = "";
-
- if (IsBucket) {
- updateRemoteName = addColonAtLast(remoteName) + newRemotePath;
- updateRemotePath = "";
-
- } else if (IsDir) {
- updateRemoteName = remoteName;
- updateRemotePath = newRemotePath;
- }
- this.props.changePath(this.props.containerID, updateRemoteName, updateRemotePath);
- }
-
- render() {
-
-
- const {remoteName} = this.props.currentPath;
- const {containerID, distractionFreeMode} = this.props;
-
- const isValidPath = remoteName && remoteName !== "";
-
- return (
-
- {/*Render remotes array*/}
- {(!distractionFreeMode) &&
-
- Remotes
-
-
-
-
- }
-
- {/*Render the files in the selected remote*/}
- {isValidPath &&
-
-
-
-
-
-
- }
-
-
- );
-
- }
+ constructor(props) {
+ super(props);
+ this.state = {
+ remoteNameTemp: ""
+ };
+
+ this.updateRemoteName = this.updateRemoteName.bind(this);
+ this.updateRemotePath = this.updateRemotePath.bind(this);
+ }
+
+
+ updateRemoteName(remoteName) {
+ this.setState({remoteNameTemp: remoteName});
+ }
+
+ updateRemotePath(newRemotePath, IsDir, IsBucket) {
+ const {remoteName} = this.props.currentPath;
+
+ let updateRemoteName = "";
+ let updateRemotePath = "";
+
+ if (IsBucket) {
+ updateRemoteName = addColonAtLast(remoteName) + newRemotePath;
+ updateRemotePath = "";
+
+ } else if (IsDir) {
+ updateRemoteName = remoteName;
+ updateRemotePath = newRemotePath;
+ }
+ this.props.changePath(this.props.containerID, updateRemoteName, updateRemotePath);
+ }
+
+ render() {
+
+
+ const {remoteName} = this.props.currentPath;
+ const {containerID, className} = this.props;
+
+ const isValidPath = remoteName && remoteName !== "";
+
+ return (
+
+
+
+
+
+
+ {isValidPath ? (
+ <>
+
+
+ >
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+ );
+
+
+ }
}
const propTypes = {
- containerID: PropTypes.string.isRequired,
- createPath: PropTypes.func.isRequired,
- currentPath: PROP_CURRENT_PATH,
- fsInfo: PROP_FS_INFO,
- hasError: PropTypes.bool,
- distractionFreeMode: PropTypes.bool.isRequired
+ containerID: PropTypes.string.isRequired,
+ createPath: PropTypes.func.isRequired,
+ currentPath: PROP_CURRENT_PATH,
+ fsInfo: PROP_FS_INFO,
+ hasError: PropTypes.bool,
+ distractionFreeMode: PropTypes.bool.isRequired,
+ className: PropTypes.string
};
@@ -108,35 +109,36 @@ const defaultProps = {};
const mapStateToProps = (state, ownProps) => {
- const currentPath = state.explorer.currentPaths[ownProps.containerID];
- let fsInfo = {};
+ const currentPath = state.explorer.currentPaths[ownProps.containerID];
+ let fsInfo = {};
+
+ const {remoteName} = currentPath;
- const {remoteName} = currentPath;
+ if (currentPath && state.remote.configs) {
- if (currentPath && state.remote.configs) {
+ const tempRemoteName = remoteName.split(':')[0];
+ if (state.remote.configs[tempRemoteName])
- const tempRemoteName = remoteName.split(':')[0];
- if (state.remote.configs[tempRemoteName])
+ fsInfo = state.remote.configs[tempRemoteName];
+ }
+ return {
+ configs: state.remote.configs,
+ hasError: state.remote.hasError,
+ error: state.remote.error,
+ currentPath,
+ fsInfo,
+ }
- fsInfo = state.remote.configs[tempRemoteName];
- }
- return {
- configs: state.remote.configs,
- hasError: state.remote.hasError,
- error: state.remote.error,
- currentPath: state.explorer.currentPaths[ownProps.containerID],
- fsInfo
- }
};
RemoteExplorer.propTypes = propTypes;
RemoteExplorer.defaultProps = defaultProps;
export default connect(
- mapStateToProps,
- {
- createPath, changePath,
- changeRemoteName, changeRemotePath, navigateUp,
- navigateBack, navigateFwd
- }
+ mapStateToProps,
+ {
+ createPath, changePath,
+ changeRemoteName, changeRemotePath, navigateUp,
+ navigateBack, navigateFwd
+ }
)(RemoteExplorer);
diff --git a/src/views/Explorer/RemoteExplorer/__snapshots__/RemoteExplorer.test.js.snap b/src/views/Explorer/RemoteExplorer/__snapshots__/RemoteExplorer.test.js.snap
index ad8145ca8..b00117007 100644
--- a/src/views/Explorer/RemoteExplorer/__snapshots__/RemoteExplorer.test.js.snap
+++ b/src/views/Explorer/RemoteExplorer/__snapshots__/RemoteExplorer.test.js.snap
@@ -5,36 +5,20 @@ exports[`Remote Explorer renders should match snapshot 1`] = `
-
- Remotes
-
-
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/src/views/Explorer/RemoteExplorerLayout/RemoteExplorerLayout.js b/src/views/Explorer/RemoteExplorerLayout/RemoteExplorerLayout.js
index d4376df51..866021ecc 100644
--- a/src/views/Explorer/RemoteExplorerLayout/RemoteExplorerLayout.js
+++ b/src/views/Explorer/RemoteExplorerLayout/RemoteExplorerLayout.js
@@ -1,5 +1,5 @@
import React from "react";
-import {Button, Card, CardBody, CardHeader, Col, Row} from "reactstrap";
+import {Button, Col, Row} from "reactstrap";
import RemoteExplorer from "../RemoteExplorer";
import HTML5Backend from "react-dnd-html5-backend";
@@ -11,35 +11,20 @@ import * as PropTypes from 'prop-types';
import {changeDistractionFreeMode, changeNumCols} from "../../../actions/explorerActions";
import ErrorBoundary from "../../../ErrorHandling/ErrorBoundary";
+import singlePaneImg from '../../../assets/img/single-pane.png';
+import doublePaneImg from '../../../assets/img/double-pane1.png';
+import triplePaneImg from '../../../assets/img/triple-pane.png';
+import TabsLayout from "../TabsLayout/TabsLayout";
-function RemoteExplorerList({cols, distractionFreeMode}) {
- let remoteExplorers = [];
- const lgSize = 12 / cols;
- for (let i = 0; i < cols; i++) {
-
- remoteExplorers.push((
-
-
-
-
- ));
- }
- return remoteExplorers;
-}
class RemoteExplorerLayout extends React.Component {
- constructor(props) {
- super(props);
- this.changeLayout = this.changeLayout.bind(this);
- }
-
changeLayout = (nos, mode) => {
const {changeNumCols} = this.props;
- // console.log("changing layout");
- if (mode === "side" && nos !== changeNumCols) {
- changeNumCols(nos);
+ // Check if the current layout is not same as previous
+ if(nos !== changeNumCols){
+ changeNumCols(nos, mode);
}
};
@@ -48,24 +33,55 @@ class RemoteExplorerLayout extends React.Component {
const {numCols, changeNumCols} = this.props;
if (numCols < 1) {
- changeNumCols(1);
+ changeNumCols(1, "horizontal");
}
}
- toggleDistractionFreeMode = (e) => {
- const {distractionFreeMode, changeDistractionFreeMode} = this.props;
- // this.setState((prevState) => ({
- // distractionFreeMode: !prevState.distractionFreeMode
- // }));
- changeDistractionFreeMode(!distractionFreeMode);
-
+ toggleDistractionFreeMode = (_) => {
+ const {distractionFreeMode, changeDistractionFreeMode} = this.props;
+ // this.setState((prevState) => ({
+ // distractionFreeMode: !prevState.distractionFreeMode
+ // }));
+ changeDistractionFreeMode(!distractionFreeMode);
+
+ };
+
+ Panes = ({numCols, activeRemoteContainerID, distractionFreeMode, containers}) => {
+ let returnData = [];
+ const lgSize = 12 / numCols;
+ for (let pane = 0; pane < numCols; pane++) {
+ returnData.push((
+
+
+
+
+
+
+ {
+ containers.map(({ID, paneID}) => {
+ if (paneID === pane) {
+ return ()
+ } else {
+ return null;
+ }
+ })
+ }
+ {/*{activeRemoteContainerID && activeRemoteContainerID[pane] && activeRemoteContainerID[pane] !== "" &&*/}
+ {/*}*/}
+
+
+ ))
+ }
+ return returnData;
};
render() {
/*Divide the 12 bootstrap columns to fit number of explorers*/
- const {numCols, backStacks, distractionFreeMode} = this.props;
-
+ const {numCols, distractionFreeMode, activeRemoteContainerID, containers} = this.props;
return (
@@ -76,46 +92,43 @@ class RemoteExplorerLayout extends React.Component {
}
{(!distractionFreeMode) &&
-
-
-
-
- Choose Layout
-
-
- this.changeLayout(1, "side")}>
- 1 - side by side
-
- this.changeLayout(2, "side")}>
- 2 - side by side
-
- this.changeLayout(3, "side")}>
- 3 - side by side
-
- this.changeLayout(4, "side")}>
- 4 - side by side
-
-
-
- {/*4 - grid */}
-
-
+
+
+
+
+ Choose Layout: {" "}
+
+
+ this.changeLayout(1, "horizontal")}>
+
+
+ this.changeLayout(2, "horizontal")}>
+
+
+ this.changeLayout(3, "horizontal")}>
+
+
+
+ Full Screen
+
+ {/*4 - grid */}
+
}
-
-
+
-
-
);
}
@@ -124,7 +137,10 @@ class RemoteExplorerLayout extends React.Component {
const mapStateToProps = (state) => ({
backStacks: state.explorer.backStacks,
numCols: state.remote.numCols,
- distractionFreeMode: state.remote.distractionFreeMode
+ distractionFreeMode: state.remote.distractionFreeMode,
+ splitMode: state.remote.splitMode,
+ activeRemoteContainerID: state.remote.activeRemoteContainerID,
+ containers: state.remote.containers,
});
RemoteExplorerLayout.propTypes = {
@@ -137,4 +153,4 @@ RemoteExplorerLayout.propTypes = {
export default compose(
connect(mapStateToProps, {createPath, changeNumCols, changeDistractionFreeMode}),
DragDropContext(HTML5Backend)
-)(RemoteExplorerLayout);
\ No newline at end of file
+)(RemoteExplorerLayout);
diff --git a/src/views/Explorer/RemoteExplorerLayout/__snapshots__/RemoteExplorerLayout.test.js.snap b/src/views/Explorer/RemoteExplorerLayout/__snapshots__/RemoteExplorerLayout.test.js.snap
index 8916ab654..e63a87322 100644
--- a/src/views/Explorer/RemoteExplorerLayout/__snapshots__/RemoteExplorerLayout.test.js.snap
+++ b/src/views/Explorer/RemoteExplorerLayout/__snapshots__/RemoteExplorerLayout.test.js.snap
@@ -6,6 +6,7 @@ exports[`Remote Explorer Layout renders should match snapshot 1`] = `
data-test="remoteExplorerLayout"
>
-
-
- Choose Layout
-
-
-
- 1 - side by side
-
-
- 2 - side by side
-
-
- 3 - side by side
-
-
- 4 - side by side
-
-
-
-
-
-
+ Choose Layout:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Full Screen
+
`;
diff --git a/src/views/Explorer/RemotesList/RemoteListAutoSuggest.js b/src/views/Explorer/RemotesList/RemoteListAutoSuggest.js
index 5236910df..6fd18a61a 100644
--- a/src/views/Explorer/RemotesList/RemoteListAutoSuggest.js
+++ b/src/views/Explorer/RemotesList/RemoteListAutoSuggest.js
@@ -81,6 +81,7 @@ class RemoteListAutoSuggest extends React.Component {
renderSuggestion={renderSuggestion}
highlightFirstSuggestion={true}
inputProps={inputProps}
+ style={{width:"100%"}}
/>
);
}
diff --git a/src/views/Explorer/RemotesList/RemotesList.js b/src/views/Explorer/RemotesList/RemotesList.js
index 6a20558b1..2971b4be1 100644
--- a/src/views/Explorer/RemotesList/RemotesList.js
+++ b/src/views/Explorer/RemotesList/RemotesList.js
@@ -4,7 +4,7 @@ import {connect} from "react-redux";
import {getFsInfo, getRemoteNames} from "../../../actions/explorerActions";
import PropTypes from 'prop-types'
import {changeRemoteName} from "../../../actions/explorerStateActions";
-import {Button, Col, Form, Row} from "reactstrap";
+import {Button, Col, Form} from "reactstrap";
import {PROP_CURRENT_PATH} from "../../../utils/RclonePropTypes";
class RemotesList extends React.Component {
@@ -72,19 +72,18 @@ class RemotesList extends React.Component {
} else {
return (
-
);
@@ -104,9 +103,7 @@ const propTypes = {
error: PropTypes.object,
hasError: PropTypes.bool,
containerID: PropTypes.string.isRequired,
-
currentPath: PROP_CURRENT_PATH
-
};
diff --git a/src/views/Explorer/TabsLayout/TabsLayout.js b/src/views/Explorer/TabsLayout/TabsLayout.js
new file mode 100644
index 000000000..7dd103ffc
--- /dev/null
+++ b/src/views/Explorer/TabsLayout/TabsLayout.js
@@ -0,0 +1,61 @@
+import React from 'react';
+import {Button, Nav, NavItem, NavLink} from "reactstrap";
+import {connect} from "react-redux";
+import {addRemoteContainer, changeActiveRemoteContainer, removeRemoteContainer} from "../../../actions/explorerActions";
+
+function TabsLayout(props) {
+ const {addRemoteContainer, removeRemoteContainer, changeActiveRemoteContainer, activeRemoteContainerID} = props;
+ const {containers, currentPaths, paneID: currentPaneID} = props;
+ const activeContainerIDInPane = activeRemoteContainerID ? activeRemoteContainerID[currentPaneID] : "";
+ return (
+ {
+ containers.map(({ID, paneID}) => {
+ if (currentPaneID === paneID) {
+ const isActiveTab = ID === activeContainerIDInPane;
+ return (
+
+ changeActiveRemoteContainer(ID, paneID)}>
+
+
+ {currentPaths[ID] && currentPaths[ID].remoteName !== "" ? currentPaths[ID].remoteName : "Open New"}
+
+ {
+ e.stopPropagation();
+ removeRemoteContainer(ID, paneID)
+ }}>
+
+
+
+ )
+ }
+ return null;
+ })
+ }
+
+ addRemoteContainer(currentPaneID)}>
+
+
+
+
+ )
+}
+
+const mapStateToProps = (state, _) => {
+ return {
+ containers: state.remote.containers,
+ numContainers: state.remote.numContainers,
+ currentPaths: state.explorer.currentPaths,
+ activeRemoteContainerID: state.remote.activeRemoteContainerID
+ };
+};
+
+
+export default connect(
+ mapStateToProps,
+ {
+ addRemoteContainer, removeRemoteContainer, changeActiveRemoteContainer
+ }
+)(TabsLayout);
+
diff --git a/src/views/Home/Home.js b/src/views/Home/Home.js
index 2c9fe0527..528caabab 100644
--- a/src/views/Home/Home.js
+++ b/src/views/Home/Home.js
@@ -15,15 +15,11 @@ class Home extends React.Component {
const ipAddress = localStorage.getItem(IP_ADDRESS_KEY);
return (
-
Welcome to Rclone dashboard.
-
Begin by creating a new remote config from the left sidebar.
-
-
-
+
-
+
diff --git a/src/views/Home/__snapshots__/Home.test.js.snap b/src/views/Home/__snapshots__/Home.test.js.snap
index b7e851dc3..9ed89f648 100644
--- a/src/views/Home/__snapshots__/Home.test.js.snap
+++ b/src/views/Home/__snapshots__/Home.test.js.snap
@@ -4,12 +4,6 @@ exports[`Home Component renders should match snapshot 1`] = `
-
- Welcome to Rclone dashboard.
-
-
- Begin by creating a new remote config from the left sidebar.
-
{
this.setState({
username: e.target.value,
- connectionSuccess: false
});
};
changePassword = e => {
this.setState({
password: e.target.value,
- connectionSuccess: false
})
};
@@ -79,7 +77,6 @@ class Login extends Component {
this.setState({
ipAddress: e.target.value,
- connectionSuccess: false
});
};
@@ -89,59 +86,69 @@ class Login extends Component {
onSubmit = e => {
- if (e)
- e.preventDefault();
-
- const {ipAddress, username, password} = this.state;
-
- Promise.all([
- changeUserNamePassword(username, password),
- changeIPAddress(ipAddress)
- ]).then(() => {
- this.redirectToDashboard()
- });
-
- };
-
- checkConnection = (e) => {
- e.preventDefault();
-
- // Set the localStorage parameters temporarily.
- const {ipAddress, username, password} = this.state;
- const {changeUserNamePassword, changeIPAddress} = this.props;
-
- Promise.all([
- changeUserNamePassword(username, password),
- changeIPAddress(ipAddress)
- ]).then(() => {
- axiosInstance.post(urls.noopAuth).then((data) => {
- console.log("Connection successful.");
- this.setState({
- connectionSuccess: true,
- error: ""
- })
- }, (error) => {
- console.log(error);
- this.setState({
- connectionSuccess: false,
- error: "Error connecting. Please check username password and verify if rclone is working at the specified IP."
- })
- })
- })
-
-
- };
-
- componentDidMount() {
- localStorage.clear();
- this.props.signOut();
-
-
- let url_string = window.location.href;
- let url = new URL(url_string);
- let loginToken = url.searchParams.get("login_token");
- let ipAddress = this.state.ipAddress;
- if (url.searchParams.get("ip_address")) {
+ if (e)
+ e.preventDefault();
+
+ const {ipAddress, username, password} = this.state;
+ const {changeUserNamePassword, changeIPAddress} = this.props;
+
+
+ Promise.all([
+ changeUserNamePassword(username, password),
+ changeIPAddress(ipAddress)
+ ]).then(() => {
+ axiosInstance.post(urls.noopAuth).then((data) => {
+ console.log("Connection successful.");
+ this.redirectToDashboard();
+ }, (error) => {
+ console.log(error);
+ this.setState({
+ error: "Error connecting. Please check username password and verify if rclone is working at the specified IP."
+ })
+ })
+
+ });
+
+ };
+
+ // checkConnection = (e) => {
+ // e.preventDefault();
+ //
+ // // Set the localStorage parameters temporarily.
+ // const {ipAddress, username, password} = this.state;
+ // const {changeUserNamePassword, changeIPAddress} = this.props;
+ //
+ // Promise.all([
+ // changeUserNamePassword(username, password),
+ // changeIPAddress(ipAddress)
+ // ]).then(() => {
+ // axiosInstance.post(urls.noopAuth).then((data) => {
+ // console.log("Connection successful.");
+ // this.setState({
+ // connectionSuccess: true,
+ // error: ""
+ // })
+ // }, (error) => {
+ // console.log(error);
+ // this.setState({
+ // connectionSuccess: false,
+ // error: "Error connecting. Please check username password and verify if rclone is working at the specified IP."
+ // })
+ // })
+ // })
+ //
+ //
+ // };
+
+ componentDidMount() {
+ localStorage.clear();
+ this.props.signOut();
+
+ let url_string = window.location.href;
+ let url = new URL(url_string);
+ let loginToken = url.searchParams.get("login_token");
+ let ipAddress = this.state.ipAddress;
+ if (url.searchParams.get("ip_address")) {
ipAddress = url.searchParams.get("ip_address");
}
// console.log(loginToken);
@@ -158,8 +165,9 @@ class Login extends Component {
}
+
render() {
- const {username, password, ipAddress, connectionSuccess, error} = this.state;
+ const {username, password, ipAddress, error} = this.state;
return (
@@ -169,27 +177,25 @@ class Login extends Component {
-
-
+
-
-
+
diff --git a/src/views/Pages/Login/__snapshots__/Login.test.js.snap b/src/views/Pages/Login/__snapshots__/Login.test.js.snap
index f5b8be83c..fbc9941de 100644
--- a/src/views/Pages/Login/__snapshots__/Login.test.js.snap
+++ b/src/views/Pages/Login/__snapshots__/Login.test.js.snap
@@ -160,42 +160,18 @@ exports[`Login Layout renders should match snapshot 1`] = `
className="px-4"
color="primary"
data-testid="LoginForm-BtnLogin"
- disabled={true}
tag="button"
+ type="submit"
>
Login
-
-
- Verify
-
-
-
+
diff --git a/src/views/RemoteManagement/NewDrive/NewDrive.js b/src/views/RemoteManagement/NewDrive/NewDrive.js
index 8b2430afe..6be562b7b 100644
--- a/src/views/RemoteManagement/NewDrive/NewDrive.js
+++ b/src/views/RemoteManagement/NewDrive/NewDrive.js
@@ -1,18 +1,5 @@
import React from 'react';
-import {
- Button,
- Card,
- CardBody,
- CardFooter,
- CardHeader,
- Col,
- Collapse,
- Form,
- FormFeedback,
- FormGroup,
- Input,
- Label
-} from "reactstrap";
+import {Button, Card, CardBody, Col, Collapse, Container, FormFeedback, FormGroup, Input, Label, Row} from "reactstrap";
// import {config} from "./config.js";
import NewDriveAuthModal from "../../Base/NewDriveAuthModal";
import axiosInstance from "../../../utils/API/API";
@@ -192,6 +179,8 @@ class NewDrive extends React.Component {
optionTypes: {},
isValid: {},
+ currentStepNumber: 1
+
};
this.configCheckInterval = null;
// console.log("Params", this.props.match.params);
@@ -428,7 +417,7 @@ class NewDrive extends React.Component {
* Validate form and submit request.
* */
async handleSubmit(e) {
- e.preventDefault();
+ e && e.preventDefault();
// console.log("Submitted form");
const {formValues, drivePrefix} = this.state;
@@ -503,13 +492,13 @@ class NewDrive extends React.Component {
}
}
} else {
- if (!this.state.colSetup) {
- this.openSetupDrive();
- }
+ // if (!this.state.colSetup) {
+ // this.openSetupDrive();
+ // }
- if (this.state.advancedOptions && !this.state.colAdvanced) {
- this.openAdvancedSettings();
- }
+ // if (this.state.advancedOptions && !this.state.colAdvanced) {
+ // this.openAdvancedSettings();
+ // }
toast.warn(`Check for errors before submitting.`, {
autoClose: false
});
@@ -530,7 +519,6 @@ class NewDrive extends React.Component {
* */
changeName = e => {
const {driveNameIsEditable} = this.state;
- console.log("changeName");
if (driveNameIsEditable) {
const value = e.target.value;
@@ -610,113 +598,194 @@ class NewDrive extends React.Component {
this.configCheckInterval = null;
}
+ gotoNextStep = () => {
+ const {currentStepNumber, advancedOptions} = this.state;
+ if((advancedOptions && currentStepNumber === 3) || (!advancedOptions && currentStepNumber === 2)){
+ this.handleSubmit(null);
+ }else{
+ this.setCurrentStep(currentStepNumber + 1);
+ }
+ }
+
+ gotoPrevStep = () => {
+ const {currentStepNumber} = this.state;
+ this.setCurrentStep(currentStepNumber - 1);
+ }
+
+
+ setCurrentStep = (stepNo) => {
+ this.setState({currentStepNumber: stepNo});
+ // const {currentStepNumber, advancedOptions} = this.state;
+ // if((advancedOptions && currentStepNumber === 3) || (!advancedOptions && currentStepNumber === 2)){
+ // this.handleSubmit(null);
+ // }else{
+ // this.setState({currentStepNumber: stepNo});
+ // }
+
+ }
+
+ StepShowCase = ({currentStepNumber}) => {
+ const buttonActiveClassName = "step-active";
+ const stepTitles = [
+ "Set up Remote Config",
+ "Set up Drive",
+ "Advanced Config"
+ ];
+
+ return (
+
+
+ {stepTitles.map((item, idx) => {
+ idx += 1;
+ return (
+
+
+ this.setCurrentStep(idx)}>{idx}
+ {item}
+
+ {idx !== stepTitles.length &&
+
+
+ }
+
+ )
+ })}
+
+
+
+ )
+
+ }
+
+ /* return (
+
+
+ 1
+
+
Shift Created
+
+
+
+
+
+
Shift Created
+
+
+
+
+
Shift Created
+
+
+
+ ) */
+
+
+
render() {
- const {colRconfig, colSetup, colAdvanced, drivePrefix, advancedOptions, driveName, driveNameIsValid} = this.state;
+ const {drivePrefix, advancedOptions, driveName, driveNameIsValid, currentStepNumber} = this.state;
const {providers} = this.props;
- // console.log("config", config);
return (
This 3 step process will guide you through creating a new config. For auto config, leave the
- parameters as is.
-
+ parameters as it is.
+
+
-
-
- Step 1: Remote
- Config
-
-
-
-
-
-
-
-
-
- Select
-
-
-
-
-
-
- Docs are available at {' '}
- Rclone Config
-
-
-
-
-
-
-
-
-
-
-
-
- {/*div for Scrolling to here*/}
- this.setupDriveDiv = el}/>
-
-
- Step 2: Setup Drive
-
-
-
-
-
-
-
-
-
-
-
- Edit Advanced Options
-
-
-
+
+
+
+
+ Select
+
+
+
+
+
+
+ Docs are available at {' '}
+ Rclone Config
+
+
+
+
-
-
-
-
-
- Step 3: Advanced
- (optional)
-
-
-
-
-
-
-
-
-
-
-
-
{
+
+
+
+ {/*div for Scrolling to here*/}
+ {/* this.setupDriveDiv = el}/> */}
+
+
+
+
+
+ Edit Advanced Options
+ Go back
+
+ Next
+
+
+
+
+
+
+
+
+ {/*
+
+ Step 3: Advanced
+ (optional)
+
+
+
+ */}
+
+
+
+
+
+
+
+ Edit Advanced Options
+ Go back
+
+ Next
+
+
+
+
+
+
+
+
+ {/*
{
this.configEndDiv = el
}}>
@@ -724,8 +793,7 @@ class NewDrive extends React.Component {
Create Config
-
-
+
*/}
);
diff --git a/src/views/RemoteManagement/NewDrive/__snapshots__/NewDrive.test.js.snap b/src/views/RemoteManagement/NewDrive/__snapshots__/NewDrive.test.js.snap
index 5abd74a3f..61f1752fd 100644
--- a/src/views/RemoteManagement/NewDrive/__snapshots__/NewDrive.test.js.snap
+++ b/src/views/RemoteManagement/NewDrive/__snapshots__/NewDrive.test.js.snap
@@ -6,161 +6,138 @@ exports[`Remote Explorer renders should match snapshot 1`] = `
>
- This 3 step process will guide you through creating a new config. For auto config, leave the parameters as is.
+ This 3 step process will guide you through creating a new config. For auto config, leave the parameters as it is.
-
+
-
-
-
-
- Step 1:
-
- Remote Config
-
-
-
-
-
+
-
-
+ Select
+
+
-
- Select
-
-
- upload cutoff) files",
- "Hide": 0,
- "IsPassword": false,
- "Name": "disable_checksum",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "bool",
- "Value": null,
- "ValueStr": "false",
- },
- Object {
- "Advanced": true,
- "Default": "",
- "DefaultStr": "",
- "Help": "Custom endpoint for downloads.
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "chunk_size",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "SizeSuffix",
+ "Value": null,
+ "ValueStr": "96M",
+ },
+ Object {
+ "Advanced": true,
+ "Default": false,
+ "DefaultStr": "false",
+ "Help": "Disable checksums for large (> upload cutoff) files",
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "disable_checksum",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "bool",
+ "Value": null,
+ "ValueStr": "false",
+ },
+ Object {
+ "Advanced": true,
+ "Default": "",
+ "DefaultStr": "",
+ "Help": "Custom endpoint for downloads.
This is usually set to a Cloudflare CDN URL as Backblaze offers
free egress for data downloaded through the Cloudflare network.
This is probably only useful for a public bucket.
Leave blank if you want to use the endpoint provided by Backblaze.",
- "Hide": 0,
- "IsPassword": false,
- "Name": "download_url",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "string",
- "Value": null,
- "ValueStr": "",
- },
- Object {
- "Advanced": true,
- "Default": 604800000000000,
- "DefaultStr": "1w",
- "Help": "Time before the authorization token will expire in s or suffix ms|s|m|h|d.
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "download_url",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "string",
+ "Value": null,
+ "ValueStr": "",
+ },
+ Object {
+ "Advanced": true,
+ "Default": 604800000000000,
+ "DefaultStr": "1w",
+ "Help": "Time before the authorization token will expire in s or suffix ms|s|m|h|d.
The duration before the download authorization token will expire.
The minimum value is 1 second. The maximum value is one week.",
- "Hide": 0,
- "IsPassword": false,
- "Name": "download_auth_duration",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "Duration",
- "Value": null,
- "ValueStr": "1w",
- },
- ],
- "Prefix": "b2",
- },
- ]
- }
- value=""
- />
-
-
-
+
+
+
+
-
-
- Docs are available at
-
-
-
- Rclone Config
-
-
-
-
-
+
+
+ Rclone Config
+
+
+
+
+
+
+
-
-
-
-
-
- Step 2:
-
- Setup Drive
-
-
-
-
-
- upload cutoff) files",
- "Hide": 0,
- "IsPassword": false,
- "Name": "disable_checksum",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "bool",
- "Value": null,
- "ValueStr": "false",
- },
- Object {
- "Advanced": true,
- "Default": "",
- "DefaultStr": "",
- "Help": "Custom endpoint for downloads.
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "chunk_size",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "SizeSuffix",
+ "Value": null,
+ "ValueStr": "96M",
+ },
+ Object {
+ "Advanced": true,
+ "Default": false,
+ "DefaultStr": "false",
+ "Help": "Disable checksums for large (> upload cutoff) files",
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "disable_checksum",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "bool",
+ "Value": null,
+ "ValueStr": "false",
+ },
+ Object {
+ "Advanced": true,
+ "Default": "",
+ "DefaultStr": "",
+ "Help": "Custom endpoint for downloads.
This is usually set to a Cloudflare CDN URL as Backblaze offers
free egress for data downloaded through the Cloudflare network.
This is probably only useful for a public bucket.
Leave blank if you want to use the endpoint provided by Backblaze.",
- "Hide": 0,
- "IsPassword": false,
- "Name": "download_url",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "string",
- "Value": null,
- "ValueStr": "",
- },
- Object {
- "Advanced": true,
- "Default": 604800000000000,
- "DefaultStr": "1w",
- "Help": "Time before the authorization token will expire in s or suffix ms|s|m|h|d.
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "download_url",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "string",
+ "Value": null,
+ "ValueStr": "",
+ },
+ Object {
+ "Advanced": true,
+ "Default": 604800000000000,
+ "DefaultStr": "1w",
+ "Help": "Time before the authorization token will expire in s or suffix ms|s|m|h|d.
The duration before the download authorization token will expire.
The minimum value is 1 second. The maximum value is one week.",
- "Hide": 0,
- "IsPassword": false,
- "Name": "download_auth_duration",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "Duration",
- "Value": null,
- "ValueStr": "1w",
- },
- ],
- "Prefix": "b2",
- },
- ]
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "download_auth_duration",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "Duration",
+ "Value": null,
+ "ValueStr": "1w",
+ },
+ ],
+ "Prefix": "b2",
+ },
+ ]
+ }
+ currentValues={Object {}}
+ drivePrefix=""
+ errorsMap={
+ Object {
+ "driveName": "",
}
- currentValues={Object {}}
- drivePrefix=""
- errorsMap={
- Object {
- "driveName": "",
- }
- }
- isValidMap={Object {}}
- loadAdvanced={false}
- />
-
-
+
-
+
+ Edit Advanced Options
+
+
-
-
- Edit Advanced Options
-
-
-
-
-
+ Go back
+
+
+ Next
+
-
-
+
+
+
+
-
-
-
-
- Step 3:
-
- Advanced (optional)
-
-
-
-
-
- upload cutoff) files",
- "Hide": 0,
- "IsPassword": false,
- "Name": "disable_checksum",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "bool",
- "Value": null,
- "ValueStr": "false",
- },
- Object {
- "Advanced": true,
- "Default": "",
- "DefaultStr": "",
- "Help": "Custom endpoint for downloads.
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "chunk_size",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "SizeSuffix",
+ "Value": null,
+ "ValueStr": "96M",
+ },
+ Object {
+ "Advanced": true,
+ "Default": false,
+ "DefaultStr": "false",
+ "Help": "Disable checksums for large (> upload cutoff) files",
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "disable_checksum",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "bool",
+ "Value": null,
+ "ValueStr": "false",
+ },
+ Object {
+ "Advanced": true,
+ "Default": "",
+ "DefaultStr": "",
+ "Help": "Custom endpoint for downloads.
This is usually set to a Cloudflare CDN URL as Backblaze offers
free egress for data downloaded through the Cloudflare network.
This is probably only useful for a public bucket.
Leave blank if you want to use the endpoint provided by Backblaze.",
- "Hide": 0,
- "IsPassword": false,
- "Name": "download_url",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "string",
- "Value": null,
- "ValueStr": "",
- },
- Object {
- "Advanced": true,
- "Default": 604800000000000,
- "DefaultStr": "1w",
- "Help": "Time before the authorization token will expire in s or suffix ms|s|m|h|d.
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "download_url",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "string",
+ "Value": null,
+ "ValueStr": "",
+ },
+ Object {
+ "Advanced": true,
+ "Default": 604800000000000,
+ "DefaultStr": "1w",
+ "Help": "Time before the authorization token will expire in s or suffix ms|s|m|h|d.
The duration before the download authorization token will expire.
The minimum value is 1 second. The maximum value is one week.",
- "Hide": 0,
- "IsPassword": false,
- "Name": "download_auth_duration",
- "NoPrefix": false,
- "Provider": "",
- "Required": false,
- "ShortOpt": "",
- "Type": "Duration",
- "Value": null,
- "ValueStr": "1w",
- },
- ],
- "Prefix": "b2",
- },
- ]
- }
- currentValues={Object {}}
- drivePrefix=""
- errorsMap={
- Object {
- "driveName": "",
- }
+ "Hide": 0,
+ "IsPassword": false,
+ "Name": "download_auth_duration",
+ "NoPrefix": false,
+ "Provider": "",
+ "Required": false,
+ "ShortOpt": "",
+ "Type": "Duration",
+ "Value": null,
+ "ValueStr": "1w",
+ },
+ ],
+ "Prefix": "b2",
+ },
+ ]
+ }
+ currentValues={Object {}}
+ drivePrefix=""
+ errorsMap={
+ Object {
+ "driveName": "",
}
- isValidMap={Object {}}
- loadAdvanced={true}
- />
-
-
-
-
-
-
+
- Clear
-
-
- Create Config
-
-
-
-
+
+
+
+ Edit Advanced Options
+
+
+ Go back
+
+
+ Next
+
+
+
+
+
+
{type}
- Update
+ Update
+ Delete
- Delete
);
}
diff --git a/src/views/RemoteManagement/ShowConfig/ShowConfig.js b/src/views/RemoteManagement/ShowConfig/ShowConfig.js
index 8d6d05d3d..1ae8a358c 100644
--- a/src/views/RemoteManagement/ShowConfig/ShowConfig.js
+++ b/src/views/RemoteManagement/ShowConfig/ShowConfig.js
@@ -32,27 +32,28 @@ class ShowConfig extends React.PureComponent {
return (
-
-
-
+ this.props.history.push("/newdrive")}>
- New Config
+ Create a New Config
+
+
+
-
+
No.
Name
Type
- Update
- Delete
+ Actions
-
+
diff --git a/src/views/RemoteManagement/ShowConfig/__snapshots__/ConfigRow.test.js.snap b/src/views/RemoteManagement/ShowConfig/__snapshots__/ConfigRow.test.js.snap
index 4638d20d7..37eeb3d16 100644
--- a/src/views/RemoteManagement/ShowConfig/__snapshots__/ConfigRow.test.js.snap
+++ b/src/views/RemoteManagement/ShowConfig/__snapshots__/ConfigRow.test.js.snap
@@ -17,15 +17,13 @@ exports[`Config Row renders should match snapshot 1`] = `
Update
-
-
+ >
+
+ Create a New Config
+
+
-
- New Config
-
-
+ />
- Update
-
-
- Delete
+ Actions