diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 58d803aa03..9ad24e2124 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -19,7 +19,6 @@ import { makeComponentUnique, } from "../componentUtils" import { Helpers } from "@budibase/bbui" -import { DefaultAppTheme, LAYOUT_NAMES } from "../../constants" import { Utils } from "@budibase/frontend-core" const INITIAL_FRONTEND_STATE = { @@ -124,35 +123,6 @@ export const getFrontendStore = () => { await integrations.init() await queries.init() await tables.init() - - // Add navigation settings to old apps - if (!application.navigation) { - const layout = layouts.find(x => x._id === LAYOUT_NAMES.MASTER.PRIVATE) - const customTheme = application.customTheme - let navigationSettings = { - navigation: "Top", - title: application.name, - navWidth: "Large", - navBackground: - customTheme?.navBackground || DefaultAppTheme.navBackground, - navTextColor: - customTheme?.navTextColor || DefaultAppTheme.navTextColor, - } - if (layout) { - navigationSettings.hideLogo = layout.props.hideLogo - navigationSettings.hideTitle = layout.props.hideTitle - navigationSettings.title = layout.props.title || application.name - navigationSettings.logoUrl = layout.props.logoUrl - navigationSettings.links = layout.props.links - navigationSettings.navigation = layout.props.navigation || "Top" - navigationSettings.sticky = layout.props.sticky - navigationSettings.navWidth = layout.props.width || "Large" - if (navigationSettings.navigation === "None") { - navigationSettings.navigation = "Top" - } - } - await store.actions.navigation.save(navigationSettings) - } }, theme: { save: async theme => { diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index ae4a60d78d..0636eded84 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -47,7 +47,14 @@ import { checkAppMetadata } from "../../automations/logging" import { getUniqueRows } from "../../utilities/usageQuota/rows" import { quotas } from "@budibase/pro" import { errors, events, migrations } from "@budibase/backend-core" -import { App, MigrationType } from "@budibase/types" +import { + App, + Layout, + Screen, + MigrationType, + AppNavigation, +} from "@budibase/types" +import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" const URL_REGEX_SLASH = /\/|\\/g @@ -243,26 +250,19 @@ const performAppCreate = async (ctx: any) => { } const instance = await createInstance(instanceConfig) const appId = instance._id - const db = context.getAppDB() - let _rev - try { - // if template there will be an existing doc - const existing = await db.get(DocumentType.APP_METADATA) - _rev = existing._rev - } catch (err) { - // nothing to do - } - const newApplication: App = { + + // Create new app doc + let newApplication: App = { _id: DocumentType.APP_METADATA, - _rev, - appId: instance._id, + _rev: undefined, + appId, type: "app", version: packageJson.version, componentLibraries: ["@budibase/standard-components"], name: name, url: url, - template: ctx.request.body.template, + template: templateKey, instance: instance, tenantId: getTenantId(), updatedAt: new Date().toISOString(), @@ -285,6 +285,37 @@ const performAppCreate = async (ctx: any) => { buttonBorderRadius: "16px", }, } + + // If we used a template or imported an app there will be an existing doc. + // Fetch and migrate some metadata from the existing app. + try { + const existing: App = await db.get(DocumentType.APP_METADATA) + const keys: string[] = [ + "_rev", + "navigation", + "theme", + "customTheme", + "icon", + ] + keys.forEach((key: string) => { + // @ts-ignore + if (existing[key]) { + // @ts-ignore + newApplication[key] = existing[key] + } + }) + + // Migrate navigation settings and screens if required + if (existing && !existing.navigation) { + const navigation = await migrateAppNavigation() + if (navigation) { + newApplication.navigation = navigation + } + } + } catch (err) { + // Nothing to do + } + const response = await db.put(newApplication, { force: true }) newApplication._rev = response.rev @@ -567,3 +598,57 @@ const updateAppPackage = async (appPackage: any, appId: any) => { return newAppPackage }) } + +const migrateAppNavigation = async () => { + const db = context.getAppDB() + const existing: App = await db.get(DocumentType.APP_METADATA) + const layouts = await getLayouts() + const screens = await getScreens() + + // Migrate all screens, removing custom layouts + for (let screen of screens) { + if (!screen.layoutId) { + return + } + const layout = layouts.find( + (layout: Layout) => layout._id === screen.layoutId + ) + screen.layoutId = undefined + screen.showNavigation = layout?.props.navigation !== "None" + screen.width = layout?.props.width || "Large" + await db.put(screen) + } + + // Migrate layout navigation settings + const { name, customTheme } = existing + const layout = layouts?.find( + (layout: Layout) => layout._id === BASE_LAYOUT_PROP_IDS.PRIVATE + ) + if (layout) { + let navigationSettings: any = { + navigation: "Top", + title: name, + navWidth: "Large", + navBackground: + customTheme?.navBackground || "var(--spectrum-global-color-gray-50)", + navTextColor: + customTheme?.navTextColor || "var(--spectrum-global-color-gray-800)", + } + if (layout) { + navigationSettings.hideLogo = layout.props.hideLogo + navigationSettings.hideTitle = layout.props.hideTitle + navigationSettings.title = layout.props.title || name + navigationSettings.logoUrl = layout.props.logoUrl + navigationSettings.links = layout.props.links + navigationSettings.navigation = layout.props.navigation || "Top" + navigationSettings.sticky = layout.props.sticky + navigationSettings.navWidth = layout.props.width || "Large" + if (navigationSettings.navigation === "None") { + navigationSettings.navigation = "Top" + } + } + return navigationSettings + } else { + return null + } +} diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index 62301d57ca..461495ff8c 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -98,7 +98,7 @@ module.exports = server.listen(env.PORT || 0, async () => { // not recommended in a clustered environment if (!env.HTTP_MIGRATIONS && !env.isTest()) { try { - await migrations.migrate() + // await migrations.migrate() } catch (e) { logAlert("Error performing migrations. Exiting.", e) shutdown() diff --git a/packages/types/src/documents/app/app.ts b/packages/types/src/documents/app/app.ts index 1def994697..55eebe389d 100644 --- a/packages/types/src/documents/app/app.ts +++ b/packages/types/src/documents/app/app.ts @@ -14,11 +14,7 @@ export interface App extends Document { tenantId: string status: string theme?: string - customTheme?: { - buttonBorderRadius?: string - primaryColor?: string - primaryColorHover?: string - } + customTheme?: AppCustomTheme revertableVersion?: string navigation?: AppNavigation automationErrors?: AppMetadataErrors @@ -47,3 +43,13 @@ export interface AppNavigationLink { id?: string roleId?: string } + +export interface AppCustomTheme { + buttonBorderRadius?: string + primaryColor?: string + primaryColorHover?: string + + // Used to exist before new design UI + navTextColor?: string + navBackground?: string +} diff --git a/packages/types/src/documents/app/screen.ts b/packages/types/src/documents/app/screen.ts index 1eead16aa0..98db658aa6 100644 --- a/packages/types/src/documents/app/screen.ts +++ b/packages/types/src/documents/app/screen.ts @@ -1,7 +1,7 @@ import { Document } from "../document" export interface Screen extends Document { - layoutId: string + layoutId?: string showNavigation?: boolean width?: string routing: { diff --git a/packages/types/src/sdk/events/screen.ts b/packages/types/src/sdk/events/screen.ts index 0d9f8cb32c..23c468b7ad 100644 --- a/packages/types/src/sdk/events/screen.ts +++ b/packages/types/src/sdk/events/screen.ts @@ -2,12 +2,12 @@ import { BaseEvent } from "./event" export interface ScreenCreatedEvent extends BaseEvent { screenId: string - layoutId: string + layoutId?: string roleId: string } export interface ScreenDeletedEvent extends BaseEvent { screenId: string - layoutId: string + layoutId?: string roleId: string }