Update parts of builder with core API refactor
This commit is contained in:
parent
b74815d41b
commit
6a7aed1c0d
|
@ -1,8 +1,9 @@
|
|||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import PosthogClient from "./PosthogClient"
|
||||
import IntercomClient from "./IntercomClient"
|
||||
import SentryClient from "./SentryClient"
|
||||
import { Events } from "./constants"
|
||||
import { notifications } from "@budibase/bbui"
|
||||
|
||||
const posthog = new PosthogClient(
|
||||
process.env.POSTHOG_TOKEN,
|
||||
|
@ -17,13 +18,15 @@ class AnalyticsHub {
|
|||
}
|
||||
|
||||
async activate() {
|
||||
const analyticsStatus = await api.get("/api/analytics")
|
||||
const json = await analyticsStatus.json()
|
||||
|
||||
// Analytics disabled
|
||||
if (!json.enabled) return
|
||||
|
||||
this.clients.forEach(client => client.init())
|
||||
try {
|
||||
// Check analytics are enabled
|
||||
const analyticsStatus = await API.getAnalyticsStatus()
|
||||
if (analyticsStatus.enabled) {
|
||||
this.clients.forEach(client => client.init())
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error("Error checking analytics status")
|
||||
}
|
||||
}
|
||||
|
||||
identify(id, metadata) {
|
||||
|
|
|
@ -1,40 +1,44 @@
|
|||
import {
|
||||
createAPIClient,
|
||||
CookieUtils,
|
||||
Constants,
|
||||
} from "@budibase/frontend-core"
|
||||
import { store } from "./index"
|
||||
import { get as svelteGet } from "svelte/store"
|
||||
import { CookieUtils, Constants } from "@budibase/frontend-core"
|
||||
import { get } from "svelte/store"
|
||||
import { notifications } from "@budibase/bbui"
|
||||
|
||||
const apiCall =
|
||||
method =>
|
||||
async (url, body, headers = { "Content-Type": "application/json" }) => {
|
||||
headers["x-budibase-app-id"] = svelteGet(store).appId
|
||||
const json = headers["Content-Type"] === "application/json"
|
||||
const resp = await fetch(url, {
|
||||
method: method,
|
||||
body: json ? JSON.stringify(body) : body,
|
||||
headers,
|
||||
})
|
||||
if (resp.status === 403) {
|
||||
export const API = createAPIClient({
|
||||
attachHeaders: headers => {
|
||||
// Attach app ID header from store
|
||||
headers["x-budibase-app-id"] = get(store).appId
|
||||
},
|
||||
|
||||
onError: error => {
|
||||
const { url, message, status } = error
|
||||
|
||||
// Log all API errors to Sentry
|
||||
// analytics.captureException(error)
|
||||
|
||||
// Show a notification for any errors
|
||||
if (message) {
|
||||
notifications.error(`Error fetching ${url}: ${message}`)
|
||||
}
|
||||
|
||||
// Logout on 403's
|
||||
if (status === 403) {
|
||||
// Don't do anything if fetching templates.
|
||||
// TODO: clarify why this is here
|
||||
if (url.includes("/api/templates")) {
|
||||
return { json: () => [] }
|
||||
return
|
||||
}
|
||||
|
||||
// Remove the auth cookie
|
||||
CookieUtils.removeCookie(Constants.Cookies.Auth)
|
||||
// reload after removing cookie, go to login
|
||||
|
||||
// Reload after removing cookie, go to login
|
||||
if (!url.includes("self") && !url.includes("login")) {
|
||||
location.reload()
|
||||
}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
export const post = apiCall("POST")
|
||||
export const get = apiCall("GET")
|
||||
export const patch = apiCall("PATCH")
|
||||
export const del = apiCall("DELETE")
|
||||
export const put = apiCall("PUT")
|
||||
|
||||
export default {
|
||||
post: apiCall("POST"),
|
||||
get: apiCall("GET"),
|
||||
patch: apiCall("PATCH"),
|
||||
delete: apiCall("DELETE"),
|
||||
put: apiCall("PUT"),
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import { get } from "builderStore/api"
|
||||
|
||||
/**
|
||||
* Fetches the definitions for component library components. This includes
|
||||
* their props and other metadata from components.json.
|
||||
* @param {string} appId - ID of the currently running app
|
||||
*/
|
||||
export const fetchComponentLibDefinitions = async appId => {
|
||||
const LIB_DEFINITION_URL = `/api/${appId}/components/definitions`
|
||||
try {
|
||||
const libDefinitionResponse = await get(LIB_DEFINITION_URL)
|
||||
return await libDefinitionResponse.json()
|
||||
} catch (err) {
|
||||
console.error(`Error fetching component definitions for ${appId}`, err)
|
||||
}
|
||||
}
|
|
@ -15,8 +15,7 @@ import {
|
|||
database,
|
||||
tables,
|
||||
} from "stores/backend"
|
||||
import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
|
||||
import api from "../api"
|
||||
import { API } from "api"
|
||||
import { FrontendTypes } from "constants"
|
||||
import analytics, { Events } from "analytics"
|
||||
import {
|
||||
|
@ -29,6 +28,7 @@ import {
|
|||
} from "../componentUtils"
|
||||
import { Helpers } from "@budibase/bbui"
|
||||
import { removeBindings } from "../dataBinding"
|
||||
import { notifications } from "@budibase/bbui"
|
||||
|
||||
const INITIAL_FRONTEND_STATE = {
|
||||
apps: [],
|
||||
|
@ -68,15 +68,12 @@ export const getFrontendStore = () => {
|
|||
store.actions = {
|
||||
initialise: async pkg => {
|
||||
const { layouts, screens, application, clientLibPath } = pkg
|
||||
const components = await fetchComponentLibDefinitions(application.appId)
|
||||
// make sure app isn't locked
|
||||
if (
|
||||
components &&
|
||||
components.status === 400 &&
|
||||
components.message?.includes("lock")
|
||||
) {
|
||||
throw { ok: false, reason: "locked" }
|
||||
}
|
||||
|
||||
// Fetch component definitions.
|
||||
// Allow errors to propagate.
|
||||
let components = await API.fetchComponentLibDefinitions(application.appId)
|
||||
|
||||
// Reset store state
|
||||
store.update(state => ({
|
||||
...state,
|
||||
libraries: application.componentLibraries,
|
||||
|
@ -100,56 +97,57 @@ export const getFrontendStore = () => {
|
|||
version: application.version,
|
||||
revertableVersion: application.revertableVersion,
|
||||
}))
|
||||
await hostingStore.actions.fetch()
|
||||
|
||||
// Initialise backend stores
|
||||
const [_integrations] = await Promise.all([
|
||||
api.get("/api/integrations").then(r => r.json()),
|
||||
])
|
||||
datasources.init()
|
||||
integrations.set(_integrations)
|
||||
queries.init()
|
||||
database.set(application.instance)
|
||||
tables.init()
|
||||
await hostingStore.actions.fetch()
|
||||
await datasources.init()
|
||||
await integrations.init()
|
||||
await queries.init()
|
||||
await tables.init()
|
||||
},
|
||||
theme: {
|
||||
save: async theme => {
|
||||
const appId = get(store).appId
|
||||
const response = await api.put(`/api/applications/${appId}`, { theme })
|
||||
if (response.status === 200) {
|
||||
const metadata = { appId, theme }
|
||||
try {
|
||||
await API.saveAppMetadata(metadata)
|
||||
store.update(state => {
|
||||
state.theme = theme
|
||||
return state
|
||||
})
|
||||
} else {
|
||||
throw new Error("Error updating theme")
|
||||
} catch (error) {
|
||||
notifications.error("Error updating theme")
|
||||
}
|
||||
},
|
||||
},
|
||||
customTheme: {
|
||||
save: async customTheme => {
|
||||
const appId = get(store).appId
|
||||
const response = await api.put(`/api/applications/${appId}`, {
|
||||
customTheme,
|
||||
})
|
||||
if (response.status === 200) {
|
||||
const metadata = { appId, customTheme }
|
||||
try {
|
||||
await API.saveAppMetadata(metadata)
|
||||
store.update(state => {
|
||||
state.customTheme = customTheme
|
||||
return state
|
||||
})
|
||||
} else {
|
||||
throw new Error("Error updating theme")
|
||||
} catch (error) {
|
||||
notifications.error("Error updating custom theme")
|
||||
}
|
||||
},
|
||||
},
|
||||
routing: {
|
||||
fetch: async () => {
|
||||
const response = await api.get("/api/routing")
|
||||
const json = await response.json()
|
||||
store.update(state => {
|
||||
state.routes = json.routes
|
||||
return state
|
||||
})
|
||||
try {
|
||||
const routes = await API.getAppRoutes()
|
||||
console.log(routes)
|
||||
store.update(state => {
|
||||
state.routes = routes.routes
|
||||
return state
|
||||
})
|
||||
} catch (error) {
|
||||
notifications.error("Error fetching app routes")
|
||||
}
|
||||
},
|
||||
},
|
||||
screens: {
|
||||
|
@ -172,81 +170,100 @@ export const getFrontendStore = () => {
|
|||
})
|
||||
},
|
||||
create: async screen => {
|
||||
screen = await store.actions.screens.save(screen)
|
||||
store.update(state => {
|
||||
state.selectedScreenId = screen._id
|
||||
state.selectedComponentId = screen.props._id
|
||||
state.currentFrontEndType = FrontendTypes.SCREEN
|
||||
selectedAccessRole.set(screen.routing.roleId)
|
||||
return state
|
||||
})
|
||||
return screen
|
||||
try {
|
||||
const savedScreen = await API.saveScreen(screen)
|
||||
store.update(state => {
|
||||
state.selectedScreenId = savedScreen._id
|
||||
state.selectedComponentId = savedScreen.props._id
|
||||
state.currentFrontEndType = FrontendTypes.SCREEN
|
||||
selectedAccessRole.set(savedScreen.routing.roleId)
|
||||
return savedScreen
|
||||
})
|
||||
|
||||
// Refresh routes
|
||||
await store.actions.routing.fetch()
|
||||
return savedScreen
|
||||
} catch (error) {
|
||||
notifications.error("Error creating screen")
|
||||
return null
|
||||
}
|
||||
},
|
||||
save: async screen => {
|
||||
const creatingNewScreen = screen._id === undefined
|
||||
const response = await api.post(`/api/screens`, screen)
|
||||
if (response.status !== 200) {
|
||||
return
|
||||
}
|
||||
screen = await response.json()
|
||||
await store.actions.routing.fetch()
|
||||
try {
|
||||
const creatingNewScreen = screen._id === undefined
|
||||
const savedScreen = await API.saveScreen(screen)
|
||||
store.update(state => {
|
||||
const idx = state.screens.findIndex(x => x._id === savedScreen._id)
|
||||
if (idx !== -1) {
|
||||
state.screens.splice(idx, 1, savedScreen)
|
||||
} else {
|
||||
state.screens.push(savedScreen)
|
||||
}
|
||||
return state
|
||||
})
|
||||
|
||||
store.update(state => {
|
||||
const foundScreen = state.screens.findIndex(
|
||||
el => el._id === screen._id
|
||||
)
|
||||
if (foundScreen !== -1) {
|
||||
state.screens.splice(foundScreen, 1)
|
||||
// Refresh routes
|
||||
await store.actions.routing.fetch()
|
||||
|
||||
// Select the new screen if creating a new one
|
||||
if (creatingNewScreen) {
|
||||
store.actions.screens.select(savedScreen._id)
|
||||
}
|
||||
state.screens.push(screen)
|
||||
return state
|
||||
})
|
||||
|
||||
if (creatingNewScreen) {
|
||||
store.actions.screens.select(screen._id)
|
||||
return savedScreen
|
||||
} catch (error) {
|
||||
notifications.error("Error saving screen")
|
||||
return null
|
||||
}
|
||||
|
||||
return screen
|
||||
},
|
||||
delete: async screens => {
|
||||
const screensToDelete = Array.isArray(screens) ? screens : [screens]
|
||||
|
||||
const screenDeletePromises = []
|
||||
store.update(state => {
|
||||
for (let screenToDelete of screensToDelete) {
|
||||
state.screens = state.screens.filter(
|
||||
screen => screen._id !== screenToDelete._id
|
||||
// Build array of promises to speed up bulk deletions
|
||||
const promises = []
|
||||
screensToDelete.forEach(screen => {
|
||||
// Delete the screen
|
||||
promises.push(
|
||||
API.deleteScreen({
|
||||
screenId: screen._id,
|
||||
screenRev: screen._rev,
|
||||
})
|
||||
)
|
||||
// Remove links to this screen
|
||||
promises.push(
|
||||
store.actions.components.links.delete(
|
||||
screen.routing.route,
|
||||
screen.props._instanceName
|
||||
)
|
||||
screenDeletePromises.push(
|
||||
api.delete(
|
||||
`/api/screens/${screenToDelete._id}/${screenToDelete._rev}`
|
||||
)
|
||||
)
|
||||
if (screenToDelete._id === state.selectedScreenId) {
|
||||
)
|
||||
})
|
||||
|
||||
try {
|
||||
await Promise.all(promises)
|
||||
const deletedIds = screensToDelete.map(screen => screen._id)
|
||||
store.update(state => {
|
||||
// Remove deleted screens from state
|
||||
state.screens = state.screens.filter(screen => {
|
||||
return !deletedIds.includes(screen._id)
|
||||
})
|
||||
// Deselect the current screen if it was deleted
|
||||
if (deletedIds.includes(state.selectedScreenId)) {
|
||||
state.selectedScreenId = null
|
||||
}
|
||||
//remove the link for this screen
|
||||
screenDeletePromises.push(
|
||||
store.actions.components.links.delete(
|
||||
screenToDelete.routing.route,
|
||||
screenToDelete.props._instanceName
|
||||
)
|
||||
)
|
||||
}
|
||||
return state
|
||||
})
|
||||
await Promise.all(screenDeletePromises)
|
||||
return state
|
||||
})
|
||||
} catch (error) {
|
||||
notifications.error("Error deleting screens")
|
||||
}
|
||||
},
|
||||
},
|
||||
preview: {
|
||||
saveSelected: async () => {
|
||||
const state = get(store)
|
||||
const selectedAsset = get(currentAsset)
|
||||
|
||||
if (state.currentFrontEndType !== FrontendTypes.LAYOUT) {
|
||||
await store.actions.screens.save(selectedAsset)
|
||||
return await store.actions.screens.save(selectedAsset)
|
||||
} else {
|
||||
await store.actions.layouts.save(selectedAsset)
|
||||
return await store.actions.layouts.save(selectedAsset)
|
||||
}
|
||||
},
|
||||
setDevice: device => {
|
||||
|
@ -270,36 +287,28 @@ export const getFrontendStore = () => {
|
|||
})
|
||||
},
|
||||
save: async layout => {
|
||||
const layoutToSave = cloneDeep(layout)
|
||||
const creatingNewLayout = layoutToSave._id === undefined
|
||||
const response = await api.post(`/api/layouts`, layoutToSave)
|
||||
const savedLayout = await response.json()
|
||||
try {
|
||||
const creatingNewLayout = layout._id === undefined
|
||||
const savedLayout = await API.saveLayout(layout)
|
||||
store.update(state => {
|
||||
const idx = state.layouts.findIndex(x => x._id === savedLayout._id)
|
||||
if (idx !== -1) {
|
||||
state.layouts.splice(idx, 1, savedLayout)
|
||||
} else {
|
||||
state.layouts.push(savedLayout)
|
||||
}
|
||||
return state
|
||||
})
|
||||
|
||||
// Abort if saving failed
|
||||
if (response.status !== 200) {
|
||||
return
|
||||
}
|
||||
|
||||
store.update(state => {
|
||||
const layoutIdx = state.layouts.findIndex(
|
||||
stateLayout => stateLayout._id === savedLayout._id
|
||||
)
|
||||
if (layoutIdx >= 0) {
|
||||
// update existing layout
|
||||
state.layouts.splice(layoutIdx, 1, savedLayout)
|
||||
} else {
|
||||
// save new layout
|
||||
state.layouts.push(savedLayout)
|
||||
// Select layout if creating a new one
|
||||
if (creatingNewLayout) {
|
||||
store.actions.layouts.select(savedLayout._id)
|
||||
}
|
||||
return state
|
||||
})
|
||||
|
||||
// Select layout if creating a new one
|
||||
if (creatingNewLayout) {
|
||||
store.actions.layouts.select(savedLayout._id)
|
||||
return savedLayout
|
||||
} catch (error) {
|
||||
notifications.error("Error saving layout")
|
||||
return null
|
||||
}
|
||||
|
||||
return savedLayout
|
||||
},
|
||||
find: layoutId => {
|
||||
if (!layoutId) {
|
||||
|
@ -308,23 +317,26 @@ export const getFrontendStore = () => {
|
|||
const storeContents = get(store)
|
||||
return storeContents.layouts.find(layout => layout._id === layoutId)
|
||||
},
|
||||
delete: async layoutToDelete => {
|
||||
const response = await api.delete(
|
||||
`/api/layouts/${layoutToDelete._id}/${layoutToDelete._rev}`
|
||||
)
|
||||
if (response.status !== 200) {
|
||||
const json = await response.json()
|
||||
throw new Error(json.message)
|
||||
delete: async layout => {
|
||||
if (!layout?._id) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await API.deleteLayout({
|
||||
layoutId: layout._id,
|
||||
layoutRev: layout._rev,
|
||||
})
|
||||
store.update(state => {
|
||||
// Select main layout if we deleted the selected layout
|
||||
if (layout._id === state.selectedLayoutId) {
|
||||
state.selectedLayoutId = get(mainLayout)._id
|
||||
}
|
||||
state.layouts = state.layouts.filter(x => x._id !== layout._id)
|
||||
return state
|
||||
})
|
||||
} catch (error) {
|
||||
notifications.error("Failed to delete layout")
|
||||
}
|
||||
store.update(state => {
|
||||
state.layouts = state.layouts.filter(
|
||||
layout => layout._id !== layoutToDelete._id
|
||||
)
|
||||
if (layoutToDelete._id === state.selectedLayoutId) {
|
||||
state.selectedLayoutId = get(mainLayout)._id
|
||||
}
|
||||
return state
|
||||
})
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
@ -414,16 +426,12 @@ export const getFrontendStore = () => {
|
|||
componentName,
|
||||
presetProps
|
||||
)
|
||||
if (!componentInstance) {
|
||||
if (!componentInstance || !asset) {
|
||||
return
|
||||
}
|
||||
|
||||
// Find parent node to attach this component to
|
||||
let parentComponent
|
||||
|
||||
if (!asset) {
|
||||
return
|
||||
}
|
||||
if (selected) {
|
||||
// Use current screen or layout as parent if no component is selected
|
||||
const definition = store.actions.components.getDefinition(
|
||||
|
@ -451,19 +459,24 @@ export const getFrontendStore = () => {
|
|||
parentComponent._children.push(componentInstance)
|
||||
|
||||
// Save components and update UI
|
||||
await store.actions.preview.saveSelected()
|
||||
store.update(state => {
|
||||
state.currentView = "component"
|
||||
state.selectedComponentId = componentInstance._id
|
||||
return state
|
||||
})
|
||||
const savedAsset = await store.actions.preview.saveSelected()
|
||||
if (savedAsset) {
|
||||
store.update(state => {
|
||||
state.currentView = "component"
|
||||
state.selectedComponentId = componentInstance._id
|
||||
return state
|
||||
})
|
||||
|
||||
// Log event
|
||||
analytics.captureEvent(Events.COMPONENT.CREATED, {
|
||||
name: componentInstance._component,
|
||||
})
|
||||
// Log event
|
||||
analytics.captureEvent(Events.COMPONENT.CREATED, {
|
||||
name: componentInstance._component,
|
||||
})
|
||||
|
||||
return componentInstance
|
||||
return componentInstance
|
||||
} else {
|
||||
notifications.error("Failed to create component")
|
||||
return null
|
||||
}
|
||||
},
|
||||
delete: async component => {
|
||||
if (!component) {
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { generate } from "shortid"
|
||||
|
||||
export const notificationStore = writable({
|
||||
notifications: [],
|
||||
})
|
||||
|
||||
export function send(message, type = "default") {
|
||||
notificationStore.update(state => {
|
||||
state.notifications = [
|
||||
...state.notifications,
|
||||
{ id: generate(), type, message },
|
||||
]
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
export const notifier = {
|
||||
danger: msg => send(msg, "danger"),
|
||||
warning: msg => send(msg, "warning"),
|
||||
info: msg => send(msg, "info"),
|
||||
success: msg => send(msg, "success"),
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { Button, Modal, notifications, ModalContent } from "@budibase/bbui"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import analytics, { Events } from "analytics"
|
||||
import { store } from "builderStore"
|
||||
|
||||
|
@ -9,18 +9,14 @@
|
|||
|
||||
async function deployApp() {
|
||||
try {
|
||||
const response = await api.post("/api/deploy")
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`status ${response.status}`)
|
||||
} else {
|
||||
analytics.captureEvent(Events.APP.PUBLISHED, {
|
||||
appId: $store.appId,
|
||||
})
|
||||
notifications.success(`Application published successfully`)
|
||||
}
|
||||
} catch (err) {
|
||||
analytics.captureException(err)
|
||||
notifications.error(`Error publishing app: ${err}`)
|
||||
await API.deployApp()
|
||||
analytics.captureEvent(Events.APP.PUBLISHED, {
|
||||
appId: $store.appId,
|
||||
})
|
||||
notifications.success("Application published successfully")
|
||||
} catch (error) {
|
||||
analytics.captureException(error)
|
||||
notifications.error("Error publishing app")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// This will eventually be replaced by the new client implementation when we
|
||||
// add a core package.
|
||||
import { writable, derived, get } from "svelte/store"
|
||||
import * as API from "../builderStore/api"
|
||||
import { API } from "api"
|
||||
import { LuceneUtils } from "@budibase/frontend-core"
|
||||
|
||||
const defaultOptions = {
|
||||
|
@ -50,7 +50,7 @@ export const fetchTableData = opts => {
|
|||
const fetchPage = async bookmark => {
|
||||
lastBookmark = bookmark
|
||||
const { tableId, limit, sortColumn, sortOrder, paginate } = options
|
||||
const res = await API.post(`/api/${options.tableId}/search`, {
|
||||
return await API.searchTable({
|
||||
tableId,
|
||||
query,
|
||||
limit,
|
||||
|
@ -60,7 +60,6 @@ export const fetchTableData = opts => {
|
|||
paginate,
|
||||
bookmark,
|
||||
})
|
||||
return await res.json()
|
||||
}
|
||||
|
||||
// Fetches a fresh set of results from the server
|
||||
|
@ -77,7 +76,7 @@ export const fetchTableData = opts => {
|
|||
// are objects
|
||||
let enrichedSchema = schema
|
||||
if (!enrichedSchema) {
|
||||
const definition = await API.get(`/api/tables/${tableId}`)
|
||||
const definition = await API.fetchTableDefinition(tableId)
|
||||
enrichedSchema = definition?.schema ?? null
|
||||
}
|
||||
if (enrichedSchema) {
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { API } from "api"
|
||||
|
||||
export const integrations = writable({})
|
||||
const createIntegrationsStore = () => {
|
||||
const store = writable(null)
|
||||
|
||||
return {
|
||||
...store,
|
||||
init: async () => {
|
||||
try {
|
||||
const integrations = await API.getIntegrations()
|
||||
store.set(integrations)
|
||||
} catch (error) {
|
||||
store.set(null)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const integrations = createIntegrationsStore()
|
||||
|
|
|
@ -56,6 +56,10 @@ export default ({ mode }) => {
|
|||
find: "stores",
|
||||
replacement: path.resolve("./src/stores"),
|
||||
},
|
||||
{
|
||||
find: "api",
|
||||
replacement: path.resolve("./src/builderStore/api.js"),
|
||||
},
|
||||
{
|
||||
find: "constants",
|
||||
replacement: path.resolve("./src/constants"),
|
||||
|
|
|
@ -7,4 +7,13 @@ export const buildAnalyticsEndpoints = API => ({
|
|||
url: `/api/analytics/ping`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the current status of analytics for this environment
|
||||
*/
|
||||
getAnalyticsStatus: async () => {
|
||||
return await API.get({
|
||||
url: "/api/analytics",
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
@ -7,4 +7,27 @@ export const buildAppEndpoints = API => ({
|
|||
url: `/api/applications/${appId}/appPackage`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Saves and patches metadata about an app
|
||||
* @param metadata the app metadata to save
|
||||
*/
|
||||
saveAppMetadata: async metadata => {
|
||||
if (!metadata?.appId) {
|
||||
throw API.error("App metadata must have an appId set")
|
||||
}
|
||||
return await API.put({
|
||||
url: `/api/applications/${metadata.appId}`,
|
||||
body: metadata,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Deploys the current app.
|
||||
*/
|
||||
deployApp: async () => {
|
||||
return await API.post({
|
||||
url: "/api/deploy",
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
export const buildBuilderEndpoints = API => ({
|
||||
/**
|
||||
* Fetches the definitions for component library components. This includes
|
||||
* their props and other metadata from components.json.
|
||||
* @param {string} appId - ID of the currently running app
|
||||
*/
|
||||
fetchComponentLibDefinitions: async appId => {
|
||||
return await API.get({ url: `/api/${appId}/components/definitions` })
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the list of available integrations.
|
||||
*/
|
||||
getIntegrations: async () => {
|
||||
return await API.get({ url: "/api/integrations" })
|
||||
},
|
||||
})
|
|
@ -8,6 +8,7 @@ import { buildQueryEndpoints } from "./queries"
|
|||
import { buildRelationshipEndpoints } from "./relationships"
|
||||
import { buildRouteEndpoints } from "./routes"
|
||||
import { buildRowEndpoints } from "./rows"
|
||||
import { buildScreenEndpoints } from "./screens"
|
||||
import { buildTableEndpoints } from "./tables"
|
||||
import { buildViewEndpoints } from "./views"
|
||||
|
||||
|
@ -167,6 +168,7 @@ export const createAPIClient = config => {
|
|||
...buildRelationshipEndpoints(API),
|
||||
...buildRouteEndpoints(API),
|
||||
...buildRowEndpoints(API),
|
||||
...buildScreenEndpoints(API),
|
||||
...buildTableEndpoints(API),
|
||||
...buildViewEndpoints(API),
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
export const buildLayoutEndpoints = API => ({
|
||||
/**
|
||||
* Saves a layout.
|
||||
* @param layout the layout to save
|
||||
*/
|
||||
saveLayout: async layout => {
|
||||
return await API.post({
|
||||
url: "/api/layouts",
|
||||
body: layout,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a layout.
|
||||
* @param layoutId the ID of the layout to delete
|
||||
* @param layoutRev the rev of the layout to delete
|
||||
*/
|
||||
deleteLayout: async ({ layoutId, layoutRev }) => {
|
||||
return await API.delete({
|
||||
url: `/api/layouts/${layoutId}/${layoutRev}`,
|
||||
})
|
||||
},
|
||||
})
|
|
@ -7,4 +7,10 @@ export const buildRouteEndpoints = API => ({
|
|||
url: `/api/routing/client`,
|
||||
})
|
||||
},
|
||||
|
||||
fetchAppRoutes: async () => {
|
||||
return await API.get({
|
||||
url: "/api/routing",
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
export const buildScreenEndpoints = API => ({
|
||||
/**
|
||||
* Saves a screen definition
|
||||
* @param screen the screen to save
|
||||
*/
|
||||
saveScreen: async screen => {
|
||||
return await API.post({
|
||||
url: "/api/screens",
|
||||
body: screen,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a screen.
|
||||
* @param screenId the ID of the screen to delete
|
||||
* @param screenRev the rev of the screen to delete
|
||||
*/
|
||||
deleteScreen: async ({ screenId, screenRev }) => {
|
||||
return await API.delete({
|
||||
url: `/api/screens/${screenId}/${screenRev}`,
|
||||
})
|
||||
},
|
||||
})
|
Loading…
Reference in New Issue