ForwardOptionsContainer

master
Tudor Stanciu 2021-05-13 01:30:34 +03:00
parent b9336e1cc6
commit 7b7578173f
13 changed files with 144 additions and 34 deletions

View File

@ -1,8 +1,13 @@
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { CheckCircleOutlineRounded, RemoveRounded } from "@material-ui/icons"; import { CheckCircleOutlineRounded, RemoveRounded } from "@material-ui/icons";
import { LinearProgress } from "@material-ui/core";
const ActiveIcon = ({ active, loading }) => {
if (loading && loading === true) {
return <LinearProgress />;
}
const ActiveIcon = ({ active }) => {
return active && active === true ? ( return active && active === true ? (
<CheckCircleOutlineRounded color="primary" /> <CheckCircleOutlineRounded color="primary" />
) : ( ) : (
@ -11,7 +16,8 @@ const ActiveIcon = ({ active }) => {
}; };
ActiveIcon.propTypes = { ActiveIcon.propTypes = {
active: PropTypes.bool active: PropTypes.bool,
loading: PropTypes.bool
}; };
export default ActiveIcon; export default ActiveIcon;

View File

@ -11,7 +11,7 @@ import ForwardOptionsDialog from "../../session/components/ForwardOptionsDialog"
const ActiveSessionContainer = ({ actions, session, forwards, domain }) => { const ActiveSessionContainer = ({ actions, session, forwards, domain }) => {
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const [optionsDialogOpen, setOptionsDialogOpen] = useState(false); const [optionsDialogOpen, setOptionsDialogOpen] = useState(false);
const [forwardOptions, setForwardOptions] = useState(null); const [focusedForward, setFocusedForward] = useState(null);
useEffect(() => { useEffect(() => {
actions.loadActiveSession(); actions.loadActiveSession();
@ -23,18 +23,20 @@ const ActiveSessionContainer = ({ actions, session, forwards, domain }) => {
if (expand) actions.loadSessionForwards(session.sessionId); if (expand) actions.loadSessionForwards(session.sessionId);
}; };
const handleOptionsDialogOpen = (options) => () => { const handleOptionsDialogOpen = forward => () => {
setForwardOptions(options); setFocusedForward(forward);
setOptionsDialogOpen(true); setOptionsDialogOpen(true);
}; };
const handleOptionsDialogClose = () => { const handleOptionsDialogClose = () => {
setOptionsDialogOpen(false); setOptionsDialogOpen(false);
setForwardOptions(null); setFocusedForward(null);
}; };
const handleForwardClick = (forward) => (event) => { const handleForwardClick = forward => event => {
const url = `${domain.scheme}://${domain.name}${forward.from}${forward.suffix || ""}`; const url = `${domain.scheme}://${domain.name}${
forward.from
}${forward.suffix || ""}`;
window.open(url, "_blank"); window.open(url, "_blank");
event.preventDefault(); event.preventDefault();
}; };
@ -52,7 +54,7 @@ const ActiveSessionContainer = ({ actions, session, forwards, domain }) => {
<ForwardOptionsDialog <ForwardOptionsDialog
open={optionsDialogOpen} open={optionsDialogOpen}
handleClose={handleOptionsDialogClose} handleClose={handleOptionsDialogClose}
options={forwardOptions} forward={focusedForward}
/> />
</> </>
); );

View File

@ -3,7 +3,7 @@ import api from "./api";
import { sendHttpRequest } from "../../redux/actions/httpActions"; import { sendHttpRequest } from "../../redux/actions/httpActions";
export function loadServerSessions() { export function loadServerSessions() {
return async function (dispatch) { return async function(dispatch) {
try { try {
dispatch({ type: types.LOAD_SERVER_SESSIONS_STARTED }); dispatch({ type: types.LOAD_SERVER_SESSIONS_STARTED });
const data = await dispatch(sendHttpRequest(api.getServerSessions())); const data = await dispatch(sendHttpRequest(api.getServerSessions()));
@ -15,7 +15,7 @@ export function loadServerSessions() {
} }
export function loadSessionForwards(sessionId) { export function loadSessionForwards(sessionId) {
return async function (dispatch, getState) { return async function(dispatch, getState) {
try { try {
const forwards = getState().forwards[sessionId]; const forwards = getState().forwards[sessionId];
if (forwards && (forwards.loading || forwards.loaded)) return; if (forwards && (forwards.loading || forwards.loaded)) return;
@ -34,3 +34,24 @@ export function loadSessionForwards(sessionId) {
} }
}; };
} }
export function loadForwardOptions(optionId) {
return async function(dispatch, getState) {
try {
const options = getState().options[optionId];
if (options && (options.loading || options.loaded)) return;
dispatch({ type: types.LOAD_FORWARD_OPTIONS_STARTED, id: optionId });
const data = await dispatch(
sendHttpRequest(api.getForwardOptions(optionId))
);
dispatch({
type: types.LOAD_FORWARD_OPTIONS_SUCCESS,
payload: data,
id: optionId
});
} catch (error) {
throw error;
}
};
}

View File

@ -3,3 +3,6 @@ export const LOAD_SERVER_SESSIONS_SUCCESS = "LOAD_SERVER_SESSIONS_SUCCESS";
export const LOAD_SESSION_FORWARDS_STARTED = "LOAD_SESSION_FORWARDS_STARTED"; export const LOAD_SESSION_FORWARDS_STARTED = "LOAD_SESSION_FORWARDS_STARTED";
export const LOAD_SESSION_FORWARDS_SUCCESS = "LOAD_SESSION_FORWARDS_SUCCESS"; export const LOAD_SESSION_FORWARDS_SUCCESS = "LOAD_SESSION_FORWARDS_SUCCESS";
export const LOAD_FORWARD_OPTIONS_STARTED = "LOAD_FORWARD_OPTIONS_STARTED";
export const LOAD_FORWARD_OPTIONS_SUCCESS = "LOAD_FORWARD_OPTIONS_SUCCESS";

View File

@ -2,10 +2,14 @@ import { get } from "../../api/axiosApi";
const baseUrl = `${process.env.REVERSE_PROXY_API_URL}/server`; const baseUrl = `${process.env.REVERSE_PROXY_API_URL}/server`;
const getServerSessions = () => get(`${baseUrl}/sessions`); const getServerSessions = () => get(`${baseUrl}/sessions`);
const getSessionForwards = (sessionId) => const getSessionForwards = sessionId =>
get(`${baseUrl}/session-forwards/${sessionId}`); get(`${baseUrl}/session-forwards/${sessionId}`);
const getForwardOptions = optionId =>
get(`${baseUrl}/forward-options/${optionId}`);
export default { export default {
getServerSessions, getServerSessions,
getSessionForwards getSessionForwards,
getForwardOptions
}; };

View File

@ -21,10 +21,12 @@ import Typography from "@material-ui/core/Typography";
const useStyles = makeStyles(styles); const useStyles = makeStyles(styles);
const ForwardOptionsComponent = ({ options }) => { const ForwardOptionsComponent = ({ title, options }) => {
const classes = useStyles(); const classes = useStyles();
const { t } = useTranslation(); const { t } = useTranslation();
const loading = !options || options.loading;
return ( return (
<> <>
<TableContainer component={Paper}> <TableContainer component={Paper}>
@ -53,7 +55,7 @@ const ForwardOptionsComponent = ({ options }) => {
</StyledTableCell> </StyledTableCell>
</Tooltip> </Tooltip>
<StyledTableCell align="center"> <StyledTableCell align="center">
<ActiveIcon active={options.trailingSlash} /> <ActiveIcon active={options.trailingSlash} loading={loading} />
</StyledTableCell> </StyledTableCell>
</StyledTableRow> </StyledTableRow>
<StyledTableRow> <StyledTableRow>
@ -65,20 +67,21 @@ const ForwardOptionsComponent = ({ options }) => {
</StyledTableCell> </StyledTableCell>
</Tooltip> </Tooltip>
<StyledTableCell align="center"> <StyledTableCell align="center">
<ActiveIcon active={options.pathOverwrite} /> <ActiveIcon active={options.pathOverwrite} loading={loading} />
</StyledTableCell> </StyledTableCell>
</StyledTableRow> </StyledTableRow>
</TableBody> </TableBody>
</Table> </Table>
</TableContainer> </TableContainer>
<Typography variant="caption" display="block" gutterBottom> <Typography variant="caption" display="block" gutterBottom>
{options.title} {title}
</Typography> </Typography>
</> </>
); );
}; };
ForwardOptionsComponent.propTypes = { ForwardOptionsComponent.propTypes = {
title: PropTypes.string.isRequired,
options: PropTypes.object.isRequired options: PropTypes.object.isRequired
}; };

View File

@ -0,0 +1,48 @@
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import PropTypes from "prop-types";
import { loadForwardOptions } from "../actionCreators";
import ForwardOptionsComponent from "./ForwardOptionsComponent";
const ForwardOptionsContainer = ({ actions, forward, options }) => {
useEffect(() => {
actions.loadForwardOptions(forward.optionId);
}, []);
const forwardOptions = options[forward.optionId];
return (
<>
{forwardOptions && (
<ForwardOptionsComponent
title={`${forward.from} >>> ${forward.to}`}
options={forwardOptions}
/>
)}
</>
);
};
ForwardOptionsContainer.propTypes = {
actions: PropTypes.object.isRequired,
forward: PropTypes.object.isRequired,
options: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {
options: state.options
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({ loadForwardOptions }, dispatch)
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ForwardOptionsContainer);

View File

@ -8,9 +8,9 @@ import {
DialogTitle DialogTitle
} from "@material-ui/core"; } from "@material-ui/core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import ForwardOptionsComponent from "./ForwardOptionsComponent"; import ForwardOptionsContainer from "./ForwardOptionsContainer";
const ForwardOptionsDialog = ({ open, handleClose, options }) => { const ForwardOptionsDialog = ({ open, handleClose, forward }) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
@ -25,7 +25,7 @@ const ForwardOptionsDialog = ({ open, handleClose, options }) => {
{t("Session.Forwards.Options.Title")} {t("Session.Forwards.Options.Title")}
</DialogTitle> </DialogTitle>
<DialogContent id="optopns-dialog-content"> <DialogContent id="optopns-dialog-content">
{options ? <ForwardOptionsComponent options={options} /> : ""} {forward ? <ForwardOptionsContainer forward={forward} /> : "N/A"}
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={handleClose} color="primary"> <Button onClick={handleClose} color="primary">
@ -40,7 +40,7 @@ const ForwardOptionsDialog = ({ open, handleClose, options }) => {
ForwardOptionsDialog.propTypes = { ForwardOptionsDialog.propTypes = {
open: PropTypes.bool.isRequired, open: PropTypes.bool.isRequired,
handleClose: PropTypes.func.isRequired, handleClose: PropTypes.func.isRequired,
options: PropTypes.object forward: PropTypes.object
}; };
export default ForwardOptionsDialog; export default ForwardOptionsDialog;

View File

@ -8,24 +8,24 @@ import { loadServerSessions, loadSessionForwards } from "../actionCreators";
const SessionContainer = ({ actions, sessions, forwards }) => { const SessionContainer = ({ actions, sessions, forwards }) => {
const [optionsDialogOpen, setOptionsDialogOpen] = useState(false); const [optionsDialogOpen, setOptionsDialogOpen] = useState(false);
const [forwardOptions, setForwardOptions] = useState(null); const [focusedForward, setFocusedForward] = useState(null);
useEffect(() => { useEffect(() => {
actions.loadServerSessions(); actions.loadServerSessions();
}, []); }, []);
const handleToggle = (sessionId) => (_, expanded) => { const handleToggle = sessionId => (_, expanded) => {
if (expanded) actions.loadSessionForwards(sessionId); if (expanded) actions.loadSessionForwards(sessionId);
}; };
const handleOptionsDialogOpen = (options) => () => { const handleOptionsDialogOpen = forward => () => {
setForwardOptions(options); setFocusedForward(forward);
setOptionsDialogOpen(true); setOptionsDialogOpen(true);
}; };
const handleOptionsDialogClose = () => { const handleOptionsDialogClose = () => {
setOptionsDialogOpen(false); setOptionsDialogOpen(false);
setForwardOptions(null); setFocusedForward(null);
}; };
return ( return (
@ -39,7 +39,7 @@ const SessionContainer = ({ actions, sessions, forwards }) => {
<ForwardOptionsDialog <ForwardOptionsDialog
open={optionsDialogOpen} open={optionsDialogOpen}
handleClose={handleOptionsDialogClose} handleClose={handleOptionsDialogClose}
options={forwardOptions} forward={focusedForward}
/> />
</> </>
); );

View File

@ -67,7 +67,7 @@ const SessionForwardsComponent = ({
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{forwards.map((row) => ( {forwards.map(row => (
<StyledTableRow key={row.forwardId}> <StyledTableRow key={row.forwardId}>
<StyledTableCell component="th" scope="row"> <StyledTableCell component="th" scope="row">
{forwards.indexOf(row) + 1} {forwards.indexOf(row) + 1}
@ -83,15 +83,12 @@ const SessionForwardsComponent = ({
</StyledTableCell> </StyledTableCell>
<StyledTableCell>{row.to}</StyledTableCell> <StyledTableCell>{row.to}</StyledTableCell>
<StyledTableCell align="right"> <StyledTableCell align="right">
{row.options ? ( {row.optionId ? (
<Tooltip title={t("Session.Forwards.Options.Title")}> <Tooltip title={t("Session.Forwards.Options.Title")}>
<IconButton <IconButton
aria-label="options" aria-label="options"
size="small" size="small"
onClick={openOptionsDialog({ onClick={openOptionsDialog(row)}
...row.options,
title: `${row.from} >>> ${row.to}`
})}
> >
<DonutLargeRoundedIcon color="primary" /> <DonutLargeRoundedIcon color="primary" />
</IconButton> </IconButton>

View File

@ -35,3 +35,26 @@ export function forwardsReducer(state = initialState.forwards, action) {
return state; return state;
} }
} }
export function optionsReducer(state = initialState.options, action) {
switch (action.type) {
case types.LOAD_FORWARD_OPTIONS_STARTED:
return {
...state,
[action.id]: { loading: true, loaded: false }
};
case types.LOAD_FORWARD_OPTIONS_SUCCESS:
return {
...state,
[action.id]: {
...action.payload,
loading: false,
loaded: true
}
};
default:
return state;
}
}

View File

@ -3,7 +3,8 @@ import ajaxStatusReducer from "./ajaxStatusReducer";
import serverReducer from "../../features/server/reducer"; import serverReducer from "../../features/server/reducer";
import { import {
sessionsReducer, sessionsReducer,
forwardsReducer forwardsReducer,
optionsReducer
} from "../../features/session/reducers"; } from "../../features/session/reducers";
import releaseNotesReducer from "../../features/releaseNotes/reducer"; import releaseNotesReducer from "../../features/releaseNotes/reducer";
import frontendSessionReducer from "../../features/frontendSession/reducer"; import frontendSessionReducer from "../../features/frontendSession/reducer";
@ -16,6 +17,7 @@ const rootReducer = combineReducers({
server: serverReducer, server: serverReducer,
sessions: sessionsReducer, sessions: sessionsReducer,
forwards: forwardsReducer, forwards: forwardsReducer,
options: optionsReducer,
releaseNotes: releaseNotesReducer, releaseNotes: releaseNotesReducer,
charts: chartsReducer, charts: chartsReducer,
snackbar: snackbarReducer, snackbar: snackbarReducer,

View File

@ -6,6 +6,7 @@ export default {
}, },
sessions: Object.assign([], { loading: false, loaded: false }), sessions: Object.assign([], { loading: false, loaded: false }),
forwards: {}, forwards: {},
options: {},
releaseNotes: Object.assign([], { loading: false, loaded: false }), releaseNotes: Object.assign([], { loading: false, loaded: false }),
charts: { charts: {
server: { server: {