Merge pull request #12060 from Budibase/fix/12046-nav-links-overwrite-app

App overwrite - take new apps navigation
This commit is contained in:
Michael Drury 2023-10-16 15:45:45 +01:00 committed by GitHub
commit 64f4701b57
6 changed files with 65 additions and 5 deletions

View File

@ -54,6 +54,7 @@
label="App export"
on:change={e => {
file = e.detail?.[0]
encrypted = file?.name?.endsWith(".enc.tar.gz")
}}
/>
<Toggle text="Encrypted" bind:value={encrypted} />

View File

@ -13,7 +13,7 @@
import ExportAppModal from "components/start/ExportAppModal.svelte"
import ImportAppModal from "components/start/ImportAppModal.svelte"
$: filteredApps = $apps.filter(app => app.devId == $store.appId)
$: filteredApps = $apps.filter(app => app.devId === $store.appId)
$: app = filteredApps.length ? filteredApps[0] : {}
$: appDeployed = app?.status === AppStatus.DEPLOYED

View File

@ -23,7 +23,10 @@ describe("/applications/:appId/import", () => {
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.message).toBe("app updated")
const appPackage = await config.api.application.get(appId!)
expect(appPackage.navigation?.links?.length).toBe(2)
expect(expect(appPackage.navigation?.links?.[0].url).toBe("/blank"))
expect(expect(appPackage.navigation?.links?.[1].url).toBe("/derp"))
const screens = await config.api.screen.list()
expect(screens.length).toBe(2)
expect(screens[0].routing.route).toBe("/derp")

View File

@ -4,6 +4,8 @@ import {
Document,
Database,
RowValue,
DocumentType,
App,
} from "@budibase/types"
import backups from "../backups"
@ -12,9 +14,39 @@ export type FileAttributes = {
path: string
}
async function getNewAppMetadata(
tempDb: Database,
appDb: Database
): Promise<App> {
// static doc denoting app information
const docId = DocumentType.APP_METADATA
try {
const [tempMetadata, appMetadata] = await Promise.all([
tempDb.get<App>(docId),
appDb.get<App>(docId),
])
return {
...appMetadata,
automationErrors: undefined,
theme: tempMetadata.theme,
customTheme: tempMetadata.customTheme,
features: tempMetadata.features,
icon: tempMetadata.icon,
navigation: tempMetadata.navigation,
type: tempMetadata.type,
version: tempMetadata.version,
}
} catch (err: any) {
throw new Error(
`Unable to retrieve app metadata for import - ${err.message}`
)
}
}
function mergeUpdateAndDeleteDocuments(
updateDocs: Document[],
deleteDocs: Document[]
deleteDocs: Document[],
metadata: App
) {
// compress the documents to create and to delete (if same ID, then just update the rev)
const finalToDelete = []
@ -26,7 +58,7 @@ function mergeUpdateAndDeleteDocuments(
finalToDelete.push(deleteDoc)
}
}
return [...updateDocs, ...finalToDelete]
return [...updateDocs, ...finalToDelete, metadata]
}
async function removeImportableDocuments(db: Database) {
@ -90,12 +122,15 @@ export async function updateWithExport(
await backups.importApp(devId, tempDb, template, {
importObjStoreContents: false,
})
const newMetadata = await getNewAppMetadata(tempDb, appDb)
// get the documents to copy
const toUpdate = await getImportableDocuments(tempDb)
// clear out the old documents
const toDelete = await removeImportableDocuments(appDb)
// now bulk update documents - add new ones, delete old ones and update common ones
await appDb.bulkDocs(mergeUpdateAndDeleteDocuments(toUpdate, toDelete))
await appDb.bulkDocs(
mergeUpdateAndDeleteDocuments(toUpdate, toDelete, newMetadata)
)
} finally {
await tempDb.destroy()
}

View File

@ -0,0 +1,18 @@
import { App } from "@budibase/types"
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class ApplicationAPI extends TestAPI {
constructor(config: TestConfiguration) {
super(config)
}
get = async (appId: string): Promise<App> => {
const result = await this.request
.get(`/api/applications/${appId}/appPackage`)
.set(this.config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)
return result.body.application as App
}
}

View File

@ -6,6 +6,7 @@ import { ViewV2API } from "./viewV2"
import { DatasourceAPI } from "./datasource"
import { LegacyViewAPI } from "./legacyView"
import { ScreenAPI } from "./screen"
import { ApplicationAPI } from "./application"
export default class API {
table: TableAPI
@ -15,6 +16,7 @@ export default class API {
permission: PermissionAPI
datasource: DatasourceAPI
screen: ScreenAPI
application: ApplicationAPI
constructor(config: TestConfiguration) {
this.table = new TableAPI(config)
@ -24,5 +26,6 @@ export default class API {
this.permission = new PermissionAPI(config)
this.datasource = new DatasourceAPI(config)
this.screen = new ScreenAPI(config)
this.application = new ApplicationAPI(config)
}
}