Merge pull request #10172 from Budibase/fix/budi-6797

Googlesheets onboarding - fix in cloud, disable self host
This commit is contained in:
Michael Drury 2023-03-31 13:19:29 +01:00 committed by GitHub
commit 1c6465edcb
9 changed files with 97 additions and 22 deletions

View File

@ -32,8 +32,7 @@ export async function getConfig<T extends Config>(
const db = context.getGlobalDB() const db = context.getGlobalDB()
try { try {
// await to catch error // await to catch error
const config = (await db.get(generateConfigID(type))) as T return (await db.get(generateConfigID(type))) as T
return config
} catch (e: any) { } catch (e: any) {
if (e.status === 404) { if (e.status === 404) {
return return

View File

@ -78,17 +78,23 @@ export async function postAuth(
), ),
{ successRedirect: "/", failureRedirect: "/error" }, { successRedirect: "/", failureRedirect: "/error" },
async (err: any, tokens: string[]) => { async (err: any, tokens: string[]) => {
const baseUrl = `/builder/app/${authStateCookie.appId}/data`
// update the DB for the datasource with all the user info // update the DB for the datasource with all the user info
await doWithDB(authStateCookie.appId, async (db: Database) => { await doWithDB(authStateCookie.appId, async (db: Database) => {
const datasource = await db.get(authStateCookie.datasourceId) let datasource
try {
datasource = await db.get(authStateCookie.datasourceId)
} catch (err: any) {
if (err.status === 404) {
ctx.redirect(baseUrl)
}
}
if (!datasource.config) { if (!datasource.config) {
datasource.config = {} datasource.config = {}
} }
datasource.config.auth = { type: "google", ...tokens } datasource.config.auth = { type: "google", ...tokens }
await db.put(datasource) await db.put(datasource)
ctx.redirect( ctx.redirect(`${baseUrl}/datasource/${authStateCookie.datasourceId}`)
`/builder/app/${authStateCookie.appId}/data/datasource/${authStateCookie.datasourceId}`
)
}) })
} }
)(ctx, next) )(ctx, next)

View File

@ -5,18 +5,28 @@
export let preAuthStep export let preAuthStep
export let datasource export let datasource
export let disabled
$: tenantId = $auth.tenantId $: tenantId = $auth.tenantId
</script> </script>
<button <button
class:disabled
{disabled}
on:click={async () => { on:click={async () => {
let ds = datasource let ds = datasource
let appId = $store.appId
if (!ds) { if (!ds) {
ds = await preAuthStep() const resp = await preAuthStep()
if (resp.datasource && resp.appId) {
ds = resp.datasource
appId = resp.appId
} else {
ds = resp
}
} }
window.open( window.open(
`/api/global/auth/${tenantId}/datasource/google?datasourceId=${ds._id}&appId=${$store.appId}`, `/api/global/auth/${tenantId}/datasource/google?datasourceId=${ds._id}&appId=${appId}`,
"_blank" "_blank"
) )
}} }}
@ -26,6 +36,10 @@
</button> </button>
<style> <style>
.disabled {
opacity: 0.5;
}
button { button {
width: 195px; width: 195px;
height: 40px; height: 40px;

View File

@ -1,12 +1,15 @@
<script> <script>
import { Button, FancyForm, FancyInput, FancyCheckbox } from "@budibase/bbui" import { Button, FancyForm, FancyInput, FancyCheckbox } from "@budibase/bbui"
import GoogleButton from "components/backend/DatasourceNavigator/_components/GoogleButton.svelte"
import { capitalise } from "helpers/helpers" import { capitalise } from "helpers/helpers"
import PanelHeader from "./PanelHeader.svelte" import PanelHeader from "./PanelHeader.svelte"
import { helpers } from "@budibase/shared-core"
export let title = "" export let title = ""
export let onBack = null export let onBack = null
export let onNext = () => {} export let onNext = () => {}
export let fields = {} export let fields = {}
export let type = ""
let errors = {} let errors = {}
@ -57,8 +60,9 @@
} }
$: isValid = getIsValid(fields, errors, values) $: isValid = getIsValid(fields, errors, values)
$: isGoogle = helpers.isGoogleSheets(type)
const handleNext = () => { const handleNext = async () => {
const parsedValues = {} const parsedValues = {}
Object.entries(values).forEach(([name, value]) => { Object.entries(values).forEach(([name, value]) => {
@ -69,7 +73,10 @@
} }
}) })
return onNext(parsedValues) if (isGoogle) {
parsedValues.isGoogle = isGoogle
}
return await onNext(parsedValues)
} }
</script> </script>
@ -99,7 +106,11 @@
{/each} {/each}
</FancyForm> </FancyForm>
</div> </div>
<Button cta disabled={!isValid} on:click={handleNext}>Connect</Button> {#if isGoogle}
<GoogleButton disabled={!isValid} preAuthStep={handleNext} />
{:else}
<Button cta disabled={!isValid} on:click={handleNext}>Connect</Button>
{/if}
</div> </div>
<style> <style>

View File

@ -4,19 +4,20 @@
import DataPanel from "./_components/DataPanel.svelte" import DataPanel from "./_components/DataPanel.svelte"
import DatasourceConfigPanel from "./_components/DatasourceConfigPanel.svelte" import DatasourceConfigPanel from "./_components/DatasourceConfigPanel.svelte"
import ExampleApp from "./_components/ExampleApp.svelte" import ExampleApp from "./_components/ExampleApp.svelte"
import { FancyButton, notifications, Modal } from "@budibase/bbui" import { FancyButton, notifications, Modal, Body } from "@budibase/bbui"
import IntegrationIcon from "components/backend/DatasourceNavigator/IntegrationIcon.svelte" import IntegrationIcon from "components/backend/DatasourceNavigator/IntegrationIcon.svelte"
import { SplitPage } from "@budibase/frontend-core" import { SplitPage } from "@budibase/frontend-core"
import { API } from "api" import { API } from "api"
import { store, automationStore } from "builderStore" import { store, automationStore } from "builderStore"
import { saveDatasource } from "builderStore/datasource" import { saveDatasource } from "builderStore/datasource"
import { integrations } from "stores/backend" import { integrations } from "stores/backend"
import { auth, admin } from "stores/portal" import { auth, admin, organisation } from "stores/portal"
import FontAwesomeIcon from "components/common/FontAwesomeIcon.svelte" import FontAwesomeIcon from "components/common/FontAwesomeIcon.svelte"
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte" import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte"
import createFromScratchScreen from "builderStore/store/screenTemplates/createFromScratchScreen" import createFromScratchScreen from "builderStore/store/screenTemplates/createFromScratchScreen"
import { Roles } from "constants/backend" import { Roles } from "constants/backend"
import Spinner from "components/common/Spinner.svelte" import Spinner from "components/common/Spinner.svelte"
import { helpers } from "@budibase/shared-core"
let name = "My first app" let name = "My first app"
let url = "my-first-app" let url = "my-first-app"
@ -25,10 +26,11 @@
let plusIntegrations = {} let plusIntegrations = {}
let integrationsLoading = true let integrationsLoading = true
$: getIntegrations()
let creationLoading = false let creationLoading = false
let uploadModal let uploadModal
let googleComplete = false
$: getIntegrations()
const createApp = async useSampleData => { const createApp = async useSampleData => {
creationLoading = true creationLoading = true
@ -62,6 +64,7 @@
await store.actions.screens.save(defaultScreenTemplate) await store.actions.screens.save(defaultScreenTemplate)
appId = createdApp.instance._id appId = createdApp.instance._id
return createdApp
} catch (e) { } catch (e) {
creationLoading = false creationLoading = false
throw e throw e
@ -74,6 +77,13 @@
const newPlusIntegrations = {} const newPlusIntegrations = {}
Object.entries($integrations).forEach(([integrationType, schema]) => { Object.entries($integrations).forEach(([integrationType, schema]) => {
// google sheets not available in self-host
if (
helpers.isGoogleSheets(integrationType) &&
!$organisation.googleDatasourceConfigured
) {
return
}
if (schema?.plus) { if (schema?.plus) {
newPlusIntegrations[integrationType] = schema newPlusIntegrations[integrationType] = schema
} }
@ -92,12 +102,17 @@
notifications.success(`App created successfully`) notifications.success(`App created successfully`)
} }
const handleCreateApp = async ({ datasourceConfig, useSampleData }) => { const handleCreateApp = async ({
datasourceConfig,
useSampleData,
isGoogle,
}) => {
try { try {
await createApp(useSampleData) const app = await createApp(useSampleData)
let datasource
if (datasourceConfig) { if (datasourceConfig) {
await saveDatasource({ datasource = await saveDatasource({
plus: true, plus: true,
auth: undefined, auth: undefined,
name: plusIntegrations[stage].friendlyName, name: plusIntegrations[stage].friendlyName,
@ -107,7 +122,14 @@
}) })
} }
goToApp() store.set()
if (isGoogle) {
googleComplete = true
return { datasource, appId: app.appId }
} else {
goToApp()
}
} catch (e) { } catch (e) {
console.log(e) console.log(e)
creationLoading = false creationLoading = false
@ -127,8 +149,15 @@
<SplitPage> <SplitPage>
{#if stage === "name"} {#if stage === "name"}
<NamePanel bind:name bind:url onNext={() => (stage = "data")} /> <NamePanel bind:name bind:url onNext={() => (stage = "data")} />
{:else if googleComplete}
<div class="centered">
<Body
>Please login to your Google account in the new tab which as opened to
continue.</Body
>
</div>
{:else if integrationsLoading || creationLoading} {:else if integrationsLoading || creationLoading}
<div class="spinner"> <div class="centered">
<Spinner /> <Spinner />
</div> </div>
{:else if stage === "data"} {:else if stage === "data"}
@ -174,8 +203,13 @@
<DatasourceConfigPanel <DatasourceConfigPanel
title={plusIntegrations[stage].friendlyName} title={plusIntegrations[stage].friendlyName}
fields={plusIntegrations[stage].datasource} fields={plusIntegrations[stage].datasource}
type={stage}
onBack={() => (stage = "data")} onBack={() => (stage = "data")}
onNext={data => handleCreateApp({ datasourceConfig: data })} onNext={data => {
const isGoogle = data.isGoogle
delete data.isGoogle
return handleCreateApp({ datasourceConfig: data, isGoogle })
}}
/> />
{:else} {:else}
<p>There was an problem. Please refresh the page and try again.</p> <p>There was an problem. Please refresh the page and try again.</p>
@ -186,7 +220,7 @@
</SplitPage> </SplitPage>
<style> <style>
.spinner { .centered {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;

View File

@ -245,6 +245,10 @@ class GoogleSheetsIntegration implements DatasourcePlus {
} }
async buildSchema(datasourceId: string, entities: Record<string, Table>) { async buildSchema(datasourceId: string, entities: Record<string, Table>) {
// not fully configured yet
if (!this.config.auth) {
return
}
await this.connect() await this.connect()
const sheets = this.client.sheetsByIndex const sheets = this.client.sheetsByIndex
const tables: Record<string, Table> = {} const tables: Record<string, Table> = {}

View File

@ -0,0 +1,2 @@
export * from "./helpers"
export * from "./integrations"

View File

@ -0,0 +1,5 @@
import { SourceName } from "@budibase/types"
export function isGoogleSheets(type: SourceName) {
return type === SourceName.GOOGLE_SHEETS
}