Update all API usages in builder components directory

This commit is contained in:
Andrew Kingston 2022-01-24 10:44:37 +00:00
parent 59349f2451
commit 816ced96df
15 changed files with 206 additions and 97 deletions

View File

@ -1,7 +1,8 @@
<script> <script>
import api from "builderStore/api" import { API } from "api"
import Table from "./Table.svelte" import Table from "./Table.svelte"
import { tables } from "stores/backend" import { tables } from "stores/backend"
import { notifications } from "@budibase/bbui"
export let tableId export let tableId
export let rowId export let rowId
@ -27,9 +28,15 @@
} }
async function fetchData(tableId, rowId) { async function fetchData(tableId, rowId) {
const QUERY_VIEW_URL = `/api/${tableId}/${rowId}/enrich` try {
const response = await api.get(QUERY_VIEW_URL) row = await API.fetchRelationshipData({
row = await response.json() tableId,
rowId,
})
} catch (error) {
row = null
notifications.error("Error fetching relationship data")
}
} }
</script> </script>

View File

@ -2,7 +2,7 @@
import { fade } from "svelte/transition" import { fade } from "svelte/transition"
import { goto, params } from "@roxi/routify" import { goto, params } from "@roxi/routify"
import { Table, Modal, Heading, notifications, Layout } from "@budibase/bbui" import { Table, Modal, Heading, notifications, Layout } from "@budibase/bbui"
import api from "builderStore/api" import { API } "api"
import Spinner from "components/common/Spinner.svelte" import Spinner from "components/common/Spinner.svelte"
import DeleteRowsButton from "./buttons/DeleteRowsButton.svelte" import DeleteRowsButton from "./buttons/DeleteRowsButton.svelte"
import CreateEditRow from "./modals/CreateEditRow.svelte" import CreateEditRow from "./modals/CreateEditRow.svelte"
@ -88,12 +88,17 @@
} }
const deleteRows = async () => { const deleteRows = async () => {
await api.delete(`/api/${tableId}/rows`, { try {
rows: selectedRows, await API.deleteRows({
}) tableId,
data = data.filter(row => !selectedRows.includes(row)) rows: selectedRows
notifications.success(`Successfully deleted ${selectedRows.length} rows`) })
selectedRows = [] data = data.filter(row => !selectedRows.includes(row))
notifications.success(`Successfully deleted ${selectedRows.length} rows`)
selectedRows = []
} catch (error) {
notifications.error("Error deleting rows")
}
} }
const editRow = row => { const editRow = row => {

View File

@ -1,5 +1,5 @@
<script> <script>
import api from "builderStore/api" import { API } from "api"
import { tables } from "stores/backend" import { tables } from "stores/backend"
import Table from "./Table.svelte" import Table from "./Table.svelte"
@ -9,6 +9,7 @@
import ExportButton from "./buttons/ExportButton.svelte" import ExportButton from "./buttons/ExportButton.svelte"
import ManageAccessButton from "./buttons/ManageAccessButton.svelte" import ManageAccessButton from "./buttons/ManageAccessButton.svelte"
import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte" import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte"
import { notifications } from "@budibase/bbui"
export let view = {} export let view = {}
@ -20,33 +21,31 @@
$: name = view.name $: name = view.name
// Fetch rows for specified view // Fetch rows for specified view
$: { $: fetchViewData(name, view.field, view.groupBy, view.calculation)
loading = true
fetchViewData(name, view.field, view.groupBy, view.calculation)
}
async function fetchViewData(name, field, groupBy, calculation) { async function fetchViewData(name, field, groupBy, calculation) {
loading = true
const _tables = $tables.list const _tables = $tables.list
const allTableViews = _tables.map(table => table.views) const allTableViews = _tables.map(table => table.views)
const thisView = allTableViews.filter( const thisView = allTableViews.filter(
views => views != null && views[name] != null views => views != null && views[name] != null
)[0] )[0]
// don't fetch view data if the view no longer exists // Don't fetch view data if the view no longer exists
if (!thisView) { if (!thisView) {
loading = false
return return
} }
const params = new URLSearchParams() try {
if (calculation) { data = await API.fetchViewData({
params.set("field", field) name,
params.set("calculation", calculation) calculation,
field,
groupBy,
})
} catch (error) {
notifications.error("Error fetching view data")
} }
if (groupBy) {
params.set("group", groupBy)
}
const QUERY_VIEW_URL = `/api/views/${name}?${params}`
const response = await api.get(QUERY_VIEW_URL)
data = await response.json()
loading = false loading = false
} }
</script> </script>

View File

@ -1,7 +1,7 @@
<script> <script>
import { ModalContent, Select, Input, Button } from "@budibase/bbui" import { ModalContent, Select, Input, Button } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import api from "builderStore/api" import { API } from "api"
import { notifications } from "@budibase/bbui" import { notifications } from "@budibase/bbui"
import ErrorsBox from "components/common/ErrorsBox.svelte" import ErrorsBox from "components/common/ErrorsBox.svelte"
import { roles } from "stores/backend" import { roles } from "stores/backend"
@ -24,8 +24,12 @@
!builtInRoles.includes(selectedRole.name) !builtInRoles.includes(selectedRole.name)
const fetchBasePermissions = async () => { const fetchBasePermissions = async () => {
const permissionsResponse = await api.get("/api/permission/builtin") try {
basePermissions = await permissionsResponse.json() basePermissions = await API.getBasePermissions()
} catch (error) {
notifications.error("Error fetching base permission options")
basePermissions = []
}
} }
// Changes the selected role // Changes the selected role
@ -68,23 +72,23 @@
} }
// Save/create the role // Save/create the role
const response = await roles.save(selectedRole) try {
if (response.status === 200) { await roles.save(selectedRole)
notifications.success("Role saved successfully.") notifications.success("Role saved successfully")
} else { } catch (error) {
notifications.error("Error saving role.") notifications.error("Error saving role")
return false return false
} }
} }
// Deletes the selected role // Deletes the selected role
const deleteRole = async () => { const deleteRole = async () => {
const response = await roles.delete(selectedRole) try {
if (response.status === 200) { await roles.delete(selectedRole)
changeRole() changeRole()
notifications.success("Role deleted successfully.") notifications.success("Role deleted successfully")
} else { } catch (error) {
notifications.error("Error deleting role.") notifications.error("Error deleting role")
} }
} }

View File

@ -1,7 +1,7 @@
<script> <script>
import { Select, ModalContent, notifications } from "@budibase/bbui" import { Select, ModalContent, notifications } from "@budibase/bbui"
import download from "downloadjs" import download from "downloadjs"
import { get } from "builderStore/api" import { API } from "api"
const FORMATS = [ const FORMATS = [
{ {
@ -19,17 +19,14 @@
let exportFormat = FORMATS[0].key let exportFormat = FORMATS[0].key
async function exportView() { async function exportView() {
const uri = encodeURIComponent(view) try {
const response = await get( const data = await API.exportView({
`/api/views/export?view=${uri}&format=${exportFormat}` viewName: view,
) format: exportFormat,
if (response.status === 200) { })
const data = await response.text()
download(data, `export.${exportFormat}`) download(data, `export.${exportFormat}`)
} else { } catch (error) {
notifications.error( notifications.error(`Unable to export ${exportFormat.toUpperCase()} data`)
`Unable to export ${exportFormat.toUpperCase()} data.`
)
} }
} }
</script> </script>

View File

@ -1,7 +1,7 @@
<script> <script>
import { ModalContent, Label, notifications, Body } from "@budibase/bbui" import { ModalContent, Label, notifications, Body } from "@budibase/bbui"
import TableDataImport from "../../TableNavigator/TableDataImport.svelte" import TableDataImport from "../../TableNavigator/TableDataImport.svelte"
import api from "builderStore/api" import { API } from "api"
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -12,15 +12,17 @@
$: valid = dataImport?.csvString != null && dataImport?.valid $: valid = dataImport?.csvString != null && dataImport?.valid
async function importData() { async function importData() {
const response = await api.post(`/api/tables/${tableId}/import`, { try {
dataImport, await API.importTableData({
}) tableId,
if (response.status !== 200) { data: dataImport,
const error = await response.text() })
notifications.error(`Unable to import data - ${error}`) notifications.success("Rows successfully imported")
} else { } catch (error) {
notifications.success("Rows successfully imported.") notifications.error("Unable to import data")
} }
// Always refresh rows just to be sure
dispatch("updaterows") dispatch("updaterows")
} }
</script> </script>

View File

@ -1,7 +1,7 @@
<script> <script>
import { Body } from "@budibase/bbui" import { Body, notifications } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import api from "builderStore/api" import { API } from "api"
import ICONS from "../icons" import ICONS from "../icons"
export let integration = {} export let integration = {}
@ -9,14 +9,17 @@
const INTERNAL = "BUDIBASE" const INTERNAL = "BUDIBASE"
async function fetchIntegrations() { async function fetchIntegrations() {
const response = await api.get("/api/integrations") let otherIntegrations
const json = await response.json() try {
otherIntegrations = await API.getIntegrations()
} catch (error) {
otherIntegrations = {}
notifications.error("Error getting integrations")
}
integrations = { integrations = {
[INTERNAL]: { datasource: {}, name: "INTERNAL/CSV" }, [INTERNAL]: { datasource: {}, name: "INTERNAL/CSV" },
...json, ...otherIntegrations,
} }
return json
} }
function selectIntegration(integrationType) { function selectIntegration(integrationType) {

View File

@ -1,8 +1,15 @@
<script> <script>
import { ModalContent, Modal, Body, Layout, Detail } from "@budibase/bbui" import {
ModalContent,
Modal,
Body,
Layout,
Detail,
notifications,
} from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import ICONS from "../icons" import ICONS from "../icons"
import api from "builderStore/api" import { API } from "api"
import { IntegrationNames, IntegrationTypes } from "constants/backend" import { IntegrationNames, IntegrationTypes } from "constants/backend"
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte" import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte"
import DatasourceConfigModal from "components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte" import DatasourceConfigModal from "components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte"
@ -11,7 +18,7 @@
import ImportRestQueriesModal from "./ImportRestQueriesModal.svelte" import ImportRestQueriesModal from "./ImportRestQueriesModal.svelte"
export let modal export let modal
let integrations = [] let integrations = {}
let integration = {} let integration = {}
let internalTableModal let internalTableModal
let externalDatasourceModal let externalDatasourceModal
@ -64,13 +71,20 @@
} }
async function fetchIntegrations() { async function fetchIntegrations() {
const response = await api.get("/api/integrations") let newIntegrations = {
const json = await response.json()
integrations = {
[IntegrationTypes.INTERNAL]: { datasource: {}, name: "INTERNAL/CSV" }, [IntegrationTypes.INTERNAL]: { datasource: {}, name: "INTERNAL/CSV" },
...json,
} }
return json try {
const integrationList = await API.getIntegrations()
newIntegrations = {
...newIntegrations,
...integrationList,
}
return newIntegrations
} catch (error) {
notifications.error("Error fetching integrations")
}
integrations = newIntegrations
} }
</script> </script>

View File

@ -1,7 +1,7 @@
<script> <script>
import { Select, InlineAlert, notifications } from "@budibase/bbui" import { Select, InlineAlert, notifications } from "@budibase/bbui"
import { FIELDS } from "constants/backend" import { FIELDS } from "constants/backend"
import api from "builderStore/api" import { API } from "api"
const BYTES_IN_MB = 1000000 const BYTES_IN_MB = 1000000
const FILE_SIZE_LIMIT = BYTES_IN_MB * 5 const FILE_SIZE_LIMIT = BYTES_IN_MB * 5
@ -50,28 +50,26 @@
} }
async function validateCSV() { async function validateCSV() {
const response = await api.post("/api/tables/csv/validate", { try {
csvString, const parseResult = await API.validateTableCSV({
schema: schema || {}, csvString,
tableId: existingTableId, schema: schema || {},
}) tableId: existingTableId,
})
schema = parseResult?.schema
fields = Object.keys(schema || {}).filter(
key => schema[key].type !== "omit"
)
const parseResult = await response.json() // Check primary display is valid
schema = parseResult && parseResult.schema if (!primaryDisplay || fields.indexOf(primaryDisplay) === -1) {
fields = Object.keys(schema || {}).filter( primaryDisplay = fields[0]
key => schema[key].type !== "omit" }
)
// Check primary display is valid hasValidated = true
if (!primaryDisplay || fields.indexOf(primaryDisplay) === -1) { } catch (error) {
primaryDisplay = fields[0]
}
if (response.status !== 200) {
notifications.error("CSV Invalid, please try another CSV file") notifications.error("CSV Invalid, please try another CSV file")
return []
} }
hasValidated = true
} }
async function handleFile(evt) { async function handleFile(evt) {

View File

@ -27,4 +27,13 @@ export const buildBuilderEndpoints = API => ({
url: "/api/dev/version", url: "/api/dev/version",
}) })
}, },
/**
* Gets the base permissions for roles.
*/
getBasePermissions: async () => {
return await API.get({
url: "/api/permission/builtin",
})
},
}) })

View File

@ -77,6 +77,9 @@ export const createAPIClient = config => {
json = true, json = true,
external = false, external = false,
}) => { }) => {
// Ensure we don't do JSON processing if sending a GET request
json = json && method !== "GET"
// Build headers // Build headers
let headers = { Accept: "application/json" } let headers = { Accept: "application/json" }
if (!external) { if (!external) {
@ -115,7 +118,11 @@ export const createAPIClient = config => {
// Handle response // Handle response
if (response.status >= 200 && response.status < 400) { if (response.status >= 200 && response.status < 400) {
try { try {
return await response.json() if (config?.parseResponse) {
return await config.parseResponse(response)
} else {
return await response.json()
}
} catch (error) { } catch (error) {
return null return null
} }

View File

@ -3,10 +3,14 @@ export const buildRelationshipEndpoints = API => ({
* Fetches related rows for a certain field of a certain row. * Fetches related rows for a certain field of a certain row.
*/ */
fetchRelationshipData: async ({ tableId, rowId, fieldName }) => { fetchRelationshipData: async ({ tableId, rowId, fieldName }) => {
if (!tableId || !rowId || !fieldName) { if (!tableId || !rowId) {
return [] return []
} }
const response = await API.get({ url: `/api/${tableId}/${rowId}/enrich` }) const response = await API.get({ url: `/api/${tableId}/${rowId}/enrich` })
return response[fieldName] || [] if (!fieldName) {
return response || []
} else {
return response[fieldName] || []
}
}, },
}) })

View File

@ -40,4 +40,18 @@ export const buildRowEndpoints = API => ({
}, },
}) })
}, },
/**
* Deletes multiple rows from a table.
* @param tableId the table ID to delete the rows from
* @param rows the array of rows to delete
*/
deleteRows: async ({ tableId, rows }) => {
return await API.delete({
url: `/api/${tableId}/rows`,
body: {
rows,
},
})
},
}) })

View File

@ -48,4 +48,35 @@ export const buildTableEndpoints = API => ({
}, },
}) })
}, },
/**
* Imports data into an existing table
* @param tableId the table ID to import to
* @param data the data import object
*/
importTableData: async ({ tableId, data }) => {
return await API.post({
url: `/api/tables/${tableId}/import`,
body: {
dataImport: data,
},
})
},
/**
* Validates a candidate CSV to be imported for a certain table.
* @param tableId the table ID to import to
* @param csvString the CSV contents as a string
* @param schema the proposed schema
*/
validateTableCSV: async ({ tableId, csvString, schema }) => {
return await API.post({
url: "/api/tables/csv/validate",
body: {
csvString,
schema,
tableId,
},
})
},
}) })

View File

@ -16,4 +16,19 @@ export const buildViewEndpoints = API => ({
: `/api/views/${name}` : `/api/views/${name}`
return await API.get({ url: QUERY_VIEW_URL }) return await API.get({ url: QUERY_VIEW_URL })
}, },
/**
* Exports a view for download
* @param viewName the view to export
* @param format the format to download
*/
exportView: async ({ viewName, format }) => {
const safeViewName = encodeURIComponent(viewName)
return await API.get({
url: `/api/views/export?view=${safeViewName}&format=${format}`,
parseResponse: async response => {
return await response.text()
},
})
},
}) })