Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add homepage #56

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
Database,
Circle,
X,
Home,
} from "lucide-react";

export type Icon = LucideIcon;
Expand Down Expand Up @@ -66,6 +67,7 @@ export const Icons = {
pizza: Pizza,
sun: SunMedium,
moon: Moon,
home: Home,
laptop: Laptop,
gitHub: ({ ...props }: LucideProps) => (
<svg
Expand Down
6 changes: 6 additions & 0 deletions src/constants/data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import {NavItem} from "@/components/dashboard-nav.tsx";

export const navItems: NavItem[] = [
{
title: "Home",
href: "/",
icon: "home",
label: "Home",
},
{
title: "Statistics",
href: "/statistics",
Expand Down
3 changes: 2 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {Statistics} from "@/pages/statistics.tsx";
import axios from "axios";
import {Instances} from "@/pages/instances.tsx";
import {Toaster} from "@/components/ui/toaster.tsx";
import {Home} from "@/pages/home.tsx";

const router = createHashRouter(createRoutesFromElements(
<Route element={<App/>}>
<Route index element={<Navigate to="/statistics"/>}/>
<Route index element={<Home/>}/>
<Route path="/statistics" element={<Statistics/>}/>
<Route path={"/instances"} element={<Instances/>}/>
</Route>
Expand Down
69 changes: 69 additions & 0 deletions src/pages/home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {useEffect, useState} from "react";
import axios, {AxiosResponse} from "axios";
import {ScrollArea, ScrollBar} from "@/components/ui/scroll-area.tsx";
import {Instance, InstancesResponse} from "@/types/InstancesResponse.ts";

export const Home = ()=>{
const [instances, setInstances] = useState<Instance[]>()

const hasFailures = (instance: Instance) : boolean => {
return instance.scan.db_reads_failed > 0 || instance.scan.db_writes_failed > 0
}

useEffect(() => {
axios.get("/instances")
.then((res: AxiosResponse<InstancesResponse>) => {
const topInstances : Instance[] = []
res.data.instances.forEach((instance) => {
if (instance.scan.is_public && instance.scan.websocket_available && !hasFailures(instance) && instance.name.startsWith('https://') && instance.scan.version.replaceAll(".", "") > "22") {
topInstances.push(instance)
}
})
topInstances.sort((a, b) => {
if (a.scan.mean_connects === null || b.scan.mean_connects === null) {
return 0
}

return a.scan.mean_connects < b.scan.mean_connects ? 1 : -1
})
setInstances(Array.from(topInstances))
})
}, [])

return (
<ScrollArea className="flex flex-col m-5 h-[99%]">
<h1 className="text-4xl font-bold mb-5">Welcome to Etherpad scanner</h1>
<p>The etherpad scanner scans the internet for running etherpad instances to get an overview of the etherpad eco system (based on the github project <a href="https://github.com/gared/ether-scan">ether-scan</a>.</p>
<p>This tool also allows you to get instant insights into your Etherpad instance. It is designed to quickly assess the configuration, health and security of your Etherpad setup.</p>
<br/>
<p>If you are looking for a public instance which you can quickly use you can find here a list of some public instances:</p>
<div className="grid grid-cols-1 gap-5">
<table className="w-full">
<thead>
<tr>
<th className="px-4 py-2">URL</th>
<th className="px-4 py-2">Plugins</th>
</tr>
</thead>
<tbody>
{instances && instances.length > 0 ?
<>
{instances.map((instance) => {
return (
<tr key={instance.name}>
<td className="border px-4 py-2 cursor-pointer" onClick={() => {
window.open(instance.name);
}}>{instance.name}</td>
<td className="border px-4 py-2">{instance.scan.plugins.join(', ')}</td>
</tr>
)
})}
</>
: <tr><td colSpan={2} className="text-center">Loading...</td></tr>}
</tbody>
</table>
</div>
<ScrollBar orientation="vertical"/>
</ScrollArea>
)
}
1 change: 1 addition & 0 deletions src/types/InstancesResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ScanResult = {
scan_time: string,
plugins: string[],
plugin_data: PluginData[],
mean_connects: number | null,
websocket_available: boolean | null,
db_reads_failed: number,
db_writes_failed: number,
Expand Down