diff --git a/app/assets/css/icon.css b/app/assets/css/icon.css index 7eac5903c..aafe80cc1 100644 --- a/app/assets/css/icon.css +++ b/app/assets/css/icon.css @@ -99,6 +99,9 @@ pr-icon { } .icon-nested-gray { + display: flex; + justify-content: center; + align-items: center; height: 30px; width: 30px; padding: 5px; @@ -109,6 +112,9 @@ pr-icon { } .icon-nested-blue { + display: flex; + justify-content: center; + align-items: center; height: 30px; width: 30px; padding: 5px; diff --git a/app/assets/css/rdash.css b/app/assets/css/rdash.css index 157982744..cb41c9fed 100644 --- a/app/assets/css/rdash.css +++ b/app/assets/css/rdash.css @@ -96,7 +96,7 @@ div.input-mask { } .widget .widget-header { color: var(--text-widget-header-color); - padding: 10px 15px; + padding: 20px 20px 10px 20px; line-height: 30px; font-weight: 500; } diff --git a/app/assets/css/vendor-override.css b/app/assets/css/vendor-override.css index 747653c1b..66ee9a1f3 100644 --- a/app/assets/css/vendor-override.css +++ b/app/assets/css/vendor-override.css @@ -234,6 +234,27 @@ json-tree .branch-preview { background-color: var(--bg-progress-color); } +.ui-select-search, +.ui-select-toggle { + height: 30px; + min-width: 260px; + padding: 4px 12px; +} + +.ui-select-toggle { + justify-content: flex-start !important; +} + +.ui-select-match-text { + display: flex; + flex-direction: row-reverse; + align-items: center; +} + +.ui-select-match-text > a { + verical-align: middle; +} + .ui-select-bootstrap .ui-select-choices-row > span { color: var(--text-ui-select-color); } diff --git a/app/assets/ico/flask.svg b/app/assets/ico/flask.svg index 3083c8f9a..4971b5886 100644 --- a/app/assets/ico/flask.svg +++ b/app/assets/ico/flask.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/app/assets/ico/vendor/helm.svg b/app/assets/ico/vendor/helm.svg new file mode 100644 index 000000000..fbc279f8f --- /dev/null +++ b/app/assets/ico/vendor/helm.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/kubernetes/components/helm/helm-templates/helm-add-repository/helm-add-repository.html b/app/kubernetes/components/helm/helm-templates/helm-add-repository/helm-add-repository.html index 09aa76313..f3aa788ae 100644 --- a/app/kubernetes/components/helm/helm-templates/helm-add-repository/helm-add-repository.html +++ b/app/kubernetes/components/helm/helm-templates/helm-add-repository/helm-add-repository.html @@ -1,5 +1,10 @@ - + + + + Additional repositories + + @@ -7,7 +12,7 @@ Add a Helm repository. All Helm charts in the repository will be added to the list. - + - + - A valid URL beginning with http(s) is required. + A valid URL beginning with http(s) is required. - - - Helm repo already exists. + + + + Helm repo already exists. + @@ -39,7 +48,7 @@ - + - + - - + + @@ -18,8 +25,8 @@ {{ $ctrl.model.name }} - - + + Helm diff --git a/app/kubernetes/components/helm/helm-templates/helm-templates-list/helm-templates-list.html b/app/kubernetes/components/helm/helm-templates/helm-templates-list/helm-templates-list.html index 32794e5f4..fd0f036d7 100644 --- a/app/kubernetes/components/helm/helm-templates/helm-templates-list/helm-templates-list.html +++ b/app/kubernetes/components/helm/helm-templates/helm-templates-list/helm-templates-list.html @@ -1,37 +1,37 @@ - - {{ $ctrl.titleText }} - - - - - - - - - {{ $select.selected }} - - - {{ category }} - - - + + + + {{ $ctrl.titleText }} - - - - + + + + + + + + + + + {{ $select.selected }} + + + {{ category }} + + + diff --git a/app/kubernetes/components/helm/helm-templates/helm-templates.controller.js b/app/kubernetes/components/helm/helm-templates/helm-templates.controller.js index cb5b3e35f..9558b596e 100644 --- a/app/kubernetes/components/helm/helm-templates/helm-templates.controller.js +++ b/app/kubernetes/components/helm/helm-templates/helm-templates.controller.js @@ -83,7 +83,7 @@ export default class HelmTemplatesController { } async selectHelmChart(chart) { - this.$anchorScroll('view-top'); + window.scrollTo(0, 0); this.state.showCustomValues = false; this.state.chart = chart; await this.getHelmValues(); diff --git a/app/kubernetes/components/helm/helm-templates/helm-templates.html b/app/kubernetes/components/helm/helm-templates/helm-templates.html index eddf76c2c..05bfdd988 100644 --- a/app/kubernetes/components/helm/helm-templates/helm-templates.html +++ b/app/kubernetes/components/helm/helm-templates/helm-templates.html @@ -2,14 +2,19 @@ - - - This is a first version for Helm charts, for more information see this blog post. - - - + + + This is a first version for Helm charts, for more information see this blog post. + + The Global Helm Repository is not configured. - Configure Global Helm Repository in Settings + Configure Global Helm Repository in Settings. @@ -18,7 +23,16 @@ - + + + {{ $ctrl.state.chart.name }} + @@ -26,7 +40,7 @@ Description - + @@ -46,17 +60,16 @@ > - - - + + You do not have access to any namespace. Contact your administrator to get access to a namespace. - - Name + + Name - + - This field is required. - - This field must consist of lower case alphanumeric characters or '-', start with an alphabetic - character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123'). + + + + This field is required. + + + + This field must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', + or 'abc-123'). @@ -83,35 +101,44 @@ - - Show custom values - - Loading values.yaml... - - Hide custom values - + + + Show custom values + + + + Loading values.yaml... + + + + Hide custom values + - Web editor - - - You can get more information about Helm values file format in the - official documentation. - - - + on-change="($ctrl.editorUpdate)" + yml="true" + placeholder="# Define or paste the content of your values yaml file here" + > + + You can get more information about Helm values file format in the + official documentation. + + @@ -124,7 +151,7 @@ - - Information - - - This is a first version for Helm charts, for more information see this - blog post. - - - - + + + + Release + + + + + This is a first version for Helm charts, for more information see this + blog post. + + - Name - + Name + {{ $ctrl.state.release.name }} - Chart - + Chart + {{ $ctrl.state.release.chart }} - App version - + App version + {{ $ctrl.state.release.app_version }} diff --git a/app/portainer/react/components/index.ts b/app/portainer/react/components/index.ts index ac7076003..c34faebd4 100644 --- a/app/portainer/react/components/index.ts +++ b/app/portainer/react/components/index.ts @@ -14,6 +14,7 @@ import { Tooltip } from '@@/Tip/Tooltip'; import { TableColumnHeaderAngular } from '@@/datatables/TableHeaderCell'; import { DashboardItem } from '@@/DashboardItem'; import { SearchBar } from '@@/datatables/SearchBar'; +import { FallbackImage } from '@@/FallbackImage'; import { fileUploadField } from './file-upload-field'; import { switchField } from './switch-field'; @@ -50,6 +51,19 @@ export const componentsModule = angular 'pageHeader', r2a(PageHeader, ['title', 'breadcrumbs', 'loading', 'onReload', 'reload']) ) + .component( + 'fallbackImage', + r2a(FallbackImage, [ + 'src', + 'fallbackIcon', + 'alt', + 'size', + 'className', + 'fallbackMode', + 'fallbackClassName', + 'feather', + ]) + ) .component( 'prIcon', react2angular(Icon, ['className', 'feather', 'icon', 'mode', 'size']) diff --git a/app/react/components/FallbackImage.tsx b/app/react/components/FallbackImage.tsx new file mode 100644 index 000000000..1e11c294d --- /dev/null +++ b/app/react/components/FallbackImage.tsx @@ -0,0 +1,58 @@ +import clsx from 'clsx'; +import { useEffect, useState } from 'react'; + +import { Icon, IconMode, IconSize } from './Icon'; + +interface Props { + // props for the image to load + src: string; // a link to an external image + fallbackIcon: string; + alt?: string; + size?: IconSize; + className?: string; + // additional fallback icon props + fallbackMode?: IconMode; + fallbackClassName?: string; + feather?: boolean; +} + +export function FallbackImage({ + src, + fallbackIcon, + alt, + size, + className, + fallbackMode, + fallbackClassName, + feather, +}: Props) { + const [error, setError] = useState(false); + + const classes = clsx(className, { [`icon-${size}`]: size }); + + useEffect(() => { + setError(false); + }, [src]); + + if (!error) { + return ( + setError(true)} + /> + ); + } + + // fallback icon if there is an error loading the image + return ( + + ); +} diff --git a/app/react/components/Icon.tsx b/app/react/components/Icon.tsx index 18b9bfae2..407582d55 100644 --- a/app/react/components/Icon.tsx +++ b/app/react/components/Icon.tsx @@ -10,23 +10,27 @@ export interface IconProps { featherIcon?: boolean; } +export type IconMode = + | 'alt' + | 'primary' + | 'primary-alt' + | 'secondary' + | 'secondary-alt' + | 'warning' + | 'warning-alt' + | 'danger' + | 'danger-alt' + | 'success' + | 'success-alt'; + +export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; + interface Props { icon: ReactNode | ComponentType<{ size?: string | number }>; feather?: boolean; className?: string; - size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; - mode?: - | 'alt' - | 'primary' - | 'primary-alt' - | 'secondary' - | 'secondary-alt' - | 'warning' - | 'warning-alt' - | 'danger' - | 'danger-alt' - | 'success' - | 'success-alt'; + size?: IconSize; + mode?: IconMode; } export function Icon({ icon, feather, className, mode, size }: Props) { diff --git a/app/react/components/Svg.tsx b/app/react/components/Svg.tsx index a04989432..5f0138a1e 100644 --- a/app/react/components/Svg.tsx +++ b/app/react/components/Svg.tsx @@ -59,6 +59,7 @@ import gitlab from '@/assets/ico/vendor/gitlab.svg?c'; import google from '@/assets/ico/vendor/google.svg?c'; import googlecloud from '@/assets/ico/vendor/googlecloud.svg?c'; import kubernetes from '@/assets/ico/vendor/kubernetes.svg?c'; +import helm from '@/assets/ico/vendor/helm.svg?c'; import linode from '@/assets/ico/vendor/linode.svg?c'; import microsoft from '@/assets/ico/vendor/microsoft.svg?c'; import nomad from '@/assets/ico/vendor/nomad.svg?c'; @@ -66,6 +67,8 @@ import openldap from '@/assets/ico/vendor/openldap.svg?c'; import proget from '@/assets/ico/vendor/proget.svg?c'; import quay from '@/assets/ico/vendor/quay.svg?c'; +const placeholder = Placeholder; + export const SvgIcons = { automode, darkmode, @@ -96,6 +99,7 @@ export const SvgIcons = { memory, objectgroup, palette, + placeholder, plug, restore, restorewindow, @@ -124,6 +128,7 @@ export const SvgIcons = { google, googlecloud, kubernetes, + helm, linode, microsoft, nomad, diff --git a/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx b/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx index ff8ac7d1a..22819b284 100644 --- a/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx +++ b/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx @@ -1,7 +1,8 @@ -import { Box, Edit, Layers, Loader, Lock, Server } from 'react-feather'; +import { Box, Edit, Layers, Lock, Server } from 'react-feather'; import { EnvironmentId } from '@/portainer/environments/types'; import { Authorized } from '@/portainer/hooks/useUser'; +import Helm from '@/assets/ico/vendor/helm.svg?c'; import { DashboardLink } from '../items/DashboardLink'; import { SidebarItem } from '../SidebarItem'; @@ -54,7 +55,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
A valid URL beginning with http(s) is required.
Helm repo already exists.
- - This is a first version for Helm charts, for more information see this blog post. -
- +
+ + This is a first version for Helm charts, for more information see this blog post.
+ The Global Helm Repository is not configured. - Configure Global Helm Repository in Settings + Configure Global Helm Repository in Settings.
This field is required.
- This field must consist of lower case alphanumeric characters or '-', start with an alphabetic - character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123'). +
+ + This field is required. +
+ + This field must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', + or 'abc-123').
- - This is a first version for Helm charts, for more information see this - blog post. -