mirror of
				https://github.com/tormachris/cf-workers-status-page.git
				synced 2025-11-04 12:56:24 +01:00 
			
		
		
		
	feat: add monitor filter field
This commit is contained in:
		@@ -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"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										42
									
								
								src/components/monitorFilter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/components/monitorFilter.js
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								yarn.lock
									
									
									
									
									
								
							@@ -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"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user