From 143128e9489c813bd5ffbdb06825c7992ec0b1d9 Mon Sep 17 00:00:00 2001 From: alecmerdler Date: Thu, 24 Jan 2019 23:08:59 -0500 Subject: [PATCH] add filter bar to CSV list view --- .../clusterserviceversion.spec.tsx | 11 +++-- frontend/public/components/factory/list.tsx | 6 +++ .../clusterserviceversion.tsx | 44 +++++++++++++------ .../operator-lifecycle-manager/index.tsx | 1 - 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/frontend/__tests__/components/operator-lifecycle-manager/clusterserviceversion.spec.tsx b/frontend/__tests__/components/operator-lifecycle-manager/clusterserviceversion.spec.tsx index 16118367975..2a4d80a5a53 100644 --- a/frontend/__tests__/components/operator-lifecycle-manager/clusterserviceversion.spec.tsx +++ b/frontend/__tests__/components/operator-lifecycle-manager/clusterserviceversion.spec.tsx @@ -8,7 +8,7 @@ import * as _ from 'lodash-es'; import { ClusterServiceVersionsDetailsPage, ClusterServiceVersionsDetailsPageProps, ClusterServiceVersionDetails, ClusterServiceVersionDetailsProps, ClusterServiceVersionsPage, ClusterServiceVersionsPageProps, ClusterServiceVersionList, ClusterServiceVersionHeader, ClusterServiceVersionRow, ClusterServiceVersionRowProps, CRDCard, CRDCardRow } from '../../../public/components/operator-lifecycle-manager/clusterserviceversion'; import { ClusterServiceVersionKind, ClusterServiceVersionLogo, ClusterServiceVersionLogoProps, referenceForProvidedAPI, CSVConditionReason } from '../../../public/components/operator-lifecycle-manager'; import { DetailsPage, ListPage, ListHeader, ColHead, List, ListInnerProps } from '../../../public/components/factory'; -import { testClusterServiceVersion, testModel } from '../../../__mocks__/k8sResourcesMocks'; +import { testClusterServiceVersion } from '../../../__mocks__/k8sResourcesMocks'; import { Timestamp, MsgBox, ResourceLink, ResourceKebab, ErrorBoundary, LoadingBox, ScrollToTopOnMount, SectionHeading } from '../../../public/components/utils'; import { referenceForModel } from '../../../public/module/k8s'; import { ClusterServiceVersionModel } from '../../../public/models'; @@ -177,7 +177,7 @@ describe(CRDCard.displayName, () => { const crd = testClusterServiceVersion.spec.customresourcedefinitions.owned[0]; it('renders a card with title, body, and footer', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find('.co-crd-card__title').exists()).toBe(true); expect(wrapper.find('.co-crd-card__body').exists()).toBe(true); @@ -185,14 +185,13 @@ describe(CRDCard.displayName, () => { }); it('renders a link to create a new instance', () => { - const kindObj = _.cloneDeep({...testModel, verbs: ['create']}); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find('.co-crd-card__footer').find(Link).props().to).toEqual(`/k8s/ns/${testClusterServiceVersion.metadata.namespace}/${ClusterServiceVersionModel.plural}/${testClusterServiceVersion.metadata.name}/${referenceForProvidedAPI(crd)}/new`); }); - it('does not render link to create new instance if "create" not included in verbs for the model', () => { - const wrapper = shallow(); + it('does not render link to create new instance if `props.canCreate` is false', () => { + const wrapper = shallow(); expect(wrapper.find('.co-crd-card__footer').find(Link).exists()).toBe(false); }); diff --git a/frontend/public/components/factory/list.tsx b/frontend/public/components/factory/list.tsx index 62dfb056955..877f060d926 100644 --- a/frontend/public/components/factory/list.tsx +++ b/frontend/public/components/factory/list.tsx @@ -105,6 +105,12 @@ const listFilters = { } return filters.selected.has(resource.kind); }, + 'clusterserviceversion-status': (filters, csv) => { + if (!filters || !filters.selected || !filters.selected.size) { + return true; + } + return filters.selected.has(_.get(csv.status, 'reason')) || !_.includes(filters.all, _.get(csv.status, 'reason')); + }, 'build-status': (phases, build) => { if (!phases || !phases.selected || !phases.selected.size) { diff --git a/frontend/public/components/operator-lifecycle-manager/clusterserviceversion.tsx b/frontend/public/components/operator-lifecycle-manager/clusterserviceversion.tsx index 5ed857268aa..bc65c123de1 100644 --- a/frontend/public/components/operator-lifecycle-manager/clusterserviceversion.tsx +++ b/frontend/public/components/operator-lifecycle-manager/clusterserviceversion.tsx @@ -9,12 +9,11 @@ import { Alert } from 'patternfly-react'; import { ProvidedAPIsPage, ProvidedAPIPage } from './clusterserviceversion-resource'; import { DetailsPage, ListHeader, ColHead, List, ListPage } from '../factory'; import { withFallback } from '../utils/error-boundary'; -import { referenceForModel, referenceFor, K8sKind } from '../../module/k8s'; +import { referenceForModel, referenceFor, GroupVersionKind, K8sKind } from '../../module/k8s'; import { ClusterServiceVersionModel } from '../../models'; import { FLAGS as featureFlags } from '../../features'; import { ResourceEventStream } from '../events'; import { Conditions } from '../conditions'; -import { connectToModel } from '../../kinds'; import { ClusterServiceVersionKind, ClusterServiceVersionLogo, @@ -105,6 +104,13 @@ export const ClusterServiceVersionsPage = connect(stateToProps)((props: ClusterS Installed Operators are represented by Cluster Service Versions within this namespace. For more information, see the . Or create an Operator and Cluster Service Version using the .

; + const rowFilters = [{ + type: 'clusterserviceversion-status', + selected: [CSVConditionReason.CSVReasonInstallSuccessful], + reducer: (csv: ClusterServiceVersionKind) => _.get(csv.status, 'reason'), + items: [CSVConditionReason.CSVReasonInstallSuccessful, CSVConditionReason.CSVReasonCopied].map(status => ({id: status, title: status})), + }]; + return ; }); @@ -122,8 +129,8 @@ export const MarkdownView = (props: {content: string, outerScroll: boolean}) => return import('./markdown-view').then(c => c.SyncMarkdownView)} {...props} />; }; -export const CRDCard = connectToModel((props: CRDCardProps) => { - const {csv, crd, kindObj} = props; +export const CRDCard: React.SFC = (props) => { + const {csv, crd, canCreate} = props; const createRoute = `/k8s/ns/${csv.metadata.namespace}/${ClusterServiceVersionModel.plural}/${csv.metadata.name}/${referenceForProvidedAPI(crd)}/new`; return
@@ -135,17 +142,27 @@ export const CRDCard = connectToModel((props: CRDCardProps) => {

{crd.description}

-
- { (kindObj.verbs || []).some(v => v === 'create') && + { canCreate &&
+ Create New - } -
+ +
}
; -}); +}; + +const crdCardRowStateToProps = ({k8s}, {crdDescs}) => { + const models: K8sKind[] = crdDescs.map(desc => k8s.getIn(['RESOURCES', 'models', referenceForProvidedAPI(desc)])); + return { + crdDescs: crdDescs.filter(desc => models.find(m => referenceForModel(m) === referenceForProvidedAPI(desc))), + createable: models.filter(m => (m.verbs || []).includes('create')).map(m => referenceForModel(m)), + }; +}; -export const CRDCardRow: React.SFC = (props) =>
- {props.crdDescs.map((desc, i) => )} -
; +export const CRDCardRow = connect(crdCardRowStateToProps)( + (props: CRDCardRowProps) =>
+ {props.crdDescs.map((desc, i) => )} +
+); export const ClusterServiceVersionDetails: React.SFC = (props) => { const {spec, metadata, status = {} as ClusterServiceVersionKind['status']} = props.obj; @@ -269,12 +286,13 @@ export type ClusterServiceVersionListProps = { export type CRDCardProps = { crd: CRDDescription | APIServiceDefinition; csv: ClusterServiceVersionKind; - kindObj: K8sKind; + canCreate: boolean; }; export type CRDCardRowProps = { crdDescs: (CRDDescription | APIServiceDefinition)[]; csv: ClusterServiceVersionKind; + createable: GroupVersionKind[]; }; export type CRDCardRowState = { diff --git a/frontend/public/components/operator-lifecycle-manager/index.tsx b/frontend/public/components/operator-lifecycle-manager/index.tsx index 1d230320bfd..03200ae23dc 100644 --- a/frontend/public/components/operator-lifecycle-manager/index.tsx +++ b/frontend/public/components/operator-lifecycle-manager/index.tsx @@ -48,7 +48,6 @@ export enum CSVConditionReason { export enum InstallPlanApproval { Automatic = 'Automatic', Manual = 'Manual', - UpdateOnly = 'Update-Only', } export enum SubscriptionState {