-
-
- setSearch(event.target.value)}
- value={search}
- startAdornment={
-
-
-
- }
- endAdornment={
-
- setSearch('')}
- edge="end"
- disabled={search.length === 0}
- >
-
-
-
- }
- />
-
-
-
+
setSelectedSidebarItem(label)} // TODO: setSelecteSidebarItem
+ buttonGroups={filterGroups}
initiallySelected="all"
/>
- {!filteredTemplates && loading &&
}
- {filteredTemplates && !filteredTemplates.length && (
+ {!matchingEntities && loading &&
}
+ {matchingEntities && !matchingEntities.length && (
Shoot! Looks like you don't have any templates. Check out the
documentation{' '}
@@ -237,9 +177,9 @@ export const ScaffolderPageContents = () => {
)}
- {filteredTemplates &&
- filteredTemplates?.length > 0 &&
- filteredTemplates.map(template => {
+ {matchingEntities &&
+ matchingEntities?.length > 0 &&
+ matchingEntities.map(template => {
return (
{
+ it('should display search value and execute set callback', async () => {
+ const setSearchSpy = jest.fn();
+ const { getByDisplayValue } = render(
+ ,
+ );
+
+ const searchInput = getByDisplayValue('hello');
+ expect(searchInput).toBeInTheDocument();
+ fireEvent.change(searchInput, { target: { value: 'world' } });
+ expect(setSearchSpy).toHaveBeenCalled();
+ });
+});
diff --git a/plugins/scaffolder/src/components/SearchToolbar/SearchToolbar.tsx b/plugins/scaffolder/src/components/SearchToolbar/SearchToolbar.tsx
new file mode 100644
index 0000000000..4a50fcb257
--- /dev/null
+++ b/plugins/scaffolder/src/components/SearchToolbar/SearchToolbar.tsx
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 {
+ FormControl,
+ InputAdornment,
+ makeStyles,
+ Toolbar,
+ Input,
+ IconButton,
+} from '@material-ui/core';
+import Search from '@material-ui/icons/Search';
+import Clear from '@material-ui/icons/Clear';
+
+interface Props {
+ search: string;
+ setSearch: Function;
+}
+
+const useStyles = makeStyles(_theme => ({
+ searchToolbar: {
+ paddingLeft: 0,
+ paddingRight: 0,
+ },
+}));
+
+const SearchToolbar = ({ search, setSearch }: Props) => {
+ const styles = useStyles();
+ return (
+
+
+ setSearch(event.target.value)}
+ value={search}
+ startAdornment={
+
+
+
+ }
+ endAdornment={
+
+ setSearch('')}
+ edge="end"
+ disabled={search.length === 0}
+ >
+
+
+
+ }
+ />
+
+
+ );
+};
+
+export default SearchToolbar;
diff --git a/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx b/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx
index 1e5474f327..ba99a0294a 100644
--- a/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx
+++ b/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { Entity, TemplateEntityV1alpha1 } from '@backstage/catalog-model';
+import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { useApi } from '@backstage/core';
import { catalogApiRef } from '@backstage/plugin-catalog-react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
@@ -50,7 +50,7 @@ function useProvideEntityFilters(): FilterGroupsContext {
const response = await catalogApi.getEntities({
filter: { kind: 'Template' },
});
- return response.items;
+ return response.items as TemplateEntityV1alpha1[];
});
const filterGroups = useRef<{
@@ -63,7 +63,9 @@ function useProvideEntityFilters(): FilterGroupsContext {
const [filterGroupStates, setFilterGroupStates] = useState<{
[filterGroupId: string]: FilterGroupStates;
}>({});
- const [matchingEntities, setMatchingEntities] = useState([]);
+ const [filteredEntities, setFilteredEntities] = useState<
+ TemplateEntityV1alpha1[]
+ >([]);
const [availableCategories, setAvailableCategories] = useState([]);
const [isCatalogEmpty, setCatalogEmpty] = useState(false);
@@ -81,7 +83,7 @@ function useProvideEntityFilters(): FilterGroupsContext {
error,
),
);
- setMatchingEntities(
+ setFilteredEntities(
buildMatchingEntities(
filterGroups.current,
selectedFilterKeys.current,
@@ -146,7 +148,7 @@ function useProvideEntityFilters(): FilterGroupsContext {
loading: !error && !entities,
error,
filterGroupStates,
- matchingEntities,
+ filteredEntities,
availableCategories,
isCatalogEmpty,
};
@@ -158,7 +160,7 @@ function buildStates(
filterGroups: { [filterGroupId: string]: FilterGroup },
selectedFilterKeys: { [filterGroupId: string]: Set },
selectedCategories: string[],
- entities?: Entity[],
+ entities?: TemplateEntityV1alpha1[],
error?: Error,
): { [filterGroupId: string]: FilterGroupStates } {
// On error - all entries are an error state
@@ -205,7 +207,7 @@ function buildStates(
}
// Given all entites, find all possible categories and provide them in a sorted list.
-function collectCategories(entities?: Entity[]): string[] {
+function collectCategories(entities?: TemplateEntityV1alpha1[]): string[] {
const categories = new Set();
(entities || []).forEach(e => {
if (e.spec?.type) {
@@ -221,9 +223,9 @@ function buildMatchingEntities(
filterGroups: { [filterGroupId: string]: FilterGroup },
selectedFilterKeys: { [filterGroupId: string]: Set },
selectedCategories: string[],
- entities?: Entity[],
+ entities?: TemplateEntityV1alpha1[],
excludeFilterGroupId?: string,
-): Entity[] {
+): TemplateEntityV1alpha1[] {
// Build one filter fn per filter group
const allFilters: EntityFilterFn[] = [];
for (const [filterGroupId, filterGroup] of Object.entries(filterGroups)) {
diff --git a/plugins/scaffolder/src/filter/context.ts b/plugins/scaffolder/src/filter/context.ts
index e46ebb5507..f0a9d3755e 100644
--- a/plugins/scaffolder/src/filter/context.ts
+++ b/plugins/scaffolder/src/filter/context.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { Entity } from '@backstage/catalog-model';
+import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { createContext } from 'react';
import { FilterGroup, FilterGroupStates } from './types';
@@ -31,7 +31,7 @@ export type FilterGroupsContext = {
loading: boolean;
error?: Error;
filterGroupStates: { [filterGroupId: string]: FilterGroupStates };
- matchingEntities: Entity[];
+ filteredEntities: TemplateEntityV1alpha1[];
availableCategories: string[];
isCatalogEmpty: boolean;
};
diff --git a/plugins/scaffolder/src/filter/useFilteredEntities.ts b/plugins/scaffolder/src/filter/useFilteredEntities.ts
index cc2c739546..d3eb553687 100644
--- a/plugins/scaffolder/src/filter/useFilteredEntities.ts
+++ b/plugins/scaffolder/src/filter/useFilteredEntities.ts
@@ -29,7 +29,7 @@ export function useFilteredEntities() {
return {
loading: context.loading,
error: context.error,
- matchingEntities: context.matchingEntities,
+ filteredEntities: context.filteredEntities,
availableCategories: context.availableCategories,
isCatalogEmpty: context.isCatalogEmpty,
reload: context.reload,