mirror of
https://github.com/JonasunderscoreJones/dash.jonasjones.dev.git
synced 2025-10-26 00:49:19 +02:00
Compare commits
No commits in common. "53eeebaf0aa9dc7fcb68883db8f7c841617a2c89" and "a4e42be9948e71324faefc3228e750e541245b54" have entirely different histories.
53eeebaf0a
...
a4e42be994
12 changed files with 105 additions and 147 deletions
53
README.md
53
README.md
|
|
@ -1,21 +1,38 @@
|
||||||
# Jonas_Jones Dashboard
|
# sv
|
||||||
This Dashboard connects the settings and configurations of most of the services of my ecosystem
|
|
||||||
|
|
||||||
## Accounts
|
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||||
It is possible for everyone to signup and get access to the settings, however most user scopes aren't available to the default user and need to be granted by an admin user.
|
|
||||||
|
|
||||||
## Settings and Configurations
|
## Creating a project
|
||||||
The following are services that can be configured from the dashboard:
|
|
||||||
|
|
||||||
| Service Name | Description | Implemented |
|
If you're seeing this, you've probably already done this step. Congrats!
|
||||||
| ------------ | ----------- | ----------- |
|
|
||||||
| accouts.jonasjones.dev | Account Management (scopes, deletion, creation, etc...) | No |
|
```bash
|
||||||
| jonasjones.dev (Projects) | Project Management (update, add, delete) | No |
|
# create a new project in the current directory
|
||||||
| Analytics (stats.jonasjones.dev) | Management (delete, graphs) | No |
|
npx sv create
|
||||||
| Rick-Roll-Tracker | Management (graphs) | No |
|
|
||||||
| kcomebacks.jonasjones.dev | run scraper, graphs, etc... | No |
|
# create a new project in my-app
|
||||||
| builds.jonasjones.dev | Add, remove, update | No |
|
npx sv create my-app
|
||||||
| blogs.jonasjones.dev | create, edit, delete Posts | No |
|
```
|
||||||
| rss.jonasjones.dev | add, edit, delete entries | No |
|
|
||||||
| API scripts | run, (probably not much more because security issues like remote code execution etc.) | No |
|
## Developing
|
||||||
| aka.jonasjones.dev | add, remove, edit aka entries | No |
|
|
||||||
|
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# or start the server and open the app in a new browser tab
|
||||||
|
npm run dev -- --open
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To create a production version of your app:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
You can preview the production build with `npm run preview`.
|
||||||
|
|
||||||
|
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<div class="alpha-notice">
|
|
||||||
<h2><b>This is an Alpha Version</b></h2>
|
|
||||||
<p>
|
|
||||||
Note that this Dashboard is in an alpha state. This means that there are bugs and missing features.
|
|
||||||
Please report any bugs or issues to the
|
|
||||||
<a href="https://github.com/JonasunderscoreJones/dash.jonasjones.dev/issues">GitHub repository</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.alpha-notice {
|
|
||||||
background-color: #c48900;
|
|
||||||
color: #721c24;
|
|
||||||
padding: 1rem;
|
|
||||||
border: 1px solid #533300;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alpha-notice h2 {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alpha-notice a {
|
|
||||||
color: #721c24;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alpha-notice a:hover {
|
|
||||||
color: #560009;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -6,11 +6,6 @@
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<head>
|
|
||||||
<!-- Include Font Awesome CDN -->
|
|
||||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<div class="app">
|
<div class="app">
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
|
|
@ -27,4 +22,33 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 64rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 480px) {
|
||||||
|
footer {
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { ensureAuthenticated } from '$lib/session.js';
|
import { ensureAuthenticated } from '../utils/session.js';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
ensureAuthenticated(); // This will check the session key and redirect if necessary
|
ensureAuthenticated(); // This will check the session key and redirect if necessary
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
|
<head>
|
||||||
|
<!-- Include Font Awesome CDN -->
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="footer-left">
|
<div class="footer-left">
|
||||||
<a href="https://github.com/JonasunderscoreJones" target="_blank" aria-label="GitHub Link"><i class="fab fa-github"></i></a>
|
<a href="https://github.com/JonasunderscoreJones" target="_blank"><i class="fab fa-github" /></a>
|
||||||
<a href="https://www.youtube.com/channel/UCVIxvKBIMSMgurYS8pK7fSg" target="_blank" aria-label="YouTube Link"><i class="fab fa-youtube"></i></a>
|
<a href="https://www.youtube.com/channel/UCVIxvKBIMSMgurYS8pK7fSg" target="_blank"><i class="fab fa-youtube" /></a>
|
||||||
<a href="https://discord.gg/V2EsuUVmWh" target="_blank" aria-label="Discord Link"><i class="fab fa-discord"></i></a>
|
<a href="https://discord.gg/V2EsuUVmWh" target="_blank"><i class="fab fa-discord" /></a>
|
||||||
<a href="mailto:me@jonasjones.dev" target="_blank" aria-label="Email Link"><i class="fas fa-envelope"></i></a>
|
<a href="mailto:me@jonasjones.dev" target="_blank"><i class="fas fa-envelope" /></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Website by Jonas_Jones 2021 - <script>document.write(new Date().getFullYear());</script></p>
|
<p>Website by Jonas_Jones 2021 - <script>document.write(new Date().getFullYear());</script></p>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import logo from '$lib/images/logo.png';
|
import logo from '$lib/images/logo.png';
|
||||||
import { getSessionKey } from '$lib/session.js';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
|
|
||||||
let sessionKey;
|
|
||||||
onMount(() => {
|
|
||||||
sessionKey = getSessionKey();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
|
@ -22,16 +15,13 @@
|
||||||
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
|
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
|
||||||
</svg>
|
</svg>
|
||||||
<ul>
|
<ul>
|
||||||
{#if sessionKey === null}
|
{#if ['/login', '/signup', '/register'].includes(page.url.pathname)}
|
||||||
<li aria-current={page.url.pathname === '/login' ? 'page' : undefined}>
|
<li aria-current={page.url.pathname === '/login' ? 'page' : undefined}>
|
||||||
<a href="/login{page.url.search}">Login</a>
|
<a href="/login{page.url.search}">Login</a>
|
||||||
</li>
|
</li>
|
||||||
<li aria-current={page.url.pathname === '/signup' ? 'page' : undefined}>
|
<li aria-current={page.url.pathname === '/signup' ? 'page' : undefined}>
|
||||||
<a href="/signup{page.url.search}">Signup</a>
|
<a href="/signup{page.url.search}">Signup</a>
|
||||||
</li>
|
</li>
|
||||||
<li aria-current={page.url.pathname === '/about' ? 'page' : undefined}>
|
|
||||||
<a href="/about">About</a>
|
|
||||||
</li>
|
|
||||||
{:else}
|
{:else}
|
||||||
<li aria-current={page.url.pathname === '/' ? 'page' : undefined}>
|
<li aria-current={page.url.pathname === '/' ? 'page' : undefined}>
|
||||||
<a href="/">Home</a>
|
<a href="/">Home</a>
|
||||||
|
|
@ -39,9 +29,6 @@
|
||||||
<li aria-current={page.url.pathname === '/about' ? 'page' : undefined}>
|
<li aria-current={page.url.pathname === '/about' ? 'page' : undefined}>
|
||||||
<a href="/about">About</a>
|
<a href="/about">About</a>
|
||||||
</li>
|
</li>
|
||||||
<li aria-current={page.url.pathname === '/logout' ? 'page' : undefined}>
|
|
||||||
<a href="/logout">Logout</a>
|
|
||||||
</li>
|
|
||||||
{/if}
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
<svg viewBox="0 0 2 3" aria-hidden="true">
|
<svg viewBox="0 0 2 3" aria-hidden="true">
|
||||||
|
|
|
||||||
9
src/routes/about/+page.js
Normal file
9
src/routes/about/+page.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { dev } from '$app/environment';
|
||||||
|
|
||||||
|
// we don't need any JS on this page, though we'll load
|
||||||
|
// it in dev so that we get hot module replacement
|
||||||
|
export const csr = dev;
|
||||||
|
|
||||||
|
// since there's no dynamic data here, we can prerender
|
||||||
|
// it so that it gets served as a static asset in production
|
||||||
|
export const prerender = true;
|
||||||
|
|
@ -1,37 +1,21 @@
|
||||||
<script>
|
|
||||||
import AlphaNotice from "$lib/components/AlphaNotice.svelte";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>About</title>
|
<title>About</title>
|
||||||
<meta name="description" content="About this app" />
|
<meta name="description" content="About this app" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="text-column">
|
<div class="text-column">
|
||||||
<h1>About this Dashboard</h1>
|
<h1>About this app</h1>
|
||||||
|
|
||||||
<AlphaNotice />
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This is a Dashboard app for my Ecosystem's services.
|
This is a <a href="https://svelte.dev/docs/kit">SvelteKit</a> app. You can make your own by typing
|
||||||
The list and roadmap of supported services can be viewed in the
|
the following into your command line and following the prompts:
|
||||||
<a href="https://github.com/JonasunderscoreJones/dash.jonasjones.dev/blob/main/README.md">README.md</a>
|
|
||||||
page of the github repository. Thus, the Dashboard is opensource in the same repository.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<pre>npx sv create</pre>
|
||||||
Signups are allowed to anyone. This is because the default user scope currently has no permissions.
|
|
||||||
However, the Dashboard is designed to be used with a user scope system. This means that the user scope
|
|
||||||
will be able to access services that are only available to them. Scopes are granted by an admin account.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Further are the accounts not limited to the Dashboard. They are their own entity, hosted on cloudflare workers.
|
The page you're looking at is purely static HTML, with no client-side interactivity needed.
|
||||||
Thus, the accounts are available to be used in other projects as well. The accounts are also opensource in the
|
Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening
|
||||||
<a href="https://github.com/JonasunderscoreJones/accounts.jonasjones.dev/">github repository</a>.
|
the devtools network panel and reloading.
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Tldr; Dashboard is opensource and signup is public but has no permissions, unless explicitly granted by an admin.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
<script>
|
<script>
|
||||||
import { navigate } from 'svelte-routing';
|
import { navigate } from 'svelte-routing';
|
||||||
import { onMount } from 'svelte';
|
import { setSessionKey } from '../../utils/session.js';
|
||||||
import { setSessionKey, redirectToHome, ACCOUNTS_WORKER_URL } from '$lib/session.js';
|
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import AlphaNotice from '$lib/components/AlphaNotice.svelte';
|
|
||||||
let email = '';
|
let email = '';
|
||||||
let password = '';
|
let password = '';
|
||||||
let errorMessage = '';
|
let errorMessage = '';
|
||||||
let showPassword = false;
|
let showPassword = false;
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
redirectToHome(); // This will check the session key and redirect if necessary
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(ACCOUNTS_WORKER_URL + '/login', {
|
const response = await fetch('https://accounts.jonasjones.dev/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({ email, password }),
|
body: JSON.stringify({ email, password }),
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -44,8 +38,6 @@
|
||||||
<div class="login-prompt">
|
<div class="login-prompt">
|
||||||
<h1>Login</h1>
|
<h1>Login</h1>
|
||||||
|
|
||||||
<AlphaNotice />
|
|
||||||
|
|
||||||
{#if errorMessage}
|
{#if errorMessage}
|
||||||
<p style="color: red;">{errorMessage}</p>
|
<p style="color: red;">{errorMessage}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -81,11 +73,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: fixed;
|
||||||
|
top: 50px;
|
||||||
|
left: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 80vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
margin-top: 25px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-prompt {
|
.login-prompt {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<script>
|
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
import { resetSession } from '$lib/session.js';
|
|
||||||
|
|
||||||
resetSession();
|
|
||||||
goto('/login');
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h1>Logging out...</h1>
|
|
||||||
<p>Redirecting to the login page...</p>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { navigate } from 'svelte-routing';
|
import { navigate } from 'svelte-routing';
|
||||||
import { setSessionKey, ACCOUNTS_WORKER_URL } from '$lib/session.js';
|
import { setSessionKey } from '../../utils/session.js';
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import AlphaNotice from '$lib/components/AlphaNotice.svelte';
|
|
||||||
let username = '';
|
let username = '';
|
||||||
let firstname = '';
|
let firstname = '';
|
||||||
let lastname = '';
|
let lastname = '';
|
||||||
|
|
@ -13,7 +12,7 @@
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(ACCOUNTS_WORKER_URL + '/register', {
|
const response = await fetch('https://accounts.jonasjones.dev/register', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({ email, password, username, firstname, lastname }),
|
body: JSON.stringify({ email, password, username, firstname, lastname }),
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -42,8 +41,6 @@
|
||||||
<div class="login-prompt">
|
<div class="login-prompt">
|
||||||
<h1>Signup</h1>
|
<h1>Signup</h1>
|
||||||
|
|
||||||
<AlphaNotice />
|
|
||||||
|
|
||||||
{#if errorMessage}
|
{#if errorMessage}
|
||||||
<p style="color: red;">{errorMessage}</p>
|
<p style="color: red;">{errorMessage}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -86,11 +83,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: fixed;
|
||||||
|
top: 50px;
|
||||||
|
left: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 80vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
margin-top: 25px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-prompt {
|
.login-prompt {
|
||||||
|
|
@ -143,7 +141,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: var(--color-theme-2);
|
background-color: #0056b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
export const ACCOUNTS_WORKER_URL = 'https://accounts.jonasjones.dev';
|
|
||||||
|
|
||||||
export function getSessionKey() {
|
export function getSessionKey() {
|
||||||
const match = document.cookie.match(/(^| )sessionKey=([^;]+)/);
|
const match = document.cookie.match(/(^| )sessionKey=([^;]+)/);
|
||||||
return match ? match[2] : null;
|
return match ? match[2] : null;
|
||||||
|
|
@ -14,20 +12,6 @@ export function redirectToLogin() {
|
||||||
window.location.href = `/login?returnUrl=${currentPath}`;
|
window.location.href = `/login?returnUrl=${currentPath}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetSession() {
|
|
||||||
document.cookie = `sessionKey=; path=/; max-age=0`;
|
|
||||||
window.location.href = '/login';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function redirectToHome() {
|
|
||||||
if (getSessionKey()) {
|
|
||||||
window.location.href = new URLSearchParams(window.location.search).get('returnUrl') || '/';
|
|
||||||
console.log(new URLSearchParams(window.location.search).get('returnUrl') || '/')
|
|
||||||
} else {
|
|
||||||
console.log(getSessionKey())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ensureAuthenticated() {
|
export function ensureAuthenticated() {
|
||||||
if (!getSessionKey()) {
|
if (!getSessionKey()) {
|
||||||
redirectToLogin();
|
redirectToLogin();
|
||||||
Loading…
Add table
Add a link
Reference in a new issue