diff --git a/packages/component-sdk/src/api/api.js b/packages/component-sdk/src/api/api.js
index e7cc5261e0..6cc643872a 100644
--- a/packages/component-sdk/src/api/api.js
+++ b/packages/component-sdk/src/api/api.js
@@ -11,7 +11,7 @@ let cache = {}
* Makes a fully formatted URL based on the SDK configuration.
*/
const makeFullURL = path => {
- const { proto, domain, port } = get(configStore).config
+ const { proto, domain, port } = get(configStore)
let url = `/${path}`.replace("//", "/")
return domain ? `${proto}://${domain}:${port}${url}` : url
}
@@ -28,15 +28,17 @@ const handleError = error => {
* Performs an API call to the server.
* App ID header is always correctly set.
*/
-const makeApiCall = async ({ method, url, body }) => {
+const makeApiCall = async ({ method, url, body, json = true }) => {
try {
+ const requestBody = json ? JSON.stringify(body) : body
const response = await fetch(url, {
method,
headers: {
+ Accept: "application/json",
"Content-Type": "application/json",
"x-budibase-app-id": getAppId(window.document.cookie),
},
- body: body && JSON.stringify(body),
+ body: requestBody,
credentials: "same-origin",
})
switch (response.status) {
@@ -79,10 +81,11 @@ const makeCachedApiCall = async params => {
/**
* Constructs an API call function for a particular HTTP method.
*/
-const requestApiCall = method => async ({ url, body, cache = false }) => {
+const requestApiCall = method => async params => {
+ const { url, cache = false } = params
const fullURL = makeFullURL(url)
- const params = { method, url: fullURL, body }
- return await (cache ? makeCachedApiCall : makeApiCall)(params)
+ const enrichedParams = { ...params, method, url: fullURL }
+ return await (cache ? makeCachedApiCall : makeApiCall)(enrichedParams)
}
export default {
diff --git a/packages/component-sdk/src/api/attachments.js b/packages/component-sdk/src/api/attachments.js
new file mode 100644
index 0000000000..68bc7df415
--- /dev/null
+++ b/packages/component-sdk/src/api/attachments.js
@@ -0,0 +1,12 @@
+import api from "./api"
+
+/**
+ * Uploads an attachment to the server.
+ */
+export const uploadAttachment = async data => {
+ return await api.post({
+ url: "/api/attachments/upload",
+ body: data,
+ json: false,
+ })
+}
diff --git a/packages/component-sdk/src/api/datasources.js b/packages/component-sdk/src/api/datasources.js
index acea8ab640..4c614b0085 100644
--- a/packages/component-sdk/src/api/datasources.js
+++ b/packages/component-sdk/src/api/datasources.js
@@ -1,20 +1,21 @@
-import { fetchTableData, fetchTableDefinition } from "./tables"
+import { fetchTableData } from "./tables"
import { fetchViewData } from "./views"
import { fetchRelationshipData } from "./relationships"
+import { enrichRows } from "./rows"
/**
* Fetches all rows for a particular Budibase data source.
*/
export const fetchDatasource = async datasource => {
- if (!datasource || !datasource.name) {
+ if (!datasource || !datasource.type) {
return []
}
// Fetch all rows in data source
- const { type, name, tableId } = datasource
+ const { type, tableId } = datasource
let rows = []
if (type === "table") {
- rows = await fetchTableData(name)
+ rows = await fetchTableData(tableId)
} else if (type === "view") {
rows = await fetchViewData(datasource)
} else if (type === "link") {
@@ -22,37 +23,5 @@ export const fetchDatasource = async datasource => {
}
// Enrich rows
- return await enrichDatasourceRows(rows, tableId)
-}
-
-/**
- * Enriches data source rows which contain certain field types so that they can
- * be properly displayed.
- */
-const enrichDatasourceRows = async (rows, tableId) => {
- if (rows && rows.length && tableId) {
- // Fetch table schema so we can check column types
- const tableDefinition = await fetchTableDefinition(tableId)
- const schema = tableDefinition && tableDefinition.schema
- if (schema) {
- const keys = Object.keys(schema)
- rows.forEach(row => {
- for (let key of keys) {
- const type = schema[key].type
- if (type === "link") {
- // Enrich row with the count of any relationship fields
- row[`${key}_count`] = Array.isArray(row[key]) ? row[key].length : 0
- } else if (type === "attachment") {
- // Enrich row with the first image URL for any attachment fields
- let url = null
- if (Array.isArray(row[key]) && row[key][0] != null) {
- url = row[key][0].url
- }
- row[`${key}_first`] = url
- }
- }
- })
- }
- }
- return rows
+ return await enrichRows(rows, tableId)
}
diff --git a/packages/component-sdk/src/api/index.js b/packages/component-sdk/src/api/index.js
index 56ef9b06ad..711479fb83 100644
--- a/packages/component-sdk/src/api/index.js
+++ b/packages/component-sdk/src/api/index.js
@@ -1,2 +1,7 @@
export * from "./rows"
export * from "./auth"
+export * from "./datasources"
+export * from "./tables"
+export * from "./attachments"
+export * from "./views"
+export * from "./relationships"
diff --git a/packages/component-sdk/src/api/relationships.js b/packages/component-sdk/src/api/relationships.js
index a4d09f1250..d988220f14 100644
--- a/packages/component-sdk/src/api/relationships.js
+++ b/packages/component-sdk/src/api/relationships.js
@@ -1,4 +1,5 @@
import api from "./api"
+import { enrichRows } from "./rows"
/**
* Fetches related rows for a certain field of a certain row.
@@ -8,5 +9,6 @@ export const fetchRelationshipData = async ({ tableId, rowId, fieldName }) => {
return []
}
const response = await api.get({ url: `/api/${tableId}/${rowId}/enrich` })
- return response[fieldName] || []
+ const rows = response[fieldName] || []
+ return await enrichRows(rows, tableId)
}
diff --git a/packages/component-sdk/src/api/rows.js b/packages/component-sdk/src/api/rows.js
index 3267bfda3e..60d83bbee0 100644
--- a/packages/component-sdk/src/api/rows.js
+++ b/packages/component-sdk/src/api/rows.js
@@ -1,4 +1,15 @@
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({
+ url: `/api/${tableId}/rows/${rowId}`,
+ })
+ return await enrichRows([row], tableId)
+}
/**
* Creates a row in a table.
@@ -31,6 +42,19 @@ export const deleteRow = async ({ tableId, rowId, revId }) => {
})
}
+/**
+ * Deletes many rows from a table.
+ */
+export const deleteRows = async ({ tableId, rows }) => {
+ return await api.post({
+ url: `/api/${tableId}/rows`,
+ body: {
+ rows,
+ type: "delete",
+ },
+ })
+}
+
/**
* Sanitises and parses column types when saving and updating rows.
*/
@@ -68,3 +92,35 @@ const makeRowRequestBody = (parameters, state) => {
return body
}
+
+/**
+ * Enriches rows which contain certain field types so that they can
+ * be properly displayed.
+ */
+export const enrichRows = async (rows, tableId) => {
+ if (rows && rows.length && tableId) {
+ // Fetch table schema so we can check column types
+ const tableDefinition = await fetchTableDefinition(tableId)
+ const schema = tableDefinition && tableDefinition.schema
+ if (schema) {
+ const keys = Object.keys(schema)
+ rows.forEach(row => {
+ for (let key of keys) {
+ const type = schema[key].type
+ if (type === "link") {
+ // Enrich row with the count of any relationship fields
+ row[`${key}_count`] = Array.isArray(row[key]) ? row[key].length : 0
+ } else if (type === "attachment") {
+ // Enrich row with the first image URL for any attachment fields
+ let url = null
+ if (Array.isArray(row[key]) && row[key][0] != null) {
+ url = row[key][0].url
+ }
+ row[`${key}_first`] = url
+ }
+ }
+ })
+ }
+ }
+ return rows
+}
diff --git a/packages/component-sdk/src/api/tables.js b/packages/component-sdk/src/api/tables.js
index f8259186d0..7ad5633b07 100644
--- a/packages/component-sdk/src/api/tables.js
+++ b/packages/component-sdk/src/api/tables.js
@@ -1,4 +1,5 @@
import api from "./api"
+import { enrichRows } from "./rows"
/**
* Fetches a table definition.
@@ -11,6 +12,7 @@ export const fetchTableDefinition = async tableId => {
/**
* Fetches all rows from a table.
*/
-export const fetchTableData = async name => {
- return await api.get({ url: `/api/views/${name}` })
+export const fetchTableData = async tableId => {
+ const rows = await api.get({ url: `/api/${tableId}/rows` })
+ return await enrichRows(rows, tableId)
}
diff --git a/packages/component-sdk/src/api/views.js b/packages/component-sdk/src/api/views.js
index 4f7acd2d8f..7c1386d721 100644
--- a/packages/component-sdk/src/api/views.js
+++ b/packages/component-sdk/src/api/views.js
@@ -1,9 +1,16 @@
import api from "./api"
+import { enrichRows } from "./rows"
/**
* Fetches all rows in a view.
*/
-export const fetchViewData = async ({ name, field, groupBy, calculation }) => {
+export const fetchViewData = async ({
+ name,
+ field,
+ groupBy,
+ calculation,
+ tableId,
+}) => {
const params = new URLSearchParams()
if (calculation) {
@@ -18,5 +25,6 @@ export const fetchViewData = async ({ name, field, groupBy, calculation }) => {
? `/api/views/${name}?${params}`
: `/api/views/${name}`
- return await api.get({ url: QUERY_VIEW_URL })
+ const rows = await api.get({ url: QUERY_VIEW_URL })
+ return await enrichRows(rows, tableId)
}
diff --git a/packages/component-sdk/src/store/auth.js b/packages/component-sdk/src/store/auth.js
index 05f7709b4a..4d69530efa 100644
--- a/packages/component-sdk/src/store/auth.js
+++ b/packages/component-sdk/src/store/auth.js
@@ -1,12 +1,11 @@
import { localStorageStore } from "../../../builder/src/builderStore/store/localStorage"
import * as api from "../api"
+import { getAppId } from "../utils"
-const initialState = {
- user: null,
-}
+const initialState = ""
export const createAuthStore = () => {
- const store = localStorageStore("bb-app-auth", initialState)
+ const store = localStorageStore("budibase:token", initialState)
/**
* Logs a user in.
@@ -14,18 +13,24 @@ export const createAuthStore = () => {
const logIn = async ({ username, password }) => {
const user = await api.logIn({ username, password })
if (!user.error) {
- store.update(state => {
- state.user = user
- return state
- })
+ store.set(user.token)
}
+ return !user.error
}
/**
* Logs a user out.
*/
const logOut = () => {
- store.update(() => initialState)
+ store.set(initialState)
+
+ // Expire any cookies
+ const appId = getAppId(window.document.cookie)
+ if (appId) {
+ for (let environment of ["local", "cloud"]) {
+ window.document.cookie = `budibase:${appId}:${environment}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`
+ }
+ }
}
store.actions = {
diff --git a/packages/component-sdk/src/store/config.js b/packages/component-sdk/src/store/config.js
index dbf9918ae3..b6978d6f77 100644
--- a/packages/component-sdk/src/store/config.js
+++ b/packages/component-sdk/src/store/config.js
@@ -26,7 +26,7 @@ export const createConfigStore = () => {
* Rests the SDK configuration
*/
const reset = () => {
- store.update(() => initialState)
+ store.set(initialState)
}
/**
diff --git a/packages/standard-components/src/DataList.svelte b/packages/standard-components/src/DataList.svelte
deleted file mode 100644
index 343ea886ad..0000000000
--- a/packages/standard-components/src/DataList.svelte
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
- {#each Object.keys(data) as key}
-
-
{col.title} | - {/each} -
---|
{cellValue(index, row)} | - {/each} -