From d484a0eb6493746d266990c676cd19f0bb656a4c Mon Sep 17 00:00:00 2001 From: Chaim Lev-Ari Date: Tue, 22 Nov 2022 15:00:55 +0200 Subject: [PATCH] fix(docker): remove word break in details [EE-4481] (#7996) --- app/docker/filters/filters.js | 9 +- app/docker/filters/utils.ts | 8 ++ app/docker/react/components/index.ts | 4 + .../views/containers/edit/container.html | 35 +------- app/docker/views/images/edit/image.html | 54 +----------- .../components/DetailsTable/DetailsRow.tsx | 22 ++++- .../containers/ItemView/HealthStatus.tsx | 54 ++++++++++++ app/react/docker/containers/types/response.ts | 7 +- .../images/ItemView/DockerfileDetails.tsx | 83 +++++++++++++++++++ 9 files changed, 178 insertions(+), 98 deletions(-) create mode 100644 app/react/docker/containers/ItemView/HealthStatus.tsx create mode 100644 app/react/docker/images/ItemView/DockerfileDetails.tsx diff --git a/app/docker/filters/filters.js b/app/docker/filters/filters.js index a72418944..1decd66b0 100644 --- a/app/docker/filters/filters.js +++ b/app/docker/filters/filters.js @@ -1,5 +1,5 @@ import _ from 'lodash-es'; -import { trimSHA } from './utils'; +import { joinCommand, trimSHA } from './utils'; function includeString(text, values) { return values.some(function (val) { @@ -191,12 +191,7 @@ angular }; }) .filter('command', function () { - 'use strict'; - return function (command) { - if (command) { - return command.join(' '); - } - }; + return joinCommand; }) .filter('hideshasum', function () { 'use strict'; diff --git a/app/docker/filters/utils.ts b/app/docker/filters/utils.ts index ea26e6960..862107e56 100644 --- a/app/docker/filters/utils.ts +++ b/app/docker/filters/utils.ts @@ -9,3 +9,11 @@ export function trimSHA(imageName: string) { } return _.split(imageName, '@sha256')[0]; } + +export function joinCommand(command: null | Array = []) { + if (!command) { + return ''; + } + + return command.join(' '); +} diff --git a/app/docker/react/components/index.ts b/app/docker/react/components/index.ts index 22ce5c716..9a5b71bdf 100644 --- a/app/docker/react/components/index.ts +++ b/app/docker/react/components/index.ts @@ -9,9 +9,13 @@ import { Gpu } from '@/react/docker/containers/CreateView/Gpu'; import { withCurrentUser } from '@/react-tools/withCurrentUser'; import { withReactQuery } from '@/react-tools/withReactQuery'; import { withUIRouter } from '@/react-tools/withUIRouter'; +import { DockerfileDetails } from '@/react/docker/images/ItemView/DockerfileDetails'; +import { HealthStatus } from '@/react/docker/containers/ItemView/HealthStatus'; export const componentsModule = angular .module('portainer.docker.react.components', []) + .component('dockerfileDetails', r2a(DockerfileDetails, ['image'])) + .component('dockerHealthStatus', r2a(HealthStatus, ['health'])) .component( 'containerQuickActions', r2a(withUIRouter(withCurrentUser(ContainerQuickActions)), [ diff --git a/app/docker/views/containers/edit/container.html b/app/docker/views/containers/edit/container.html index 948926d65..908bf81b2 100644 --- a/app/docker/views/containers/edit/container.html +++ b/app/docker/views/containers/edit/container.html @@ -162,40 +162,7 @@ -
-
- - - - - - - - - - - - - - - - - - -
Status - - {{ container.State.Health.Status }} -
Failure count{{ container.State.Health.FailingStreak }}
Last output{{ container.State.Health.Log[container.State.Health.Log.length - 1].Output }}
-
-
-
-
+
diff --git a/app/docker/views/images/edit/image.html b/app/docker/views/images/edit/image.html index 90167b68b..bdde4e217 100644 --- a/app/docker/views/images/edit/image.html +++ b/app/docker/views/images/edit/image.html @@ -162,58 +162,8 @@
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
CMD{{ image.Command | command }}
ENTRYPOINT{{ image.Entrypoint | command }}
EXPOSE - - {{ port }} - -
VOLUME - - {{ volume }} - -
ENV - - - - - -
{{ var|key: '=' }}{{ var|value: '=' }}
-
-
-
-
-
+ +
diff --git a/app/react/components/DetailsTable/DetailsRow.tsx b/app/react/components/DetailsTable/DetailsRow.tsx index 7ed9bd3f4..9aadcf95e 100644 --- a/app/react/components/DetailsTable/DetailsRow.tsx +++ b/app/react/components/DetailsTable/DetailsRow.tsx @@ -1,15 +1,29 @@ +import clsx from 'clsx'; import { ReactNode } from 'react'; interface Props { children?: ReactNode; label: string; + colClassName?: string; + className?: string; } -export function DetailsRow({ label, children }: Props) { +export function DetailsRow({ + label, + children, + colClassName, + className, +}: Props) { return ( - - {label} - {children && {children}} + + + {label} + + {children && ( + + {children} + + )} ); } diff --git a/app/react/docker/containers/ItemView/HealthStatus.tsx b/app/react/docker/containers/ItemView/HealthStatus.tsx new file mode 100644 index 000000000..8be5b7102 --- /dev/null +++ b/app/react/docker/containers/ItemView/HealthStatus.tsx @@ -0,0 +1,54 @@ +import { ComponentProps } from 'react'; +import { Server } from 'react-feather'; + +import { TableContainer, TableTitle } from '@@/datatables'; +import { DetailsTable } from '@@/DetailsTable'; +import { Icon } from '@@/Icon'; + +import { Health } from '../types/response'; + +const StatusMode: Record< + Health['Status'], + ComponentProps['mode'] +> = { + healthy: 'success', + unhealthy: 'danger', + starting: 'warning', +}; + +interface Props { + health: Health; +} + +export function HealthStatus({ health }: Props) { + return ( +
+
+ + + + + +
+ + {health.Status} +
+
+ + + {health.FailingStreak} + + + + {health.Log[health.Log.length - 1].Output} + +
+
+
+
+ ); +} diff --git a/app/react/docker/containers/types/response.ts b/app/react/docker/containers/types/response.ts index 71b3c9249..be41ed517 100644 --- a/app/react/docker/containers/types/response.ts +++ b/app/react/docker/containers/types/response.ts @@ -70,6 +70,12 @@ interface MountPoint { Propagation: MountPropagation; } +export interface Health { + Status: 'healthy' | 'unhealthy' | 'starting'; + FailingStreak: number; + Log: Array<{ Output: string }>; +} + export interface DockerContainerResponse { Id: string; Names: string[]; @@ -88,7 +94,6 @@ export interface DockerContainerResponse { }; NetworkSettings?: SummaryNetworkSettings; Mounts: MountPoint[]; - Portainer: PortainerMetadata; IsPortainer: boolean; } diff --git a/app/react/docker/images/ItemView/DockerfileDetails.tsx b/app/react/docker/images/ItemView/DockerfileDetails.tsx new file mode 100644 index 000000000..36e7eb7c5 --- /dev/null +++ b/app/react/docker/images/ItemView/DockerfileDetails.tsx @@ -0,0 +1,83 @@ +import { List } from 'react-feather'; + +import { joinCommand } from '@/docker/filters/utils'; +import { getPairKey, getPairValue } from '@/portainer/filters/filters'; + +import { TableContainer, TableTitle } from '@@/datatables'; +import { DetailsTable } from '@@/DetailsTable'; + +interface DockerImage { + Command: Array; + Entrypoint: Array; + ExposedPorts: Array; + Volumes: Array; + Env: Array; +} + +interface Props { + image: DockerImage; +} + +export function DockerfileDetails({ image }: Props) { + return ( +
+
+ + + + + {joinCommand(image.Command)} + + + {image.Entrypoint && ( + + {joinCommand(image.Entrypoint)} + + )} + + {image.ExposedPorts.length > 0 && ( + + {image.ExposedPorts.map((port, index) => ( + + {port} + + ))} + + )} + + {image.Volumes.length > 0 && ( + +
+ {image.Volumes.map((volume, index) => ( + + {volume} + + ))} +
+
+ )} + + {image.Env.length > 0 && ( + + + + {image.Env.map((variable) => ( + + + + + ))} + +
{getPairKey(variable, '=')}{getPairValue(variable, '=')}
+
+ )} +
+
+
+
+ ); +}