Merge pull request #3424 from sveltejs/gh-3019

Show a list of the user's apps
pull/3428/head
Rich Harris 5 years ago committed by GitHub
commit 1bb0728a5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,11 +1,32 @@
<script>
import { setContext } from 'svelte';
import { stores } from '@sapper/app';
import { Icon, Icons, Nav, NavItem } from '@sveltejs/site-kit';
import PreloadingIndicator from '../components/PreloadingIndicator.svelte';
const { page, preloading } = stores();
export let segment;
const { page, preloading, session } = stores();
setContext('app', {
login: () => {
const login_window = window.open(`${window.location.origin}/auth/login`, 'login', 'width=600,height=400');
window.addEventListener('message', function handler(event) {
login_window.close();
window.removeEventListener('message', handler);
$session.user = event.data.user;
});
},
logout: async () => {
const r = await fetch(`/auth/logout`, {
credentials: 'include'
});
if (r.ok) $session.user = null;
}
});
</script>
<Icons/>

@ -0,0 +1,24 @@
import send from '@polka/send';
import { query } from '../../utils/db';
export async function get(req, res) {
if (req.user) {
const offset = req.params.offset || 0;
const rows = await query(`
select g.uid, g.name, coalesce(g.updated_at, g.created_at) as updated_at
from gists g
where g.user_id = $1
order by updated_at desc
limit 100
offset $2
`, [req.user.id, offset]);
rows.forEach(row => {
row.uid = row.uid.replace(/-/g, '');
});
send(res, 200, rows);
} else {
send(res, 401);
}
}

@ -0,0 +1,130 @@
<script context="module">
export async function preload(page, { user }) {
let apps;
if (user) {
const r = await this.fetch('apps.json', {
credentials: 'include'
});
if (!r.ok) return this.error(r.status, await r.text());
apps = await r.json();
}
return { user, apps };
}
</script>
<script>
import { getContext } from 'svelte';
export let user;
export let apps;
const { login, logout } = getContext('app');
const formatter = new Intl.DateTimeFormat(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
});
const format = str => formatter.format(new Date(str));
</script>
<svelte:head>
<title>Your apps • Svelte</title>
</svelte:head>
<div class="apps">
{#if user}
<header>
<h1>Your apps</h1>
<div class="user">
<img class="avatar" alt="{user.name} avatar" src="{user.avatar}">
<span>
{user.name}
(<a on:click|preventDefault={logout} href="auth/logout">log out</a>)
</span>
</div>
</header>
<ul>
{#each apps as app}
<li>
<a href="repl/{app.uid}">
<h2>{app.name}</h2>
<span>updated {format(app.updated_at)}</span>
</a>
</li>
{/each}
</ul>
{:else}
<p>Please <a on:click|preventDefault={login} href="auth/login">log in</a> to see your saved apps.</p>
{/if}
</div>
<style>
.apps {
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
max-width: var(--main-width);
margin: 0 auto;
}
header {
margin: 0 0 1em 0;
}
h1 {
font-size: 4rem;
font-weight: 400;
}
.user {
display: flex;
padding: 0 0 0 3.2rem;
position: relative;
margin: 1rem 0 5rem 0;
color: var(--text);
}
.avatar {
position: absolute;
left: 0;
top: 0.1rem;
width: 2.4rem;
height: 2.4rem;
border: 1px solid rgba(0,0,0,0.3);
border-radius: 0.2rem;
}
ul {
list-style: none;
}
li {
margin: 0 0 1em 0;
}
h2 {
color: var(--text);
font-size: var(--h3);
font-weight: 400;
}
li a {
border: none;
}
li a:hover h2 {
color: var(--flash);
}
li span {
font-size: 14px;
color: #999;
}
</style>

@ -1,14 +1,9 @@
<script>
import { getContext } from 'svelte';
import { stores } from '@sapper/app';
const { session } = stores();
const logout = async () => {
const r = await fetch(`/auth/logout`, {
credentials: 'include'
});
if (r.ok) $session.user = null;
}
const { logout } = getContext('app');
let showMenu = false;
let name;
@ -22,6 +17,7 @@
{#if showMenu}
<div class="menu">
<a href="apps">Your saved apps</a>
<button on:click={logout}>Log out</button>
</div>
{/if}
@ -73,7 +69,7 @@
.menu {
position: absolute;
width: calc(100% + 1.6rem);
min-width: 6em;
min-width: 10em;
top: 3rem;
right: -1.6rem;
background-color: var(--second);
@ -81,17 +77,25 @@
z-index: 99;
text-align: left;
border-radius: 0.4rem;
display: flex;
flex-direction: column;
}
.menu button {
.menu button, .menu a {
background-color: transparent;
font-family: var(--font);
font-size: 1.6rem;
/* opacity: 0.7; */
opacity: 0.7;
padding: 0.4rem 0;
text-decoration: none;
text-align: left;
border: none;
color: inherit;
}
.menu button:hover {
.menu button:hover, .menu a:hover {
opacity: 1;
color: inherit;
}
@media (min-width: 600px) {

@ -1,5 +1,5 @@
<script>
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, getContext } from 'svelte';
import { stores } from '@sapper/app';
import UserMenu from './UserMenu.svelte';
import { Icon } from '@sveltejs/site-kit';
@ -10,6 +10,7 @@
const dispatch = createEventDispatcher();
const { session } = stores();
const { login } = getContext('app');
export let repl;
export let gist;
@ -35,19 +36,6 @@
}
}
function login(event) {
event.preventDefault();
const loginWindow = window.open(`${window.location.origin}/auth/login`, 'login', 'width=600,height=400');
const handleLogin = event => {
loginWindow.close();
$session.user = event.data.user;
window.removeEventListener('message', handleLogin);
};
window.addEventListener('message', handleLogin);
}
async function fork(intentWasSave) {
saving = true;
@ -218,7 +206,7 @@ export default app;` });
{#if $session.user}
<UserMenu/>
{:else}
<button class="icon" on:click={login}>
<button class="icon" on:click|preventDefault={login}>
<Icon name="log-in" />
<span>&nbsp;Log in to save</span>
</button>

Loading…
Cancel
Save