Skip to content

Commit

Permalink
Merge pull request #1 from gimlet-io/flux-state-in-footer
Browse files Browse the repository at this point in the history
Flux state in footer
  • Loading branch information
laszlocph committed Nov 2, 2023
2 parents 4b87606 + 1eebfd3 commit d9e4807
Show file tree
Hide file tree
Showing 9 changed files with 710 additions and 41 deletions.
61 changes: 56 additions & 5 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@heroicons/react": "^2.0.18",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.5.1",
"date-fns": "^2.30.0",
"jsonpath": "^1.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
55 changes: 51 additions & 4 deletions web/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import StreamingBackend from "./streamingBackend";
import CapacitorClient from "./client";
import { createStore } from 'redux'
import { rootReducer } from './redux';
import FluxState from "./FluxState";
import Footer from "./Footer";
import Service from "./Service";
import FilterBar from "./FilterBar";

function App() {
const capacitorClient = new CapacitorClient(
Expand All @@ -13,15 +15,60 @@ function App() {
);

const store = createStore(rootReducer);
// store.subscribe(() => console.log(store.getState()))

return (
<>
<APIBackend capacitorClient={capacitorClient} store={store}/>
<StreamingBackend capacitorClient={capacitorClient} store={store}/>
<div className="App">
<FluxState store={store}/>
<div className="max-w-6xl mx-auto">
<div className="my-16">
<FilterBar
filters={[
{
property: "Owner",
value: "backend-team"
},
{
property: "App",
value: "*app*"
},
]}
/>
</div>
<div className="grid grid-cols-1 gap-y-4">
<Service
stack={{
deployment: {
pods: [
{name: "xxx", status: "Running"},
{name: "xxx", status: "Running"}
]
},
service: {
name: "my-app",
namespace: "default"
}
}}
alerts={[]}
/>
<Service
stack={{
deployment: {
pods: [
{name: "xxx", status: "Running"},
{name: "xxx", status: "Running"}
]
},
service: {
name: "your-app",
namespace: "default"
}
}}
alerts={[]}
/>
</div>
</div>
<Footer store={store} />
</>
);
}
Expand Down
122 changes: 122 additions & 0 deletions web/src/FilterBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import React, { useState, useRef, useEffect } from 'react';
import { FunnelIcon, XMarkIcon } from '@heroicons/react/24/outline'

function FilterBar(props) {
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} />
))}
<FilterInput addFilter={props.addFilter} />
</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>
</div>
)
}

export default FilterBar;

function Filter(props) {
const { filter } = props;
return (
<span className="ml-1 text-blue-50 bg-blue-600 rounded-full pl-3 pr-1" aria-hidden="true">
<span>{filter.property}</span>: <span>{filter.value}</span>
<span className="ml-1 px-1 bg-blue-400 rounded-full ">
<XMarkIcon className="cursor-pointer text-white inline h-3 w-3" aria-hidden="true" onClick={() => props.deleteFilter(filter)}/>
</span>
</span>
)
}

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 inputRef = useRef(null);

const reset = () => {
setActive(false)
setProperty("")
setValue("")
}

useEffect(() => {
if (property !== "") {
inputRef.current.focus();
}
});

return (
<span className="relative w-48 ml-2">
<span className="items-center flex">
{property !== "" &&
<span>{property}: </span>
}
<input
ref={inputRef}
key={property}
className={`${property ? "ml-10" : "" }block border-0 border-t border-b border-neutral-300 pt-1.5 pb-1 px-1 text-neutral-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6`}
placeholder='Enter Filter'
value={value}
onChange={(e) => setValue(e.target.value)}
onFocus={() => {setActive(true)}}
onBlur={() => {
setTimeout(() => {
setActive(false);
if (value !== "") {
if (property === "") {
addFilter({property: "Repository", value: value})
} else {
addFilter({property, value})
}
reset()
} else {
if (property !== "") {
reset()
}
}
}, 200);}
}
onKeyUp={(e) => {
if (e.keyCode === 13){
setActive(false)
if (property === "") {
addFilter({property: "Repository", value: value})
} else {
addFilter({property, value})
}
reset()
}
if (e.keyCode === 27){
reset()
// inputRef.current.blur();
}
}}
type="search"
/>
</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>
}
</span>
)
}
Loading

0 comments on commit d9e4807

Please sign in to comment.