forked from tsai/budibase
committed by
GitHub
15 changed files with 527 additions and 9 deletions
@ -0,0 +1,56 @@ |
|||||
|
<script> |
||||
|
import { Button } from "@budibase/bbui" |
||||
|
export let remove = false |
||||
|
</script> |
||||
|
|
||||
|
<div class="container"> |
||||
|
<div class="content"> |
||||
|
<div class="img"> |
||||
|
<img src="https://picsum.photos/60/60" alt="zoom" /> |
||||
|
</div> |
||||
|
<div class="body"> |
||||
|
<div class="title">Zoom</div> |
||||
|
<div class="description"> |
||||
|
Lorem, ipsum dolor sit amet consectetur adipisicing elit |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="footer"> |
||||
|
<Button wide error={remove} secondary={!remove} on:click> |
||||
|
<span>{remove ? 'Remove' : 'Add'}</span> |
||||
|
</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
display: grid; |
||||
|
padding: 12px; |
||||
|
background: var(--light-grey); |
||||
|
grid-gap: 20px; |
||||
|
} |
||||
|
span { |
||||
|
font-size: 12px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.content { |
||||
|
display: grid; |
||||
|
grid-gap: 12px; |
||||
|
grid-template-columns: 60px auto; |
||||
|
} |
||||
|
.title { |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.description { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
.img { |
||||
|
border-radius: 3px; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
img { |
||||
|
height: 60px; |
||||
|
width: 60px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<script> |
||||
|
import Modal from "./Modal.svelte" |
||||
|
import { SettingsIcon } from "components/common/Icons/" |
||||
|
import { getContext } from "svelte" |
||||
|
import { isActive, goto, layout } from "@sveltech/routify" |
||||
|
|
||||
|
// Handle create app modal |
||||
|
const { open } = getContext("simple-modal") |
||||
|
|
||||
|
const showSettingsModal = () => { |
||||
|
open( |
||||
|
Modal, |
||||
|
{ |
||||
|
name: "Placeholder App Name", |
||||
|
description: "This is a hardcoded description that needs to change", |
||||
|
}, |
||||
|
{ |
||||
|
closeButton: false, |
||||
|
closeOnEsc: true, |
||||
|
styleContent: { padding: 0 }, |
||||
|
closeOnOuterClick: true, |
||||
|
} |
||||
|
) |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<span class="topnavitemright" on:click={showSettingsModal}> |
||||
|
<SettingsIcon /> |
||||
|
</span> |
||||
|
|
||||
|
<style> |
||||
|
span:first-letter { |
||||
|
text-transform: capitalize; |
||||
|
} |
||||
|
.topnavitemright { |
||||
|
cursor: pointer; |
||||
|
color: var(--ink-light); |
||||
|
margin: 0px 20px 0px 0px; |
||||
|
padding-top: 4px; |
||||
|
font-weight: 500; |
||||
|
font-size: 1rem; |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
flex: 1; |
||||
|
align-items: center; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,92 @@ |
|||||
|
<script> |
||||
|
import { General, Users, DangerZone } from "./tabs" |
||||
|
|
||||
|
import { Input, TextArea, Button, Switcher } from "@budibase/bbui" |
||||
|
import { SettingsIcon, CloseIcon } from "components/common/Icons/" |
||||
|
import { getContext } from "svelte" |
||||
|
import { post } from "builderStore/api" |
||||
|
|
||||
|
const { open, close } = getContext("simple-modal") |
||||
|
export let name = "" |
||||
|
export let description = "" |
||||
|
const tabs = [ |
||||
|
{ |
||||
|
title: "General", |
||||
|
key: "GENERAL", |
||||
|
component: General, |
||||
|
}, |
||||
|
{ |
||||
|
title: "Users", |
||||
|
key: "USERS", |
||||
|
component: Users, |
||||
|
}, |
||||
|
{ |
||||
|
title: "Danger Zone", |
||||
|
key: "DANGERZONE", |
||||
|
component: DangerZone, |
||||
|
}, |
||||
|
] |
||||
|
let value = "GENERAL" |
||||
|
$: selectedTab = tabs.find(tab => tab.key === value).component |
||||
|
</script> |
||||
|
|
||||
|
<div class="container"> |
||||
|
<div class="body"> |
||||
|
<div class="heading"> |
||||
|
<span class="icon"> |
||||
|
<SettingsIcon /> |
||||
|
</span> |
||||
|
<h3>Settings</h3> |
||||
|
</div> |
||||
|
<Switcher headings={tabs} bind:value> |
||||
|
<svelte:component this={selectedTab} /> |
||||
|
</Switcher> |
||||
|
</div> |
||||
|
<div class="close-button" on:click={close}> |
||||
|
<CloseIcon /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.close-button { |
||||
|
cursor: pointer; |
||||
|
position: absolute; |
||||
|
top: 20px; |
||||
|
right: 20px; |
||||
|
} |
||||
|
.close-button :global(svg) { |
||||
|
width: 24px; |
||||
|
height: 24px; |
||||
|
} |
||||
|
.heading { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
h3 { |
||||
|
margin: 0; |
||||
|
font-size: 24px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.icon { |
||||
|
display: grid; |
||||
|
border-radius: 3px; |
||||
|
align-content: center; |
||||
|
justify-content: center; |
||||
|
margin-right: 12px; |
||||
|
height: 20px; |
||||
|
width: 20px; |
||||
|
padding: 10px; |
||||
|
background-color: var(--blue-light); |
||||
|
} |
||||
|
.body { |
||||
|
padding: 40px 40px 80px 40px; |
||||
|
display: grid; |
||||
|
grid-gap: 20px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,13 @@ |
|||||
|
<h3> |
||||
|
<slot /> |
||||
|
</h3> |
||||
|
|
||||
|
<style> |
||||
|
h3 { |
||||
|
font-size: 18px; |
||||
|
font-weight: bold; |
||||
|
color: var(--ink); |
||||
|
margin-top: 40px; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,42 @@ |
|||||
|
<script> |
||||
|
import { createEventDispatcher } from "svelte" |
||||
|
const dispatch = createEventDispatcher() |
||||
|
import { Input, Select, Button } from "@budibase/bbui" |
||||
|
export let user |
||||
|
|
||||
|
let editMode = false |
||||
|
</script> |
||||
|
|
||||
|
<div class="inputs"> |
||||
|
<Input |
||||
|
disabled |
||||
|
thin |
||||
|
bind:value={user.username} |
||||
|
name="Name" |
||||
|
placeholder="Username" /> |
||||
|
<Select disabled={!editMode} bind:value={user.accessLevelId} thin> |
||||
|
<option value="ADMIN">Admin</option> |
||||
|
<option value="POWER_USER">Power User</option> |
||||
|
</Select> |
||||
|
{#if editMode} |
||||
|
<Button |
||||
|
blue |
||||
|
on:click={() => { |
||||
|
dispatch('save', user) |
||||
|
editMode = false |
||||
|
}}> |
||||
|
Save |
||||
|
</Button> |
||||
|
{:else} |
||||
|
<Button secondary on:click={() => (editMode = true)}>Edit</Button> |
||||
|
{/if} |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.inputs { |
||||
|
display: grid; |
||||
|
justify-items: stretch; |
||||
|
grid-gap: 18px; |
||||
|
grid-template-columns: 1fr 1fr 1fr; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,46 @@ |
|||||
|
<script> |
||||
|
import { Input, TextArea, Button } from "@budibase/bbui" |
||||
|
import Title from "../TabTitle.svelte" |
||||
|
|
||||
|
let value = "" |
||||
|
let loading = false |
||||
|
|
||||
|
const deleteApp = () => { |
||||
|
loading = true |
||||
|
// Do stuff here to delete app! |
||||
|
// Navigate to start |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<Title>Danger Zone</Title> |
||||
|
<div class="background"> |
||||
|
<Input |
||||
|
on:change={e => (value = e.target.value)} |
||||
|
on:input={e => (value = e.target.value)} |
||||
|
thin |
||||
|
disabled={loading} |
||||
|
placeholder="Enter your name" |
||||
|
label="Type DELETE into the textbox, then click the following button to |
||||
|
delete your web app:" /> |
||||
|
|
||||
|
<Button |
||||
|
disabled={value !== 'DELETE' || loading} |
||||
|
primary |
||||
|
wide |
||||
|
on:click={deleteApp}> |
||||
|
Delete Entire Web App |
||||
|
</Button> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.background { |
||||
|
display: grid; |
||||
|
grid-gap: var(--space); |
||||
|
border-radius: 5px; |
||||
|
background-color: var(--light-grey); |
||||
|
padding: 12px 12px 18px 12px; |
||||
|
} |
||||
|
.background :global(button) { |
||||
|
max-width: 100%; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,26 @@ |
|||||
|
<script> |
||||
|
import { Input, TextArea, Button } from "@budibase/bbui" |
||||
|
import Title from "../TabTitle.svelte" |
||||
|
</script> |
||||
|
|
||||
|
<Title>General</Title> |
||||
|
<div class="container"> |
||||
|
<div class="background"> |
||||
|
<Input thin edit placeholder="Enter your name" label="Name" /> |
||||
|
</div> |
||||
|
<div class="background"> |
||||
|
<TextArea thin edit placeholder="Enter your name" label="Name" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
display: grid; |
||||
|
grid-gap: var(--space); |
||||
|
} |
||||
|
.background { |
||||
|
border-radius: 5px; |
||||
|
background-color: var(--light-grey); |
||||
|
padding: 12px 12px 18px 12px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,45 @@ |
|||||
|
<script> |
||||
|
import Integration from "../Integration.svelte" |
||||
|
</script> |
||||
|
|
||||
|
<div class="container"> |
||||
|
<div class="title">Your Integrations</div> |
||||
|
<div class="integrations"> |
||||
|
<Integration remove /> |
||||
|
<Integration remove /> |
||||
|
<Integration remove /> |
||||
|
<Integration remove /> |
||||
|
</div> |
||||
|
<div class="apps">Recommended apps</div> |
||||
|
<div class="integrations"> |
||||
|
<Integration /> |
||||
|
<Integration /> |
||||
|
<Integration /> |
||||
|
<Integration /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
display: grid; |
||||
|
grid-gap: 16px; |
||||
|
} |
||||
|
.integrations { |
||||
|
display: grid; |
||||
|
grid-template-columns: 1fr 1fr; |
||||
|
grid-gap: 20px; |
||||
|
} |
||||
|
.title { |
||||
|
font-size: 18px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.apps { |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.background { |
||||
|
border-radius: 5px; |
||||
|
background-color: var(--light-grey); |
||||
|
padding: 12px 12px 18px 12px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1 @@ |
|||||
|
Permissions |
||||
@ -0,0 +1,135 @@ |
|||||
|
<script> |
||||
|
import { Input, Select, Button } from "@budibase/bbui" |
||||
|
import Title from "../TabTitle.svelte" |
||||
|
import UserRow from "../UserRow.svelte" |
||||
|
|
||||
|
import { store, backendUiStore } from "builderStore" |
||||
|
import api from "builderStore/api" |
||||
|
// import * as api from "../api" |
||||
|
|
||||
|
let username = "" |
||||
|
let password = "" |
||||
|
let accessLevelId |
||||
|
|
||||
|
$: valid = username && password && accessLevelId |
||||
|
$: appId = $store.appId |
||||
|
|
||||
|
// Create user! |
||||
|
async function createUser() { |
||||
|
if (valid) { |
||||
|
const user = { name: username, username, password, accessLevelId } |
||||
|
const response = await api.post(`/api/users`, user) |
||||
|
const json = await response.json() |
||||
|
backendUiStore.actions.users.create(json) |
||||
|
fetchUsersPromise = fetchUsers() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Update user! |
||||
|
async function updateUser(event) { |
||||
|
let data = event.detail |
||||
|
delete data.password |
||||
|
const response = await api.put(`/api/users`, data) |
||||
|
const users = await response.json() |
||||
|
backendUiStore.update(state => { |
||||
|
state.users = users |
||||
|
return state |
||||
|
}) |
||||
|
fetchUsersPromise = fetchUsers() |
||||
|
} |
||||
|
|
||||
|
// Get users |
||||
|
async function fetchUsers() { |
||||
|
const response = await api.get(`/api/users`) |
||||
|
const users = await response.json() |
||||
|
backendUiStore.update(state => { |
||||
|
state.users = users |
||||
|
return state |
||||
|
}) |
||||
|
return users |
||||
|
} |
||||
|
|
||||
|
let fetchUsersPromise = fetchUsers() |
||||
|
</script> |
||||
|
|
||||
|
<Title>Users</Title> |
||||
|
<div class="container"> |
||||
|
<div class="background create"> |
||||
|
<div class="title">Create new user</div> |
||||
|
<div class="inputs"> |
||||
|
<Input thin bind:value={username} name="Name" placeholder="Username" /> |
||||
|
<Input |
||||
|
thin |
||||
|
bind:value={password} |
||||
|
name="Password" |
||||
|
placeholder="Password" /> |
||||
|
<Select bind:value={accessLevelId} thin> |
||||
|
<option value="ADMIN">Admin</option> |
||||
|
<option value="POWER_USER">Power User</option> |
||||
|
</Select> |
||||
|
</div> |
||||
|
<div class="create-button"> |
||||
|
<Button on:click={createUser} small blue>Create</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="background"> |
||||
|
<div class="title">Current Users</div> |
||||
|
{#await fetchUsersPromise} |
||||
|
Loading state! |
||||
|
{:then users} |
||||
|
<ul> |
||||
|
{#each users as user} |
||||
|
<li> |
||||
|
<UserRow {user} on:save={updateUser} /> |
||||
|
</li> |
||||
|
{:else} |
||||
|
<li>No Users found</li> |
||||
|
{/each} |
||||
|
</ul> |
||||
|
{:catch error} |
||||
|
err0r |
||||
|
{/await} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
display: grid; |
||||
|
grid-gap: 14px; |
||||
|
} |
||||
|
.background { |
||||
|
position: relative; |
||||
|
display: grid; |
||||
|
grid-gap: 12px; |
||||
|
border-radius: 5px; |
||||
|
background-color: var(--grey-2); |
||||
|
padding: 12px 12px 18px 12px; |
||||
|
} |
||||
|
.background.create { |
||||
|
background-color: var(--blue-light); |
||||
|
} |
||||
|
.inputs :global(select) { |
||||
|
padding: 12px 9px; |
||||
|
height: initial; |
||||
|
} |
||||
|
.create-button { |
||||
|
position: absolute; |
||||
|
top: 12px; |
||||
|
right: 12px; |
||||
|
} |
||||
|
.title { |
||||
|
font-size: 14px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
.inputs { |
||||
|
display: grid; |
||||
|
grid-gap: 18px; |
||||
|
grid-template-columns: 1fr 1fr 1fr; |
||||
|
} |
||||
|
ul { |
||||
|
list-style: none; |
||||
|
padding: 0; |
||||
|
display: grid; |
||||
|
grid-gap: 8px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,5 @@ |
|||||
|
export { default as General } from "./General.svelte" |
||||
|
export { default as Integrations } from "./Integrations.svelte" |
||||
|
export { default as Permissions } from "./Permissions.svelte" |
||||
|
export { default as Users } from "./Users.svelte" |
||||
|
export { default as DangerZone } from "./DangerZone.svelte" |
||||
Loading…
Reference in new issue