Forráskód Böngészése

Added new responsive design features.

Alexander 4 éve
szülő
commit
7ebcab3cbf
49 módosított fájl, 634 hozzáadás és 487 törlés
  1. 17 12
      src/react/package-lock.json
  2. 1 0
      src/react/package.json
  3. 1 10
      src/react/src/components/Backup/RestoreSetting/RestoreSetting.scss
  4. 29 13
      src/react/src/components/ControlPanel/AddItemLayout/AddItemLayout.scss
  5. 1 7
      src/react/src/components/ControlPanel/ListItem/ListItem.scss
  6. 1 1
      src/react/src/components/ControlPanel/Modal/Modal.scss
  7. 1 10
      src/react/src/components/CronJob/Generator/Generator.scss
  8. 4 1
      src/react/src/components/Database/Database.jsx
  9. 1 10
      src/react/src/components/Lists/Row/Row.scss
  10. 42 12
      src/react/src/components/Login/Login.scss
  11. 5 1
      src/react/src/components/Mail/Mail.jsx
  12. 5 1
      src/react/src/components/MailAccount/MailAccount.jsx
  13. 1 1
      src/react/src/components/MailAccount/MailInfoBlock/MailInfoBlock.scss
  14. 2 1
      src/react/src/components/MainNav/MainNav.jsx
  15. 72 27
      src/react/src/components/MainNav/Mobile/MobileTopNav.jsx
  16. 108 30
      src/react/src/components/MainNav/Mobile/MobileTopNav.scss
  17. 9 5
      src/react/src/components/MainNav/Panel/Panel.jsx
  18. 31 51
      src/react/src/components/MainNav/Panel/Panel.scss
  19. 0 14
      src/react/src/components/MainNav/Stat-menu/Menu.jsx
  20. 15 59
      src/react/src/components/MainNav/Stat-menu/Menu.scss
  21. 11 10
      src/react/src/components/MainNav/Toolbar/LeftButton/LeftButton.scss
  22. 4 0
      src/react/src/components/MainNav/Toolbar/Select/Select.scss
  23. 30 38
      src/react/src/components/MainNav/Toolbar/Toolbar.jsx
  24. 33 13
      src/react/src/components/MainNav/Toolbar/Toolbar.scss
  25. 1 10
      src/react/src/components/Menu/Menu.scss
  26. 1 12
      src/react/src/components/Modal/Modal.scss
  27. 1 12
      src/react/src/components/Path/Path.scss
  28. 1 1
      src/react/src/components/Server/Edit/EditBackupOption.jsx
  29. 2 3
      src/react/src/components/Server/Edit/EditDatabaseOption.jsx
  30. 4 0
      src/react/src/components/Server/Edit/EditServer.jsx
  31. 1 11
      src/react/src/components/Server/Edit/EditServer.scss
  32. 1 1
      src/react/src/components/Spinner/Spinner.scss
  33. 9 2
      src/react/src/components/Statistic/Statistic.jsx
  34. 1 11
      src/react/src/components/TopPanel/TopPanel.scss
  35. 1 11
      src/react/src/components/User/Add/AddUser.scss
  36. 9 2
      src/react/src/components/User/User.jsx
  37. 32 12
      src/react/src/components/User/User.scss
  38. 1 8
      src/react/src/components/WebDomain/Edit/SslSupport/SslSupport.scss
  39. 9 2
      src/react/src/components/WebDomain/WebDomain.jsx
  40. 83 11
      src/react/src/containers/App/App.scss
  41. 21 13
      src/react/src/containers/ControlPanelContent/ControlPanelContent.scss
  42. 2 2
      src/react/src/containers/CronJobs/CronJobs.jsx
  43. 1 11
      src/react/src/containers/CronJobs/CronJobs.scss
  44. 1 11
      src/react/src/containers/DNSRecords/DNSRecords.scss
  45. 1 1
      src/react/src/containers/MailAccounts/MailAccounts.scss
  46. 2 2
      src/react/src/containers/Mails/Mails.jsx
  47. 1 11
      src/react/src/containers/RRDs/RRDs.scss
  48. 11 0
      src/react/src/utils/scss/_breakpoints.scss
  49. 13 0
      src/react/src/utils/scss/_variables.scss

+ 17 - 12
src/react/package-lock.json

@@ -1,6 +1,6 @@
 {
-  "name": "file_manager",
-  "version": "0.1.0",
+  "name": "react-control-panel",
+  "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -2250,9 +2250,9 @@
       "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
     },
     "are-we-there-yet": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
-      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+      "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
       "requires": {
         "delegates": "^1.0.0",
         "readable-stream": "^2.0.6"
@@ -6350,9 +6350,9 @@
       }
     },
     "globule": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
-      "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz",
+      "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==",
       "requires": {
         "glob": "~7.1.1",
         "lodash": "~4.17.10",
@@ -9845,6 +9845,11 @@
         "sha.js": "^2.4.8"
       }
     },
+    "perfect-scrollbar": {
+      "version": "1.5.3",
+      "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.3.tgz",
+      "integrity": "sha512-+Lo6t61lSuCY9ghpqh1NFMXOu8fNwlYGqPoUMOZ3HTFIL4g7+L7zD7hQCLW5yjkOZ6LGTw1m9+MfEew7cngtAQ=="
+    },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -14588,11 +14593,11 @@
       "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
     },
     "wide-align": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
-      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+      "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
       "requires": {
-        "string-width": "^1.0.2 || 2"
+        "string-width": "^1.0.2 || 2 || 3 || 4"
       }
     },
     "word-wrap": {

+ 1 - 0
src/react/package.json

@@ -16,6 +16,7 @@
     "dayjs": "^1.10.7",
     "jquery": "^3.5.1",
     "node-sass": "^4.14.1",
+    "perfect-scrollbar": "^1.5.3",
     "popper.js": "^1.15.0",
     "prop-types": "^15.7.2",
     "qs": "^6.9.4",

+ 1 - 10
src/react/src/components/Backup/RestoreSetting/RestoreSetting.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .backups-restore-settings {
   .list-item {

+ 29 - 13
src/react/src/components/ControlPanel/AddItemLayout/AddItemLayout.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 $optionalButtonHover: $primary;
 $optionalButtonActive: $primaryLight;
@@ -64,6 +55,7 @@ $errorColor: #BE5ABF;
     }
   
     .search-toolbar-name {
+      width: auto !important;
       padding: 10px 0;
       margin-left: 0;
     }
@@ -134,6 +126,18 @@ $errorColor: #BE5ABF;
       }
     }
 
+    @media screen and (max-width: 900px) {
+      .form-group {
+        input[type=text],
+        input[type=password],
+        input[type=email],
+        textarea,
+        select {
+          width: 100%;
+        }
+      }
+    }
+
     width: 100%;
 
     .form-group select,
@@ -156,7 +160,7 @@ $errorColor: #BE5ABF;
     input:-webkit-autofill:hover,
     input:-webkit-autofill:focus,
     input:-webkit-autofill:active  {
-      background-color: $primaryLight;
+      background: $primaryLight;
       border-color: $primaryActive;
       filter: none;
       box-shadow: none;
@@ -166,7 +170,7 @@ $errorColor: #BE5ABF;
     input:autofill:hover,
     input:autofill:focus,
     input:autofill:active  {
-      background-color: $primaryLight;
+      background: $primaryLight;
       border-color: $primaryActive;
       filter: none;
       box-shadow: none;
@@ -292,4 +296,16 @@ $errorColor: #BE5ABF;
       font-weight: bold;
     }
   }
-}
+}
+
+@media screen and (max-width: 1066px) {
+  .form-group {
+    input[type=text],
+    input[type=password],
+    input[type=email],
+    textarea,
+    select {
+      width: 75%;
+    }
+  }
+}

+ 1 - 7
src/react/src/components/ControlPanel/ListItem/ListItem.scss

@@ -1,10 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #2e5bb1;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .list-item {
   display: flex;

+ 1 - 1
src/react/src/components/ControlPanel/Modal/Modal.scss

@@ -1,4 +1,4 @@
-$primary: #2c54ac;
+@import 'src/utils/scss/variables';
 
 div.modal {
   z-index: 2;

+ 1 - 10
src/react/src/components/CronJob/Generator/Generator.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .cron-job-generator {
   border: 1px solid #d9d9d9;

+ 4 - 1
src/react/src/components/Database/Database.jsx

@@ -47,7 +47,10 @@ const Database = props => {
         <br />
         <div className="stats">
           <Container className="c-1">
-            <div className="disk">{i18n.Disk}: <span><span className="stat">{data.U_DISK}</span>{i18n.mb}</span></div>
+            <div className="disk">
+              {i18n.Disk}: <span><span className="stat">{data.U_DISK}</span>{i18n.mb}</span>
+              <div className="percent" style={{ width: `${data.U_DISK_PERCENT}%` || '0%' }}></div>
+            </div>
           </Container>
           <Container className="c-2">
             <div>{i18n.User}: <span className="stat">{data.DBUSER}</span></div>

+ 1 - 10
src/react/src/components/Lists/Row/Row.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .list .list-container ul li svg {
   width: 25px;

+ 42 - 12
src/react/src/components/Login/Login.scss

@@ -1,13 +1,5 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
+@import 'src/utils/scss/breakpoints';
 
 .login-page {
   display: flex;
@@ -78,7 +70,7 @@ $textColor: #555;
           background-color: $primary;
           border: 1px solid $primary;
           padding: 1px 16px 3px;
-          font-size: 13px;;
+          font-size: 13px;
           height: 35px;
           color: #fafafa;
           border-radius: 3px;
@@ -107,4 +99,42 @@ $textColor: #555;
       }
     }
   }
-}
+
+  @media (max-width: $tabletMax) {
+    .login-form-wrapper {
+      margin: 2rem;
+
+      .login-layout {
+        form {
+          flex-direction: column;
+          justify-content: center;
+          align-items: center;
+
+          .c1 {
+            width: 100%;
+            margin-bottom: 1.5rem;
+
+            a {
+              text-align: center;
+
+              img {
+                width: 75%;
+              }
+            }
+          }
+
+          .c2 {
+            margin: 0;
+            width: 100%;
+          }
+
+          .buttons-wrapper {
+            .add {
+              margin-bottom: 10px;
+            }
+          }
+        }
+      }
+    }
+  }
+}

+ 5 - 1
src/react/src/components/Mail/Mail.jsx

@@ -54,7 +54,11 @@ const Mail = props => {
         <div className="name">{data.NAME}</div>
         <div className="stats">
           <Container className="c-1">
-            <div className="bandwidth">{i18n.Disk} <span><span className="stat">{data.U_DISK}</span>{i18n.mb}</span></div>
+            <div className="bandwidth">
+              {i18n.Disk}
+              <span><span className="stat">{data.U_DISK}</span>{i18n.mb}</span>
+              <div className="percent" style={{ width: `${data.U_DISK_PERCENT}%` || '0%' }}></div>
+            </div>
           </Container>
           <Container className="c-2">
             {printStat(i18n['AntiVirus Support'], data.ANTIVIRUS)}

+ 5 - 1
src/react/src/components/MailAccount/MailAccount.jsx

@@ -53,7 +53,11 @@ export default function MailAccount(props) {
         <div className="name">{`${data.NAME}@${domain}`}</div>
         <div className="stats">
           <Container className="c-1">
-            <div className="bandwidth">{i18n.Disk} <span><span className="stat">{data.U_DISK}</span>&nbsp;{i18n.mb}</span></div>
+            <div className="bandwidth">
+              {i18n.Disk}
+              <span><span className="stat">{data.U_DISK}</span>&nbsp;{i18n.mb}</span>
+              <div className="percent" style={{ width: `${data.U_DISK_PERCENT}%` || '0%' }}></div>
+            </div>
           </Container>
           <Container className="c-2">
             <div>{i18n['Quota']}: <span><span className="stat">{data.QUOTA}</span>&nbsp; {i18n.mb}</span></div>

+ 1 - 1
src/react/src/components/MailAccount/MailInfoBlock/MailInfoBlock.scss

@@ -1,4 +1,4 @@
-$primary: #2c54ac;
+@import 'src/utils/scss/variables';
 
 .mail-info-block {
   .select-group {

+ 2 - 1
src/react/src/components/MainNav/MainNav.jsx

@@ -165,8 +165,9 @@ const MainNav = () => {
       return "mobile-top-nav-wrapper hide";
     }
   }
+
   const topNavigation = () => {
-    if (document.documentElement.clientWidth > 900) {
+    if (window.innerWidth > 900) {
       return (
         <div className={topNavClassName()}>
           <Menu menuHeight={state.menuHeight} mobile={false} />

+ 72 - 27
src/react/src/components/MainNav/Mobile/MobileTopNav.jsx

@@ -1,37 +1,82 @@
-import React, { Component } from 'react';
+import React from 'react';
 import Menu from '../../MainNav/Stat-menu/Menu';
-import Toolbar from '../../MainNav/Toolbar/Toolbar';
+import { addActiveElement } from '../../../actions/MainNavigation/mainNavigationActions';
+import { useSelector, useDispatch } from "react-redux";
+import { Link } from "react-router-dom";
 import './MobileTopNav.scss';
 
-class MobileTopNav extends Component {
-  render() {
-    return (
-      <div className={this.props.class}>
-        <div className="mobile-menu">
-          <div>
-            <div>Packages</div>
-            <div>IP</div>
-            <div>Graphs</div>
-            <div>Statistics</div>
-            <div>Log</div>
+const MobileTopNav = props => {
+  const { i18n, userName } = useSelector(state => state.session);
+  const { session } = useSelector(state => state.userSession);
+  const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
+  const dispatch = useDispatch();
+
+  const className = (activeName, extraClass = '') => {
+    let className = 'top-link';
+
+    if (activeName === activeElement) {
+      className += ' active';
+    }
+
+    if (activeName === focusedElement) {
+      className += ' focus';
+    }
+
+    return className + ` ${extraClass}`;
+  }
+
+  const handleState = (tab, event) => {
+    if (`${window.location.pathname}${window.location.search}` === tab) {
+      return event.preventDefault();
+    }
+
+    dispatch(addActiveElement(tab));
+  }
+
+  return (
+    <div className={props.class}>
+      <div className="mobile-menu">
+        {userName === 'admin' && (<>
+          <div className={className("/list/package/")}>
+            <Link to="/list/package/" onClick={event => handleState("/list/package/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Packages}</Link>
           </div>
-          <div>
-            <div>Updates</div>
-            <div>Firewall</div>
-            <div className="fm">File Manager</div>
-            <div>Apps</div>
-            <div>Server</div>
+          <div className={className("/list/ip/")}>
+            <Link to="/list/ip/" onClick={event => handleState("/list/ip/", event)} onKeyPress={event => event.preventDefault()}>{i18n.IP}</Link>
           </div>
+          <div className={className("/list/rrd/")}>
+            <Link to="/list/rrd/" onClick={event => handleState("/list/rrd/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Graphs}</Link>
+          </div>
+        </>)}
+        <div className={className("/list/stats/")}>
+          <Link to="/list/stats/" onClick={event => handleState("/list/stats/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Statistics}</Link>
         </div>
-        <div className="mobile-stat-menu">
-          <Menu mobile={true} />
-        </div>
-        <div className="mobile-toolbar">
-          <Toolbar mobile={true} />
+        <div className={className("/list/log/")}>
+          <Link to="/list/log/" onClick={event => handleState("/list/log/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Log}</Link>
         </div>
+        {userName === 'admin' && (<>
+          <div className={className("/list/updates/")}>
+            <Link to="/list/updates/" onClick={event => handleState("/list/updates/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Updates}</Link>
+          </div>
+          {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>}
+        </>)}
+        {session.FILEMANAGER_KEY && <div className={className("/list/directory/")}>
+          <Link to="/list/directory/">{i18n['File Manager']}</Link>
+        </div>}
+        {session.SOFTACULOUS === "yes" && <div className={className("/softaculous/")}><Link to="/softaculous/" target="_blank">{i18n.Apps ?? 'Apps'}</Link>
+        </div>}
+        {userName === 'admin' && (
+          <div className={className("/list/server/")}>
+            <Link to="/list/server/" onClick={event => handleState("/list/server/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Server}</Link>
+          </div>
+        )}
       </div>
-    );
-  }
+      <div className="mobile-stat-menu">
+        <Menu mobile={true} />
+      </div>
+    </div>
+  );
 }
 
-export default MobileTopNav;
+export default MobileTopNav;

+ 108 - 30
src/react/src/components/MainNav/Mobile/MobileTopNav.scss

@@ -1,25 +1,87 @@
-$secondaryLight: #f8b014;
+@import 'src/utils/scss/variables';
+@import 'src/utils/scss/breakpoints';
 
 .mobile-top-nav-wrapper.hide {
   opacity: 0;
 }
 
 .mobile-top-nav-wrapper.show {
+  z-index: 5;
   opacity: 1;
   position: fixed;
   width: 100%;
-  height: 100vh;
+  height: 111px;
   background: white;
   display: flex;
   flex-direction: column;
   animation: showMobileNav forwards .3s;
-  margin-top: 34px;
+  margin-top: 82px;
 
-  > div {
-    height: 33.33%;
+  .mobile-menu {
+    padding: 0 10%;
+    flex-wrap: wrap;
+    margin-top: 15px;
+  }
+
+  > div .top-link {
     display: flex;
-    justify-content: center;
-    align-items: center;
+    font-size: 14px;
+    padding: 4px 0;
+
+    &:hover {
+      background: $secondaryLight;
+      
+      a, button {
+        color: $white;
+      }
+    }
+  }
+
+  div {
+    display: flex;
+    
+    a, button {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      padding: 0 10px !important;
+      width: max-content;
+      height: 100%;
+      text-decoration: none;
+      color: $black;
+    }
+
+    button {
+      background: none;
+      border: none;
+    }
+
+    &:hover {
+      cursor: pointer;
+    }
+  }
+
+  div.active {
+    background: white;
+    
+    a, button {
+      color: $secondary;
+      font-weight: bold;
+
+      &:hover {
+        color: white;
+      }
+
+      &:active {
+        background: $secondaryActive;
+        color: white;
+      }
+    }
+
+    &:hover {
+      color: white;
+      background: $secondaryLight;
+    }
   }
 
   .toolbar {
@@ -29,13 +91,37 @@ $secondaryLight: #f8b014;
   }
 
 
-  .mobile-stat-menu .menu-wrapper {
-    position: relative;
-    height: auto;
-    min-height: auto;
+  .mobile-stat-menu {
+    box-shadow: 0 5px 3px 0 hsla(0,0%,78.4%,.5);
 
-    .menu-stat {
-      margin: 0;
+    .menu-wrapper {
+      position: relative;
+      height: auto;
+      min-height: auto;
+      padding: 0;
+      margin-top: 9px;
+
+      .menu-stat {
+        margin: 0;
+
+        .stat {
+          text-align: left;
+          flex: 1 1 auto;
+          margin-bottom: 15px;
+        }
+      }
+    }
+  }
+}
+
+@media (max-width: 1066px) {
+  .mobile-stat-menu .menu-wrapper .menu-stat {
+    margin-top: 40px;
+
+    .stat {
+      .stats {
+        display: none;
+      }
     }
   }
 }
@@ -46,25 +132,17 @@ $secondaryLight: #f8b014;
   }
 }
 
-@media (max-width: 450px) {
-  .mobile-top-nav-wrapper.show .mobile-menu {
-    padding: 15px 0 0 15px;
-    font-size: 19px;
-    height: 27%;
-
-    > div {
-      width: 50%;
-      height: 100%;
-
-      > div {
-        padding: 2px;
-
-        &:hover {
-          color: $secondaryLight;
-        }
-      }
+@media (max-width: 725px) {
+  .mobile-top-nav-wrapper.show {
+    .menu-stat {
+      display: flex;
+      flex-wrap: wrap;
     }
   }
+
+  .mobile-menu {
+    padding: 0 10%;
+  }
 }
 
 @keyframes showMobileNav {

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

@@ -132,7 +132,13 @@ const Panel = props => {
 
       <div className="top-panel small-device">
         <div className="container left-menu">
-          <div className="logo">LOGO</div>
+          <div className="logo">
+            <Link to="/list/user/" onClick={() => dispatch(addActiveElement('/list/user/'))}>
+              <div>
+                <img src="/images/white_logo.png" alt="Logo" />
+              </div>
+            </Link>
+          </div>
         </div>
         <div className="container hamburger" onClick={toggleNavigation}>
           <span className="bar"></span>
@@ -140,9 +146,7 @@ const Panel = props => {
           <span className="bar"></span>
         </div>
         <div className="container profile-menu">
-          <div className="bell">
-            <FontAwesomeIcon icon="bell" />
-          </div>
+          {panel[userName]['NOTIFICATIONS'] === 'yes' && <Notifications />}
           <div><Link to={`/edit/user?user=${userName}`}>{userName}</Link></div>
           <div><button onClick={signOut}>{i18n['Log out']}</button></div>
         </div>
@@ -151,4 +155,4 @@ const Panel = props => {
   );
 }
 
-export default Panel;
+export default Panel;

+ 31 - 51
src/react/src/components/MainNav/Panel/Panel.scss

@@ -1,13 +1,5 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
+@import 'src/utils/scss/breakpoints';
 
 .top-panel.small-device {
   display: none;
@@ -24,6 +16,7 @@ $textColor: #555;
   background: #222e44;
   height: 34px;
   align-items: center;
+  justify-content: space-between;
   padding: 0 13%;
   z-index: 2;
 
@@ -53,7 +46,7 @@ $textColor: #555;
         justify-content: center;
         align-items: center;
         padding: 0 10px !important;
-        width: 100%;
+        width: max-content;
         height: 100%;
         text-decoration: none;
         color: white;
@@ -94,8 +87,8 @@ $textColor: #555;
 
   .left-menu {
     width: 75%;
-    padding-left: 0;
-    margin-left: 0;
+    margin: 0;
+    padding: 0;
     justify-content: space-between;
 
     div {
@@ -141,7 +134,10 @@ $textColor: #555;
   }
 
   .profile-menu {
-    width: auto;
+    width: 25%;
+    margin: 0;
+    padding: 0;
+    justify-content: flex-end;
 
     div {
       height: 100%;
@@ -240,36 +236,37 @@ $textColor: #555;
   }
 }
 
-@media screen and (max-width: 1350px) {
+@media screen and (min-width: $desktopMax) {
   .top-panel {
     padding: 0 10%;
   }
 }
 
-@media screen and (max-width: 1024px) {
+@media screen and (max-width: $desktopMin) {
+  .top-panel {
+    padding: 0 8%;
+  }
+}
+
+@media screen and (max-width: 1200px) {
   .top-panel {
-    padding: 0 5%;
+    padding: 0 10%;
   }
 }
 
-//Small Devices
-@media (max-width: 900px) {
+@media (max-width: 1065px) {
   .top-panel {
     display: none;
   }
 
   .top-panel.small-device {
     display: flex;
-    padding: 0;
+    justify-content: space-between;
+    padding: 0 10%;
 
     > .container {
-      justify-content: center;
       align-items: center;
-      width: 30%;
-    }
-
-    .profile-menu {
-      padding-left: 10%;
+      width: auto;
     }
 
     .hamburger {
@@ -287,35 +284,18 @@ $textColor: #555;
       }
     }
   }
-
-  @keyframes toggleNav {
-    from {
-      transform: translateY(-20px);
-    }
-
-    to {
-      transform: translateY(50px);
-    }
-  }
 }
 
-@media (max-width: 420px) {
+@media (max-width: $phoneMax) {
   .top-panel.small-device {
-    .profile-menu {
-      padding: 0;
-      margin-right: 5px;
+    padding: 0;
+  }
 
-      .bell {
-        width: 20%;
-      }
+  .top-panel .left-menu div.logo {
+    width: unset;
 
-      .bell + div {
-        width: 40%;
-      }
-
-      .bell + div + div {
-        width: 40%;
-      }
+    a div {
+      width: 5rem;
     }
   }
-}
+}

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

@@ -50,20 +50,6 @@ const Menu = props => {
     return `stat ${activeName === activeElement && 'l-active'} ${activeName === focusedElement && 'focus'}`;
   }
 
-  const sizeFormatter = (bytes, decimals) => {
-    if (!bytes) return null;
-
-    if (bytes === "0") {
-      return <span className="value">0 <span className="unit">b</span></span>;
-    }
-
-    let k = 1024,
-      dm = decimals <= 0 ? 0 : decimals || 2,
-      sizes = ['b', 'kb', 'Mb', 'GB'],
-      i = Math.floor(Math.log(bytes) / Math.log(k));
-    return (<span className="value">{parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} <span className="unit">{sizes[i]}</span></span>);
-  }
-
   return (
     <div className="menu-wrapper">
       <div className={className(props.menuHeight)} style={{ height: style(props) }}>

+ 15 - 59
src/react/src/components/MainNav/Stat-menu/Menu.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .menu-wrapper {
   position: fixed;
@@ -18,7 +9,7 @@ $textColor: #555;
   .menu-stat {
     display: flex;
     flex-direction: row;
-    margin-top: 70px;
+    margin-top: 50px;
     min-height: 45px;
     max-height: 135px;
     height: 145px;
@@ -152,13 +143,24 @@ $textColor: #555;
   }
 }
 
+@media screen and (max-width: 1066px) {
+  .menu-wrapper {
+    .menu-stat {
+      padding: 0 10%;
+      margin-top: 40px;
+    }
+  }
+}
+
 @media screen and (max-width: 1024px) {
   .menu-wrapper {
-    padding: 0 10%;
+    .menu-stat {
+      padding: 0 10%;
+    }
   }
 }
 
-@media (max-width: 900px) {
+@media (max-width: 1066px) {
   .menu-wrapper {
     padding: 1%;
 
@@ -167,55 +169,9 @@ $textColor: #555;
       min-height: auto;
 
       .stat {
-        flex-grow: 1;
-        height: 30px;
-        padding-left: 5px;
-        min-width: 14%;
-        text-align: left;
-
         h3 {
           padding: 0;
         }
-
-        .stats {
-          display: none;
-        }
-      }
-    }
-  }
-}
-
-@media (max-width: 450px) {
-  .main-nav .mobile-top-nav-wrapper.show .mobile-stat-menu {
-    border: 1px solid black;
-    border-width: 1px 0;
-    margin-top: 15px;
-
-    .menu-wrapper {
-      height: 100%;
-      padding: 0;
-
-      .menu-stat {
-        flex-wrap: wrap;
-        max-height: 100%;
-        min-height: 100%;
-
-        .stat {
-          display: flex;
-          align-items: center;
-          border: none;
-          padding: 5px 5px 5px 15px;
-          min-width: 50%;
-          height: auto;
-
-          h3 {
-            margin: 0;
-          }
-        }
-
-        .stat.l-active {
-          background: #fdac020d;
-        }
       }
     }
   }

+ 11 - 10
src/react/src/components/MainNav/Toolbar/LeftButton/LeftButton.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .l-menu {
   transform: translate(35px, 50%);
@@ -39,6 +30,12 @@ $textColor: #555;
       }
     }
 
+    @media screen and (max-width: 900px) {
+      span.add {
+        display: none !important;
+      }
+    }
+
     &:active {
       background: $primary;
 
@@ -72,6 +69,10 @@ $textColor: #555;
       height: 21px;
     }
   }
+
+  @media screen and (max-width: 900px) {
+    transform: unset;
+  }
 }
 
 .l-menu.none {

+ 4 - 0
src/react/src/components/MainNav/Toolbar/Select/Select.scss

@@ -1,6 +1,10 @@
 .select-wrapper {
   display: flex;
 
+  select {
+    width: auto;
+  }
+
   select, button {
     border-radius: 0;
   }

+ 30 - 38
src/react/src/components/MainNav/Toolbar/Toolbar.jsx

@@ -1,70 +1,62 @@
-import React, { Component } from 'react';
+import React, { useEffect, useState } from 'react';
 import './Toolbar.scss';
 
-class Toolbar extends Component {
-  state = {
-    toolbarHeight: 205
-  }
+const Toolbar = props => {
+  const [toolbarHeight, setToolbarHeight] = useState(185);
 
-  componentDidMount() {
-    window.addEventListener("resize", this.handleToolbar);
-    document.addEventListener("scroll", this.changeToolbarHeight);
-  }
+  useEffect(() => {
+    window.addEventListener("resize", handleToolbar);
+    document.addEventListener("scroll", changeToolbarHeight);
 
-  componentWillUnmount() {
-    window.removeEventListener("resize", this.handleToolbar);
-    document.removeEventListener("scroll", this.changeToolbarHeight);
-  }
+    return () => {
+      window.removeEventListener("resize", handleToolbar);
+      document.removeEventListener("scroll", changeToolbarHeight);
+    }
+  }, []);
 
-  handleToolbar = () => {
+  const handleToolbar = () => {
     if (document.documentElement.clientWidth < 900) {
-      this.setState({
-        toolbarHeight: 115
-      });
+      setToolbarHeight(95);
     } else {
-      this.setState({
-        toolbarHeight: 205
-      });
+      setToolbarHeight(185);
     }
   }
 
-  changeToolbarHeight = () => {
+  const changeToolbarHeight = () => {
     if (document.documentElement.clientWidth > 900) {
       let scrollTop = window.scrollY;
-      let toolbarHeight = Math.max(115, 205 - scrollTop);
-      this.setState({ toolbarHeight });
+      let newToolbarHeight = Math.max(95, 185 - scrollTop);
+      setToolbarHeight(newToolbarHeight);
     }
   }
 
-  className = () => {
-    const { className } = this.props;
+  const className = () => {
+    const { className } = props;
 
     if (className === "justify-right") {
-      return this.state.toolbarHeight === 115 ? "toolbar t-shadow " + className : "toolbar " + className;
+      return toolbarHeight === 95 ? "toolbar t-shadow " + className : "toolbar " + className;
     }
 
-    return this.state.toolbarHeight === 115 ? "toolbar t-shadow" : "toolbar";
+    return toolbarHeight === 95 ? "toolbar t-shadow" : "toolbar";
   }
 
-  style = () => {
-    if (this.props.mobile) {
+  const style = () => {
+    if (props.mobile) {
       return;
     }
 
     if (document.documentElement.clientWidth > 900) {
-      return { marginTop: this.state.toolbarHeight };
+      return { marginTop: toolbarHeight };
     } else {
-      return { marginTop: 145 };
+      return { marginTop: 33 };
     }
   }
 
-  render() {
-    return (
-      <div className={this.className()} style={this.style()}>
-        {this.props.children}
-      </div>
-    );
-  }
+  return (
+    <div className={className()} style={style()} id="v-toolbar">
+      {props.children}
+    </div>
+  );
 }
 
 export default Toolbar;

+ 33 - 13
src/react/src/components/MainNav/Toolbar/Toolbar.scss

@@ -1,15 +1,4 @@
-$primary: #2c54ac;
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .toolbar {
   display: flex;
@@ -27,8 +16,15 @@ $textColor: #555;
 
   .r-menu {
     display: flex;
-    justify-content: center;
     align-items: center;
+    overflow-x: scroll;
+
+    > div {
+      display: flex;
+      flex-wrap: unset;
+      width: 100%;
+      align-items: center;
+    }
 
     a.button-extra,
     button.button-extra {
@@ -157,6 +153,30 @@ $textColor: #555;
   }
 }
 
+@media (max-width: 900px) {
+  .toolbar {
+    .r-menu {
+      // overflow: scroll;
+
+      > div {
+        margin-left: 3rem;
+        // overflow: scroll;
+        position: relative;
+        display: flex;
+        flex-wrap: unset;
+        width: 100%;
+        align-items: center;
+      }
+    }
+  }
+}
+
+@media (max-width: 450px) {
+  .toolbar {
+    padding: 3px 1% 1px;
+  }
+}
+
 @media (max-width: 450px) {
   .mobile-toolbar .toolbar {
     display: flex;

+ 1 - 10
src/react/src/components/Menu/Menu.scss

@@ -1,13 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .menu {
   display: flex;

+ 1 - 12
src/react/src/components/Modal/Modal.scss

@@ -1,15 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
-$black: #000;
+@import 'src/utils/scss/variables';
 
 .modal {
   display: block;

+ 1 - 12
src/react/src/components/Path/Path.scss

@@ -1,15 +1,4 @@
-$white: #fff;
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .path {
   display: flex;

+ 1 - 1
src/react/src/components/Server/Edit/EditBackupOption.jsx

@@ -12,7 +12,7 @@ const EditBackupOption = ({ data, visible }) => {
   return (
     <div className="server-dns-option" style={{ display: `${visible ? 'block' : 'none'}` }}>
       <SelectInput
-        options={[i18n['no'], i18n['yes']]}
+        options={['no', 'yes']}
         title={i18n['Local backup']}
         selected={data.backup}
         name="v_backup"

+ 2 - 3
src/react/src/components/Server/Edit/EditDatabaseOption.jsx

@@ -1,8 +1,7 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
 
 import SelectInput from 'src/components/ControlPanel/AddItemLayout/Form/SelectInput/SelectInput';
 import TextInput from 'src/components/ControlPanel/AddItemLayout/Form/TextInput/TextInput';
-import Checkbox from 'src/components/ControlPanel/AddItemLayout/Form/Checkbox/Checkbox';
 import { Link } from 'react-router-dom';
 import { useSelector } from 'react-redux';
 
@@ -86,7 +85,7 @@ const EditDatabaseOption = ({ data, visible }) => {
           <>
             <TextInput
               title={i18n['phpMyAdmin URL']}
-              value={data.db_pma_url}
+              value={data.mail_url}
               name="v_mysql_url"
               id="mysql_url" />
 

+ 4 - 0
src/react/src/components/Server/Edit/EditServer.jsx

@@ -73,6 +73,10 @@ const EditServer = props => {
       updatedServer[name] = value;
     }
 
+    if (updatedServer['v_backup_type']) {
+      updatedServer['v_backup_type'] = updatedServer['v_backup_type'].toLowerCase();
+    }
+
     updatedServer['save'] = 'save';
     updatedServer['token'] = token;
 

+ 1 - 11
src/react/src/components/Server/Edit/EditServer.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .edit-server {
   .modules {

+ 1 - 1
src/react/src/components/Spinner/Spinner.scss

@@ -1,7 +1,7 @@
 .spinner-wrapper {
   position: absolute;
   bottom: 5px;
-  width: 15%;
+  width: 150px;
   left: 42%;
   height: 10px;
 }

+ 9 - 2
src/react/src/components/Statistic/Statistic.jsx

@@ -35,8 +35,15 @@ const Statistic = props => {
         <div className="name">{printName(data.DATE)}</div>
         <div className="stats">
           <Container className="c-1">
-            <div className="bandwidth">{i18n.Bandwidth} <span><span className="stat">{data.U_BANDWIDTH}</span>{i18n.mb}</span></div>
-            <div className="disk">{i18n.Disk}: <span><span className="stat">{data.U_DISK}</span>{i18n.mb}</span></div>
+            <div className="bandwidth">
+              {i18n.Bandwidth}
+              <span><span className="stat">{data.U_BANDWIDTH}</span>{i18n.mb}</span>
+              <div className="percent" style={{ width: `${data.U_BANDWIDTH_PERCENT}%` || '0%' }}></div>
+            </div>
+            <div className="disk">
+              {i18n.Disk}: <span><span className="stat">{data.U_DISK}</span>{i18n.mb}</span>
+              <div className="percent" style={{ width: `${data.U_DISK_PERCENT}%` || '0%' }}></div>
+            </div>
             <div className="sub-disk-stats">
               <div>
                 <div>{i18n.Web}: <span><span className="stat">{data.U_DISK_WEB}</span>{i18n.mb}</span></div>

+ 1 - 11
src/react/src/components/TopPanel/TopPanel.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .panel-wrapper {
   .logo-img {

+ 1 - 11
src/react/src/components/User/Add/AddUser.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .password-wrapper {
   display: flex;

+ 9 - 2
src/react/src/components/User/User.jsx

@@ -76,8 +76,15 @@ const User = ({ data, toggleFav, handleModal, checkItem, logOut, logInAs }) => {
         <div>{data.FNAME} {data.LNAME}</div>
         <div className="stats">
           <Container className="c-1">
-            <div className="bandwidth">{i18n.Bandwidth} <span><span className="stat">{data.U_BANDWIDTH}</span> {data.U_BANDWIDTH_MEASURE}</span></div>
-            <div className="disk">{i18n.Disk}: <span><span className="stat">{data.U_DISK}</span> {data.U_DISK_MEASURE}</span></div>
+            <div className="bandwidth">
+              {i18n.Bandwidth}
+              <span><span className="stat">{data.U_BANDWIDTH}</span> {data.U_BANDWIDTH_MEASURE}</span>
+              <div className="percent" style={{ width: `${data.U_BANDWIDTH_PERCENT}%` || '0%' }}></div>
+            </div>
+            <div className="disk">
+              {i18n.Disk}: <span><span className="stat">{data.U_DISK}</span> {data.U_DISK_MEASURE}</span>
+              <div className="percent" style={{ width: `${data.U_DISK_PERCENT}%` || '0%' }}></div>
+            </div>
             <div className="sub-disk-stats">
               <div>
                 <div><span>{i18n.Web}:</span> <span><b>{data.U_DISK_WEB}</b> {data.U_DISK_WEB_MEASURE}</span></div>

+ 32 - 12
src/react/src/components/User/User.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .checkbox {
   margin-bottom: 10px;
@@ -75,6 +65,16 @@ span.stat.email{
         justify-content: space-between;
         margin-bottom: 25px;
         border-bottom: 1px dotted gray;
+        position: relative;
+
+        .percent {
+          position: absolute;
+          left: 0px;
+          bottom: -1px;
+          height: 2px;
+          background: $primary;
+          width: 0%;
+        }
       }
 
       .sub-disk-stats {
@@ -201,8 +201,28 @@ span.stat.email{
   svg {
     margin-left: 12px;
   }
+
+  @media (max-width: 1066px) {
+    opacity: 1;
+  }
+
+  @media (max-width: 850px) {
+    > div {
+      width: max-content;
+
+      a, button {
+        width: 100%;
+      }
+    }
+  }
 }
 
 .list-item.focused .r-col .name {
   color: $secondaryLight;
-}
+}
+
+@media (max-width: 1066px) {
+  div.star div > svg {
+    opacity: 1 !important;
+  }
+}

+ 1 - 8
src/react/src/components/WebDomain/Edit/SslSupport/SslSupport.scss

@@ -1,11 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #2e5bb1;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$secondaryActive: #fdb51c;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .edit-web {
   .ssl-support {

+ 9 - 2
src/react/src/components/WebDomain/WebDomain.jsx

@@ -77,8 +77,15 @@ export default function WebDomain(props) {
         <div>{data.IP}</div>
         <div className="stats">
           <Container className="c-1 w-25">
-            <div className="bandwidth">{i18n.Bandwidth} <span><span className="stat">{data.U_BANDWIDTH_SIZE}</span>{data.U_BANDWIDTH_MEASURE}</span></div>
-            <div className="disk">{i18n.Disk}: <span><span className="stat">{data.U_DISK_SIZE}</span>{data.U_DISK_MEASURE}</span></div>
+            <div className="bandwidth">
+              {i18n.Bandwidth}
+              <span><span className="stat">{data.U_BANDWIDTH_SIZE}</span>{data.U_BANDWIDTH_MEASURE}</span>
+              <div className="percent" style={{ width: `${data.U_BANDWIDTH_PERCENT}%` || '0%' }}></div>
+            </div>
+            <div className="disk">
+              {i18n.Disk}: <span><span className="stat">{data.U_DISK_SIZE}</span>{data.U_DISK_MEASURE}</span>
+              <div className="percent" style={{ width: `${data.U_DISK_PERCENT}%` || '0%' }}></div>
+            </div>
           </Container>
           <Container className="c-2 w-45">
             <div>{i18n['Web Template']}: <span className="stat">{data.TPL}</span></div>

+ 83 - 11
src/react/src/containers/App/App.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 html {
   overflow-y: scroll;
@@ -81,6 +71,25 @@ html {
   }
 }
 
+@media screen and (max-width: 700px) {
+  .actions {
+    background: unset !important;
+    flex-wrap: wrap;
+    justify-content: flex-end !important;
+
+    div {
+      height: 30px !important;
+
+      a,button {
+        background: #dfdedd !important;
+        padding: 0px 10px !important;
+        height: 100% !important;
+        font-size: 10px !important;
+      }
+    }
+  }
+}
+
 button:active, a:active, .period:active {
   color: $primaryActive;
 }
@@ -176,3 +185,66 @@ button {
     }
   }
 }
+
+@media (min-width: 1067px) {
+  .App div.content {
+    padding-top: 0 !important;
+    margin-top: -20px !important;
+  }
+}
+
+@media (max-width: 1066px) {
+  .App div.content {
+    padding-top: 0 !important;
+    margin-top: -20px !important;
+  }
+
+  .content > div {
+    .l-col {
+      margin-top: 2rem;
+      padding-left: 5px;
+    }
+
+    .r-col {
+      margin-top: 1rem;
+      .name {
+        margin-top: 2rem;
+      }
+
+      .stats {
+        flex-wrap: wrap;
+
+        > div {
+          margin: 1rem 0 !important;
+          padding: 0 !important;
+          width: 100% !important;
+        }
+      }
+    }
+  }
+}
+
+@media (max-width: 900px) {
+  .App div.content {
+    padding-top: 77px !important;
+    margin-top: 0 !important;
+  }
+
+  .content > div {
+    .l-col {
+      padding-left: 5px;
+    }
+
+    .r-col {
+      padding-left: 2rem;
+    }
+  }
+}
+
+@media (max-width: 725px) {
+  .content {
+    .r-col {
+      padding-left: 3.5rem;
+    }
+  }
+}

+ 21 - 13
src/react/src/containers/ControlPanelContent/ControlPanelContent.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .content {
   padding: 0 13%;
@@ -29,9 +19,15 @@ $textColor: #555;
   }
 }
 
-@media (max-width: 1000px) {
+@media (max-width: 1066px) {
   .content {
-    padding: 5%;
+    padding: 5% 10%;
+  }
+}
+
+@media (max-width: 900px) {
+  .content {
+    margin-top: 40px;
   }
 }
 
@@ -114,3 +110,15 @@ $textColor: #555;
     }
   }
 }
+
+@media screen and (max-width: 1066px) {
+  .fixed-buttons > div:first-child {
+    display: none;
+  }
+}
+
+@media screen and (max-width: 450px) {
+  .content {
+    padding: 5% 1%;
+  }
+}

+ 2 - 2
src/react/src/containers/CronJobs/CronJobs.jsx

@@ -175,7 +175,7 @@ const CronJobs = props => {
             cronFav: result.data.cron_fav,
             selection: [],
             toggledAll: false,
-            totalAmount: result.data.totalAmount
+            totalAmount: result.data.totalAmount,
           });
           resolve();
         })
@@ -385,7 +385,7 @@ const CronJobs = props => {
     handleAction(url)
       .then(res => {
         displayModal(res.data.message, '');
-        fetchData();
+        fetchData().then(() => setLoading(false));
       })
       .catch(err => console.error(err));
   }

+ 1 - 11
src/react/src/containers/CronJobs/CronJobs.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .r-menu {
   > div {

+ 1 - 11
src/react/src/containers/DNSRecords/DNSRecords.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 .dns-records {
   div.subtitle {

+ 1 - 1
src/react/src/containers/MailAccounts/MailAccounts.scss

@@ -1,4 +1,4 @@
-$primary: #2c54ac;
+@import 'src/utils/scss/variables';
 
 .mail-accounts {
   div.subtitle {

+ 2 - 2
src/react/src/containers/Mails/Mails.jsx

@@ -395,13 +395,13 @@ const Mails = props => {
         <LeftButton name="Add Mail Domain" href="/add/mail" showLeftMenu={true} />
         <div className="r-menu">
           <div className="input-group input-group-sm">
-            <Link
+            {state.webmail && <Link
               to={{ pathname: `http://${window.location.hostname}${state.webmail}` }}
               target="_blank"
               className="button-extra"
               type="submit">
               {i18n['open webmail']}
-            </Link>
+            </Link>}
             <Checkbox toggleAll={toggleAll} toggled={state.toggledAll} />
             <Select list='mailList' bulkAction={bulk} />
             <DropdownFilter changeSorting={changeSorting} sorting={state.sorting} order={state.order} list="mailList" />

+ 1 - 11
src/react/src/containers/RRDs/RRDs.scss

@@ -1,14 +1,4 @@
-$whiteBackground: #ececec;
-$primary: #2c54ac;
-$primaryLight: #d7dcef;
-$primaryActive: #1e5cb2;
-$secondary: #fcac04;
-$secondaryLight: #f8b014;
-$danger: #b00e5b;
-$secondaryActive: #fdb51c;
-$hoverButtonText: #2c54ac;
-$activeButtonText: #fff;
-$textColor: #555;
+@import 'src/utils/scss/variables';
 
 div.content {
   margin-top: 0;

+ 11 - 0
src/react/src/utils/scss/_breakpoints.scss

@@ -0,0 +1,11 @@
+$phoneMin: 320px;
+$phoneMax: 480px;
+
+$tabletMin: 481px;
+$tabletMax: 768px;
+
+$smallScreenMin: 769px;
+$smallScreenMax: 1024px;
+
+$desktopMin: 1025px;
+$desktopMax: 1200px;

+ 13 - 0
src/react/src/utils/scss/_variables.scss

@@ -0,0 +1,13 @@
+$whiteBackground: #ececec;
+$primary: #2c54ac;
+$primaryLight: #d7dcef;
+$primaryActive: #1e5cb2;
+$secondary: #fcac04;
+$secondaryLight: #f8b014;
+$secondaryActive: #fdb51c;
+$hoverButtonText: #2c54ac;
+$activeButtonText: #fff;
+$textColor: #555;
+$danger: #b00e5b;
+$black: #000;
+$white: #fff;