Merge master.
This commit is contained in:
commit
5ae9a3e46b
|
@ -194,7 +194,7 @@ spec:
|
|||
{{ end }}
|
||||
|
||||
image: budibase/apps:{{ .Values.globals.appVersion | default .Chart.AppVersion }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
imagePullPolicy: Always
|
||||
{{- if .Values.services.apps.startupProbe }}
|
||||
{{- with .Values.services.apps.startupProbe }}
|
||||
startupProbe:
|
||||
|
|
|
@ -6,7 +6,7 @@ services:
|
|||
app-service:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: packages/server/Dockerfile.v2
|
||||
dockerfile: packages/server/Dockerfile
|
||||
args:
|
||||
- BUDIBASE_VERSION=0.0.0+dev-docker
|
||||
container_name: build-bbapps
|
||||
|
@ -36,7 +36,7 @@ services:
|
|||
worker-service:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: packages/worker/Dockerfile.v2
|
||||
dockerfile: packages/worker/Dockerfile
|
||||
args:
|
||||
- BUDIBASE_VERSION=0.0.0+dev-docker
|
||||
container_name: build-bbworker
|
||||
|
|
|
@ -1,44 +1,59 @@
|
|||
FROM node:18-slim as build
|
||||
|
||||
# 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
|
||||
ADD packages/server .
|
||||
COPY package.json .
|
||||
COPY yarn.lock .
|
||||
RUN yarn install --production=true --network-timeout 1000000
|
||||
RUN /cleanup.sh
|
||||
COPY lerna.json .
|
||||
COPY .yarnrc .
|
||||
|
||||
# build worker
|
||||
WORKDIR /worker
|
||||
ADD packages/worker .
|
||||
COPY yarn.lock .
|
||||
RUN yarn install --production=true --network-timeout 1000000
|
||||
RUN /cleanup.sh
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
COPY --from=build /app /app
|
||||
COPY --from=build /worker /worker
|
||||
|
||||
# install base dependencies
|
||||
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
|
||||
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 \
|
||||
&& 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 \
|
||||
|
@ -47,14 +62,12 @@ RUN apt install software-properties-common apt-transport-https gpg -y \
|
|||
|
||||
# install other dependencies, nodejs, oracle requirements, jdk8, redis, nginx
|
||||
WORKDIR /nodejs
|
||||
RUN curl -sL https://deb.nodesource.com/setup_16.x -o /tmp/nodesource_setup.sh && \
|
||||
bash /tmp/nodesource_setup.sh && \
|
||||
apt-get install -y --no-install-recommends libaio1 nodejs && \
|
||||
npm install --global yarn pm2
|
||||
COPY scripts/install-node.sh ./install.sh
|
||||
RUN chmod +x install.sh && ./install.sh
|
||||
|
||||
# setup nginx
|
||||
ADD 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.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 && \
|
||||
|
@ -62,19 +75,19 @@ RUN mkdir -p /var/log/nginx && \
|
|||
|
||||
WORKDIR /
|
||||
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
|
||||
|
||||
# setup minio
|
||||
WORKDIR /minio
|
||||
ADD scripts/install-minio.sh ./install.sh
|
||||
COPY scripts/install-minio.sh ./install.sh
|
||||
RUN chmod +x install.sh && ./install.sh
|
||||
|
||||
# setup runner file
|
||||
WORKDIR /
|
||||
ADD hosting/single/runner.sh .
|
||||
COPY hosting/single/runner.sh .
|
||||
RUN chmod +x ./runner.sh
|
||||
ADD hosting/single/healthcheck.sh .
|
||||
COPY hosting/single/healthcheck.sh .
|
||||
RUN chmod +x ./healthcheck.sh
|
||||
|
||||
# Script below sets the path for storing data based on $DATA_DIR
|
||||
|
@ -82,8 +95,19 @@ RUN chmod +x ./healthcheck.sh
|
|||
ADD hosting/single/ssh/sshd_config /etc/
|
||||
ADD hosting/single/ssh/ssh_setup.sh /tmp
|
||||
|
||||
# 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 443
|
||||
|
@ -91,20 +115,10 @@ EXPOSE 443
|
|||
EXPOSE 2222
|
||||
VOLUME /data
|
||||
|
||||
# setup letsencrypt certificate
|
||||
RUN apt-get install -y certbot python3-certbot-nginx
|
||||
ADD hosting/letsencrypt /app/letsencrypt
|
||||
RUN chmod +x /app/letsencrypt/certificate-request.sh /app/letsencrypt/certificate-renew.sh
|
||||
# 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/*
|
||||
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"
|
||||
|
||||
|
|
|
@ -1,130 +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
|
||||
|
||||
|
||||
# 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 ColumnEditor from "./controls/ColumnEditor/ColumnEditor.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 FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration.svelte"
|
||||
import ButtonConfiguration from "./controls/ButtonConfiguration/ButtonConfiguration.svelte"
|
||||
|
@ -28,6 +28,7 @@ import RelationshipFilterEditor from "./controls/RelationshipFilterEditor.svelte
|
|||
|
||||
const componentMap = {
|
||||
text: DrawerBindableInput,
|
||||
plainText: Input,
|
||||
select: Select,
|
||||
radio: RadioGroup,
|
||||
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,
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -781,7 +781,7 @@
|
|||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<Divider />
|
||||
<Divider noMargin />
|
||||
<div class="body">
|
||||
<Layout gap="L" noPadding>
|
||||
<div class="user-invite-form">
|
||||
|
@ -808,19 +808,21 @@
|
|||
: Constants.BudibaseRoleOptionsNew.filter(
|
||||
option => option.value !== Constants.BudibaseRoles.Admin
|
||||
)}
|
||||
label="Role"
|
||||
label="Access"
|
||||
/>
|
||||
{#if creationRoleType !== Constants.BudibaseRoles.Admin}
|
||||
<RoleSelect
|
||||
placeholder={false}
|
||||
bind:value={creationAccessType}
|
||||
allowPublic={false}
|
||||
allowCreator={true}
|
||||
quiet={true}
|
||||
autoWidth
|
||||
align="right"
|
||||
fancySelect
|
||||
/>
|
||||
<span class="role-wrap">
|
||||
<RoleSelect
|
||||
placeholder={false}
|
||||
bind:value={creationAccessType}
|
||||
allowPublic={false}
|
||||
allowCreator={true}
|
||||
quiet={true}
|
||||
autoWidth
|
||||
align="right"
|
||||
fancySelect
|
||||
/>
|
||||
</span>
|
||||
{/if}
|
||||
</FancyForm>
|
||||
{#if creationRoleType === Constants.BudibaseRoles.Admin}
|
||||
|
@ -847,6 +849,13 @@
|
|||
</div>
|
||||
|
||||
<style>
|
||||
.role-wrap :global(.fancy-field:not(:last-of-type)) {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.search :global(input) {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
minWidth: "200px",
|
||||
},
|
||||
role: {
|
||||
displayName: "Access",
|
||||
sortable: false,
|
||||
width: "1fr",
|
||||
},
|
||||
|
|
|
@ -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": {
|
||||
"name": "Text Field",
|
||||
"icon": "Text",
|
||||
|
@ -6308,19 +6324,6 @@
|
|||
"key": "table",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "columns/grid",
|
||||
"label": "Columns",
|
||||
"key": "columns",
|
||||
"dependsOn": [
|
||||
"table",
|
||||
{
|
||||
"setting": "table.type",
|
||||
"value": "custom",
|
||||
"invert": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "filter",
|
||||
"label": "Filtering",
|
||||
|
@ -6417,6 +6420,18 @@
|
|||
"key": "stripeRows",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"name": "Columns",
|
||||
"settings": [
|
||||
{
|
||||
"type": "columns/grid",
|
||||
"key": "columns",
|
||||
"nested": true,
|
||||
"resetOn": "table"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"name": "Buttons",
|
||||
|
|
|
@ -19,6 +19,22 @@
|
|||
export let onRowClick = 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 component = getContext("component")
|
||||
const {
|
||||
|
@ -33,16 +49,17 @@
|
|||
|
||||
let grid
|
||||
|
||||
$: columnWhitelist = columns?.map(col => col.name)
|
||||
$: schemaOverrides = getSchemaOverrides(columns)
|
||||
$: columnWhitelist = parsedColumns
|
||||
?.filter(col => col.active)
|
||||
?.map(col => col.field)
|
||||
$: schemaOverrides = getSchemaOverrides(parsedColumns)
|
||||
$: enrichedButtons = enrichButtons(buttons)
|
||||
|
||||
const getSchemaOverrides = columns => {
|
||||
let overrides = {}
|
||||
columns?.forEach(column => {
|
||||
overrides[column.name] = {
|
||||
displayName: column.displayName || column.name,
|
||||
visible: true,
|
||||
overrides[column.field] = {
|
||||
displayName: column.label,
|
||||
}
|
||||
})
|
||||
return overrides
|
||||
|
|
|
@ -55,11 +55,20 @@ export const deriveStores = context => {
|
|||
|
||||
// Apply whitelist if specified
|
||||
if ($columnWhitelist?.length) {
|
||||
Object.keys(enrichedSchema).forEach(key => {
|
||||
if (!$columnWhitelist.includes(key)) {
|
||||
delete enrichedSchema[key]
|
||||
const sortedColumns = {}
|
||||
|
||||
$columnWhitelist.forEach((columnKey, idx) => {
|
||||
const enrichedColumn = enrichedSchema[columnKey]
|
||||
if (enrichedColumn) {
|
||||
sortedColumns[columnKey] = {
|
||||
...enrichedColumn,
|
||||
order: idx,
|
||||
visible: true,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return sortedColumns
|
||||
}
|
||||
|
||||
return enrichedSchema
|
||||
|
|
|
@ -18,12 +18,12 @@ ENV TOP_LEVEL_PATH=/
|
|||
|
||||
# handle node-gyp
|
||||
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
|
||||
|
||||
# Install client for oracle datasource
|
||||
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
|
||||
|
||||
# Install postgres client for pg_dump utils
|
||||
|
@ -35,18 +35,42 @@ RUN apt update && apt upgrade -y \
|
|||
&& apt install postgresql-client-15 -y \
|
||||
&& apt remove software-properties-common apt-transport-https curl gpg -y
|
||||
|
||||
WORKDIR /
|
||||
|
||||
COPY package.json .
|
||||
COPY dist/yarn.lock .
|
||||
RUN yarn install --production=true --network-timeout 1000000 \
|
||||
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 \
|
||||
&& 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 dist/ dist/
|
||||
COPY docker_run.sh .
|
||||
COPY builder/ builder/
|
||||
COPY client/ client/
|
||||
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
|
||||
|
||||
|
|
|
@ -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/*"],
|
||||
"@budibase/shared-core": ["../shared-core/src"],
|
||||
"@budibase/pro": ["../pro/src"]
|
||||
"@budibase/pro": ["../pro/src"],
|
||||
"@budibase/string-templates": ["../string-templates/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-check="scripts/watchtower-hooks/post-check.sh"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 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
|
||||
|
||||
WORKDIR /
|
||||
|
||||
COPY package.json .
|
||||
COPY dist/yarn.lock .
|
||||
RUN yarn install --production=true --network-timeout 1000000
|
||||
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 dist/ dist/
|
||||
COPY docker_run.sh .
|
||||
COPY packages/worker/dist/ dist/
|
||||
COPY packages/worker/docker_run.sh .
|
||||
|
||||
EXPOSE 4001
|
||||
|
||||
|
@ -34,4 +50,9 @@ 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,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
|
||||
yarn build --scope @budibase/server --scope @budibase/worker
|
||||
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