Automatically migrate old apps server-side when importing or using templates
This commit is contained in:
parent
e77e6b070f
commit
452eba8635
|
@ -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 => {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Document } from "../document"
|
||||
|
||||
export interface Screen extends Document {
|
||||
layoutId: string
|
||||
layoutId?: string
|
||||
showNavigation?: boolean
|
||||
width?: string
|
||||
routing: {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue