diff --git a/ui/src/app/applications/components/application-details/application-details.tsx b/ui/src/app/applications/components/application-details/application-details.tsx index 75eabc52b3caa..1719c3a0c6e5b 100644 --- a/ui/src/app/applications/components/application-details/application-details.tsx +++ b/ui/src/app/applications/components/application-details/application-details.tsx @@ -1,4 +1,4 @@ -import {DropDownMenu, NotificationType, SlidingPanel} from 'argo-ui'; +import {DropDownMenu, NotificationType, SlidingPanel, Tooltip} from 'argo-ui'; import * as classNames from 'classnames'; import * as PropTypes from 'prop-types'; import * as React from 'react'; @@ -147,7 +147,8 @@ export class ApplicationDetails extends React.Component (usrMsg.appName === appName && usrMsg.msgKey === 'groupNodes' ? {...usrMsg, display: true} : usrMsg)); services.viewPreferences.updatePreferences({appDetails: {...pref, groupNodes: !pref.groupNodes}}); } @@ -231,6 +232,7 @@ export class ApplicationDetails extends React.Component usrMsg.appName === application.metadata.name); const resourceNodes = (): any[] => { const statusByKey = new Map(); application.status.resources.forEach(res => statusByKey.set(AppUtils.nodeKey(res), res)); @@ -296,6 +298,14 @@ export class ApplicationDetails extends React.Component { services.viewPreferences.updatePreferences({appDetails: {...pref, groupNodes: showCompactView}}); }; + const updateHelpTipState = (usrHelpTip: models.UserMessages) => { + const existingIndex = pref.userHelpTipMsgs.findIndex(msg => msg.appName === usrHelpTip.appName && msg.msgKey === usrHelpTip.msgKey); + if (existingIndex !== -1) { + pref.userHelpTipMsgs[existingIndex] = usrHelpTip; + } else { + (pref.userHelpTipMsgs || []).push(usrHelpTip); + } + }; const toggleNameDirection = () => { this.setState({truncateNameOnRight: !this.state.truncateNameOnRight}); }; @@ -446,13 +456,19 @@ export class ApplicationDetails extends React.Component {(pref.view === 'tree' || pref.view === 'network') && ( - this.toggleCompactView(pref)}> - - + + this.toggleCompactView(application.metadata.name, pref)}> + + + )} + expandAll()} title='Expand all child nodes of all parent nodes'> @@ -481,6 +497,7 @@ export class ApplicationDetails extends React.Component this.setNodeExpansion(node, isExpanded)} getNodeExpansion={node => this.getNodeExpansion(node)} diff --git a/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx b/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx index b5426ff1de2bf..6f28a40ea5046 100644 --- a/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx +++ b/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx @@ -1,4 +1,4 @@ -import {DropDown, DropDownMenu, NotificationType, Tooltip} from 'argo-ui'; +import {DropDown, DropDownMenu, Tooltip} from 'argo-ui'; import * as classNames from 'classnames'; import * as dagre from 'dagre'; import * as React from 'react'; @@ -22,7 +22,8 @@ import { isYoungerThanXMinutes, NodeId, nodeKey, - PodHealthIcon + PodHealthIcon, + getUsrMsgKeyToDisplay } from '../utils'; import {NodeUpdateAnimation} from './node-update-animation'; import {PodGroup} from '../application-pod-view/pod-view'; @@ -59,6 +60,8 @@ export interface ApplicationResourceTreeProps { appContext?: AppContext; showOrphanedResources: boolean; showCompactNodes: boolean; + userMsgs: models.UserMessages[]; + updateUsrHelpTipMsgs: (userMsgs: models.UserMessages) => void; setShowCompactNodes: (showCompactNodes: boolean) => void; zoom: number; podGroupCount: number; @@ -927,6 +930,7 @@ export const ApplicationResourceTree = (props: ApplicationResourceTreeProps) => const [filters, setFilters] = React.useState(props.filters); const [filteredGraph, setFilteredGraph] = React.useState([]); const filteredNodes: any[] = []; + React.useEffect(() => { if (props.filters !== filters) { setFilters(props.filters); @@ -934,19 +938,16 @@ export const ApplicationResourceTree = (props: ApplicationResourceTreeProps) => props.setTreeFilterGraph(filteredGraph); } }, [props.filters]); - + const {podGroupCount, userMsgs, updateUsrHelpTipMsgs, setShowCompactNodes} = props; const podCount = nodes.filter(node => node.kind === 'Pod').length; + React.useEffect(() => { - const {podGroupCount, setShowCompactNodes, appContext} = props; if (podCount > podGroupCount) { - setShowCompactNodes(true); - appContext.apis.notifications.show({ - content: `Since the number of pods has surpassed the threshold pod count of ${podGroupCount}, you will now be switched to the group node view. - If you prefer the tree view, you can simply click on the Group Nodes toolbar button to deselect the current view.`, - type: NotificationType.Success - }); - } else { - props.setShowCompactNodes(false); + const userMsg = getUsrMsgKeyToDisplay(appNode.name, 'groupNodes', userMsgs); + updateUsrHelpTipMsgs(userMsg); + if (!userMsg.display) { + setShowCompactNodes(true); + } } }, [podCount]); diff --git a/ui/src/app/applications/components/utils.tsx b/ui/src/app/applications/components/utils.tsx index 0df581ca0f291..674ffc6728db4 100644 --- a/ui/src/app/applications/components/utils.tsx +++ b/ui/src/app/applications/components/utils.tsx @@ -1252,3 +1252,17 @@ export function formatCreationTimestamp(creationTimestamp: string) { } export const selectPostfix = (arr: string[], singular: string, plural: string) => (arr.length > 1 ? plural : singular); + +export function getUsrMsgKeyToDisplay(appName: string, msgKey: string, usrMessages: appModels.UserMessages[]) { + const usrMsg = usrMessages?.find((msg: appModels.UserMessages) => msg.appName === appName && msg.msgKey === msgKey); + if (usrMsg !== undefined) { + return {...usrMsg, display: true}; + } else { + return {appName, msgKey, display: false, duration: 1} as appModels.UserMessages; + } +} + +export const userMsgsList: {[key: string]: string} = { + groupNodes: `Since the number of pods has surpassed the threshold pod count of 15, you will now be switched to the group node view. + If you prefer the tree view, you can simply click on the Group Nodes toolbar button to deselect the current view.` +}; diff --git a/ui/src/app/shared/models.ts b/ui/src/app/shared/models.ts index ef0d47331c403..23643f7bbbb53 100644 --- a/ui/src/app/shared/models.ts +++ b/ui/src/app/shared/models.ts @@ -955,3 +955,12 @@ export interface LinkInfo { export interface LinksResponse { items: LinkInfo[]; } + +export interface UserMessages { + appName: string; + msgKey: string; + display: boolean; + condition?: HealthStatusCode; + duration?: number; + animation?: string; +} diff --git a/ui/src/app/shared/services/view-preferences-service.ts b/ui/src/app/shared/services/view-preferences-service.ts index 314170dba0404..b6cdbbdc08a46 100644 --- a/ui/src/app/shared/services/view-preferences-service.ts +++ b/ui/src/app/shared/services/view-preferences-service.ts @@ -2,6 +2,7 @@ import * as deepMerge from 'deepmerge'; import {BehaviorSubject, Observable} from 'rxjs'; import {PodGroupType} from '../../applications/components/application-pod-view/pod-view'; +import {UserMessages} from '../models'; export type AppsDetailsViewType = 'tree' | 'network' | 'list' | 'pods'; @@ -28,6 +29,7 @@ export interface AppDetailsPreferences { groupNodes?: boolean; zoom: number; podGroupCount: number; + userHelpTipMsgs: UserMessages[]; } export interface PodViewPreferences { @@ -122,7 +124,8 @@ const DEFAULT_PREFERENCES: ViewPreferences = { followLogs: false, wrapLines: false, zoom: 1.0, - podGroupCount: 15.0 + podGroupCount: 15.0, + userHelpTipMsgs: [] }, appList: { view: 'tiles' as AppsListViewType,