dashboard fixes

This commit is contained in:
Nicholas Orlowsky 2024-08-29 15:33:55 -05:00
parent 517f9bffe7
commit 35dd581969
Signed by: nickorlow
GPG key ID: 838827D8C4611687
9 changed files with 119 additions and 47 deletions

BIN
bun.lockb Executable file

Binary file not shown.

View file

@ -7,7 +7,7 @@ import './CreateCruisePage.css';
export default function CreateCruisePage() {
const [page, setPage] = useState('info');
const [strat, setStrat] = useState<'raw-html' | 'react-js'>('raw-html');
const [strat, setStrat] = useState<'raw-html' | 'react-js' | 'raw-html-anthracite' | 'docker' | 'default'>('default');
const [owner, setOwner] = useState('');
const [repo, setRepo] = useState('');
const [name, setName] = useState('');
@ -32,8 +32,8 @@ export default function CreateCruisePage() {
"serviceName": name,
"containerUrl": `ghcr.io/${owner}/${repo}`,
"namespaceId": search.get("namespaceId"),
"serviceUrl": hostUriInput,
"hostnammes": []
"serviceUrl": "https://"+hostUriInput,
"hostnames": []
})
}).then((response)=> {
if(response.status === 200) {
@ -84,10 +84,13 @@ export default function CreateCruisePage() {
<input value={name} onChange={(e)=>{setName(e.currentTarget.value)}}/>
<h5 className={"label-text"}>How did you create your website?</h5>
<h5 className={"label-text"}>Choose a Dockerfile template</h5>
<p className={"help-text"}>Don't see your technology/framework? Email me: <a href={"mailto:nws-support@nickorlow.com"}>nws-support@nickorlow.com</a></p>
<select value={strat}>
<option id={"raw-html"} onClick={()=>setStrat('raw-html')}>Raw HTML</option>
<select>
<option hidden>Select a template</option>
<option id={"raw-html"} onClick={()=>setStrat('docker')}>I already have a Dockerfile in the root of my repository</option>
<option id={"raw-html"} onClick={()=>setStrat('raw-html-anthracite')}>Raw HTML (with Anthracite Web Server, created by Nick)</option>
<option id={"raw-html"} onClick={()=>setStrat('raw-html')}>Raw HTML (with NGINX)</option>
<option id={"react-js"} onClick={()=>setStrat('react-js')}>React JS</option>
</select>
@ -113,7 +116,7 @@ export default function CreateCruisePage() {
setRepo(git_url.pathname.split('/')[2])
}
} catch (e) {
alert('invalid github url')
alert('Invalid GitHub URL. Should be of format https://github.com/owner/repo')
return;
}
@ -121,7 +124,7 @@ export default function CreateCruisePage() {
try {
let url = new URL("https://"+hostUriInput);
} catch (e) {
alert('invalid host url')
alert('Invalid domain! Should be format subdomain.domain.tld. Don\'t include protocols in front (i.e https://)')
return;
}
@ -138,10 +141,11 @@ export default function CreateCruisePage() {
page === 'scriptgen' &&
<div>
<h4>Copy & Paste the below into your terminal to add NWS deployment scripts to your webapp</h4>
<code lang={"shell"} style={{backgroundColor: "black", padding: 5, borderRadius: 10}}>
<code lang={"shell"} style={{backgroundColor: "#bbbbbb", padding: 5, borderRadius: 10}}>
curl -s https://raw.githubusercontent.com/nickorlow/nws-ghactions-templates/main/add-nws.sh | bash -s {strat} {owner} {repo}
</code>
<br/><span>Ensure the script finishes running before continuing</span>
<br/><span>For your security, you may view the source code of the script <a href="https://github.com/nickorlow/nws-ghactions-templates/blob/main/add-nws.sh" target="_blank">here</a></span>
<br/>
<button onClick={()=>setPage('framework-hostname')}>Back</button>
@ -173,7 +177,7 @@ export default function CreateCruisePage() {
new URI("https://"+hostUriInput).subdomain().length > 0 &&
<div>
<p>Type: CNAME</p>
<p>Name: {new URI(hostUriInput).subdomain()} ({new URI(hostUriInput).hostname()})</p>
<p>Name: {new URI("https://"+hostUriInput).subdomain()} ({new URI("https://"+hostUriInput).hostname()})</p>
<p>Value: entry.nws.nickorlow.com</p>
</div>
}
@ -184,9 +188,22 @@ export default function CreateCruisePage() {
{
page === 'done' &&
<div>
<h3>Welcome to NWS</h3> <br/>
<h3>Welcome to NWS!</h3> <br/>
<p>Your site should be avaliable on NWS momentairly</p> <br/>
<p>It would be great if you could add the following to your website:</p><br/>
<code lang={"html"} style={{ backgroundColor: "#bbbbbb", padding: 5, borderRadius: 10 }}>
&lt;p&gt;Hosting provided by &lt;a href="https://nws.nickorlow.com"&gt;NWS&lt;/a&gt;&lt;/p&gt;
</code> <br/> <br/>
{ strat === "raw-html-anthracite" &&
<div>
<p>It would be great if you could add the following to your website as well:</p><br/>
<code lang={"html"} style={{ backgroundColor: "#bbbbbb", padding: 5, borderRadius: 10 }}>
&lt;p&gt;Powered by &lt;a href="https://github.com/nickorlow/anthracite"&gt;Anthracite Web Server&lt;/a&gt;&lt;/p&gt;
</code> <br/> <br/>
</div>
}
<button onClick={()=>{window.location.href="/dashboard"}}>Go to Dashboard</button> <br/>
<button onClick={()=>{window.location.href=hostUriInput}}>See my Site</button>
</div>
}
</div>

View file

@ -4,9 +4,13 @@ import {
useGetAccountServices,
useGetServicesInNamespace,
useLoggedInRedirect,
useNWSAccount
useNWSAccount,
useNWSAuthKey
} from "../nws-api/hooks";
import {useState} from "react";
import {
createNamespace
} from "../nws-api/calls"
import {useState, useEffect} from "react";
import {enableSSL} from "../nws-api/calls";
@ -16,25 +20,60 @@ export default function DashboardPage() {
let {setNs, services, ns} = useGetServicesInNamespace();
let namespaces: Namespace[] = useGetAccountNamespaces();
const urlParams = new URLSearchParams(window.location.search);
return(
<div style={{minHeight: "100vh", padding: "50px"}}>
<div className={"row"}>
<p>I don't really know what I was on when I wrote this but a lot of things in the web ui are goofy, sorry about that.. :/ A new one is on its way.</p>
<h1 className={"col-md-10 col-12"}>Welcome to NWS, {account?.name}!</h1>
<select className={"col-12 col-md-2"} defaultValue={"Select Namespace..."}>
<option value="" disabled selected>Select Namespace...</option>
{
namespaces.map((e)=>{
return <option onClick={(a)=>{setNs(e)}}>{e.name}</option>
})
}
<option value="" disabled>---</option>
<option value="create-ns">Create Namespace</option>
</select>
<div className={"col-12 col-md-2"}>
<p>Namespace</p>
<select className="w-100">
<option value="" disabled selected={!urlParams.has('namespace')}>Select Namespace...</option>
{
namespaces.map((e)=>{
if (urlParams.get('namespace') === e.id && ns?.id != e.id)
setNs(e);
return <option onClick={(a)=>{
const url = new URL(window.location.toString());
url.searchParams.set('namespace', e.id);
window.history.pushState(null, '', url.toString());
setNs(e);
}} selected={urlParams.get('namespace') === e.id}>{e.name}</option>
})
}
</select>
<div>
<button className="w-100 p-0 mt-2" onClick={async () => {
let name = prompt("Enter a name for the namespace");
let rawSession: string | null = localStorage.getItem("session_key");
if (rawSession != null) {
let session: SessionKey = JSON.parse(rawSession);
let newNamespace = await createNamespace(name!, account!.id!, session);
const url = new URL(window.location.toString());
url.searchParams.set('namespace', newNamespace.id);
window.history.pushState(null, '', url.toString());
window.location.reload();
} else {
alert("Error creating namespace");
}
}}>
Create Namespace
</button>
</div>
</div>
</div>
<hr/>
<div className={"d-flex justify-content-between"}>
<h2>Container Deployment Services</h2>
<button onClick={(e) => {window.location.href = "/cruise/new?namespaceId="+ns!.id}}>Create Cruise Service</button>
<button onClick={(e) => {
if (ns != null)
window.location.href = "/cruise/new?namespaceId="+ns!.id
else
alert("Please select a namespace!")
}}>Create Container Deployment</button>
</div>
<div className={"row"}>
@ -47,16 +86,19 @@ export default function DashboardPage() {
<p>{e.serviceId}</p>
{e.hostnames.map((host)=>{
return (
<div className={"mb-2 p-2"}>
<a href={host.hostname}>{host.hostname}</a>
{!host.isSslEnabled ? <a onClick={async () => {
<div className={"mb-2 p-2 d-flex justify-content-between"}>
<a href={"http://"+host.hostname}>{host.hostname}</a>
{!host.isSslEnabled ? <div><button onClick={async () => {
let rawSession: string | null = localStorage.getItem("session_key");
if (rawSession != null) {
let session: SessionKey = JSON.parse(rawSession);
await enableSSL(account!.id!, e.serviceId, host.hostname, session);
alert(`SSL has been enabled on the hostname ${host.hostname}. It should be ready in 2-5 minutes.`);
// hack but whatever
window.location.reload();
}
}}>Enable SSL</a> : <p>SSL is enabled!</p>
}}>Enable SSL</button></div> : <p>SSL is enabled!</p>
}
</div>
)

View file

@ -3,7 +3,7 @@ import React from "react";
export default function Footer() {
return (
<footer className={"mt-2 p-3"} style={{backgroundColor: "#eee"}}>
<p>NWS is owned and operated by <a href={"http://nickorlow.com"}>Nicholas Orlowsky</a>.</p>
<p>SMC is owned and operated by <a href={"http://nickorlow.com"}>Nicholas Orlowsky</a>.</p>
<p>Copyright © Nicholas Orlowsky {new Date().getFullYear()}</p>
</footer>
);

View file

@ -37,18 +37,15 @@ export default function HomePage() {
<img src={NWSLogo} alt="nws-logo" style={{width: "70%"}}/>
</div>
<div className={"col-md-6 text-center d-flex justify-content-center flex-column align-items-center"}>
<h1>Nick Web Services</h1>
<p style={{maxWidth: 500}} className={"col-md-6 text-center"}>
Nick Web Services is a hosting service based out of
Austin, Texas. It is committed
to achieving maximum uptime with better performance and a lower cost than any of the major cloud
services.
<h1>Sharpe Mountain Compute</h1>
<p className={"col-md-6 text-center"}>
Sharpe Mountain Compute (fka Nick Web Services) is a reliable cloud compute provider. SMC is dedicated to achieving maximum uptime at a lower cost than traditional cloud compute providers.
</p>
</div>
</div>
<div className={"w-100 mt-2 flex justify-content-center align-content-center text-center"}>
<h3><i>100% Uptime from 1/1/2023 - 11/8/2023</i></h3>
<h4><a href={"https://youtu.be/WHdXWMFHuqA"} target="_blank" rel="noopener noreferrer">Watch the NWS Deployment Demo</a></h4>
<h4><a href={"https://youtu.be/WHdXWMFHuqA"} target="_blank" rel="noopener noreferrer">Watch the SMC Deployment Demo</a></h4>
</div>
<div style={{width: '75vw'}}>
<hr/>

View file

@ -96,9 +96,9 @@ export default function RegisterPage() {
</div>
<div className={"reg-box"} style={{display: didRegister ? "flex" : "none"}}>
<h3>Verify your E-Mail address.</h3>
<h3>Successfully Registered!</h3>
<p>Please verify your E-Mail by clicking the link we sent to you at: <b>{email}</b></p>
<p><a href="/login">Proceed to login</a></p>
</div>
</div>
);

View file

@ -38,22 +38,22 @@ export default function UptimeComparisonCard(props: {uptime: UptimeRecord, isSer
</div>
<hr className={" w-100"}/>
<p className={"fw-bold d-lg-none"}>Uptime (Last Month)</p>
<div style={{height: 25, margin: 0}} className={"pt-2 pt-lg-0"}>
<div style={{height: 25, margin: 0}} className={"pb-2 pt-lg-0"}>
<p className={getUptimeClass(props.uptime.uptimeMonth)}>{props.uptime.uptimeMonth}%</p>
</div>
<hr className={"d-lg-block d-none w-100"}/>
<p className={"fw-bold d-lg-none"}>Uptime ({new Date().getFullYear()} YTD)</p>
<div style={{height: 25, margin: 0}} className={"pt-2 pt-lg-0"}>
<div style={{height: 25, margin: 0}} className={"pb-2 pt-lg-0"}>
<p className={getUptimeClass(props.uptime.uptimeYtd)}>{props.uptime.uptimeYtd}%</p>
</div>
<hr className={"d-lg-block d-none w-100"}/>
<p className={"fw-bold d-lg-none"}>Avg Response Time (24hr)</p>
<div style={{height: 25, margin: 0}} className={"pt-2 pt-lg-0"}>
<div style={{height: 25, margin: 0}} className={"pb-2 pt-lg-0"}>
<p className={getResponseTimeClass(props.uptime.averageResponseTime)}>{props.uptime.averageResponseTime}ms</p>
</div>
<hr className={"d-lg-block d-none w-100"} />
<p className={"fw-bold d-lg-none"}>Current Status</p>
<div style={{height: 25, margin: 0}} className={"pt-2 pt-lg-0"}>
<div style={{height: 25, margin: 0}} className={"pb-2 pt-lg-0"}>
<div className={`p-1 d-flex justify-content-start w-100`} >
<p className={`fw-bold severity-label w-100

View file

@ -28,7 +28,7 @@ function Layout (props: {children: any}) {
<div>
<header className={"w-100 sticky-top"}>
<div className={"w-100"}>
<Navbar sticky={"top"} expand="lg" className={"row justify-content-center m-0 p-0"} style={{backgroundColor: "#eee"}}>
<Navbar sticky={"top"} expand="md" className={"row justify-content-center m-0 p-0"} style={{backgroundColor: "#eee"}}>
<div className={"row w-100"}>
<div className="row w-100 d-md-none d-sm-block">
<div className={"col-9"}>

View file

@ -50,6 +50,22 @@ export async function getNamespaces(accountId: string, skey: SessionKey): Promis
return namespaces;
}
export async function createNamespace(name: string, accountId: string, session: SessionKey): Promise<Namespace> {
let response: Response = await fetch('https://api-nws.nickorlow.com/namespaces', {
headers: {
'Content-Type': 'application/json',
Authorization: btoa(session.accountId + ":" + session.id)
},
method: 'POST',
body: JSON.stringify({
'name': name,
'ownerId': accountId
})
});
let namespace: Namespace = await response.json();
return namespace;
}
export async function enableSSL(accountId: string, serviceId: string, hostname: string, session: SessionKey) {
await fetch('https://api-nws.nickorlow.com/'+accountId+'/service/'+serviceId+"/hosts/"+hostname+"/ssl", {
headers: {