Browse Source

Improved LE support and CSR is now generted in modal window with cert prepopulating feature.

Alexander 4 years ago
parent
commit
62d9652437

+ 1 - 1
src/react/src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea.jsx

@@ -12,7 +12,7 @@ const TextArea = ({ id, name, defaultValue = '', title, optionalTitle = '', rows
         id={id}
         rows={rows}
         name={name}
-        disabled={disabled}
+        readOnly={disabled}
         defaultValue={defaultValue}
         {...rest}
       >

+ 5 - 5
src/react/src/components/MainNav/MainNav.jsx

@@ -19,18 +19,18 @@ const MainNav = () => {
   });
 
   const { userName } = useSelector(state => state.session);
-  const { session: { look } } = useSelector(state => state.userSession);
+  const { session } = useSelector(state => state.userSession);
   const { user } = useSelector(state => state.menuCounters);
   const { activeElement, focusedElement, adminMenuTabs, userMenuTabs } = useSelector(state => state.mainNavigation);
   const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
   const dispatch = useDispatch();
 
   useEffect(() => {
-    if (!userName || !Object.entries(user).length) {
+    if (!userName || !Object.entries(user).length || !Object.entries(session).length) {
       return history.push('/login');
     }
 
-    if (look) {
+    if (session.look) {
       const commonUserRoutes = ['package', 'ip', 'rrd', 'updates', 'firewall', 'server'];
       const splitPath = history.location.pathname.split('/')[2];
 
@@ -41,11 +41,11 @@ const MainNav = () => {
       }
     }
 
-    const tabs = look ? userMenuTabs : adminMenuTabs;
+    const tabs = session.look ? userMenuTabs : adminMenuTabs;
     setState({ ...state, tabs });
 
     setLoading(false);
-  }, [userName, user, history, look]);
+  }, [userName, user, history, session]);
 
   const controlFocusedTabWithCallback = useCallback(event => {
     let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus') || document.querySelector('textarea:focus');

+ 8 - 8
src/react/src/components/MainNav/Panel/Panel.jsx

@@ -10,7 +10,7 @@ import './Panel.scss';
 
 const Panel = props => {
   const { i18n, userName } = useSelector(state => state.session);
-  const { session: { look, user, FIREWALL_SYSTEM, FILEMANAGER_KEY, SOFTACULOUS } } = useSelector(state => state.userSession);
+  const { session } = useSelector(state => state.userSession);
   const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
   const dispatch = useDispatch();
   const [loading, setLoading] = useState(false);
@@ -67,7 +67,7 @@ const Panel = props => {
     <div className="panel-wrapper">
       {loading && <Spinner />}
 
-      <div className={`top-panel ${look ? 'long-profile' : ''}`}>
+      <div className={`top-panel ${session.look ? 'long-profile' : ''}`}>
         <div className="container left-menu">
           <div className="logo">
             <Link to="/list/user/" onClick={() => dispatch(addActiveElement('/list/user/'))}>
@@ -97,14 +97,14 @@ const Panel = props => {
             <div className={className("/list/updates/")}>
               <Link to="/list/updates/" onClick={event => handleState("/list/updates/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Updates}</Link>
             </div>
-            {FIREWALL_SYSTEM && <div className={className("/list/firewall/")}>
+            {session.FIREWALL_SYSTEM && <div className={className("/list/firewall/")}>
               <Link to="/list/firewall/" onClick={event => handleState("/list/firewall/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Firewall}</Link>
             </div>}
           </>)}
-          {FILEMANAGER_KEY && <div className={className("/list/directory/")}>
+          {session.FILEMANAGER_KEY && <div className={className("/list/directory/")}>
             <Link to="/list/directory/">{i18n['File Manager']}</Link>
           </div>}
-          {SOFTACULOUS === "yes" && <div className={className("/softaculous/")}><Link to="/softaculous/" target="_blank">{i18n.Apps ?? 'Apps'}</Link>
+          {session.SOFTACULOUS === "yes" && <div className={className("/softaculous/")}><Link to="/softaculous/" target="_blank">{i18n.Apps ?? 'Apps'}</Link>
           </div>}
           {userName === 'admin' && (
             <div className={className("/list/server/")}>
@@ -116,11 +116,11 @@ const Panel = props => {
           <Notifications />
           <div>
             <Link to={`/edit/user?user=${userName}`}>
-              {look
+              {session.look
                 ? <div className="long-username">
-                  <span>{user}</span>
+                  <span>{session.user}</span>
                   <FontAwesomeIcon icon="long-arrow-alt-right" />
-                  <span>{look}</span>
+                  <span>{session.look}</span>
                 </div>
                 : userName
               }

+ 2 - 2
src/react/src/components/MainNav/Stat-menu/Menu.jsx

@@ -28,7 +28,7 @@ const style = ({ menuHeight, mobile }) => {
 const Menu = props => {
   const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
   const { i18n } = useSelector(state => state.session);
-  const { session: { look } } = useSelector(state => state.userSession);
+  const { session } = useSelector(state => state.userSession);
   const { user } = useSelector(state => state.menuCounters);
   const dispatch = useDispatch();
 
@@ -72,7 +72,7 @@ const Menu = props => {
             <h3>{i18n.USER}</h3>
             <div className="stats">
               {
-                look
+                session.look
                   ? (<>
                     <div><span>{i18n.Disk}:</span> <span>{sizeFormatter(user.U_DISK)}</span></div>
                     <div><span>{i18n.Bandwidth}:</span> <span>{sizeFormatter(user.U_BANDWIDTH)}</span></div>

+ 0 - 1
src/react/src/components/User/Add/AddUser.jsx

@@ -19,7 +19,6 @@ import HtmlParser from 'react-html-parser';
 const AddUser = props => {
   const { i18n } = useSelector(state => state.session);
   const { session } = useSelector(state => state.userSession);
-  const userLanguage = localStorage.getItem("language");
   const history = useHistory();
   const dispatch = useDispatch();
   const [state, setState] = useState({

+ 33 - 3
src/react/src/components/WebDomain/Add/AddWebDomain.jsx

@@ -6,7 +6,6 @@ import { addWeb, getWebDomainInfo } from '../../../ControlPanelService/Web';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import AdvancedOptions from './AdvancedOptions/AdvancedOptions';
 import Checkbox from 'src/components/ControlPanel/AddItemLayout/Form/Checkbox/Checkbox';
-import SelectInput from 'src/components/ControlPanel/AddItemLayout/Form/SelectInput/SelectInput';
 import TextArea from 'src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea';
 import Toolbar from '../../MainNav/Toolbar/Toolbar';
 import { useHistory } from 'react-router-dom';
@@ -14,6 +13,8 @@ import Spinner from '../../Spinner/Spinner';
 import { useDispatch, useSelector } from 'react-redux';
 
 import './AddWebDomain.scss';
+import GenerateSSL from 'src/containers/GenerateCSR';
+import 'src/components/Modal/Modal.scss';
 import { Helmet } from 'react-helmet';
 import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
 import HtmlParser from 'react-html-parser';
@@ -23,6 +24,7 @@ const AddWebDomain = props => {
   const { session } = useSelector(state => state.userSession);
   const dispatch = useDispatch();
   const token = localStorage.getItem("token");
+  const [modalVisible, setModalVisible] = useState(false);
   const history = useHistory();
   const [state, setState] = useState({
     loading: false,
@@ -31,6 +33,8 @@ const AddWebDomain = props => {
     proxySupport: true,
     showAdvancedOptions: false,
     okMessage: '',
+    ssl_crt: '',
+    ssl_key: '',
     domain: '',
     errorMessage: '',
     webStats: [],
@@ -83,7 +87,14 @@ const AddWebDomain = props => {
 
   const renderAdvancedOptions = () => {
     if (state.showAdvancedOptions) {
-      return <AdvancedOptions prefixI18N={state.prefixI18N} domain={state.domain} webStats={state.webStats} prePath={state.prePath} />;
+      return <AdvancedOptions
+        prefixI18N={state.prefixI18N}
+        setModalVisible={bool => setModalVisible(bool)}
+        sslCertificate={state.ssl_crt}
+        sslKey={state.ssl_key}
+        domain={state.domain}
+        webStats={state.webStats}
+        prePath={state.prePath} />;
     }
   }
 
@@ -239,8 +250,27 @@ const AddWebDomain = props => {
           </form>
         )}
       </AddItemLayout>
+      <div className={`modal fade ${modalVisible ? 'show' : ''}`} id="c-panel-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" style={{ display: modalVisible ? 'block' : 'none' }}>
+        <div className="modal-dialog" role="document">
+          <div className="modal-content">
+            <div className="modal-header">
+              <h5>{i18n['Generating CSR']}</h5>
+              <button type="button" onClick={() => setModalVisible(false)} className="close" data-dismiss="modal" aria-label="Close">
+                <span aria-hidden="true">&times;</span>
+              </button>
+            </div>
+            <GenerateSSL
+              domain={state.domain}
+              closeModal={() => setModalVisible(false)}
+              prePopulateInputs={({ crt, key }) => {
+                setState({ ...state, ssl_crt: crt, ssl_key: key });
+                setModalVisible(false);
+              }} />
+          </div>
+        </div>
+      </div>
     </div >
   );
 }
 
-export default AddWebDomain;
+export default AddWebDomain;

+ 24 - 0
src/react/src/components/WebDomain/Add/AddWebDomain.scss

@@ -23,4 +23,28 @@
       }
     }
   }
+
+  #c-panel-modal {
+    padding: 2rem;
+
+    form .form-group input[type="text"] {
+      width: 90% !important;
+    }
+
+    label {
+      color: white;
+    }
+
+    .form-group {
+      padding-left: 1.5rem;
+
+      textarea {
+        width: 90% !important;
+      }
+    }
+
+    .l-col {
+      display: none;
+    }
+  }
 }

+ 1 - 1
src/react/src/components/WebDomain/Add/AdvancedOptions/AdvancedOptions.jsx

@@ -23,7 +23,7 @@ const AdvancedOptions = ({ prefixI18N, prePath, ...props }) => {
 
   const renderSslSupport = () => {
     if (state.sslSupport) {
-      return <SslSupport />;
+      return <SslSupport sslCertificate={props.sslCertificate} sslKey={props.sslKey} setModalVisible={bool => props.setModalVisible(bool)} />;
     }
   }
 

+ 13 - 14
src/react/src/components/WebDomain/Add/SslSupport/SslSupport.jsx

@@ -1,5 +1,7 @@
 import React, { useState } from 'react';
 import { useSelector } from 'react-redux';
+import { Link } from 'react-router-dom';
+import TextArea from 'src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea';
 
 import './SslSupport.scss';
 
@@ -22,30 +24,27 @@ const SslSupport = props => {
         <span className="lets-encrypt-span">{letsEncrypt ? i18n['Your certificate will be automatically issued in 5 minutes'] : null}</span>
       </div>
 
-      <div class="form-group">
-        <label htmlFor="package">{i18n['SSL Home Directory']}</label>
-        <select class="form-control" id="ssl_home" name="v_ssl_home">
-          <option value="same">public_html</option>
-          <option value="single">public_shtml</option>
-        </select>
-      </div>
+      <input type="hidden" value="same" name="v_ssl_home" />
 
-      <div class="form-group">
-        <label htmlFor="aliases">{i18n['SSL Certificate']}</label>
-        <textarea class="form-control" id="aliases" rows="3" name="v_ssl_crt" disabled={letsEncrypt}></textarea>
-      </div>
+      <TextArea
+        id="ssl-certificate"
+        name="v_ssl_crt"
+        title={i18n['SSL Certificate']}
+        value={props.sslCertificate}
+        disabled={letsEncrypt}
+        optionalTitle={<>/ <button type="button" onClick={() => props.setModalVisible(true)} className="generate-csr">{i18n['Generate CSR']}</button></>} />
 
       <div class="form-group">
         <label htmlFor="aliases">{i18n['SSL Key']}</label>
-        <textarea class="form-control" id="aliases" rows="3" name="v_ssl_key" disabled={letsEncrypt}></textarea>
+        <textarea class="form-control" id="ssl_key" rows="3" name="v_ssl_key" defaultValue={props.sslKey} disabled={letsEncrypt}></textarea>
       </div>
 
       <div class="form-group">
         <label htmlFor="aliases">{i18n['SSL Certificate Authority / Intermediate']}</label>
-        <textarea class="form-control" id="aliases" rows="3" name="v_ssl_ca" disabled={letsEncrypt}></textarea>
+        <textarea class="form-control" id="ssl_ca" rows="3" name="v_ssl_ca" disabled={letsEncrypt}></textarea>
       </div>
     </div>
   );
 }
 
-export default SslSupport;
+export default SslSupport;

+ 44 - 0
src/react/src/components/WebDomain/Edit/EditWeb.jsx

@@ -13,6 +13,8 @@ import Toolbar from '../../MainNav/Toolbar/Toolbar';
 import SslSupport from './SslSupport/SslSupport';
 import { useHistory } from 'react-router-dom';
 import { useDispatch, useSelector } from 'react-redux';
+import GenerateSSL from 'src/containers/GenerateCSR';
+import 'src/components/Modal/Modal.scss';
 import QS from 'qs';
 
 import './EditWeb.scss';
@@ -28,6 +30,7 @@ const EditWeb = props => {
   const history = useHistory();
   const dispatch = useDispatch();
   const [errorMessage, setErrorMessage] = useState('');
+  const [modalVisible, setModalVisible] = useState(false);
   const [okMessage, setOkMessage] = useState('');
   const [state, setState] = useState({
     data: {},
@@ -85,6 +88,26 @@ const EditWeb = props => {
 
     if (updatedDomain['v_ssl'] === 'on') {
       updatedDomain['v_ssl'] = 'yes';
+    } else {
+      delete updatedDomain['v_ssl'];
+    }
+
+    if (updatedDomain['v_letsencrypt'] === 'on') {
+      updatedDomain['v_letsencrypt'] = 'yes';
+    } else {
+      delete updatedDomain['v_letsencrypt'];
+    }
+
+    if (!updatedDomain['v_ssl_ca']) {
+      delete updatedDomain['v_ssl_ca'];
+    }
+
+    if (!updatedDomain['v_ssl_crt']) {
+      delete updatedDomain['v_ssl_crt'];
+    }
+
+    if (!updatedDomain['v_ssl_key']) {
+      delete updatedDomain['v_ssl_key'];
     }
 
     if (Object.keys(updatedDomain).length !== 0 && updatedDomain.constructor === Object) {
@@ -246,6 +269,7 @@ const EditWeb = props => {
                   sslIssuer={state.data.ssl_issuer}
                   sslCertificate={state.data.ssl_crt}
                   sslKey={state.data.ssl_key}
+                  setModalVisible={bool => setModalVisible(bool)}
                   sslCertificateAuthority={state.data.ssl_ca}
                   domain={state.domain}
                   sslHome={state.data.ssl_home}
@@ -307,6 +331,26 @@ const EditWeb = props => {
           </form>
         }
       </AddItemLayout>
+
+      <div className={`modal fade ${modalVisible ? 'show' : ''}`} id="c-panel-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" style={{ display: modalVisible ? 'block' : 'none' }}>
+        <div className="modal-dialog" role="document">
+          <div className="modal-content">
+            <div className="modal-header">
+              <h5>{i18n['Generating CSR']}</h5>
+              <button type="button" onClick={() => setModalVisible(false)} className="close" data-dismiss="modal" aria-label="Close">
+                <span aria-hidden="true">&times;</span>
+              </button>
+            </div>
+            <GenerateSSL
+              domain={state.domain}
+              closeModal={() => setModalVisible(false)}
+              prePopulateInputs={({ crt, key }) => {
+                setState({ ...state, data: { ...state.data, ssl_crt: crt, ssl_key: key } });
+                setModalVisible(false);
+              }} />
+          </div>
+        </div>
+      </div>
     </div>
   );
 }

+ 24 - 0
src/react/src/components/WebDomain/Edit/EditWeb.scss

@@ -2,4 +2,28 @@
   .web-stat-additional {
     transform: translateX(3rem);
   }
+
+  #c-panel-modal {
+    padding: 2rem;
+
+    form .form-group input[type="text"] {
+      width: 90% !important;
+    }
+
+    label {
+      color: white;
+    }
+
+    .form-group {
+      padding-left: 1.5rem;
+
+      textarea {
+        width: 90% !important;
+      }
+    }
+
+    .l-col {
+      display: none;
+    }
+  }
 }

+ 15 - 23
src/react/src/components/WebDomain/Edit/SslSupport/SslSupport.jsx

@@ -1,16 +1,13 @@
 import React, { useEffect, useState } from 'react';
 import { useSelector } from 'react-redux';
-import { Link } from 'react-router-dom';
 import Checkbox from '../../../ControlPanel/AddItemLayout/Form/Checkbox/Checkbox';
-import SelectInput from '../../../ControlPanel/AddItemLayout/Form/SelectInput/SelectInput';
 import TextArea from '../../../ControlPanel/AddItemLayout/Form/TextArea/TextArea';
 
 import './SslSupport.scss';
 
 const SslSupport = props => {
   const { i18n } = useSelector(state => state.session);
-  const [letsEncrypt, setLetsEncrypt] = useState(false);
-  const [sslHomeOptions, setSslHomeOptions] = useState(['public_html', 'public_shtml']);
+  const [letsEncrypt, setLetsEncrypt] = useState(props.letsEncrypt);
 
   useEffect(() => {
     setLetsEncrypt(props.letsEncrypt);
@@ -22,19 +19,18 @@ const SslSupport = props => {
 
   return (
     <div className="ssl-support">
-      <Checkbox
-        onChange={onChangeLetsEncrypt}
-        name="v_letsencrypt"
-        id="lets-encrypt"
-        title={i18n['Lets Encrypt Support']}
-        defaultChecked={letsEncrypt} />
-
-      <SelectInput
-        options={sslHomeOptions}
-        selected={props.sslHome === 'same' ? 'public_html' : 'public_shtml'}
-        name="v_ssl_home"
-        id="ssl_home"
-        title={i18n['SSL Home Directory']} />
+      <>
+        <Checkbox
+          onChange={onChangeLetsEncrypt}
+          name="v_letsencrypt"
+          id="lets-encrypt"
+          title={i18n['Lets Encrypt Support']}
+          defaultChecked={letsEncrypt} />
+
+        {!props.letsEncrypt && <span className="lets-encrypt-span">{letsEncrypt ? i18n['Your certificate will be automatically issued in 5 minutes'] : null}</span>}
+      </>
+
+      <input type="hidden" value="same" name="v_ssl_home" />
 
       <TextArea
         id="ssl-certificate"
@@ -42,11 +38,7 @@ const SslSupport = props => {
         title={i18n['SSL Certificate']}
         defaultValue={props.sslCertificate}
         disabled={letsEncrypt}
-        optionalTitle={
-          !letsEncrypt
-            ? (<>/ <Link className="generate-csr" target="_blank" to={`/generate/ssl/?domain=${props.domain}`}>{i18n['Generate CSR']}</Link></>)
-            : ''
-        } />
+        optionalTitle={<>/ <button type="button" onClick={() => props.setModalVisible(true)} className="generate-csr">{i18n['Generate CSR']}</button></>} />
 
       <TextArea
         id="ssl-key"
@@ -141,4 +133,4 @@ const SslSupport = props => {
   );
 }
 
-export default SslSupport;
+export default SslSupport;

+ 0 - 2
src/react/src/containers/ControlPanelContent/ControlPanelContent.jsx

@@ -52,7 +52,6 @@ import Users from '../../containers/Users/Users';
 import RRDs from '../../containers/RRDs/RRDs';
 import BanList from '../Firewalls/Banlist';
 import Web from '../../containers/Web/Web';
-import GenerateCSR from '../GenerateCSR';
 import Search from '../Search/Search';
 import Logs from '../Logs/Logs';
 
@@ -190,7 +189,6 @@ const ControlPanelContent = props => {
 
                 <Route path="/list/user" component={props => <Users changeSearchTerm={handleSearchTerm} {...props} />} />
                 <Route path="/add/user" component={() => <AddUser />} />
-                <Route path="/generate/ssl" component={GenerateCSR} />
                 <Route path="/edit/user" component={() => <EditUser />} />
                 <Route path="/list/web" component={props => <Web {...props} changeSearchTerm={handleSearchTerm} />} />
                 <Route path="/add/web" component={() => <AddWebDomain />} />

+ 9 - 20
src/react/src/containers/GenerateCSR/index.jsx

@@ -3,15 +3,11 @@ import { addActiveElement, removeFocusedElement } from "src/actions/MainNavigati
 import TextInput from 'src/components/ControlPanel/AddItemLayout/Form/TextInput/TextInput';
 import AddItemLayout from 'src/components/ControlPanel/AddItemLayout/AddItemLayout';
 import TextArea from 'src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import Toolbar from 'src/components/MainNav/Toolbar/Toolbar';
 import { generateCSR, getCsrInitialData } from 'src/ControlPanelService/Web';
 import { useDispatch, useSelector } from 'react-redux';
 import Spinner from 'src/components/Spinner/Spinner';
 import { useHistory } from 'react-router-dom';
 import HtmlParser from 'react-html-parser';
-import { Helmet } from 'react-helmet';
-import QS from 'qs';
 
 const GenerateSSL = props => {
   const token = localStorage.getItem("token");
@@ -28,8 +24,7 @@ const GenerateSSL = props => {
   });
 
   useEffect(() => {
-    let queryParams = QS.parse(history.location.search, { ignoreQueryPrefix: true });
-    const { domain } = queryParams;
+    const { domain } = props;
 
     dispatch(addActiveElement('/list/web/'));
     dispatch(removeFocusedElement());
@@ -94,17 +89,6 @@ const GenerateSSL = props => {
 
   return (
     <div className="edit-template edit-user">
-      <Helmet>
-        <title>{`Vesta - ${i18n.WEB}`}</title>
-      </Helmet>
-      <Toolbar mobile={false}>
-        <div></div>
-        <div className="search-toolbar-name">{i18n['Generating CSR']}</div>
-        <div className="error"><span className="error-message">{errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {errorMessage}</span></div>
-        <div className="success">
-          <span className="ok-message">{okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(okMessage)}</span> </span>
-        </div>
-      </Toolbar>
       <AddItemLayout date={state.data.date} time={state.data.time} status={state.data.status}>
         {state.loading ? <Spinner /> :
           <form onSubmit={event => submitFormHandler(event)} id="add-user">
@@ -132,7 +116,8 @@ const GenerateSSL = props => {
                     defaultValue={state.generatedData.key} />
 
                   <div className="buttons-wrapper">
-                    <button type="button" className="back" onClick={() => history.push(`/edit/web/?domain=${state.domain}`)}>{i18n.Back}</button>
+                    <button type="button" className="add" onClick={() => props.prePopulateInputs(state.generatedData)}>{i18n.Add}</button>
+                    <button type="button" className="back" onClick={props.closeModal}>{i18n.Back}</button>
                   </div>
                 </>)
                 : (<>
@@ -149,12 +134,16 @@ const GenerateSSL = props => {
                   <TextInput id="org" name="v_org" title={i18n['Organization']} value={state.data.org} />
 
                   <div className="buttons-wrapper">
-                    <button type="submit" className="add">{i18n.Save}</button>
-                    <button type="button" className="back" onClick={() => history.push(`/edit/web/?domain=${state.domain}`)}>{i18n.Back}</button>
+                    <button type="submit" className="add">{i18n.Generate}</button>
+                    <button type="button" className="back" onClick={props.closeModal}>{i18n.Back}</button>
                   </div>
                 </>)
             }
 
+            <div className="error"><span className="error-message">{errorMessage}</span></div>
+            <div className="success">
+              <span className="ok-message"><span>{HtmlParser(okMessage)}</span> </span>
+            </div>
           </form>
         }
       </AddItemLayout>

+ 4 - 4
src/react/src/containers/Users/Users.jsx

@@ -21,7 +21,7 @@ import { useHistory } from 'react-router';
 
 const Users = props => {
   const { userName, i18n } = useSelector(state => state.session);
-  const { session: { look } } = useSelector(state => state.userSession);
+  const { session } = useSelector(state => state.userSession);
   const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
   const { focusedElement } = useSelector(state => state.mainNavigation);
   const dispatch = useDispatch();
@@ -74,7 +74,7 @@ const Users = props => {
 
     if (event.keyCode === 65) {
       switch (history.location.pathname) {
-        case '/list/user/': return look ? history.push('/add/web/') : history.push('/add/user/');
+        case '/list/user/': return session.look ? history.push('/add/web/') : history.push('/add/user/');
         default: break;
       }
     }
@@ -403,8 +403,8 @@ const Users = props => {
       </Helmet>
       <Toolbar mobile={false} >
         <LeftButton
-          name={look ? i18n['Add Web Domain'] : i18n['Add User']}
-          href={look ? "/add/web/" : "/add/user/"}
+          name={session.look ? i18n['Add Web Domain'] : i18n['Add User']}
+          href={session.look ? "/add/web/" : "/add/user/"}
           showLeftMenu={true} />
         <div className="r-menu">
           <div className="input-group input-group-sm">