commit
9f7aba3f19
|
@ -11,6 +11,7 @@ it("should rename an unpublished application", () => {
|
||||||
renameApp(appRename)
|
renameApp(appRename)
|
||||||
cy.searchForApplication(appRename)
|
cy.searchForApplication(appRename)
|
||||||
cy.get(".appGrid").find(".wrapper").should("have.length", 1)
|
cy.get(".appGrid").find(".wrapper").should("have.length", 1)
|
||||||
|
cy.deleteApp(appRename)
|
||||||
})
|
})
|
||||||
|
|
||||||
xit("Should rename a published application", () => {
|
xit("Should rename a published application", () => {
|
||||||
|
|
|
@ -43,24 +43,26 @@ Cypress.Commands.add("createApp", name => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("deleteApp", () => {
|
Cypress.Commands.add("deleteApp", appName => {
|
||||||
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.request(`localhost:${Cypress.env("PORT")}/api/applications?status=all`)
|
cy.request(`localhost:${Cypress.env("PORT")}/api/applications?status=all`)
|
||||||
.its("body")
|
.its("body")
|
||||||
.then(val => {
|
.then(val => {
|
||||||
console.log(val)
|
|
||||||
if (val.length > 0) {
|
if (val.length > 0) {
|
||||||
cy.get(".title > :nth-child(3) > .spectrum-Icon").click()
|
cy.get(".title > :nth-child(3) > .spectrum-Icon").click()
|
||||||
cy.contains("Delete").click()
|
cy.contains("Delete").click()
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
cy.get("input").type(appName)
|
||||||
cy.get(".spectrum-Button--warning").click()
|
cy.get(".spectrum-Button--warning").click()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createTestApp", () => {
|
Cypress.Commands.add("createTestApp", () => {
|
||||||
const appName = "Cypress Tests"
|
const appName = "Cypress Tests"
|
||||||
cy.deleteApp()
|
cy.deleteApp(appName)
|
||||||
cy.createApp(appName, "This app is used for Cypress testing.")
|
cy.createApp(appName, "This app is used for Cypress testing.")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
export let onOk = undefined
|
export let onOk = undefined
|
||||||
export let onCancel = undefined
|
export let onCancel = undefined
|
||||||
export let warning = true
|
export let warning = true
|
||||||
|
export let disabled
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
confirmText={okText}
|
confirmText={okText}
|
||||||
{cancelText}
|
{cancelText}
|
||||||
{warning}
|
{warning}
|
||||||
|
{disabled}
|
||||||
>
|
>
|
||||||
<Body size="S">
|
<Body size="S">
|
||||||
{body}
|
{body}
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { Icon, Modal, notifications, ModalContent } from "@budibase/bbui"
|
import {
|
||||||
|
Icon,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
notifications,
|
||||||
|
ModalContent,
|
||||||
|
} from "@budibase/bbui"
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
|
|
||||||
let revertModal
|
let revertModal
|
||||||
|
let appName
|
||||||
|
|
||||||
$: appId = $store.appId
|
$: appId = $store.appId
|
||||||
|
|
||||||
|
@ -33,10 +40,17 @@
|
||||||
|
|
||||||
<Icon name="Revert" hoverable on:click={revertModal.show} />
|
<Icon name="Revert" hoverable on:click={revertModal.show} />
|
||||||
<Modal bind:this={revertModal}>
|
<Modal bind:this={revertModal}>
|
||||||
<ModalContent title="Revert Changes" confirmText="Revert" onConfirm={revert}>
|
<ModalContent
|
||||||
|
title="Revert Changes"
|
||||||
|
confirmText="Revert"
|
||||||
|
onConfirm={revert}
|
||||||
|
disabled={appName !== $store.name}
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
>The changes you have made will be deleted and the application reverted
|
>The changes you have made will be deleted and the application reverted
|
||||||
back to its production state.</span
|
back to its production state.</span
|
||||||
>
|
>
|
||||||
|
<span>Please enter your app name to continue.</span>
|
||||||
|
<Input bind:value={appName} />
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
theme: $store.theme,
|
theme: $store.theme,
|
||||||
customTheme: $store.customTheme,
|
customTheme: $store.customTheme,
|
||||||
previewDevice: $store.previewDevice,
|
previewDevice: $store.previewDevice,
|
||||||
|
messagePassing: $store.clientFeatures.messagePassing
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saving pages and screens to the DB causes them to have _revs.
|
// Saving pages and screens to the DB causes them to have _revs.
|
||||||
|
@ -94,12 +95,12 @@
|
||||||
const handlers = {
|
const handlers = {
|
||||||
[MessageTypes.READY]: () => {
|
[MessageTypes.READY]: () => {
|
||||||
// Initialise the app when mounted
|
// Initialise the app when mounted
|
||||||
// Display preview immediately if the intelligent loading feature
|
|
||||||
// is not supported
|
|
||||||
if ($store.clientFeatures.messagePassing) {
|
if ($store.clientFeatures.messagePassing) {
|
||||||
if (!loading) return
|
if (!loading) return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Display preview immediately if the intelligent loading feature
|
||||||
|
// is not supported
|
||||||
if (!$store.clientFeatures.intelligentLoading) {
|
if (!$store.clientFeatures.intelligentLoading) {
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
@ -118,9 +119,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if ($store.clientFeatures.messagePassing) {
|
|
||||||
window.addEventListener("message", receiveMessage)
|
window.addEventListener("message", receiveMessage)
|
||||||
} else {
|
if (!$store.clientFeatures.messagePassing) {
|
||||||
// Legacy - remove in later versions of BB
|
// Legacy - remove in later versions of BB
|
||||||
iframe.contentWindow.addEventListener("ready", () => {
|
iframe.contentWindow.addEventListener("ready", () => {
|
||||||
receiveMessage({ data: { type: MessageTypes.READY }})
|
receiveMessage({ data: { type: MessageTypes.READY }})
|
||||||
|
@ -137,9 +137,8 @@
|
||||||
// Remove all iframe event listeners on component destroy
|
// Remove all iframe event listeners on component destroy
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
if (iframe.contentWindow) {
|
if (iframe.contentWindow) {
|
||||||
if ($store.clientFeatures.messagePassing) {
|
|
||||||
window.removeEventListener("message", receiveMessage)
|
window.removeEventListener("message", receiveMessage)
|
||||||
} else {
|
if (!$store.clientFeatures.messagePassing) {
|
||||||
// Legacy - remove in later versions of BB
|
// Legacy - remove in later versions of BB
|
||||||
iframe.contentWindow.removeEventListener("bb-event", handleBudibaseEvent)
|
iframe.contentWindow.removeEventListener("bb-event", handleBudibaseEvent)
|
||||||
iframe.contentWindow.removeEventListener("keydown", handleKeydownEvent)
|
iframe.contentWindow.removeEventListener("keydown", handleKeydownEvent)
|
||||||
|
|
|
@ -97,6 +97,7 @@ export default `
|
||||||
window.addEventListener("keydown", evt => {
|
window.addEventListener("keydown", evt => {
|
||||||
window.parent.postMessage({ type: "keydown", key: event.key })
|
window.parent.postMessage({ type: "keydown", key: event.key })
|
||||||
})
|
})
|
||||||
|
|
||||||
window.parent.postMessage({ type: "ready" })
|
window.parent.postMessage({ type: "ready" })
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -157,6 +157,11 @@
|
||||||
}
|
}
|
||||||
return title
|
return title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onCancel() {
|
||||||
|
template = null
|
||||||
|
await auth.setInitInfo({})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showTemplateSelection}
|
{#if showTemplateSelection}
|
||||||
|
@ -186,7 +191,7 @@
|
||||||
title={getModalTitle()}
|
title={getModalTitle()}
|
||||||
confirmText={template?.fromFile ? "Import app" : "Create app"}
|
confirmText={template?.fromFile ? "Import app" : "Create app"}
|
||||||
onConfirm={createNewApp}
|
onConfirm={createNewApp}
|
||||||
onCancel={inline ? () => (template = null) : null}
|
onCancel={inline ? onCancel : null}
|
||||||
cancelText={inline ? "Back" : undefined}
|
cancelText={inline ? "Back" : undefined}
|
||||||
showCloseIcon={!inline}
|
showCloseIcon={!inline}
|
||||||
disabled={!valid}
|
disabled={!valid}
|
||||||
|
|
|
@ -28,9 +28,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user && user.tenantId) {
|
if (user && user.tenantId) {
|
||||||
// no tenant in the url - send to account portal to fix this
|
|
||||||
if (!urlTenantId) {
|
if (!urlTenantId) {
|
||||||
window.location.href = $admin.accountPortalUrl
|
// redirect to correct tenantId subdomain
|
||||||
|
if (!window.location.host.includes("localhost")) {
|
||||||
|
let redirectUrl = window.location.href
|
||||||
|
redirectUrl = redirectUrl.replace("://", `://${user.tenantId}.`)
|
||||||
|
window.location.href = redirectUrl
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
ActionButton,
|
ActionButton,
|
||||||
ActionGroup,
|
ActionGroup,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
|
Input,
|
||||||
Select,
|
Select,
|
||||||
Modal,
|
Modal,
|
||||||
Page,
|
Page,
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
let loaded = false
|
let loaded = false
|
||||||
let searchTerm = ""
|
let searchTerm = ""
|
||||||
let cloud = $admin.cloud
|
let cloud = $admin.cloud
|
||||||
|
let appName = ""
|
||||||
|
|
||||||
$: enrichedApps = enrichApps($apps, $auth.user, sortBy)
|
$: enrichedApps = enrichApps($apps, $auth.user, sortBy)
|
||||||
$: filteredApps = enrichedApps.filter(app =>
|
$: filteredApps = enrichedApps.filter(app =>
|
||||||
|
@ -296,8 +298,12 @@
|
||||||
title="Confirm deletion"
|
title="Confirm deletion"
|
||||||
okText="Delete app"
|
okText="Delete app"
|
||||||
onOk={confirmDeleteApp}
|
onOk={confirmDeleteApp}
|
||||||
|
disabled={appName !== selectedApp?.name}
|
||||||
>
|
>
|
||||||
Are you sure you want to delete the app <b>{selectedApp?.name}</b>?
|
Are you sure you want to delete the app <b>{selectedApp?.name}</b>?
|
||||||
|
|
||||||
|
<p>Please enter the app name below to confirm.</p>
|
||||||
|
<Input bind:value={appName} data-cy="delete-app-confirmation" />
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={unpublishModal}
|
bind:this={unpublishModal}
|
||||||
|
|
|
@ -80,16 +80,30 @@ export function createAuthStore() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setInitInfo(info) {
|
||||||
|
await api.post(`/api/global/auth/init`, info)
|
||||||
|
auth.update(store => {
|
||||||
|
store.initInfo = info
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getInitInfo() {
|
||||||
|
const response = await api.get(`/api/global/auth/init`)
|
||||||
|
const json = response.json()
|
||||||
|
auth.update(store => {
|
||||||
|
store.initInfo = json
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe: store.subscribe,
|
subscribe: store.subscribe,
|
||||||
setOrganisation: setOrganisation,
|
setOrganisation,
|
||||||
getInitInfo: async () => {
|
getInitInfo,
|
||||||
const response = await api.get(`/api/global/auth/init`)
|
setInitInfo,
|
||||||
return await response.json()
|
|
||||||
},
|
|
||||||
setInitInfo: async info => {
|
|
||||||
await api.post(`/api/global/auth/init`, info)
|
|
||||||
},
|
|
||||||
checkQueryString: async () => {
|
checkQueryString: async () => {
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
if (urlParams.has("tenantId")) {
|
if (urlParams.has("tenantId")) {
|
||||||
|
@ -129,6 +143,7 @@ export function createAuthStore() {
|
||||||
throw "Unable to create logout"
|
throw "Unable to create logout"
|
||||||
}
|
}
|
||||||
await response.json()
|
await response.json()
|
||||||
|
await setInitInfo({})
|
||||||
setUser(null)
|
setUser(null)
|
||||||
},
|
},
|
||||||
updateSelf: async fields => {
|
updateSelf: async fields => {
|
||||||
|
|
|
@ -323,7 +323,7 @@ exports.delete = async ctx => {
|
||||||
ctx.body = result
|
ctx.body = result
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.sync = async ctx => {
|
exports.sync = async (ctx, next) => {
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
if (!isDevAppID(appId)) {
|
if (!isDevAppID(appId)) {
|
||||||
ctx.throw(400, "This action cannot be performed for production apps")
|
ctx.throw(400, "This action cannot be performed for production apps")
|
||||||
|
@ -336,10 +336,11 @@ exports.sync = async ctx => {
|
||||||
if (info.error) throw info.error
|
if (info.error) throw info.error
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// the database doesn't exist. Don't replicate
|
// the database doesn't exist. Don't replicate
|
||||||
|
ctx.status = 200
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
message: "App sync not required, app not deployed.",
|
message: "App sync not required, app not deployed.",
|
||||||
}
|
}
|
||||||
return
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
const replication = new Replication({
|
const replication = new Replication({
|
||||||
|
|
Loading…
Reference in New Issue