Skip to content

Commit

Permalink
Merge pull request #4 from gimlet-io/enhancement/filter-bar
Browse files Browse the repository at this point in the history
Enhancement: Filter bar
  • Loading branch information
laszlocph authored Dec 28, 2023
2 parents 777c448 + 591d545 commit 3718ba5
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 34 deletions.
44 changes: 33 additions & 11 deletions web/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { rootReducer } from './redux';
import Footer from "./Footer";
import FilterBar from "./FilterBar";
import Services from "./Services";
import { useState, useEffect } from "react";

function App() {
const capacitorClient = new CapacitorClient(
Expand All @@ -15,6 +16,32 @@ function App() {
);

const store = createStore(rootReducer);
const [filters, setFilters] = useState(JSON.parse(localStorage.getItem("filters")) ?? [])

useEffect(() => {
localStorage.setItem("filters", JSON.stringify(filters));
}, [filters]);

const addFilter = (filter) => {
setFilters([...filters, filter]);
}

const filterValueByProperty = (property) => {
const filter = filters.find(f => f.property === property)
if (!filter) {
return ""
}

return filter.value
}

const deleteFilter = (filter) => {
setFilters(filters.filter(f => f.property !== filter.property))
}

const resetFilters = () => {
setFilters([])
}

return (
<>
Expand All @@ -23,20 +50,15 @@ function App() {
<div className="max-w-6xl mx-auto">
<div className="my-16">
<FilterBar
filters={[
{
property: "Owner",
value: "backend-team"
},
{
property: "App",
value: "*app*"
},
]}
filters={filters}
addFilter={addFilter}
deleteFilter={deleteFilter}
resetFilters={resetFilters}
filterValueByProperty={filterValueByProperty}
/>
</div>
<div className="grid grid-cols-1 gap-y-4 pb-32">
<Services store={store} />
<Services store={store} filters={filters} />
</div>
</div>
<Footer store={store} />
Expand Down
47 changes: 27 additions & 20 deletions web/src/FilterBar.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import React, { useState, useRef, useEffect } from 'react';
import { FunnelIcon, XMarkIcon } from '@heroicons/react/24/outline'

function FilterBar(props) {
function FilterBar({ filters, addFilter, deleteFilter, resetFilters, filterValueByProperty }) {
return (
<div className="w-full">
<div className="relative">
<div className="absolute inset-y-0 left-0 flex items-center pl-3">
<FunnelIcon className="h-5 w-5 text-neutral-400" aria-hidden="true" />
{props.filters.map(filter => (
<Filter key={filter.property + filter.value} filter={filter} deleteFilter={props.deleteFilter} />
{filters.map(filter => (
<Filter key={filter.property + filter.value} filter={filter} deleteFilter={deleteFilter} />
))}
<FilterInput addFilter={props.addFilter} />
<FilterInput addFilter={addFilter} filterValueByProperty={filterValueByProperty} />
</div>
<div className="block w-full rounded-lg border-0 bg-white py-1.5 pl-10 pr-3 text-neutral-900 ring-1 ring-inset ring-neutral-300 placeholder:text-neutral-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
&nbsp;
</div>
<div className="absolute inset-y-0 right-0 flex items-center p-1">
<button onClick={resetFilters} className="py-1 px-2 bg-gray-200 text-gray-400 rounded-full text-sm">reset</button>
</div>
</div>
</div>
)
Expand All @@ -38,8 +41,8 @@ function FilterInput(props) {
const [active, setActive] = useState(false)
const [property, setProperty] = useState("")
const [value, setValue] = useState("")
const properties=["Repository", "Service", "Namespace", "Owner", "Starred", "Domain"]
const { addFilter } = props;
const properties=["Service", "Namespace", "Owner", "Domain"]
const { addFilter, filterValueByProperty } = props;
const inputRef = useRef(null);

const reset = () => {
Expand Down Expand Up @@ -73,7 +76,7 @@ function FilterInput(props) {
setActive(false);
if (value !== "") {
if (property === "") {
addFilter({property: "Repository", value: value})
addFilter({property: "Service", value: value})
} else {
addFilter({property, value})
}
Expand All @@ -89,7 +92,7 @@ function FilterInput(props) {
if (e.keyCode === 13){
setActive(false)
if (property === "") {
addFilter({property: "Repository", value: value})
addFilter({property: "Service", value: value})
} else {
addFilter({property, value})
}
Expand All @@ -104,18 +107,22 @@ function FilterInput(props) {
/>
</span>
{active && property === "" &&
<div className="z-10 absolute bg-blue-100 w-48 p-2 text-blue-800">
<ul className="">
{properties.map(p => (
<li
key={p}
className="cursor-pointer hover:bg-blue-200"
onClick={() => {setProperty(p); setActive(false); }}>
{p}
</li>
))}
</ul>
</div>
<div className="z-10 absolute bg-blue-100 w-48 p-2 text-blue-800">
<ul className="">
{properties.map(p => {
if (filterValueByProperty(p) !== "") {
return null;
}

return (<li
key={p}
className="cursor-pointer hover:bg-blue-200"
onClick={() => { setProperty(p); setActive(false); }}>
{p}
</li>)
})}
</ul>
</div>
}
</span>
)
Expand Down
28 changes: 25 additions & 3 deletions web/src/Services.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import React, { memo, useState } from 'react';
import Service from "./Service";

const Services = memo(function Services(props) {
const { store } = props

const { store, filters } = props
const [services, setServices] = useState(store.getState().services);
store.subscribe(() => setServices(store.getState().services))
const filteredServices = filterServices(services, filters)

return (
<>
{services.map((service) => {
{filteredServices.map((service) => {
return (
<Service key={`${service.svc.metadata.namespace}/${service.svc.metadata.name}`} service={service} alerts={[]} />
)
Expand All @@ -19,3 +19,25 @@ const Services = memo(function Services(props) {
})

export default Services;

const filterServices = (services, filters) => {
let filteredServices = services;
filters.forEach(filter => {
switch (filter.property) {
case 'Service':
filteredServices = filteredServices.filter(service => service.svc.metadata.name.includes(filter.value))
break;
case 'Namespace':
filteredServices = filteredServices.filter(service => service.svc.metadata.namespace.includes(filter.value))
break;
case 'Owner':
filteredServices = filteredServices.filter(service => service.osca && service.osca.owner.includes(filter.value))
break;
case 'Domain':
filteredServices = filteredServices.filter(service => service.ingresses && service.ingresses.some(ingress => ingress.url.includes(filter.value)))
break;
default:
}
})
return filteredServices;
}

0 comments on commit 3718ba5

Please sign in to comment.