From dacdeb6025ec30c845aed9e87546bbeaab0732a2 Mon Sep 17 00:00:00 2001 From: Alexander Matyushentsev Date: Wed, 31 Jul 2019 18:39:41 -0700 Subject: [PATCH] Improve wrapped text rendering on application list and application sync status pages (#2067) --- .../application-operation-state.scss | 10 +++- .../application-operation-state.tsx | 18 +++--- .../application-summary.tsx | 3 +- .../applications-list/applications-list.scss | 6 -- .../applications-list/applications-list.tsx | 6 +- .../applications-list/applications-table.scss | 26 +++++++++ .../applications-list/applications-table.tsx | 56 +++++++++++-------- .../applications-list/applications-tiles.tsx | 2 +- .../components/repos-list/repos-list.tsx | 3 +- ui/src/app/shared/components/cluster.tsx | 38 ++++++++++--- ui/src/app/shared/components/index.ts | 2 + ui/yarn.lock | 2 +- 12 files changed, 114 insertions(+), 58 deletions(-) create mode 100644 ui/src/app/applications/components/applications-list/applications-table.scss diff --git a/ui/src/app/applications/components/application-operation-state/application-operation-state.scss b/ui/src/app/applications/components/application-operation-state/application-operation-state.scss index 07b0d73cf4..444f6a211d 100644 --- a/ui/src/app/applications/components/application-operation-state/application-operation-state.scss +++ b/ui/src/app/applications/components/application-operation-state/application-operation-state.scss @@ -8,4 +8,12 @@ left: 15px; position: relative; } -} \ No newline at end of file + + &__message { + white-space: normal; + line-height: 16px; + display: inline-block; + vertical-align: middle; + } + +} diff --git a/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx b/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx index 182185ab96..df28ae820a 100644 --- a/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx +++ b/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx @@ -91,12 +91,9 @@ export const ApplicationOperationState: React.StatelessComponent = ({appl
- API VERSION -
-
KIND
-
+
NAMESPACE
@@ -120,12 +117,9 @@ export const ApplicationOperationState: React.StatelessComponent = ({appl
{resource.hookType && ()}
- {resource.group ? resource.group + '/' + resource.version : resource.version} + {resource.group ? resource.group + '/' + resource.version : resource.version}/{resource.kind}
-
- {resource.kind} -
-
+
{resource.namespace}
@@ -138,8 +132,10 @@ export const ApplicationOperationState: React.StatelessComponent = ({appl
{resource.hookType}
-
- {resource.message} +
+
+ {resource.message} +
diff --git a/ui/src/app/applications/components/application-summary/application-summary.tsx b/ui/src/app/applications/components/application-summary/application-summary.tsx index 0f7ca13c25..992fdd56ef 100644 --- a/ui/src/app/applications/components/application-summary/application-summary.tsx +++ b/ui/src/app/applications/components/application-summary/application-summary.tsx @@ -5,12 +5,11 @@ import { FormApi, Text } from 'react-form'; require('./application-summary.scss'); import { Cluster, clusterTitle, DataLoader, EditablePanel, EditablePanelItem } from '../../../shared/components'; +import { Repo, Revision } from '../../../shared/components'; import { Consumer } from '../../../shared/context'; import * as models from '../../../shared/models'; import { services } from '../../../shared/services'; -import {Repo} from '../../../shared/components/repo'; -import {Revision} from '../../../shared/components/revision'; import { ComparisonStatusIcon, HealthStatusIcon, syncStatusMessage } from '../utils'; const urlPattern = new RegExp('^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))' diff --git a/ui/src/app/applications/components/applications-list/applications-list.scss b/ui/src/app/applications/components/applications-list/applications-list.scss index 2da6a9f491..c94d939a40 100644 --- a/ui/src/app/applications/components/applications-list/applications-list.scss +++ b/ui/src/app/applications/components/applications-list/applications-list.scss @@ -190,12 +190,6 @@ & > .columns:first-child { padding-left: 30px; } - & > .columns:last-child { - .argo-dropdown { - position: absolute; - right: 0; - } - } margin-left: -30px !important; } diff --git a/ui/src/app/applications/components/applications-list/applications-list.tsx b/ui/src/app/applications/components/applications-list/applications-list.tsx index 9907074f66..2b3782548a 100644 --- a/ui/src/app/applications/components/applications-list/applications-list.tsx +++ b/ui/src/app/applications/components/applications-list/applications-list.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { RouteComponentProps } from 'react-router'; import { Observable } from 'rxjs'; -import { Autocomplete, DataLoader, EmptyState, ObservableQuery, Page, Paginate, Query } from '../../../shared/components'; +import { Autocomplete, ClusterCtx, DataLoader, EmptyState, ObservableQuery, Page, Paginate, Query } from '../../../shared/components'; import { Consumer } from '../../../shared/context'; import * as models from '../../../shared/models'; import { AppsListPreferences, AppsListViewType, services } from '../../../shared/services'; @@ -112,6 +112,7 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => { const [createApi, setCreateApi] = React.useState(null); return ( + { (ctx) => ( ({ @@ -277,5 +278,6 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => { )} -); + +); }; diff --git a/ui/src/app/applications/components/applications-list/applications-table.scss b/ui/src/app/applications/components/applications-list/applications-table.scss new file mode 100644 index 0000000000..eefd8bfc39 --- /dev/null +++ b/ui/src/app/applications/components/applications-list/applications-table.scss @@ -0,0 +1,26 @@ +@import 'node_modules/argo-ui/src/app/shared/styles/config'; + +.applications-table { + &__revision { + background-color: $argo-color-gray-4; + border-radius: 5px; + position: absolute; + right: 5px; + padding: 0 2px; + } + + .argo-table-list__row { + line-height: 26px; + padding-top: 4px; + padding-bottom: 4px; + + .columns:last-child { + .argo-dropdown { + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + } + } + } +} diff --git a/ui/src/app/applications/components/applications-list/applications-table.tsx b/ui/src/app/applications/components/applications-list/applications-table.tsx index 4ef62b5c2f..3713943d4c 100644 --- a/ui/src/app/applications/components/applications-list/applications-table.tsx +++ b/ui/src/app/applications/components/applications-list/applications-table.tsx @@ -1,11 +1,19 @@ -import { DropDownMenu } from 'argo-ui'; +import { DropDownMenu, Tooltip } from 'argo-ui'; import * as React from 'react'; +import { Cluster } from '../../../shared/components'; import { Consumer } from '../../../shared/context'; import * as models from '../../../shared/models'; import { ApplicationURLs } from '../application-urls'; import * as AppUtils from '../utils'; +require('./applications-table.scss'); + +function shortRepo(repo: string) { + const url = new URL(repo); + return {url.pathname.slice(1)}; +} + export const ApplicationsTable = (props: { applications: models.Application[]; syncApplication: (appName: string) => any; @@ -14,37 +22,39 @@ export const ApplicationsTable = (props: { }) => ( {(ctx) => ( -
-
-
-
PROJECT/NAME
-
SOURCE
-
TARGET REVISION
-
DESTINATION
-
STATUS
-
-
+
{props.applications.map((app) => (
ctx.navigation.goto(`/applications/${app.metadata.name}`, {}, { event: e })}> -
- {app.spec.project}/{app.metadata.name} +
+
+
Project:
+
{app.spec.project}
+
+
+
Name:
+
{app.metadata.name}
+
-
- {app.spec.source.repoURL}/{app.spec.source.path} +
+
+
Source:
+
+ {shortRepo(app.spec.source.repoURL)}/{app.spec.source.path} + {app.spec.source.targetRevision || 'HEAD'} +
+
+
+
Destination:
+
/{app.spec.destination.namespace}
+
-
- {app.spec.source.targetRevision || 'HEAD'} -
-
- {app.spec.destination.server}/{app.spec.destination.namespace} -
-
+
{app.status.health.status} -   +
{app.status.sync.status} (
Namespace:
-
+
{app.spec.destination.namespace}
diff --git a/ui/src/app/settings/components/repos-list/repos-list.tsx b/ui/src/app/settings/components/repos-list/repos-list.tsx index 780cb40ef8..2d359fc0e7 100644 --- a/ui/src/app/settings/components/repos-list/repos-list.tsx +++ b/ui/src/app/settings/components/repos-list/repos-list.tsx @@ -4,8 +4,7 @@ import * as React from 'react'; import {Form, FormApi, Text, TextArea} from 'react-form'; import {RouteComponentProps} from 'react-router'; -import {CheckboxField, ConnectionStateIcon, DataLoader, EmptyState, ErrorNotification, Page} from '../../../shared/components'; -import {Repo} from '../../../shared/components/repo'; +import {CheckboxField, ConnectionStateIcon, DataLoader, EmptyState, ErrorNotification, Page, Repo} from '../../../shared/components'; import {AppContext} from '../../../shared/context'; import * as models from '../../../shared/models'; import {services} from '../../../shared/services'; diff --git a/ui/src/app/shared/components/cluster.tsx b/ui/src/app/shared/components/cluster.tsx index 142ca57e50..6df4229e85 100644 --- a/ui/src/app/shared/components/cluster.tsx +++ b/ui/src/app/shared/components/cluster.tsx @@ -17,14 +17,34 @@ const clusterHTML = (cluster: models.Cluster, showUrl: boolean) => { return {text}; }; -interface Props { - url: string; - showUrl?: boolean; +async function getCluster(clusters: Promise, url: string): Promise { + let cluster: models.Cluster; + if (clusters) { + cluster = await clusters.then((items) => items.find((item) => item.server === url)); + } else { + try { + cluster = await services.clusters.get(url); + } catch { + cluster = null; + } + } + if (!cluster) { + cluster = { + connectionState: null, + name: url, + server: url, + }; + } + return cluster; } -export const Cluster = React.memo((props: Props) => { - return ( - services.clusters.get(url)}>{(cluster: models.Cluster) => clusterHTML(cluster, props.showUrl)} - ); -}); +export const ClusterCtx = React.createContext>>(null); + +export const Cluster = (props: {url: string; showUrl?: boolean; }) => ( + + {(clusters) => ( + {props.url}} + load={(url) => getCluster(clusters, url)}>{(cluster: models.Cluster) => clusterHTML(cluster, props.showUrl)} + )} + +); diff --git a/ui/src/app/shared/components/index.ts b/ui/src/app/shared/components/index.ts index ead4aa6981..8fe76630d6 100644 --- a/ui/src/app/shared/components/index.ts +++ b/ui/src/app/shared/components/index.ts @@ -16,3 +16,5 @@ export * from './autocomplete/autocomplete'; export * from './autocomplete/autocomplete-field'; export * from './monaco-editor'; export * from './yaml-editor/yaml-editor'; +export * from './repo'; +export * from './revision'; diff --git a/ui/yarn.lock b/ui/yarn.lock index b52525ad22..ed5d3db5f5 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -887,7 +887,7 @@ are-we-there-yet@~1.1.2: "argo-ui@https://github.com/argoproj/argo-ui.git": version "1.0.0" - resolved "https://github.com/argoproj/argo-ui.git#7c6a57447d54b2487609e727132e188678b43106" + resolved "https://github.com/argoproj/argo-ui.git#f12c7f443d8108289276feafe47d0161c9de2390" dependencies: "@fortawesome/fontawesome-free" "^5.8.1" "@tippy.js/react" "^2.1.2"