From c1ef70139518f6e6058943bf380fa971bf6f2203 Mon Sep 17 00:00:00 2001
From: lmejbar <42239917+lmejbar@users.noreply.github.com>
Date: Fri, 20 Aug 2021 15:45:01 +0200
Subject: [PATCH] Added SearchBar and ScrollBar on Techradar
Signed-off-by: lmejbar <42239917+lmejbar@users.noreply.github.com>
---
.changeset/late-news-chew.md | 6 ++
.../InputTextFilter/InputTextFilter.test.tsx | 64 +++++++++++++++++++
.../InputTextFilter/InputTextFilter.tsx | 60 +++++++++++++++++
.../src/components/InputTextFilter/index.ts | 17 +++++
.../core-components/src/components/index.ts | 1 +
.../src/layout/Content/Content.tsx | 2 +-
.../layout/ContentHeader/ContentHeader.tsx | 1 +
plugins/tech-radar/src/api.ts | 1 +
.../src/components/RadarComponent.tsx | 20 +++++-
.../components/RadarLegend/RadarLegend.tsx | 12 +++-
.../tech-radar/src/components/RadarPage.tsx | 12 +++-
11 files changed, 189 insertions(+), 7 deletions(-)
create mode 100644 .changeset/late-news-chew.md
create mode 100644 packages/core-components/src/components/InputTextFilter/InputTextFilter.test.tsx
create mode 100644 packages/core-components/src/components/InputTextFilter/InputTextFilter.tsx
create mode 100644 packages/core-components/src/components/InputTextFilter/index.ts
diff --git a/.changeset/late-news-chew.md b/.changeset/late-news-chew.md
new file mode 100644
index 0000000000..cde2063ea9
--- /dev/null
+++ b/.changeset/late-news-chew.md
@@ -0,0 +1,6 @@
+---
+'@backstage/core-components': minor
+'@backstage/plugin-tech-radar': minor
+---
+
+Added SearchBar to allow filtering and a scrollbar to display hidden tech
diff --git a/packages/core-components/src/components/InputTextFilter/InputTextFilter.test.tsx b/packages/core-components/src/components/InputTextFilter/InputTextFilter.test.tsx
new file mode 100644
index 0000000000..35be191cde
--- /dev/null
+++ b/packages/core-components/src/components/InputTextFilter/InputTextFilter.test.tsx
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import {
+ render,
+ act,
+ RenderResult,
+ waitFor,
+ fireEvent,
+ screen,
+} from '@testing-library/react';
+import { wrapInTestApp, renderInTestApp } from '@backstage/test-utils';
+import { InputTextFilter } from './InputTextFilter';
+
+const SUPPORT_BUTTON_ID = 'support-button';
+const POPOVER_ID = 'support-button-popover';
+
+describe('', () => {
+ // it('renders without exploding', async () => {
+ // let renderResult: RenderResult;
+ // await act(async () => {
+ // renderResult = render(wrapInTestApp());
+ // });
+ // await waitFor(() =>
+ // expect(renderResult.getByTestId(SUPPORT_BUTTON_ID)).toBeInTheDocument(),
+ // );
+ // });
+ // it('supports passing a title', async () => {
+ // await renderInTestApp();
+ // fireEvent.click(screen.getByTestId(SUPPORT_BUTTON_ID));
+ // expect(screen.getByText('Custom title')).toBeInTheDocument();
+ // });
+ // it('shows popover on click', async () => {
+ // let renderResult: RenderResult;
+ // await act(async () => {
+ // renderResult = render(wrapInTestApp());
+ // });
+ // let button: HTMLElement;
+ // await waitFor(() => {
+ // expect(renderResult.getByTestId(SUPPORT_BUTTON_ID)).toBeInTheDocument();
+ // button = renderResult.getByTestId(SUPPORT_BUTTON_ID);
+ // });
+ // await act(async () => {
+ // fireEvent.click(button);
+ // });
+ // await waitFor(() => {
+ // expect(renderResult.getByTestId(POPOVER_ID)).toBeInTheDocument();
+ // });
+ // });
+});
diff --git a/packages/core-components/src/components/InputTextFilter/InputTextFilter.tsx b/packages/core-components/src/components/InputTextFilter/InputTextFilter.tsx
new file mode 100644
index 0000000000..814efeccc6
--- /dev/null
+++ b/packages/core-components/src/components/InputTextFilter/InputTextFilter.tsx
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import TextField from '@material-ui/core/TextField';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ '& > *': {
+ width: '50ch',
+ 'margin-right': '40ch',
+ 'margin-bottom': '1ch',
+ },
+ },
+}));
+
+export const InputTextFilter = ({
+ searchCategory,
+}: {
+ searchCategory: any;
+}) => {
+ const classes = useStyles();
+
+ const [, setSearchCategory] = React.useState('');
+
+ const setSearchCategoryValue = event => {
+ setSearchCategory(event.target.value);
+ };
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
diff --git a/packages/core-components/src/components/InputTextFilter/index.ts b/packages/core-components/src/components/InputTextFilter/index.ts
new file mode 100644
index 0000000000..42896a9d30
--- /dev/null
+++ b/packages/core-components/src/components/InputTextFilter/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { InputTextFilter } from './InputTextFilter';
diff --git a/packages/core-components/src/components/index.ts b/packages/core-components/src/components/index.ts
index 3c9376a894..73d04dccb7 100644
--- a/packages/core-components/src/components/index.ts
+++ b/packages/core-components/src/components/index.ts
@@ -28,6 +28,7 @@ export * from './ResponseErrorPanel';
export * from './FeatureDiscovery';
export * from './HeaderIconLinkRow';
export * from './HorizontalScrollGrid';
+export * from './InputTextFilter';
export * from './Lifecycle';
export * from './Link';
export * from './MarkdownContent';
diff --git a/packages/core-components/src/layout/Content/Content.tsx b/packages/core-components/src/layout/Content/Content.tsx
index a3771dff3f..ae8259a315 100644
--- a/packages/core-components/src/layout/Content/Content.tsx
+++ b/packages/core-components/src/layout/Content/Content.tsx
@@ -22,7 +22,7 @@ const useStyles = makeStyles((theme: Theme) => ({
root: {
gridArea: 'pageContent',
minWidth: 0,
- paddingTop: theme.spacing(3),
+ paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(3),
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx
index 76fec703a9..99260c626d 100644
--- a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx
+++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx
@@ -53,6 +53,7 @@ const useStyles = (props: ContentHeaderProps) =>
title: {
display: 'inline-flex',
marginBottom: 0,
+ color: '#0082C3',
},
}));
diff --git a/plugins/tech-radar/src/api.ts b/plugins/tech-radar/src/api.ts
index 34307a1697..2497834e22 100644
--- a/plugins/tech-radar/src/api.ts
+++ b/plugins/tech-radar/src/api.ts
@@ -81,4 +81,5 @@ export interface TechRadarComponentProps {
width: number;
height: number;
svgProps?: object;
+ searchText?: string;
}
diff --git a/plugins/tech-radar/src/components/RadarComponent.tsx b/plugins/tech-radar/src/components/RadarComponent.tsx
index faa2763f17..88c865f999 100644
--- a/plugins/tech-radar/src/components/RadarComponent.tsx
+++ b/plugins/tech-radar/src/components/RadarComponent.tsx
@@ -45,13 +45,29 @@ const useTechRadarLoader = (id: string | undefined) => {
return { loading, value, error };
};
-const RadarComponent = (props: TechRadarComponentProps): JSX.Element => {
+const RadarComponent = (
+ props: TechRadarComponentProps,
+ searchText: string,
+): JSX.Element => {
const { loading, error, value: data } = useTechRadarLoader(props.id);
const mapToEntries = (
loaderResponse: TechRadarLoaderResponse | undefined,
): Array => {
- return loaderResponse!.entries.map(entry => {
+ let filteredArray = loaderResponse!.entries;
+ if (!(props.searchText === '')) {
+ // Compare the name or the description with the search input text
+ filteredArray = loaderResponse!.entries.filter(
+ element =>
+ element.title
+ .toLowerCase()
+ .includes(props.searchText.toLowerCase()) ||
+ element.timeline[0].description
+ ?.toLowerCase()
+ .includes(props.searchText.toLowerCase()),
+ );
+ }
+ return filteredArray.map(entry => {
return {
id: entry.key,
quadrant: loaderResponse!.quadrants.find(q => q.id === entry.quadrant)!,
diff --git a/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx b/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx
index b9bc6a59a6..92fb5de9b8 100644
--- a/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx
+++ b/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx
@@ -32,21 +32,25 @@ export type Props = {
};
const useStyles = makeStyles(theme => ({
+ foreignObject: {
+ overflowY: 'visible',
+ },
quadrant: {
height: '100%',
width: '100%',
- overflow: 'hidden',
+ overflowY: 'visible',
pointerEvents: 'none',
},
quadrantHeading: {
pointerEvents: 'none',
userSelect: 'none',
+ color: '#0082C3',
marginTop: 0,
marginBottom: theme.spacing(8 / (18 * 0.375)),
fontSize: '18px',
},
rings: {
- columns: 3,
+ columns: 2,
},
ring: {
breakInside: 'avoid-column',
@@ -66,6 +70,9 @@ const useStyles = makeStyles(theme => ({
listStylePosition: 'inside',
marginTop: 0,
paddingLeft: 0,
+ height: '100%',
+ width: '100%',
+ overflow: 'scroll',
fontVariantNumeric: 'proportional-nums',
'-moz-font-feature-settings': 'pnum',
'-webkit-font-feature-settings': 'pnum',
@@ -221,6 +228,7 @@ const RadarLegend = (props: Props): JSX.Element => {
y={quadrant.legendY}
width={quadrant.legendWidth}
height={quadrant.legendHeight}
+ className={classes.foreignObject}
data-testid="radar-quadrant"
>
diff --git a/plugins/tech-radar/src/components/RadarPage.tsx b/plugins/tech-radar/src/components/RadarPage.tsx
index 2393ccc9c6..a332fd63c3 100644
--- a/plugins/tech-radar/src/components/RadarPage.tsx
+++ b/plugins/tech-radar/src/components/RadarPage.tsx
@@ -24,6 +24,7 @@ import {
Page,
Header,
SupportButton,
+ InputTextFilter,
} from '@backstage/core-components';
const useStyles = makeStyles(() => ({
@@ -45,11 +46,18 @@ export const RadarPage = ({
...props
}: TechRadarPageProps): JSX.Element => {
const classes = useStyles();
+ const [searchText, setSearchText] = React.useState('');
+
+ const searchInput = event => {
+ setSearchText(event.target.value);
+ };
+
return (
-
+ {/* */}
+
This is used for visualizing the official guidelines of different
areas of software development such as languages, frameworks,
@@ -58,7 +66,7 @@ export const RadarPage = ({
-
+