diff --git a/.github/workflows/deploy-cloud.yaml b/.github/workflows/deploy-cloud.yaml index 869a88a5b3..644eb5f1be 100644 --- a/.github/workflows/deploy-cloud.yaml +++ b/.github/workflows/deploy-cloud.yaml @@ -38,17 +38,6 @@ jobs: fi echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV - - name: Tag and release Proxy service docker image - run: | - docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - yarn build:docker:proxy:prod - docker tag proxy-service budibase/proxy:$PROD_TAG - docker push budibase/proxy:$PROD_TAG - env: - DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - PROD_TAG: k8s - - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: diff --git a/.github/workflows/deploy-preprod.yml b/.github/workflows/deploy-preprod.yml index c3f690f568..cef47636ee 100644 --- a/.github/workflows/deploy-preprod.yml +++ b/.github/workflows/deploy-preprod.yml @@ -28,17 +28,6 @@ jobs: release_version=$(cat lerna.json | jq -r '.version') echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV - - name: Tag and release Proxy service docker image - run: | - docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - yarn build:docker:proxy:preprod - docker tag proxy-service budibase/proxy:$PREPROD_TAG - docker push budibase/proxy:$PREPROD_TAG - env: - DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - PREPROD_TAG: k8s-preprod - - name: Pull values.yaml from budibase-infra run: | curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \ diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml index b37ff9cee8..cff26fd7c8 100644 --- a/.github/workflows/deploy-release.yml +++ b/.github/workflows/deploy-release.yml @@ -29,17 +29,6 @@ jobs: release_version=$(cat lerna.json | jq -r '.version') echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV - - name: Tag and release Proxy service docker image - run: | - docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - yarn build:docker:proxy:release - docker tag proxy-service budibase/proxy:$RELEASE_TAG - docker push budibase/proxy:$RELEASE_TAG - env: - DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - RELEASE_TAG: k8s-release - - name: Pull values.yaml from budibase-infra run: | curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \ diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml index 21c74851e1..7ec18c0974 100644 --- a/.github/workflows/release-develop.yml +++ b/.github/workflows/release-develop.yml @@ -76,22 +76,25 @@ jobs: DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - - name: Get the latest budibase release version + deploy-to-release-env: + needs: [release-images] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Get the current budibase release version id: version - run: | + run: | release_version=$(cat lerna.json | jq -r '.version') echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV - - name: Tag and release Proxy service docker image - run: | - docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - yarn build:docker:proxy:release - docker tag proxy-service budibase/proxy:$RELEASE_TAG - docker push budibase/proxy:$RELEASE_TAG - env: - DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - RELEASE_TAG: k8s-release + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: eu-west-1 - name: Pull values.yaml from budibase-infra run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index de288dd7db..2a28150891 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,17 +98,6 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: eu-west-1 - - name: Tag and release Proxy service docker image - run: | - docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - yarn build:docker:proxy:preprod - docker tag proxy-service budibase/proxy:$PREPROD_TAG - docker push budibase/proxy:$PREPROD_TAG - env: - DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - PREPROD_TAG: k8s-preprod - - name: Pull values.yaml from budibase-infra run: | curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \ diff --git a/.gitignore b/.gitignore index 915e2ea160..6eb9eed952 100644 --- a/.gitignore +++ b/.gitignore @@ -66,8 +66,6 @@ typings/ .env !qa-core/.env !hosting/.env -hosting/.generated-nginx.dev.conf -hosting/proxy/.generated-nginx.prod.conf # parcel-bundler cache (https://parceljs.org/) .cache @@ -105,5 +103,7 @@ stats.html # TypeScript cache *.tsbuildinfo + +# plugins budibase-component budibase-datasource diff --git a/charts/budibase/templates/proxy-service-deployment.yaml b/charts/budibase/templates/proxy-service-deployment.yaml index 3cde7a2388..00c12271db 100644 --- a/charts/budibase/templates/proxy-service-deployment.yaml +++ b/charts/budibase/templates/proxy-service-deployment.yaml @@ -28,11 +28,26 @@ spec: app.kubernetes.io/name: budibase-proxy spec: containers: - - image: budibase/proxy:{{ .Values.services.proxy.tag | default "k8s" }} + - image: budibase/proxy:{{ .Values.globals.appVersion }} imagePullPolicy: Always name: proxy-service ports: - containerPort: {{ .Values.services.proxy.port }} + env: + - name: APPS_UPSTREAM_URL + value: {{ tpl .Values.services.proxy.upstreams.apps . | quote }} + - name: WORKER_UPSTREAM_URL + value: {{ tpl .Values.services.proxy.upstreams.worker . | quote }} + - name: MINIO_UPSTREAM_URL + value: {{ tpl .Values.services.proxy.upstreams.minio . | quote }} + - name: COUCHDB_UPSTREAM_URL + value: {{ .Values.services.couchdb.url | default (tpl .Values.services.proxy.upstreams.couchdb .) | quote }} + - name: RESOLVER + {{ if .Values.services.proxy.resolver }} + value: {{ .Values.services.proxy.resolver }} + {{ else }} + value: kube-dns.kube-system.svc.{{ .Values.services.dns }} + {{ end }} {{ with .Values.services.proxy.resources }} resources: {{- toYaml . | nindent 10 }} diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 726df7585b..5c20fc220a 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -124,6 +124,11 @@ services: proxy: port: 10000 replicaCount: 1 + upstreams: + apps: 'http://app-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.apps.port }}' + worker: 'http://worker-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.worker.port }}' + minio: 'http://minio-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.objectStore.port }}' + couchdb: 'http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}' resources: {} apps: diff --git a/hosting/docker-compose.dev.yaml b/hosting/docker-compose.dev.yaml index 7322b0e8a9..1626d520b6 100644 --- a/hosting/docker-compose.dev.yaml +++ b/hosting/docker-compose.dev.yaml @@ -25,9 +25,9 @@ services: proxy-service: container_name: budi-nginx-dev restart: on-failure - image: nginx:latest + image: budibase/proxy:latest volumes: - - ./.generated-nginx.dev.conf:/etc/nginx/nginx.conf + - ./nginx.dev.conf:/etc/nginx/templates/nginx.conf.template - ./proxy/error.html:/usr/share/nginx/html/error.html ports: - "${MAIN_PORT}:10000" @@ -36,6 +36,8 @@ services: - couchdb-service extra_hosts: - "host.docker.internal:host-gateway" + environment: + - PROXY_ADDRESS=host.docker.internal couchdb-service: # platform: linux/amd64 diff --git a/hosting/docker-compose.yaml b/hosting/docker-compose.yaml index 5b2adc2665..d36937910f 100644 --- a/hosting/docker-compose.yaml +++ b/hosting/docker-compose.yaml @@ -82,6 +82,12 @@ services: environment: - PROXY_RATE_LIMIT_WEBHOOKS_PER_SECOND=10 - PROXY_RATE_LIMIT_API_PER_SECOND=20 + - APPS_UPSTREAM_URL=http://app-service:4002 + - WORKER_UPSTREAM_URL=http://worker-service:4003 + - MINIO_UPSTREAM_URL=http://minio-service:9000 + - COUCHDB_UPSTREAM_URL=http://couchdb-service:5984 + - WATCHTOWER_UPSTREAM_URL=http://watchtower-service:8080 + - RESOLVER=127.0.0.11 depends_on: - minio-service - worker-service diff --git a/hosting/nginx.dev.conf.hbs b/hosting/nginx.dev.conf similarity index 97% rename from hosting/nginx.dev.conf.hbs rename to hosting/nginx.dev.conf index 93a07435e5..bfe30ba369 100644 --- a/hosting/nginx.dev.conf.hbs +++ b/hosting/nginx.dev.conf @@ -25,17 +25,17 @@ http { } upstream app-service { - server {{address}}:4001; + server ${PROXY_ADDRESS}:4001; keepalive 32; } upstream worker-service { - server {{address}}:4002; + server ${PROXY_ADDRESS}:4002; keepalive 32; } upstream builder { - server {{address}}:3000; + server ${PROXY_ADDRESS}:3000; keepalive 32; } diff --git a/hosting/proxy/Dockerfile b/hosting/proxy/Dockerfile index 68e8134750..42327be087 100644 --- a/hosting/proxy/Dockerfile +++ b/hosting/proxy/Dockerfile @@ -4,7 +4,7 @@ FROM nginx:latest # use the default nginx behaviour for *.template files which are processed with envsubst # override the output dir to output directly to /etc/nginx instead of /etc/nginx/conf.d ENV NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx -COPY .generated-nginx.prod.conf /etc/nginx/templates/nginx.conf.template +COPY nginx.prod.conf /etc/nginx/templates/nginx.conf.template # IPv6 removal needs to happen after envsubst RUN rm -rf /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh @@ -16,4 +16,11 @@ COPY error.html /usr/share/nginx/html/error.html # Default environment ENV PROXY_RATE_LIMIT_WEBHOOKS_PER_SECOND=10 -ENV PROXY_RATE_LIMIT_API_PER_SECOND=20 \ No newline at end of file +ENV PROXY_RATE_LIMIT_API_PER_SECOND=20 +# Use docker-compose values as defaults for backwards compatibility +ENV APPS_UPSTREAM_URL=http://app-service:4002 +ENV WORKER_UPSTREAM_URL=http://worker-service:4003 +ENV MINIO_UPSTREAM_URL=http://minio-service:9000 +ENV COUCHDB_UPSTREAM_URL=http://couchdb-service:5984 +ENV WATCHTOWER_UPSTREAM_URL=http://watchtower-service:8080 +ENV RESOLVER=127.0.0.11 diff --git a/hosting/nginx.prod.conf.hbs b/hosting/proxy/nginx.prod.conf similarity index 91% rename from hosting/nginx.prod.conf.hbs rename to hosting/proxy/nginx.prod.conf index 6f0f1b420d..a39b8dc803 100644 --- a/hosting/nginx.prod.conf.hbs +++ b/hosting/proxy/nginx.prod.conf @@ -23,7 +23,7 @@ http { tcp_nodelay on; server_tokens off; types_hash_max_size 2048; - resolver {{ resolver }} valid=10s ipv6=off; + resolver ${RESOLVER} valid=10s ipv6=off; # buffering client_header_buffer_size 1k; @@ -76,27 +76,23 @@ http { add_header Content-Security-Policy "${csp_default}; ${csp_script}; ${csp_style}; ${csp_object}; ${csp_base_uri}; ${csp_connect}; ${csp_font}; ${csp_frame}; ${csp_img}; ${csp_manifest}; ${csp_media}; ${csp_worker};" always; # upstreams - set $apps {{ apps }}; - set $worker {{ worker }}; - set $minio {{ minio }}; - set $couchdb {{ couchdb }}; - {{#if watchtower}} - set $watchtower {{ watchtower }}; - {{/if}} + set $apps ${APPS_UPSTREAM_URL}; + set $worker ${WORKER_UPSTREAM_URL}; + set $minio ${MINIO_UPSTREAM_URL}; + set $couchdb ${COUCHDB_UPSTREAM_URL}; + set $watchtower ${WATCHTOWER_UPSTREAM_URL}; location /app { - proxy_pass http://$apps:4002; + proxy_pass $apps; } location = / { - proxy_pass http://$apps:4002; + proxy_pass $apps; } - {{#if watchtower}} location = /v1/update { - proxy_pass http://$watchtower:8080; + proxy_pass $watchtower; } - {{/if}} location ~ ^/(builder|app_) { proxy_http_version 1.1; @@ -107,19 +103,17 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://$apps:4002; + proxy_pass $apps; } location ~ ^/api/(system|admin|global)/ { proxy_set_header Host $host; - - proxy_pass http://$worker:4003; + proxy_pass $worker; } location /worker/ { proxy_set_header Host $host; - - proxy_pass http://$worker:4003; + proxy_pass $worker; rewrite ^/worker/(.*)$ /$1 break; } @@ -138,7 +132,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://$apps:4002; + proxy_pass $apps; } location /api/ { @@ -157,7 +151,7 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://$apps:4002; + proxy_pass $apps; } location /api/webhooks/ { @@ -177,11 +171,11 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://$apps:4002; + proxy_pass $apps; } location /db/ { - proxy_pass http://$couchdb:5984; + proxy_pass $couchdb; rewrite ^/db/(.*)$ /$1 break; } @@ -191,7 +185,7 @@ http { proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; - proxy_pass http://$apps:4002; + proxy_pass $apps; } location / { @@ -205,7 +199,7 @@ http { proxy_set_header Connection ""; chunked_transfer_encoding off; - proxy_pass http://$minio:9000; + proxy_pass $minio; } client_header_timeout 60; diff --git a/lerna.json b/lerna.json index 4caa4afe17..0cff848e18 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.2.12", + "version": "2.2.22", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index 6c147698ad..6134ae2880 100644 --- a/package.json +++ b/package.json @@ -55,15 +55,11 @@ "test:e2e:ci:record": "lerna run cy:ci:record --stream", "test:e2e:ci:notify": "lerna run cy:ci:notify", "build:specs": "lerna run specs", - "build:docker": "lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -", + "build:docker": "lerna run build:docker && npm run build:docker:proxy && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -", "build:docker:pre": "lerna run build && lerna run predocker", "build:docker:proxy": "docker build hosting/proxy -t proxy-service", - "build:docker:proxy:compose": "node scripts/proxy/generateProxyConfig compose && npm run build:docker:proxy", - "build:docker:proxy:preprod": "node scripts/proxy/generateProxyConfig preprod && npm run build:docker:proxy", - "build:docker:proxy:release": "node scripts/proxy/generateProxyConfig release && npm run build:docker:proxy", - "build:docker:proxy:prod": "node scripts/proxy/generateProxyConfig prod && npm run build:docker:proxy", "build:docker:selfhost": "lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh latest && cd -", - "build:docker:develop": "node scripts/pinVersions && lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -", + "build:docker:develop": "node scripts/pinVersions && lerna run build:docker && npm run build:docker:proxy && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -", "build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild", "build:digitalocean": "cd hosting/digitalocean && ./build.sh && cd -", "build:docker:single:multiarch": "docker buildx build --platform linux/arm64,linux/amd64 -f hosting/single/Dockerfile -t budibase:latest .", @@ -87,4 +83,4 @@ "install:pro": "bash scripts/pro/install.sh", "dep:clean": "yarn clean && yarn bootstrap" } -} +} \ No newline at end of file diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index f4c468c047..7d56478c84 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.2.12", + "version": "2.2.22", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -21,7 +21,7 @@ }, "dependencies": { "@budibase/nano": "10.1.1", - "@budibase/types": "^2.2.12", + "@budibase/types": "^2.2.22", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-sdk": "2.1030.0", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index ee51cfd977..d314995fb1 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "2.2.12", + "version": "2.2.22", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "1.2.1", - "@budibase/string-templates": "^2.2.12", + "@budibase/string-templates": "^2.2.22", "@spectrum-css/actionbutton": "1.0.1", "@spectrum-css/actiongroup": "1.0.1", "@spectrum-css/avatar": "3.0.2", diff --git a/packages/bbui/src/Form/Core/DatePicker.svelte b/packages/bbui/src/Form/Core/DatePicker.svelte index 6996525a76..30f6d84f5a 100644 --- a/packages/bbui/src/Form/Core/DatePicker.svelte +++ b/packages/bbui/src/Form/Core/DatePicker.svelte @@ -76,13 +76,6 @@ } // If time only set date component to 2000-01-01 if (timeOnly) { - // Classic flackpickr causing issues. - // When selecting a value for the first time for a "time only" field, - // the time is always offset by 1 hour for some reason (regardless of time - // zone) so we need to correct it. - if (!value && newValue) { - newValue = new Date(dates[0].getTime() + 60 * 60 * 1000).toISOString() - } newValue = `2000-01-01T${newValue.split("T")[1]}` } @@ -113,7 +106,7 @@ const clearDateOnBackspace = event => { if (["Backspace", "Clear", "Delete"].includes(event.key)) { - dispatch("change", null) + dispatch("change", "") flatpickr.close() } } diff --git a/packages/builder/package.json b/packages/builder/package.json index 1f67de0032..69dc4c3a99 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.2.12", + "version": "2.2.22", "license": "GPL-3.0", "private": true, "scripts": { @@ -71,10 +71,10 @@ } }, "dependencies": { - "@budibase/bbui": "^2.2.12", - "@budibase/client": "^2.2.12", - "@budibase/frontend-core": "^2.2.12", - "@budibase/string-templates": "^2.2.12", + "@budibase/bbui": "^2.2.22", + "@budibase/client": "^2.2.22", + "@budibase/frontend-core": "^2.2.22", + "@budibase/string-templates": "^2.2.22", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionDrawer.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionDrawer.svelte index 1d18fa3a92..b2daf0a2d7 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/ButtonActionDrawer.svelte @@ -74,8 +74,18 @@ } const deleteAction = index => { + // Check if we're deleting the selected action + const selectedIndex = actions.indexOf(selectedAction) + const isSelected = index === selectedIndex + + // Delete the action actions.splice(index, 1) actions = actions + + // Select a new action if we deleted the selected one + if (isSelected) { + selectedAction = actions?.length ? actions[0] : null + } } const toggleActionList = () => { diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte index c301bfdc20..096e47430c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsPanel.svelte @@ -30,7 +30,7 @@ {#if $selectedComponent} {#key $selectedComponent._id} - {#if componentDefinition.info} + {#if componentDefinition?.info} {/if} {#if showSkeleton} diff --git a/packages/client/src/components/app/DataProvider.svelte b/packages/client/src/components/app/DataProvider.svelte index c28cdef24c..1b4504e689 100644 --- a/packages/client/src/components/app/DataProvider.svelte +++ b/packages/client/src/components/app/DataProvider.svelte @@ -11,20 +11,23 @@ export let limit export let paginate - const loading = writable(false) - const { styleable, Provider, ActionTypes, API } = getContext("sdk") const component = getContext("component") + // Update loading state + const parentLoading = getContext("loading") + const loading = writable(true) + setContext("loading", loading) + // We need to manage our lucene query manually as we want to allow components // to extend it let queryExtensions = {} $: defaultQuery = LuceneUtils.buildLuceneQuery(filter) $: query = extendQuery(defaultQuery, queryExtensions) - // Keep our data fetch instance up to date - $: fetch = createFetch(dataSource) - $: fetch.update({ + // Fetch data and refresh when needed + $: fetch = createFetch(dataSource, $parentLoading) + $: updateFetch({ query, sortColumn, sortOrder, @@ -32,6 +35,9 @@ paginate, }) + // Keep loading context updated + $: loading.set($parentLoading || !$fetch.loaded) + // Build our action context $: actions = [ { @@ -80,14 +86,21 @@ sortColumn: $fetch.sortColumn, sortOrder: $fetch.sortOrder, }, - limit: limit, + limit, } - const parentLoading = getContext("loading") - setContext("loading", loading) - $: loading.set($parentLoading || !$fetch.loaded) + const createFetch = (datasource, parentLoading) => { + // Return a dummy fetch if parent is still loading. We do this so that we + // can still properly subscribe to a valid fetch object and check all + // properties, but we want to avoid fetching the real data until all parents + // have finished loading. + // This logic is only needed due to skeleton loaders, as previously we + // simply blocked component rendering until data was ready. + if (parentLoading) { + return fetchData({ API }) + } - const createFetch = datasource => { + // Otherwise return the real thing return fetchData({ API, datasource, @@ -101,6 +114,14 @@ }) } + const updateFetch = opts => { + // Only update fetch if parents have stopped loading. Otherwise we will + // trigger a fetch of the real data before parents are ready. + if (!$parentLoading) { + fetch.update(opts) + } + } + const addQueryExtension = (key, extension) => { if (!key || !extension) { return diff --git a/packages/client/src/components/app/forms/Form.svelte b/packages/client/src/components/app/forms/Form.svelte index 977b940d1f..f155474d9f 100644 --- a/packages/client/src/components/app/forms/Form.svelte +++ b/packages/client/src/components/app/forms/Form.svelte @@ -1,7 +1,8 @@