Compare commits

..

24 Commits

Author SHA1 Message Date
Steven Kang
14b998d270 Set static DOCKER_VERSION for ppc64le and s390x (#7135) 2022-06-28 11:38:12 +12:00
Chaim Lev-Ari
605ff8c1da fix(environments): hide async mode on deployment [EE-3380] (#7129)
fixes [EE-3380]
2022-06-28 10:23:07 +12:00
Chaim Lev-Ari
13f93f4262 fix(analytics): load public settings [EE-3590] (#7127) 2022-06-27 19:29:06 +03:00
Steven Kang
16be5ed329 feat(build): set static DOCKER_VERSION for ppc64le and s390x (#7124) 2022-06-27 09:54:04 +12:00
Chaim Lev-Ari
c6612898f3 fix(api): add missing edge types [EE-3590] (#7117) 2022-06-26 08:38:20 +03:00
andres-portainer
564f34b0ba fix(wizard): replace the YAML file by the docker commands EE-3589 (#7112) 2022-06-24 14:59:00 -03:00
LP B
392fbdb4a7 fix(app/account): ensure newTransition exists in uiCanExit [EE-3336] (#7109) 2022-06-24 17:35:39 +02:00
Chaim Lev-Ari
a826c78786 fix(edge): show heartbeat for async env [EE-3380] (#7096) 2022-06-22 20:11:42 +03:00
Matt Hook
a35f0607f1 fix docker download path for mac platforms (#7101) 2022-06-22 10:06:28 +12:00
LP B
081d32af0d fix(app/account): create access token button (#7091)
* fix(app/account): create access token button

* fix(app/formcontrol): error message overlapping input on smaller screens
2022-06-20 14:14:41 +02:00
itsconquest
4cc0b1f567 fix(auth): track skips per user [EE-3318] (#7088) 2022-06-20 17:00:00 +12:00
Chaim Lev-Ari
d4da7e1760 fix(docker/networks): show correct resource control data [EE-3401] (#7061) 2022-06-17 19:21:38 +03:00
itsconquest
aced418880 fix(auth): clear skips when using new instance [EE-3331] (#7026) 2022-06-17 14:45:42 +12:00
Chaim Lev-Ari
614f42fe5a feat(custom-templates): hide variables [EE-2602] (#7069) 2022-06-16 08:32:43 +03:00
itsconquest
58736fe93b feat(auth): allow single char passwords [EE-3385] (#7049)
* feat(auth): allow single character passwords

* match weak password modal logic to slider
2022-06-16 12:31:39 +12:00
Matt Hook
b78330b10d fix(swarm): don't stomp on the x-registry-auth header EE-3308 (#7037)
* don't stomp on the x-registry-auth header

* del header if empty json provided for registry auth
2022-06-16 09:54:06 +12:00
itsconquest
eed4a92ca8 fix(auth): notify user password requirements [EE-3344] (#7041)
* fix(auth): notify user password requirements [EE-3344]

* fix angular code
2022-06-15 17:15:38 +12:00
Dmitry Salakhov
0e7468a1e8 fix: clarify password change error (#7020) 2022-06-15 15:44:54 +12:00
congs
b807481f1c fix(teamleader): EE-3411 normal users get an unauthorized error (#7053) 2022-06-14 14:12:33 +12:00
Ali
da27de2154 fix(wizard): return back to envs page EE-3419 (#7064) 2022-06-13 14:59:23 +12:00
congs
6743e4fbb2 fix(teamleader): EE-3383 allow teamleader promote member to teamleader (#7039) 2022-06-10 17:13:23 +12:00
Ali
b489ffaa63 fix(wizard): show teasers for kaas and kubeconfig features [EE-3316] (#7033)
* fix(wizard): add nomad, kaas, kubeconfig teasers
2022-06-10 09:16:43 +12:00
congs
6e12499d61 fix(teamleader): EE-3332 hide name and leaders (#7032) 2022-06-09 14:22:42 +12:00
Ali
f7acbe16ba fix(wizard): use 'New Environments' title EE-3329 (#7035) 2022-06-08 16:37:53 +12:00
579 changed files with 6546 additions and 6494 deletions

View File

@@ -31,12 +31,7 @@ rules:
[
'error',
{
pathGroups:
[
{ pattern: '@@/**', group: 'internal', position: 'after' },
{ pattern: '@/**', group: 'internal' },
{ pattern: '{Kubernetes,Portainer,Agent,Azure,Docker}/**', group: 'internal' },
],
pathGroups: [{ pattern: '@/**', group: 'internal' }, { pattern: '{Kubernetes,Portainer,Agent,Azure,Docker}/**', group: 'internal' }],
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
pathGroupsExcludedImportTypes: ['internal'],
},
@@ -46,7 +41,6 @@ settings:
'import/resolver':
alias:
map:
- ['@@', './app/react/components']
- ['@', './app']
extensions: ['.js', '.ts', '.tsx']
@@ -58,7 +52,6 @@ overrides:
parser: '@typescript-eslint/parser'
plugins:
- '@typescript-eslint'
- 'regex'
extends:
- airbnb
- airbnb-typescript
@@ -75,14 +68,7 @@ overrides:
version: 'detect'
rules:
import/order:
[
'error',
{
pathGroups: [{ pattern: '@@/**', group: 'internal', position: 'after' }, { pattern: '@/**', group: 'internal' }],
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
'newlines-between': 'always',
},
]
['error', { pathGroups: [{ pattern: '@/**', group: 'internal' }], groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], 'newlines-between': 'always' }]
func-style: [error, 'declaration']
import/prefer-default-export: off
no-use-before-define: ['error', { functions: false }]
@@ -104,7 +90,6 @@ overrides:
'react/jsx-no-bind': off
'no-await-in-loop': 'off'
'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }]
'regex/invalid': ['error', [{ 'regex': 'data-feather="(.*)"', 'message': 'Please use `react-feather` package instead' }]]
- files:
- app/**/*.test.*
extends:

View File

@@ -22,7 +22,7 @@ Please note that the public demo cluster is **reset every 15min**.
Portainer CE is updated regularly. We aim to do an update release every couple of months.
**The latest version of Portainer is 2.13.x**.
**The latest version of Portainer is 2.9.x**. Portainer is on version 2, the second number denotes the month of release.
## Getting started

View File

@@ -910,7 +910,7 @@
],
"version": {
"DB_UPDATING": "false",
"DB_VERSION": "60",
"DB_VERSION": "50",
"INSTANCE_ID": "null"
}
}

View File

@@ -80,7 +80,7 @@ type Handler struct {
}
// @title PortainerCE API
// @version 2.15.0
// @version 2.14.0
// @description.markdown api-description.md
// @termsOfService

View File

@@ -37,7 +37,7 @@ func parseRegToken(registry *portainer.Registry) (username, password string, err
func EnsureRegTokenValid(dataStore dataservices.DataStore, registry *portainer.Registry) (err error) {
if registry.Type == portainer.EcrRegistry {
if isRegTokenValid(registry) {
log.Println("[DEBUG] [registry, GetEcrAccessToken] [message: current ECR token is still valid]")
log.Println("[DEBUG] [registry, GetEcrAccessToken] [message: curretn ECR token is still valid]")
} else {
err = doGetRegToken(dataStore, registry)
if err != nil {

View File

@@ -1385,9 +1385,9 @@ type (
const (
// APIVersion is the version number of the Portainer API
APIVersion = "2.15.0"
APIVersion = "2.14.0"
// DBVersion is the version number of the Portainer database
DBVersion = 60
DBVersion = 50
// ComposeSyntaxMaxVersion is a maximum supported version of the docker compose syntax
ComposeSyntaxMaxVersion = "3.9"
// AssetsServerURL represents the URL of the Portainer asset server

View File

@@ -1,5 +1,4 @@
import $ from 'jquery';
import feather from 'feather-icons';
import { PortainerEndpointTypes } from 'Portainer/models/endpoint/models';
/* @ngInject */
@@ -7,14 +6,7 @@ export function onStartupAngular($rootScope, $state, $interval, LocalStorage, En
EndpointProvider.initialize();
$rootScope.$state = $state;
const defaultTitle = document.title;
$transitions.onEnter({}, () => {
const endpoint = EndpointProvider.currentEndpoint();
if (endpoint) {
document.title = `${defaultTitle} | ${endpoint.Name}`;
}
});
$rootScope.defaultTitle = document.title;
// Workaround to prevent the loading bar from going backward
// https://github.com/chieffancypants/angular-loading-bar/issues/273
@@ -29,10 +21,6 @@ export function onStartupAngular($rootScope, $state, $interval, LocalStorage, En
HttpRequestHelper.resetAgentHeaders();
});
$transitions.onSuccess({}, () => {
feather.replace();
});
// Keep-alive Edge endpoints by sending a ping request every minute
$interval(() => {
ping(EndpointProvider, SystemService);

View File

@@ -2,27 +2,8 @@
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'Inter';
src: url('../fonts/Inter-VariableFont.ttf') format('truetype');
font-weight: 100 900;
font-style: normal;
}
@media screen and (-webkit-min-device-pixel-ratio: 0) {
select {
font-family: Inter, Arial, Helvetica, sans-serif;
}
}
html {
font-size: 16px;
overflow-y: scroll;
}
body {
background: var(--bg-body-color);
font-family: 'Inter';
color: var(--text-body-color) !important;
}
html,
@@ -86,6 +67,7 @@ body,
}
.form-section-title {
border-bottom: 1px solid var(--border-form-section-title-color);
margin-top: 5px;
margin-bottom: 15px;
color: var(--text-form-section-title-color);
@@ -167,7 +149,7 @@ a[ng-click] {
}
.fa.red-icon {
color: #f04438;
color: #ae2323;
}
.fa.orange-icon {
@@ -239,13 +221,12 @@ a[ng-click] {
}
.blocklist-item {
padding: 10px;
margin-bottom: 10px;
padding: 7px;
margin-bottom: 7px;
cursor: pointer;
border: 1px solid var(--border-blocklist);
border-radius: 8px;
border: 1px solid var(--border-blocklist-color);
border-radius: 2px;
box-shadow: var(--shadow-box-color);
margin-right: 10px;
}
.blocklist-item--disabled {
@@ -260,8 +241,6 @@ a[ng-click] {
}
.blocklist-item:hover {
@apply border border-blue-7;
background-color: var(--bg-blocklist-hover-color);
color: var(--text-blocklist-hover-color);
}
@@ -400,13 +379,12 @@ a[ng-click] {
}
.panel-body {
padding: 30px 25px;
background-color: var(--white-color);
border-radius: 8px;
padding-top: 30px;
background-color: var(--white-color) fff;
}
.user-box {
margin-right: 15px;
margin-right: 25px;
}
.select-endpoint {
@@ -829,12 +807,11 @@ json-tree .branch-preview {
}
/* !spinkit override */
/* uib-typeahead override */
#scrollable-dropdown-menu .dropdown-menu {
max-height: 300px;
overflow-y: auto;
.kubectl-shell {
display: block;
text-align: center;
padding-bottom: 5px;
}
/* !uib-typeahead override */
.no-margin {
margin: 0 !important;
@@ -858,12 +835,3 @@ json-tree .branch-preview {
.form-check.radio {
margin-left: 15px;
}
.inline-text {
display: inline;
position: absolute;
font-family: 'Montserrat';
font-size: smaller;
margin-left: 5px;
margin-right: 5px;
}

View File

@@ -1,468 +0,0 @@
/* Main Color UI Override*/
.blue {
background: var(--bg-dashboard-item) !important;
}
/* Button */
.btn {
border-radius: 5px;
}
.btn-primary {
background-color: var(--ui-blue-8);
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active .active {
background-color: var(--ui-blue-2);
}
.btn-danger {
background-color: var(--ui-error-8);
}
.btn-success {
background-color: var(--ui-success-7);
}
/* Toggle switch */
.switch {
position: relative;
display: inline-block;
width: 42px;
height: 25px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* Toggle */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--bg-switch-box-color);
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: '';
height: 19px;
width: 19px;
left: 3px;
bottom: 3px;
background-color: var(--white-color);
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked + .slider {
background-color: var(--ui-blue-8);
}
input:focus + .slider {
box-shadow: 0 0 1px var(--ui-blue-8);
}
input:checked + .slider:before {
-webkit-transform: translateX(17px);
-ms-transform: translateX(17px);
transform: translateX(17px);
}
.slider.round {
border-radius: 25px;
}
.slider.round:before {
border-radius: 50%;
}
/* Checkbox */
.md-checkbox input[type='checkbox']:enabled + label:before {
background-color: var(--bg-checkbox) !important;
border: 1px solid var(--border-checkbox) !important;
border-radius: 5px;
}
.md-checkbox input[type='checkbox']:disabled + label:before {
border-radius: 5px;
}
.md-checkbox input[type='checkbox']:checked + label:before {
background-color: var(--ui-blue-8) !important;
color: var(--ui-blue-8) !important;
border: 1px solid var(--ui-blue-8) !important;
}
.md-checkbox input[type='checkbox']:checked + .checkmark {
border-color: var(--grey-6);
background-color: var(--bg-checkbox);
}
/* Slider */
.rzslider .rz-pointer {
background-color: var(--white-color);
border: 3px solid var(--ui-blue-8);
width: 25px;
height: 25px;
top: -10px;
}
.rzslider .rz-bar {
background-color: var(--ui-gray-5);
height: 8px;
border-radius: 5px;
}
.rzslider .rz-selection {
background-color: var(--ui-blue-8);
}
.rzslider .rz-pointer:after {
display: none;
}
/* Datatable */
.datatable .searchBar {
border: 1px solid var(--border-searchbar);
padding: 5px;
background: var(--bg-searchbar) !important;
border-radius: 5px;
}
.datatable .searchBar input[type='text'] {
border: 0px !important;
}
.datatable .toolBar {
border-radius: 8px;
}
.datatable .footer {
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
padding-bottom: 10px;
}
.datatable .toolBar {
padding-top: 20px !important;
padding-bottom: 20px !important;
}
.toolBar {
display: flex;
flex-direction: row;
}
.toolBar > .toolBarTitle {
flex: auto;
}
.toolBar > .searchBar {
flex: right;
margin-right: 10px;
width: 500px;
height: 30px;
}
.datatable .searchBar {
padding: 4px 10px !important;
font-size: 14px;
}
.toolBar > .actionBar {
flex: right;
margin-right: 10px;
}
.datatable .actionBar {
padding: 0px !important;
}
.toolBar > .settings {
width: 60px;
}
.datatable .toolBar .settings {
margin-right: 5px !important;
}
/* Widget */
.widget .widget-icon i {
color: var(--ui-blue-8);
}
.widget .widget-body table thead {
border-top: 1px solid var(--border-table-color);
}
/* Button Group */
.input-group-addon:first-child {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.input-group .form-control:not(:first-child):not(:last-child) {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.input-group-btn:last-child .btn {
margin-left: 5px;
border-radius: 5px;
}
.form-control {
border-radius: 5px;
}
.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
background-color: var(--bg-button-group);
border: 1px solid var(--border-button-group);
color: var(--text-button-group);
}
.btn-group .btn-light {
background-color: var(--bg-button-group);
border: 1px solid var(--border-button-group);
color: var(--text-button-group);
}
.btn-group .btn-dangerlight {
background-color: var(--ui-error-2);
border: 1px solid var(--border-button-group);
color: var(--ui-error-8);
}
.btn.active {
box-shadow: none;
}
/* Toaster */
#toast-container > .toast-success {
background-image: url(../images/icon-success.svg) !important;
background-position: top 20px left 20px;
}
#toast-container > .toast-error {
background-image: url(../images/icon-error.svg) !important;
background-position: top 20px left 20px;
}
#toast-container > .toast-warning {
background-image: url(../images/icon-warning.svg) !important;
}
.toast-success .toast-progress {
background-color: var(--ui-success-7);
}
.toast-warning .toast-progress {
background-color: var(--ui-warning-6);
}
.toast-error .toast-progress {
background-color: var(--ui-error-8);
}
#toast-container > div {
color: var(--ui-gray-7);
background-color: var(--white-color);
border-radius: 8px;
padding: 20px 20px 20px 80px;
width: 300px;
opacity: 1;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
filter: alpha(opacity=100);
}
#toast-container > div:hover {
-moz-box-shadow: 0 0 12px var(--ui-gray-7);
-webkit-box-shadow: 0 0 12px var(--ui-gray-7);
box-shadow: 0 0 12px var(--ui-gray-7);
}
.toast-close-button {
color: var(--black-color);
text-decoration: none;
cursor: pointer;
opacity: 0.4;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
filter: alpha(opacity=40);
}
.toast-close-button:hover,
.toast-close-button:focus {
color: var(--black-color);
text-decoration: none;
cursor: pointer;
opacity: 0.6;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60);
filter: alpha(opacity=60);
}
.toast-title {
color: var(--black-color);
padding: 10px 0px;
}
/* Modal */
.modal-dialog {
width: 450px;
}
.modal-content {
padding: 55px 20px 20px 20px;
background-image: url(../images/icon-warning.svg);
background-repeat: no-repeat;
background-position: top 10px left 10px;
}
.modal-header {
padding: 10px 0px 10px 0px;
border-bottom: none;
}
.modal-header .close {
margin-top: -40px;
}
.modal-header .modal-title {
font-weight: bold;
}
.modal-body {
padding: 10px 0px;
border-bottom: none;
}
.modal-body .bootbox-body {
font-size: 12px;
color: var(--text-bootbox);
}
.modal-footer {
padding: 10px 0px;
border-top: none;
display: flex;
}
.modal-footer .bootbox-cancel {
width: 100%;
}
.modal-footer .bootbox-accept {
width: 100%;
}
.bootbox-checkbox-list {
border: 0px;
}
/* Boxselector */
.boxselector_wrapper input[type='radio']:checked + label,
.box-selector-item input[type='radio']:checked + label {
background: var(--ui-blue-3) !important;
color: black !important;
border-radius: 8px;
border-color: var(--ui-blue-7);
padding: 15px;
box-shadow: none;
}
.boxselector_wrapper input[type='radio']:not(:disabled) + label,
.box-selector-item input[type='radio']:not(:disabled) + label {
background: var(--ui-gray-2);
color: var(--black-color) !important;
border-radius: 8px;
border-color: var(--ui-gray-5);
padding: 15px;
box-shadow: none;
}
.row.header {
background-color: var(--bg-body-color) !important;
margin-bottom: 5px !important;
}
/* Databatle Setting Menu */
.tableMenu {
border: 1px solid var(--border-bootbox);
border-radius: 8px;
}
[data-reach-menu-list],
[data-reach-menu-items] {
background: none;
}
.dropdown-menu {
border-radius: 8px;
}
.dropdown-menu .tableMenu {
border: 0px;
}
/* Myaccount Dropdown Menu */
.myaccount-dropdown {
color: var(--text-body-color);
font-size: 17px;
}
.myaccount-container {
margin-top: -25px;
}
.myaccount-icon {
padding-left: 8px;
}
.myaccount-link {
display: inline;
border: 0px;
background: none;
padding: 10px 0px;
}
/* Status Indicator Label Style */
.label {
border-radius: 8px !important;
}
.label-danger {
background-color: var(--ui-error-8);
}
.label-success {
background-color: var(--ui-success-7);
}
/* Feather Icon */
.feather {
height: 18px;
width: 18px;
position: relative;
top: 3px;
margin-right: 5px;
color: var(--text-body-color);
}

View File

@@ -1,355 +0,0 @@
{
"black": "#000000",
"white": "#ffffff",
"gray": {
"1": "#fcfcfd",
"2": "#f9fafb",
"3": "#f2f4f7",
"4": "#eaecf0",
"5": "#d0d5dd",
"6": "#98a2b3",
"7": "#667085",
"8": "#475467",
"9": "#344054",
"10": "#1d2939",
"11": "#101828"
},
"blue": {
"1": "#f5fbff",
"2": "#f0f9ff",
"3": "#e0f2fe",
"4": "#b9e6fe",
"5": "#7cd4fd",
"6": "#36bffa",
"7": "#0ba5ec",
"8": "#0086c9",
"9": "#026aa2",
"10": "#065986",
"11": "#0b4a6f"
},
"error": {
"1": "#fffbfa",
"2": "#fef3f2",
"3": "#fee4e2",
"4": "#fecdca",
"5": "#fda29b",
"6": "#f97066",
"7": "#f04438",
"8": "#d92d20",
"9": "#b42318",
"10": "#912018",
"11": "#7a271a"
},
"warning": {
"1": "#fffcf5",
"2": "#fffaeb",
"3": "#fef0c7",
"4": "#fedf89",
"5": "#fec84b",
"6": "#fdb022",
"7": "#f79009",
"8": "#dc6803",
"9": "#b54708",
"10": "#93370d",
"11": "#7a2e0e"
},
"success": {
"1": "#f6fef9",
"2": "#ecfdf3",
"3": "#d1fadf",
"4": "#a6f4c5",
"5": "#6ce9a6",
"6": "#32d583",
"7": "#12b76a",
"8": "#039855",
"9": "#027a48",
"10": "#05603a",
"11": "#054f31"
},
"gray-blue": {
"1": "#fcfcfd",
"2": "#f8f9fc",
"3": "#eaecf5",
"4": "#d5d9eb",
"5": "#b3b8db",
"6": "#717bbc",
"7": "#4e5ba6",
"8": "#3e4784",
"9": "#363f72",
"10": "#293056",
"11": "#293056"
},
"gray-cool": {
"1": "#fcfcfd",
"2": "#f9f9fb",
"3": "#eff1f5",
"4": "#dcdfea",
"5": "#b9c0d4",
"6": "#7d89b0",
"7": "#5d6b98",
"8": "#4a5578",
"9": "#404968",
"10": "#30374f",
"11": "#111322"
},
"gray-modern": {
"1": "#fcfcfd",
"2": "#f8fafc",
"3": "#eef2f6",
"4": "#e3e8ef",
"5": "#cdd5df",
"6": "#9aa4b2",
"7": "#697586",
"8": "#4b5565",
"9": "#364152",
"10": "#202939",
"11": "#121926"
},
"gray-neutral": {
"1": "#fcfcfd",
"2": "#f9fafb",
"3": "#f3f4f6",
"4": "#e5e7eb",
"5": "#d2d6db",
"6": "#9da4ae",
"7": "#6c737f",
"8": "#4d5761",
"9": "#384250",
"10": "#1f2a37",
"11": "#111927"
},
"gray-iron": {
"1": "#fcfcfc",
"2": "#fafafa",
"3": "#f4f4f5",
"4": "#e4e4e7",
"5": "#d1d1d6",
"6": "#d1d1d6",
"7": "#70707b",
"8": "#51525c",
"9": "#3f3f46",
"10": "#26272b",
"11": "#18181b"
},
"gray-true": {
"1": "#fcfcfc",
"2": "#fafafa",
"3": "#f5f5f5",
"4": "#e5e5e5",
"5": "#d6d6d6",
"6": "#a3a3a3",
"7": "#737373",
"8": "#525252",
"9": "#424242",
"10": "#292929",
"11": "#141414"
},
"gray-warm": {
"1": "#fdfdfc",
"2": "#fafaf9",
"3": "#f5f5f4",
"4": "#e7e5e4",
"5": "#d7d3d0",
"6": "#d7d3d0",
"7": "#79716b",
"8": "#57534e",
"9": "#44403c",
"10": "#292524",
"11": "#1c1917"
},
"moss": {
"1": "#fafdf7",
"2": "#f5fbee",
"3": "#e6f4d7",
"4": "#ceeab0",
"5": "#acdc79",
"6": "#86cb3c",
"7": "#669f2a",
"8": "#4f7a21",
"9": "#3f621a",
"10": "#335015",
"11": "#2b4212"
},
"green-light": {
"1": "#fafef5",
"2": "#f3fee7",
"3": "#e4fbcc",
"4": "#d0f8ab",
"5": "#a6ef67",
"6": "#85e13a",
"7": "#66c61c",
"8": "#4ca30d",
"9": "#3b7c0f",
"10": "#326212",
"11": "#2b5314"
},
"green": {
"1": "#f6fef9",
"2": "#edfcf2",
"3": "#d3f8df",
"4": "#aaf0c4",
"5": "#73e2a3",
"6": "#73e2a3",
"7": "#16b364",
"8": "#099250",
"9": "#087443",
"10": "#095c37",
"11": "#084c2e"
},
"teal": {
"1": "#f6fefc",
"2": "#f0fdf9",
"3": "#ccfbef",
"4": "#99f6e0",
"5": "#5fe9d0",
"6": "#2ed3b7",
"7": "#15b79e",
"8": "#0e9384",
"9": "#107569",
"10": "#125d56",
"11": "#134e48"
},
"cyan": {
"1": "#f5feff",
"2": "#ecfdff",
"3": "#cff9fe",
"4": "#a5f0fc",
"5": "#67e3f9",
"6": "#22ccee",
"7": "#06aed4",
"8": "#088ab2",
"9": "#0e7090",
"10": "#155b75",
"11": "#164c63"
},
"blue-dark": {
"1": "#f5f8ff",
"2": "#eff4ff",
"3": "#d1e0ff",
"4": "#b2ccff",
"5": "#84adff",
"6": "#528bff",
"7": "#2970ff",
"8": "#155eef",
"9": "#004eeb",
"10": "#0040c1",
"11": "#00359e"
},
"indigo": {
"1": "#f5f8ff",
"2": "#eef4ff",
"3": "#e0eaff",
"4": "#c7d7fe",
"5": "#a4bcfd",
"6": "#8098f9",
"7": "#8098f9",
"8": "#444ce7",
"9": "#3538cd",
"10": "#2d31a6",
"11": "#2d3282"
},
"violet": {
"1": "#fbfaff",
"2": "#f5f3ff",
"3": "#ece9fe",
"4": "#ddd6fe",
"5": "#c3b5fd",
"6": "#a48afb",
"7": "#875bf7",
"8": "#7839ee",
"9": "#6927da",
"10": "#5720b7",
"11": "#491c96"
},
"purple": {
"1": "#fafaff",
"2": "#f4f3ff",
"3": "#ebe9fe",
"4": "#d9d6fe",
"5": "#bdb4fe",
"6": "#9b8afb",
"7": "#7a5af8",
"8": "#6938ef",
"9": "#5925dc",
"10": "#4a1fb8",
"11": "#3e1c96"
},
"fuchsia": {
"1": "#fefaff",
"2": "#fdf4ff",
"3": "#fbe8ff",
"4": "#f6d0fe",
"5": "#eeaafd",
"6": "#e478fa",
"7": "#d444f1",
"8": "#ba24d5",
"9": "#9f1ab1",
"10": "#821890",
"11": "#6f1877"
},
"pink": {
"1": "#fef6fb",
"2": "#fdf2fa",
"3": "#fce7f6",
"4": "#fce7f6",
"5": "#faa7e0",
"6": "#f670c7",
"7": "#ee46bc",
"8": "#dd2590",
"9": "#c11574",
"10": "#9e165f",
"11": "#851651"
},
"rose": {
"1": "#fff5f6",
"2": "#fff1f3",
"3": "#ffe4e8",
"4": "#fecdd6",
"5": "#fea3b4",
"6": "#fd6f8e",
"7": "#f63d68",
"8": "#e31b54",
"9": "#c01048",
"10": "#a11043",
"11": "#89123e"
},
"orange-dark": {
"1": "#fff9f5",
"2": "#fff4ed",
"3": "#ffe6d5",
"4": "#ffd6ae",
"5": "#ff9c66",
"6": "#ff692e",
"7": "#ff4405",
"8": "#e62e05",
"9": "#bc1b06",
"10": "#97180c",
"11": "#771a0d"
},
"orange": {
"1": "#fefaf5",
"2": "#fef6ee",
"3": "#fdead7",
"4": "#f9dbaf",
"5": "#f7b27a",
"6": "#f38744",
"7": "#ef6820",
"8": "#e04f16",
"9": "#b93815",
"10": "#932f19",
"11": "#772917"
},
"yellow": {
"1": "#fefdf0",
"2": "#fefbe8",
"3": "#fef7c3",
"4": "#feee95",
"5": "#feee95",
"6": "#fac515",
"7": "#eaaa08",
"8": "#ca8504",
"9": "#a15c07",
"10": "#854a0e",
"11": "#713b12"
}
}

View File

@@ -1,19 +0,0 @@
import colors from './colors.json';
const element = document.createElement('style');
element.innerHTML = `:root {
${Object.entries(colors)
.map(([color, hex]) => {
if (typeof hex === 'string') {
return `--ui-${color}: ${hex}`;
}
return Object.entries(hex)
.map(([key, value]) => `--ui-${color}-${key}: ${value}`)
.join(';\n');
})
.join(';\n')}
}`;
document.head.prepend(element);

View File

@@ -15,12 +15,9 @@ import 'angular-multiselect/isteven-multi-select.css';
import 'spinkit/spinkit.min.css';
import '@reach/menu-button/styles.css';
import './colors';
import './rdash.css';
import './app.css';
import './theme.css';
import './vendor-override.css';
import '../fonts/nomad-icon.css';
import './bootstrap-override.css';

View File

@@ -4,6 +4,49 @@
width: 100%;
height: auto;
}
@media only screen and (min-width: 561px) {
#page-wrapper.open {
padding-left: 250px;
}
}
@media only screen and (max-width: 560px) {
#page-wrapper.open {
padding-left: 70px;
}
}
/**
* Hamburg Menu
* When the class of 'hamburg' is applied to the body tag of the document,
* the sidebar changes it's style to attempt to mimic a menu on a phone app,
* where the content is overlaying the content, rather than push it.
*/
@media only screen and (max-width: 560px) {
body.hamburg #page-wrapper {
padding-left: 0;
}
body.hamburg #page-wrapper:not(.open) #sidebar-wrapper {
position: absolute;
left: -100px;
}
body.hamburg #page-wrapper:not(.open) ul.sidebar .sidebar-title.separator {
display: none;
}
body.hamburg #page-wrapper.open #sidebar-wrapper {
position: fixed;
}
body.hamburg #page-wrapper.open #sidebar-wrapper ul.sidebar li.sidebar-main {
margin-left: 0px;
}
body.hamburg #sidebar-wrapper ul.sidebar li.sidebar-main,
body.hamburg .row.header .meta {
margin-left: 70px;
}
body.hamburg #sidebar-wrapper ul.sidebar li.sidebar-main,
body.hamburg #page-wrapper.open #sidebar-wrapper ul.sidebar li.sidebar-main {
transition: margin-left 0.4s ease 0s;
}
}
.loading {
width: 40px;
@@ -49,6 +92,33 @@
}
}
/* Fonts */
@font-face {
font-family: 'Montserrat';
src: url('../fonts/montserrat-regular-webfont.eot');
src: url('../fonts/montserrat-regular-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/montserrat-regular-webfont.woff') format('woff'),
url('../fonts/montserrat-regular-webfont.ttf') format('truetype'), url('../fonts/montserrat-regular-webfont.svg#montserratregular') format('svg');
font-weight: normal;
font-style: normal;
}
@media screen and (-webkit-min-device-pixel-ratio: 0) {
@font-face {
font-family: 'Montserrat';
src: url('../fonts/montserrat-regular-webfont.svg') format('svg');
}
select {
font-family: Arial, Helvetica, sans-serif;
}
}
/* Base */
html {
overflow-y: scroll;
}
body {
background: var(--bg-body-color);
font-family: 'Montserrat';
color: var(--text-body-color) !important;
}
.row {
margin-left: 0 !important;
margin-right: 0 !important;
@@ -59,7 +129,22 @@
.alerts-container .alert:last-child {
margin-bottom: 0;
}
#page-wrapper {
padding-left: 70px;
height: 100%;
}
#sidebar-wrapper {
margin-left: -150px;
left: -30px;
width: 250px;
position: fixed;
height: 100%;
z-index: 999;
}
#page-wrapper,
#sidebar-wrapper {
transition: all 0.4s ease 0s;
}
.green {
background: #23ae89 !important;
}
@@ -87,8 +172,9 @@ div.input-mask {
-moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
background: var(--bg-widget-color);
border: 1px solid var(--border-widget);
border-radius: 8px;
border: 1px solid transparent;
border-radius: 2px;
border-color: var(--border-widget-color);
}
.widget .widget-header .pagination,
.widget .widget-footer .pagination {
@@ -96,7 +182,9 @@ div.input-mask {
}
.widget .widget-header {
color: var(--text-widget-header-color);
background-color: var(--bg-widget-header-color);
padding: 10px 15px;
border-bottom: 1px solid var(--border-widget-color);
line-height: 30px;
}
.widget .widget-header i {
@@ -104,7 +192,6 @@ div.input-mask {
}
.widget .widget-body {
padding: 20px;
border-radius: 8px;
}
.widget .widget-body table thead {
background: var(--bg-widget-table-color);

View File

@@ -1,12 +1,13 @@
/* Color Variable */
:root {
--black-color: var(--ui-black);
--white-color: var(--ui-white);
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;
@@ -34,6 +35,7 @@
--grey-30: #444;
--grey-31: #868686;
--grey-32: #65798e;
--grey-34: #314252;
--grey-35: #546477;
--grey-36: #55637d;
--grey-37: #2d3e63;
@@ -51,12 +53,15 @@
--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;
--grey-61: rgb(231, 231, 231);
--blue-1: #219;
@@ -71,6 +76,7 @@
--blue-10: #61b6ff;
--blue-11: #3ea5ff;
--blue-12: #41a6ff;
--blue-13: #2361ae;
--blue-14: #357ebd;
--red-1: #a94442;
@@ -78,6 +84,7 @@
--red-3: #a11;
--red-4: #d9534f;
--red-5: #ff2727;
--red-6: #ff00e0;
--red-7: #f00;
--green-1: #164;
@@ -87,22 +94,25 @@
--orange-1: #e86925;
--BE-only: var(--orange-1);
}
/* Default Theme */
--bg-card-color: var(--white-color);
/* Default Theme */
: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(--ui-gray-5);
--bg-input-group-addon-color: var(--ui-gray-3);
--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(--ui-blue-3);
--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);
@@ -129,16 +139,10 @@
--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-tooltip-color: var(--ui-gray-11);
--bg-input-sm-color: var(--white-color);
--bg-service-datatable-thead: var(--grey-23);
--bg-app-datatable-thead: var(--grey-23);
--bg-inner-datatable-thead: var(--grey-23);
--bg-service-datatable-tbody: var(--grey-24);
--bg-app-datatable-tbody: var(--grey-24);
--bg-multiselect-color: var(--white-color);
--bg-daterangepicker-color: var(--white-color);
--bg-calendar-color: var(--white-color);
@@ -158,10 +162,6 @@
--bg-stepper-item-active: var(--white-color);
--bg-stepper-item-counter: var(--grey-61);
--bg-sortbutton-color: var(--white-color);
--bg-dashboard-item: var(--ui-blue-3);
--bg-searchbar: var(--ui-gray-2);
--bg-inputbox: var(--ui-gray-2);
--bg-dropdown-hover: var(--ui-gray-3);
--text-main-color: var(--grey-7);
--text-body-color: var(--grey-6);
@@ -193,21 +193,23 @@
--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(--ui-gray-3);
--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-tooltip-color: var(--white-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);
--text-bootbox: var(--ui-gray-7);
--border-color: var(--grey-42);
--border-widget-color: var(--grey-43);
@@ -242,10 +244,8 @@
--border-tooltip-color: var(--grey-47);
--border-modal: 0px;
--border-sortbutton: var(--grey-8);
--border-bootbox: var(--ui-gray-5);
--border-blocklist: var(--ui-gray-5);
--border-widget: var(--ui-gray-5);
--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);
@@ -265,13 +265,9 @@
--text-multiselect-item: var(--grey-30);
--bg-multiselect-helpercontainer: var(--white-color);
--text-input-textarea: var(--white-color);
--border-checkbox: var(--ui-gray-5);
--bg-checkbox: var(--white-color);
--border-searchbar: var(--ui-gray-5);
--bg-button-group: var(--white-color);
--border-button-group: var(--ui-gray-5);
--text-button-group: var(--ui-gray-9);
--bg-service-datatable-thead: var(--grey-23);
--bg-inner-datatable-thead: var(--grey-23);
--bg-service-datatable-tbody: var(--grey-24);
}
:root[theme='dark'] {
@@ -279,6 +275,7 @@
--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);
@@ -316,6 +313,7 @@
--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);
@@ -339,10 +337,6 @@
--bg-stepper-item-active: var(--grey-1);
--bg-stepper-item-counter: var(--grey-7);
--bg-sortbutton-color: var(--grey-1);
--bg-dashboard-item: var(--grey-3);
--bg-searchbar: var(--grey-1);
--bg-inputbox: var(--grey-2);
--bg-dropdown-hover: var(--grey-3);
--text-main-color: var(--white-color);
--text-body-color: var(--white-color);
@@ -374,13 +368,14 @@
--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(--ui-gray-3);
--text-pagination-span-color: var(--blue-2);
--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);
@@ -390,7 +385,6 @@
--text-input-autofill-color: var(--grey-8);
--text-button-hover-color: var(--white-color);
--text-small-select-color: var(--grey-7);
--text-bootbox: var(--white-color);
--border-color: var(--grey-3);
--border-widget-color: var(--grey-1);
@@ -414,7 +408,9 @@
--border-pagination-color: var(--grey-3);
--border-pagination-span-color: var(--grey-3);
--border-pagination-hover-color: var(--grey-3);
--border-boxselector-wrapper-hover: 3px solid var(--blue-8);
--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);
@@ -424,10 +420,8 @@
--border-tooltip-color: var(--grey-3);
--border-modal: 0px;
--border-sortbutton: var(--grey-3);
--border-bootbox: var(--ui-gray-9);
--border-blocklist: var(--ui-gray-9);
--border-widget: var(--ui-gray-9);
--hover-sidebar-color: var(--grey-3);
--blue-color: var(--blue-2);
--button-close-color: var(--white-color);
--button-opacity: 0.6;
@@ -445,13 +439,9 @@
--text-multiselect-item: var(--white-color);
--bg-multiselect-helpercontainer: var(--grey-1);
--text-input-textarea: var(--grey-1);
--border-checkbox: var(--ui-gray-5);
--bg-checkbox: var(--white-color);
--border-searchbar: var(--ui-gray-5);
--bg-button-group: var(--white-color);
--border-button-group: var(--ui-gray-5);
--text-button-group: var(--ui-gray-9);
--bg-service-datatable-thead: var(--grey-1);
--bg-inner-datatable-thead: var(--grey-1);
--bg-service-datatable-tbody: var(--grey-1);
}
:root[theme='highcontrast'] {
@@ -459,6 +449,7 @@
--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);
@@ -470,10 +461,11 @@
--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-3);
--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);
@@ -520,9 +512,6 @@
--bg-stepper-item-active: var(--black-color);
--bg-stepper-item-counter: var(--grey-3);
--bg-sortbutton-color: var(--grey-1);
--bg-inputbox: var(--black-color);
--bg-searchbar: var(--black-color);
--bg-dropdown-hover: var(--black-color);
--text-main-color: var(--white-color);
--text-body-color: var(--white-color);
@@ -551,6 +540,7 @@
--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);
@@ -564,8 +554,7 @@
--text-btn-default-color: var(--white-color);
--text-small-select-color: var(--white-color);
--text-multiselect-item-color: var(--white-color);
--text-pagination-span-color: var(--ui-gray-3);
--text-bootbox: var(--white-color);
--text-pagination-span-color: var(--blue-2);
--border-color: var(--grey-55);
--border-widget-color: var(--white-color);
@@ -595,10 +584,9 @@
--border-modal: 1px solid var(--white-color);
--border-blocklist-color: var(--white-color);
--border-sortbutton: var(--black-color);
--border-bootbox: var(--black-color);
--border-blocklist: var(--white-color);
--border-widget: var(--white-color);
--hover-sidebar-color: var(--blue-9);
--hover-sidebar-color: var(--black-color);
--shadow-box-color: none;
--shadow-boxselector-color: none;
@@ -617,11 +605,4 @@
--text-cm-meta-color: var(--white-color);
--text-cm-string-color: var(--red-7);
--text-progress-bar-color: var(--black-color);
--border-checkbox: var(--ui-gray-5);
--bg-checkbox: var(--white-color);
--border-searchbar: var(--ui-gray-5);
--bg-button-group: var(--white-color);
--border-button-group: var(--ui-gray-5);
--text-button-group: var(--ui-gray-9);
}

View File

@@ -1,7 +1,7 @@
/* Overide Vendor CSS */
.form-control {
background-color: var(--bg-main-color) !important;
border: 1px solid var(--border-form-control-color);
background-color: var(--bg-inputbox);
color: var(--text-form-control-color);
}
@@ -10,7 +10,7 @@
}
.table > thead > tr > th {
border-bottom: 1px solid var(--border-table-color);
border-bottom: 2px solid var(--border-table-color);
}
.table-hover > tbody > tr:hover {
@@ -243,10 +243,6 @@ json-tree .branch-preview {
.panel {
border: 1px solid var(--border-panel-color);
background-color: var(--bg-panel-body-color);
border-radius: 8px;
-webkit-box-shadow: 0 4px 4px rgba(0, 0, 0, 0.05);
-moz-box-shadow: 0 4px 4px rgba(0, 0, 0, 0.05);
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.05);
}
.theme-information .col-sm-12 {
@@ -385,10 +381,3 @@ fieldset[disabled] .btn {
.multiSelect.inlineBlock button {
margin: 0;
}
.nav-tabs > li.active > a {
border-top: 0px;
border-left: 0px;
border-right: 0px;
border-bottom: 3px solid red;
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +0,0 @@
<svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3" y="3" width="40" height="40" rx="20" fill="#FEE4E2"/>
<path d="M23 19.6667V23M23 26.3333H23.0083M31.3333 23C31.3333 27.6024 27.6024 31.3333 23 31.3333C18.3976 31.3333 14.6667 27.6024 14.6667 23C14.6667 18.3976 18.3976 14.6667 23 14.6667C27.6024 14.6667 31.3333 18.3976 31.3333 23Z" stroke="#D92D20" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="3" y="3" width="40" height="40" rx="20" stroke="#FEF3F2" stroke-width="6"/>
</svg>

Before

Width:  |  Height:  |  Size: 571 B

View File

@@ -1,5 +0,0 @@
<svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3" y="3" width="40" height="40" rx="20" fill="#D1FADF"/>
<path d="M31.3333 22.2333V23C31.3323 24.797 30.7504 26.5456 29.6744 27.9849C28.5985 29.4241 27.0861 30.4771 25.3628 30.9866C23.6395 31.4961 21.7977 31.4349 20.112 30.8122C18.4264 30.1894 16.9872 29.0384 16.0091 27.5309C15.031 26.0234 14.5665 24.2401 14.6847 22.4469C14.803 20.6538 15.4977 18.9469 16.6652 17.5809C17.8328 16.2148 19.4106 15.2628 21.1635 14.8668C22.9163 14.4708 24.7502 14.6519 26.3917 15.3833M31.3333 16.3333L23 24.675L20.5 22.175" stroke="#039855" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="3" y="3" width="40" height="40" rx="20" stroke="#ECFDF3" stroke-width="6"/>
</svg>

Before

Width:  |  Height:  |  Size: 791 B

View File

@@ -1,5 +0,0 @@
<svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3" y="3" width="40" height="40" rx="20" fill="#FEF0C7"/>
<path d="M22.9998 19.6667V23M22.9998 26.3333H23.0081M21.5748 15.3833L14.5165 27.1667C14.3709 27.4187 14.2939 27.7044 14.2931 27.9954C14.2923 28.2864 14.3677 28.5726 14.5118 28.8254C14.6559 29.0783 14.8637 29.2889 15.1146 29.4365C15.3654 29.5841 15.6505 29.6635 15.9415 29.6667H30.0581C30.3491 29.6635 30.6342 29.5841 30.885 29.4365C31.1359 29.2889 31.3437 29.0783 31.4878 28.8254C31.6319 28.5726 31.7073 28.2864 31.7065 27.9954C31.7057 27.7044 31.6287 27.4187 31.4831 27.1667L24.4248 15.3833C24.2762 15.1384 24.0671 14.9359 23.8175 14.7954C23.5679 14.6549 23.2863 14.581 22.9998 14.581C22.7134 14.581 22.4317 14.6549 22.1821 14.7954C21.9325 14.9359 21.7234 15.1384 21.5748 15.3833Z" stroke="#DC6803" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="3" y="3" width="40" height="40" rx="20" stroke="#FFFAEB" stroke-width="6"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -1,9 +1,5 @@
import { UserContext } from '@/portainer/hooks/useUser';
import { UserViewModel } from '@/portainer/models/user';
import { render, within } from '@/react-tools/test-utils';
import { TestSidebarProvider } from '../useSidebarState';
import { AzureSidebar } from './AzureSidebar';
test('dashboard items should render correctly', () => {
@@ -13,28 +9,26 @@ test('dashboard items should render correctly', () => {
expect(dashboardItem).toHaveTextContent('Dashboard');
const dashboardItemElements = within(dashboardItem);
expect(
dashboardItemElements.getByRole('img', { hidden: true })
).toBeVisible();
expect(dashboardItemElements.getByLabelText('itemIcon')).toBeVisible();
expect(dashboardItemElements.getByLabelText('itemIcon')).toHaveClass(
'fa-tachometer-alt',
'fa-fw'
);
const containerInstancesItem = getByLabelText(/Container Instances/i);
const containerInstancesItem = getByLabelText('ContainerInstances');
expect(containerInstancesItem).toBeVisible();
expect(containerInstancesItem).toHaveTextContent('Container instances');
const containerInstancesItemElements = within(containerInstancesItem);
expect(
containerInstancesItemElements.getByRole('img', { hidden: true })
containerInstancesItemElements.getByLabelText('itemIcon')
).toBeVisible();
expect(containerInstancesItemElements.getByLabelText('itemIcon')).toHaveClass(
'fa-cubes',
'fa-fw'
);
});
function renderComponent() {
const user = new UserViewModel({ Username: 'user' });
return render(
<UserContext.Provider value={{ user }}>
<TestSidebarProvider>
<AzureSidebar environmentId={1} />
</TestSidebarProvider>
</UserContext.Provider>
);
return render(<AzureSidebar environmentId={1} />);
}

View File

@@ -0,0 +1,36 @@
import { r2a } from '@/react-tools/react2angular';
import { SidebarMenuItem } from '@/portainer/components/sidebar/SidebarMenuItem';
import type { EnvironmentId } from '@/portainer/environments/types';
interface Props {
environmentId: EnvironmentId;
}
export function AzureSidebar({ environmentId }: Props) {
return (
<>
<SidebarMenuItem
path="azure.dashboard"
pathParams={{ endpointId: environmentId }}
iconClass="fa-tachometer-alt fa-fw"
className="sidebar-list"
itemName="Dashboard"
data-cy="azureSidebar-dashboard"
>
Dashboard
</SidebarMenuItem>
<SidebarMenuItem
path="azure.containerinstances"
pathParams={{ endpointId: environmentId }}
iconClass="fa-cubes fa-fw"
className="sidebar-list"
itemName="ContainerInstances"
data-cy="azureSidebar-containerInstances"
>
Container instances
</SidebarMenuItem>
</>
);
}
export const AzureSidebarAngular = r2a(AzureSidebar, ['environmentId']);

View File

@@ -0,0 +1 @@
export { AzureSidebar, AzureSidebarAngular } from './AzureSidebar';

View File

@@ -1,17 +1,16 @@
import { Field, Form, Formik } from 'formik';
import { useCurrentStateAndParams, useRouter } from '@uirouter/react';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input, Select } from '@/portainer/components/form-components/Input';
import { FormSectionTitle } from '@/portainer/components/form-components/FormSectionTitle';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { InputListError } from '@/portainer/components/form-components/InputList/InputList';
import { ContainerInstanceFormValues } from '@/azure/types';
import * as notifications from '@/portainer/services/notifications';
import { useUser } from '@/portainer/hooks/useUser';
import { AccessControlForm } from '@/portainer/access-control/AccessControlForm';
import { FormControl } from '@@/form-components/FormControl';
import { Input, Select } from '@@/form-components/Input';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { InputListError } from '@@/form-components/InputList/InputList';
import { validationSchema } from './CreateContainerInstanceForm.validation';
import { PortMapping, PortsMappingField } from './PortsMappingField';
import { useLoadFormState } from './useLoadFormState';

View File

@@ -1,11 +1,11 @@
import { ButtonSelector } from '@@/form-components/ButtonSelector/ButtonSelector';
import { FormError } from '@@/form-components/FormError';
import { InputGroup } from '@@/form-components/InputGroup';
import { InputList } from '@@/form-components/InputList';
import { ButtonSelector } from '@/portainer/components/form-components/ButtonSelector/ButtonSelector';
import { FormError } from '@/portainer/components/form-components/FormError';
import { InputGroup } from '@/portainer/components/form-components/InputGroup';
import { InputList } from '@/portainer/components/form-components/InputList';
import {
InputListError,
ItemProps,
} from '@@/form-components/InputList/InputList';
} from '@/portainer/components/form-components/InputList/InputList';
import styles from './PortsMappingField.module.css';

View File

@@ -4,14 +4,13 @@ import { useEffect } from 'react';
import * as notifications from '@/portainer/services/notifications';
import PortainerError from '@/portainer/error';
import { EnvironmentId } from '@/portainer/environments/types';
import { Option } from '@/portainer/components/form-components/Input/Select';
import { getResourceGroups } from '@/azure/services/resource-groups.service';
import { getSubscriptions } from '@/azure/services/subscription.service';
import { getContainerInstanceProvider } from '@/azure/services/provider.service';
import { ContainerInstanceFormValues, Subscription } from '@/azure/types';
import { parseAccessControlFormData } from '@/portainer/access-control/utils';
import { Option } from '@@/form-components/Input/Select';
import {
getSubscriptionLocations,
getSubscriptionResourceGroups,

View File

@@ -1,8 +1,7 @@
import { PageHeader } from '@/portainer/components/PageHeader';
import { Widget, WidgetBody } from '@/portainer/components/widget';
import { r2a } from '@/react-tools/react2angular';
import { PageHeader } from '@@/PageHeader';
import { Widget, WidgetBody } from '@@/Widget';
import { CreateContainerInstanceForm } from './CreateContainerInstanceForm';
export function CreateContainerInstanceView() {

View File

@@ -24,9 +24,7 @@ test('dashboard items should render correctly', async () => {
const subscriptionElements = within(subscriptionsItem);
expect(subscriptionElements.getByLabelText('value')).toBeVisible();
expect(subscriptionElements.getByRole('img', { hidden: true })).toHaveClass(
'fa-th-list'
);
expect(subscriptionElements.getByLabelText('icon')).toHaveClass('fa-th-list');
expect(subscriptionElements.getByLabelText('resourceType')).toHaveTextContent(
'Subscriptions'
);
@@ -36,7 +34,7 @@ test('dashboard items should render correctly', async () => {
const resourceGroupElements = within(resourceGroupsItem);
expect(resourceGroupElements.getByLabelText('value')).toBeVisible();
expect(resourceGroupElements.getByRole('img', { hidden: true })).toHaveClass(
expect(resourceGroupElements.getByLabelText('icon')).toHaveClass(
'fa-th-list'
);
expect(

View File

@@ -1,13 +1,12 @@
import { useEffect } from 'react';
import { useEnvironmentId } from '@/portainer/hooks/useEnvironmentId';
import { PageHeader } from '@/portainer/components/PageHeader';
import { DashboardItem } from '@/portainer/components/Dashboard/DashboardItem';
import { error as notifyError } from '@/portainer/services/notifications';
import PortainerError from '@/portainer/error';
import { r2a } from '@/react-tools/react2angular';
import { DashboardItem } from '@@/DashboardItem';
import { PageHeader } from '@@/PageHeader';
import { useResourceGroups, useSubscriptions } from '../queries';
export function DashboardView() {

View File

@@ -1,5 +1,6 @@
import angular from 'angular';
import { AzureSidebarAngular } from './AzureSidebar/AzureSidebar';
import { DashboardViewAngular } from './Dashboard/DashboardView';
import { containerInstancesModule } from './ContainerInstances';
import { reactModule } from './react';
@@ -83,4 +84,5 @@ angular
$stateRegistryProvider.register(dashboard);
},
])
.component('azureSidebar', AzureSidebarAngular)
.component('dashboardView', DashboardViewAngular);

View File

@@ -3,8 +3,11 @@ import angular from 'angular';
import { EnvironmentStatus } from '@/portainer/environments/types';
import { reactModule } from './react';
import containersModule from './containers';
import { componentsModule } from './components';
import { networksModule } from './networks';
angular.module('portainer.docker', ['portainer.app', reactModule]).config([
angular.module('portainer.docker', ['portainer.app', containersModule, componentsModule, networksModule, reactModule]).config([
'$stateRegistryProvider',
function ($stateRegistryProvider) {
'use strict';

View File

@@ -1,10 +1,9 @@
import clsx from 'clsx';
import { DockerContainerStatus } from '@/react/docker/containers/types';
import { Authorized } from '@/portainer/hooks/useUser';
import { Link } from '@/portainer/components/Link';
import { react2angular } from '@/react-tools/react2angular';
import { Link } from '@@/Link';
import { DockerContainerStatus } from '@/docker/containers/types';
import styles from './ContainerQuickActions.module.css';

View File

@@ -3,35 +3,9 @@
<rd-widget-body classes="no-padding">
<div class="toolBar">
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px"></i> {{ $ctrl.titleText }} </div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
auto-focus
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="actionBar" ng-if="!$ctrl.offlineMode" authorization="DockerNetworkDelete, DockerNetworkCreate">
<button
type="button"
class="btn btn-sm btn-danger"
authorization="DockerNetworkDelete"
ng-disabled="$ctrl.state.selectedItemCount === 0"
ng-click="$ctrl.removeAction($ctrl.state.selectedItems)"
>
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button>
<button type="button" class="btn btn-sm btn-primary" ui-sref="docker.networks.new" authorization="DockerNetworkCreate">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add network
</button>
</div>
<div class="settings">
<span class="setting" ng-class="{ 'setting-active': $ctrl.settings.open }" uib-dropdown dropdown-append-to-body auto-close="disabled" is-open="$ctrl.settings.open">
<span uib-dropdown-toggle aria-label="Settings"><i class="fa fa-cog" aria-hidden="true"></i></span>
<span uib-dropdown-toggle><i class="fa fa-cog" aria-hidden="true"></i> Settings</span>
<div class="dropdown-menu dropdown-menu-right" uib-dropdown-menu>
<div class="tableMenu">
<div class="menuHeader"> Table settings </div>
@@ -64,6 +38,32 @@
</span>
</div>
</div>
<div class="actionBar" ng-if="!$ctrl.offlineMode" authorization="DockerNetworkDelete, DockerNetworkCreate">
<button
type="button"
class="btn btn-sm btn-danger"
authorization="DockerNetworkDelete"
ng-disabled="$ctrl.state.selectedItemCount === 0"
ng-click="$ctrl.removeAction($ctrl.state.selectedItems)"
>
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button>
<button type="button" class="btn btn-sm btn-primary" ui-sref="docker.networks.new" authorization="DockerNetworkCreate">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add network
</button>
</div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
auto-focus
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="table-responsive">
<table class="table table-hover nowrap-cells">
<thead>

View File

@@ -0,0 +1,186 @@
<sidebar-menu-item
path="docker.dashboard"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-tachometer-alt fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-dashboard"
title="Dashboard"
>
Dashboard
</sidebar-menu-item>
<sidebar-menu
ng-if="!$ctrl.offlineMode"
label="App Templates"
icon-class="fa-rocket fa-fw"
path="docker.templates"
path-params="{ endpointId: $ctrl.endpointId }"
is-sidebar-open="$ctrl.isSidebarOpen"
children-paths="[]"
>
<sidebar-menu-item
path="docker.templates.custom"
path-params="{ endpointId: $ctrl.endpointId }"
class-name="sidebar-sublist"
data-cy="dockerSidebar-customTemplates"
title="Custom Templates"
>
Custom Templates
</sidebar-menu-item>
</sidebar-menu>
<sidebar-menu-item
ng-if="$ctrl.showStacks"
path="docker.stacks"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-th-list fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-stacks"
title="Stacks"
>
Stacks
</sidebar-menu-item>
<sidebar-menu-item
ng-if="$ctrl.swarmManagement"
path="docker.services"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-list-alt fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-services"
title="Services"
>
Services
</sidebar-menu-item>
<sidebar-menu-item
path="docker.containers"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-cubes fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-containers"
title="Containers"
>
Containers
</sidebar-menu-item>
<sidebar-menu-item
path="docker.images"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-clone fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-images"
title="Images"
>
Images
</sidebar-menu-item>
<sidebar-menu-item
path="docker.networks"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-sitemap fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-networks"
title="Networks"
>
Networks
</sidebar-menu-item>
<sidebar-menu-item
path="docker.volumes"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-hdd fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-volumes"
title="Volumes"
>
Volumes
</sidebar-menu-item>
<sidebar-menu-item
ng-if="$ctrl.endpointApiVersion >= 1.3 && $ctrl.swarmManagement"
path="docker.configs"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-file-code fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-configs"
title="Configs"
>
Configs
</sidebar-menu-item>
<sidebar-menu-item
ng-if="$ctrl.endpointApiVersion >= 1.25 && $ctrl.swarmManagement"
path="docker.secrets"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-user-secret fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-secrets"
title="Secrets"
>
Secrets
</sidebar-menu-item>
<sidebar-menu-item
ng-if="$ctrl.standaloneManagement && $ctrl.adminAccess && !$ctrl.offlineMode"
path="docker.events"
path-params="{ endpointId: $ctrl.endpointId }"
icon-class="fa-history fa-fw"
class-name="sidebar-list"
data-cy="dockerSidebar-events"
title="Events"
>
Events
</sidebar-menu-item>
<sidebar-menu
ng-if="$ctrl.standaloneManagement"
label="Host"
icon-class="fa-th fa-fw"
path="docker.host"
path-params="{ endpointId: $ctrl.endpointId }"
is-sidebar-open="$ctrl.isSidebarOpen"
children-paths="['docker.registries', 'docker.registries.access', 'docker.featuresConfiguration']"
>
<sidebar-menu-item
ng-if="$ctrl.adminAccess"
authorization="PortainerEndpointUpdateSettings"
path="docker.featuresConfiguration"
path-params="{ endpointId: $ctrl.endpointId }"
class-name="sidebar-sublist"
data-cy="dockerSidebar-setup"
title="Setup"
>
Setup
</sidebar-menu-item>
<sidebar-menu-item path="docker.registries" path-params="{ endpointId: $ctrl.endpointId }" class-name="sidebar-sublist" data-cy="dockerSidebar-registries" title="Registries">
Registries
</sidebar-menu-item>
</sidebar-menu>
<sidebar-menu
ng-if="$ctrl.swarmManagement"
label="Swarm"
icon-class="fa-object-group fa-fw"
path="docker.swarm"
path-params="{ endpointId: $ctrl.endpointId }"
is-sidebar-open="$ctrl.isSidebarOpen"
children-paths="['docker.registries', 'docker.registries.access', 'docker.featuresConfiguration']"
>
<sidebar-menu-item
ng-if="$ctrl.adminAccess"
authorization="PortainerEndpointUpdateSettings"
path="docker.featuresConfiguration"
path-params="{ endpointId: $ctrl.endpointId }"
class-name="sidebar-sublist"
data-cy="swarmSidebar-setup"
title="Setup"
>
Setup
</sidebar-menu-item>
<sidebar-menu-item path="docker.registries" path-params="{ endpointId: $ctrl.endpointId }" class-name="sidebar-sublist" data-cy="swarmSidebar-registries" title="Registries">
Registries
</sidebar-menu-item>
</sidebar-menu>

View File

@@ -0,0 +1,15 @@
angular.module('portainer.docker').component('dockerSidebar', {
templateUrl: './docker-sidebar.html',
bindings: {
isSidebarOpen: '<',
endpointApiVersion: '<',
swarmManagement: '<',
standaloneManagement: '<',
adminAccess: '<',
offlineMode: '<',
currentRouteName: '<',
endpointId: '<',
showStacks: '<',
},
});

View File

@@ -0,0 +1,7 @@
import angular from 'angular';
import { ContainerQuickActionsAngular } from './container-quick-actions';
export const componentsModule = angular
.module('portainer.docker.components', [])
.component('containerQuickActions', ContainerQuickActionsAngular).name;

View File

@@ -9,18 +9,11 @@ import {
} from 'react-table';
import { useRowSelectColumn } from '@lineup-lite/hooks';
import { useDebounce } from '@/portainer/hooks/useDebounce';
import type {
ContainersTableSettings,
DockerContainer,
} from '@/react/docker/containers/types';
import { useEnvironment } from '@/portainer/environments/useEnvironment';
import { PaginationControls } from '@@/PaginationControls';
import { PaginationControls } from '@/portainer/components/pagination-controls';
import {
QuickActionsSettings,
buildAction,
} from '@@/datatables/QuickActionsSettings';
} from '@/portainer/components/datatables/components/QuickActionsSettings';
import {
Table,
TableActions,
@@ -30,16 +23,25 @@ import {
TableSettingsMenu,
TableTitle,
TableTitleActions,
} from '@@/datatables';
import { multiple } from '@@/datatables/filter-types';
import { useTableSettings } from '@@/datatables/useTableSettings';
import { ColumnVisibilityMenu } from '@@/datatables/ColumnVisibilityMenu';
import { useRepeater } from '@@/datatables/useRepeater';
import { SearchBar, useSearchBarState } from '@@/datatables/SearchBar';
import { useRowSelect } from '@@/datatables/useRowSelect';
import { Checkbox } from '@@/form-components/Checkbox';
import { TableFooter } from '@@/datatables/TableFooter';
import { SelectedRowsCount } from '@@/datatables/SelectedRowsCount';
} from '@/portainer/components/datatables/components';
import { multiple } from '@/portainer/components/datatables/components/filter-types';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import { ColumnVisibilityMenu } from '@/portainer/components/datatables/components/ColumnVisibilityMenu';
import { useRepeater } from '@/portainer/components/datatables/components/useRepeater';
import { useDebounce } from '@/portainer/hooks/useDebounce';
import {
SearchBar,
useSearchBarState,
} from '@/portainer/components/datatables/components/SearchBar';
import type {
ContainersTableSettings,
DockerContainer,
} from '@/docker/containers/types';
import { useEnvironment } from '@/portainer/environments/useEnvironment';
import { useRowSelect } from '@/portainer/components/datatables/components/useRowSelect';
import { Checkbox } from '@/portainer/components/form-components/Checkbox';
import { TableFooter } from '@/portainer/components/datatables/components/TableFooter';
import { SelectedRowsCount } from '@/portainer/components/datatables/components/SelectedRowsCount';
import { ContainersDatatableActions } from './ContainersDatatableActions';
import { ContainersDatatableSettings } from './ContainersDatatableSettings';
@@ -141,14 +143,6 @@ export function ContainersDatatable({
return (
<TableContainer>
<TableTitle icon="fa-cubes" label="Containers">
<SearchBar value={searchBarValue} onChange={handleSearchBarChange} />
<TableActions>
<ContainersDatatableActions
selectedItems={selectedFlatRows.map((row) => row.original)}
isAddActionVisible={isAddActionVisible}
endpointId={endpoint.Id}
/>
</TableActions>
<TableTitleActions>
<ColumnVisibilityMenu<DockerContainer>
columns={columnsToHide}
@@ -164,6 +158,16 @@ export function ContainersDatatable({
</TableTitleActions>
</TableTitle>
<TableActions>
<ContainersDatatableActions
selectedItems={selectedFlatRows.map((row) => row.original)}
isAddActionVisible={isAddActionVisible}
endpointId={endpoint.Id}
/>
</TableActions>
<SearchBar value={searchBarValue} onChange={handleSearchBarChange} />
<Table
className={tableProps.className}
role={tableProps.role}

View File

@@ -2,12 +2,10 @@ import { useRouter } from '@uirouter/react';
import * as notifications from '@/portainer/services/notifications';
import { useAuthorizations, Authorized } from '@/portainer/hooks/useUser';
import { Link } from '@/portainer/components/Link';
import { confirmContainerDeletion } from '@/portainer/services/modal.service/prompt';
import { setPortainerAgentTargetHeader } from '@/portainer/services/http-request.helper';
import type {
ContainerId,
DockerContainer,
} from '@/react/docker/containers/types';
import type { ContainerId, DockerContainer } from '@/docker/containers/types';
import {
killContainer,
pauseContainer,
@@ -16,11 +14,9 @@ import {
resumeContainer,
startContainer,
stopContainer,
} from '@/react/docker/containers/containers.service';
} from '@/docker/containers/containers.service';
import type { EnvironmentId } from '@/portainer/environments/types';
import { Link } from '@@/Link';
import { ButtonGroup, Button } from '@@/buttons';
import { ButtonGroup, Button } from '@/portainer/components/Button';
type ContainerServiceAction = (
endpointId: EnvironmentId,
@@ -71,7 +67,7 @@ export function ContainersDatatableActions({
<ButtonGroup>
<Authorized authorizations="DockerContainerStart">
<Button
color="light"
color="success"
onClick={() => onStartClick(selectedItems)}
disabled={selectedItemCount === 0 || !hasStoppedItemsSelected}
>
@@ -82,7 +78,7 @@ export function ContainersDatatableActions({
<Authorized authorizations="DockerContainerStop">
<Button
color="light"
color="danger"
onClick={() => onStopClick(selectedItems)}
disabled={selectedItemCount === 0 || !hasRunningItemsSelected}
>
@@ -93,7 +89,7 @@ export function ContainersDatatableActions({
<Authorized authorizations="DockerContainerKill">
<Button
color="light"
color="danger"
onClick={() => onKillClick(selectedItems)}
disabled={selectedItemCount === 0}
>
@@ -104,7 +100,6 @@ export function ContainersDatatableActions({
<Authorized authorizations="DockerContainerRestart">
<Button
color="light"
onClick={() => onRestartClick(selectedItems)}
disabled={selectedItemCount === 0}
>
@@ -115,7 +110,6 @@ export function ContainersDatatableActions({
<Authorized authorizations="DockerContainerPause">
<Button
color="light"
onClick={() => onPauseClick(selectedItems)}
disabled={selectedItemCount === 0 || !hasRunningItemsSelected}
>
@@ -126,7 +120,6 @@ export function ContainersDatatableActions({
<Authorized authorizations="DockerContainerUnpause">
<Button
color="light"
onClick={() => onResumeClick(selectedItems)}
disabled={selectedItemCount === 0 || !hasPausedItemsSelected}
>
@@ -137,7 +130,7 @@ export function ContainersDatatableActions({
<Authorized authorizations="DockerContainerDelete">
<Button
color="dangerlight"
color="danger"
onClick={() => onRemoveClick(selectedItems)}
disabled={selectedItemCount === 0}
>

View File

@@ -1,8 +1,8 @@
import { react2angular } from '@/react-tools/react2angular';
import { EnvironmentProvider } from '@/portainer/environments/useEnvironment';
import { TableSettingsProvider } from '@/portainer/components/datatables/components/useTableSettings';
import type { Environment } from '@/portainer/environments/types';
import { TableSettingsProvider } from '@@/datatables/useTableSettings';
import {
ContainersDatatable,
ContainerTableProps,
@@ -35,3 +35,15 @@ export function ContainersDatatableContainer({
</EnvironmentProvider>
);
}
export const ContainersDatatableAngular = react2angular(
ContainersDatatableContainer,
[
'endpoint',
'isAddActionVisible',
'dataset',
'onRefresh',
'isHostColumnVisible',
'tableKey',
]
);

View File

@@ -1,8 +1,7 @@
import type { ContainersTableSettings } from '@/react/docker/containers/types';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { useTableSettings } from '@@/datatables/useTableSettings';
import { Checkbox } from '@@/form-components/Checkbox';
import { TableSettingsMenuAutoRefresh } from '@/portainer/components/datatables/components/TableSettingsMenuAutoRefresh';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import { Checkbox } from '@/portainer/components/form-components/Checkbox';
import type { ContainersTableSettings } from '@/docker/containers/types';
interface Props {
isRefreshVisible: boolean;

View File

@@ -1,7 +1,7 @@
import { Column } from 'react-table';
import { isoDateFromTimestamp } from '@/portainer/filters/filters';
import type { DockerContainer } from '@/react/docker/containers/types';
import type { DockerContainer } from '@/docker/containers/types';
export const created: Column<DockerContainer> = {
Header: 'Created',

View File

@@ -1,6 +1,6 @@
import { Column } from 'react-table';
import type { DockerContainer } from '@/react/docker/containers/types';
import type { DockerContainer } from '@/docker/containers/types';
export const host: Column<DockerContainer> = {
Header: 'Host',

View File

@@ -3,7 +3,7 @@ import { useSref } from '@uirouter/react';
import { useEnvironment } from '@/portainer/environments/useEnvironment';
import { EnvironmentStatus } from '@/portainer/environments/types';
import type { DockerContainer } from '@/react/docker/containers/types';
import type { DockerContainer } from '@/docker/containers/types';
export const image: Column<DockerContainer> = {
Header: 'Image',

View File

@@ -1,6 +1,6 @@
import { Column } from 'react-table';
import type { DockerContainer } from '@/react/docker/containers/types';
import type { DockerContainer } from '@/docker/containers/types';
export const ip: Column<DockerContainer> = {
Header: 'IP Address',

View File

@@ -3,12 +3,11 @@ import _ from 'lodash';
import { useSref } from '@uirouter/react';
import { useEnvironment } from '@/portainer/environments/useEnvironment';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import type {
ContainersTableSettings,
DockerContainer,
} from '@/react/docker/containers/types';
import { useTableSettings } from '@@/datatables/useTableSettings';
} from '@/docker/containers/types';
export const name: Column<DockerContainer> = {
Header: 'Name',

View File

@@ -2,7 +2,7 @@ import { Column } from 'react-table';
import clsx from 'clsx';
import { ownershipIcon } from '@/portainer/filters/filters';
import type { DockerContainer } from '@/react/docker/containers/types';
import type { DockerContainer } from '@/docker/containers/types';
import { ResourceControlOwnership } from '@/portainer/access-control/types';
export const ownership: Column<DockerContainer> = {

View File

@@ -2,7 +2,7 @@ import { Column } from 'react-table';
import _ from 'lodash';
import { useEnvironment } from '@/portainer/environments/useEnvironment';
import type { DockerContainer, Port } from '@/react/docker/containers/types';
import type { DockerContainer, Port } from '@/docker/containers/types';
export const ports: Column<DockerContainer> = {
Header: 'Published Ports',

View File

@@ -1,16 +1,15 @@
import { CellProps, Column } from 'react-table';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import { useEnvironment } from '@/portainer/environments/useEnvironment';
import { useAuthorizations } from '@/portainer/hooks/useUser';
import { ContainerQuickActions } from '@/react/docker/containers/components/ContainerQuickActions/ContainerQuickActions';
import { ContainerQuickActions } from '@/docker/components/container-quick-actions/ContainerQuickActions';
import type {
ContainersTableSettings,
DockerContainer,
} from '@/react/docker/containers/types';
} from '@/docker/containers/types';
import { EnvironmentStatus } from '@/portainer/environments/types';
import { useTableSettings } from '@@/datatables/useTableSettings';
export const quickActions: Column<DockerContainer> = {
Header: 'Quick Actions',
id: 'actions',

View File

@@ -1,6 +1,6 @@
import { Column } from 'react-table';
import type { DockerContainer } from '@/react/docker/containers/types';
import type { DockerContainer } from '@/docker/containers/types';
export const stack: Column<DockerContainer> = {
Header: 'Stack',

View File

@@ -2,12 +2,11 @@ import { Column } from 'react-table';
import clsx from 'clsx';
import _ from 'lodash';
import { DefaultFilter } from '@/portainer/components/datatables/components/Filter';
import type {
DockerContainer,
DockerContainerStatus,
} from '@/react/docker/containers/types';
import { DefaultFilter } from '@@/datatables/Filter';
} from '@/docker/containers/types';
export const state: Column<DockerContainer> = {
Header: 'State',

View File

@@ -1,9 +1,9 @@
import { EnvironmentId } from '@/portainer/environments/types';
import PortainerError from '@/portainer/error';
import axios from '@/portainer/services/axios';
import { genericHandler } from '@/docker/rest/response/handlers';
import { NetworkId } from '../networks/types';
import { genericHandler } from '../rest/response/handlers';
import { ContainerId, DockerContainer } from './types';

View File

@@ -0,0 +1,7 @@
import angular from 'angular';
import { ContainersDatatableAngular } from './components/ContainersDatatable/ContainersDatatableContainer';
export default angular
.module('portainer.docker.containers', [])
.component('containersDatatable', ContainersDatatableAngular).name;

View File

@@ -1,12 +1,11 @@
import { ResourceControlViewModel } from '@/portainer/access-control/models/ResourceControlViewModel';
import {
PaginationTableSettings,
RefreshableTableSettings,
SettableColumnsTableSettings,
SettableQuickActionsTableSettings,
SortableTableSettings,
} from '@@/datatables/types';
} from '@/portainer/components/datatables/types';
export type DockerContainerStatus =
| 'paused'

View File

@@ -1,10 +1,9 @@
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import { DetailsTable } from '@/portainer/components/DetailsTable';
import { Button } from '@/portainer/components/Button';
import { Authorized } from '@/portainer/hooks/useUser';
import { EnvironmentId } from '@/portainer/environments/types';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { DetailsTable } from '@@/DetailsTable';
import { Button } from '@@/buttons';
import { Link } from '@@/Link';
import { Link } from '@/portainer/components/Link';
import { NetworkContainer, NetworkId } from '../types';
import { useDisconnectContainer } from '../queries';
@@ -66,7 +65,7 @@ export function NetworkContainersTable({
<td>
<Authorized authorizations="DockerNetworkDisconnect">
<Button
data-cy={`networkDetails-disconnect${container.Name}`}
dataCy={`networkDetails-disconnect${container.Name}`}
size="xsmall"
color="danger"
onClick={() => {

View File

@@ -1,12 +1,11 @@
import { Fragment } from 'react';
import DockerNetworkHelper from 'Docker/helpers/networkHelper';
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import { DetailsTable } from '@/portainer/components/DetailsTable';
import { Button } from '@/portainer/components/Button';
import { Authorized } from '@/portainer/hooks/useUser';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { DetailsTable } from '@@/DetailsTable';
import { Button } from '@@/buttons';
import { isSystemNetwork } from '../network.helper';
import { DockerNetwork, IPConfig } from '../types';
@@ -41,7 +40,7 @@ export function NetworkDetailsTable({
{allowRemoveNetwork && (
<Authorized authorizations="DockerNetworkDelete">
<Button
data-cy="networkDetails-deleteNetwork"
dataCy="networkDetails-deleteNetwork"
size="xsmall"
color="danger"
onClick={() => onRemoveNetworkClicked()}

View File

@@ -4,24 +4,23 @@ import { useQueryClient } from 'react-query';
import _ from 'lodash';
import { useEnvironmentId } from '@/portainer/hooks/useEnvironmentId';
import { PageHeader } from '@/portainer/components/PageHeader';
import { confirmDeletionAsync } from '@/portainer/services/modal.service/confirm';
import { AccessControlPanel } from '@/portainer/access-control/AccessControlPanel/AccessControlPanel';
import { ResourceControlType } from '@/portainer/access-control/types';
import { DockerContainer } from '@/react/docker/containers/types';
import { DockerContainer } from '@/docker/containers/types';
import { ResourceControlViewModel } from '@/portainer/access-control/models/ResourceControlViewModel';
import { PageHeader } from '@@/PageHeader';
import { useNetwork, useDeleteNetwork } from '../queries';
import { isSystemNetwork } from '../network.helper';
import { DockerNetwork, NetworkContainer } from '../types';
import { useContainers } from '../../containers/queries';
import { DockerNetwork, NetworkContainer } from '../types';
import { NetworkDetailsTable } from './NetworkDetailsTable';
import { NetworkOptionsTable } from './NetworkOptionsTable';
import { NetworkContainersTable } from './NetworkContainersTable';
export function ItemView() {
export function NetworkDetailsView() {
const router = useRouter();
const queryClient = useQueryClient();

View File

@@ -1,5 +1,5 @@
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { DetailsTable } from '@@/DetailsTable';
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import { DetailsTable } from '@/portainer/components/DetailsTable';
import { NetworkOptions } from '../types';

View File

@@ -0,0 +1,5 @@
import { react2angular } from '@/react-tools/react2angular';
import { NetworkDetailsView } from './NetworkDetailsView';
export const NetworkDetailsViewAngular = react2angular(NetworkDetailsView, []);

View File

@@ -0,0 +1,7 @@
import angular from 'angular';
import { NetworkDetailsViewAngular } from './edit';
export const networksModule = angular
.module('portainer.docker.networks', [])
.component('networkDetailsView', NetworkDetailsViewAngular).name;

View File

@@ -1,7 +1,8 @@
import { ContainerId } from '@/react/docker/containers/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { EnvironmentId } from '@/portainer/environments/types';
import { ContainerId } from '../containers/types';
import { NetworkId, DockerNetwork } from './types';
type NetworkAction = 'connect' | 'disconnect' | 'create';

View File

@@ -5,7 +5,8 @@ import {
error as notifyError,
success as notifySuccess,
} from '@/portainer/services/notifications';
import { ContainerId } from '@/react/docker/containers/types';
import { ContainerId } from '../containers/types';
import {
getNetwork,

View File

@@ -1,29 +1,6 @@
import angular from 'angular';
import { r2a } from '@/react-tools/react2angular';
import { ContainersDatatableContainer } from '@/react/docker/containers/ListView/ContainersDatatable/ContainersDatatableContainer';
import { ContainerQuickActions } from '@/react/docker/containers/components/ContainerQuickActions';
export const componentsModule = angular
.module('portainer.docker.react.components', [])
.component(
'containersDatatable',
r2a(ContainersDatatableContainer, [
'endpoint',
'isAddActionVisible',
'dataset',
'onRefresh',
'isHostColumnVisible',
'tableKey',
])
)
.component(
'containerQuickActions',
r2a(ContainerQuickActions, [
'containerId',
'nodeName',
'state',
'status',
'taskId',
])
).name;
export const componentsModule = angular.module(
'portainer.docker.react.components',
[]
).name;

View File

@@ -1,8 +1,6 @@
import angular from 'angular';
import { ItemView } from '@/react/docker/networks/ItemView';
import { r2a } from '@/react-tools/react2angular';
export const viewsModule = angular
.module('portainer.docker.react.views', [])
.component('networkDetailsView', r2a(ItemView, [])).name;
export const viewsModule = angular.module(
'portainer.docker.react.views',
[]
).name;

View File

@@ -8,7 +8,7 @@ import {
resumeContainer,
startContainer,
stopContainer,
} from '@/react/docker/containers/containers.service';
} from '@/docker/containers/containers.service';
import { ContainerDetailsViewModel, ContainerStatsViewModel, ContainerViewModel } from '../models/container';
angular.module('portainer.docker').factory('ContainerService', ContainerServiceFactory);

View File

@@ -1,76 +0,0 @@
import { useQuery } from 'react-query';
import { EnvironmentId } from '@/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
export interface VersionResponse {
ApiVersion: string;
}
export async function getVersion(environmentId: EnvironmentId) {
try {
const { data } = await axios.get<VersionResponse>(
buildUrl(environmentId, 'version')
);
return data;
} catch (err) {
throw parseAxiosError(err as Error, 'Unable to retrieve version');
}
}
export interface InfoResponse {
Swarm?: {
NodeID: string;
ControlAvailable: boolean;
};
}
export async function getInfo(environmentId: EnvironmentId) {
try {
const { data } = await axios.get<InfoResponse>(
buildUrl(environmentId, 'info')
);
return data;
} catch (err) {
throw parseAxiosError(err as Error, 'Unable to retrieve version');
}
}
function buildUrl(
environmentId: EnvironmentId,
action: string,
subAction = ''
) {
let url = `/endpoints/${environmentId}/docker/${action}`;
if (subAction) {
url += `/${subAction}`;
}
return url;
}
export function useInfo<TSelect = InfoResponse>(
environmentId: EnvironmentId,
select?: (info: InfoResponse) => TSelect
) {
return useQuery(
['environment', environmentId, 'docker', 'info'],
() => getInfo(environmentId),
{
select,
}
);
}
export function useVersion<TSelect = VersionResponse>(
environmentId: EnvironmentId,
select?: (info: VersionResponse) => TSelect
) {
return useQuery(
['environment', environmentId, 'docker', 'version'],
() => getVersion(environmentId),
{
select,
}
);
}

View File

@@ -13,7 +13,6 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
'HttpRequestHelper',
'LocalStorage',
'CONSOLE_COMMANDS_LABEL_PREFIX',
'SidebarService',
function (
$scope,
$state,
@@ -25,8 +24,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
ExecService,
HttpRequestHelper,
LocalStorage,
CONSOLE_COMMANDS_LABEL_PREFIX,
SidebarService
CONSOLE_COMMANDS_LABEL_PREFIX
) {
var socket, term;
@@ -191,7 +189,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
$scope.$apply();
};
$scope.$watch(SidebarService.isSidebarOpen, function () {
$scope.$watch('toggle', function () {
setTimeout(resizefun, 400);
});

View File

@@ -14,29 +14,29 @@
<rd-widget-header icon="fa-cogs" title-text="Actions"></rd-widget-header>
<rd-widget-body classes="padding">
<div class="btn-group" role="group" aria-label="...">
<button authorization="DockerContainerStart" class="btn btn-light btn-sm" ng-click="start()" ng-disabled="container.State.Running || container.IsPortainer"
<button authorization="DockerContainerStart" class="btn btn-success btn-sm" ng-click="start()" ng-disabled="container.State.Running || container.IsPortainer"
><i class="fa fa-play space-right" aria-hidden="true"></i>Start</button
>
<button authorization="DockerContainerStop" class="btn btn-light btn-sm" ng-click="stop()" ng-disabled="!container.State.Running || container.IsPortainer"
<button authorization="DockerContainerStop" class="btn btn-danger btn-sm" ng-click="stop()" ng-disabled="!container.State.Running || container.IsPortainer"
><i class="fa fa-stop space-right" aria-hidden="true"></i>Stop</button
>
<button authorization="DockerContainerKill" class="btn btn-light btn-sm" ng-click="kill()" ng-disabled="!container.State.Running || container.IsPortainer"
<button authorization="DockerContainerKill" class="btn btn-danger btn-sm" ng-click="kill()" ng-disabled="!container.State.Running || container.IsPortainer"
><i class="fa fa-bomb space-right" aria-hidden="true"></i>Kill</button
>
<button authorization="DockerContainerRestart" class="btn btn-light btn-sm" ng-click="restart()" ng-disabled="!container.State.Running || container.IsPortainer"
<button authorization="DockerContainerRestart" class="btn btn-primary btn-sm" ng-click="restart()" ng-disabled="!container.State.Running || container.IsPortainer"
><i class="fa fa-sync space-right" aria-hidden="true"></i>Restart</button
>
<button
authorization="DockerContainerPause"
class="btn btn-light btn-sm"
class="btn btn-primary btn-sm"
ng-click="pause()"
ng-disabled="!container.State.Running || container.State.Paused || container.IsPortainer"
><i class="fa fa-pause space-right" aria-hidden="true"></i>Pause</button
>
<button authorization="DockerContainerUnpause" class="btn btn-light btn-sm" ng-click="unpause()" ng-disabled="!container.State.Paused || container.IsPortainer"
<button authorization="DockerContainerUnpause" class="btn btn-primary btn-sm" ng-click="unpause()" ng-disabled="!container.State.Paused || container.IsPortainer"
><i class="fa fa-play space-right" aria-hidden="true"></i>Resume</button
>
<button authorization="DockerContainerDelete" class="btn btn-dangerlight btn-sm" ng-click="confirmRemove()" ng-disabled="container.IsPortainer"
<button authorization="DockerContainerDelete" class="btn btn-danger btn-sm" ng-click="confirmRemove()" ng-disabled="container.IsPortainer"
><i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove</button
>
</div>
@@ -51,7 +51,7 @@
<span ng-hide="state.recreateContainerInProgress"><i class="fa fa-sync space-right" aria-hidden="true"></i>Recreate</span>
<span ng-show="state.recreateContainerInProgress">Recreation in progress...</span>
</button>
<a class="btn btn-light btn-sm" type="button" ui-sref="docker.containers.new({ from: container.Id, nodeName: nodeName })" ng-disabled="container.IsPortainer"
<a class="btn btn-primary btn-sm" type="button" ui-sref="docker.containers.new({ from: container.Id, nodeName: nodeName })" ng-disabled="container.IsPortainer"
><i class="fa fa-copy space-right" aria-hidden="true"></i>Duplicate/Edit</a
>
</div>

View File

@@ -372,8 +372,7 @@ angular.module('portainer.docker').controller('ContainerController', [
}
$scope.recreate = function () {
const cannotPullImage = !$scope.container.Config.Image || $scope.container.Config.Image.toLowerCase().startsWith('sha256');
ModalService.confirmContainerRecreation(cannotPullImage, function (result) {
ModalService.confirmContainerRecreation(function (result) {
if (!result) {
return;
}

View File

@@ -27,13 +27,6 @@ function BuildImageController($scope, $async, $window, ModalService, BuildServic
$scope.state.isEditorDirty = false;
});
$scope.checkName = function (name) {
const parts = name.split('/');
const repository = parts[parts.length - 1];
const repositoryRegExp = RegExp('^[a-z0-9-_]{2,255}(:[A-Za-z0-9-_.]{1,128})?$');
return repositoryRegExp.test(repository);
};
$scope.addImageName = function () {
$scope.formValues.ImageNames.push({ Name: '' });
};
@@ -99,16 +92,13 @@ function BuildImageController($scope, $async, $window, ModalService, BuildServic
}
$scope.validImageNames = function () {
if ($scope.formValues.ImageNames.length == 0) {
return false;
}
for (var i = 0; i < $scope.formValues.ImageNames.length; i++) {
var item = $scope.formValues.ImageNames[i];
if (!$scope.checkName(item.Name)) {
return false;
if (item.Name !== '') {
return true;
}
}
return true;
return false;
};
$scope.editorUpdate = function (cm) {

View File

@@ -47,7 +47,7 @@
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="item.Name" placeholder="e.g. my-image:my-tag" auto-focus />
<span class="input-group-addon"
><i ng-class="{ true: 'fa fa-check green-icon', false: 'fa fa-times red-icon' }[checkName(item.Name)]" aria-hidden="true"></i
><i ng-class="{ true: 'fa fa-check green-icon', false: 'fa fa-times red-icon' }[item.Name !== '']" aria-hidden="true"></i
></span>
</div>
<!-- !name-input -->

View File

@@ -1,14 +1,18 @@
import { usePagination, useTable } from 'react-table';
import {
Table,
TableContainer,
TableHeaderRow,
TableRow,
} from '@/portainer/components/datatables/components';
import { InnerDatatable } from '@/portainer/components/datatables/components/InnerDatatable';
import { Device } from '@/portainer/hostmanagement/open-amt/model';
import { useAMTDevices } from '@/edge/EdgeDevices/EdgeDevicesView/AMTDevicesDatatable/useAMTDevices';
import { RowProvider } from '@/edge/EdgeDevices/EdgeDevicesView/AMTDevicesDatatable/columns/RowContext';
import { EnvironmentId } from '@/portainer/environments/types';
import PortainerError from '@/portainer/error';
import { InnerDatatable } from '@@/datatables/InnerDatatable';
import { Table, TableContainer, TableHeaderRow, TableRow } from '@@/datatables';
import { useColumns } from './columns';
export interface AMTDevicesTableProps {

View File

@@ -4,12 +4,11 @@ import { MenuItem, MenuLink } from '@reach/menu-button';
import { useQueryClient } from 'react-query';
import { Device } from '@/portainer/hostmanagement/open-amt/model';
import { ActionsMenu } from '@/portainer/components/datatables/components/ActionsMenu';
import { confirmAsync } from '@/portainer/services/modal.service/confirm';
import { executeDeviceAction } from '@/portainer/hostmanagement/open-amt/open-amt.service';
import * as notifications from '@/portainer/services/notifications';
import { ActionsMenu } from '@@/datatables/ActionsMenu';
import { ActionsMenuTitle } from '@@/datatables/ActionsMenuTitle';
import { ActionsMenuTitle } from '@/portainer/components/datatables/components/ActionsMenuTitle';
import { useRowContext } from './RowContext';

View File

@@ -3,10 +3,7 @@ import { useRowSelectColumn } from '@lineup-lite/hooks';
import _ from 'lodash';
import { Environment } from '@/portainer/environments/types';
import { AMTDevicesDatatable } from '@/edge/EdgeDevices/EdgeDevicesView/AMTDevicesDatatable/AMTDevicesDatatable';
import { EnvironmentGroup } from '@/portainer/environment-groups/types';
import { PaginationControls } from '@@/PaginationControls';
import { PaginationControls } from '@/portainer/components/pagination-controls';
import {
Table,
TableActions,
@@ -16,15 +13,17 @@ import {
TableSettingsMenu,
TableTitle,
TableTitleActions,
} from '@@/datatables';
import { multiple } from '@@/datatables/filter-types';
import { useTableSettings } from '@@/datatables/useTableSettings';
import { ColumnVisibilityMenu } from '@@/datatables/ColumnVisibilityMenu';
import { SearchBar } from '@@/datatables/SearchBar';
import { useRowSelect } from '@@/datatables/useRowSelect';
import { TableFooter } from '@@/datatables/TableFooter';
import { SelectedRowsCount } from '@@/datatables/SelectedRowsCount';
import { TextTip } from '@@/Tip/TextTip';
} from '@/portainer/components/datatables/components';
import { multiple } from '@/portainer/components/datatables/components/filter-types';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import { ColumnVisibilityMenu } from '@/portainer/components/datatables/components/ColumnVisibilityMenu';
import { SearchBar } from '@/portainer/components/datatables/components/SearchBar';
import { useRowSelect } from '@/portainer/components/datatables/components/useRowSelect';
import { TableFooter } from '@/portainer/components/datatables/components/TableFooter';
import { SelectedRowsCount } from '@/portainer/components/datatables/components/SelectedRowsCount';
import { AMTDevicesDatatable } from '@/edge/EdgeDevices/EdgeDevicesView/AMTDevicesDatatable/AMTDevicesDatatable';
import { TextTip } from '@/portainer/components/Tip/TextTip';
import { EnvironmentGroup } from '@/portainer/environment-groups/types';
import { EdgeDevicesDatatableActions } from './EdgeDevicesDatatableActions';
import { EdgeDevicesDatatableSettings } from './EdgeDevicesDatatableSettings';

View File

@@ -1,14 +1,13 @@
import { useRouter } from '@uirouter/react';
import type { Environment } from '@/portainer/environments/types';
import { Button } from '@/portainer/components/Button';
import { confirmAsync } from '@/portainer/services/modal.service/confirm';
import { promptAsync } from '@/portainer/services/modal.service/prompt';
import * as notifications from '@/portainer/services/notifications';
import { activateDevice } from '@/portainer/hostmanagement/open-amt/open-amt.service';
import { deleteEndpoint } from '@/portainer/environments/environment.service';
import { Button } from '@@/buttons';
import { Link } from '@@/Link';
import { Link } from '@/portainer/components/Link';
interface Props {
selectedItems: Environment[];

View File

@@ -1,14 +1,13 @@
import { useState } from 'react';
import { useEnvironmentList } from '@/portainer/environments/queries/useEnvironmentList';
import { Environment } from '@/portainer/environments/types';
import { useDebounce } from '@/portainer/hooks/useDebounce';
import { useSearchBarState } from '@@/datatables/SearchBar';
import {
TableSettingsProvider,
useTableSettings,
} from '@@/datatables/useTableSettings';
} from '@/portainer/components/datatables/components/useTableSettings';
import { useEnvironmentList } from '@/portainer/environments/queries/useEnvironmentList';
import { Environment } from '@/portainer/environments/types';
import { useSearchBarState } from '@/portainer/components/datatables/components/SearchBar';
import { useDebounce } from '@/portainer/hooks/useDebounce';
import {
EdgeDevicesDatatable,

View File

@@ -1,5 +1,5 @@
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { useTableSettings } from '@@/datatables/useTableSettings';
import { TableSettingsMenuAutoRefresh } from '@/portainer/components/datatables/components/TableSettingsMenuAutoRefresh';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import { EdgeDeviceTableSettings } from './types';

View File

@@ -3,12 +3,11 @@ import { MenuItem, MenuLink } from '@reach/menu-button';
import { useRouter, useSref } from '@uirouter/react';
import { Environment } from '@/portainer/environments/types';
import { ActionsMenu } from '@/portainer/components/datatables/components/ActionsMenu';
import { snapshotEndpoint } from '@/portainer/environments/environment.service';
import * as notifications from '@/portainer/services/notifications';
import { getRoute } from '@/portainer/environments/utils';
import { ActionsMenu } from '@@/datatables/ActionsMenu';
export const actions: Column<Environment> = {
Header: 'Actions',
accessor: () => 'actions',

View File

@@ -1,8 +1,7 @@
import { Column } from 'react-table';
import { Environment } from '@/portainer/environments/types';
import { DefaultFilter } from '@@/datatables/Filter';
import { DefaultFilter } from '@/portainer/components/datatables/components/Filter';
import { useRowContext } from './RowContext';

View File

@@ -1,9 +1,8 @@
import { CellProps, Column } from 'react-table';
import { Environment } from '@/portainer/environments/types';
import { Link } from '@@/Link';
import { ExpandingCell } from '@@/datatables/ExpandingCell';
import { Link } from '@/portainer/components/Link';
import { ExpandingCell } from '@/portainer/components/datatables/components/ExpandingCell';
import { useRowContext } from './RowContext';

View File

@@ -3,7 +3,7 @@ import {
RefreshableTableSettings,
SettableColumnsTableSettings,
SortableTableSettings,
} from '@@/datatables/types';
} from '@/portainer/components/datatables/types';
export interface Pagination {
pageLimit: number;

View File

@@ -1,11 +1,10 @@
import { useState } from 'react';
import { PageHeader } from '@/portainer/components/PageHeader';
import { useSettings } from '@/portainer/settings/queries';
import { useGroups } from '@/portainer/environment-groups/queries';
import { r2a } from '@/react-tools/react2angular';
import { PageHeader } from '@@/PageHeader';
import { ViewLoading } from '@@/ViewLoading';
import { ViewLoading } from '@/portainer/components/ViewLoading';
import { EdgeDevicesDatatableContainer } from './EdgeDevicesDatatable/EdgeDevicesDatatableContainer';

View File

@@ -8,16 +8,18 @@ import {
} from 'react-table';
import { useRowSelectColumn } from '@lineup-lite/hooks';
import { Button } from '@/portainer/components/Button';
import { Table } from '@/portainer/components/datatables/components';
import {
SearchBar,
useSearchBarState,
} from '@/portainer/components/datatables/components/SearchBar';
import { SelectedRowsCount } from '@/portainer/components/datatables/components/SelectedRowsCount';
import { PaginationControls } from '@/portainer/components/pagination-controls';
import { Environment } from '@/portainer/environments/types';
import { useTableSettings } from '@/portainer/components/datatables/components/useTableSettings';
import { notifySuccess } from '@/portainer/services/notifications';
import { Button } from '@@/buttons';
import { Table } from '@@/datatables';
import { SearchBar, useSearchBarState } from '@@/datatables/SearchBar';
import { SelectedRowsCount } from '@@/datatables/SelectedRowsCount';
import { PaginationControls } from '@@/PaginationControls';
import { useTableSettings } from '@@/datatables/useTableSettings';
import { useAssociateDeviceMutation } from '../queries';
import { TableSettings } from './types';

View File

@@ -1,7 +1,7 @@
import {
PaginationTableSettings,
SortableTableSettings,
} from '@@/datatables/types';
} from '@/portainer/components/datatables/types';
export interface TableSettings
extends SortableTableSettings,

View File

@@ -1,12 +1,11 @@
import { useRouter } from '@uirouter/react';
import { TableSettingsProvider } from '@/portainer/components/datatables/components/useTableSettings';
import { PageHeader } from '@/portainer/components/PageHeader';
import { useEnvironmentList } from '@/portainer/environments/queries/useEnvironmentList';
import { r2a } from '@/react-tools/react2angular';
import { InformationPanel } from '@@/InformationPanel';
import { TextTip } from '@@/Tip/TextTip';
import { TableSettingsProvider } from '@@/datatables/useTableSettings';
import { PageHeader } from '@@/PageHeader';
import { InformationPanel } from '@/portainer/components/InformationPanel';
import { TextTip } from '@/portainer/components/Tip/TextTip';
import { DataTable } from './Datatable/Datatable';
import { TableSettings } from './Datatable/types';

View File

@@ -1,11 +1,10 @@
import { useEffect, useState } from 'react';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Select } from '@/portainer/components/form-components/Input';
import { useSettings } from '@/portainer/settings/queries';
import { r2a } from '@/react-tools/react2angular';
import { FormControl } from '@@/form-components/FormControl';
import { Select } from '@@/form-components/Input';
interface Props {
value: number;
onChange(value: number): void;

View File

@@ -7,11 +7,7 @@
<rd-header-content>Edge Jobs</rd-header-content>
</rd-header>
<information-panel title-text="Information">
<span class="small">
<p class="text-muted">Edge Jobs requires Docker Standalone and a cron implementation that reads jobs from <code>/etc/cron.d</code></p>
</span>
</information-panel>
<beta-panel></beta-panel>
<div class="row">
<div class="col-sm-12">

22
app/global.d.ts vendored
View File

@@ -5,13 +5,6 @@ declare module '*.png' {
export default '' as string;
}
type SvgrComponent = React.StatelessComponent<React.SVGAttributes<SVGElement>>;
declare module '*.svg?c' {
const value: SvgrComponent;
export default value;
}
declare module '*.css';
declare module '@open-amt-cloud-toolkit/ui-toolkit-react/reactjs/src/kvm.bundle';
@@ -27,18 +20,5 @@ declare module 'axios-progress-bar' {
}
interface Window {
/**
* will be true if portainer is run as a Docker Desktop Extension
*/
ddExtension?: boolean;
}
declare module 'process' {
global {
namespace NodeJS {
interface ProcessEnv {
PORTAINER_EDITION: 'BE' | 'CE';
}
}
}
ddExtension: boolean;
}

Some files were not shown because too many files have changed in this diff Show More