feat(frontend): dark and high contrast theme supported EE-909 (#5353)

* feat dark theme & high contrast theme supported
pull/5589/head
Richard Wei 2021-09-08 11:06:18 +12:00 committed by GitHub
parent e49e90f304
commit 8d8f21368d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1352 additions and 107 deletions

View File

@ -17,6 +17,7 @@ import (
type userUpdatePayload struct {
Username string `validate:"required" example:"bob"`
Password string `validate:"required" example:"cg9Wgky3"`
UserTheme string `example:"dark"`
// User role (1 for administrator account and 2 for regular account)
Role int `validate:"required" enums:"1,2" example:"2"`
}
@ -104,6 +105,10 @@ func (handler *Handler) userUpdate(w http.ResponseWriter, r *http.Request) *http
user.Role = portainer.UserRole(payload.Role)
}
if payload.UserTheme != "" {
user.UserTheme = payload.UserTheme
}
err = handler.DataStore.User().UpdateUser(user.ID, user)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist user changes inside the database", err}

View File

@ -1003,6 +1003,8 @@ type (
ID UserID `json:"Id" example:"1"`
Username string `json:"Username" example:"bob"`
Password string `json:"Password,omitempty" example:"passwd"`
// User Theme
UserTheme string `example:"dark"`
// User role (1 for administrator account and 2 for regular account)
Role UserRole `json:"Role" example:"1"`

View File

@ -59,10 +59,10 @@ body,
}
.form-section-title {
border-bottom: 1px solid #777;
border-bottom: 1px solid var(--border-form-section-title-color);
margin-top: 5px;
margin-bottom: 15px;
color: #777;
color: var(--text-form-section-title-color);
padding-left: 0;
}
@ -108,12 +108,33 @@ a[ng-click] {
pointer-events: none;
}
.datatable-highlighted {
background-color: var(--bg-item-highlighted-color);
}
.datatable-unhighlighted {
background-color: var(--bg-item-highlighted-null-color);
}
.service-datatable {
background-color: var(--bg-item-highlighted-color);
padding: 2px;
}
.service-datatable thead {
background-color: var(--bg-service-datatable-thead) !important;
}
.service-datatable tbody {
background-color: var(--bg-service-datatable-tbody);
}
.tooltip.portainer-tooltip .tooltip-inner {
font-family: Montserrat;
background-color: #ffffff;
background-color: var(--bg-tooltip-color);
padding: 0.833em 1em;
color: #333333;
border: 1px solid #d4d4d5;
color: var(--text-tooltip-color);
border: 1px solid var(--border-tooltip-color);
border-radius: 0.14285714rem;
box-shadow: 0 2px 4px 0 rgba(34, 36, 38, 0.12), 0 2px 10px 0 rgba(34, 36, 38, 0.15);
}
@ -145,7 +166,7 @@ a[ng-click] {
.fa.blue-icon,
.fab.blue-icon {
color: #337ab7;
color: var(--blue-2);
}
.text-warning {
@ -207,25 +228,25 @@ a[ng-click] {
padding: 0.7rem;
margin-bottom: 0.7rem;
cursor: pointer;
border: 1px solid #cccccc;
border: 1px solid var(--border-blocklist-color);
border-radius: 2px;
box-shadow: 0 3px 10px -2px rgba(161, 170, 166, 0.5);
box-shadow: var(--shadow-box-color);
}
.blocklist-item--disabled {
cursor: auto;
background-color: #ececec;
background-color: var(--grey-12);
}
.blocklist-item--selected {
border: 2px solid #bbbbbb;
background-color: #ececec;
color: #2d3e63;
background-color: var(--bg-blocklist-item-selected-color);
border: 2px solid var(--border-blocklist-item-selected-color);
color: var(--text-blocklist-item-selected-color);
}
.blocklist-item:hover {
background-color: #ececec;
color: #2d3e63;
background-color: var(--bg-blocklist-hover-color);
color: var(--text-blocklist-hover-color);
}
.blocklist-item-box {
@ -360,7 +381,7 @@ a[ng-click] {
.panel-body {
padding-top: 30px;
background-color: #ffffff;
background-color: var(--white-color) fff;
}
.pagination-controls {
@ -443,8 +464,8 @@ a[ng-click] {
display: inline-block;
padding: 0px 6px;
margin-left: 10px;
color: #555555;
background-color: #fff;
color: var(--text-small-select-color);
background-color: var(--bg-small-select-color);
background-image: none;
border-radius: 4px;
font-size: 14px;
@ -462,11 +483,11 @@ a[ng-click] {
}
.visualizer_container .node {
border: 1px dashed #337ab7;
border: 1px dashed var(--blue-2);
background-color: rgb(51, 122, 183);
background-color: rgba(51, 122, 183, 0.1);
border-radius: 4px;
box-shadow: 0 3px 10px -2px rgba(161, 170, 166, 0.5);
box-shadow: 0 3px 10px -2px var(--grey-50);
padding: 15px;
margin: 5px;
}
@ -476,7 +497,7 @@ a[ng-click] {
flex-direction: column;
justify-content: center;
text-align: center;
border-bottom: 1px solid #777;
border-bottom: 1px solid var(--grey-26);
padding-bottom: 10px;
}
@ -486,7 +507,7 @@ a[ng-click] {
}
.visualizer_container .node .node_info .node_labels {
border-top: 1px solid #777;
border-top: 1px solid var(--grey-26);
padding-top: 10px;
margin-top: 10px;
}
@ -503,9 +524,9 @@ a[ng-click] {
}
.visualizer_container .node .tasks .task {
border: 1px solid #333333;
border: 1px solid var(--grey-6);
border-radius: 2px;
box-shadow: 0 3px 10px -2px rgba(161, 170, 166, 0.5);
box-shadow: 0 3px 10px -2px var(--grey-50);
padding: 10px;
margin: 5px;
font-size: 10px;
@ -547,9 +568,9 @@ a[ng-click] {
.log_viewer {
height: 100%;
overflow-y: scroll;
color: black;
color: var(--text-log-viewer-color);
font-size: 0.85em;
background-color: white;
background-color: var(--bg-log-viewer-color);
}
.log_viewer.wrap_lines {
@ -568,7 +589,7 @@ a[ng-click] {
}
.log_viewer .line_selected {
background-color: #c5cae9;
background-color: var(--bg-log-line-selected-color);
}
.row.header .meta .page {
@ -578,7 +599,7 @@ a[ng-click] {
.tag {
padding: 2px 6px;
color: white;
background-color: #337ab7;
background-color: var(--blue-2);
border: 1px solid #2e6da4;
border-radius: 4px;
}
@ -588,7 +609,7 @@ a[ng-click] {
}
.line-separator {
border-bottom: 1px solid #777;
border-bottom: 1px solid var(--grey-26);
width: 50%;
margin: 20px auto 10px auto;
}
@ -613,7 +634,7 @@ a[ng-click] {
}
.striked::after {
border-bottom: 0.2em solid #777777;
border-bottom: 0.2em solid var(--grey-26);
content: '';
left: 0;
margin-top: calc(0.2em / 2 * -1);
@ -625,7 +646,7 @@ a[ng-click] {
.striketext:before,
.striketext:after {
background-color: #777777;
background-color: var(--grey-26);
content: '';
display: inline-block;
height: 1px;
@ -657,20 +678,51 @@ a[ng-click] {
/*angular-multi-select override*/
.multiSelect > button {
min-height: 30px !important;
background-color: unset;
background-image: unset;
background-image: var(--bg-image-multiselect-button);
border-color: var(--border-multiselect);
color: var(--text-multiselect);
background-color: var(--bg-multiselect-color);
}
.multiSelect > button:hover {
background-image: var(--bg-image-multiselect-hover);
}
.multiSelect .checkboxLayer {
border-color: var(--border-multiselect-checkboxlayer);
}
.multiSelect .checkBoxContainer {
background-color: var(--bg-multiselect-checkboxcontainer);
}
.multiSelect .multiSelectItem {
color: var(--text-multiselect-item);
}
.multiSelect .helperContainer {
background-color: var(--bg-multiselect-helpercontainer);
}
.multiSelect .multiSelectFocus {
background-image: var(--bg-image-multiselect);
}
.multiSelect .multiSelectItem:not(.multiSelectGroup).selected {
background-image: linear-gradient(#337ab7, #337ab7);
color: #fff;
background-image: var(--bg-image-multiselect);
color: var(--white-color);
border: none;
}
.multiSelect .multiSelectItem:hover,
.multiSelect .multiSelectGroup:hover {
background-image: linear-gradient(#337ab7, #337ab7) !important;
color: #fff !important;
border-color: var(--grey-3);
}
.multiSelect .multiSelectItem:hover,
.multiSelect .multiSelectGroup:hover {
background-image: var(--bg-image-multiselect) !important;
color: var(--white-color) !important;
}
.multiSelect .tickMark,
@ -696,7 +748,7 @@ a[ng-click] {
#loading-bar .bar {
position: relative;
height: 3px;
background: #738bc0;
background: var(--blue-3);
}
/*!angular-loading-bar override*/
@ -708,11 +760,11 @@ a[ng-click] {
/* json-tree override */
json-tree {
font-size: 13px;
color: #30426a;
color: var(--blue-5);
}
json-tree .key {
color: #738bc0;
color: var(--blue-3);
padding-right: 5px;
}
@ -725,7 +777,7 @@ json-tree .branch-preview {
/* uib-progressbar override */
.progress-bar {
color: #4e4e4e;
color: var(--text-progress-bar-color);
}
/* !uib-progressbar override */
@ -756,7 +808,7 @@ json-tree .branch-preview {
}
.sk-fold-cube:before {
background-color: #337ab7;
background-color: var(--blue-2);
}
/* !spinkit override */

View File

@ -1,2 +1,4 @@
import './rdash.css';
import './app.css';
import './theme.css';
import './vendor-override.css';

View File

@ -52,7 +52,8 @@
* Header
*/
.row.header {
background: #fff;
height: 60px;
background: var(--bg-row-header-color);
margin-bottom: 15px;
}
.row.header > div:last-child {
@ -202,9 +203,9 @@ html {
overflow-y: scroll;
}
body {
background: #f3f3f3;
background: var(--bg-body-color);
font-family: 'Montserrat';
color: #333333 !important;
color: var(--text-body-color) !important;
}
.row {
margin-left: 0 !important;
@ -236,7 +237,7 @@ body {
background: #23ae89 !important;
}
.blue {
background: #2361ae !important;
background: var(--blue-color) !important;
}
.orange {
background: #d3a938 !important;
@ -258,20 +259,20 @@ div.input-mask {
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
-moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
background: #ffffff;
background: var(--bg-widget-color);
border: 1px solid transparent;
border-radius: 2px;
border-color: #e9e9e9;
border-color: var(--border-widget-color);
}
.widget .widget-header .pagination,
.widget .widget-footer .pagination {
margin: 0;
}
.widget .widget-header {
color: #767676;
background-color: #f6f6f6;
color: var(--text-widget-header-color);
background-color: var(--bg-widget-header-color);
padding: 10px 15px;
border-bottom: 1px solid #e9e9e9;
border-bottom: 1px solid var(--border-widget-color);
line-height: 30px;
}
.widget .widget-header i {
@ -281,7 +282,7 @@ div.input-mask {
padding: 20px;
}
.widget .widget-body table thead {
background: #fafafa;
background: var(--bg-widget-table-color);
}
.widget .widget-body table thead * {
font-size: 14px !important;

576
app/assets/css/theme.css Normal file
View File

@ -0,0 +1,576 @@
/* Color Variable */
html {
--black-color: #000;
--white-color: #fff;
--grey-1: #212121;
--grey-2: #181818;
--grey-3: #383838;
--grey-4: #585858;
--grey-5: #323c48;
--grey-6: #333333;
--grey-7: #767676;
--grey-8: #aaa;
--grey-9: #f3f3f3;
--grey-10: #f6f6f6;
--grey-11: #eeeeee;
--grey-12: #ececec;
--grey-13: #fafafa;
--grey-14: #f5f5f5;
--grey-15: #f9f2f4;
--grey-16: #eee;
--grey-17: #f7f7f7;
--grey-18: #c5cae9;
--grey-19: #ddd;
--grey-20: #dae3f3;
--grey-21: #d5e8f3;
--grey-22: #c3c3e4;
--grey-23: #e7f6ff;
--grey-24: #f1f9fd;
--grey-25: #555555;
--grey-26: #777777;
--grey-27: #4e4e4e;
--grey-28: #262626;
--grey-29: #555;
--grey-30: #444;
--grey-31: #868686;
--grey-32: #65798e;
--grey-34: #314252;
--grey-35: #546477;
--grey-36: #55637d;
--grey-37: #2d3e63;
--grey-38: #434343;
--grey-39: #194973;
--grey-40: #cfddfc;
--grey-41: #b4b4b4;
--grey-42: #d2d1d1;
--grey-43: #e9e9e9;
--grey-44: #ccc;
--grey-45: #e5e5e5;
--grey-46: #bbbbbb;
--grey-47: #d4d4d5;
--grey-48: #c6c6c6;
--grey-49: rgba(0, 0, 0, 0.54);
--grey-50: rgba(161, 170, 166, 0.5);
--grey-51: rgba(0, 0, 0, 0.15);
--grey-52: rgba(255, 255, 255, 0.3);
--grey-53: rgba(255, 255, 255, 0.6);
--grey-54: rgb(54, 54, 54);
--grey-55: rgba(255, 255, 255, 0.8);
--grey-56: #b2bfdc;
--grey-57: #999;
--grey-58: #ebf4f8;
--grey-59: #e6e6e6;
--grey-60: #cacaca;
--blue-1: #219;
--blue-2: #337ab7;
--blue-3: #738bc0;
--blue-4: #23527c;
--blue-5: #30426a;
--blue-6: #577bc9;
--blue-7: #6b9aff;
--blue-8: #90ccff;
--blue-9: #3ea6ff;
--blue-10: #61b6ff;
--blue-11: #3ea5ff;
--blue-12: #41a6ff;
--blue-13: #2361ae;
--blue-14: #357ebd;
--red-1: #a94442;
--red-2: #c7254e;
--red-3: #a11;
--red-4: #d9534f;
--red-5: #ff2727;
--red-6: #ff00e0;
--red-7: #f00;
--green-1: #164;
--green-2: #1ec863;
}
:root {
--bg-card-color: var(--grey-10);
--bg-main-color: var(--white-color);
--bg-body-color: var(--grey-9);
--bg-checkbox-border-color: var(--grey-49);
--bg-sidebar-color: var(--grey-37);
--bg-sidebar-header-color: var(--grey-37);
--bg-widget-color: var(--white-color);
--bg-widget-header-color: var(--grey-10);
--bg-widget-table-color: var(--grey-13);
--bg-header-color: var(--white-color);
--bg-hover-table-color: var(--grey-14);
--bg-switch-box-color: var(--white-color);
--bg-input-group-addon-color: var(--grey-11);
--bg-btn-default-color: var(--white-color);
--bg-blocklist-hover-color: var(--grey-12);
--bg-boxselector-color: var(--white-color);
--bg-table-color: var(--white-color);
--bg-md-checkbox-color: var(--grey-12);
--bg-form-control-disabled-color: var(--grey-11);
--bg-modal-content-color: var(--white-color);
--bg-code-color: var(--grey-15);
--bg-navtabs-color: var(--white-color);
--bg-navtabs-hover-color: var(--grey-16);
--bg-table-selected-color: var(--grey-14);
--bg-codemirror-gutters-color: var(--grey-17);
--bg-dropdown-menu-color: var(--white-color);
--bg-log-viewer-color: var(--white-color);
--bg-log-line-selected-color: var(--grey-18);
--bg-pre-color: var(--grey-14);
--bg-blocklist-item-selected-color: var(--grey-12);
--bg-progress-color: var(--grey-14);
--bg-pagination-color: var(--white-color);
--bg-pagination-span-color: var(--white-color);
--bg-pagination-hover-color: var(--grey-11);
--bg-ui-select-hover-color: var(--grey-14);
--bg-motd-body-color: var(--grey-20);
--bg-item-highlighted-color: var(--grey-21);
--bg-item-highlighted-null-color: var(--grey-14);
--bg-row-header-color: var(--white-color);
--bg-image-multiselect-button: linear-gradient(var(--white-color), var(--grey-17));
--bg-multiselect-checkbox-color: var(--white-color);
--bg-sidebar-wrapper-color: var(--blue-5);
--bg-panel-body-color: var(--white-color);
--bg-codemirror-color: var(--white-color);
--bg-codemirror-selected-color: var(--grey-22);
--bg-multiselect-color: var(--white-color);
--bg-daterangepicker-color: var(--white-color);
--bg-calendar-color: var(--white-color);
--bg-calendar-table-color: var(--white-color);
--bg-daterangepicker-end-date: var(--white-color);
--bg-daterangepicker-hover: var(--grey-16);
--bg-daterangepicker-in-range: var(--grey-58);
--bg-daterangepicker-active: var(--blue-14);
--bg-tooltip-color: var(--white-color);
--bg-input-autofill-color: var(--white-color);
--bg-btn-default-hover-color: var(--grey-59);
--bg-btn-focus: var(--grey-59);
--bg-boxselector-disabled-color: var(--white-color);
--bg-small-select-color: var(--white-color);
--text-main-color: var(--grey-7);
--text-body-color: var(--grey-6);
--text-sidebar-title-color: var(--blue-3);
--text-widget-header-color: var(--grey-7);
--text-form-control-color: var(--grey-25);
--text-muted-color: var(--grey-26);
--text-link-color: var(--blue-2);
--text-link-hover-color: var(--blue-4);
--text-input-group-addon-color: var(--grey-25);
--text-btn-default-color: var(--grey-6);
--text-blocklist-hover-color: var(--grey-37);
--text-dashboard-item-color: var(--grey-32);
--text-danger-color: var(--red-1);
--text-code-color: var(--red-2);
--text-navtabs-color: var(--grey-25);
--text-form-section-title-color: var(--grey-26);
--text-cm-default-color: var(--blue-1);
--text-cm-meta-color: var(--black-color);
--text-cm-string-color: var(--red-3);
--text-cm-number-color: var(--green-1);
--text-codemirror-color: var(--black-color);
--text-dropdown-menu-color: var(--grey-6);
--text-log-viewer-color: var(--black-color);
--text-json-tree-color: var(--blue-3);
--text-json-tree-leaf-color: var(--blue-5);
--text-json-tree-branch-preview-color: var(--blue-5);
--text-pre-color: var(--grey-6);
--text-blocklist-item-selected-color: var(--grey-37);
--text-progress-bar-color: var(--grey-27);
--text-pagination-color: var(--grey-26);
--text-pagination-span-color: var(--blue-2);
--text-pagination-span-hover-color: var(--blue-4);
--text-ui-select-color: var(--grey-6);
--text-ui-select-hover-color: var(--grey-28);
--text-summary-color: var(--black-color);
--text-multiselect-button-color: var(--grey-29);
--text-multiselect-item-color: var(--grey-30);
--text-sidebar-list-color: var(--grey-56);
--text-rzslider-color: var(--grey-36);
--text-rzslider-limit-color: var(--grey-36);
--text-daterangepicker-end-date: var(--grey-57);
--text-daterangepicker-in-range: var(--black-color);
--text-daterangepicker-active: var(--white-color);
--text-tooltip-color: var(--grey-6);
--text-input-autofill-color: var(--black-color);
--text-button-hover-color: var(--grey-6);
--text-small-select-color: var(--grey-25);
--border-color: var(--grey-42);
--border-widget-color: var(--grey-43);
--border-sidebar-color: var(--white-color);
--border-form-control-color: var(--grey-44);
--border-table-color: var(--grey-19);
--border-table-top-color: var(--grey-19);
--border-datatable-top-color: var(--grey-10);
--border-blocklist-color: var(--grey-44) ccc;
--border-input-group-addon-color: var(--grey-44);
--border-btn-default-color: var(--grey-44);
--border-boxselector-color: var(--grey-6);
--border-md-checkbox-color: var(--grey-19);
--border-modal-header-color: var(--grey-45);
--border-navtabs-color: var(--grey-19);
--border-form-section-title-color: var(--grey-26);
--border-codemirror-cursor-color: var(--black-color);
--border-codemirror-gutters-color: var(--grey-19);
--border-pre-color: var(--grey-43);
--border-blocklist-item-selected-color: var(--grey-46);
--border-pagination-color: var(--grey-19);
--border-pagination-span-color: var(--grey-19);
--border-pagination-hover-color: var(--grey-19);
--border-multiselect-button-color: var(--grey-48);
--border-searchbar-color: var(--grey-10);
--border-panel-color: var(--white-color);
--border-daterangepicker-color: var(--grey-19);
--border-calendar-table: var(--white-color);
--border-daterangepicker: var(--grey-19);
--border-pre-next-month: var(--black-color);
--border-daterangepicker-after: var(--white-color);
--border-tooltip-color: var(--grey-47);
--border-modal: 0px;
--hover-sidebar-color: var(--grey-37);
--shadow-box-color: 0 3px 10px -2px var(--grey-50);
--shadow-boxselector-color: 0 3px 10px -2px var(--grey-50);
--blue-color: var(--blue-13);
--button-close-color: var(--black-color);
--button-opacity: 0.2;
--button-opacity-hover: 0.5;
--bg-boxselector-wrapper-color: var(--grey-6);
--bg-image-multiselect: linear-gradient(var(--blue-2), var(--blue-2));
--bg-image-multiselect-button: linear-gradient(var(--white-color), var(--grey-17));
--bg-image-multiselect-hover: linear-gradient(var(--white-color), var(--grey-43));
--border-multiselect: var(--grey-48);
--border-multiselect-checkboxlayer: var(--grey-51);
--text-multiselect: var(--grey-29);
--text-multiselect-selectitem: var(--white-color);
--bg-multiselect-checkboxcontainer: var(--white-color);
--text-multiselect-item: var(--grey-30);
--bg-multiselect-helpercontainer: var(--white-color);
--text-input-textarea: var(--white-color);
--bg-service-datatable-thead: var(--grey-23);
--bg-service-datatable-tbody: var(--grey-24);
}
:root[theme='dark'] {
--bg-card-color: var(--grey-1);
--bg-main-color: var(--grey-2);
--bg-body-color: var(--grey-2);
--bg-checkbox-border-color: var(--grey-8);
--bg-sidebar-color: var(--grey-3);
--bg-widget-color: var(--grey-1);
--bg-widget-header-color: var(--grey-1);
--bg-widget-table-color: var(--grey-1);
--bg-header-color: var(--grey-2);
--bg-hover-table-color: var(--grey-3);
--bg-switch-box-color: var(--grey-53);
--bg-input-group-addon-color: var(--grey-3);
--bg-btn-default-color: var(--grey-3);
--bg-blocklist-hover-color: var(--grey-3);
--bg-boxselector-color: var(--grey-54);
--bg-table-color: var(--grey-1);
--bg-md-checkbox-color: var(--grey-31);
--bg-form-control-disabled-color: var(--grey-3);
--bg-modal-content-color: var(--grey-1);
--bg-code-color: var(--red-4);
--bg-navtabs-color: var(--grey-3);
--bg-navtabs-hover-color: var(--grey-3);
--bg-table-selected-color: var(--grey-3);
--bg-codemirror-color: var(--grey-2);
--bg-codemirror-gutters-color: var(--grey-2);
--bg-dropdown-menu-color: var(--grey-1);
--bg-log-viewer-color: var(--grey-2);
--bg-log-line-selected-color: var(--grey-3);
--bg-pre-color: var(--grey-2);
--bg-blocklist-item-selected-color: var(--grey-3);
--bg-progress-color: var(--grey-3);
--bg-pagination-color: var(--grey-3);
--bg-pagination-span-color: var(--grey-3);
--bg-pagination-hover-color: var(--grey-4);
--bg-ui-select-hover-color: var(--grey-3);
--bg-motd-body-color: var(--grey-1);
--bg-item-highlighted-color: var(--grey-2);
--bg-item-highlighted-null-color: var(--grey-2);
--bg-row-header-color: var(--grey-2);
--bg-multiselect-button-color: var(--grey-3);
--bg-image-multiselect-button: none !important;
--bg-multiselect-checkbox-color: var(--grey-3);
--bg-sidebar-wrapper-color: var(--grey-1);
--bg-panel-body-color: var(--grey-1);
--bg-boxselector-wrapper-disabled-color: var(--grey-39);
--bg-codemirror-selected-color: var(--grey-3);
--bg-sidebar-header-color: var(--grey-1);
--bg-multiselect-color: var(--grey-1);
--bg-daterangepicker-color: var(--grey-3);
--bg-calendar-color: var(--grey-3);
--bg-calendar-table-color: var(--grey-3);
--bg-daterangepicker-end-date: var(--grey-4);
--bg-daterangepicker-hover: var(--grey-4);
--bg-daterangepicker-in-range: var(--grey-2);
--bg-daterangepicker-active: var(--blue-14);
--bg-tooltip-color: var(--grey-3);
--bg-input-autofill-color: var(--grey-2);
--bg-btn-default-hover-color: var(--grey-3);
--bg-btn-focus: var(--grey-3);
--bg-boxselector-disabled-color: var(--grey-54);
--bg-small-select-color: var(--grey-2);
--text-main-color: var(--white-color);
--text-body-color: var(--white-color);
--text-sidebar-title-color: var(--grey-8);
--text-widget-header-color: var(--white-color);
--text-form-control-color: var(--grey-8);
--text-muted-color: var(--grey-8);
--text-link-color: var(--blue-9);
--text-link-hover-color: var(--blue-2);
--text-input-group-addon-color: var(--grey-8);
--text-btn-default-color: var(--grey-8);
--text-blocklist-hover-color: var(--white-color);
--text-dashboard-item-color: var(--blue-2);
--text-danger-color: var(--red-4);
--text-code-color: var(--white-color);
--text-navtabs-color: var(--white-color);
--text-form-section-title-color: var(--grey-8);
--text-cm-default-color: var(--blue-10);
--text-cm-meta-color: var(--white-color);
--text-cm-string-color: var(--red-5);
--text-cm-number-color: var(--green-2);
--text-codemirror-color: var(--white-color);
--text-dropdown-menu-color: var(--white-color);
--text-log-viewer-color: var(--white-color);
--text-json-tree-color: var(--grey-40);
--text-json-tree-leaf-color: var(--blue-6);
--text-json-tree-branch-preview-color: var(--blue-7);
--text-pre-color: var(--white-color);
--text-blocklist-item-selected-color: var(--white-color);
--text-progress-bar-color: var(--white-color);
--text-pagination-color: var(--white-color);
--text-pagination-span-color: var(--white-color);
--text-pagination-span-hover-color: var(--white-color);
--text-ui-select-color: var(--white-color);
--text-ui-select-hover-color: var(--white-color);
--text-summary-color: var(--white-color);
--text-multiselect-button-color: var(--white-color);
--text-multiselect-item-color: var(--white-color);
--text-sidebar-list-color: var(--white-color);
--text-boxselector-wrapper-color: var(--white-color);
--text-daterangepicker-end-date: var(--grey-7);
--text-daterangepicker-in-range: var(--white-color);
--text-daterangepicker-active: var(--white-color);
--text-tooltip-color: var(--white-color);
--text-btn-default-color: var(--white-color);
--text-input-autofill-color: var(--grey-8);
--text-button-hover-color: var(--white-color);
--text-small-select-color: var(--grey-7);
--border-color: var(--grey-3);
--border-widget-color: var(--grey-1);
--border-sidebar-color: var(--blue-9);
--border-form-control-color: var(--grey-54);
--border-table-color: var(--grey-3);
--border-table-top-color: var(--grey-3);
--border-datatable-top-color: var(--grey-3);
--border-blocklist-color: var(--grey-3);
--border-input-group-addon-color: var(--grey-38);
--border-btn-default-color: var(--grey-38);
--border-boxselector-color: var(--grey-1);
--border-md-checkbox-color: var(--grey-41);
--border-modal-header-color: var(--grey-1);
--border-navtabs-color: var(--grey-38);
--border-form-section-title-color: var(--grey-8);
--border-codemirror-cursor-color: var(--white-color);
--border-codemirror-gutters-color: var(--grey-26);
--border-pre-color: var(--grey-3);
--border-blocklist-item-selected-color: var(--grey-38);
--border-pagination-color: var(--grey-3);
--border-pagination-span-color: var(--grey-3);
--border-pagination-hover-color: var(--grey-3);
--border-pagination-hover-color: var(--grey-3);
--border-multiselect-button-color: var(--grey-3);
--border-searchbar-color: var(--grey-1);
--border-panel-color: var(--grey-2);
--border-daterangepicker-color: var(--grey-3);
--border-calendar-table: var(--grey-3);
--border-daterangepicker: var(--grey-4);
--border-pre-next-month: var(--white-color);
--border-daterangepicker-after: var(--grey-3);
--border-tooltip-color: var(--grey-3);
--border-modal: 0px;
--hover-sidebar-color: var(--grey-3);
--blue-color: var(--blue-2);
--button-close-color: var(--white-color);
--button-opacity: 0.6;
--button-opacity-hover: 0.3;
--shadow-box-color: none;
--shadow-boxselector-color: none;
--bg-image-multiselect: linear-gradient(var(--grey-38), var(--grey-38));
--bg-image-multiselect-button: linear-gradient(var(--grey-1), var(--grey-1));
--bg-image-multiselect-hover: linear-gradient(var(--grey-3), var(--grey-3));
--border-multiselect: var(--grey-3);
--border-multiselect-checkboxlayer: var(--grey-3);
--text-multiselect: var(--white-color);
--bg-multiselect-checkboxcontainer: var(--grey-3);
--text-multiselect-item: var(--white-color);
--bg-multiselect-helpercontainer: var(--grey-1);
--text-input-textarea: var(--grey-1);
--bg-service-datatable-thead: var(--grey-1);
--bg-service-datatable-tbody: var(--grey-1);
}
:root[theme='highcontrast'] {
--bg-card-color: var(--black-color);
--bg-main-color: var(--black-color);
--bg-body-color: var(--black-color);
--bg-checkbox-border-color: var(--grey-8);
--bg-sidebar-color: var(--black-color);
--bg-widget-color: var(--black-color);
--bg-widget-header-color: var(--black-color);
--bg-widget-table-color: var(--black-color);
--bg-header-color: var(--black-color);
--bg-hover-table-color: var(--grey-3);
--bg-switch-box-color: var(--grey-53);
--bg-panel-body-color: var(--black-color);
--bg-boxselector-wrapper-disabled-color: var(--grey-39);
--bg-dropdown-menu-color: var(--black-color);
--bg-codemirror-selected-color: var(--grey-3);
--bg-row-header-color: var(--black-color);
--bg-sidebar-wrapper-color: var(--black-color);
--bg-motd-body-color: var(--black-color);
--bg-blocklist-hover-color: var(--black-color);
--bg-blocklist-item-selected-color: var(--black-color);
--bg-input-group-addon-color: var(--grey-1);
--bg-table-color: var(--black-color);
--bg-codemirror-gutters-color: var(--black-color);
--bg-codemirror-color: var(--black-color);
--bg-codemirror-selected-color: var(--grey-3);
--bg-log-viewer-color: var(--black-color);
--bg-log-line-selected-color: var(--grey-3);
--bg-sidebar-header-color: var(--black-color);
--bg-modal-content-color: var(--black-color);
--bg-form-control-disabled-color: var(--grey-1);
--bg-input-sm-color: var(--black-color);
--bg-item-highlighted-color: var(--black-color);
--bg-service-datatable-thead: var(--black-color);
--bg-service-datatable-tbody: var(--black-color);
--bg-pagination-color: var(--grey-3);
--bg-pagination-span-color: var(--grey-3);
--bg-multiselect-color: var(--grey-1);
--bg-daterangepicker-color: var(--black-color);
--bg-calendar-color: var(--black-color);
--bg-calendar-table-color: var(--black-color);
--bg-daterangepicker-end-date: var(--grey-3);
--bg-daterangepicker-hover: var(--grey-3);
--bg-daterangepicker-in-range: var(--grey-2);
--bg-daterangepicker-active: var(--blue-14);
--bg-tooltip-color: var(--black-color);
--bg-table-selected-color: var(--grey-3);
--bg-pre-color: var(--grey-2);
--bg-navtabs-hover-color: var(--grey-3);
--bg-btn-default-color: var(--black-color);
--bg-code-color: var(--red-4);
--bg-navtabs-color: var(--black-color);
--bg-input-autofill-color: var(--black-color);
--bg-code-color: var(--grey-2);
--bg-navtabs-color: var(--grey-2);
--bg-navtabs-hover-color: var(--grey-3);
--bg-btn-default-hover-color: var(--grey-3);
--bg-btn-default-color: var(--black-color);
--bg-btn-focus: var(--black-color);
--bg-boxselector-color: var(--black-color);
--bg-boxselector-disabled-color: var(--black-color);
--bg-small-select-color: var(--black-color);
--text-main-color: var(--white-color);
--text-body-color: var(--white-color);
--text-sidebar-title-color: var(--grey-8);
--text-widget-header-color: var(--white-color);
--text-link-color: var(--blue-9);
--text-link-hover-color: var(--blue-9);
--text-danger-color: var(--red-7);
--text-code-color: var(--red-7);
--text-form-control-color: var(--white-color);
--text-blocklist-hover-color: var(--blue-11);
--text-boxselector-wrapper-color: var(--white-color);
--text-dashboard-item-color: var(--blue-12);
--text-form-section-title-color: var(--white-color);
--text-muted-color: var(--white-color);
--text-tooltip-color: var(--white-color);
--text-blocklist-item-selected-color: var(--blue-9);
--text-input-group-addon-color: var(--white-color);
--text-codemirror-color: var(--white-color);
--text-log-viewer-color: var(--white-color);
--text-summary-color: var(--white-color);
--text-rzslider-color: var(--white-color);
--text-rzslider-limit-color: var(--white-color);
--text-pagination-color: var(--white-color);
--text-daterangepicker-end-date: var(--grey-7);
--text-daterangepicker-in-range: var(--white-color);
--text-daterangepicker-active: var(--white-color);
--text-sidebar-list-color: var(--white-color);
--text-ui-select-color: var(--white-color);
--text-btn-default-color: var(--white-color);
--text-json-tree-color: var(--white-color);
--text-json-tree-leaf-color: var(--white-color);
--text-json-tree-branch-preview-color: var(--white-color);
--text-pre-color: var(--white-color);
--text-navtabs-color: var(--white-color);
--text-input-autofill-color: var(--white-color);
--text-navtabs-color: var(--white-color);
--text-button-hover-color: var(--white-color);
--text-btn-default-color: var(--white-color);
--text-small-select-color: var(--white-color);
--border-color: var(--grey-55);
--border-widget-color: var(--white-color);
--border-sidebar-color: var(--blue-9);
--border-form-control-color: var(--grey-54);
--border-table-color: var(--grey-55);
--border-table-top-color: var(--grey-55);
--border-datatable-top-color: var(--grey-55);
--border-sidebar-high-contrast: 1px solid var(--blue-9);
--border-code-high-contrast: 1px solid var(--white-color);
--border-boxselector-wrapper: 3px solid var(--blue-2);
--border-boxselector-wrapper-hover: 3px solid var(--blue-8);
--border-panel-color: var(--white-color);
--border-input-group-addon-color: var(--grey-54);
--border-modal-header-color: var(--grey-3);
--border-input-sm-color: var(--white-color);
--border-pagination-color: var(--grey-3);
--border-pagination-span-color: var(--grey-3);
--border-daterangepicker-color: var(--white-color);
--border-calendar-table: var(--black-color);
--border-daterangepicker: var(--black-color);
--border-pre-next-month: var(--white-color);
--border-daterangepicker-after: var(--black-color);
--border-tooltip-color: var(--white-color);
--border-pre-color: var(--grey-3);
--border-codemirror-cursor-color: var(--white-color);
--border-modal: 1px solid var(--white-color);
--hover-sidebar-color: var(--blue-9);
--hover-sidebar-color: var(--black-color);
--shadow-box-color: none;
--shadow-boxselector-color: none;
--bg-image-multiselect: linear-gradient(var(--black-color), var(--black-color));
--bg-image-multiselect-button: linear-gradient(var(--grey-1), var(--grey-1));
--bg-image-multiselect-hover: linear-gradient(var(--grey-3), var(--grey-3));
--border-multiselect: var(--black-color);
--border-multiselect-checkboxlayer: var(--grey-3);
--text-multiselect: var(--white-color);
--bg-multiselect-checkboxcontainer: var(--grey-3);
--text-multiselect-item: var(--white-color);
--bg-multiselect-helpercontainer: var(--grey-1);
--text-input-textarea: var(--black-color);
--bg-item-highlighted-null-color: var(--grey-2);
--text-cm-default-color: var(--blue-9);
--text-cm-meta-color: var(--white-color);
--text-cm-string-color: var(--red-7);
--text-progress-bar-color: var(--black-color);
}

View File

@ -0,0 +1,399 @@
/* Overide Vendor CSS */
.form-control {
background-color: var(--bg-main-color) !important;
border: 1px solid var(--border-form-control-color);
color: var(--text-form-control-color);
}
.text-muted {
color: var(--text-muted-color);
}
.table > thead > tr > th {
border-bottom: 2px solid var(--border-table-color);
}
.table-hover > tbody > tr:hover {
background-color: var(--bg-hover-table-color);
}
.switch i,
.bootbox-form .checkbox i {
background: var(--bg-switch-box-color);
}
.table > thead > tr > th,
.table > tbody > tr > th,
.table > tfoot > tr > th,
.table > thead > tr > td,
.table > tbody > tr > td,
.table > tfoot > tr > td {
border-top: 1px solid var(--border-table-top-color);
}
a {
color: var(--text-link-color);
}
a:hover,
a:focus {
color: var(--text-link-hover-color);
}
.input-group-addon {
color: var(--text-input-group-addon-color);
background-color: var(--bg-input-group-addon-color);
border: 1px solid var(--border-input-group-addon-color);
}
.btn-default {
color: var(--text-btn-default-color);
background-color: var(--bg-btn-default-color);
border-color: var(--border-btn-default-color);
}
.text-danger {
color: var(--text-danger-color);
}
.table .table {
background-color: var(--bg-table-color);
}
.table-bordered {
border-color: var(--border-table-top-color);
}
.table-bordered > thead > tr > th,
.table-bordered > tbody > tr > th,
.table-bordered > tfoot > tr > th,
.table-bordered > thead > tr > td,
.table-bordered > tbody > tr > td,
.table-bordered > tfoot > tr > td {
border-color: var(--border-table-top-color);
}
.md-checkbox input[type='checkbox']:disabled + label:before {
background: var(--bg-md-checkbox-color) !important;
border-color: var(--border-md-checkbox-color) !important;
}
.form-control[disabled],
.form-control[readonly],
fieldset[disabled] .form-control {
background-color: var(--bg-form-control-disabled-color) !important;
}
.modal.in .modal-dialog {
border: var(--border-modal);
}
.modal-content {
background-color: var(--bg-modal-content-color);
}
.modal-header {
border-bottom: 1px solid var(--border-modal-header-color);
}
.modal-footer {
border-top: 1px solid var(--border-modal-header-color);
}
.close {
color: var(--button-close-color);
opacity: var(--button-opacity);
}
.close:hover,
.close:focus {
color: var(--button-close-color);
opacity: var(--button-opacity-hover);
}
code {
color: var(--text-code-color);
background-color: var(--bg-code-color);
}
.nav-tabs > li.active > a,
.nav-tabs > li.active > a:hover,
.nav-tabs > li.active > a:focus {
color: var(--text-navtabs-color);
background-color: var(--bg-navtabs-color);
border: 1px solid var(--border-navtabs-color);
}
.nav-tabs {
border-bottom: 1px solid var(--border-navtabs-color);
}
.nav-tabs > li > a:hover {
border-color: var(--border-navtabs-color);
}
.nav > li > a:hover,
.nav > li > a:focus {
background-color: var(--bg-navtabs-hover-color);
}
.table > thead > tr > td.active,
.table > tbody > tr > td.active,
.table > tfoot > tr > td.active,
.table > thead > tr > th.active,
.table > tbody > tr > th.active,
.table > tfoot > tr > th.active,
.table > thead > tr.active > td,
.table > tbody > tr.active > td,
.table > tfoot > tr.active > td,
.table > thead > tr.active > th,
.table > tbody > tr.active > th,
.table > tfoot > tr.active > th {
background-color: var(--bg-table-selected-color);
}
.table-hover > tbody > tr > td.active:hover,
.table-hover > tbody > tr > th.active:hover,
.table-hover > tbody > tr.active:hover > td,
.table-hover > tbody > tr:hover > .active,
.table-hover > tbody > tr.active:hover > th {
background-color: var(--bg-table-selected-color);
}
.CodeMirror-gutters {
background: var(--bg-codemirror-gutters-color);
border-right: 1px solid var(--border-codemirror-gutters-color);
}
.CodeMirror {
background: var(--bg-codemirror-color);
color: var(--text-codemirror-color);
}
.CodeMirror-selected {
background: var(--bg-codemirror-selected-color) !important;
}
.CodeMirror-cursor {
border-left: 1px solid var(--border-codemirror-cursor-color);
}
.cm-s-default .cm-atom {
color: var(--text-cm-default-color);
}
.cm-s-default .cm-meta {
color: var(--text-cm-meta-color);
}
.cm-s-default .cm-string {
color: var(--text-cm-string-color);
}
.cm-s-default .cm-number {
color: var(--text-cm-number-color);
}
.dropdown-menu {
background: var(--bg-dropdown-menu-color);
}
.dropdown-menu > li > a {
color: var(--text-dropdown-menu-color);
}
pre {
border: 1px solid var(--border-pre-color);
background-color: var(--bg-pre-color);
color: var(--text-pre-color);
}
json-tree .key {
color: var(--text-json-tree-color);
}
json-tree .leaf-value {
color: var(--text-json-tree-leaf-color);
}
json-tree .branch-preview {
color: var(--text-json-tree-branch-preview-color);
}
.progress {
background-color: var(--bg-progress-color);
}
.pagination > .disabled > span,
.pagination > .disabled > span:hover,
.pagination > .disabled > span:focus,
.pagination > .disabled > a,
.pagination > .disabled > a:hover,
.pagination > .disabled > a:focus {
color: var(--text-pagination-color);
background-color: var(--bg-pagination-color);
border-color: var(--border-pagination-color);
}
.pagination > li > a,
.pagination > li > span {
background-color: var(--bg-pagination-span-color);
border-color: var(--border-pagination-span-color);
color: var(--text-pagination-span-color);
}
.pagination > li > a:hover,
.pagination > li > span:hover,
.pagination > li > a:focus,
.pagination > li > span:focus {
background-color: var(--bg-pagination-hover-color);
border-color: var(--border-pagination-hover-color);
}
.pagination > li > a:hover,
.pagination > li > span:hover,
.pagination > li > a:focus,
.pagination > li > span:focus {
color: var(--text-pagination-span-hover-color);
}
.ui-select-bootstrap .ui-select-choices-row > span {
color: var(--text-ui-select-color);
}
.ui-select-bootstrap .ui-select-choices-row > span:hover,
.ui-select-bootstrap .ui-select-choices-row > span:focus {
background-color: var(--bg-ui-select-hover-color);
color: var(--text-ui-select-hover-color);
}
.motd-body {
background-color: var(--bg-motd-body-color) !important;
}
.panel-body {
background-color: var(--bg-panel-body-color) !important;
}
.panel {
border: 1px solid var(--border-panel-color);
}
.theme-information .col-sm-12 {
padding-left: 0px;
padding-right: 0px;
margin-top: 15px;
}
.theme-panel {
margin-top: 15px;
}
.summary {
color: var(--text-summary-color);
font-weight: 700;
}
.input-sm {
background-color: var(--bg-input-sm-color);
border: 1px solid var(--border-input-sm-color);
}
.rzslider .rz-bubble {
color: var(--text-rzslider-color);
}
.rzslider .rz-bubble.rz-limit {
color: var(--text-rzslider-limit-color);
}
input,
button,
select,
textarea {
background: var(--text-input-textarea);
}
.daterangepicker {
background-color: var(--bg-daterangepicker-color);
border: 1px solid var(--border-daterangepicker-color);
}
.daterangepicker .drp-calendar.left {
background: var(--bg-calendar-color);
}
.daterangepicker .drp-calendar.left .calendar-table {
background: var(--bg-calendar-table-color);
}
.daterangepicker .drp-calendar.right {
background: var(--bg-calendar-color);
}
.daterangepicker .drp-calendar.right .calendar-table {
background: var(--bg-calendar-table-color);
}
.daterangepicker .calendar-table {
border: 1px solid var(--border-calendar-table);
}
.daterangepicker td.off,
.daterangepicker td.off.in-range,
.daterangepicker td.off.start-date,
.daterangepicker td.off.end-date {
background-color: var(--bg-daterangepicker-end-date);
color: var(--text-daterangepicker-end-date);
}
.daterangepicker td.available:hover,
.daterangepicker th.available:hover {
background-color: var(--bg-daterangepicker-hover);
}
.daterangepicker td.in-range {
background-color: var(--bg-daterangepicker-in-range);
color: var(--text-daterangepicker-in-range);
}
.daterangepicker td.active,
.daterangepicker td.active:hover {
background-color: var(--bg-daterangepicker-active);
color: var(--text-daterangepicker-active);
}
.daterangepicker .drp-buttons {
border-top: 1px solid var(--border-daterangepicker);
}
.daterangepicker .calendar-table .next span,
.daterangepicker .calendar-table .prev span {
border-color: var(--border-pre-next-month);
}
.daterangepicker:after {
border-bottom: 6px solid var(--border-daterangepicker-after);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px var(--bg-input-autofill-color) inset !important;
box-shadow: 0 0 0 30px var(--bg-input-autofill-color) inset !important;
}
input:-webkit-autofill {
-webkit-text-fill-color: var(--text-input-autofill-color) !important;
}
.btn:hover {
color: var(--text-button-hover-color);
}
.btn-default:hover {
background-color: var(--bg-btn-default-hover-color);
}
.btn-primary:hover {
color: var(--white-color) !important;
}
/* Overide Vendor CSS */

View File

@ -73,7 +73,11 @@
</button>
</td>
</tr>
<tr dir-paginate-end ng-show="$ctrl.itemCanExpand(value) && value.Expanded" ng-style="{ background: value.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
dir-paginate-end
ng-show="$ctrl.itemCanExpand(value) && value.Expanded"
ng-class="{ 'datatable-highlighted': value.Highlighted, 'datatable-unhighlighted': !value.Highlighted }"
>
<td colspan="1"></td>
<td colspan="1">
{{ value.GlobalIPv6Address }}

View File

@ -171,7 +171,7 @@
allow-checkbox="true"
>
</tr>
<tr dir-paginate-end ng-show="item.Expanded" ng-repeat="it in item.Subs" style="background: #d5e8f3;" network-row-content item="it" parent-ctrl="$ctrl"> </tr>
<tr dir-paginate-end ng-show="item.Expanded" ng-repeat="it in item.Subs" class="datatable-highlighted" network-row-content item="it" parent-ctrl="$ctrl"> </tr>
<tr ng-if="!$ctrl.dataset">
<td colspan="9" class="text-center text-muted">Loading...</td>
</tr>

View File

@ -1,6 +1,6 @@
<div style="background-color: #d5e8f3; padding: 2px;">
<div class="service-datatable">
<table class="table table-condensed table-hover nowrap-cells">
<thead style="background-color: #e7f6ff;">
<thead>
<tr>
<th uib-dropdown dropdown-append-to-body auto-close="disabled" is-open="$ctrl.filters.state.open" style="width: 10%;">
<a ng-click="$ctrl.changeOrderBy('Status.State')">
@ -54,7 +54,7 @@
</th>
</tr>
</thead>
<tbody style="background-color: #f1f9fd;">
<tbody>
<tr
ng-repeat="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter: $ctrl.applyFilters | filter:$ctrl.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder))"
>

View File

@ -105,8 +105,7 @@
<!-- dir-paginate-start track by $index -->
<tr
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | filter: $ctrl.isDisplayed | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
ng-class="{ active: item.Checked }"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '' }"
ng-class="{ active: item.Checked, 'datatable-highlighted': item.Highlighted }"
ng-click="$ctrl.expandItem(item, !item.Expanded)"
pagination-id="$ctrl.tableKey"
>
@ -177,7 +176,7 @@
</td>
</tr>
<!-- sub rows -->
<tr ng-show="item.Expanded" ng-repeat-start="port in item.Ports" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr ng-show="item.Expanded" ng-repeat-start="port in item.Ports" ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }">
<td ng-if="!$ctrl.portHasIngressRules(port)"></td>
<td ng-if="!$ctrl.portHasIngressRules(port)">-</td>
<td ng-if="!$ctrl.portHasIngressRules(port)">-</td>
@ -190,7 +189,12 @@
<td ng-if="!$ctrl.portHasIngressRules(port)">{{ port.TargetPort }}/{{ port.Protocol }}</td>
<td ng-if="!$ctrl.portHasIngressRules(port)">-</td>
</tr>
<tr ng-show="item.Expanded" ng-repeat-end ng-repeat="rule in port.IngressRules" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
ng-show="item.Expanded"
ng-repeat-end
ng-repeat="rule in port.IngressRules"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td></td>
<td>-</td>
<td>-</td>

View File

@ -109,8 +109,7 @@
<tbody>
<tr
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | filter: $ctrl.isDisplayed | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
ng-class="{ active: item.Checked }"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '' }"
ng-class="{ active: item.Checked, 'datatable-highlighted': item.Highlighted }"
ng-click="$ctrl.expandItem(item, !item.Expanded)"
pagination-id="$ctrl.tableKey"
>
@ -141,7 +140,12 @@
<a ui-sref="kubernetes.stacks.stack.logs({ namespace: item.ResourcePool, name: item.Name })"> <i class="fa fa-file-alt" aria-hidden="true"></i> Logs </a>
</td>
</tr>
<tr dir-paginate-end ng-show="item.Expanded" ng-repeat="app in item.Applications" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
dir-paginate-end
ng-show="item.Expanded"
ng-repeat="app in item.Applications"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td></td>
<td colspan="4">
<a ui-sref="kubernetes.applications.application({ name: app.Name, namespace: app.ResourcePool })">{{ app.Name }}</a>

View File

@ -75,8 +75,7 @@
<tbody>
<tr
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | filter: $ctrl.isDisplayed | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
ng-class="{ active: item.Checked }"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '' }"
ng-class="{ active: item.Checked, 'datatable-highlighted': item.Highlighted }"
ng-click="$ctrl.expandItem(item, !item.Expanded)"
pagination-id="$ctrl.tableKey"
>
@ -92,14 +91,23 @@
</td>
</tr>
<!-- ADMIN + UNMET TAINTS -->
<tr ng-if="$ctrl.isAdmin" ng-show="item.Expanded" ng-repeat="taint in item.UnmetTaints" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
ng-if="$ctrl.isAdmin"
ng-show="item.Expanded"
ng-repeat="taint in item.UnmetTaints"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td colspan="2">
This application is missing a toleration for the taint <code>{{ taint.Key }}{{ taint.Value ? '=' + taint.Value : '' }}:{{ taint.Effect }}</code>
</td>
</tr>
<!-- !ADMIN + UNMET TAINTS -->
<!-- USER + UNMET TAINTS -->
<tr ng-if="!$ctrl.isAdmin && item.UnmetTaints.length" ng-show="item.Expanded" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
ng-if="!$ctrl.isAdmin && item.UnmetTaints.length"
ng-show="item.Expanded"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td colspan="2">
Placement constraint not respected for that node.
</td>
@ -110,7 +118,7 @@
ng-if="$ctrl.isAdmin"
ng-show="item.Expanded"
ng-repeat="label in item.UnmatchedNodeSelectorLabels"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td colspan="2">
This application can only be scheduled on a node where the label <code>{{ label.key }}</code> is set to <code>{{ label.value }}</code>
@ -121,7 +129,7 @@
<tr
ng-if="!$ctrl.isAdmin && (item.UnmatchedNodeSelectorLabels.length || item.UnmatchedNodeAffinities.length)"
ng-show="item.Expanded"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td colspan="2">
Placement label not respected for that node.
@ -129,7 +137,11 @@
</tr>
<!-- ! USER + UNMET NODE SELECTOR LABELS || UNMET NODE AFFINITIES -->
<!-- ADMIN + UNMET NODE AFFINITIES -->
<tr ng-if="$ctrl.isAdmin" ng-show="item.Expanded && item.UnmatchedNodeAffinities.length" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
ng-if="$ctrl.isAdmin"
ng-show="item.Expanded && item.UnmatchedNodeAffinities.length"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td colspan="2">
This application can only be scheduled on nodes respecting one of the following labels combination:
</td>
@ -139,7 +151,7 @@
ng-if="$ctrl.isAdmin"
ng-show="item.Expanded"
ng-repeat="aff in item.UnmatchedNodeAffinities"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td></td>
<td>

View File

@ -73,8 +73,7 @@
<tbody>
<tr
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
ng-class="{ active: item.Checked }"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '' }"
ng-class="{ active: item.Checked, 'datatable-highlighted': item.Highlighted }"
ng-click="$ctrl.expandItem(item, !item.Expanded)"
pagination-id="$ctrl.tableKey"
>
@ -84,7 +83,12 @@
>{{ item.Name }}
</td>
</tr>
<tr dir-paginate-end ng-show="item.Expanded" ng-repeat="path in item.Paths" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
dir-paginate-end
ng-show="item.Expanded"
ng-repeat="path in item.Paths"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td>
<a style="margin-left: 15px;" ng-href="http://{{ path.Host ? path.Host : path.IP }}{{ path.Path }}" target="_blank">
{{ path.Host ? path.Host : path.IP }}{{ path.Path }}

View File

@ -22,7 +22,7 @@
<li ng-repeat="summary in $ctrl.state.resources" ng-if="summary.action && summary.kind && summary.name">
{{ summary.action }}
{{ $ctrl.getArticle(summary.kind, summary.action) }}
<span style="color: black; font-weight: 700;">{{ summary.kind }}</span> named <code>{{ summary.name }}</code>
<span class="summary">{{ summary.kind }}</span> named <code>{{ summary.name }}</code>
<span ng-if="summary.type">
of type <code>{{ summary.type }}</code></span
>

View File

@ -82,8 +82,7 @@
<tbody>
<tr
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
ng-class="{ active: item.Checked }"
ng-style="{ background: item.Highlighted ? '#d5e8f3' : '' }"
ng-class="{ active: item.Checked, 'datatable-highlighted': item.Highlighted }"
ng-click="$ctrl.expandItem(item, !item.Expanded)"
pagination-id="$ctrl.tableKey"
>
@ -95,7 +94,12 @@
<td>{{ item.Name }}</td>
<td>{{ item.Size }}</td>
</tr>
<tr dir-paginate-end ng-show="item.Expanded" ng-repeat="vol in item.Volumes" ng-style="{ background: item.Highlighted ? '#d5e8f3' : '#f5f5f5' }">
<tr
dir-paginate-end
ng-show="item.Expanded"
ng-repeat="vol in item.Volumes"
ng-class="{ 'datatable-highlighted': item.Highlighted, 'datatable-unhighlighted': !item.Highlighted }"
>
<td></td>
<td>
<a ui-sref="kubernetes.volumes.volume({ name: vol.PersistentVolumeClaim.Name, namespace: vol.PersistentVolumeClaim.Namespace })">

View File

@ -27,22 +27,27 @@
.boxselector_wrapper input[type='radio']:not(:disabled) ~ label {
cursor: pointer;
background-color: var(--bg-boxselector-wrapper-disabled-color);
}
.boxselector_wrapper input[type='radio']:not(:disabled):hover ~ label:hover {
cursor: pointer;
}
.boxselector_wrapper label {
font-weight: normal;
font-size: 12px;
display: block;
background: white;
border: 1px solid #333333;
background: var(--bg-boxselector-color);
border: 1px solid var(--border-boxselector-color);
border-radius: 2px;
padding: 10px 10px 0 10px;
text-align: center;
box-shadow: 0 3px 10px -2px rgba(161, 170, 166, 0.5);
box-shadow: var(--shadow-boxselector-color);
position: relative;
}
.boxselector_wrapper label.boxselector_disabled {
background: #cacaca;
background: var(--bg-boxselector-disabled-color) !important;
border-color: #787878;
color: #787878;
cursor: not-allowed;

View File

@ -8,7 +8,7 @@
<button type="button" class="btn btn-sm btn-primary" ui-state="$ctrl.createPath"> <i class="fa fa-plus space-right" aria-hidden="true"></i>Add Custom Template </button>
</div>
<div class="searchBar" style="border-top: 2px solid #f6f6f6;">
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input
type="text"

View File

@ -1,6 +1,6 @@
.datatable .toolBar {
background-color: #f6f6f6;
color: #767676;
background-color: var(--bg-card-color);
color: var(--text-main-color);
overflow: auto;
padding: 10px;
}
@ -30,9 +30,10 @@
}
.datatable .searchBar {
border-top: 1px solid #d2d1d1;
border-bottom: 1px solid #d2d1d1;
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
padding: 8px;
background: var(--bg-main-color);
}
.datatable .searchInput {
@ -60,9 +61,10 @@
}
.datatable .footer {
background-color: #f6f6f6;
color: #767676;
background-color: var(--bg-card-color);
color: var(--text-main-color);
overflow: auto;
border-top: 1px solid var(--border-datatable-top-color);
}
.datatable .footer .infoBar {
@ -152,9 +154,8 @@
}
.md-checkbox label:before {
background: #fff;
border: 2px solid black;
border: 2px solid rgba(0, 0, 0, 0.54);
background: var(--bg-main-color);
border: 2px solid var(--bg-checkbox-border-color);
border-radius: 2px;
cursor: pointer;
height: 16px;

View File

@ -13,7 +13,7 @@
* Sidebar
*/
#sidebar-wrapper {
background: #30426a;
background: var(--bg-sidebar-wrapper-color);
}
ul.sidebar .sidebar-main a,
@ -21,7 +21,7 @@ ul.sidebar .sidebar-main a,
ul.sidebar .sidebar-list a:hover,
#page-wrapper:not(.open) ul.sidebar .sidebar-title.separator {
/* Sidebar header and footer color */
background: #2d3e63;
background: var(--hover-sidebar-color);
}
ul.sidebar {
@ -63,7 +63,7 @@ ul.sidebar .sidebar-main .menu-icon {
}
ul.sidebar .sidebar-title {
color: #738bc0;
color: var(--text-sidebar-title-color);
font-size: 12px;
height: 35px;
line-height: 40px;
@ -74,7 +74,7 @@ ul.sidebar .sidebar-title {
ul.sidebar .sidebar-list a {
text-indent: 25px;
font-size: 15px;
color: #b2bfdc;
color: var(--text-sidebar-list-color);
line-height: 40px;
padding-left: 5px;
border-left: 3px solid transparent;
@ -132,7 +132,7 @@ ul.sidebar .sidebar-list .menu-icon {
}
.sidebar-footer div a {
color: #b2bfdc;
color: var(--text-sidebar-list-color);
font-size: 12px;
line-height: 43px;
}
@ -172,8 +172,8 @@ ul.sidebar .sidebar-list a {
ul.sidebar .sidebar-list a.active {
color: #fff;
border-left-color: #fff;
background: #2d3e63;
border-left-color: var(--border-sidebar-color);
background: var(--hover-sidebar-color);
}
.sidebar-header {
@ -181,7 +181,7 @@ ul.sidebar .sidebar-list a.active {
list-style: none;
text-indent: 20px;
font-size: 18px;
background: #2d3e63;
background: var(--bg-sidebar-header-color);
}
.sidebar-header a {
@ -255,7 +255,7 @@ ul.sidebar .sidebar-list a.active .menu-icon {
ul.sidebar .sidebar-list .sidebar-sublist a {
text-indent: 35px;
font-size: 12px;
color: #b2bfdc;
color: var(--text-sidebar-list-color);
line-height: 36px;
}
@ -280,7 +280,7 @@ ul.sidebar .sidebar-list .menu-icon {
ul.sidebar .sidebar-list .sidebar-sublist a.active {
color: #fff;
border-left: 3px solid #fff;
background: #2d3e63;
background: var(--bg-sidebar-color);
}
@media (max-height: 785px) {

View File

@ -32,7 +32,7 @@
</div>
</div>
<div class="searchBar" style="border-top: 2px solid #f6f6f6;">
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input
type="text"

View File

@ -0,0 +1,70 @@
import { buildOption } from '@/portainer/components/box-selector';
export default class ThemeSettingsController {
/* @ngInject */
constructor($async, Authentication, ThemeManager, StateManager, UserService, Notifications) {
this.$async = $async;
this.Authentication = Authentication;
this.ThemeManager = ThemeManager;
this.StateManager = StateManager;
this.UserService = UserService;
this.Notifications = Notifications;
this.setTheme = this.setTheme.bind(this);
}
/** Theme Settings Panel */
async updateTheme() {
try {
await this.UserService.updateUserTheme(this.state.userId, this.state.userTheme);
this.state.themeInProgress = false;
this.Notifications.success('Success', 'User theme successfully updated');
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to update user theme');
}
}
setTheme(theme) {
this.ThemeManager.setTheme(theme);
this.state.themeInProgress = true;
}
$onInit() {
return this.$async(async () => {
this.state = {
userId: null,
userTheme: '',
initTheme: '',
defaultTheme: 'light',
themeInProgress: false,
};
this.state.availableThemes = [
buildOption('light', 'fas fa-sun', 'Light Theme', 'Default color mode', 'light'),
buildOption('dark', 'fas fa-moon', 'Dark Theme', 'Dark color mode', 'dark'),
buildOption('highcontrast', 'fas fa-adjust', 'High Contrast', 'High contrast color mode', 'highcontrast'),
];
this.state.availableTheme = {
light: 'light',
dark: 'dark',
highContrast: 'highcontrast',
};
try {
this.state.userId = await this.Authentication.getUserDetails().ID;
const data = await this.UserService.user(this.state.userId);
this.state.userTheme = data.UserTheme || this.state.defaultTheme;
this.state.initTheme = this.state.userTheme;
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to get user details');
}
});
}
$onDestroy() {
if (this.state.themeInProgress) {
this.ThemeManager.setTheme(this.state.initTheme);
}
}
}

View File

@ -0,0 +1,19 @@
<information-panel class="theme-information" title-text="Information">
<span class="small text-muted">
<p>
<i class="fa fa-flask orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
Dark and High-contrast theme are experimental. Some UI components might not display properly.
</p>
</span>
</information-panel>
<rd-widget>
<rd-widget-header icon="fa-palette" title-text="Change user theme"></rd-widget-header>
<rd-widget-body>
<form class="theme-panel">
<!-- Theme -->
<box-selector radio-name="theme" ng-model="$ctrl.state.userTheme" options="$ctrl.state.availableThemes" on-change="($ctrl.setTheme)"></box-selector>
<button ng-click="$ctrl.updateTheme()" class="btn btn-primary btn-sm">Update theme</button>
<!-- !Theme -->
</form>
</rd-widget-body>
</rd-widget>

View File

@ -0,0 +1,7 @@
import angular from 'angular';
import controller from './theme-settings.controller';
angular.module('portainer.app').component('themeSettings', {
templateUrl: './theme-settings.html',
controller,
});

View File

@ -2,6 +2,7 @@ export function UserViewModel(data) {
this.Id = data.Id;
this.Username = data.Username;
this.Role = data.Role;
this.UserTheme = data.UserTheme;
if (data.Role === 1) {
this.RoleName = 'administrator';
} else {

View File

@ -12,6 +12,7 @@ angular.module('portainer.app').factory('Users', [
get: { method: 'GET', params: { id: '@id' } },
update: { method: 'PUT', params: { id: '@id' }, ignoreLoadingBar: true },
updatePassword: { method: 'PUT', params: { id: '@id', entity: 'passwd' } },
updateTheme: { method: 'PUT', params: { id: '@id' } },
remove: { method: 'DELETE', params: { id: '@id' } },
queryMemberships: { method: 'GET', isArray: true, params: { id: '@id', entity: 'memberships' } },
checkAdminUser: { method: 'GET', params: { id: 'admin', entity: 'check' }, isArray: true, ignoreLoadingBar: true },

View File

@ -91,6 +91,10 @@ angular.module('portainer.app').factory('UserService', [
return Users.updatePassword({ id: id }, payload).$promise;
};
service.updateUserTheme = function (id, userTheme) {
return Users.updateTheme({ id }, { userTheme }).$promise;
};
service.userMemberships = function (id) {
var deferred = $q.defer();

View File

@ -9,7 +9,9 @@ angular.module('portainer.app').factory('Authentication', [
'LocalStorage',
'StateManager',
'EndpointProvider',
function AuthenticationFactory($async, $state, Auth, OAuth, jwtHelper, LocalStorage, StateManager, EndpointProvider) {
'UserService',
'ThemeManager',
function AuthenticationFactory($async, $state, Auth, OAuth, jwtHelper, LocalStorage, StateManager, EndpointProvider, UserService, ThemeManager) {
'use strict';
var service = {};
@ -82,12 +84,20 @@ angular.module('portainer.app').factory('Authentication', [
return user;
}
async function setUserTheme() {
const data = await UserService.user(user.ID);
// Initialize user theme base on Usertheme from database
const userTheme = data.UserTheme;
ThemeManager.setTheme(userTheme);
}
async function setUser(jwt) {
LocalStorage.storeJWT(jwt);
var tokenPayload = jwtHelper.decodeToken(jwt);
user.username = tokenPayload.username;
user.ID = tokenPayload.id;
user.role = tokenPayload.role;
await setUserTheme();
}
function isAdmin() {

View File

@ -54,6 +54,11 @@ angular.module('portainer.app').factory('StateManager', [
LocalStorage.storeApplicationState(state.application);
};
manager.updateTheme = function (theme) {
state.application.theme = theme;
LocalStorage.storeApplicationState(state.application);
};
manager.updateSnapshotInterval = function (interval) {
state.application.snapshotInterval = interval;
LocalStorage.storeApplicationState(state.application);

View File

@ -0,0 +1,23 @@
angular.module('portainer.app').service('ThemeManager', ThemeManager);
/* @ngInject */
export function ThemeManager(StateManager) {
return {
setTheme,
defaultTheme,
};
function setTheme(theme) {
if (!theme) {
document.documentElement.removeAttribute('theme');
} else {
document.documentElement.setAttribute('theme', theme);
}
StateManager.updateTheme(theme);
}
function defaultTheme() {
document.documentElement.removeAttribute('theme');
}
}

View File

@ -78,5 +78,6 @@
</form>
</rd-widget-body>
</rd-widget>
<theme-settings></theme-settings>
</div>
</div>

View File

@ -5,11 +5,14 @@ angular.module('portainer.app').controller('AccountController', [
'UserService',
'Notifications',
'SettingsService',
function ($scope, $state, Authentication, UserService, Notifications, SettingsService) {
'StateManager',
'ThemeManager',
function ($scope, $state, Authentication, UserService, Notifications, SettingsService, StateManager, ThemeManager) {
$scope.formValues = {
currentPassword: '',
newPassword: '',
confirmPassword: '',
userTheme: '',
};
$scope.updatePassword = function () {
@ -23,8 +26,30 @@ angular.module('portainer.app').controller('AccountController', [
});
};
function initView() {
// Update DOM for theme attribute & LocalStorage
$scope.setTheme = function (theme) {
ThemeManager.setTheme(theme);
StateManager.updateTheme(theme);
};
// Rest API Call to update theme with userID in DB
$scope.updateTheme = function () {
UserService.updateUserTheme($scope.userID, $scope.formValues.userTheme)
.then(function success() {
Notifications.success('Success', 'User theme successfully updated');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, err.msg);
});
};
async function initView() {
$scope.userID = Authentication.getUserDetails().ID;
const data = await UserService.user($scope.userID);
$scope.formValues.userTheme = data.Usertheme;
SettingsService.publicSettings()
.then(function success(data) {
$scope.AuthenticationMethod = data.AuthenticationMethod;

View File

@ -2,7 +2,7 @@ import angular from 'angular';
class LogoutController {
/* @ngInject */
constructor($async, $state, $transition$, $window, Authentication, StateManager, Notifications, LocalStorage, SettingsService) {
constructor($async, $state, $transition$, $window, Authentication, StateManager, Notifications, LocalStorage, SettingsService, ThemeManager) {
this.$async = $async;
this.$state = $state;
this.$transition$ = $transition$;
@ -13,6 +13,7 @@ class LogoutController {
this.Notifications = Notifications;
this.LocalStorage = LocalStorage;
this.SettingsService = SettingsService;
this.ThemeManager = ThemeManager;
this.logo = this.StateManager.getState().application.logo;
this.logoutAsync = this.logoutAsync.bind(this);
@ -28,6 +29,8 @@ class LogoutController {
const performApiLogout = this.$transition$.params().performApiLogout;
const settings = await this.SettingsService.publicSettings();
this.ThemeManager.defaultTheme();
try {
await this.Authentication.logout(performApiLogout);
} finally {

View File

@ -3,6 +3,7 @@ angular.module('portainer.app').controller('MainController', [
'LocalStorage',
'StateManager',
'EndpointProvider',
'ThemeManager',
function ($scope, LocalStorage, StateManager, EndpointProvider) {
/**
* Sidebar Toggle & Cookie Control