Merge branch 'master' of github.com:Budibase/budibase into creator-changes
This commit is contained in:
commit
c4a3837fc1
|
@ -6,7 +6,7 @@ services:
|
||||||
app-service:
|
app-service:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: packages/server/Dockerfile.v2
|
dockerfile: packages/server/Dockerfile
|
||||||
args:
|
args:
|
||||||
- BUDIBASE_VERSION=0.0.0+dev-docker
|
- BUDIBASE_VERSION=0.0.0+dev-docker
|
||||||
container_name: build-bbapps
|
container_name: build-bbapps
|
||||||
|
@ -36,7 +36,7 @@ services:
|
||||||
worker-service:
|
worker-service:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: packages/worker/Dockerfile.v2
|
dockerfile: packages/worker/Dockerfile
|
||||||
args:
|
args:
|
||||||
- BUDIBASE_VERSION=0.0.0+dev-docker
|
- BUDIBASE_VERSION=0.0.0+dev-docker
|
||||||
container_name: build-bbworker
|
container_name: build-bbworker
|
||||||
|
|
|
@ -1,44 +1,59 @@
|
||||||
FROM node:18-slim as build
|
FROM node:18-slim as build
|
||||||
|
|
||||||
# install node-gyp dependencies
|
# install node-gyp dependencies
|
||||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends apt-utils cron g++ make python3
|
RUN apt-get update && apt-get install -y --no-install-recommends g++ make python3 jq
|
||||||
|
|
||||||
# add pin script
|
|
||||||
WORKDIR /
|
|
||||||
ADD scripts/cleanup.sh ./
|
|
||||||
RUN chmod +x /cleanup.sh
|
|
||||||
|
|
||||||
# build server
|
# copy and install dependencies
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ADD packages/server .
|
COPY package.json .
|
||||||
COPY yarn.lock .
|
COPY yarn.lock .
|
||||||
RUN yarn install --production=true --network-timeout 1000000
|
COPY lerna.json .
|
||||||
RUN /cleanup.sh
|
COPY .yarnrc .
|
||||||
|
|
||||||
# build worker
|
COPY packages/server/package.json packages/server/package.json
|
||||||
WORKDIR /worker
|
COPY packages/worker/package.json packages/worker/package.json
|
||||||
ADD packages/worker .
|
# string-templates does not get bundled during the esbuild process, so we want to use the local version
|
||||||
COPY yarn.lock .
|
COPY packages/string-templates/package.json packages/string-templates/package.json
|
||||||
RUN yarn install --production=true --network-timeout 1000000
|
|
||||||
RUN /cleanup.sh
|
|
||||||
|
|
||||||
FROM budibase/couchdb
|
|
||||||
|
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
||||||
|
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
||||||
|
RUN ./scripts/removeWorkspaceDependencies.sh packages/server/package.json
|
||||||
|
RUN ./scripts/removeWorkspaceDependencies.sh packages/worker/package.json
|
||||||
|
|
||||||
|
|
||||||
|
# We will never want to sync pro, but the script is still required
|
||||||
|
RUN echo '' > scripts/syncProPackage.js
|
||||||
|
RUN jq 'del(.scripts.postinstall)' package.json > temp.json && mv temp.json package.json
|
||||||
|
RUN ./scripts/removeWorkspaceDependencies.sh package.json
|
||||||
|
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production
|
||||||
|
|
||||||
|
# copy the actual code
|
||||||
|
COPY packages/server/dist packages/server/dist
|
||||||
|
COPY packages/server/pm2.config.js packages/server/pm2.config.js
|
||||||
|
COPY packages/server/client packages/server/client
|
||||||
|
COPY packages/server/builder packages/server/builder
|
||||||
|
COPY packages/worker/dist packages/worker/dist
|
||||||
|
COPY packages/worker/pm2.config.js packages/worker/pm2.config.js
|
||||||
|
COPY packages/string-templates packages/string-templates
|
||||||
|
|
||||||
|
|
||||||
|
FROM budibase/couchdb as runner
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ENV TARGETARCH $TARGETARCH
|
ENV TARGETARCH $TARGETARCH
|
||||||
|
ENV NODE_MAJOR 18
|
||||||
#TARGETBUILD can be set to single (for single docker image) or aas (for azure app service)
|
#TARGETBUILD can be set to single (for single docker image) or aas (for azure app service)
|
||||||
# e.g. docker build --build-arg TARGETBUILD=aas ....
|
# e.g. docker build --build-arg TARGETBUILD=aas ....
|
||||||
ARG TARGETBUILD=single
|
ARG TARGETBUILD=single
|
||||||
ENV TARGETBUILD $TARGETBUILD
|
ENV TARGETBUILD $TARGETBUILD
|
||||||
|
|
||||||
COPY --from=build /app /app
|
|
||||||
COPY --from=build /worker /worker
|
|
||||||
|
|
||||||
# install base dependencies
|
# install base dependencies
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends software-properties-common nginx uuid-runtime redis-server
|
apt-get install -y --no-install-recommends software-properties-common nginx uuid-runtime redis-server libaio1
|
||||||
|
|
||||||
# Install postgres client for pg_dump utils
|
# Install postgres client for pg_dump utils
|
||||||
RUN apt install software-properties-common apt-transport-https gpg -y \
|
RUN apt install -y software-properties-common apt-transport-https ca-certificates gnupg \
|
||||||
&& curl -fsSl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/postgresql.gpg > /dev/null \
|
&& curl -fsSl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/postgresql.gpg > /dev/null \
|
||||||
&& echo deb [arch=amd64,arm64,ppc64el signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main | tee /etc/apt/sources.list.d/postgresql.list \
|
&& echo deb [arch=amd64,arm64,ppc64el signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main | tee /etc/apt/sources.list.d/postgresql.list \
|
||||||
&& apt update -y \
|
&& apt update -y \
|
||||||
|
@ -47,14 +62,12 @@ RUN apt install software-properties-common apt-transport-https gpg -y \
|
||||||
|
|
||||||
# install other dependencies, nodejs, oracle requirements, jdk8, redis, nginx
|
# install other dependencies, nodejs, oracle requirements, jdk8, redis, nginx
|
||||||
WORKDIR /nodejs
|
WORKDIR /nodejs
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_16.x -o /tmp/nodesource_setup.sh && \
|
COPY scripts/install-node.sh ./install.sh
|
||||||
bash /tmp/nodesource_setup.sh && \
|
RUN chmod +x install.sh && ./install.sh
|
||||||
apt-get install -y --no-install-recommends libaio1 nodejs && \
|
|
||||||
npm install --global yarn pm2
|
|
||||||
|
|
||||||
# setup nginx
|
# setup nginx
|
||||||
ADD hosting/single/nginx/nginx.conf /etc/nginx
|
COPY hosting/single/nginx/nginx.conf /etc/nginx
|
||||||
ADD hosting/single/nginx/nginx-default-site.conf /etc/nginx/sites-enabled/default
|
COPY hosting/single/nginx/nginx-default-site.conf /etc/nginx/sites-enabled/default
|
||||||
RUN mkdir -p /var/log/nginx && \
|
RUN mkdir -p /var/log/nginx && \
|
||||||
touch /var/log/nginx/error.log && \
|
touch /var/log/nginx/error.log && \
|
||||||
touch /var/run/nginx.pid && \
|
touch /var/run/nginx.pid && \
|
||||||
|
@ -62,29 +75,41 @@ RUN mkdir -p /var/log/nginx && \
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
RUN mkdir -p scripts/integrations/oracle
|
RUN mkdir -p scripts/integrations/oracle
|
||||||
ADD packages/server/scripts/integrations/oracle scripts/integrations/oracle
|
COPY packages/server/scripts/integrations/oracle scripts/integrations/oracle
|
||||||
RUN /bin/bash -e ./scripts/integrations/oracle/instantclient/linux/install.sh
|
RUN /bin/bash -e ./scripts/integrations/oracle/instantclient/linux/install.sh
|
||||||
|
|
||||||
# setup minio
|
# setup minio
|
||||||
WORKDIR /minio
|
WORKDIR /minio
|
||||||
ADD scripts/install-minio.sh ./install.sh
|
COPY scripts/install-minio.sh ./install.sh
|
||||||
RUN chmod +x install.sh && ./install.sh
|
RUN chmod +x install.sh && ./install.sh
|
||||||
|
|
||||||
# setup runner file
|
# setup runner file
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
ADD hosting/single/runner.sh .
|
COPY hosting/single/runner.sh .
|
||||||
RUN chmod +x ./runner.sh
|
RUN chmod +x ./runner.sh
|
||||||
ADD hosting/single/healthcheck.sh .
|
COPY hosting/single/healthcheck.sh .
|
||||||
RUN chmod +x ./healthcheck.sh
|
RUN chmod +x ./healthcheck.sh
|
||||||
|
|
||||||
# Script below sets the path for storing data based on $DATA_DIR
|
# Script below sets the path for storing data based on $DATA_DIR
|
||||||
# For Azure App Service install SSH & point data locations to /home
|
# For Azure App Service install SSH & point data locations to /home
|
||||||
ADD hosting/single/ssh/sshd_config /etc/
|
COPY hosting/single/ssh/sshd_config /etc/
|
||||||
ADD hosting/single/ssh/ssh_setup.sh /tmp
|
COPY hosting/single/ssh/ssh_setup.sh /tmp
|
||||||
RUN /build-target-paths.sh
|
RUN /build-target-paths.sh
|
||||||
|
|
||||||
# cleanup cache
|
|
||||||
RUN yarn cache clean -f
|
# setup letsencrypt certificate
|
||||||
|
RUN apt-get install -y certbot python3-certbot-nginx
|
||||||
|
COPY hosting/letsencrypt /app/letsencrypt
|
||||||
|
RUN chmod +x /app/letsencrypt/certificate-request.sh /app/letsencrypt/certificate-renew.sh
|
||||||
|
|
||||||
|
COPY --from=build /app/node_modules /node_modules
|
||||||
|
COPY --from=build /app/package.json /package.json
|
||||||
|
COPY --from=build /app/packages/server /app
|
||||||
|
COPY --from=build /app/packages/worker /worker
|
||||||
|
COPY --from=build /app/packages/string-templates /string-templates
|
||||||
|
|
||||||
|
RUN cd /string-templates && yarn link && cd ../app && yarn link @budibase/string-templates && cd ../worker && yarn link @budibase/string-templates
|
||||||
|
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
EXPOSE 443
|
EXPOSE 443
|
||||||
|
@ -92,20 +117,10 @@ EXPOSE 443
|
||||||
EXPOSE 2222
|
EXPOSE 2222
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
|
|
||||||
# setup letsencrypt certificate
|
ARG BUDIBASE_VERSION
|
||||||
RUN apt-get install -y certbot python3-certbot-nginx
|
# Ensuring the version argument is sent
|
||||||
ADD hosting/letsencrypt /app/letsencrypt
|
RUN test -n "$BUDIBASE_VERSION"
|
||||||
RUN chmod +x /app/letsencrypt/certificate-request.sh /app/letsencrypt/certificate-renew.sh
|
ENV BUDIBASE_VERSION=$BUDIBASE_VERSION
|
||||||
# Remove cached files
|
|
||||||
RUN rm -rf \
|
|
||||||
/root/.cache \
|
|
||||||
/root/.npm \
|
|
||||||
/root/.pip \
|
|
||||||
/usr/local/share/doc \
|
|
||||||
/usr/share/doc \
|
|
||||||
/usr/share/man \
|
|
||||||
/var/lib/apt/lists/* \
|
|
||||||
/tmp/*
|
|
||||||
|
|
||||||
HEALTHCHECK --interval=15s --timeout=15s --start-period=45s CMD "/healthcheck.sh"
|
HEALTHCHECK --interval=15s --timeout=15s --start-period=45s CMD "/healthcheck.sh"
|
||||||
|
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
FROM node:18-slim as build
|
|
||||||
|
|
||||||
# install node-gyp dependencies
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends g++ make python3 jq
|
|
||||||
|
|
||||||
|
|
||||||
# copy and install dependencies
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package.json .
|
|
||||||
COPY yarn.lock .
|
|
||||||
COPY lerna.json .
|
|
||||||
COPY .yarnrc .
|
|
||||||
|
|
||||||
COPY packages/server/package.json packages/server/package.json
|
|
||||||
COPY packages/worker/package.json packages/worker/package.json
|
|
||||||
# string-templates does not get bundled during the esbuild process, so we want to use the local version
|
|
||||||
COPY packages/string-templates/package.json packages/string-templates/package.json
|
|
||||||
|
|
||||||
|
|
||||||
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
|
||||||
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
|
||||||
RUN ./scripts/removeWorkspaceDependencies.sh packages/server/package.json
|
|
||||||
RUN ./scripts/removeWorkspaceDependencies.sh packages/worker/package.json
|
|
||||||
|
|
||||||
|
|
||||||
# We will never want to sync pro, but the script is still required
|
|
||||||
RUN echo '' > scripts/syncProPackage.js
|
|
||||||
RUN jq 'del(.scripts.postinstall)' package.json > temp.json && mv temp.json package.json
|
|
||||||
RUN ./scripts/removeWorkspaceDependencies.sh package.json
|
|
||||||
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production
|
|
||||||
|
|
||||||
# copy the actual code
|
|
||||||
COPY packages/server/dist packages/server/dist
|
|
||||||
COPY packages/server/pm2.config.js packages/server/pm2.config.js
|
|
||||||
COPY packages/server/client packages/server/client
|
|
||||||
COPY packages/server/builder packages/server/builder
|
|
||||||
COPY packages/worker/dist packages/worker/dist
|
|
||||||
COPY packages/worker/pm2.config.js packages/worker/pm2.config.js
|
|
||||||
COPY packages/string-templates packages/string-templates
|
|
||||||
|
|
||||||
|
|
||||||
FROM budibase/couchdb as runner
|
|
||||||
ARG TARGETARCH
|
|
||||||
ENV TARGETARCH $TARGETARCH
|
|
||||||
ENV NODE_MAJOR 18
|
|
||||||
#TARGETBUILD can be set to single (for single docker image) or aas (for azure app service)
|
|
||||||
# e.g. docker build --build-arg TARGETBUILD=aas ....
|
|
||||||
ARG TARGETBUILD=single
|
|
||||||
ENV TARGETBUILD $TARGETBUILD
|
|
||||||
|
|
||||||
# install base dependencies
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y --no-install-recommends software-properties-common nginx uuid-runtime redis-server libaio1
|
|
||||||
|
|
||||||
# Install postgres client for pg_dump utils
|
|
||||||
RUN apt install -y software-properties-common apt-transport-https ca-certificates gnupg \
|
|
||||||
&& curl -fsSl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/postgresql.gpg > /dev/null \
|
|
||||||
&& echo deb [arch=amd64,arm64,ppc64el signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main | tee /etc/apt/sources.list.d/postgresql.list \
|
|
||||||
&& apt update -y \
|
|
||||||
&& apt install postgresql-client-15 -y \
|
|
||||||
&& apt remove software-properties-common apt-transport-https gpg -y
|
|
||||||
|
|
||||||
# install other dependencies, nodejs, oracle requirements, jdk8, redis, nginx
|
|
||||||
WORKDIR /nodejs
|
|
||||||
COPY scripts/install-node.sh ./install.sh
|
|
||||||
RUN chmod +x install.sh && ./install.sh
|
|
||||||
|
|
||||||
# setup nginx
|
|
||||||
COPY hosting/single/nginx/nginx.conf /etc/nginx
|
|
||||||
COPY hosting/single/nginx/nginx-default-site.conf /etc/nginx/sites-enabled/default
|
|
||||||
RUN mkdir -p /var/log/nginx && \
|
|
||||||
touch /var/log/nginx/error.log && \
|
|
||||||
touch /var/run/nginx.pid && \
|
|
||||||
usermod -a -G tty www-data
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
RUN mkdir -p scripts/integrations/oracle
|
|
||||||
COPY packages/server/scripts/integrations/oracle scripts/integrations/oracle
|
|
||||||
RUN /bin/bash -e ./scripts/integrations/oracle/instantclient/linux/install.sh
|
|
||||||
|
|
||||||
# setup minio
|
|
||||||
WORKDIR /minio
|
|
||||||
COPY scripts/install-minio.sh ./install.sh
|
|
||||||
RUN chmod +x install.sh && ./install.sh
|
|
||||||
|
|
||||||
# setup runner file
|
|
||||||
WORKDIR /
|
|
||||||
COPY hosting/single/runner.sh .
|
|
||||||
RUN chmod +x ./runner.sh
|
|
||||||
COPY hosting/single/healthcheck.sh .
|
|
||||||
RUN chmod +x ./healthcheck.sh
|
|
||||||
|
|
||||||
# Script below sets the path for storing data based on $DATA_DIR
|
|
||||||
# For Azure App Service install SSH & point data locations to /home
|
|
||||||
COPY hosting/single/ssh/sshd_config /etc/
|
|
||||||
COPY hosting/single/ssh/ssh_setup.sh /tmp
|
|
||||||
RUN /build-target-paths.sh
|
|
||||||
|
|
||||||
|
|
||||||
# setup letsencrypt certificate
|
|
||||||
RUN apt-get install -y certbot python3-certbot-nginx
|
|
||||||
COPY hosting/letsencrypt /app/letsencrypt
|
|
||||||
RUN chmod +x /app/letsencrypt/certificate-request.sh /app/letsencrypt/certificate-renew.sh
|
|
||||||
|
|
||||||
COPY --from=build /app/node_modules /node_modules
|
|
||||||
COPY --from=build /app/package.json /package.json
|
|
||||||
COPY --from=build /app/packages/server /app
|
|
||||||
COPY --from=build /app/packages/worker /worker
|
|
||||||
COPY --from=build /app/packages/string-templates /string-templates
|
|
||||||
|
|
||||||
RUN cd /string-templates && yarn link && cd ../app && yarn link @budibase/string-templates && cd ../worker && yarn link @budibase/string-templates
|
|
||||||
|
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
EXPOSE 443
|
|
||||||
# Expose port 2222 for SSH on Azure App Service build
|
|
||||||
EXPOSE 2222
|
|
||||||
VOLUME /data
|
|
||||||
|
|
||||||
ARG BUDIBASE_VERSION
|
|
||||||
# Ensuring the version argument is sent
|
|
||||||
RUN test -n "$BUDIBASE_VERSION"
|
|
||||||
ENV BUDIBASE_VERSION=$BUDIBASE_VERSION
|
|
||||||
|
|
||||||
HEALTHCHECK --interval=15s --timeout=15s --start-period=45s CMD "/healthcheck.sh"
|
|
||||||
|
|
||||||
# must set this just before running
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
CMD ["./runner.sh"]
|
|
|
@ -20,7 +20,7 @@ import ValidationEditor from "./controls/ValidationEditor/ValidationEditor.svelt
|
||||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||||
import ColumnEditor from "./controls/ColumnEditor/ColumnEditor.svelte"
|
import ColumnEditor from "./controls/ColumnEditor/ColumnEditor.svelte"
|
||||||
import BasicColumnEditor from "./controls/ColumnEditor/BasicColumnEditor.svelte"
|
import BasicColumnEditor from "./controls/ColumnEditor/BasicColumnEditor.svelte"
|
||||||
import GridColumnEditor from "./controls/ColumnEditor/GridColumnEditor.svelte"
|
import GridColumnEditor from "./controls/GridColumnConfiguration/GridColumnConfiguration.svelte"
|
||||||
import BarButtonList from "./controls/BarButtonList.svelte"
|
import BarButtonList from "./controls/BarButtonList.svelte"
|
||||||
import FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration.svelte"
|
import FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration.svelte"
|
||||||
import ButtonConfiguration from "./controls/ButtonConfiguration/ButtonConfiguration.svelte"
|
import ButtonConfiguration from "./controls/ButtonConfiguration/ButtonConfiguration.svelte"
|
||||||
|
@ -28,6 +28,7 @@ import RelationshipFilterEditor from "./controls/RelationshipFilterEditor.svelte
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
text: DrawerBindableInput,
|
text: DrawerBindableInput,
|
||||||
|
plainText: Input,
|
||||||
select: Select,
|
select: Select,
|
||||||
radio: RadioGroup,
|
radio: RadioGroup,
|
||||||
dataSource: DataSourceSelect,
|
dataSource: DataSourceSelect,
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
<script>
|
|
||||||
import ColumnEditor from "./ColumnEditor.svelte"
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ColumnEditor
|
|
||||||
{...$$props}
|
|
||||||
on:change
|
|
||||||
allowCellEditing={false}
|
|
||||||
allowReorder={false}
|
|
||||||
/>
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
<script>
|
||||||
|
import EditComponentPopover from "../EditComponentPopover.svelte"
|
||||||
|
import { FieldTypeToComponentMap } from "../FieldConfiguration/utils"
|
||||||
|
import { Toggle, Icon } from "@budibase/bbui"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
|
||||||
|
export let item
|
||||||
|
export let anchor
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
const onToggle = item => {
|
||||||
|
return e => {
|
||||||
|
item.active = e.detail
|
||||||
|
dispatch("change", { ...cloneDeep(item), active: e.detail })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseSettings = settings => {
|
||||||
|
return settings
|
||||||
|
.filter(setting => setting.key !== "field")
|
||||||
|
.map(setting => {
|
||||||
|
return { ...setting, nested: true }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getIcon = () => {
|
||||||
|
const component = `@budibase/standard-components/${
|
||||||
|
FieldTypeToComponentMap[item.columnType]
|
||||||
|
}`
|
||||||
|
return store.actions.components.getDefinition(component).icon
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="list-item-body">
|
||||||
|
<div class="list-item-left">
|
||||||
|
<EditComponentPopover
|
||||||
|
{anchor}
|
||||||
|
componentInstance={item}
|
||||||
|
{parseSettings}
|
||||||
|
on:change
|
||||||
|
>
|
||||||
|
<div slot="header" class="type-icon">
|
||||||
|
<Icon name={getIcon()} />
|
||||||
|
<span>{item.field}</span>
|
||||||
|
</div>
|
||||||
|
</EditComponentPopover>
|
||||||
|
<div class="field-label">{item.label || item.field}</div>
|
||||||
|
</div>
|
||||||
|
<div class="list-item-right">
|
||||||
|
<Toggle on:change={onToggle(item)} text="" value={item.active} thin />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.field-label {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.list-item-body,
|
||||||
|
.list-item-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.list-item-right :global(div.spectrum-Switch) {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.list-item-body {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.type-icon {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
margin: var(--spacing-xl);
|
||||||
|
margin-bottom: 0px;
|
||||||
|
height: var(--spectrum-alias-item-height-m);
|
||||||
|
padding: 0px var(--spectrum-alias-item-padding-m);
|
||||||
|
border-width: var(--spectrum-actionbutton-border-size);
|
||||||
|
border-radius: var(--spectrum-alias-border-radius-regular);
|
||||||
|
border: 1px solid
|
||||||
|
var(
|
||||||
|
--spectrum-actionbutton-m-border-color,
|
||||||
|
var(--spectrum-alias-border-color)
|
||||||
|
);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getDatasourceForProvider,
|
||||||
|
getSchemaForDatasource,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
|
import { currentAsset, store } from "builderStore"
|
||||||
|
import DraggableList from "../DraggableList/DraggableList.svelte"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
import FieldSetting from "./FieldSetting.svelte"
|
||||||
|
import PrimaryColumnFieldSetting from "./PrimaryColumnFieldSetting.svelte"
|
||||||
|
import getColumns from "./getColumns.js"
|
||||||
|
|
||||||
|
export let value
|
||||||
|
export let componentInstance
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
let primaryDisplayColumnAnchor
|
||||||
|
|
||||||
|
const handleChange = newValues => {
|
||||||
|
dispatch("change", newValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSchema = (asset, datasource) => {
|
||||||
|
const schema = getSchemaForDatasource(asset, datasource).schema
|
||||||
|
|
||||||
|
// Don't show ID and rev in tables
|
||||||
|
if (schema) {
|
||||||
|
delete schema._id
|
||||||
|
delete schema._rev
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
|
||||||
|
$: primaryDisplayColumnName = getSchemaForDatasource(
|
||||||
|
$currentAsset,
|
||||||
|
datasource
|
||||||
|
)?.table?.primaryDisplay
|
||||||
|
$: schema = getSchema(currentAsset, datasource)
|
||||||
|
$: columns = getColumns({
|
||||||
|
columns: value,
|
||||||
|
schema,
|
||||||
|
primaryDisplayColumnName,
|
||||||
|
onChange: handleChange,
|
||||||
|
createComponent: store.actions.components.createInstance,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if columns.primary}
|
||||||
|
<div class="sticky-item">
|
||||||
|
<div bind:this={primaryDisplayColumnAnchor} class="sticky-item-inner">
|
||||||
|
<div class="right-content">
|
||||||
|
<PrimaryColumnFieldSetting
|
||||||
|
anchor={primaryDisplayColumnAnchor}
|
||||||
|
item={columns.primary}
|
||||||
|
on:change={e => columns.update(e.detail)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<DraggableList
|
||||||
|
on:change={e => columns.updateSortable(e.detail)}
|
||||||
|
on:itemChange={e => columns.update(e.detail)}
|
||||||
|
items={columns.sortable}
|
||||||
|
listItemKey={"_id"}
|
||||||
|
listType={FieldSetting}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.right-content {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-left: 17.5px;
|
||||||
|
}
|
||||||
|
.sticky-item {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: var(
|
||||||
|
--spectrum-table-background-color,
|
||||||
|
var(--spectrum-global-color-gray-50)
|
||||||
|
);
|
||||||
|
border: 1px solid
|
||||||
|
var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.sticky-item-inner {
|
||||||
|
background-color: var(
|
||||||
|
--spectrum-table-background-color,
|
||||||
|
var(--spectrum-global-color-gray-50)
|
||||||
|
);
|
||||||
|
transition: background-color ease-in-out 130ms;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid
|
||||||
|
var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
|
||||||
|
padding-left: var(--spacing-s);
|
||||||
|
padding-right: var(--spacing-s);
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,100 @@
|
||||||
|
<script>
|
||||||
|
import EditComponentPopover from "../EditComponentPopover.svelte"
|
||||||
|
import { Icon } from "@budibase/bbui"
|
||||||
|
import { setContext } from "svelte"
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import { FieldTypeToComponentMap } from "../FieldConfiguration/utils"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
|
||||||
|
export let item
|
||||||
|
export let anchor
|
||||||
|
|
||||||
|
let draggableStore = writable({
|
||||||
|
selected: null,
|
||||||
|
actions: {
|
||||||
|
select: id => {
|
||||||
|
draggableStore.update(state => ({
|
||||||
|
...state,
|
||||||
|
selected: id,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
setContext("draggable", draggableStore)
|
||||||
|
|
||||||
|
const parseSettings = settings => {
|
||||||
|
return settings
|
||||||
|
.filter(setting => setting.key !== "field")
|
||||||
|
.map(setting => {
|
||||||
|
return { ...setting, nested: true }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getIcon = item => {
|
||||||
|
const component = `@budibase/standard-components/${
|
||||||
|
FieldTypeToComponentMap[item.columnType]
|
||||||
|
}`
|
||||||
|
return store.actions.components.getDefinition(component)?.icon
|
||||||
|
}
|
||||||
|
|
||||||
|
$: icon = getIcon(item)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="list-item-body">
|
||||||
|
<div class="list-item-left">
|
||||||
|
<EditComponentPopover
|
||||||
|
{anchor}
|
||||||
|
componentInstance={item}
|
||||||
|
{parseSettings}
|
||||||
|
on:change
|
||||||
|
>
|
||||||
|
<div slot="header" class="type-icon">
|
||||||
|
<Icon name={icon} />
|
||||||
|
<span>{item.field}</span>
|
||||||
|
</div>
|
||||||
|
</EditComponentPopover>
|
||||||
|
<div class="field-label">{item.label || item.field}</div>
|
||||||
|
</div>
|
||||||
|
<div title="The display column is always shown first" class="list-item-right">
|
||||||
|
<Icon name={"Info"} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.field-label {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.list-item-body,
|
||||||
|
.list-item-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.list-item-right :global(svg) {
|
||||||
|
color: var(--grey-5);
|
||||||
|
padding: 7px 5px 7px 0;
|
||||||
|
}
|
||||||
|
.list-item-body {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.type-icon {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
margin: var(--spacing-xl);
|
||||||
|
margin-bottom: 0px;
|
||||||
|
height: var(--spectrum-alias-item-height-m);
|
||||||
|
padding: 0px var(--spectrum-alias-item-padding-m);
|
||||||
|
border-width: var(--spectrum-actionbutton-border-size);
|
||||||
|
border-radius: var(--spectrum-alias-border-radius-regular);
|
||||||
|
border: 1px solid
|
||||||
|
var(
|
||||||
|
--spectrum-actionbutton-m-border-color,
|
||||||
|
var(--spectrum-alias-border-color)
|
||||||
|
);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,129 @@
|
||||||
|
const modernize = columns => {
|
||||||
|
if (!columns) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
// If the first element has no active key then it's safe to assume all elements are in the old format
|
||||||
|
if (columns?.[0] && columns[0].active === undefined) {
|
||||||
|
return columns.map(column => ({
|
||||||
|
label: column.displayName,
|
||||||
|
field: column.name,
|
||||||
|
active: true,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
return columns
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeInvalidAddMissing = (
|
||||||
|
columns = [],
|
||||||
|
defaultColumns,
|
||||||
|
primaryDisplayColumnName
|
||||||
|
) => {
|
||||||
|
const defaultColumnNames = defaultColumns.map(column => column.field)
|
||||||
|
const columnNames = columns.map(column => column.field)
|
||||||
|
|
||||||
|
const validColumns = columns.filter(column =>
|
||||||
|
defaultColumnNames.includes(column.field)
|
||||||
|
)
|
||||||
|
let missingColumns = defaultColumns.filter(
|
||||||
|
defaultColumn => !columnNames.includes(defaultColumn.field)
|
||||||
|
)
|
||||||
|
|
||||||
|
// If the user already has fields selected, any appended missing fields should be disabled by default
|
||||||
|
if (validColumns.length) {
|
||||||
|
missingColumns = missingColumns.map(field => ({ ...field, active: false }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const combinedColumns = [...validColumns, ...missingColumns]
|
||||||
|
|
||||||
|
// Ensure the primary display column is always visible
|
||||||
|
const primaryDisplayIndex = combinedColumns.findIndex(
|
||||||
|
column => column.field === primaryDisplayColumnName
|
||||||
|
)
|
||||||
|
if (primaryDisplayIndex > -1) {
|
||||||
|
combinedColumns[primaryDisplayIndex].active = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinedColumns
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDefault = (schema = {}) => {
|
||||||
|
const defaultValues = Object.values(schema)
|
||||||
|
.filter(column => !column.nestedJSON)
|
||||||
|
.map(column => ({
|
||||||
|
label: column.name,
|
||||||
|
field: column.name,
|
||||||
|
active: column.visible ?? true,
|
||||||
|
order: column.visible ? column.order ?? -1 : Number.MAX_SAFE_INTEGER,
|
||||||
|
}))
|
||||||
|
|
||||||
|
defaultValues.sort((a, b) => a.order - b.order)
|
||||||
|
|
||||||
|
return defaultValues
|
||||||
|
}
|
||||||
|
|
||||||
|
const toGridFormat = draggableListColumns => {
|
||||||
|
return draggableListColumns.map(entry => ({
|
||||||
|
label: entry.label,
|
||||||
|
field: entry.field,
|
||||||
|
active: entry.active,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const toDraggableListFormat = (gridFormatColumns, createComponent, schema) => {
|
||||||
|
return gridFormatColumns.map(column => {
|
||||||
|
return createComponent(
|
||||||
|
"@budibase/standard-components/labelfield",
|
||||||
|
{
|
||||||
|
_instanceName: column.field,
|
||||||
|
active: column.active,
|
||||||
|
field: column.field,
|
||||||
|
label: column.label,
|
||||||
|
columnType: schema[column.field].type,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getColumns = ({
|
||||||
|
columns,
|
||||||
|
schema,
|
||||||
|
primaryDisplayColumnName,
|
||||||
|
onChange,
|
||||||
|
createComponent,
|
||||||
|
}) => {
|
||||||
|
const validatedColumns = removeInvalidAddMissing(
|
||||||
|
modernize(columns),
|
||||||
|
getDefault(schema),
|
||||||
|
primaryDisplayColumnName
|
||||||
|
)
|
||||||
|
const draggableList = toDraggableListFormat(
|
||||||
|
validatedColumns,
|
||||||
|
createComponent,
|
||||||
|
schema
|
||||||
|
)
|
||||||
|
const primary = draggableList.find(
|
||||||
|
entry => entry.field === primaryDisplayColumnName
|
||||||
|
)
|
||||||
|
const sortable = draggableList.filter(
|
||||||
|
entry => entry.field !== primaryDisplayColumnName
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
primary,
|
||||||
|
sortable,
|
||||||
|
updateSortable: newDraggableList => {
|
||||||
|
onChange(toGridFormat(newDraggableList.concat(primary)))
|
||||||
|
},
|
||||||
|
update: newEntry => {
|
||||||
|
const newDraggableList = draggableList.map(entry => {
|
||||||
|
return newEntry.field === entry.field ? newEntry : entry
|
||||||
|
})
|
||||||
|
|
||||||
|
onChange(toGridFormat(newDraggableList))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getColumns
|
|
@ -0,0 +1,374 @@
|
||||||
|
import { it, expect, describe, beforeEach, vi } from "vitest"
|
||||||
|
import getColumns from "./getColumns"
|
||||||
|
|
||||||
|
describe("getColumns", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.schema = {
|
||||||
|
one: { name: "one", visible: false, order: 0, type: "foo" },
|
||||||
|
two: { name: "two", visible: true, order: 1, type: "foo" },
|
||||||
|
three: { name: "three", visible: true, order: 2, type: "foo" },
|
||||||
|
four: { name: "four", visible: false, order: 3, type: "foo" },
|
||||||
|
five: {
|
||||||
|
name: "excluded",
|
||||||
|
visible: true,
|
||||||
|
order: 4,
|
||||||
|
type: "foo",
|
||||||
|
nestedJSON: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.primaryDisplayColumnName = "four"
|
||||||
|
ctx.onChange = vi.fn()
|
||||||
|
ctx.createComponent = (componentName, props) => {
|
||||||
|
return { componentName, ...props }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("nested json fields", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.columns = getColumns({
|
||||||
|
columns: null,
|
||||||
|
schema: ctx.schema,
|
||||||
|
primaryDisplayColumnName: ctx.primaryDisplayColumnName,
|
||||||
|
onChange: ctx.onChange,
|
||||||
|
createComponent: ctx.createComponent,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("does not return nested json fields, as the grid cannot display them", ctx => {
|
||||||
|
expect(ctx.columns.sortable).not.toContainEqual({
|
||||||
|
name: "excluded",
|
||||||
|
visible: true,
|
||||||
|
order: 4,
|
||||||
|
type: "foo",
|
||||||
|
nestedJSON: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("using the old grid column format", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
const oldGridFormatColumns = [
|
||||||
|
{ displayName: "three label", name: "three" },
|
||||||
|
{ displayName: "two label", name: "two" },
|
||||||
|
]
|
||||||
|
|
||||||
|
ctx.columns = getColumns({
|
||||||
|
columns: oldGridFormatColumns,
|
||||||
|
schema: ctx.schema,
|
||||||
|
primaryDisplayColumnName: ctx.primaryDisplayColumnName,
|
||||||
|
onChange: ctx.onChange,
|
||||||
|
createComponent: ctx.createComponent,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns the selected and unselected fields in the modern format, respecting the original order", ctx => {
|
||||||
|
expect(ctx.columns.sortable).toEqual([
|
||||||
|
{
|
||||||
|
_instanceName: "three",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "three",
|
||||||
|
label: "three label",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "two",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "two",
|
||||||
|
label: "two label",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "one",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "one",
|
||||||
|
label: "one",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(ctx.columns.primary).toEqual({
|
||||||
|
_instanceName: "four",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "four",
|
||||||
|
label: "four",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("default columns", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.columns = getColumns({
|
||||||
|
columns: undefined,
|
||||||
|
schema: ctx.schema,
|
||||||
|
primaryDisplayColumnName: ctx.primaryDisplayColumnName,
|
||||||
|
onChange: ctx.onChange,
|
||||||
|
createComponent: ctx.createComponent,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns all columns, with non-hidden columns automatically selected", ctx => {
|
||||||
|
expect(ctx.columns.sortable).toEqual([
|
||||||
|
{
|
||||||
|
_instanceName: "two",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "two",
|
||||||
|
label: "two",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "three",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "three",
|
||||||
|
label: "three",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "one",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "one",
|
||||||
|
label: "one",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(ctx.columns.primary).toEqual({
|
||||||
|
_instanceName: "four",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "four",
|
||||||
|
label: "four",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Unselected columns should be placed at the end", ctx => {
|
||||||
|
expect(ctx.columns.sortable[2].field).toEqual("one")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("missing columns", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
const gridFormatColumns = [
|
||||||
|
{ label: "three label", field: "three", active: true },
|
||||||
|
]
|
||||||
|
|
||||||
|
ctx.columns = getColumns({
|
||||||
|
columns: gridFormatColumns,
|
||||||
|
schema: ctx.schema,
|
||||||
|
primaryDisplayColumnName: ctx.primaryDisplayColumnName,
|
||||||
|
onChange: ctx.onChange,
|
||||||
|
createComponent: ctx.createComponent,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns all columns, including those missing from the initial data", ctx => {
|
||||||
|
expect(ctx.columns.sortable).toEqual([
|
||||||
|
{
|
||||||
|
_instanceName: "three",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "three",
|
||||||
|
label: "three label",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "two",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "two",
|
||||||
|
label: "two",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "one",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "one",
|
||||||
|
label: "one",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(ctx.columns.primary).toEqual({
|
||||||
|
_instanceName: "four",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "four",
|
||||||
|
label: "four",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("invalid columns", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
const gridFormatColumns = [
|
||||||
|
{ label: "three label", field: "three", active: true },
|
||||||
|
{ label: "some nonsense", field: "some nonsense", active: true },
|
||||||
|
]
|
||||||
|
|
||||||
|
ctx.columns = getColumns({
|
||||||
|
columns: gridFormatColumns,
|
||||||
|
schema: ctx.schema,
|
||||||
|
primaryDisplayColumnName: ctx.primaryDisplayColumnName,
|
||||||
|
onChange: ctx.onChange,
|
||||||
|
createComponent: ctx.createComponent,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns all valid columns, excluding those that aren't valid for the schema", ctx => {
|
||||||
|
expect(ctx.columns.sortable).toEqual([
|
||||||
|
{
|
||||||
|
_instanceName: "three",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "three",
|
||||||
|
label: "three label",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "two",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "two",
|
||||||
|
label: "two",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "one",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "one",
|
||||||
|
label: "one",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(ctx.columns.primary).toEqual({
|
||||||
|
_instanceName: "four",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "four",
|
||||||
|
label: "four",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("methods", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
const { update, updateSortable } = getColumns({
|
||||||
|
columns: [],
|
||||||
|
schema: ctx.schema,
|
||||||
|
primaryDisplayColumnName: ctx.primaryDisplayColumnName,
|
||||||
|
onChange: ctx.onChange,
|
||||||
|
createComponent: ctx.createComponent,
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.update = update
|
||||||
|
ctx.updateSortable = updateSortable
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("update", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.update({
|
||||||
|
field: "one",
|
||||||
|
label: "a new label",
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the callback with the updated columns", ctx => {
|
||||||
|
expect(ctx.onChange).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.onChange).toHaveBeenCalledWith([
|
||||||
|
{
|
||||||
|
field: "two",
|
||||||
|
label: "two",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "three",
|
||||||
|
label: "three",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "one",
|
||||||
|
label: "a new label",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "four",
|
||||||
|
label: "four",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("updateSortable", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.updateSortable([
|
||||||
|
{
|
||||||
|
_instanceName: "three",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "three",
|
||||||
|
label: "three",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "one",
|
||||||
|
active: true,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "one",
|
||||||
|
label: "one",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_instanceName: "two",
|
||||||
|
active: false,
|
||||||
|
columnType: "foo",
|
||||||
|
componentName: "@budibase/standard-components/labelfield",
|
||||||
|
field: "two",
|
||||||
|
label: "two",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the callback with the updated columns", ctx => {
|
||||||
|
expect(ctx.onChange).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.onChange).toHaveBeenCalledWith([
|
||||||
|
{
|
||||||
|
field: "three",
|
||||||
|
label: "three",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "one",
|
||||||
|
label: "one",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "two",
|
||||||
|
label: "two",
|
||||||
|
active: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "four",
|
||||||
|
label: "four",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -2698,6 +2698,22 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"labelfield": {
|
||||||
|
"name": "Text Field",
|
||||||
|
"icon": "Text",
|
||||||
|
"editable": true,
|
||||||
|
"size": {
|
||||||
|
"width": 400,
|
||||||
|
"height": 32
|
||||||
|
},
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "plainText",
|
||||||
|
"label": "Label",
|
||||||
|
"key": "label"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"stringfield": {
|
"stringfield": {
|
||||||
"name": "Text Field",
|
"name": "Text Field",
|
||||||
"icon": "Text",
|
"icon": "Text",
|
||||||
|
@ -6308,19 +6324,6 @@
|
||||||
"key": "table",
|
"key": "table",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "columns/grid",
|
|
||||||
"label": "Columns",
|
|
||||||
"key": "columns",
|
|
||||||
"dependsOn": [
|
|
||||||
"table",
|
|
||||||
{
|
|
||||||
"setting": "table.type",
|
|
||||||
"value": "custom",
|
|
||||||
"invert": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
"label": "Filtering",
|
"label": "Filtering",
|
||||||
|
@ -6417,6 +6420,18 @@
|
||||||
"key": "stripeRows",
|
"key": "stripeRows",
|
||||||
"defaultValue": false
|
"defaultValue": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": true,
|
||||||
|
"name": "Columns",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "columns/grid",
|
||||||
|
"key": "columns",
|
||||||
|
"nested": true,
|
||||||
|
"resetOn": "table"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": true,
|
"section": true,
|
||||||
"name": "Buttons",
|
"name": "Buttons",
|
||||||
|
|
|
@ -19,6 +19,22 @@
|
||||||
export let onRowClick = null
|
export let onRowClick = null
|
||||||
export let buttons = null
|
export let buttons = null
|
||||||
|
|
||||||
|
// parses columns to fix older formats
|
||||||
|
const getParsedColumns = columns => {
|
||||||
|
// If the first element has an active key all elements should be in the new format
|
||||||
|
if (columns?.length && columns[0]?.active !== undefined) {
|
||||||
|
return columns
|
||||||
|
}
|
||||||
|
|
||||||
|
return columns?.map(column => ({
|
||||||
|
label: column.displayName || column.name,
|
||||||
|
field: column.name,
|
||||||
|
active: true,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
$: parsedColumns = getParsedColumns(columns)
|
||||||
|
|
||||||
const context = getContext("context")
|
const context = getContext("context")
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
const {
|
const {
|
||||||
|
@ -33,16 +49,17 @@
|
||||||
|
|
||||||
let grid
|
let grid
|
||||||
|
|
||||||
$: columnWhitelist = columns?.map(col => col.name)
|
$: columnWhitelist = parsedColumns
|
||||||
$: schemaOverrides = getSchemaOverrides(columns)
|
?.filter(col => col.active)
|
||||||
|
?.map(col => col.field)
|
||||||
|
$: schemaOverrides = getSchemaOverrides(parsedColumns)
|
||||||
$: enrichedButtons = enrichButtons(buttons)
|
$: enrichedButtons = enrichButtons(buttons)
|
||||||
|
|
||||||
const getSchemaOverrides = columns => {
|
const getSchemaOverrides = columns => {
|
||||||
let overrides = {}
|
let overrides = {}
|
||||||
columns?.forEach(column => {
|
columns?.forEach(column => {
|
||||||
overrides[column.name] = {
|
overrides[column.field] = {
|
||||||
displayName: column.displayName || column.name,
|
displayName: column.label,
|
||||||
visible: true,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return overrides
|
return overrides
|
||||||
|
|
|
@ -55,11 +55,20 @@ export const deriveStores = context => {
|
||||||
|
|
||||||
// Apply whitelist if specified
|
// Apply whitelist if specified
|
||||||
if ($columnWhitelist?.length) {
|
if ($columnWhitelist?.length) {
|
||||||
Object.keys(enrichedSchema).forEach(key => {
|
const sortedColumns = {}
|
||||||
if (!$columnWhitelist.includes(key)) {
|
|
||||||
delete enrichedSchema[key]
|
$columnWhitelist.forEach((columnKey, idx) => {
|
||||||
|
const enrichedColumn = enrichedSchema[columnKey]
|
||||||
|
if (enrichedColumn) {
|
||||||
|
sortedColumns[columnKey] = {
|
||||||
|
...enrichedColumn,
|
||||||
|
order: idx,
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return sortedColumns
|
||||||
}
|
}
|
||||||
|
|
||||||
return enrichedSchema
|
return enrichedSchema
|
||||||
|
|
|
@ -18,12 +18,12 @@ ENV TOP_LEVEL_PATH=/
|
||||||
|
|
||||||
# handle node-gyp
|
# handle node-gyp
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends g++ make python3
|
&& apt-get install -y --no-install-recommends g++ make python3 jq
|
||||||
RUN yarn global add pm2
|
RUN yarn global add pm2
|
||||||
|
|
||||||
# Install client for oracle datasource
|
# Install client for oracle datasource
|
||||||
RUN apt-get install unzip libaio1
|
RUN apt-get install unzip libaio1
|
||||||
COPY scripts/integrations/oracle/ scripts/integrations/oracle/
|
COPY 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/x86-64/install.sh
|
||||||
|
|
||||||
# Install postgres client for pg_dump utils
|
# Install postgres client for pg_dump utils
|
||||||
|
@ -35,18 +35,42 @@ RUN apt update && apt upgrade -y \
|
||||||
&& apt install postgresql-client-15 -y \
|
&& apt install postgresql-client-15 -y \
|
||||||
&& apt remove software-properties-common apt-transport-https curl gpg -y
|
&& apt remove software-properties-common apt-transport-https curl gpg -y
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
COPY package.json .
|
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
||||||
COPY dist/yarn.lock .
|
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
||||||
RUN yarn install --production=true --network-timeout 1000000 \
|
|
||||||
|
|
||||||
|
WORKDIR /string-templates
|
||||||
|
COPY packages/string-templates/package.json package.json
|
||||||
|
RUN ../scripts/removeWorkspaceDependencies.sh package.json
|
||||||
|
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000
|
||||||
|
COPY packages/string-templates .
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY packages/server/package.json .
|
||||||
|
COPY packages/server/dist/yarn.lock .
|
||||||
|
RUN cd ../string-templates && yarn link && cd - && yarn link @budibase/string-templates
|
||||||
|
|
||||||
|
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
||||||
|
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
||||||
|
RUN ./scripts/removeWorkspaceDependencies.sh package.json
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000 \
|
||||||
# Remove unneeded data from file system to reduce image size
|
# Remove unneeded data from file system to reduce image size
|
||||||
&& yarn cache clean && apt-get remove -y --purge --auto-remove g++ make python \
|
&& yarn cache clean && apt-get remove -y --purge --auto-remove g++ make python jq \
|
||||||
&& rm -rf /tmp/* /root/.node-gyp /usr/local/lib/node_modules/npm/node_modules/node-gyp
|
&& rm -rf /tmp/* /root/.node-gyp /usr/local/lib/node_modules/npm/node_modules/node-gyp
|
||||||
|
|
||||||
COPY dist/ dist/
|
COPY packages/server/dist/ dist/
|
||||||
COPY docker_run.sh .
|
COPY packages/server/docker_run.sh .
|
||||||
COPY builder/ builder/
|
COPY packages/server/builder/ builder/
|
||||||
COPY client/ client/
|
COPY packages/server/client/ client/
|
||||||
|
|
||||||
|
ARG BUDIBASE_VERSION
|
||||||
|
# Ensuring the version argument is sent
|
||||||
|
RUN test -n "$BUDIBASE_VERSION"
|
||||||
|
ENV BUDIBASE_VERSION=$BUDIBASE_VERSION
|
||||||
|
|
||||||
EXPOSE 4001
|
EXPOSE 4001
|
||||||
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
FROM node:18-slim
|
|
||||||
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.pre-check="scripts/watchtower-hooks/pre-check.sh"
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.pre-update="scripts/watchtower-hooks/pre-update.sh"
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.post-update="scripts/watchtower-hooks/post-update.sh"
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.post-check="scripts/watchtower-hooks/post-check.sh"
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
ENV PORT=4001
|
|
||||||
ENV COUCH_DB_URL=https://couchdb.budi.live:5984
|
|
||||||
ENV BUDIBASE_ENVIRONMENT=PRODUCTION
|
|
||||||
ENV SERVICE=app-service
|
|
||||||
ENV POSTHOG_TOKEN=phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU
|
|
||||||
ENV TENANT_FEATURE_FLAGS=*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR
|
|
||||||
ENV ACCOUNT_PORTAL_URL=https://account.budibase.app
|
|
||||||
ENV TOP_LEVEL_PATH=/
|
|
||||||
|
|
||||||
# handle node-gyp
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends g++ make python3 jq
|
|
||||||
RUN yarn global add pm2
|
|
||||||
|
|
||||||
# Install client for oracle datasource
|
|
||||||
RUN apt-get install unzip libaio1
|
|
||||||
COPY packages/server/scripts/integrations/oracle/ scripts/integrations/oracle/
|
|
||||||
RUN /bin/bash -e scripts/integrations/oracle/instantclient/linux/x86-64/install.sh
|
|
||||||
|
|
||||||
# Install postgres client for pg_dump utils
|
|
||||||
RUN apt update && apt upgrade -y \
|
|
||||||
&& apt install software-properties-common apt-transport-https curl gpg -y \
|
|
||||||
&& curl -fsSl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/postgresql.gpg > /dev/null \
|
|
||||||
&& echo deb [arch=amd64,arm64,ppc64el signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main | tee /etc/apt/sources.list.d/postgresql.list \
|
|
||||||
&& apt update -y \
|
|
||||||
&& apt install postgresql-client-15 -y \
|
|
||||||
&& apt remove software-properties-common apt-transport-https curl gpg -y
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
|
||||||
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /string-templates
|
|
||||||
COPY packages/string-templates/package.json package.json
|
|
||||||
RUN ../scripts/removeWorkspaceDependencies.sh package.json
|
|
||||||
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000
|
|
||||||
COPY packages/string-templates .
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY packages/server/package.json .
|
|
||||||
COPY packages/server/dist/yarn.lock .
|
|
||||||
RUN cd ../string-templates && yarn link && cd - && yarn link @budibase/string-templates
|
|
||||||
|
|
||||||
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
|
||||||
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
|
||||||
RUN ./scripts/removeWorkspaceDependencies.sh package.json
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000 \
|
|
||||||
# Remove unneeded data from file system to reduce image size
|
|
||||||
&& yarn cache clean && apt-get remove -y --purge --auto-remove g++ make python jq \
|
|
||||||
&& rm -rf /tmp/* /root/.node-gyp /usr/local/lib/node_modules/npm/node_modules/node-gyp
|
|
||||||
|
|
||||||
COPY packages/server/dist/ dist/
|
|
||||||
COPY packages/server/docker_run.sh .
|
|
||||||
COPY packages/server/builder/ builder/
|
|
||||||
COPY packages/server/client/ client/
|
|
||||||
|
|
||||||
ARG BUDIBASE_VERSION
|
|
||||||
# Ensuring the version argument is sent
|
|
||||||
RUN test -n "$BUDIBASE_VERSION"
|
|
||||||
ENV BUDIBASE_VERSION=$BUDIBASE_VERSION
|
|
||||||
|
|
||||||
EXPOSE 4001
|
|
||||||
|
|
||||||
# have to add node environment production after install
|
|
||||||
# due to this causing yarn to stop installing dev dependencies
|
|
||||||
# which are actually needed to get this environment up and running
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
ENV CLUSTER_MODE=${CLUSTER_MODE}
|
|
||||||
ENV TOP_LEVEL_PATH=/app
|
|
||||||
|
|
||||||
CMD ["./docker_run.sh"]
|
|
|
@ -17,7 +17,8 @@
|
||||||
"@budibase/backend-core": ["../backend-core/src"],
|
"@budibase/backend-core": ["../backend-core/src"],
|
||||||
"@budibase/backend-core/*": ["../backend-core/*"],
|
"@budibase/backend-core/*": ["../backend-core/*"],
|
||||||
"@budibase/shared-core": ["../shared-core/src"],
|
"@budibase/shared-core": ["../shared-core/src"],
|
||||||
"@budibase/pro": ["../pro/src"]
|
"@budibase/pro": ["../pro/src"],
|
||||||
|
"@budibase/string-templates": ["../string-templates/src"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
|
|
|
@ -5,22 +5,38 @@ LABEL com.centurylinklabs.watchtower.lifecycle.pre-update="scripts/watchtower-ho
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.post-update="scripts/watchtower-hooks/post-update.sh"
|
LABEL com.centurylinklabs.watchtower.lifecycle.post-update="scripts/watchtower-hooks/post-update.sh"
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.post-check="scripts/watchtower-hooks/post-check.sh"
|
LABEL com.centurylinklabs.watchtower.lifecycle.post-check="scripts/watchtower-hooks/post-check.sh"
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# handle node-gyp
|
# handle node-gyp
|
||||||
RUN apk add --no-cache --virtual .gyp python3 make g++
|
RUN apk add --no-cache --virtual .gyp python3 make g++ jq
|
||||||
RUN yarn global add pm2
|
RUN yarn global add pm2
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
COPY package.json .
|
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
||||||
COPY dist/yarn.lock .
|
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
||||||
RUN yarn install --production=true --network-timeout 1000000
|
|
||||||
|
|
||||||
|
WORKDIR /string-templates
|
||||||
|
COPY packages/string-templates/package.json package.json
|
||||||
|
RUN ../scripts/removeWorkspaceDependencies.sh package.json
|
||||||
|
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000
|
||||||
|
COPY packages/string-templates .
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY packages/worker/package.json .
|
||||||
|
COPY packages/worker/dist/yarn.lock .
|
||||||
|
RUN cd ../string-templates && yarn link && cd - && yarn link @budibase/string-templates
|
||||||
|
|
||||||
|
RUN ../scripts/removeWorkspaceDependencies.sh package.json
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000
|
||||||
# Remove unneeded data from file system to reduce image size
|
# Remove unneeded data from file system to reduce image size
|
||||||
RUN apk del .gyp \
|
RUN apk del .gyp \
|
||||||
&& yarn cache clean
|
&& yarn cache clean
|
||||||
|
|
||||||
COPY dist/ dist/
|
COPY packages/worker/dist/ dist/
|
||||||
COPY docker_run.sh .
|
COPY packages/worker/docker_run.sh .
|
||||||
|
|
||||||
EXPOSE 4001
|
EXPOSE 4001
|
||||||
|
|
||||||
|
@ -34,4 +50,9 @@ ENV POSTHOG_TOKEN=phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU
|
||||||
ENV TENANT_FEATURE_FLAGS=*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR
|
ENV TENANT_FEATURE_FLAGS=*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR
|
||||||
ENV ACCOUNT_PORTAL_URL=https://account.budibase.app
|
ENV ACCOUNT_PORTAL_URL=https://account.budibase.app
|
||||||
|
|
||||||
|
ARG BUDIBASE_VERSION
|
||||||
|
# Ensuring the version argument is sent
|
||||||
|
RUN test -n "$BUDIBASE_VERSION"
|
||||||
|
ENV BUDIBASE_VERSION=$BUDIBASE_VERSION
|
||||||
|
|
||||||
CMD ["./docker_run.sh"]
|
CMD ["./docker_run.sh"]
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.pre-check="scripts/watchtower-hooks/pre-check.sh"
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.pre-update="scripts/watchtower-hooks/pre-update.sh"
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.post-update="scripts/watchtower-hooks/post-update.sh"
|
|
||||||
LABEL com.centurylinklabs.watchtower.lifecycle.post-check="scripts/watchtower-hooks/post-check.sh"
|
|
||||||
|
|
||||||
|
|
||||||
# handle node-gyp
|
|
||||||
RUN apk add --no-cache --virtual .gyp python3 make g++ jq
|
|
||||||
RUN yarn global add pm2
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
COPY scripts/removeWorkspaceDependencies.sh scripts/removeWorkspaceDependencies.sh
|
|
||||||
RUN chmod +x ./scripts/removeWorkspaceDependencies.sh
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /string-templates
|
|
||||||
COPY packages/string-templates/package.json package.json
|
|
||||||
RUN ../scripts/removeWorkspaceDependencies.sh package.json
|
|
||||||
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000
|
|
||||||
COPY packages/string-templates .
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY packages/worker/package.json .
|
|
||||||
COPY packages/worker/dist/yarn.lock .
|
|
||||||
RUN cd ../string-templates && yarn link && cd - && yarn link @budibase/string-templates
|
|
||||||
|
|
||||||
RUN ../scripts/removeWorkspaceDependencies.sh package.json
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000
|
|
||||||
# Remove unneeded data from file system to reduce image size
|
|
||||||
RUN apk del .gyp \
|
|
||||||
&& yarn cache clean
|
|
||||||
|
|
||||||
COPY packages/worker/dist/ dist/
|
|
||||||
COPY packages/worker/docker_run.sh .
|
|
||||||
|
|
||||||
EXPOSE 4001
|
|
||||||
|
|
||||||
# have to add node environment production after install
|
|
||||||
# due to this causing yarn to stop installing dev dependencies
|
|
||||||
# which are actually needed to get this environment up and running
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
ENV CLUSTER_MODE=${CLUSTER_MODE}
|
|
||||||
ENV SERVICE=worker-service
|
|
||||||
ENV POSTHOG_TOKEN=phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU
|
|
||||||
ENV TENANT_FEATURE_FLAGS=*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR
|
|
||||||
ENV ACCOUNT_PORTAL_URL=https://account.budibase.app
|
|
||||||
|
|
||||||
ARG BUDIBASE_VERSION
|
|
||||||
# Ensuring the version argument is sent
|
|
||||||
RUN test -n "$BUDIBASE_VERSION"
|
|
||||||
ENV BUDIBASE_VERSION=$BUDIBASE_VERSION
|
|
||||||
|
|
||||||
CMD ["./docker_run.sh"]
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
yarn build --scope @budibase/server --scope @budibase/worker
|
yarn build --scope @budibase/server --scope @budibase/worker
|
||||||
version=$(./scripts/getCurrentVersion.sh)
|
version=$(./scripts/getCurrentVersion.sh)
|
||||||
docker build -f hosting/single/Dockerfile.v2 -t budibase:latest --build-arg BUDIBASE_VERSION=$version .
|
docker build -f hosting/single/Dockerfile -t budibase:latest --build-arg BUDIBASE_VERSION=$version .
|
||||||
|
|
Loading…
Reference in New Issue