Merge branch 'develop' of github.com:Budibase/budibase into new-design-ui
This commit is contained in:
commit
955c7b0600
|
@ -20,6 +20,8 @@ RUN node /pinVersions.js && yarn && yarn build && /cleanup.sh
|
||||||
|
|
||||||
FROM couchdb:3.2.1
|
FROM couchdb:3.2.1
|
||||||
|
|
||||||
|
ARG TARGETARCH amd64
|
||||||
|
|
||||||
COPY --from=build /app /app
|
COPY --from=build /app /app
|
||||||
COPY --from=build /worker /worker
|
COPY --from=build /worker /worker
|
||||||
|
|
||||||
|
@ -39,7 +41,6 @@ ENV DEPLOYMENT_ENVIRONMENT=docker \
|
||||||
SELF_HOSTED=1 \
|
SELF_HOSTED=1 \
|
||||||
CLUSTER_PORT=10000 \
|
CLUSTER_PORT=10000 \
|
||||||
REDIS_PASSWORD=budibase \
|
REDIS_PASSWORD=budibase \
|
||||||
ARCHITECTURE=amd \
|
|
||||||
APP_PORT=4001 \
|
APP_PORT=4001 \
|
||||||
WORKER_PORT=4002
|
WORKER_PORT=4002
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ RUN mkdir /etc/nginx/logs && \
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
RUN mkdir -p scripts/integrations/oracle
|
RUN mkdir -p scripts/integrations/oracle
|
||||||
ADD packages/server/scripts/integrations/oracle scripts/integrations/oracle
|
ADD packages/server/scripts/integrations/oracle scripts/integrations/oracle
|
||||||
RUN /bin/bash -e ./scripts/integrations/oracle/instantclient/linux/x86-64/install.sh
|
RUN /bin/bash -e ./scripts/integrations/oracle/instantclient/linux/install.sh
|
||||||
|
|
||||||
# setup clouseau
|
# setup clouseau
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
@ -87,7 +88,8 @@ ADD hosting/single/vm.args ./etc/
|
||||||
|
|
||||||
# setup minio
|
# setup minio
|
||||||
WORKDIR /minio
|
WORKDIR /minio
|
||||||
RUN wget https://dl.min.io/server/minio/release/linux-${ARCHITECTURE}64/minio && chmod +x minio
|
ADD scripts/install-minio.sh ./install.sh
|
||||||
|
RUN chmod +x install.sh && ./install.sh
|
||||||
|
|
||||||
# setup runner file
|
# setup runner file
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
"build:docker:develop": "node scripts/pinVersions && lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -",
|
"build:docker:develop": "node scripts/pinVersions && lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -",
|
||||||
"build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild",
|
"build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild",
|
||||||
"build:digitalocean": "cd hosting/digitalocean && ./build.sh && cd -",
|
"build:digitalocean": "cd hosting/digitalocean && ./build.sh && cd -",
|
||||||
|
"build:docker:single:multiarch": "docker buildx build --platform linux/arm64,linux/amd64 -f hosting/single/Dockerfile -t budibase:latest .",
|
||||||
"build:docker:single:image": "docker build -f hosting/single/Dockerfile -t budibase:latest .",
|
"build:docker:single:image": "docker build -f hosting/single/Dockerfile -t budibase:latest .",
|
||||||
"build:docker:single": "lerna run build && lerna run predocker && npm run build:docker:single:image",
|
"build:docker:single": "lerna run build && lerna run predocker && npm run build:docker:single:image",
|
||||||
"build:docs": "lerna run build:docs",
|
"build:docs": "lerna run build:docs",
|
||||||
|
|
|
@ -222,6 +222,7 @@ export const getFrontendStore = () => {
|
||||||
|
|
||||||
// Build array of promises to speed up bulk deletions
|
// Build array of promises to speed up bulk deletions
|
||||||
const promises = []
|
const promises = []
|
||||||
|
let deleteUrls = []
|
||||||
screensToDelete.forEach(screen => {
|
screensToDelete.forEach(screen => {
|
||||||
// Delete the screen
|
// Delete the screen
|
||||||
promises.push(
|
promises.push(
|
||||||
|
@ -231,14 +232,10 @@ export const getFrontendStore = () => {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
// Remove links to this screen
|
// Remove links to this screen
|
||||||
promises.push(
|
deleteUrls.push(screen.routing.route)
|
||||||
store.actions.components.links.delete(
|
|
||||||
screen.routing.route,
|
|
||||||
screen.props._instanceName
|
|
||||||
)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
promises.push(store.actions.links.delete(deleteUrls))
|
||||||
await Promise.all(promises)
|
await Promise.all(promises)
|
||||||
const deletedIds = screensToDelete.map(screen => screen._id)
|
const deletedIds = screensToDelete.map(screen => screen._id)
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
|
@ -617,89 +614,38 @@ export const getFrontendStore = () => {
|
||||||
})
|
})
|
||||||
await store.actions.preview.saveSelected()
|
await store.actions.preview.saveSelected()
|
||||||
},
|
},
|
||||||
links: {
|
},
|
||||||
save: async (url, title) => {
|
links: {
|
||||||
const layout = get(mainLayout)
|
save: async (url, title) => {
|
||||||
if (!layout) {
|
const layout = get(mainLayout)
|
||||||
return
|
if (!layout) {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Add link setting to main layout
|
// Add link setting to main layout
|
||||||
if (layout.props._component.endsWith("layout")) {
|
if (!layout.props.links) {
|
||||||
// If using a new SDK, add to the layout component settings
|
layout.props.links = []
|
||||||
if (!layout.props.links) {
|
}
|
||||||
layout.props.links = []
|
layout.props.links.push({
|
||||||
}
|
text: title,
|
||||||
layout.props.links.push({
|
url,
|
||||||
text: title,
|
})
|
||||||
url,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// If using an old SDK, add to the navigation component
|
|
||||||
// TODO: remove this when we can assume everyone has updated
|
|
||||||
const nav = findComponentType(
|
|
||||||
layout.props,
|
|
||||||
"@budibase/standard-components/navigation"
|
|
||||||
)
|
|
||||||
if (!nav) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let newLink
|
await store.actions.layouts.save(layout)
|
||||||
if (nav._children && nav._children.length) {
|
},
|
||||||
// Clone an existing link if one exists
|
delete: async urls => {
|
||||||
newLink = cloneDeep(nav._children[0])
|
const layout = get(mainLayout)
|
||||||
|
if (!layout?.props.links?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Set our new props
|
// Filter out the URLs to delete
|
||||||
newLink._id = Helpers.uuid()
|
urls = Array.isArray(urls) ? urls : [urls]
|
||||||
newLink._instanceName = `${title} Link`
|
layout.props.links = layout.props.links.filter(
|
||||||
newLink.url = url
|
link => !urls.includes(link.url)
|
||||||
newLink.text = title
|
)
|
||||||
} else {
|
|
||||||
// Otherwise create vanilla new link
|
|
||||||
newLink = {
|
|
||||||
...store.actions.components.createInstance("link"),
|
|
||||||
url,
|
|
||||||
text: title,
|
|
||||||
_instanceName: `${title} Link`,
|
|
||||||
}
|
|
||||||
nav._children = [...nav._children, newLink]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save layout
|
await store.actions.layouts.save(layout)
|
||||||
await store.actions.layouts.save(layout)
|
|
||||||
},
|
|
||||||
delete: async (url, title) => {
|
|
||||||
const layout = get(mainLayout)
|
|
||||||
if (!layout) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add link setting to main layout
|
|
||||||
if (layout.props._component.endsWith("layout")) {
|
|
||||||
// If using a new SDK, add to the layout component settings
|
|
||||||
layout.props.links = layout.props.links.filter(
|
|
||||||
link => !(link.text === title && link.url === url)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// If using an old SDK, add to the navigation component
|
|
||||||
// TODO: remove this when we can assume everyone has updated
|
|
||||||
const nav = findComponentType(
|
|
||||||
layout.props,
|
|
||||||
"@budibase/standard-components/navigation"
|
|
||||||
)
|
|
||||||
if (!nav) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nav._children = nav._children.filter(
|
|
||||||
child => !(child.url === url && child.text === title)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Save layout
|
|
||||||
await store.actions.layouts.save(layout)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default function (tables) {
|
||||||
name: `${table.name} - New`,
|
name: `${table.name} - New`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(table),
|
||||||
id: NEW_ROW_TEMPLATE,
|
id: NEW_ROW_TEMPLATE,
|
||||||
table: table.name,
|
table: table._id,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default function (tables) {
|
||||||
name: `${table.name} - Detail`,
|
name: `${table.name} - Detail`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(table),
|
||||||
id: ROW_DETAIL_TEMPLATE,
|
id: ROW_DETAIL_TEMPLATE,
|
||||||
table: table.name,
|
table: table._id,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default function (tables) {
|
||||||
name: `${table.name} - List`,
|
name: `${table.name} - List`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(table),
|
||||||
id: ROW_LIST_TEMPLATE,
|
id: ROW_LIST_TEMPLATE,
|
||||||
table: table.name,
|
table: table._id,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
import { Label, Select, Body } from "@budibase/bbui"
|
import { Label, Select, Body, Multiselect } from "@budibase/bbui"
|
||||||
import { findAllMatchingComponents } from "builderStore/componentUtils"
|
import {
|
||||||
|
findAllMatchingComponents,
|
||||||
|
findComponent,
|
||||||
|
} from "builderStore/componentUtils"
|
||||||
import { currentAsset } from "builderStore"
|
import { currentAsset } from "builderStore"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
import {
|
||||||
|
getDatasourceForProvider,
|
||||||
|
getSchemaForDatasource,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
|
|
||||||
export let parameters
|
export let parameters
|
||||||
|
|
||||||
$: tables = findAllMatchingComponents($currentAsset?.props, component =>
|
|
||||||
component._component.endsWith("table")
|
|
||||||
).map(table => ({
|
|
||||||
label: table._instanceName,
|
|
||||||
value: table._id,
|
|
||||||
}))
|
|
||||||
|
|
||||||
$: tableBlocks = findAllMatchingComponents($currentAsset?.props, component =>
|
|
||||||
component._component.endsWith("tableblock")
|
|
||||||
).map(block => ({
|
|
||||||
label: block._instanceName,
|
|
||||||
value: `${block._id}-table`,
|
|
||||||
}))
|
|
||||||
|
|
||||||
$: componentOptions = tables.concat(tableBlocks)
|
|
||||||
|
|
||||||
const FORMATS = [
|
const FORMATS = [
|
||||||
{
|
{
|
||||||
label: "CSV",
|
label: "CSV",
|
||||||
|
@ -33,6 +24,32 @@
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
$: tables = findAllMatchingComponents($currentAsset?.props, component =>
|
||||||
|
component._component.endsWith("table")
|
||||||
|
).map(table => ({
|
||||||
|
label: table._instanceName,
|
||||||
|
value: table._id,
|
||||||
|
}))
|
||||||
|
$: tableBlocks = findAllMatchingComponents($currentAsset?.props, component =>
|
||||||
|
component._component.endsWith("tableblock")
|
||||||
|
).map(block => ({
|
||||||
|
label: block._instanceName,
|
||||||
|
value: `${block._id}-table`,
|
||||||
|
}))
|
||||||
|
$: componentOptions = tables.concat(tableBlocks)
|
||||||
|
$: columnOptions = getColumnOptions(parameters.tableComponentId)
|
||||||
|
|
||||||
|
const getColumnOptions = tableId => {
|
||||||
|
// Strip block suffix if block component
|
||||||
|
if (tableId?.includes("-")) {
|
||||||
|
tableId = tableId.split("-")[0]
|
||||||
|
}
|
||||||
|
const selectedTable = findComponent($currentAsset?.props, tableId)
|
||||||
|
const datasource = getDatasourceForProvider($currentAsset, selectedTable)
|
||||||
|
const { schema } = getSchemaForDatasource($currentAsset, datasource)
|
||||||
|
return Object.keys(schema || {})
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!parameters.type) {
|
if (!parameters.type) {
|
||||||
parameters.type = "csv"
|
parameters.type = "csv"
|
||||||
|
@ -53,10 +70,16 @@
|
||||||
<Select
|
<Select
|
||||||
bind:value={parameters.tableComponentId}
|
bind:value={parameters.tableComponentId}
|
||||||
options={componentOptions}
|
options={componentOptions}
|
||||||
|
on:change={() => (parameters.columns = [])}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Label small>Export as</Label>
|
<Label small>Export as</Label>
|
||||||
<Select bind:value={parameters.type} options={FORMATS} />
|
<Select bind:value={parameters.type} options={FORMATS} />
|
||||||
|
<Label small>Export columns</Label>
|
||||||
|
<Multiselect
|
||||||
|
placeholder="All columns"
|
||||||
|
bind:value={parameters.columns}
|
||||||
|
options={columnOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -80,7 +103,7 @@
|
||||||
display: grid;
|
display: grid;
|
||||||
column-gap: var(--spacing-xs);
|
column-gap: var(--spacing-xs);
|
||||||
row-gap: var(--spacing-s);
|
row-gap: var(--spacing-s);
|
||||||
grid-template-columns: 70px 1fr;
|
grid-template-columns: 90px 1fr;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -20,14 +20,14 @@
|
||||||
let selectedScreens = [...initalScreens]
|
let selectedScreens = [...initalScreens]
|
||||||
|
|
||||||
const toggleScreenSelection = (table, datasource) => {
|
const toggleScreenSelection = (table, datasource) => {
|
||||||
if (selectedScreens.find(s => s.table === table.name)) {
|
if (selectedScreens.find(s => s.table === table._id)) {
|
||||||
selectedScreens = selectedScreens.filter(
|
selectedScreens = selectedScreens.filter(
|
||||||
screen => screen.table !== table.name
|
screen => screen.table !== table._id
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let partialTemplates = getTemplates($store, $tables.list).reduce(
|
let partialTemplates = getTemplates($store, $tables.list).reduce(
|
||||||
(acc, template) => {
|
(acc, template) => {
|
||||||
if (template.table === table.name) {
|
if (template.table === table._id) {
|
||||||
template.datasource = datasource.name
|
template.datasource = datasource.name
|
||||||
acc.push(template)
|
acc.push(template)
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
<div
|
<div
|
||||||
class="data-source-entry"
|
class="data-source-entry"
|
||||||
class:selected={selectedScreens.find(
|
class:selected={selectedScreens.find(
|
||||||
x => x.table === table.name
|
x => x.table === table._id
|
||||||
)}
|
)}
|
||||||
on:click={() => toggleScreenSelection(table, datasource)}
|
on:click={() => toggleScreenSelection(table, datasource)}
|
||||||
>
|
>
|
||||||
|
@ -109,8 +109,7 @@
|
||||||
<use xlink:href="#spectrum-icon-18-Table" />
|
<use xlink:href="#spectrum-icon-18-Table" />
|
||||||
</svg>
|
</svg>
|
||||||
{table.name}
|
{table.name}
|
||||||
|
{#if selectedScreens.find(x => x.table === table._id)}
|
||||||
{#if selectedScreens.find(x => x.table === table.name)}
|
|
||||||
<span class="data-source-check">
|
<span class="data-source-check">
|
||||||
<Icon size="S" name="CheckmarkCircle" />
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -123,7 +122,7 @@
|
||||||
<div
|
<div
|
||||||
class="data-source-entry"
|
class="data-source-entry"
|
||||||
class:selected={selectedScreens.find(
|
class:selected={selectedScreens.find(
|
||||||
x => x.table === datasource.entities[table_key].name
|
x => x.table === datasource.entities[table_key]._id
|
||||||
)}
|
)}
|
||||||
on:click={() =>
|
on:click={() =>
|
||||||
toggleScreenSelection(
|
toggleScreenSelection(
|
||||||
|
@ -141,8 +140,7 @@
|
||||||
<use xlink:href="#spectrum-icon-18-Table" />
|
<use xlink:href="#spectrum-icon-18-Table" />
|
||||||
</svg>
|
</svg>
|
||||||
{datasource.entities[table_key].name}
|
{datasource.entities[table_key].name}
|
||||||
|
{#if selectedScreens.find(x => x.table === datasource.entities[table_key]._id)}
|
||||||
{#if selectedScreens.find(x => x.table === datasource.entities[table_key].name)}
|
|
||||||
<span class="data-source-check">
|
<span class="data-source-check">
|
||||||
<Icon size="S" name="CheckmarkCircle" />
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
|
|
||||||
// Add link in layout for list screens
|
// Add link in layout for list screens
|
||||||
if (screen.props._instanceName.endsWith("List")) {
|
if (screen.props._instanceName.endsWith("List")) {
|
||||||
await store.actions.components.links.save(
|
await store.actions.links.save(
|
||||||
screen.routing.route,
|
screen.routing.route,
|
||||||
screen.routing.route.split("/")[1]
|
screen.routing.route.split("/")[1]
|
||||||
)
|
)
|
||||||
|
@ -133,6 +133,7 @@
|
||||||
const screens = selectedTemplates.map(template => {
|
const screens = selectedTemplates.map(template => {
|
||||||
let screenTemplate = template.create()
|
let screenTemplate = template.create()
|
||||||
screenTemplate.datasource = template.datasource
|
screenTemplate.datasource = template.datasource
|
||||||
|
screenTemplate.autoTableId = template.table
|
||||||
return screenTemplate
|
return screenTemplate
|
||||||
})
|
})
|
||||||
await createScreens({ screens, screenAccessRole })
|
await createScreens({ screens, screenAccessRole })
|
||||||
|
|
|
@ -270,6 +270,7 @@ const exportDataHandler = async action => {
|
||||||
tableId: selection.tableId,
|
tableId: selection.tableId,
|
||||||
rows: selection.selectedRows,
|
rows: selection.selectedRows,
|
||||||
format: action.parameters.type,
|
format: action.parameters.type,
|
||||||
|
columns: action.parameters.columns,
|
||||||
})
|
})
|
||||||
download(data, `${selection.tableId}.${action.parameters.type}`)
|
download(data, `${selection.tableId}.${action.parameters.type}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -65,12 +65,15 @@ export const buildRowEndpoints = API => ({
|
||||||
* Exports rows.
|
* Exports rows.
|
||||||
* @param tableId the table ID to export the rows from
|
* @param tableId the table ID to export the rows from
|
||||||
* @param rows the array of rows to export
|
* @param rows the array of rows to export
|
||||||
|
* @param format the format to export (csv or json)
|
||||||
|
* @param columns which columns to export (all if undefined)
|
||||||
*/
|
*/
|
||||||
exportRows: async ({ tableId, rows, format }) => {
|
exportRows: async ({ tableId, rows, format, columns }) => {
|
||||||
return await API.post({
|
return await API.post({
|
||||||
url: `/api/${tableId}/rows/exportRows?format=${format}`,
|
url: `/api/${tableId}/rows/exportRows?format=${format}`,
|
||||||
body: {
|
body: {
|
||||||
rows,
|
rows,
|
||||||
|
columns,
|
||||||
},
|
},
|
||||||
parseResponse: async response => {
|
parseResponse: async response => {
|
||||||
return await response.text()
|
return await response.text()
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Must be root to continue
|
||||||
|
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
|
||||||
|
|
||||||
|
# Allow for re-runs
|
||||||
|
rm -rf /opt/oracle
|
||||||
|
|
||||||
|
echo "Installing oracle instant client"
|
||||||
|
|
||||||
|
# copy and unzip package
|
||||||
|
mkdir -p /opt/oracle
|
||||||
|
cp scripts/integrations/oracle/instantclient/linux/arm64/basiclite-19.10.zip /opt/oracle
|
||||||
|
cd /opt/oracle
|
||||||
|
unzip -qq basiclite-19.10.zip -d .
|
||||||
|
rm *.zip
|
||||||
|
mv instantclient* instantclient
|
||||||
|
|
||||||
|
# update runtime link path
|
||||||
|
sh -c "echo /opt/oracle/instantclient > /etc/ld.so.conf.d/oracle-instantclient.conf"
|
||||||
|
ldconfig /etc/ld.so.conf.d
|
||||||
|
|
||||||
|
echo "Installation complete"
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"
|
||||||
|
if [[ $TARGETARCH == arm* ]] ;
|
||||||
|
then
|
||||||
|
echo "Installing ARM Oracle instant client..."
|
||||||
|
$SCRIPT_DIR/arm64/install.sh
|
||||||
|
else
|
||||||
|
echo "Installing x86-64 Oracle instant client..."
|
||||||
|
$SCRIPT_DIR/x86-64/install.sh
|
||||||
|
fi
|
|
@ -157,7 +157,8 @@ exports.validate = async () => {
|
||||||
exports.exportRows = async ctx => {
|
exports.exportRows = async ctx => {
|
||||||
const { datasourceId } = breakExternalTableId(ctx.params.tableId)
|
const { datasourceId } = breakExternalTableId(ctx.params.tableId)
|
||||||
const db = getAppDB()
|
const db = getAppDB()
|
||||||
let format = ctx.query.format
|
const format = ctx.query.format
|
||||||
|
const { columns } = ctx.request.body
|
||||||
const datasource = await db.get(datasourceId)
|
const datasource = await db.get(datasourceId)
|
||||||
if (!datasource || !datasource.entities) {
|
if (!datasource || !datasource.entities) {
|
||||||
ctx.throw(400, "Datasource has not been configured for plus API.")
|
ctx.throw(400, "Datasource has not been configured for plus API.")
|
||||||
|
@ -171,13 +172,27 @@ exports.exportRows = async ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = await exports.search(ctx)
|
let result = await exports.search(ctx)
|
||||||
let headers = Object.keys(result.rows[0])
|
let rows = []
|
||||||
|
|
||||||
|
// Filter data to only specified columns if required
|
||||||
|
if (columns && columns.length) {
|
||||||
|
for (let i = 0; i < result.rows.length; i++) {
|
||||||
|
rows[i] = {}
|
||||||
|
for (let column of columns) {
|
||||||
|
rows[i][column] = result.rows[i][column]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rows = result.rows
|
||||||
|
}
|
||||||
|
|
||||||
|
let headers = Object.keys(rows[0])
|
||||||
const exporter = exporters[format]
|
const exporter = exporters[format]
|
||||||
const filename = `export.${format}`
|
const filename = `export.${format}`
|
||||||
|
|
||||||
// send down the file
|
// send down the file
|
||||||
ctx.attachment(filename)
|
ctx.attachment(filename)
|
||||||
return apiFileReturn(exporter(headers, result.rows))
|
return apiFileReturn(exporter(headers, rows))
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetchEnrichedRow = async ctx => {
|
exports.fetchEnrichedRow = async ctx => {
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
sudo apt-get install -y qemu qemu-user-static
|
||||||
|
docker buildx create --name budibase
|
||||||
|
docker buildx use budibase
|
|
@ -1,11 +1,16 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
dir=$(pwd)
|
dir=$(pwd)
|
||||||
mv dist /
|
declare -a keep=("dist" "package.json" "yarn.lock" "client" "builder" "build" "pm2.config.js" "docker_run.sh")
|
||||||
mv package.json /
|
for moveDir in "${keep[@]}"
|
||||||
|
do
|
||||||
|
mv $moveDir / 2>/dev/null
|
||||||
|
done
|
||||||
cd /
|
cd /
|
||||||
rm -r $dir
|
rm -r $dir
|
||||||
mkdir $dir
|
mkdir $dir
|
||||||
mv /dist $dir
|
for keepDir in "${keep[@]}"
|
||||||
mv /package.json $dir
|
do
|
||||||
|
mv /$keepDir $dir/ 2>/dev/null
|
||||||
|
done
|
||||||
cd $dir
|
cd $dir
|
||||||
NODE_ENV=production yarn
|
NODE_ENV=production yarn
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
if [[ $TARGETARCH == arm* ]] ;
|
||||||
|
then
|
||||||
|
wget https://dl.min.io/server/minio/release/linux-arm64/minio
|
||||||
|
else
|
||||||
|
wget https://dl.min.io/server/minio/release/linux-amd64/minio
|
||||||
|
fi
|
||||||
|
chmod +x minio
|
Loading…
Reference in New Issue