1
0
mirror of https://github.com/tormachris/cf-workers-status-page.git synced 2024-09-21 05:03:02 +02:00

feat: add monitor filter field

This commit is contained in:
Alex 2020-11-17 00:50:19 +01:00
parent 9e178fe386
commit e2c6a6a538
5 changed files with 116 additions and 7 deletions

View File

@ -13,6 +13,8 @@
}, },
"dependencies": { "dependencies": {
"flareact": "^0.7.1", "flareact": "^0.7.1",
"laco": "^1.2.1",
"laco-react": "^1.1.0",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1" "react-dom": "^16.13.1"
}, },

View File

@ -5,11 +5,28 @@ import {
getLastUpdate, getLastUpdate,
getMonitors, getMonitors,
getMonitorsHistory, getMonitorsHistory,
useKeyPress,
} from '../src/functions/helpers' } from '../src/functions/helpers'
import config from '../config.yaml' import config from '../config.yaml'
import MonitorStatusLabel from '../src/components/monitorStatusLabel' import MonitorStatusLabel from '../src/components/monitorStatusLabel'
import MonitorStatusHeader from '../src/components/monitorStatusHeader' import MonitorStatusHeader from '../src/components/monitorStatusHeader'
import MonitorFilter from '../src/components/monitorFilter'
import { Store } from 'laco'
import { useStore } from 'laco-react'
const MonitorStore = new Store(
{
monitors: config.monitors,
visible: config.monitors,
activeFilter: false
}
)
const filterByTerm = (term) => MonitorStore.set(
state => ({ visible: state.monitors.filter((monitor) => monitor.name.toLowerCase().includes(term)) })
)
export async function getEdgeProps() { export async function getEdgeProps() {
// get KV data // get KV data
@ -50,6 +67,9 @@ export default function Index({
monitorsOperational, monitorsOperational,
kvLastUpdate, kvLastUpdate,
}) { }) {
const state = useStore(MonitorStore)
const slash = useKeyPress('/')
return ( return (
<div> <div>
<Head> <Head>
@ -62,18 +82,24 @@ export default function Index({
<link rel="stylesheet" href="./main.css" /> <link rel="stylesheet" href="./main.css" />
</Head> </Head>
<div className="ui basic segment container"> <div className="ui basic segment container">
<h1 className="ui huge title header"> <div className="horizontal flex between">
<h1 className="ui huge marginless title header">
<img <img
className="ui middle aligned tiny image" className="ui middle aligned tiny image"
src={config.settings.logo} src={config.settings.logo}
/> />
{config.settings.title} {config.settings.title}
</h1> </h1>
<MonitorFilter
active={slash}
callback={filterByTerm}
/>
</div>
<MonitorStatusHeader <MonitorStatusHeader
operational={monitorsOperational} operational={monitorsOperational}
lastUpdate={kvLastUpdate} lastUpdate={kvLastUpdate}
/> />
{config.monitors.map((monitor, key) => { {state.visible.map((monitor, key) => {
return ( return (
<div key={key} className="ui segment"> <div key={key} className="ui segment">
<div <div

View File

@ -0,0 +1,42 @@
import config from '../../config.yaml'
import { useState } from 'react'
export default function MonitorFilter({ active, callback }) {
const [input, setInput] = useState('')
const handleInput = (event) => {
// ignore focus trigger
if (event.target.value === '/') {
return
}
setInput(event.target.value)
callback(event.target.value)
}
const handleKeyDown = (event) => {
// blur input field on escape
if (event.keyCode === 27) {
event.target.blur()
}
}
return (
<div className="ui search">
<div className="ui icon input">
<input
className="prompt"
type="text"
value={input}
onInput={handleInput}
onKeyDown={handleKeyDown}
placeholder="Tap '/' to search"
tabIndex={0}
ref={
(e) => e && active && e.focus()
}
/>
<i className="search icon"></i>
</div>
</div>
)
}

View File

@ -1,4 +1,5 @@
import config from '../../config.yaml' import config from '../../config.yaml'
import {useEffect, useState} from 'react'
export async function getMonitors() { export async function getMonitors() {
const monitors = await listKV('s_') const monitors = await listKV('s_')
@ -115,3 +116,31 @@ export async function notifySlack(monitor, newMetadata) {
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
}) })
} }
export function useKeyPress(targetKey) {
const [keyPressed, setKeyPressed] = useState(false)
function downHandler({ key }) {
if (key === targetKey) {
setKeyPressed(true);
}
}
const upHandler = ({ key }) => {
if (key === targetKey) {
setKeyPressed(false);
}
}
useEffect(() => {
window.addEventListener('keydown', downHandler);
window.addEventListener('keyup', upHandler);
return () => {
window.removeEventListener('keydown', downHandler);
window.removeEventListener('keyup', upHandler);
};
}, [])
return keyPressed
}

View File

@ -3902,6 +3902,16 @@ kind-of@^6.0.0, kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
laco-react@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/laco-react/-/laco-react-1.1.0.tgz#8572117aabd245e9ff0000aab534c0f817da8238"
integrity sha512-RbN7dFUH7RsNpRMB46gWSjEMXo7WDhgkKl8HXpxn1o/bJItHj7FT0VsIWF963mrvORncIgI7bnZJ6KPcHV8fvA==
laco@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/laco/-/laco-1.2.1.tgz#4acf24ab4ea7b2983d10c2fd982208e96a315158"
integrity sha512-fw3vWTR1L/u/XTReyBQt3bnhylMLMqp+YoIFEr52bb9NqRnwPcvTQuFH0TRMyvg0Zucbx+eRViO4wxoij6xzDg==
last-call-webpack-plugin@^3.0.0: last-call-webpack-plugin@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555"