diff --git a/src/admin/components/EditChannelFlags.js b/src/admin/components/EditChannelFlags.js index c9dd5cc6b833194e109bb740e9c9b342370f76c0..238d7781a96ea1b7167015c126c77cccf822a132 100644 --- a/src/admin/components/EditChannelFlags.js +++ b/src/admin/components/EditChannelFlags.js @@ -1,8 +1,8 @@ -import React, {useState, useEffect} from 'react'; +import React, {useEffect, useState} from 'react'; import {PropTypes} from 'prop-types'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {Form, Button, Label, Checkbox, Segment} from 'semantic-ui-react'; +import {Button, Checkbox, Form, Label, Modal, Segment} from 'semantic-ui-react'; import * as updateChannelActionCreators from 'channels/actions/UpdateChannel'; import * as getChannelEditInfoByIdActionCreators from 'channels/actions/GetChannelEditInfoById'; @@ -19,6 +19,7 @@ const EditChannelFlags = ({ }) => { const [updatedChannel, setChannel] = useState(channel); const [searchId, setSearchId] = useState(''); + const [open, setOpen] = useState(false); useEffect(() => { setChannel(channel); @@ -68,6 +69,8 @@ const EditChannelFlags = ({ } async function loadChannel() { + if (!searchId) return; + const response = await getChannelEditInfoById(searchId, false); if (response.error) { showSnackbar( @@ -76,78 +79,98 @@ const EditChannelFlags = ({ 'error' ); } else { + setOpen(true); showSnackbar('The channel info has been loaded successfully', 'success'); } } return ( - <Segment> - <Form onSubmit={handleSubmit} loading={loading}> + <> + <Form loading={loading}> <Form.Group inline> <label>Channel ID</label> <Form.Input width={6} name="channelId" placeholder="Channel ID" - //value={searchId} onChange={(e, d) => setSearchId(d.value)} - autoFocus /> <Button type="button" onClick={() => loadChannel()}> Load Channel to Edit </Button> </Form.Group> - - <Label color="blue" ribbon className="form-ribbon"> - Name * - </Label> - <Form.Input - name="name" - placeholder="Name" - value={updatedChannel.name || ''} - onChange={updateField} - maxLength="128" - minLength="4" - /> - <Label color="blue" ribbon className="form-ribbon"> - Slug * - </Label> - <Form.Input - disabled - label="Identifier for mail to channel" - name="slug" - placeholder="Slug" - value={updatedChannel.slug || ''} - onChange={updateField} - /> - - <Label color="blue" ribbon className="form-ribbon"> - Channel Flags - </Label> - <Form.Group grouped> - <Form.Field - control={Checkbox} - label="Mandatory Channel means members cannot unsubscribe." - checked={updatedChannel.channelFlags?.includes(channelFlagTypes.MANDATORY)} - value={channelFlagTypes.MANDATORY} - onChange={() => updateFlags(channelFlagTypes.MANDATORY)} - /> - <Form.Field - control={Checkbox} - label="Critical Channel can be used to send emergency notification on all user devices, bypassing all preferences." - checked={updatedChannel.channelFlags?.includes(channelFlagTypes.CRITICAL)} - value={channelFlagTypes.CRITICAL} - onChange={() => updateFlags(channelFlagTypes.CRITICAL)} - /> - </Form.Group> - - <Form.Group inline> - <Form.Button type="submit" primary disabled={loadingUpdate} loading={loadingUpdate}> - Save - </Form.Button> - </Form.Group> </Form> - </Segment> + + <Modal scrolling open={open} onClose={() => setOpen(false)} size="large"> + <Modal.Header>Edit channel flags</Modal.Header> + + <Segment basic> + <Form onSubmit={handleSubmit} loading={loading}> + <Form.Group inline> + <label>Channel ID</label> + <Form.Input + disabled + width={6} + name="channelId" + placeholder="Channel ID" + value={searchId} + autoFocus + /> + </Form.Group> + + <Label color="blue" ribbon className="form-ribbon"> + Name * + </Label> + <Form.Input + name="name" + placeholder="Name" + value={updatedChannel.name || ''} + onChange={updateField} + maxLength="128" + minLength="4" + /> + <Label color="blue" ribbon className="form-ribbon"> + Slug * + </Label> + <Form.Input + disabled + label="Identifier for mail to channel" + name="slug" + placeholder="Slug" + value={updatedChannel.slug || ''} + onChange={updateField} + /> + + <Label color="blue" ribbon className="form-ribbon"> + Channel Flags + </Label> + <Form.Group grouped> + <Form.Field + control={Checkbox} + label="Mandatory - means members cannot unsubscribe." + checked={updatedChannel.channelFlags?.includes(channelFlagTypes.MANDATORY)} + value={channelFlagTypes.MANDATORY} + onChange={() => updateFlags(channelFlagTypes.MANDATORY)} + /> + <Form.Field + control={Checkbox} + label="Critical - allow sending critical level notifications on all user devices, + bypassing all preferences." + checked={updatedChannel.channelFlags?.includes(channelFlagTypes.CRITICAL)} + value={channelFlagTypes.CRITICAL} + onChange={() => updateFlags(channelFlagTypes.CRITICAL)} + /> + </Form.Group> + + <Form.Group inline> + <Form.Button type="submit" primary disabled={loadingUpdate} loading={loadingUpdate}> + Save + </Form.Button> + </Form.Group> + </Form> + </Segment> + </Modal> + </> ); }; diff --git a/src/admin/pages/AdminPage.js b/src/admin/pages/AdminPage.js index c04540c424090529be76c34f656355d32ce0cc0d..2af62e41d50af324eb887276f99a1b1799951117 100644 --- a/src/admin/pages/AdminPage.js +++ b/src/admin/pages/AdminPage.js @@ -1,18 +1,26 @@ import React, {useEffect, useState} from 'react'; -import {Divider, Header, Segment} from 'semantic-ui-react'; +import {Divider, Grid, Header, Menu, Segment} from 'semantic-ui-react'; import {Helmet} from 'react-helmet'; import CategoriesList from 'admin/components/CategoriesList'; import {connect} from 'react-redux'; import PropTypes from 'prop-types'; -import ErrorComponent from '../../utils/error-component'; -import {isAdmin} from '../../auth/utils/authUtils'; import AuditDisplay from 'admin/components/AuditDisplay'; import EditChannelFlags from 'admin/components/EditChannelFlags'; +import {Link, useLocation} from 'react-router-dom'; +import {isAdmin} from '../../auth/utils/authUtils'; +import ErrorComponent from '../../utils/error-component'; const TITLE = `${process.env.REACT_APP_NAME} | Admin`; +const SECTIONS = Object.freeze({ + AUDIT: '#audit', + CATEGORIES: '#category', + CHANNELS: '#channel', +}); const AdminPage = ({roles}) => { + const location = useLocation(); const [hasAdminAccess, setHasAdminAccess] = useState(false); + const [activeSection, setActiveSection] = useState(location.hash || SECTIONS.AUDIT); useEffect(() => { if (isAdmin(roles)) { @@ -20,33 +28,64 @@ const AdminPage = ({roles}) => { } }, [roles]); + useEffect(() => { + setActiveSection(location.hash || SECTIONS.AUDIT); + }, [location]); + + const handleSectionClick = (e, {to}) => { + setActiveSection(to); + }; + return !hasAdminAccess ? ( <ErrorComponent error={{status: 403}} /> ) : ( - <div - style={{ - width: 933, - marginTop: 100, - marginLeft: 'auto', - marginRight: 'auto', - marginBottom: 50, - }} - > - <Helmet> - <title>{TITLE}</title> - </Helmet> - <Header as="h3">Admin Tools</Header> - <Divider /> - - <Segment basic> - <AuditDisplay /> - <EditChannelFlags /> - </Segment> - - <Segment basic> - <CategoriesList /> - </Segment> - </div> + <Grid centered columns={1} padded verticalAlign="middle"> + <Grid.Column width={10} stretched> + <Helmet> + <title>{TITLE}</title> + </Helmet> + <Header as="h3">Admin Tools</Header> + <Divider /> + <Grid columns={2} centered> + <Grid.Column width={4}> + <Menu vertical> + <Menu.Item> + <Menu.Header>Admin Tools</Menu.Header> + <Menu.Menu> + <Menu.Item + as={Link} + name="Audit" + to={SECTIONS.AUDIT} + active={activeSection === SECTIONS.AUDIT} + onClick={handleSectionClick} + /> + <Menu.Item + as={Link} + name="Channels" + to={SECTIONS.CHANNELS} + active={activeSection === SECTIONS.CHANNELS} + onClick={handleSectionClick} + /> + <Menu.Item + as={Link} + to={SECTIONS.CATEGORIES} + name="Categories" + active={activeSection === SECTIONS.CATEGORIES} + onClick={handleSectionClick} + /> + </Menu.Menu> + </Menu.Item> + </Menu> + </Grid.Column> + + <Grid.Column stretched width={12}> + {activeSection === SECTIONS.CHANNELS && <EditChannelFlags />} + {activeSection === SECTIONS.CATEGORIES && <CategoriesList />} + {activeSection === SECTIONS.AUDIT && <AuditDisplay />} + </Grid.Column> + </Grid> + </Grid.Column> + </Grid> ); };