Fetch app definition and routes from the server

This commit is contained in:
Andrew Kingston 2020-11-19 18:39:22 +00:00
parent 71b59d7cca
commit 674b89df5d
18 changed files with 92 additions and 73 deletions

View File

@ -0,0 +1,10 @@
import API from "./api"
/**
* Fetches screen definition for an app.
*/
export const fetchAppDefinition = async appId => {
return await API.get({
url: `/api/applications/${appId}/definition`,
})
}

View File

@ -1,10 +1,10 @@
import api from "./api"
import API from "./api"
/**
* Uploads an attachment to the server.
*/
export const uploadAttachment = async data => {
return await api.post({
return await API.post({
url: "/api/attachments/upload",
body: data,
json: false,

View File

@ -1,16 +1,16 @@
import api from "./api"
import API from "./api"
/**
* Performs a log in request.
*/
export const logIn = async ({ username, password }) => {
if (!username) {
return api.error("Please enter your username")
return API.error("Please enter your username")
}
if (!password) {
return api.error("Please enter your password")
return API.error("Please enter your password")
}
return await api.post({
return await API.post({
url: "/api/authenticate",
body: { username, password },
})

View File

@ -6,3 +6,4 @@ export * from "./attachments"
export * from "./views"
export * from "./relationships"
export * from "./routes"
export * from "./app"

View File

@ -1,4 +1,4 @@
import api from "./api"
import API from "./api"
import { enrichRows } from "./rows"
/**
@ -8,7 +8,7 @@ export const fetchRelationshipData = async ({ tableId, rowId, fieldName }) => {
if (!tableId || !rowId || !fieldName) {
return []
}
const response = await api.get({ url: `/api/${tableId}/${rowId}/enrich` })
const response = await API.get({ url: `/api/${tableId}/${rowId}/enrich` })
const rows = response[fieldName] || []
return await enrichRows(rows, tableId)
}

View File

@ -1,10 +1,10 @@
import api from "./api"
import API from "./api"
/**
* Fetches available routes for the client app.
*/
export const fetchRoutes = async () => {
return await api.get({
return await API.get({
url: `/api/routing/client`,
})
}

View File

@ -1,11 +1,11 @@
import api from "./api"
import API from "./api"
import { fetchTableDefinition } from "./tables"
/**
* Fetches data about a certain row in a table.
*/
export const fetchRow = async ({ tableId, rowId }) => {
const row = await api.get({
const row = await API.get({
url: `/api/${tableId}/rows/${rowId}`,
})
return (await enrichRows([row], tableId))[0]
@ -15,7 +15,7 @@ export const fetchRow = async ({ tableId, rowId }) => {
* Creates a row in a table.
*/
export const saveRow = async row => {
return await api.post({
return await API.post({
url: `/api/${row.tableId}/rows`,
body: row,
})
@ -25,7 +25,7 @@ export const saveRow = async row => {
* Updates a row in a table.
*/
export const updateRow = async row => {
return await api.patch({
return await API.patch({
url: `/api/${row.tableId}/rows/${row._id}`,
body: row,
})
@ -35,7 +35,7 @@ export const updateRow = async row => {
* Deletes a row from a table.
*/
export const deleteRow = async ({ tableId, rowId, revId }) => {
return await api.del({
return await API.del({
url: `/api/${tableId}/rows/${rowId}/${revId}`,
})
}
@ -44,7 +44,7 @@ export const deleteRow = async ({ tableId, rowId, revId }) => {
* Deletes many rows from a table.
*/
export const deleteRows = async ({ tableId, rows }) => {
return await api.post({
return await API.post({
url: `/api/${tableId}/rows`,
body: {
rows,

View File

@ -1,4 +1,4 @@
import api from "./api"
import API from "./api"
import { enrichRows } from "./rows"
/**
@ -6,13 +6,13 @@ import { enrichRows } from "./rows"
* Since definitions cannot change at runtime, the result is cached.
*/
export const fetchTableDefinition = async tableId => {
return await api.get({ url: `/api/tables/${tableId}`, cache: true })
return await API.get({ url: `/api/tables/${tableId}`, cache: true })
}
/**
* Fetches all rows from a table.
*/
export const fetchTableData = async tableId => {
const rows = await api.get({ url: `/api/${tableId}/rows` })
const rows = await API.get({ url: `/api/${tableId}/rows` })
return await enrichRows(rows, tableId)
}

View File

@ -1,4 +1,4 @@
import api from "./api"
import API from "./api"
import { enrichRows } from "./rows"
/**
@ -25,6 +25,6 @@ export const fetchViewData = async ({
? `/api/views/${name}?${params}`
: `/api/views/${name}`
const rows = await api.get({ url: QUERY_VIEW_URL })
const rows = await API.get({ url: QUERY_VIEW_URL })
return await enrichRows(rows, tableId)
}

View File

@ -1,14 +1,22 @@
<script>
import { setContext } from "svelte"
import { setContext, onMount } from "svelte"
import Component from "./Component.svelte"
import SDK from "../sdk"
import { routeStore, screenStore } from "../store"
// Provide SDK for components
setContext("app", SDK)
const frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
$: pageDefinition = frontendDefinition?.page?.props
$: console.log(frontendDefinition)
let loaded = false
// Load app config
onMount(async () => {
await routeStore.actions.fetchRoutes()
await screenStore.actions.fetchScreens()
loaded = true
})
</script>
<Component definition={pageDefinition} />
{#if loaded}
<Component definition={$screenStore.page.props} />
{/if}

View File

@ -6,27 +6,26 @@
import { styleable } from "../utils"
export let styles
let routes
$: routerConfig = getRouterConfig($routeStore.routes)
onMount(async () => {
await routeStore.actions.fetchRoutes()
await screenStore.actions.fetchScreens()
routes = {}
$routeStore.routes.forEach(route => {
routes[route.path] = Screen
const getRouterConfig = routes => {
let config = {}
routes.forEach(route => {
config[route.path] = Screen
})
// Add catch-all route so that we serve the Screen component always
routes["*"] = Screen
})
config["*"] = Screen
return config
}
function onRouteLoading({ detail }) {
const onRouteLoading = ({ detail }) => {
routeStore.actions.setActiveRoute(detail.route)
}
</script>
{#if routes}
{#if routerConfig}
<div use:styleable={styles}>
<Router on:routeLoading={onRouteLoading} {routes} />
<Router on:routeLoading={onRouteLoading} routes={routerConfig} />
</div>
{/if}

View File

@ -1,6 +1,7 @@
import * as API from "../api"
import { getAppId } from "../utils"
import { writable } from "svelte/store"
import { loc } from "svelte-spa-router"
const createAuthStore = () => {
const store = writable("")
@ -12,8 +13,8 @@ const createAuthStore = () => {
const user = await API.logIn({ username, password })
if (!user.error) {
store.set(user.token)
location.reload()
}
return !user.error
}
/**
@ -21,14 +22,13 @@ const createAuthStore = () => {
*/
const logOut = () => {
store.set("")
// Expire any cookies
const appId = getAppId()
if (appId) {
for (let environment of ["local", "cloud"]) {
window.document.cookie = `budibase:${appId}:${environment}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`
}
}
location.reload()
}
return {

View File

@ -12,18 +12,15 @@ const createRouteStore = () => {
const fetchRoutes = async () => {
const routeConfig = await API.fetchRoutes()
let routes = {}
Object.values(routeConfig.routes).forEach(pathConfig => {
Object.entries(config).forEach(([subPath, subPathConfig]) => {})
let routes = []
Object.values(routeConfig.routes).forEach(route => {
Object.entries(route.subpaths).forEach(([path, config]) => {
routes.push({
path,
screenId: config.screenId,
})
})
})
console.log(routes2)
const frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
const routes = frontendDefinition.screens.map(screen => ({
path: screen.route,
screenId: screen._id,
}))
store.update(state => {
state.routes = routes
return state

View File

@ -1,22 +1,34 @@
import { writable, derived } from "svelte/store"
import { routeStore } from "./routes"
import * as API from "../api"
import { getAppId } from "../utils"
const createScreenStore = () => {
const screens = writable([])
const store = derived([screens, routeStore], ([$screens, $routeStore]) => {
const config = writable({
screens: [],
page: {},
})
const store = derived([config, routeStore], ([$config, $routeStore]) => {
const { screens, page } = $config
const activeScreen =
$screens.length === 1
? $screens[0]
: $screens.find(screen => screen.route === $routeStore.activeRoute)
screens.length === 1
? screens[0]
: screens.find(
screen => screen.routing.route === $routeStore.activeRoute
)
return {
screens: $screens,
screens,
page,
activeScreen,
}
})
const fetchScreens = () => {
const frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
screens.set(frontendDefinition.screens)
const fetchScreens = async () => {
const appDefinition = await API.fetchAppDefinition(getAppId())
config.set({
screens: appDefinition.screens,
page: appDefinition.page,
})
}
return {

View File

@ -14,12 +14,10 @@
<style>
div {
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
}
div :global(> *) {
flex: 1 1 auto;
width: 100%;
height: 100%;
position: absolute;
}
</style>

View File

@ -24,12 +24,7 @@
const login = async () => {
loading = true
const success = await authStore.actions.logIn({ username, password })
if (success) {
location.reload()
} else {
error = true
}
await authStore.actions.logIn({ username, password })
loading = false
}
</script>

View File

@ -9,7 +9,6 @@
const logOut = () => {
authStore.actions.logOut()
location.reload()
}
</script>