Commit 4b828ee3 authored by Aral Balkan's avatar Aral Balkan
Browse files

Pages displaying and basic navigation works

parent 895d40bb
<script>
import Router from 'svelte-spa-router'
import Navigation from './Navigation.svelte'
import SetupSection from './sections/Setup.svelte'
import HomeSection from './sections/Home.svelte'
import AboutSection from './sections/About.svelte'
import SlidingSection from './sections/Sliding.svelte'
import SwitchSection from './sections/Switch.svelte'
import PrivateSection from './sections/Private.svelte'
import SignInSection from './sections/SignIn.svelte'
import SignOutSection from './sections/SignOut.svelte'
import NotFound from './sections/NotFound.svelte'
import { routes } from './sections'
import { onMount, getContext } from 'svelte'
// Initialise state.
import { initialise, state } from './state.js'
initialise()
// Initialise context.
import { initialiseContext, state } from './state.js'
initialiseContext()
const { publicSocket } = getContext(state)
......@@ -22,7 +15,7 @@
// Make the public socket connection.
$publicSocket = new WebSocket(`wss://${location.hostname}/public`)
$publicSocket.onmessage = message => {
alert(message.data)
console.log(message.data)
}
})
</script>
......@@ -36,13 +29,5 @@
<Navigation />
<main>
<SetupSection />
<HomeSection />
<AboutSection />
<SlidingSection />
<SwitchSection />
<PrivateSection />
<SignInSection />
<SignOutSection />
<NotFound />
<Router {routes}/>
</main>
......@@ -3,16 +3,7 @@
import { state } from './state.js'
import sections from './sections.js'
let { signedIn, currentSection } = getContext(state)
let selectedSection = $currentSection
function handleNavigation (event) {
selectedSection = event.target.hash.replace('#', '')
if (selectedSection !== $currentSection) {
$currentSection = selectedSection
}
}
let { signedIn} = getContext(state)
function shouldDisplay(path) {
// Display either the Sign In or Private section based on sign in status.
......@@ -32,14 +23,9 @@
<ul>
{#each sections as section}
<!-- Including $currentSection here to trigger reactivity. -->
{#if !section.notInNavigation && $currentSection && shouldDisplay(section.path)}
{#if !section.notInNavigation && shouldDisplay(section.path)}
<li>
<!-- Display the current section without a hyperlink; all other sections with a link. -->
{#if section.path !== $currentSection}
<a href='/#{section.path}' on:click={handleNavigation}>{section.title}</a>
{:else}
{section.title}
{/if}
<a href='/#{section.path}'>{section.title}</a>
</li>
{/if}
{/each}
......
......@@ -14,6 +14,7 @@
"buffer": "^6.0.3",
"session25519": "^1.1.0",
"svelte-loading-spinners": "^0.1.4",
"svelte-spa-router": "^3.1.0",
"svelte-switch": "0.0.4",
"tweetnacl": "^1.0.3",
"tweetnacl-sealedbox-js": "^1.2.0",
......@@ -526,6 +527,14 @@
"url": "https://opencollective.com/postcss/"
}
},
"node_modules/regexparam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-1.3.0.tgz",
"integrity": "sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g==",
"engines": {
"node": ">=6"
}
},
"node_modules/require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
......@@ -625,6 +634,17 @@
"resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.1.4.tgz",
"integrity": "sha512-r/0Hs9cxtRLh2RwBwwEat1V1M1kypaGFPllM7XdZSH299JTed994B6zMHJ1Z5Ug8B9Tl2bs+VOy8Vz5EFWy5Ww=="
},
"node_modules/svelte-spa-router": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/svelte-spa-router/-/svelte-spa-router-3.1.0.tgz",
"integrity": "sha512-jlM/xwjn57mylr+pzHYCOOy+IPQauT46gOucNGTBu6jHcFXu3F+oaojN4PXC1LYizRGxFB6QA0qnYbZnRfX7Sg==",
"dependencies": {
"regexparam": "1.3.0"
},
"funding": {
"url": "https://github.com/sponsors/ItalyPaleAle"
}
},
"node_modules/svelte-switch": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/svelte-switch/-/svelte-switch-0.0.4.tgz",
......@@ -1025,6 +1045,11 @@
"source-map": "^0.6.1"
}
},
"regexparam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-1.3.0.tgz",
"integrity": "sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g=="
},
"require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
......@@ -1105,6 +1130,14 @@
"resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.1.4.tgz",
"integrity": "sha512-r/0Hs9cxtRLh2RwBwwEat1V1M1kypaGFPllM7XdZSH299JTed994B6zMHJ1Z5Ug8B9Tl2bs+VOy8Vz5EFWy5Ww=="
},
"svelte-spa-router": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/svelte-spa-router/-/svelte-spa-router-3.1.0.tgz",
"integrity": "sha512-jlM/xwjn57mylr+pzHYCOOy+IPQauT46gOucNGTBu6jHcFXu3F+oaojN4PXC1LYizRGxFB6QA0qnYbZnRfX7Sg==",
"requires": {
"regexparam": "1.3.0"
}
},
"svelte-switch": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/svelte-switch/-/svelte-switch-0.0.4.tgz",
......
export default [
{ path: '/', title: 'Home'},
{ path: '/about', title: 'About'},
{ path: '/sliding', title: 'Sliding'},
{ path: '/switch', title: 'Switch'},
{ path: '/sign-in', title: 'Sign in'},
{ path: '/sign-out', title: 'Sign out'},
{ path: '/private', title: 'Private'},
{ path: '/setup', title: 'Setup', notInNavigation: true},
{ path: '/404', title: '404: not found', notInNavigation: true}
import SetupSection from './sections/Setup.svelte'
import HomeSection from './sections/Home.svelte'
import AboutSection from './sections/About.svelte'
import SlidingSection from './sections/Sliding.svelte'
import SwitchSection from './sections/Switch.svelte'
import PrivateSection from './sections/Private.svelte'
import SignInSection from './sections/SignIn.svelte'
import SignOutSection from './sections/SignOut.svelte'
import NotFound from './sections/NotFound.svelte'
import wrap from 'svelte-spa-router/wrap'
import { replace } from 'svelte-spa-router'
import { signedIn } from './state.js'
let isSignedIn
signedIn.subscribe(value => {
isSignedIn = value
})
export const sections = [
{ path: '/', title: 'Home', route: HomeSection},
{ path: '/about', title: 'About', route: AboutSection},
{ path: '/sliding', title: 'Sliding', route: SlidingSection},
{ path: '/switch', title: 'Switch', route: SwitchSection},
{ path: '/sign-in', title: 'Sign in', route: SignInSection},
{ path: '/sign-out', title: 'Sign out', route: SignOutSection, isPrivate: true},
{ path: '/private', title: 'Private', route: PrivateSection, isPrivate: true},
{ path: '/setup', title: 'Setup', notInNavigation: true, route: SetupSection},
{ path: '*', title: '404: not found', notInNavigation: true, route: NotFound}
]
const isPrivate = () => {
if (!isSignedIn) {
replace('/sign-in')
}
return false
}
// Create the routes map.
export let routes = new Map()
sections.forEach(section => {
const wrappedRoute = wrap({
component: section.route,
props: { title: section.title }
})
if (section.isPrivate) {
wrappedRoute.conditions = [ isPrivate ]
}
routes.set(section.path, wrappedRoute)
})
export default sections
......@@ -4,9 +4,6 @@
import { state } from '../state.js'
import { fade } from 'svelte/transition'
let { currentSection } = getContext(state)
export let path
export let title
</script>
......@@ -17,10 +14,7 @@
}
</style>
<!-- Only display a section if it is the current one. -->
{#if $currentSection === path}
<section transition:fade="{{duration: 300}}">
<h2>{title}</h2>
<slot></slot>
</section>
{/if}
import { setContext } from 'svelte'
import { writable, get } from 'svelte/store'
import sections from './sections.js'
const sectionPaths = sections.map(value => value.path)
import { writable } from 'svelte/store'
// Context key.
export const state = {}
// Set initial application state, including the current section based on the hash.
export function initialise () {
const signedIn = writable(false)
const privateToken = writable(null)
const privateSocket = writable(null)
const publicSocket = writable(null)
const currentSection = writable(currentSectionFromHash(false))
setContext(state, { currentSection, signedIn, publicSocket, privateToken, privateSocket })
window.addEventListener('hashchange', () => {
const _signedIn = get(signedIn)
currentSection.update(value => value = currentSectionFromHash(_signedIn))
})
}
function currentSectionFromHash (signedIn) {
let section = location.hash.replace('#', '')
export const signedIn = writable(false)
const privateToken = writable(null)
const privateSocket = writable(null)
const publicSocket = writable(null)
// Redirect to Sign In page if trying to access private area while not signed in.
// (This is just client-side validation, not security.)
if (!signedIn && section.startsWith('/private') || !signedIn && section.startsWith('/sign-out')) {
section = '/sign-in'
// In a real app, you would also save a redirect path in a store in the context.
}
// Normalise all paths so they do not end in a slash.
if (section !== '/' && section.endsWith('/')) { section = section.slice(0, section.length - 1) }
// Normalise index path.
if (section === '') { section = '/'; }
// If we’ve updated the section path, update the hash also.
if (section !== location.hash.replace('#', '')) { location.hash = section }
// Check if this is a known path and show 404 page if it’s not.
// (Note: we do not update the hash here on purpose so the original missing path is shown.)
if (!sectionPaths.includes(section)) { section = '/404' }
return section
// Set initial application state, including the current section based on the hash.
export function initialiseContext () {
setContext(state, { signedIn, publicSocket, privateToken, privateSocket })
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment