From b057484cb17d60aa301d48099051eabaa00f9d24 Mon Sep 17 00:00:00 2001 From: Jon Jackson Date: Mon, 25 Mar 2019 12:53:27 -0400 Subject: [PATCH] Move overview group and filter state to redux --- .../public/components/overview/constants.ts | 14 + frontend/public/components/overview/index.tsx | 301 +++++++++--------- frontend/public/ui/ui-actions.js | 9 + frontend/public/ui/ui-reducers.js | 16 + 4 files changed, 187 insertions(+), 153 deletions(-) create mode 100644 frontend/public/components/overview/constants.ts diff --git a/frontend/public/components/overview/constants.ts b/frontend/public/components/overview/constants.ts new file mode 100644 index 00000000000..e6fa1c48560 --- /dev/null +++ b/frontend/public/components/overview/constants.ts @@ -0,0 +1,14 @@ +/* eslint-disable no-undef */ + +// Keys for special 'group by' options +// Should not be valid label keys to avoid conflicts. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set +export enum OverviewSpecialGroup { + GROUP_BY_APPLICATION = '#GROUP_BY_APPLICATION#', + GROUP_BY_RESOURCE = '#GROUP_BY_RESOURCE#', +} + +// View options for overview page +export enum OverviewViewOption { + RESOURCES = 'resources', + DASHBOARD = 'dashboard', +} diff --git a/frontend/public/components/overview/index.tsx b/frontend/public/components/overview/index.tsx index facac15cfd6..f1314ab3465 100644 --- a/frontend/public/components/overview/index.tsx +++ b/frontend/public/components/overview/index.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-unused-vars, no-undef */ - import * as _ from 'lodash-es'; import * as classnames from 'classnames'; import * as fuzzy from 'fuzzysearch'; @@ -14,6 +13,7 @@ import { coFetchJSON } from '../../co-fetch'; import { getBuildNumber } from '../../module/k8s/builds'; import { prometheusTenancyBasePath } from '../graphs'; import { TextFilter } from '../factory'; +import { PodStatus } from '../pod'; import { UIActions, formatNamespacedRouteForResource } from '../../ui/ui-actions'; import { apiVersionForModel, @@ -48,31 +48,40 @@ import { import { overviewMenuActions, OverviewNamespaceDashboard } from './namespace-overview'; import { ProjectOverview } from './project-overview'; import { ResourceOverviewPage } from './resource-overview-page'; -import { PodStatus } from '../pod'; +import { OverviewViewOption, OverviewSpecialGroup } from './constants'; -enum View { - Resources = 'resources', - Dashboard = 'dashboard', -} -// The following values should not be valid label keys to avoid conflicts. -// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set -const GROUP_BY_APPLICATION = '#GROUP_BY_APPLICATION#'; -const GROUP_BY_RESOURCE = '#GROUP_BY_RESOURCE#'; -const EMPTY_GROUP_NAME = 'other resources'; +// List of container status waiting reason values that we should call out as errors in project status rows. +const CONTAINER_WAITING_STATE_ERROR_REASONS = ['CrashLoopBackOff', 'ErrImagePull', 'ImagePullBackOff']; -const DEPLOYMENT_REVISION_ANNOTATION = 'deployment.kubernetes.io/revision'; +// Annotation key for deployment config latest version const DEPLOYMENT_CONFIG_LATEST_VERSION_ANNOTATION = 'openshift.io/deployment-config.latest-version'; + +// Annotation key for deployment phase const DEPLOYMENT_PHASE_ANNOTATION = 'openshift.io/deployment.phase'; -const TRIGGERS_ANNOTATION = 'image.openshift.io/triggers'; + +// Annotaton key for deployment revision +const DEPLOYMENT_REVISION_ANNOTATION = 'deployment.kubernetes.io/revision'; + +// Display name for default overview group. +// Should not be a valid label key to avoid conflicts. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-setexport +const DEFAULT_GROUP_NAME = 'other resources'; + +// Interval at which metrics are retrieved and updated const METRICS_POLL_INTERVAL = 30 * 1000; +// Namespace prefixes that are reserved and should not have calls to action on empty state +const RESERVED_NS_PREFIXES = ['openshift-', 'kube-', 'kubernetes-']; + +// Annotation key for image triggers +const TRIGGERS_ANNOTATION = 'image.openshift.io/triggers'; + const asOverviewGroups = (keyedItems: { [name: string]: OverviewItem[] }): OverviewGroup[] => { const compareGroups = (a: OverviewGroup, b: OverviewGroup) => { - if (a.name === EMPTY_GROUP_NAME) { + if (a.name === DEFAULT_GROUP_NAME) { return 1; } - if (b.name === EMPTY_GROUP_NAME) { + if (b.name === DEFAULT_GROUP_NAME) { return -1; } return a.name.localeCompare(b.name); @@ -88,7 +97,7 @@ const asOverviewGroups = (keyedItems: { [name: string]: OverviewItem[] }): Overv const getApplication = (item: OverviewItem): string => { const labels = _.get(item, 'obj.metadata.labels') || {}; - return labels['app.kubernetes.io/part-of'] || labels['app.kubernetes.io/name'] || labels.app || EMPTY_GROUP_NAME; + return labels['app.kubernetes.io/part-of'] || labels['app.kubernetes.io/name'] || labels.app || DEFAULT_GROUP_NAME; }; const groupByApplication = (items: OverviewItem[]): OverviewGroup[] => { @@ -102,24 +111,21 @@ const groupByResource = (items: OverviewItem[]): OverviewGroup[] => { }; const groupByLabel = (items: OverviewItem[], label: string): OverviewGroup[] => { - const byLabel = _.groupBy(items, (item): string => _.get(item, ['obj', 'metadata', 'labels', label]) || EMPTY_GROUP_NAME); + const byLabel = _.groupBy(items, (item): string => _.get(item, ['obj', 'metadata', 'labels', label]) || DEFAULT_GROUP_NAME); return asOverviewGroups(byLabel); }; const groupItems = (items: OverviewItem[], selectedGroup: string): OverviewGroup[] => { switch (selectedGroup) { - case GROUP_BY_APPLICATION: + case OverviewSpecialGroup.GROUP_BY_APPLICATION: return groupByApplication(items); - case GROUP_BY_RESOURCE: + case OverviewSpecialGroup.GROUP_BY_RESOURCE: return groupByResource(items); default: return groupByLabel(items, selectedGroup); } }; -// List of container status waiting reason values that we should call out as errors in overview rows. -const CONTAINER_WAITING_STATE_ERROR_REASONS = ['CrashLoopBackOff', 'ErrImagePull', 'ImagePullBackOff']; - const getAnnotation = (obj: K8sResourceKind, annotation: string): string => { return _.get(obj, ['metadata', 'annotations', annotation]); }; @@ -293,8 +299,7 @@ const sortBuilds = (builds: K8sResourceKind[]): K8sResourceKind[] => { return builds.sort(byBuildNumber); }; -const reservedNSPrefixes = ['openshift-', 'kube-', 'kubernetes-']; -const isReservedNamespace = (ns: string) => ns === 'default' || ns === 'openshift' || reservedNSPrefixes.some(prefix => _.startsWith(ns, prefix)); +const isReservedNamespace = (ns: string) => ns === 'default' || ns === 'openshift' || RESERVED_NS_PREFIXES.some(prefix => _.startsWith(ns, prefix)); const OverviewItemReadiness: React.SFC = ({desired = 0, ready = 0, resource}) => { const href = `${resourceObjPath(resource, resource.kind)}/pods`; @@ -337,106 +342,114 @@ const OverviewEmptyState = connect(overviewEmptyStateToProps)(({activeNamespace, }); const headingStateToProps = ({UI}): OverviewHeadingPropsFromState => { - const selectedView = UI.getIn(['overview', 'selectedView']); - return { selectedView }; + const {selectedView, selectedGroup, groupOptions, filterValue} = UI.get('overview').toJS(); + return {groupOptions, selectedGroup, selectedView, filterValue}; }; const headingDispatchToProps = (dispatch): OverviewHeadingPropsFromDispatch => ({ - selectView: (view: View) => dispatch(UIActions.selectOverviewView(view)), + selectView: (view: OverviewViewOption) => dispatch(UIActions.selectOverviewView(view)), + selectGroup: (group: string) => dispatch(UIActions.updateOverviewSelectedGroup(group)), + changeFilter: (value: string) => dispatch(UIActions.updateOverviewFilterValue(value)), }); -const OverviewHeading_: React.SFC = ({disabled, firstLabel = '', groupOptions, handleFilterChange = _.noop, handleGroupChange = _.noop, selectedGroup = '', selectView, selectedView, title, project}) => ( -
- { - title && -

-
{title}
-

- } - {!_.isEmpty(project) &&
-
-