diff --git a/app/app.js b/app/app.js
index bf795ccc6..5e94c74f0 100644
--- a/app/app.js
+++ b/app/app.js
@@ -31,10 +31,6 @@ angular.module('portainer').run([
HttpRequestHelper.resetAgentHeaders();
});
- $state.defaultErrorHandler(function () {
- // Do not log transitionTo errors
- });
-
// Keep-alive Edge endpoints by sending a ping request every minute
$interval(function () {
ping(EndpointProvider, SystemService);
diff --git a/app/assets/css/app.css b/app/assets/css/app.css
index 8d946337d..d88bfc110 100644
--- a/app/assets/css/app.css
+++ b/app/assets/css/app.css
@@ -376,98 +376,6 @@ a[ng-click] {
margin: 0 auto;
}
-ul.sidebar {
- position: relative;
- overflow: hidden;
- flex-shrink: 0;
-}
-
-ul.sidebar .sidebar-title {
- height: auto;
-}
-
-ul.sidebar .sidebar-title.endpoint-name {
- color: #fff;
- text-align: center;
- text-indent: 0;
-}
-
-ul.sidebar .sidebar-list a {
- font-size: 14px;
-}
-
-ul.sidebar .sidebar-list a.active {
- color: #fff;
- text-indent: 22px;
- border-left: 3px solid #fff;
- background: #2d3e63;
-}
-
-.sidebar-header {
- height: 60px;
- list-style: none;
- text-indent: 20px;
- font-size: 18px;
- background: #2d3e63;
-}
-
-.sidebar-header a {
- color: #fff;
-}
-.sidebar-header a:hover {
- text-decoration: none;
-}
-
-.sidebar-header .menu-icon {
- float: right;
- padding-right: 28px;
- line-height: 60px;
-}
-
-#page-wrapper:not(.open) .sidebar-footer-content {
- display: none;
-}
-
-.sidebar-footer-content {
- text-align: center;
-}
-
-.sidebar-footer-content .logo {
- width: 100%;
- max-width: 100px;
- height: 100%;
- max-height: 35px;
- margin: 2px 0 2px 20px;
-}
-
-.sidebar-footer-content .update-notification {
- font-size: 14px;
- padding: 12px;
- border-radius: 2px;
- background-color: #ff851b;
- margin-bottom: 5px;
-}
-
-.sidebar-footer-content .version {
- font-size: 11px;
- margin: 11px 20px 0 7px;
- color: #fff;
-}
-
-#sidebar-wrapper {
- display: flex;
- flex-flow: column;
-}
-
-.sidebar-content {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- overflow-y: auto;
- overflow-x: hidden;
- height: 100%;
-}
-
#image-layers .btn {
padding: 0;
}
@@ -481,86 +389,6 @@ ul.sidebar .sidebar-list a.active {
font-size: 90%;
}
-ul.sidebar .sidebar-list a.active .menu-icon {
- text-indent: 25px;
-}
-
-ul.sidebar .sidebar-list .sidebar-sublist a {
- text-indent: 35px;
- font-size: 12px;
- color: #b2bfdc;
- line-height: 36px;
-}
-
-ul.sidebar .sidebar-title {
- line-height: 36px;
-}
-ul.sidebar .sidebar-title .form-control {
- height: 36px;
- padding: 6px 12px;
-}
-
-ul.sidebar .sidebar-list {
- height: 36px;
-}
-
-ul.sidebar .sidebar-list a,
-ul.sidebar .sidebar-list .sidebar-sublist a {
- line-height: 36px;
-}
-
-ul.sidebar .sidebar-list .menu-icon {
- line-height: 36px;
-}
-
-ul.sidebar .sidebar-list .sidebar-sublist a.active {
- color: #fff;
- border-left: 3px solid #fff;
- background: #2d3e63;
-}
-
-@media (max-height: 785px) {
- ul.sidebar .sidebar-title {
- line-height: 26px;
- }
- ul.sidebar .sidebar-title .form-control {
- height: 26px;
- padding: 3px 6px;
- }
- ul.sidebar .sidebar-list {
- height: 26px;
- }
- ul.sidebar .sidebar-list a,
- ul.sidebar .sidebar-list .sidebar-sublist a {
- font-size: 12px;
- line-height: 26px;
- }
- ul.sidebar .sidebar-list .menu-icon {
- line-height: 26px;
- }
-}
-
-@media (min-height: 786px) and (max-height: 924px) {
- ul.sidebar .sidebar-title {
- line-height: 30px;
- }
- ul.sidebar .sidebar-title .form-control {
- height: 30px;
- padding: 5px 10px;
- }
- ul.sidebar .sidebar-list {
- height: 30px;
- }
- ul.sidebar .sidebar-list a,
- ul.sidebar .sidebar-list .sidebar-sublist a {
- font-size: 12px;
- line-height: 30px;
- }
- ul.sidebar .sidebar-list .menu-icon {
- line-height: 30px;
- }
-}
-
@media (min-width: 768px) {
.margin-sm-top {
margin-top: 5px;
diff --git a/app/assets/css/rdash.css b/app/assets/css/rdash.css
index 950d8fd8d..a9dc4ff48 100644
--- a/app/assets/css/rdash.css
+++ b/app/assets/css/rdash.css
@@ -14,9 +14,6 @@
padding-left: 70px;
}
}
-#page-wrapper.open #sidebar-wrapper {
- left: 150px;
-}
/**
* Hamburg Menu
@@ -254,139 +251,6 @@ div.input-mask {
padding-top: 7px;
}
-/* #592727 RED */
-/* #2f5927 GREEN */
-/* #30426a BLUE (default)*/
-/* Sidebar background color */
-/* Sidebar header and footer color */
-/* Sidebar title text colour */
-/* Sidebar menu item hover color */
-/**
- * Sidebar
- */
-#sidebar-wrapper {
- background: #30426a;
-}
-ul.sidebar .sidebar-main a,
-.sidebar-footer,
-ul.sidebar .sidebar-list a:hover,
-#page-wrapper:not(.open) ul.sidebar .sidebar-title.separator {
- /* Sidebar header and footer color */
- background: #2d3e63;
-}
-ul.sidebar {
- position: absolute;
- top: 0;
- bottom: 0;
- padding: 0;
- margin: 0;
- list-style: none;
- text-indent: 20px;
- overflow-x: hidden;
- overflow-y: auto;
-}
-ul.sidebar li a {
- color: #fff;
- display: block;
- float: left;
- text-decoration: none;
- width: 250px;
-}
-ul.sidebar .sidebar-main {
- height: 65px;
-}
-ul.sidebar .sidebar-main a {
- font-size: 18px;
- line-height: 60px;
-}
-ul.sidebar .sidebar-main a:hover {
- cursor: pointer;
-}
-ul.sidebar .sidebar-main .menu-icon {
- float: right;
- font-size: 18px;
- padding-right: 28px;
- line-height: 60px;
-}
-ul.sidebar .sidebar-title {
- color: #738bc0;
- font-size: 12px;
- height: 35px;
- line-height: 40px;
- text-transform: uppercase;
- transition: all 0.6s ease 0s;
-}
-ul.sidebar .sidebar-list {
- height: 40px;
-}
-ul.sidebar .sidebar-list a {
- text-indent: 25px;
- font-size: 15px;
- color: #b2bfdc;
- line-height: 40px;
-}
-ul.sidebar .sidebar-list a:hover {
- color: #fff;
- border-left: 3px solid #e99d1a;
- text-indent: 22px;
-}
-ul.sidebar .sidebar-list a:hover .menu-icon {
- text-indent: 25px;
-}
-ul.sidebar .sidebar-list .menu-icon {
- float: right;
- padding-right: 29px;
- line-height: 40px;
- width: 70px;
-}
-#page-wrapper:not(.open) ul.sidebar {
- bottom: 0;
-}
-#page-wrapper:not(.open) ul.sidebar .sidebar-title {
- display: none;
- height: 0px;
- text-indent: -100px;
-}
-#page-wrapper:not(.open) ul.sidebar .sidebar-title.separator {
- display: block;
- height: 2px;
- margin: 13px 0;
-}
-#page-wrapper:not(.open) ul.sidebar .sidebar-list a:hover span {
- border-left: 3px solid #e99d1a;
- text-indent: 22px;
-}
-#page-wrapper:not(.open) .sidebar-footer {
- display: none;
-}
-.sidebar-footer {
- position: absolute;
- height: 40px;
- bottom: 0;
- width: 100%;
- padding: 0;
- margin: 0;
- transition: all 0.6s ease 0s;
- text-align: center;
-}
-.sidebar-footer div a {
- color: #b2bfdc;
- font-size: 12px;
- line-height: 43px;
-}
-.sidebar-footer div a:hover {
- color: #ffffff;
- text-decoration: none;
-}
-
-/* #592727 RED */
-/* #2f5927 GREEN */
-/* #30426a BLUE (default)*/
-/* Sidebar background color */
-/* Sidebar header and footer color */
-/* Sidebar title text colour */
-/* Sidebar menu item hover color */
-
/**
* Widgets
*/
diff --git a/app/azure/components/azure-sidebar-content/azure-sidebar-content.js b/app/azure/components/azure-sidebar-content/azure-sidebar-content.js
deleted file mode 100644
index 1cdf11ca3..000000000
--- a/app/azure/components/azure-sidebar-content/azure-sidebar-content.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import angular from 'angular';
-
-angular.module('portainer.azure').component('azureSidebarContent', {
- templateUrl: './azureSidebarContent.html',
- bindings: {
- endpointId: '<',
- },
-});
diff --git a/app/azure/components/azure-sidebar-content/azureSidebarContent.html b/app/azure/components/azure-sidebar-content/azureSidebarContent.html
deleted file mode 100644
index d6e68d12b..000000000
--- a/app/azure/components/azure-sidebar-content/azureSidebarContent.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
diff --git a/app/azure/components/azure-sidebar/azure-sidebar.html b/app/azure/components/azure-sidebar/azure-sidebar.html
new file mode 100644
index 000000000..7f6c5345a
--- /dev/null
+++ b/app/azure/components/azure-sidebar/azure-sidebar.html
@@ -0,0 +1,7 @@
+
+ Dashboard
+
+
+
+ Container instances
+
diff --git a/app/azure/components/azure-sidebar/index.js b/app/azure/components/azure-sidebar/index.js
new file mode 100644
index 000000000..5b5b13f8b
--- /dev/null
+++ b/app/azure/components/azure-sidebar/index.js
@@ -0,0 +1,8 @@
+import angular from 'angular';
+
+angular.module('portainer.azure').component('azureSidebar', {
+ templateUrl: './azure-sidebar.html',
+ bindings: {
+ endpointId: '<',
+ },
+});
diff --git a/app/docker/components/docker-sidebar/docker-sidebar.html b/app/docker/components/docker-sidebar/docker-sidebar.html
new file mode 100644
index 000000000..59866f008
--- /dev/null
+++ b/app/docker/components/docker-sidebar/docker-sidebar.html
@@ -0,0 +1,121 @@
+
+ Dashboard
+
+
+
+
+ Custom Templates
+
+
+
+
+ Stacks
+
+
+
+ Services
+
+
+
+ Containers
+
+
+
+ Images
+
+
+
+ Networks
+
+
+
+ Volumes
+
+
+
+ Configs
+
+
+
+ Secrets
+
+
+
+ Events
+
+
+
+
+
+ Setup
+
+
+
+ Registries
+
+
+
+
+
+
+
+ Setup
+
+
+
+ Registries
+
+
+
diff --git a/app/docker/components/dockerSidebarContent/docker-sidebar-content.js b/app/docker/components/docker-sidebar/docker-sidebar.js
similarity index 62%
rename from app/docker/components/dockerSidebarContent/docker-sidebar-content.js
rename to app/docker/components/docker-sidebar/docker-sidebar.js
index 088165ac3..65e679262 100644
--- a/app/docker/components/dockerSidebarContent/docker-sidebar-content.js
+++ b/app/docker/components/docker-sidebar/docker-sidebar.js
@@ -1,12 +1,13 @@
-angular.module('portainer.docker').component('dockerSidebarContent', {
- templateUrl: './dockerSidebarContent.html',
+angular.module('portainer.docker').component('dockerSidebar', {
+ templateUrl: './docker-sidebar.html',
bindings: {
+ isSidebarOpen: '<',
+
endpointApiVersion: '<',
swarmManagement: '<',
standaloneManagement: '<',
adminAccess: '<',
offlineMode: '<',
- toggle: '<',
currentRouteName: '<',
endpointId: '<',
showStacks: '<',
diff --git a/app/docker/components/dockerSidebarContent/dockerSidebarContent.html b/app/docker/components/dockerSidebarContent/dockerSidebarContent.html
deleted file mode 100644
index 086047756..000000000
--- a/app/docker/components/dockerSidebarContent/dockerSidebarContent.html
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html b/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html
deleted file mode 100644
index f7439c9a6..000000000
--- a/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
diff --git a/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.js b/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.js
deleted file mode 100644
index 8a44e8a8d..000000000
--- a/app/kubernetes/components/kubernetes-sidebar-content/kubernetesSidebarContent.js
+++ /dev/null
@@ -1,8 +0,0 @@
-angular.module('portainer.kubernetes').component('kubernetesSidebarContent', {
- templateUrl: './kubernetesSidebarContent.html',
- bindings: {
- adminAccess: '<',
- endpointId: '<',
- currentState: '<',
- },
-});
diff --git a/app/kubernetes/components/kubernetes-sidebar/index.js b/app/kubernetes/components/kubernetes-sidebar/index.js
new file mode 100644
index 000000000..def39be7a
--- /dev/null
+++ b/app/kubernetes/components/kubernetes-sidebar/index.js
@@ -0,0 +1,9 @@
+import angular from 'angular';
+
+angular.module('portainer.kubernetes').component('kubernetesSidebar', {
+ templateUrl: './kubernetes-sidebar.html',
+ bindings: {
+ endpointId: '<',
+ isSidebarOpen: '<',
+ },
+});
diff --git a/app/kubernetes/components/kubernetes-sidebar/kubernetes-sidebar.html b/app/kubernetes/components/kubernetes-sidebar/kubernetes-sidebar.html
new file mode 100644
index 000000000..dc6901a06
--- /dev/null
+++ b/app/kubernetes/components/kubernetes-sidebar/kubernetes-sidebar.html
@@ -0,0 +1,38 @@
+
+ Dashboard
+
+
+
+ Namespaces
+
+
+
+ Applications
+
+
+
+ Configurations
+
+
+
+ Volumes
+
+
+
+
+
+ Setup
+
+
+
+ Registries
+
+
+
diff --git a/app/portainer/components/index.js b/app/portainer/components/index.js
index bef46f4d7..9a660facf 100644
--- a/app/portainer/components/index.js
+++ b/app/portainer/components/index.js
@@ -1,7 +1,8 @@
import angular from 'angular';
+import sidebarModule from './sidebar';
import gitFormModule from './forms/git-form';
import porAccessManagementModule from './accessManagement';
import formComponentsModule from './form-components';
-export default angular.module('portainer.app.components', [gitFormModule, porAccessManagementModule, formComponentsModule]).name;
+export default angular.module('portainer.app.components', [sidebarModule, gitFormModule, porAccessManagementModule, formComponentsModule]).name;
diff --git a/app/portainer/components/sidebar/index.js b/app/portainer/components/sidebar/index.js
new file mode 100644
index 000000000..1d2c18062
--- /dev/null
+++ b/app/portainer/components/sidebar/index.js
@@ -0,0 +1,12 @@
+import angular from 'angular';
+import './sidebar.css';
+
+import { sidebarMenu } from './sidebar-menu';
+import { sidebarSection } from './sidebar-section';
+import { sidebarMenuItem } from './sidebar-menu-item';
+
+export default angular
+ .module('portainer.app.components.sidebar', [])
+ .component('sidebarMenu', sidebarMenu)
+ .component('sidebarMenuItem', sidebarMenuItem)
+ .component('sidebarSection', sidebarSection).name;
diff --git a/app/portainer/components/sidebar/sidebar-menu-item/index.js b/app/portainer/components/sidebar/sidebar-menu-item/index.js
new file mode 100644
index 000000000..014d6262f
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu-item/index.js
@@ -0,0 +1,12 @@
+import './sidebar-menu-item.css';
+
+export const sidebarMenuItem = {
+ templateUrl: './sidebar-menu-item.html',
+ bindings: {
+ path: '@',
+ pathParams: '<',
+ iconClass: '@',
+ className: '@',
+ },
+ transclude: true,
+};
diff --git a/app/portainer/components/sidebar/sidebar-menu-item/sidebar-menu-item.css b/app/portainer/components/sidebar/sidebar-menu-item/sidebar-menu-item.css
new file mode 100644
index 000000000..4f751ad36
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu-item/sidebar-menu-item.css
@@ -0,0 +1,4 @@
+.sidebar-menu-item > a {
+ display: flex;
+ justify-content: space-between;
+}
diff --git a/app/portainer/components/sidebar/sidebar-menu-item/sidebar-menu-item.html b/app/portainer/components/sidebar/sidebar-menu-item/sidebar-menu-item.html
new file mode 100644
index 000000000..bfcb509c9
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu-item/sidebar-menu-item.html
@@ -0,0 +1,6 @@
+
diff --git a/app/portainer/components/sidebar/sidebar-menu/index.js b/app/portainer/components/sidebar/sidebar-menu/index.js
new file mode 100644
index 000000000..8c9d24aea
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu/index.js
@@ -0,0 +1,18 @@
+import './sidebar-menu.css';
+
+import controller from './sidebar-menu.controller.js';
+
+export const sidebarMenu = {
+ templateUrl: './sidebar-menu.html',
+ controller,
+ bindings: {
+ iconClass: '@',
+ path: '@', // string
+ pathParams: '<', //object, corresponds to https://ui-router.github.io/ng1/docs/latest/modules/directives.html#uistatedirective
+ childrenPaths: '<', // []string (globs)
+ label: '@', // string
+ isSidebarOpen: '<',
+ currentState: '@',
+ },
+ transclude: true,
+};
diff --git a/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.controller.js b/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.controller.js
new file mode 100644
index 000000000..8122f7ea9
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.controller.js
@@ -0,0 +1,45 @@
+class SidebarMenuController {
+ /* @ngInject */
+ constructor($state) {
+ this.$state = $state;
+
+ this.state = {
+ forceOpen: false,
+ };
+ }
+
+ isOpen() {
+ if (!this.isSidebarOpen) {
+ return false;
+ }
+
+ if (this.state.forceOpen) {
+ return true;
+ }
+
+ return this.isOpenByPathState();
+ }
+
+ isOpenByPathState() {
+ const currentName = this.$state.current.name;
+ return currentName.startsWith(this.path) || this.childrenPaths.includes(currentName);
+ }
+
+ onClickArrow(event) {
+ event.stopPropagation();
+ event.preventDefault();
+
+ // prevent toggling when menu is open by state
+ if (this.isOpenByPathState()) {
+ return;
+ }
+
+ this.state.forceOpen = !this.state.forceOpen;
+ }
+
+ $onInit() {
+ this.childrenPaths = this.childrenPaths || [];
+ }
+}
+
+export default SidebarMenuController;
diff --git a/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.css b/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.css
new file mode 100644
index 000000000..f28c4ae14
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.css
@@ -0,0 +1,15 @@
+.sidebar-menu .sidebar-menu-head {
+ position: relative;
+}
+
+.sidebar-menu .sidebar-menu-head .sidebar-menu-indicator {
+ background: none;
+ border: 0;
+ width: fit-content;
+ height: fit-content;
+ color: white;
+ margin: 0 10px;
+ padding: 0;
+ position: absolute;
+ left: -5px;
+}
diff --git a/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.html b/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.html
new file mode 100644
index 000000000..a9e6243d5
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-menu/sidebar-menu.html
@@ -0,0 +1,14 @@
+
diff --git a/app/portainer/components/sidebar/sidebar-section/index.js b/app/portainer/components/sidebar/sidebar-section/index.js
new file mode 100644
index 000000000..b577b6660
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-section/index.js
@@ -0,0 +1,7 @@
+export const sidebarSection = {
+ templateUrl: './sidebar-section.html',
+ transclude: true,
+ bindings: {
+ title: '@',
+ },
+};
diff --git a/app/portainer/components/sidebar/sidebar-section/sidebar-section.html b/app/portainer/components/sidebar/sidebar-section/sidebar-section.html
new file mode 100644
index 000000000..057db83f8
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar-section/sidebar-section.html
@@ -0,0 +1,7 @@
+
diff --git a/app/portainer/components/sidebar/sidebar.css b/app/portainer/components/sidebar/sidebar.css
new file mode 100644
index 000000000..e5d27df9b
--- /dev/null
+++ b/app/portainer/components/sidebar/sidebar.css
@@ -0,0 +1,326 @@
+#page-wrapper.open #sidebar-wrapper {
+ left: 150px;
+}
+
+/* #592727 RED */
+/* #2f5927 GREEN */
+/* #30426a BLUE (default)*/
+/* Sidebar background color */
+/* Sidebar header and footer color */
+/* Sidebar title text colour */
+/* Sidebar menu item hover color */
+/**
+ * Sidebar
+ */
+#sidebar-wrapper {
+ background: #30426a;
+}
+
+ul.sidebar .sidebar-main a,
+.sidebar-footer,
+ul.sidebar .sidebar-list a:hover,
+#page-wrapper:not(.open) ul.sidebar .sidebar-title.separator {
+ /* Sidebar header and footer color */
+ background: #2d3e63;
+}
+
+ul.sidebar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ text-indent: 20px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+ul.sidebar li a {
+ color: #fff;
+ text-decoration: none;
+ width: 250px;
+}
+
+ul.sidebar .sidebar-main {
+ height: 65px;
+}
+
+ul.sidebar .sidebar-main a {
+ font-size: 18px;
+ line-height: 60px;
+}
+
+ul.sidebar .sidebar-main a:hover {
+ cursor: pointer;
+}
+
+ul.sidebar .sidebar-main .menu-icon {
+ float: right;
+ font-size: 18px;
+ padding-right: 28px;
+ line-height: 60px;
+}
+
+ul.sidebar .sidebar-title {
+ color: #738bc0;
+ font-size: 12px;
+ height: 35px;
+ line-height: 40px;
+ text-transform: uppercase;
+ transition: all 0.6s ease 0s;
+}
+
+ul.sidebar .sidebar-list a {
+ text-indent: 25px;
+ font-size: 15px;
+ color: #b2bfdc;
+ line-height: 40px;
+ padding-left: 5px;
+ border-left: 3px solid transparent;
+}
+
+ul.sidebar .sidebar-list a:hover {
+ color: #fff;
+ border-left-color: #e99d1a;
+}
+
+ul.sidebar .sidebar-list a:hover .menu-icon {
+ text-indent: 25px;
+}
+
+ul.sidebar .sidebar-list .menu-icon {
+ padding-right: 30px;
+ line-height: 40px;
+ width: fit-content;
+}
+
+#page-wrapper:not(.open) ul.sidebar {
+ bottom: 0;
+}
+
+#page-wrapper:not(.open) ul.sidebar .sidebar-title {
+ display: none;
+ height: 0px;
+ text-indent: -100px;
+}
+
+#page-wrapper:not(.open) ul.sidebar .sidebar-title.separator {
+ display: block;
+ height: 2px;
+ margin: 13px 0;
+}
+
+#page-wrapper:not(.open) ul.sidebar .sidebar-list a:hover span {
+ border-left: 3px solid #e99d1a;
+ text-indent: 22px;
+}
+
+#page-wrapper:not(.open) .sidebar-footer {
+ display: none;
+}
+
+.sidebar-footer {
+ position: absolute;
+ height: 40px;
+ bottom: 0;
+ width: 100%;
+ padding: 0;
+ margin: 0;
+ transition: all 0.6s ease 0s;
+ text-align: center;
+}
+
+.sidebar-footer div a {
+ color: #b2bfdc;
+ font-size: 12px;
+ line-height: 43px;
+}
+
+.sidebar-footer div a:hover {
+ color: #ffffff;
+ text-decoration: none;
+}
+
+/* #592727 RED */
+/* #2f5927 GREEN */
+/* #30426a BLUE (default)*/
+/* Sidebar background color */
+/* Sidebar header and footer color */
+/* Sidebar title text colour */
+/* Sidebar menu item hover color */
+
+ul.sidebar {
+ position: relative;
+ overflow: hidden;
+ flex-shrink: 0;
+}
+
+ul.sidebar .sidebar-title {
+ height: auto;
+}
+
+ul.sidebar .sidebar-title.endpoint-name {
+ color: #fff;
+ text-align: center;
+ text-indent: 0;
+}
+
+ul.sidebar .sidebar-list a {
+ font-size: 14px;
+}
+
+ul.sidebar .sidebar-list a.active {
+ color: #fff;
+ border-left-color: #fff;
+ background: #2d3e63;
+}
+
+.sidebar-header {
+ height: 60px;
+ list-style: none;
+ text-indent: 20px;
+ font-size: 18px;
+ background: #2d3e63;
+}
+
+.sidebar-header a {
+ color: #fff;
+}
+
+.sidebar-header a:hover {
+ text-decoration: none;
+}
+
+.sidebar-header .menu-icon {
+ float: right;
+ padding-right: 28px;
+ line-height: 60px;
+}
+
+#page-wrapper:not(.open) .sidebar-footer-content {
+ display: none;
+}
+
+.sidebar-footer-content {
+ text-align: center;
+}
+
+.sidebar-footer-content .logo {
+ width: 100%;
+ max-width: 100px;
+ height: 100%;
+ max-height: 35px;
+ margin: 2px 0 2px 20px;
+}
+
+.sidebar-footer-content .update-notification {
+ font-size: 14px;
+ padding: 12px;
+ border-radius: 2px;
+ background-color: #ff851b;
+ margin-bottom: 5px;
+}
+
+.sidebar-footer-content .version {
+ font-size: 11px;
+ margin: 11px 20px 0 7px;
+ color: #fff;
+}
+
+.sidebar-footer-content .edition-version {
+ font-size: 10px;
+ margin-bottom: 8px;
+ color: #fff;
+}
+
+#sidebar-wrapper {
+ display: flex;
+ flex-flow: column;
+}
+
+.sidebar-content {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ overflow-y: auto;
+ overflow-x: hidden;
+ height: 100%;
+}
+
+ul.sidebar .sidebar-list a.active .menu-icon {
+ text-indent: 25px;
+}
+
+ul.sidebar .sidebar-list .sidebar-sublist a {
+ text-indent: 35px;
+ font-size: 12px;
+ color: #b2bfdc;
+ line-height: 36px;
+}
+
+ul.sidebar .sidebar-title {
+ line-height: 36px;
+}
+
+ul.sidebar .sidebar-title .form-control {
+ height: 36px;
+ padding: 6px 12px;
+}
+
+ul.sidebar .sidebar-list a,
+ul.sidebar .sidebar-list .sidebar-sublist a {
+ line-height: 36px;
+}
+
+ul.sidebar .sidebar-list .menu-icon {
+ line-height: 36px;
+}
+
+ul.sidebar .sidebar-list .sidebar-sublist a.active {
+ color: #fff;
+ border-left: 3px solid #fff;
+ background: #2d3e63;
+}
+
+@media (max-height: 785px) {
+ ul.sidebar .sidebar-title {
+ line-height: 26px;
+ }
+
+ ul.sidebar .sidebar-title .form-control {
+ height: 26px;
+ padding: 3px 6px;
+ }
+
+ ul.sidebar .sidebar-list a,
+ ul.sidebar .sidebar-list .sidebar-sublist a {
+ font-size: 12px;
+ line-height: 26px;
+ }
+
+ ul.sidebar .sidebar-list .menu-icon {
+ line-height: 26px;
+ }
+}
+
+@media (min-height: 786px) and (max-height: 924px) {
+ ul.sidebar .sidebar-title {
+ line-height: 30px;
+ }
+
+ ul.sidebar .sidebar-title .form-control {
+ height: 30px;
+ padding: 5px 10px;
+ }
+
+ ul.sidebar .sidebar-list a,
+ ul.sidebar .sidebar-list .sidebar-sublist a {
+ font-size: 12px;
+ line-height: 30px;
+ }
+
+ ul.sidebar .sidebar-list .menu-icon {
+ line-height: 30px;
+ }
+}
diff --git a/app/portainer/views/sidebar/sidebar.html b/app/portainer/views/sidebar/sidebar.html
index 9dd6fdc5e..94ad02c9d 100644
--- a/app/portainer/views/sidebar/sidebar.html
+++ b/app/portainer/views/sidebar/sidebar.html
@@ -9,193 +9,92 @@
-