diff --git a/.dockerignore b/.dockerignore index 90105c8112..03c57ce6ee 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ +**/.output **/.nuxt **/.nuxt-storybook **/.storybook diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58a680a657..ce4999b986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1360,27 +1360,17 @@ jobs: git clone -b develop https://oauth2:${GITLAB_SAAS_PAT}@gitlab.com/baserow/baserow-saas.git saas cd saas - - name: Update image version files + - name: Update baserow submodule to current commit working-directory: saas run: | - echo "🧩 Generating updated image references..." - - BACKEND_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}/backend:ci-tested-${{ env.REAL_GITHUB_SHA }}" - BACKEND_DEV_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}/backend_dev:ci-${{ env.REAL_GITHUB_SHA }}" - WEB_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}/web-frontend:ci-tested-${{ env.REAL_GITHUB_SHA }}" - WEB_DEV_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}/web-frontend_dev:ci-${{ env.REAL_GITHUB_SHA }}" - ALL_IN_ONE_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}/baserow:ci-tested-${{ env.REAL_GITHUB_SHA }}" - - echo "$BACKEND_IMAGE" > plugins/saas/backend/build_from_image.version - echo "$BACKEND_DEV_IMAGE" > plugins/saas/backend/build_from_dev_image.version - echo "$WEB_IMAGE" > plugins/saas/web-frontend/build_from_image.version - echo "$WEB_DEV_IMAGE" > plugins/saas/web-frontend/build_from_dev_image.version - echo "$ALL_IN_ONE_IMAGE" > all_in_one_image.version - - echo "βœ… Updated image references:" - cat plugins/saas/backend/build_from_image.version - cat plugins/saas/web-frontend/build_from_image.version - cat all_in_one_image.version + echo "πŸ”„ Updating baserow submodule to ${{ github.sha }}..." + git submodule update --init + cd baserow + git fetch origin + git checkout ${{ github.sha }} + cd .. + git add baserow + echo "βœ… Submodule updated." - name: Commit and push changes to GitLab working-directory: saas @@ -1390,24 +1380,12 @@ jobs: git config user.name "${GIT_USER_NAME}" git config user.email "${GIT_USER_EMAIL}" - git add \ - plugins/saas/backend/build_from_image.version \ - plugins/saas/backend/build_from_dev_image.version \ - plugins/saas/web-frontend/build_from_image.version \ - plugins/saas/web-frontend/build_from_dev_image.version \ - all_in_one_image.version - if git diff-index --quiet HEAD --; then echo "No changes detected β€” skipping commit." exit 0 fi - COMMIT_MSG="Automatic core image bump: - - backend: ${BACKEND_IMAGE} - - web-frontend: ${WEB_IMAGE} - - all-in-one: ${ALL_IN_ONE_IMAGE}" - - git commit -m "$COMMIT_MSG" + git commit -m "Automatic baserow submodule bump to ${{ github.sha }}" git push origin develop echo "βœ… Successfully pushed updates to baserow-saas." diff --git a/backend/Dockerfile b/backend/Dockerfile index ead34b1c90..0dba2ca5dc 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -244,6 +244,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ procps \ tmux \ vim \ + lsof \ sudo ENV DOCKER_USER=baserow_docker_user \ @@ -303,9 +304,7 @@ RUN echo "set -g default-command \"\${SHELL}\"" > /baserow/.tmux.conf && \ 'echo " j - See available commands"' \ > /baserow/.bashrc -COPY --chown=$UID:$GID LICENSE /baserow/LICENSE COPY --chown=$UID:$GID backend/docker/docker-entrypoint.sh /baserow/backend/docker/docker-entrypoint.sh - RUN dos2unix /baserow/backend/docker/docker-entrypoint.sh \ && chmod a+x /baserow/backend/docker/docker-entrypoint.sh diff --git a/backend/src/baserow/api/user/serializers.py b/backend/src/baserow/api/user/serializers.py index d433179d57..70f562a669 100755 --- a/backend/src/baserow/api/user/serializers.py +++ b/backend/src/baserow/api/user/serializers.py @@ -471,3 +471,7 @@ class ShareOnboardingDetailsWithBaserowSerializer(serializers.Serializer): help_text="The country that the user has chosen during the onboarding.", required=True, ) + how = serializers.CharField( + help_text="How the user found Baserow.", + required=True, + ) diff --git a/backend/src/baserow/api/user/views.py b/backend/src/baserow/api/user/views.py index a7c349c11b..e4f6a48a53 100755 --- a/backend/src/baserow/api/user/views.py +++ b/backend/src/baserow/api/user/views.py @@ -863,7 +863,12 @@ class ShareOnboardingDetailsWithBaserowView(APIView): @validate_body(ShareOnboardingDetailsWithBaserowSerializer) def post(self, request, data): UserHandler().start_share_onboarding_details_with_baserow( - request.user, data["team"], data["role"], data["size"], data["country"] + request.user, + data["team"], + data["role"], + data["size"], + data["country"], + data["how"], ) return Response(status=204) diff --git a/backend/src/baserow/core/user/handler.py b/backend/src/baserow/core/user/handler.py index 49ed4b22c4..64e450f18f 100755 --- a/backend/src/baserow/core/user/handler.py +++ b/backend/src/baserow/core/user/handler.py @@ -945,7 +945,13 @@ def send_email(): )(send_email)() def start_share_onboarding_details_with_baserow( - self, user, team: str, role: str, size: str, country: str + self, + user, + team: str, + role: str, + size: str, + country: str, + how: str, ): """ Starts a celery task that shares some user information with baserow.io. Note @@ -962,10 +968,17 @@ def start_share_onboarding_details_with_baserow( email = user.email share_onboarding_details_with_baserow.delay( - email=email, team=team, role=role, size=size, country=country + email=email, + team=team, + role=role, + size=size, + country=country, + how=how, ) - def share_onboarding_details_with_baserow(self, email, team, role, size, country): + def share_onboarding_details_with_baserow( + self, email, team, role, size, country, how + ): """ Makes an API request to baserow.io that shares the additional information. Note that this is only triggered if the user given permission during the onboarding @@ -975,6 +988,7 @@ def share_onboarding_details_with_baserow(self, email, team, role, size, country :param role: The role that the user shared. :param size: The company size that the user shared. :param country: The country name that the user shared. + :param how: How the user found Baserow. """ settings_object = CoreHandler().get_settings() @@ -990,6 +1004,7 @@ def share_onboarding_details_with_baserow(self, email, team, role, size, country "size": size, "country": country, "email": email, + "how": how, "instance_id": settings_object.instance_id, }, timeout=settings.ADDITIONAL_INFORMATION_TIMEOUT_SECONDS, diff --git a/backend/tests/baserow/api/users/test_user_views.py b/backend/tests/baserow/api/users/test_user_views.py index 9690983107..0e8ab2b532 100755 --- a/backend/tests/baserow/api/users/test_user_views.py +++ b/backend/tests/baserow/api/users/test_user_views.py @@ -1247,6 +1247,7 @@ def test_share_onboarding_details_with_baserow(mock_task, client, data_fixture): "role": "CEO", "size": "11 - 50", "country": "The Netherlands", + "how": "Google", }, format="json", HTTP_AUTHORIZATION=f"JWT {token}", @@ -1260,6 +1261,7 @@ def test_share_onboarding_details_with_baserow(mock_task, client, data_fixture): role="CEO", size="11 - 50", country="The Netherlands", + how="Google", ) diff --git a/backend/tests/baserow/core/user/test_user_handler.py b/backend/tests/baserow/core/user/test_user_handler.py index dd31343abc..acf623830a 100755 --- a/backend/tests/baserow/core/user/test_user_handler.py +++ b/backend/tests/baserow/core/user/test_user_handler.py @@ -792,7 +792,7 @@ def test_start_share_onboarding_details_with_baserow(mock_task, data_fixture): user = data_fixture.create_user() UserHandler().start_share_onboarding_details_with_baserow( - user, "Marketing", "CEO", "11 - 50", "The Netherlands" + user, "Marketing", "CEO", "11 - 50", "The Netherlands", "Google" ) mock_task.delay.assert_called_with( @@ -801,6 +801,7 @@ def test_start_share_onboarding_details_with_baserow(mock_task, data_fixture): role="CEO", size="11 - 50", country="The Netherlands", + how="Google", ) @@ -822,6 +823,7 @@ def test_share_onboarding_details_with_baserow_valid_response(data_fixture): "role": "CEO", "size": "11 - 50", "country": "The Netherlands", + "how": "Google", "instance_id": "1", } ) @@ -834,6 +836,7 @@ def test_share_onboarding_details_with_baserow_valid_response(data_fixture): role="CEO", size="11 - 50", country="The Netherlands", + how="Google", ) assert response1.call_count == 1 diff --git a/changelog/entries/unreleased/feature/add_kuma_to_onboarding_and_reorganize.json b/changelog/entries/unreleased/feature/add_kuma_to_onboarding_and_reorganize.json new file mode 100644 index 0000000000..60da51829a --- /dev/null +++ b/changelog/entries/unreleased/feature/add_kuma_to_onboarding_and_reorganize.json @@ -0,0 +1,9 @@ +{ + "type": "feature", + "message": "Add Kuma to onboarding and reorganize the steps.", + "issue_origin": "github", + "issue_number": null, + "domain": "core", + "bullet_points": [], + "created_at": "2026-01-30" +} diff --git a/deploy/all-in-one/supervisor/supervisor.conf b/deploy/all-in-one/supervisor/supervisor.conf index 0856cd2fc3..66645ab350 100644 --- a/deploy/all-in-one/supervisor/supervisor.conf +++ b/deploy/all-in-one/supervisor/supervisor.conf @@ -24,7 +24,7 @@ startsecs=30 [program:webfrontend] user=%(ENV_DOCKER_USER)s directory=/baserow/web-frontend -command=/baserow/supervisor/wrapper.sh YELLOW WEBFRONTEND ./docker/docker-entrypoint.sh %(ENV_BASEROW_WEB_FRONTEND_STARTUP_COMMAND)s +command=/baserow/supervisor/wrapper.sh YELLOW WEBFRONTEND node --import ./env-remap.mjs .output/server/index.mjs stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stdout diff --git a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/all.scss b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/all.scss index bd1a00b0f7..36ff700ccf 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/all.scss +++ b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/all.scss @@ -22,4 +22,5 @@ @import 'file_input_element_form'; @import 'custom_code'; @import 'assistant'; +@import 'assistant_onboarding'; @import 'date_dependency'; diff --git a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/assistant_onboarding.scss b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/assistant_onboarding.scss new file mode 100644 index 0000000000..8373ea8c61 --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/assistant_onboarding.scss @@ -0,0 +1,55 @@ +.assistant-onboarding { + margin-top: 20px; + width: 360px; + height: 210px; + display: flex; + flex-direction: column; + align-items: center; +} + +.assistant-onboarding__logo { + margin-bottom: 10px; +} + +.assistant-onboarding__title { + font-size: 20px; + font-weight: 500; + color: $palette-neutral-1200; + margin-bottom: 32px; + display: flex; + align-items: center; +} + +.assistant-onboarding__title-icon { + color: $palette-cyan-700; + margin-right: 6px; +} + +.assistant-onboarding__message { + display: flex; + background-color: $palette-cyan-50; + border: 1px solid $palette-cyan-200; + border-radius: 12px; + padding: 12px 16px; + overflow-wrap: break-word; + width: 100%; +} + +.assistant-onboarding__loading-wrapper { + flex: 0 0 28px; + width: 28px; +} + +.assistant-onboarding__loading { + @include loading(1.4rem, $palette-cyan-500); +} + +.assistant-onboarding__text { + display: -webkit-box; + max-width: 100%; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + overflow: hidden; + line-height: 20px; + color: $palette-cyan-700; +} diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantOnboardingMessage.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantOnboardingMessage.vue new file mode 100644 index 0000000000..9745b74fee --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantOnboardingMessage.vue @@ -0,0 +1,50 @@ + + + diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantSidebarItem.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantSidebarItem.vue index 60bb6941a2..81b618cacd 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantSidebarItem.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/assistant/AssistantSidebarItem.vue @@ -41,7 +41,7 @@ export default { ) }, isConfigured() { - return this.$config.public.baserowEnterpriseAssistantLLMModel !== null + return !!this.$config.public.baserowEnterpriseAssistantLLMModel }, }, mounted() { diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/onboarding/AIDatabaseOnboardingForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/onboarding/AIDatabaseOnboardingForm.vue new file mode 100644 index 0000000000..3dd2411f30 --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/onboarding/AIDatabaseOnboardingForm.vue @@ -0,0 +1,105 @@ + + + diff --git a/enterprise/web-frontend/modules/baserow_enterprise/databaseOnboardingStepTypes.js b/enterprise/web-frontend/modules/baserow_enterprise/databaseOnboardingStepTypes.js new file mode 100644 index 0000000000..16ab178320 --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/databaseOnboardingStepTypes.js @@ -0,0 +1,90 @@ +import { DatabaseOnboardingStepType } from '@baserow/modules/database/databaseOnboardingStepTypes' +import AIDatabaseOnboardingForm from '@baserow_enterprise/components/onboarding/AIDatabaseOnboardingForm' +import { nextTick } from 'vue' +import { pageFinished } from '@baserow/modules/core/utils/routing.js' +import { DatabaseOnboardingType } from '@baserow/modules/database/onboardingTypes.js' +import { waitFor } from '@baserow/modules/core/utils/queue.js' +import AssistantOnboardingMessage from '@baserow_enterprise/components/assistant/AssistantOnboardingMessage.vue' + +/** + * AI-assisted database onboarding step type. Only visible when an LLM model is + * configured in the enterprise settings. + */ +export class AIDatabaseOnboardingStepType extends DatabaseOnboardingStepType { + static getType() { + return 'ai' + } + + getOrder() { + return 10 + } + + getLabel() { + return this.app.$i18n.t('databaseStep.ai') + } + + getComponent() { + return AIDatabaseOnboardingForm + } + + hasNameInput() { + return false + } + + isVisible() { + // Only show if the AI-assistant is configured because it will use the + // AI-assistant to create the database. + return !!this.app.$config.public.baserowEnterpriseAssistantLLMModel + } + + isValid(data, vuelidate, refs) { + const component = refs.stepComponent + return ( + !!component && + !!component.v$ && + !component.v$.$invalid && + component.v$.$dirty + ) + } + + async completeAfterWorkspace(workspace, stepData, callback) { + await this.app.$store.dispatch('workspace/select', workspace) + const message = this.app.$i18n.t('aiDatabaseOnboardingStepType.prompt', { + prompt: stepData.prompt, + }) + callback(null, AssistantOnboardingMessage) + await this.app.$store.dispatch('assistant/sendMessage', { + message, + workspace, + }) + const chat = this.app.$store.getters['assistant/currentChat'] + await waitFor(() => { + const currentChat = this.app.$store.getters['assistant/currentChat'] + return !currentChat?.running + }, 50) + const tableLocation = this.app.$store.getters[ + 'assistant/uiLocationHistory' + ].filter((location) => location.type === 'database-table')[0] + if (!tableLocation) { + throw new Error('The assistant did not create a table.') + } + return { tableLocation, chat } + } + + getCompletedRoute(data, responses) { + const response = responses[DatabaseOnboardingType.getType()] + nextTick(async () => { + await pageFinished() + await nextTick() + await this.app.$bus.$emit('toggle-right-sidebar', true) + await this.app.$store.dispatch('assistant/selectChat', response.chat) + }) + return { + name: 'database-table', + params: { + databaseId: response.tableLocation.database_id, + tableId: response.tableLocation.table_id, + }, + } + } +} diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json index dc69fd649b..361e46b3f6 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json +++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json @@ -709,6 +709,30 @@ }, "viewOwnershipType": { "restricted": "Restricted", - "restrictedDescription": "Editors and lower can only see the filtered data and visible fields. It’s possible to manage the members." + "restrictedDescription": "Editors and lower can only see the filtered data and visible fields. It's possible to manage the members." + }, + "databaseStep": { + "ai": "Kuma AI" + }, + "aiDatabaseOnboardingForm": { + "label": "Describe your database", + "placeholder": "e.g. Create project management solution", + "description": "Describe what you want to track. Kuma will create the tables and fields.", + "exampleProjectTrackerName": "Project Tracker", + "exampleProjectTrackerPrompt": "Create a project tracker with Projects, Tasks, Assignees, Status, Priority, Due dates, and dependencies.", + "exampleProductRoadmapName": "Product Roadmap", + "exampleProductRoadmapPrompt": "Create a product roadmap with Initiatives, Features, Owners, Status, Priority, Target quarter, and release notes.", + "exampleCompanyAssetTrackerName": "Company Asset Tracker", + "exampleCompanyAssetTrackerPrompt": "Create an asset tracker with Assets, Categories, Serial numbers, Purchase date, Assigned to, Location, and warranty expiry.", + "exampleTeamCheckInsName": "Team Check-ins", + "exampleTeamCheckInsPrompt": "Create a weekly team check-in tracker with Team members, Date, Wins, Blockers, Mood, Priorities, and follow-ups.", + "exampleBugTrackerName": "Bug Tracker", + "exampleBugTrackerPrompt": "Create a bug tracker with Bugs, Severity, Status, Steps to reproduce, Environment, Reporter, Assignee, and fix version." + }, + "aiDatabaseOnboardingStepType": { + "prompt": "Create a database including tables, fields, example rows, and example views matching this description: {prompt}" + }, + "assistantOnboardingMessage": { + "instructing": "Instructing Kuma to create your database." } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/plugin.js b/enterprise/web-frontend/modules/baserow_enterprise/plugin.js index c128629074..4fb6c0bd3e 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/plugin.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/plugin.js @@ -90,6 +90,7 @@ import { import { CustomCodeBuilderSettingType } from '@baserow_enterprise/builderSettingTypes' import { RealtimePushTwoWaySyncStrategyType } from '@baserow_enterprise/twoWaySyncStrategyTypes' import { RestrictedViewOwnershipType } from '@baserow_enterprise/viewOwnershipTypes' +import { AIDatabaseOnboardingStepType } from '@baserow_enterprise/databaseOnboardingStepTypes' export default defineNuxtPlugin({ name: 'enterprise', @@ -253,6 +254,11 @@ export default defineNuxtPlugin({ new MadeWithBaserowBuilderPageDecoratorType(context) ) + $registry.register( + 'databaseOnboardingStep', + new AIDatabaseOnboardingStepType(context) + ) + $registry.register( 'fieldContextItem', new FieldPermissionsContextItemType(context) diff --git a/enterprise/web-frontend/modules/baserow_enterprise/store/assistant.js b/enterprise/web-frontend/modules/baserow_enterprise/store/assistant.js index 4cfa357e0b..c6b148eebe 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/store/assistant.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/store/assistant.js @@ -18,6 +18,7 @@ export const state = () => ({ chats: [], isLoadingChats: false, uiLocation: null, + uiLocationHistory: [], }) export const mutations = { @@ -109,12 +110,18 @@ export const mutations = { SET_UI_LOCATION(state, location) { state.uiLocation = location || null + state.uiLocationHistory.push(location) + }, + + CLEAR_UI_LOCATION_HISTORY(state) { + state.uiLocationHistory = [] }, } export const actions = { reset({ commit }) { commit('CLEAR_MESSAGES') + commit('CLEAR_UI_LOCATION_HISTORY') commit('SET_CURRENT_CHAT_ID', null) commit('SET_CHATS', []) }, @@ -123,6 +130,7 @@ export const actions = { const id = uuidv4() commit('ADD_CHAT', { id, title: '' }) commit('CLEAR_MESSAGES') + commit('CLEAR_UI_LOCATION_HISTORY') commit('SET_CURRENT_CHAT_ID', id) return id @@ -150,6 +158,7 @@ export const actions = { clearChat({ commit }) { commit('CLEAR_MESSAGES') + commit('CLEAR_UI_LOCATION_HISTORY') commit('SET_CURRENT_CHAT_ID', null) }, @@ -451,6 +460,10 @@ export const getters = { uiLocation: (state) => { return state.uiLocation }, + + uiLocationHistory: (state) => { + return state.uiLocationHistory + }, } export default { diff --git a/web-frontend/Dockerfile b/web-frontend/Dockerfile index f65f11200a..6354634c45 100644 --- a/web-frontend/Dockerfile +++ b/web-frontend/Dockerfile @@ -123,7 +123,7 @@ RUN mkdir -p /baserow/reports /baserow/.cache /baserow/.yarn && \ COPY --chown=$UID:$GID ./eslint.config.mjs /baserow/eslint.config.mjs COPY --chown=$UID:$GID web-frontend /baserow/web-frontend COPY --chown=$UID:$GID premium/web-frontend /baserow/premium/web-frontend -COPY --chown=$UID:$GID enterprise/web-frontend /baserow/enterprise/web-frontend/ +COPY --chown=$UID:$GID enterprise/web-frontend /baserow/enterprise/web-frontend COPY --chown=$UID:$GID --from=builder-ci /baserow/web-frontend/node_modules /baserow/web-frontend/node_modules COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.nuxt /baserow/web-frontend/.nuxt @@ -170,6 +170,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ wget \ tmux \ vim \ + lsof \ + procps \ sudo ENV DOCKER_USER=baserow_docker_user \ @@ -236,7 +238,7 @@ CMD ["nuxt-dev"] # ============================================================================= # Production target - minimal image with only runtime requirements # ============================================================================= -FROM node:24.13-bookworm-slim AS local-base +FROM node:24.13-bookworm-slim AS local ARG UID ARG GID @@ -257,44 +259,14 @@ RUN groupadd --system --gid $GID ${DOCKER_USER} && \ USER $UID:$GID RUN mkdir -p /baserow/web-frontend -WORKDIR /baserow/web-frontend - -COPY --chown=$UID:$GID web-frontend/package.json /baserow/web-frontend/package.json -COPY --chown=$UID:$GID web-frontend/yarn.lock /baserow/web-frontend/yarn.lock - -# Install dependencies first (cached unless package.json/yarn.lock change) -RUN --mount=type=cache,target=$YARN_CACHE_FOLDER,uid=$UID,gid=$GID,sharing=locked \ - yarn install --production --pure-lockfile --cache-folder $YARN_CACHE_FOLDER \ - # Clean up unnecessary files to reduce image size - && find node_modules -type f -name "*.map" -delete \ - && find node_modules -type f \( \ - -name "*.md" -o -name "*.markdown" \ - -o -name "*.ts" -o -name "*.d.ts" \ - -o -name "LICENSE*" -o -name "license*" -o -name "License*" \ - -o -name "CHANGELOG*" -o -name "HISTORY*" \ - -o -name ".npmignore" -o -name ".gitignore" -o -name ".eslintrc*" \ - \) -delete \ - && find node_modules -type d \( \ - -name "test" -o -name "tests" -o -name "__tests__" \ - -o -name "example" -o -name "examples" \ - -o -name "doc" -o -name "docs" \ - -o -name ".github" \ - \) -prune -exec rm -rf {} + +COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.output /baserow/web-frontend/.output COPY --chown=$UID:$GID ./web-frontend/env-remap.mjs /baserow/web-frontend/env-remap.mjs -COPY --chown=$UID:$GID ./web-frontend/docker/docker-entrypoint.sh /baserow/web-frontend/docker/docker-entrypoint.sh -COPY --chown=$UID:$GID ./deploy/plugins/*.sh /baserow/plugins/ - -HEALTHCHECK --interval=60s CMD wget -q -O /dev/null http://localhost:3000/_health/ || exit 1 -ENTRYPOINT ["/usr/bin/tini", "--", "/bin/bash", "/baserow/web-frontend/docker/docker-entrypoint.sh"] -FROM local-base AS local - -COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.output /baserow/web-frontend/.output +HEALTHCHECK --interval=10s CMD wget -q -O /dev/null http://localhost:3000/_health/ || exit 1 -CMD ["nuxt-prod"] +WORKDIR /baserow/web-frontend +CMD ["node", "--import", "./env-remap.mjs", ".output/server/index.mjs"] FROM local AS prod - -CMD ["nuxt-prod"] diff --git a/web-frontend/docker/docker-entrypoint.sh b/web-frontend/docker/docker-entrypoint.sh index 5cc7d49929..70f815da22 100755 --- a/web-frontend/docker/docker-entrypoint.sh +++ b/web-frontend/docker/docker-entrypoint.sh @@ -91,7 +91,7 @@ case "$1" in setup_additional_modules export NITRO_HOST="${BASEROW_WEBFRONTEND_BIND_ADDRESS:-0.0.0.0}" export NITRO_PORT="$BASEROW_WEBFRONTEND_PORT" - exec yarn prod "${@:2}" + exec node --import ./env-remap.mjs .output/server/index.mjs "${@:2}" ;; nuxt-prepare) setup_additional_modules diff --git a/web-frontend/modules/core/assets/scss/components/onboarding.scss b/web-frontend/modules/core/assets/scss/components/onboarding.scss index c10f924b7e..06853d478d 100644 --- a/web-frontend/modules/core/assets/scss/components/onboarding.scss +++ b/web-frontend/modules/core/assets/scss/components/onboarding.scss @@ -25,6 +25,15 @@ width: 320px; } +.onboarding__waiting-message { + margin-top: 20px; + font-size: 14px; + width: 320px; + text-align: center; + line-height: 1.6; + color: $palette-neutral-900; +} + .onboarding__form { display: flex; flex-direction: column; diff --git a/web-frontend/modules/core/assets/scss/components/onboarding_user_preview.scss b/web-frontend/modules/core/assets/scss/components/onboarding_user_preview.scss index 6fbeba4a81..3cc4eb8b49 100644 --- a/web-frontend/modules/core/assets/scss/components/onboarding_user_preview.scss +++ b/web-frontend/modules/core/assets/scss/components/onboarding_user_preview.scss @@ -53,27 +53,6 @@ line-height: 1.4; } -.onboarding-user-preview__role { - @extend %ellipsis; - - position: relative; - text-align: center; - margin-top: 14px; - font-size: 16px; - font-weight: 500; - line-height: 1.25; - height: 20px; - color: $palette-neutral-900; - - &--empty::before { - @extend %empty; - - left: 20px; - right: 20px; - border-radius: 20px; - } -} - .onboarding-user-preview__body { padding: 24px 40px; } diff --git a/web-frontend/modules/core/assets/scss/mixins/helpers.scss b/web-frontend/modules/core/assets/scss/mixins/helpers.scss index 3b711c7906..12ffdef841 100644 --- a/web-frontend/modules/core/assets/scss/mixins/helpers.scss +++ b/web-frontend/modules/core/assets/scss/mixins/helpers.scss @@ -17,14 +17,14 @@ gap: $gap; } -@mixin loading($size: 1.4rem) { +@mixin loading($size: 1.4rem, $color: $color-primary-500) { position: relative; display: block; width: $size; height: $size; border-radius: 50%; border: 0.25em solid; - border-color: $color-primary-500 transparent $color-primary-500 transparent; + border-color: $color transparent $color transparent; animation: spin infinite 1800ms; animation-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86); } diff --git a/web-frontend/modules/core/components/onboarding/AppLayoutPreview.vue b/web-frontend/modules/core/components/onboarding/AppLayoutPreview.vue deleted file mode 100644 index 1a50c9a803..0000000000 --- a/web-frontend/modules/core/components/onboarding/AppLayoutPreview.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - diff --git a/web-frontend/modules/core/components/onboarding/InviteStep.vue b/web-frontend/modules/core/components/onboarding/InviteStep.vue deleted file mode 100644 index 33f01d3cc0..0000000000 --- a/web-frontend/modules/core/components/onboarding/InviteStep.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - diff --git a/web-frontend/modules/core/components/onboarding/MoreStep.vue b/web-frontend/modules/core/components/onboarding/MoreStep.vue index 16737386d8..8c7a846163 100644 --- a/web-frontend/modules/core/components/onboarding/MoreStep.vue +++ b/web-frontend/modules/core/components/onboarding/MoreStep.vue @@ -1,46 +1,47 @@ - - diff --git a/web-frontend/modules/core/components/onboarding/UserPreview.vue b/web-frontend/modules/core/components/onboarding/UserPreview.vue index 0cabe85155..ecd460a43f 100644 --- a/web-frontend/modules/core/components/onboarding/UserPreview.vue +++ b/web-frontend/modules/core/components/onboarding/UserPreview.vue @@ -11,12 +11,6 @@
{{ name }}
-
- {{ role }} -
import { mapGetters } from 'vuex' -import { - TeamOnboardingType, - MoreOnboardingType, -} from '@baserow/modules/core/onboardingTypes' +import { MoreOnboardingType } from '@baserow/modules/core/onboardingTypes' export default { name: 'UserPreview', @@ -63,7 +54,7 @@ export default { return this.data[MoreOnboardingType.getType()]?.role }, team() { - return this.data[TeamOnboardingType.getType()]?.team + return this.data[MoreOnboardingType.getType()]?.team }, }, } diff --git a/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue b/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue deleted file mode 100644 index 8e3d28124a..0000000000 --- a/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - diff --git a/web-frontend/modules/core/components/sidebar/SidebarWithWorkspace.vue b/web-frontend/modules/core/components/sidebar/SidebarWithWorkspace.vue index ce4017678c..2ee06f2ccd 100644 --- a/web-frontend/modules/core/components/sidebar/SidebarWithWorkspace.vue +++ b/web-frontend/modules/core/components/sidebar/SidebarWithWorkspace.vue @@ -51,7 +51,7 @@ :class="{ 'margin-bottom-0': pendingJobs[applicationGroup.type].length, }" - data-highlight="applications" + :data-highlight="`applications-${applicationGroup.type}`" >
-
-
- {{ $t('onboarding.creating') }} -
-
- -
+ + {{ message }} + +