diff --git a/.changeset/clean-rocks-ring.md b/.changeset/clean-rocks-ring.md new file mode 100644 index 0000000000..706f3640c2 --- /dev/null +++ b/.changeset/clean-rocks-ring.md @@ -0,0 +1,18 @@ +--- +'@backstage/cli': minor +--- + +We've bumped the `@eslint-typescript` packages to the latest, which now add some additional rules that might cause lint failures. +The main one which could become an issue is the [no-use-before-define](https://eslint.org/docs/rules/no-use-before-define) rule. + +Every plugin and app has the ability to override these rules if you want to ignore them for now. + +You can reset back to the default behaviour by using the following in your own `.eslint.js` + +```js +rules: { + 'no-use-before-define': 'off' +} +``` + +Because of the nature of this change, we're unable to provide a grace period for the update :( diff --git a/packages/cli/config/eslint.backend.js b/packages/cli/config/eslint.backend.js index 67f0a49b9f..7acb538d38 100644 --- a/packages/cli/config/eslint.backend.js +++ b/packages/cli/config/eslint.backend.js @@ -34,12 +34,12 @@ module.exports = { parserOptions: { ecmaVersion: 2018, sourceType: 'module', + lib: require('./tsconfig.json').compilerOptions.lib, }, ignorePatterns: ['.eslintrc.js', '**/dist/**', '**/dist-types/**'], rules: { - // TODO(Rugvip): We need to bump @typescript-eslint to v4 to enable these - '@typescript-eslint/no-shadow': 0, - '@typescript-eslint/no-redeclare': 0, + '@typescript-eslint/no-shadow': 'off', + '@typescript-eslint/no-redeclare': 'off', 'no-console': 0, // Permitted in console programs 'new-cap': ['error', { capIsNew: false }], // Because Express constructs things e.g. like 'const r = express.Router()' @@ -79,6 +79,13 @@ module.exports = { ], }, overrides: [ + { + files: ['**/*.ts?(x)'], + rules: { + '@typescript-eslint/no-unused-vars': 'off', + 'no-undef': 'off', + }, + }, { files: ['*.test.*', 'src/setupTests.*', 'dev/**'], rules: { diff --git a/packages/cli/config/eslint.js b/packages/cli/config/eslint.js index e2a807e42e..044d737d15 100644 --- a/packages/cli/config/eslint.js +++ b/packages/cli/config/eslint.js @@ -32,7 +32,11 @@ module.exports = { }, parserOptions: { ecmaVersion: 2018, + ecmaFeatures: { + jsx: true, + }, sourceType: 'module', + lib: require('./tsconfig.json').compilerOptions.lib, }, settings: { react: { @@ -41,10 +45,9 @@ module.exports = { }, ignorePatterns: ['.eslintrc.js', '**/dist/**', '**/dist-types/**'], rules: { - // TODO(Rugvip): We need to bump @typescript-eslint to v4 to enable these - '@typescript-eslint/no-shadow': 0, - '@typescript-eslint/no-redeclare': 0, - + '@typescript-eslint/no-shadow': 'off', + '@typescript-eslint/no-redeclare': 'off', + 'no-undef': 'off', 'import/newline-after-import': 'error', 'import/no-duplicates': 'warn', 'import/no-extraneous-dependencies': [ @@ -90,6 +93,8 @@ module.exports = { rules: { // Default to not enforcing prop-types in typescript 'react/prop-types': 0, + '@typescript-eslint/no-unused-vars': 'off', + 'no-undef': 'off', }, }, { diff --git a/packages/cli/package.json b/packages/cli/package.json index e7d4379b5d..0d1605f752 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,8 +50,8 @@ "@types/start-server-webpack-plugin": "^2.2.0", "@types/webpack-env": "^1.15.2", "@types/webpack-node-externals": "^2.5.0", - "@typescript-eslint/eslint-plugin": "^v3.10.1", - "@typescript-eslint/parser": "^v3.10.1", + "@typescript-eslint/eslint-plugin": "^v4.14.0", + "@typescript-eslint/parser": "^v4.14.0", "@yarnpkg/lockfile": "^1.1.0", "bfj": "^7.0.2", "chalk": "^4.0.0", diff --git a/packages/core/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx index 4868af54bd..916259042c 100644 --- a/packages/core/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx +++ b/packages/core/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx @@ -40,6 +40,21 @@ const nestedListStyle = (theme: Theme) => }, }); +interface StyleProps extends WithStyles { + children?: React.ReactNode; +} +// Sub Components +const StyledList = withStyles( + listStyle, +)(({ classes, children }: StyleProps) => ( + {children} +)); +const StyledNestedList = withStyles( + nestedListStyle, +)(({ classes, children }: StyleProps) => ( + {children} +)); + function renderList(list: Array, nested?: boolean) { const values = list.map((item: any, index: number) => ( {toValue(item)} @@ -100,30 +115,10 @@ function toValue( return {value}; } - -function mapToItems(info: { [key: string]: string }, options: any) { - return Object.keys(info).map(key => ( - - )); -} - -interface StyleProps extends WithStyles { - children?: React.ReactNode; -} -// Sub Components -const StyledList = withStyles( - listStyle, -)(({ classes, children }: StyleProps) => ( - {children} -)); -const StyledNestedList = withStyles( - nestedListStyle, -)(({ classes, children }: StyleProps) => ( - {children} -)); const ItemValue = ({ value, options }: { value: any; options: any }) => ( {toValue(value, options)} ); + const TableItem = ({ title, value, @@ -146,6 +141,12 @@ const TableItem = ({ ); }; +function mapToItems(info: { [key: string]: string }, options: any) { + return Object.keys(info).map(key => ( + + )); +} + type Props = { metadata: { [key: string]: any }; dense?: boolean; diff --git a/packages/core/src/layout/ErrorBoundary/ErrorBoundary.tsx b/packages/core/src/layout/ErrorBoundary/ErrorBoundary.tsx index 17900ad8e3..88784dc8b0 100644 --- a/packages/core/src/layout/ErrorBoundary/ErrorBoundary.tsx +++ b/packages/core/src/layout/ErrorBoundary/ErrorBoundary.tsx @@ -26,6 +26,21 @@ type State = { errorInfo?: ErrorInfo; }; +type EProps = { + error?: Error; + slackChannel?: string; + children?: React.ReactNode; +}; + +const Error = ({ slackChannel }: EProps) => { + return ( +
+ Something went wrong here.{' '} + {slackChannel && <>Please contact {slackChannel} for help.} +
+ ); +}; + export const ErrorBoundary: ComponentClass< Props, State @@ -56,18 +71,3 @@ export const ErrorBoundary: ComponentClass< return ; } }; - -type EProps = { - error?: Error; - slackChannel?: string; - children?: React.ReactNode; -}; - -const Error = ({ slackChannel }: EProps) => { - return ( -
- Something went wrong here.{' '} - {slackChannel && <>Please contact {slackChannel} for help.} -
- ); -}; diff --git a/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx b/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx index 55fa056e59..9f7973c387 100644 --- a/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx @@ -20,25 +20,6 @@ import { } from '@backstage/core'; import { SidebarSearch } from '@backstage/plugin-search'; -export const AppSidebar = () => ( - - - - - {/* Global nav, not org-specific */} - - - - - - - {/* End global nav */} - - - - - -); const useSidebarLogoStyles = makeStyles({ root: { @@ -72,3 +53,23 @@ const SidebarLogo = () => { ); }; + +export const AppSidebar = () => ( + + + + + {/* Global nav, not org-specific */} + + + + + + + {/* End global nav */} + + + + + +); diff --git a/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx b/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx index 18ae5a2d04..32b82eb206 100644 --- a/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx +++ b/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx @@ -99,18 +99,6 @@ const pickClassName = ( return classes.neutral; }; -const BuildsList = ({ build }: { build?: BuildWithSteps }) => ( - - {build && - build.steps && - build.steps.map( - ({ name, actions }: { name: string; actions: BuildStepAction[] }) => ( - - ), - )} - -); - const ActionsList = ({ actions, }: { @@ -132,6 +120,18 @@ const ActionsList = ({ ); }; +const BuildsList = ({ build }: { build?: BuildWithSteps }) => ( + + {build && + build.steps && + build.steps.map( + ({ name, actions }: { name: string; actions: BuildStepAction[] }) => ( + + ), + )} + +); + export const BuildWithStepsPage = () => { const { buildId = '' } = useParams(); const classes = useStyles(); diff --git a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx index 5e6de017d1..b3c5be94ba 100644 --- a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx +++ b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx @@ -31,16 +31,6 @@ type CostInsightsHeaderProps = { alerts: number; }; -export const CostInsightsHeader = (props: CostInsightsHeaderProps) => { - if (!props.hasCostData) { - return ; - } - if (props.alerts) { - return ; - } - return ; -}; - const CostInsightsHeaderNoData = ({ owner, groups, @@ -132,3 +122,13 @@ export const CostInsightsHeaderNoGroups = () => { ); }; + +export const CostInsightsHeader = (props: CostInsightsHeaderProps) => { + if (!props.hasCostData) { + return ; + } + if (props.alerts) { + return ; + } + return ; +}; diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx index a30b6c5a90..5a25216909 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx @@ -39,6 +39,24 @@ type CostInsightsNavigationProps = { products: Maybe; }; +const NavigationMenuItem = ({ navigation, icon, title }: NavigationItem) => { + const classes = useStyles(); + const { scrollIntoView } = useScroll(navigation); + return ( + + {icon} + {title}} + /> + + ); +}; + export const CostInsightsNavigation = React.memo( ({ alerts, products }: CostInsightsNavigationProps) => { const classes = useStyles(); @@ -102,21 +120,3 @@ export const CostInsightsNavigation = React.memo( ); }, ); - -const NavigationMenuItem = ({ navigation, icon, title }: NavigationItem) => { - const classes = useStyles(); - const { scrollIntoView } = useScroll(navigation); - return ( - - {icon} - {title}} - /> - - ); -}; diff --git a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx index 8503210c5e..7bcdb1f9bc 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx +++ b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx @@ -72,26 +72,6 @@ const useStyles = makeStyles(theme => ({ }, })); -const JobsList = ({ jobs, entity }: { jobs?: Jobs; entity: Entity }) => { - const classes = useStyles(); - return ( - - {jobs && - jobs.total_count > 0 && - jobs.jobs.map(job => ( - - ))} - - ); -}; - const getElapsedTime = (start: string, end: string) => { const diff = moment(moment(end || moment()).diff(moment(start))); const timeElapsed = diff.format('m [minutes] s [seconds]'); @@ -159,6 +139,26 @@ const JobListItem = ({ ); }; +const JobsList = ({ jobs, entity }: { jobs?: Jobs; entity: Entity }) => { + const classes = useStyles(); + return ( + + {jobs && + jobs.total_count > 0 && + jobs.jobs.map(job => ( + + ))} + + ); +}; + export const WorkflowRunDetails = ({ entity }: { entity: Entity }) => { const config = useApi(configApiRef); const projectName = useProjectName(entity); diff --git a/plugins/jenkins/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx b/plugins/jenkins/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx index 637cd40d6d..d8f728bb27 100644 --- a/plugins/jenkins/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx +++ b/plugins/jenkins/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx @@ -47,12 +47,6 @@ const useStyles = makeStyles(theme => ({ }, })); -const Page = () => ( - - - -); - const BuildWithStepsView = () => { const { owner, repo } = useProjectSlugFromEntity(); const { branch, buildNumber } = useParams(); @@ -129,6 +123,11 @@ const BuildWithStepsView = () => { ); }; +const Page = () => ( + + + +); export default Page; export { BuildWithStepsView as BuildWithSteps }; diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx index c2bda7a895..e03a749185 100644 --- a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx +++ b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx @@ -43,67 +43,6 @@ type DeploymentsAccordionsProps = { children?: React.ReactNode; }; -export const DeploymentsAccordions = ({ - deploymentResources, - clusterPodNamesWithErrors, -}: DeploymentsAccordionsProps) => { - const isOwnedBy = ( - ownerReferences: V1OwnerReference[], - obj: V1Pod | V1ReplicaSet | V1Deployment, - ): boolean => { - return ownerReferences?.some(or => or.name === obj.metadata?.name); - }; - - return ( - - {deploymentResources.deployments.map((deployment, i) => ( - - {deploymentResources.replicaSets - // Filter out replica sets with no replicas - .filter(rs => rs.status && rs.status.replicas > 0) - // Find the replica sets this deployment owns - .filter(rs => - isOwnedBy(rs.metadata?.ownerReferences ?? [], deployment), - ) - .map((rs, j) => { - // Find the pods this replica set owns and render them in the table - const ownedPods = deploymentResources.pods.filter(pod => - isOwnedBy(pod.metadata?.ownerReferences ?? [], rs), - ); - - const matchingHpa = deploymentResources.horizontalPodAutoscalers.find( - (hpa: V1HorizontalPodAutoscaler) => { - return ( - (hpa.spec?.scaleTargetRef?.kind ?? '').toLowerCase() === - 'deployment' && - (hpa.spec?.scaleTargetRef?.name ?? '') === - (deployment.metadata?.name ?? 'unknown-deployment') - ); - }, - ); - - return ( - - - - ); - })} - - ))} - - ); -}; - type DeploymentAccordionProps = { deployment: V1Deployment; ownedPods: V1Pod[]; @@ -112,33 +51,6 @@ type DeploymentAccordionProps = { children?: React.ReactNode; }; -const DeploymentAccordion = ({ - deployment, - ownedPods, - matchingHpa, - clusterPodNamesWithErrors, -}: DeploymentAccordionProps) => { - const podsWithErrors = ownedPods.filter(p => - clusterPodNamesWithErrors.has(p.metadata?.name ?? ''), - ); - - return ( - - }> - - - - - - - ); -}; - type DeploymentSummaryProps = { deployment: V1Deployment; numberOfCurrentPods: number; @@ -219,3 +131,91 @@ const DeploymentSummary = ({ ); }; + +const DeploymentAccordion = ({ + deployment, + ownedPods, + matchingHpa, + clusterPodNamesWithErrors, +}: DeploymentAccordionProps) => { + const podsWithErrors = ownedPods.filter(p => + clusterPodNamesWithErrors.has(p.metadata?.name ?? ''), + ); + + return ( + + }> + + + + + + + ); +}; + +export const DeploymentsAccordions = ({ + deploymentResources, + clusterPodNamesWithErrors, +}: DeploymentsAccordionsProps) => { + const isOwnedBy = ( + ownerReferences: V1OwnerReference[], + obj: V1Pod | V1ReplicaSet | V1Deployment, + ): boolean => { + return ownerReferences?.some(or => or.name === obj.metadata?.name); + }; + + return ( + + {deploymentResources.deployments.map((deployment, i) => ( + + {deploymentResources.replicaSets + // Filter out replica sets with no replicas + .filter(rs => rs.status && rs.status.replicas > 0) + // Find the replica sets this deployment owns + .filter(rs => + isOwnedBy(rs.metadata?.ownerReferences ?? [], deployment), + ) + .map((rs, j) => { + // Find the pods this replica set owns and render them in the table + const ownedPods = deploymentResources.pods.filter(pod => + isOwnedBy(pod.metadata?.ownerReferences ?? [], rs), + ); + + const matchingHpa = deploymentResources.horizontalPodAutoscalers.find( + (hpa: V1HorizontalPodAutoscaler) => { + return ( + (hpa.spec?.scaleTargetRef?.kind ?? '').toLowerCase() === + 'deployment' && + (hpa.spec?.scaleTargetRef?.name ?? '') === + (deployment.metadata?.name ?? 'unknown-deployment') + ); + }, + ); + + return ( + + + + ); + })} + + ))} + + ); +}; diff --git a/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx b/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx index 21f66f28c0..e33ded1fac 100644 --- a/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx +++ b/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx @@ -86,29 +86,6 @@ const sortBySeverity = (a: DetectedError, b: DetectedError) => { return 0; }; -export const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => { - const errors = Array.from(detectedErrors.values()) - .flat() - .sort(sortBySeverity); - - return ( - <> - {errors.length === 0 ? ( - - - - ) : ( - - )} - - ); -}; - export const ErrorEmptyState = () => { return ( { ); }; + +export const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => { + const errors = Array.from(detectedErrors.values()) + .flat() + .sort(sortBySeverity); + + return ( + <> + {errors.length === 0 ? ( + + + + ) : ( +
+ )} + + ); +}; diff --git a/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx b/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx index a49f966ffd..6ecfa63e23 100644 --- a/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx +++ b/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx @@ -32,42 +32,10 @@ type IngressesAccordionsProps = { deploymentResources: GroupedResponses; }; -export const IngressesAccordions = ({ - deploymentResources, -}: IngressesAccordionsProps) => { - return ( - - {deploymentResources.ingresses.map((ingress, i) => ( - - - - ))} - - ); -}; - type IngressAccordionProps = { ingress: ExtensionsV1beta1Ingress; }; -const IngressAccordion = ({ ingress }: IngressAccordionProps) => { - return ( - - }> - - - - - - - ); -}; - type IngressSummaryProps = { ingress: ExtensionsV1beta1Ingress; }; @@ -99,3 +67,34 @@ const IngressCard = ({ ingress }: IngressCardProps) => { /> ); }; + +const IngressAccordion = ({ ingress }: IngressAccordionProps) => { + return ( + + }> + + + + + + + ); +}; +export const IngressesAccordions = ({ + deploymentResources, +}: IngressesAccordionsProps) => { + return ( + + {deploymentResources.ingresses.map((ingress, i) => ( + + + + ))} + + ); +}; diff --git a/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx b/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx index 092ada0724..18351c7455 100644 --- a/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx +++ b/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx @@ -50,6 +50,115 @@ import { DetectedError, detectErrors } from '../../error-detection'; import { IngressesAccordions } from '../IngressesAccordions'; import { ServicesAccordions } from '../ServicesAccordions'; +type ClusterSummaryProps = { + clusterName: string; + totalNumberOfPods: number; + numberOfPodsWithErrors: number; + children?: React.ReactNode; +}; + +const ClusterSummary = ({ + clusterName, + totalNumberOfPods, + numberOfPodsWithErrors, +}: ClusterSummaryProps) => { + return ( + + + + {clusterName} + + Cluster + + + + + + + + + {totalNumberOfPods} pods + + + {numberOfPodsWithErrors > 0 ? ( + {numberOfPodsWithErrors} pods with errors + ) : ( + No pods with errors + )} + + + + ); +}; + +type ClusterProps = { + clusterObjects: ClusterObjects; + detectedErrors?: DetectedError[]; + children?: React.ReactNode; +}; + +const Cluster = ({ clusterObjects, detectedErrors }: ClusterProps) => { + const groupedResponses = groupResponses(clusterObjects.resources); + + const podsWithErrors = new Set( + detectedErrors + ?.filter(de => de.kind === 'Pod') + .map(de => de.names) + .flat() ?? [], + ); + + return ( + <> + + }> + + + + + + + + + + + + + + + + + + + + ); +}; + type KubernetesContentProps = { entity: Entity; children?: React.ReactNode }; export const KubernetesContent = ({ entity }: KubernetesContentProps) => { @@ -161,112 +270,3 @@ export const KubernetesContent = ({ entity }: KubernetesContentProps) => { ); }; - -type ClusterProps = { - clusterObjects: ClusterObjects; - detectedErrors?: DetectedError[]; - children?: React.ReactNode; -}; - -const Cluster = ({ clusterObjects, detectedErrors }: ClusterProps) => { - const groupedResponses = groupResponses(clusterObjects.resources); - - const podsWithErrors = new Set( - detectedErrors - ?.filter(de => de.kind === 'Pod') - .map(de => de.names) - .flat() ?? [], - ); - - return ( - <> - - }> - - - - - - - - - - - - - - - - - - - - ); -}; - -type ClusterSummaryProps = { - clusterName: string; - totalNumberOfPods: number; - numberOfPodsWithErrors: number; - children?: React.ReactNode; -}; - -const ClusterSummary = ({ - clusterName, - totalNumberOfPods, - numberOfPodsWithErrors, -}: ClusterSummaryProps) => { - return ( - - - - {clusterName} - - Cluster - - - - - - - - - {totalNumberOfPods} pods - - - {numberOfPodsWithErrors > 0 ? ( - {numberOfPodsWithErrors} pods with errors - ) : ( - No pods with errors - )} - - - - ); -}; diff --git a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx b/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx index 8deb49bf07..ee4de96177 100644 --- a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx +++ b/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx @@ -77,65 +77,6 @@ interface KubernetesDrawerable { metadata?: V1ObjectMeta; } -interface KubernetesDrawerProps { - object: T; - renderObject: (obj: T) => object; - buttonVariant?: 'h5' | 'subtitle2'; - kind: string; - expanded?: boolean; - children?: React.ReactNode; -} - -export const KubernetesDrawer = ({ - object, - renderObject, - kind, - buttonVariant = 'subtitle2', - expanded = false, - children, -}: KubernetesDrawerProps) => { - const [isOpen, setIsOpen] = useState(expanded); - const classes = useDrawerStyles(); - - const toggleDrawer = (e: ChangeEvent<{}>, newValue: boolean) => { - e.stopPropagation(); - setIsOpen(newValue); - }; - - return ( - <> - toggleDrawer(e, true)} - onFocus={event => event.stopPropagation()} - > - {children === undefined ? ( - - {object.metadata?.name ?? 'unknown object'} - - ) : ( - children - )} - - toggleDrawer(e, false)} - onClick={event => event.stopPropagation()} - > - - - - ); -}; - interface KubernetesDrawerContentProps { toggleDrawer: (e: ChangeEvent<{}>, isOpen: boolean) => void; object: T; @@ -203,3 +144,61 @@ const KubernetesDrawerContent = ({ ); }; +interface KubernetesDrawerProps { + object: T; + renderObject: (obj: T) => object; + buttonVariant?: 'h5' | 'subtitle2'; + kind: string; + expanded?: boolean; + children?: React.ReactNode; +} + +export const KubernetesDrawer = ({ + object, + renderObject, + kind, + buttonVariant = 'subtitle2', + expanded = false, + children, +}: KubernetesDrawerProps) => { + const [isOpen, setIsOpen] = useState(expanded); + const classes = useDrawerStyles(); + + const toggleDrawer = (e: ChangeEvent<{}>, newValue: boolean) => { + e.stopPropagation(); + setIsOpen(newValue); + }; + + return ( + <> + toggleDrawer(e, true)} + onFocus={event => event.stopPropagation()} + > + {children === undefined ? ( + + {object.metadata?.name ?? 'unknown object'} + + ) : ( + children + )} + + toggleDrawer(e, false)} + onClick={event => event.stopPropagation()} + > + + + + ); +}; diff --git a/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx b/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx index 6484f2211d..c378f02658 100644 --- a/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx +++ b/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx @@ -29,46 +29,6 @@ import { V1Service } from '@kubernetes/client-node'; import { StructuredMetadataTable } from '@backstage/core'; import { ServiceDrawer } from './ServiceDrawer'; -type ServicesAccordionsProps = { - deploymentResources: GroupedResponses; -}; - -export const ServicesAccordions = ({ - deploymentResources, -}: ServicesAccordionsProps) => { - return ( - - {deploymentResources.services.map((service, i) => ( - - - - ))} - - ); -}; - -type ServiceAccordionProps = { - service: V1Service; -}; - -const ServiceAccordion = ({ service }: ServiceAccordionProps) => { - return ( - - }> - - - - - - - ); -}; - type ServiceSummaryProps = { service: V1Service; }; @@ -121,3 +81,43 @@ const ServiceCard = ({ service }: ServiceCardProps) => { /> ); }; + +type ServicesAccordionsProps = { + deploymentResources: GroupedResponses; +}; + +type ServiceAccordionProps = { + service: V1Service; +}; + +const ServiceAccordion = ({ service }: ServiceAccordionProps) => { + return ( + + }> + + + + + + + ); +}; + +export const ServicesAccordions = ({ + deploymentResources, +}: ServicesAccordionsProps) => { + return ( + + {deploymentResources.services.map((service, i) => ( + + + + ))} + + ); +}; diff --git a/yarn.lock b/yarn.lock index f6762a63f0..e8cddda224 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2413,7 +2413,7 @@ to-fast-properties "^2.0.0" "@backstage/catalog-model@^0.2.0": - version "0.6.1" + version "0.7.0" dependencies: "@backstage/config" "^0.1.2" "@types/json-schema" "^7.0.5" @@ -2424,7 +2424,7 @@ yup "^0.29.3" "@backstage/catalog-model@^0.3.0": - version "0.6.1" + version "0.7.0" dependencies: "@backstage/config" "^0.1.2" "@types/json-schema" "^7.0.5" @@ -2435,7 +2435,7 @@ yup "^0.29.3" "@backstage/core@^0.3.0": - version "0.4.4" + version "0.5.0" dependencies: "@backstage/config" "^0.1.2" "@backstage/core-api" "^0.2.8" @@ -6440,11 +6440,6 @@ dependencies: "@types/node" "*" -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - "@types/eslint@*": version "6.1.8" resolved "https://registry.npmjs.org/@types/eslint/-/eslint-6.1.8.tgz#7e868f89bc1e520323d405940e49cb912ede5bba" @@ -7478,91 +7473,62 @@ resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== -"@typescript-eslint/eslint-plugin@^v3.10.1": - version "3.10.1" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" - integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== +"@typescript-eslint/eslint-plugin@^v4.14.0": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.0.tgz#92db8e7c357ed7d69632d6843ca70b71be3a721d" + integrity sha512-IJ5e2W7uFNfg4qh9eHkHRUCbgZ8VKtGwD07kannJvM5t/GU8P8+24NX8gi3Hf5jST5oWPY8kyV1s/WtfiZ4+Ww== dependencies: - "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/experimental-utils" "4.14.0" + "@typescript-eslint/scope-manager" "4.14.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" + lodash "^4.17.15" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@3.10.1": - version "3.10.1" - resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== +"@typescript-eslint/experimental-utils@4.14.0", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.0.tgz#5aa7b006736634f588a69ee343ca959cd09988df" + integrity sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" + "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/typescript-estree" "4.14.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/experimental-utils@^4.0.1": - version "4.4.1" - resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.4.1.tgz#40613b9757fa0170de3e0043254dbb077cafac0c" - integrity sha512-Nt4EVlb1mqExW9cWhpV6pd1a3DkUbX9DeyYsdoeziKOpIJ04S2KMVDO+SEidsXRH/XHDpbzXykKcMTLdTXH6cQ== +"@typescript-eslint/parser@^v4.14.0": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.14.0.tgz#62d4cd2079d5c06683e9bfb200c758f292c4dee7" + integrity sha512-sUDeuCjBU+ZF3Lzw0hphTyScmDDJ5QVkyE21pRoBo8iDl7WBtVFS+WDN3blY1CH3SBt7EmYCw6wfmJjF0l/uYg== dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.4.1" - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/typescript-estree" "4.4.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@^v3.10.1": - version "3.10.1" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" - integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.1" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/scope-manager@4.4.1": - version "4.4.1" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.4.1.tgz#d19447e60db2ce9c425898d62fa03b2cce8ea3f9" - integrity sha512-2oD/ZqD4Gj41UdFeWZxegH3cVEEH/Z6Bhr/XvwTtGv66737XkR4C9IqEkebCuqArqBJQSj4AgNHHiN1okzD/wQ== - dependencies: - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/visitor-keys" "4.4.1" - -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - -"@typescript-eslint/types@4.4.1": - version "4.4.1" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.4.1.tgz#c507b35cf523bc7ba00aae5f75ee9b810cdabbc1" - integrity sha512-KNDfH2bCyax5db+KKIZT4rfA8rEk5N0EJ8P0T5AJjo5xrV26UAzaiqoJCxeaibqc0c/IvZxp7v2g3difn2Pn3w== - -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" + "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/typescript-estree" "4.14.0" debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@4.4.1": - version "4.4.1" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.1.tgz#598f6de488106c2587d47ca2462c60f6e2797cb8" - integrity sha512-wP/V7ScKzgSdtcY1a0pZYBoCxrCstLrgRQ2O9MmCUZDtmgxCO/TCqOTGRVwpP4/2hVfqMz/Vw1ZYrG8cVxvN3g== +"@typescript-eslint/scope-manager@4.14.0": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.14.0.tgz#55a4743095d684e1f7b7180c4bac2a0a3727f517" + integrity sha512-/J+LlRMdbPh4RdL4hfP1eCwHN5bAhFAGOTsvE6SxsrM/47XQiPSgF5MDgLyp/i9kbZV9Lx80DW0OpPkzL+uf8Q== dependencies: - "@typescript-eslint/types" "4.4.1" - "@typescript-eslint/visitor-keys" "4.4.1" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/visitor-keys" "4.14.0" + +"@typescript-eslint/types@4.14.0": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.14.0.tgz#d8a8202d9b58831d6fd9cee2ba12f8a5a5dd44b6" + integrity sha512-VsQE4VvpldHrTFuVPY1ZnHn/Txw6cZGjL48e+iBxTi2ksa9DmebKjAeFmTVAYoSkTk7gjA7UqJ7pIsyifTsI4A== + +"@typescript-eslint/typescript-estree@4.14.0": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.0.tgz#4bcd67486e9acafc3d0c982b23a9ab8ac8911ed7" + integrity sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag== + dependencies: + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/visitor-keys" "4.14.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -7570,19 +7536,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== +"@typescript-eslint/visitor-keys@4.14.0": + version "4.14.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.0.tgz#b1090d9d2955b044b2ea2904a22496849acbdf54" + integrity sha512-MeHHzUyRI50DuiPgV9+LxcM52FCJFYjJiWHtXlbyC27b80mfOwKeiKI+MHOTEpcpfmoPFm/vvQS88bYIx6PZTA== dependencies: - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/visitor-keys@4.4.1": - version "4.4.1" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.1.tgz#1769dc7a9e2d7d2cfd3318b77ed8249187aed5c3" - integrity sha512-H2JMWhLaJNeaylSnMSQFEhT/S/FsJbebQALmoJxMPMxLtlVAMy2uJP/Z543n9IizhjRayLSqoInehCeNW9rWcw== - dependencies: - "@typescript-eslint/types" "4.4.1" + "@typescript-eslint/types" "4.14.0" eslint-visitor-keys "^2.0.0" "@webassemblyjs/ast@1.9.0":