Improve routing based on auth and roles, and use redirects rather than pushing new routes
This commit is contained in:
parent
473c9ebfa6
commit
78ba798be2
|
@ -25,11 +25,11 @@
|
|||
<Layout noPadding gap="XS" alignContent="start">
|
||||
<div class="preview" use:gradient={{ seed: app.name }} />
|
||||
<div class="title">
|
||||
<Link on:click={() => openApp(app)}>
|
||||
<div class="name" on:click={() => openApp(app)}>
|
||||
<Heading size="XS">
|
||||
{app.name}
|
||||
</Heading>
|
||||
</Link>
|
||||
</div>
|
||||
<ActionMenu align="right">
|
||||
<Icon slot="control" name="More" hoverable />
|
||||
<MenuItem on:click={() => exportApp(app)} icon="Download">
|
||||
|
@ -76,7 +76,7 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.title :global(a) {
|
||||
.name {
|
||||
text-decoration: none;
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
<script>
|
||||
import { gradient } from "actions"
|
||||
import {
|
||||
Heading,
|
||||
Button,
|
||||
Icon,
|
||||
ActionMenu,
|
||||
MenuItem,
|
||||
Link,
|
||||
} from "@budibase/bbui"
|
||||
import { Heading, Button, Icon, ActionMenu, MenuItem } from "@budibase/bbui"
|
||||
import { auth } from "stores/backend"
|
||||
|
||||
export let app
|
||||
|
@ -21,11 +14,11 @@
|
|||
|
||||
<div class="title" class:last>
|
||||
<div class="preview" use:gradient={{ seed: app.name }} />
|
||||
<Link on:click={() => openApp(app)}>
|
||||
<div class="name" on:click={() => openApp(app)}>
|
||||
<Heading size="XS">
|
||||
{app.name}
|
||||
</Heading>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div class:last>
|
||||
Edited {Math.round(Math.random() * 10 + 1)} months ago
|
||||
|
@ -66,7 +59,7 @@
|
|||
width: 40px;
|
||||
border-radius: var(--border-radius-s);
|
||||
}
|
||||
.title :global(a) {
|
||||
.name {
|
||||
text-decoration: none;
|
||||
}
|
||||
.title :global(h1:hover) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { isActive, goto } from "@roxi/routify"
|
||||
import { isActive, goto, redirect } from "@roxi/routify"
|
||||
import { auth } from "stores/backend"
|
||||
import { admin } from "stores/portal"
|
||||
|
||||
|
@ -16,14 +16,14 @@
|
|||
// Force creation of an admin user if one doesn't exist
|
||||
$: {
|
||||
if (loaded && !hasAdminUser) {
|
||||
$goto("./admin")
|
||||
$redirect("./admin")
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to log in at any time if the user isn't authenticated
|
||||
$: {
|
||||
if (loaded && hasAdminUser && !$auth.user && !$isActive("./auth")) {
|
||||
$goto("./auth/login")
|
||||
$redirect("./auth/login")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<script>
|
||||
import { auth } from "stores/backend"
|
||||
</script>
|
||||
|
||||
{#if $auth.user}
|
||||
<slot />
|
||||
{/if}
|
|
@ -9,93 +9,25 @@
|
|||
Avatar,
|
||||
Page,
|
||||
Icon,
|
||||
notifications,
|
||||
Body,
|
||||
} from "@budibase/bbui"
|
||||
import api, { del } from "builderStore/api"
|
||||
import analytics from "analytics"
|
||||
import { onMount } from "svelte"
|
||||
import { apps, organisation } from "stores/portal"
|
||||
import { auth } from "stores/backend"
|
||||
import download from "downloadjs"
|
||||
import { goto } from "@roxi/routify"
|
||||
import { AppStatus } from "constants"
|
||||
import { gradient } from "actions"
|
||||
|
||||
let layout = "grid"
|
||||
let template
|
||||
let appToDelete
|
||||
let creationModal
|
||||
let deletionModal
|
||||
let creatingApp = false
|
||||
let loaded = false
|
||||
|
||||
const checkKeys = async () => {
|
||||
const response = await api.get(`/api/keys/`)
|
||||
const keys = await response.json()
|
||||
if (keys.userId) {
|
||||
analytics.identify(keys.userId)
|
||||
}
|
||||
}
|
||||
|
||||
const initiateAppCreation = () => {
|
||||
creationModal.show()
|
||||
creatingApp = true
|
||||
}
|
||||
|
||||
const initiateAppImport = () => {
|
||||
template = { fromFile: true }
|
||||
creationModal.show()
|
||||
creatingApp = true
|
||||
}
|
||||
|
||||
const stopAppCreation = () => {
|
||||
template = null
|
||||
creatingApp = false
|
||||
}
|
||||
|
||||
const openApp = app => {
|
||||
$goto(`../../app/${app._id}`)
|
||||
}
|
||||
|
||||
const exportApp = app => {
|
||||
try {
|
||||
download(
|
||||
`/api/backups/export?appId=${app._id}&appname=${encodeURIComponent(
|
||||
app.name
|
||||
)}`
|
||||
)
|
||||
notifications.success("App export complete")
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
notifications.error("App export failed")
|
||||
}
|
||||
}
|
||||
|
||||
const deleteApp = app => {
|
||||
appToDelete = app
|
||||
deletionModal.show()
|
||||
}
|
||||
|
||||
const confirmDeleteApp = async () => {
|
||||
if (!appToDelete) {
|
||||
return
|
||||
}
|
||||
await del(`/api/applications/${appToDelete?._id}`)
|
||||
await apps.load()
|
||||
appToDelete = null
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
checkKeys()
|
||||
await apps.load(AppStatus.DEV)
|
||||
loaded = true
|
||||
})
|
||||
|
||||
$: console.log($auth.user)
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
{#if loaded}
|
||||
<div class="container">
|
||||
<Page>
|
||||
<div class="content">
|
||||
<Layout noPadding>
|
||||
|
@ -104,9 +36,9 @@
|
|||
<Layout noPadding gap="XS">
|
||||
<Heading size="L">Hey {$auth.user.email}</Heading>
|
||||
<Body noPadding>
|
||||
Welcome to the {$organisation.company} portal. Below you'll find the
|
||||
list of apps that you have access to, as well as company news and the
|
||||
employee handbook.
|
||||
Welcome to the {$organisation.company} portal. Below you'll find
|
||||
the list of apps that you have access to, as well as company news
|
||||
and the employee handbook.
|
||||
</Body>
|
||||
</Layout>
|
||||
<ActionMenu align="right">
|
||||
|
@ -114,13 +46,12 @@
|
|||
<Avatar size="M" name="John Doe" />
|
||||
<Icon size="XL" name="ChevronDown" />
|
||||
</div>
|
||||
<MenuItem icon="UserEdit" on:click={auth.logout}>
|
||||
Update user information
|
||||
</MenuItem>
|
||||
<MenuItem icon="LockClosed" on:click={auth.logout}>
|
||||
Update password
|
||||
</MenuItem>
|
||||
<MenuItem icon="UserDeveloper" on:click={() => $goto("../portal")}>
|
||||
<MenuItem icon="UserEdit">Update user information</MenuItem>
|
||||
<MenuItem icon="LockClosed">Update password</MenuItem>
|
||||
<MenuItem
|
||||
icon="UserDeveloper"
|
||||
on:click={() => $goto("../portal")}
|
||||
>
|
||||
Open developer mode
|
||||
</MenuItem>
|
||||
<MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem>
|
||||
|
@ -140,7 +71,7 @@
|
|||
{/if}
|
||||
</div>
|
||||
{#each $apps as app, idx (app.appId)}
|
||||
<div class="app" on:click={() => $goto(`../app/${app.appId}`)}>
|
||||
<a class="app" target="_blank" href={`/${app.appId}`}>
|
||||
<div class="preview" use:gradient={{ seed: app.name }} />
|
||||
<div class="app-info">
|
||||
<Heading size="XS">{app.name}</Heading>
|
||||
|
@ -149,14 +80,15 @@
|
|||
</Body>
|
||||
</div>
|
||||
<Icon name="ChevronRight" />
|
||||
</div>
|
||||
</a>
|
||||
{/each}
|
||||
</Layout>
|
||||
</div>
|
||||
</Layout>
|
||||
</div>
|
||||
</Page>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.container {
|
||||
|
@ -208,6 +140,7 @@
|
|||
border-radius: var(--border-radius-s);
|
||||
align-items: center;
|
||||
grid-gap: var(--spacing-xl);
|
||||
color: inherit;
|
||||
}
|
||||
.app:hover {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<script>
|
||||
import { goto } from "@roxi/routify"
|
||||
$goto("./login")
|
||||
import { redirect } from "@roxi/routify"
|
||||
$redirect("./login")
|
||||
</script>
|
||||
|
|
|
@ -1,4 +1,14 @@
|
|||
<script>
|
||||
import { goto } from "@roxi/routify"
|
||||
$goto("./portal")
|
||||
import { redirect } from "@roxi/routify"
|
||||
import { auth } from "stores/backend"
|
||||
|
||||
$: {
|
||||
if (!$auth.user) {
|
||||
$redirect("./auth/login")
|
||||
} else if ($auth.user.builder?.global) {
|
||||
$redirect("./portal")
|
||||
} else {
|
||||
$redirect("./apps")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { isActive, goto } from "@roxi/routify"
|
||||
import { isActive, redirect, goto } from "@roxi/routify"
|
||||
import {
|
||||
Icon,
|
||||
Avatar,
|
||||
|
@ -15,12 +15,12 @@
|
|||
import { organisation } from "stores/portal"
|
||||
import { auth } from "stores/backend"
|
||||
import BuilderSettingsModal from "components/start/BuilderSettingsModal.svelte"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
let oldSettingsModal
|
||||
let loaded = false
|
||||
|
||||
organisation.init()
|
||||
|
||||
let menu = [
|
||||
const menu = [
|
||||
{ title: "Apps", href: "/builder/portal/apps" },
|
||||
{ title: "Drafts", href: "/builder/portal/drafts" },
|
||||
{ title: "Users", href: "/builder/portal/manage/users", heading: "Manage" },
|
||||
|
@ -35,9 +35,20 @@
|
|||
{ title: "Theming", href: "/builder/portal/theming" },
|
||||
{ title: "Account", href: "/builder/portal/account" },
|
||||
]
|
||||
|
||||
onMount(async () => {
|
||||
// Prevent non-builders from accessing the portal
|
||||
if (!$auth.user?.builder?.global) {
|
||||
$redirect("../")
|
||||
} else {
|
||||
await organisation.init()
|
||||
loaded = true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
{#if loaded}
|
||||
<div class="container">
|
||||
<div class="nav">
|
||||
<Layout paddingX="L" paddingY="L">
|
||||
<div class="branding">
|
||||
|
@ -79,10 +90,11 @@
|
|||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal bind:this={oldSettingsModal} width="30%">
|
||||
</div>
|
||||
<Modal bind:this={oldSettingsModal} width="30%">
|
||||
<BuilderSettingsModal />
|
||||
</Modal>
|
||||
</Modal>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.container {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<script>
|
||||
import { goto } from "@roxi/routify"
|
||||
$goto("./apps")
|
||||
import { redirect } from "@roxi/routify"
|
||||
$redirect("./apps")
|
||||
</script>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<script>
|
||||
import { goto } from "@roxi/routify"
|
||||
$goto("./builder")
|
||||
import { redirect } from "@roxi/routify"
|
||||
$redirect("./builder")
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue