This makes it so that Googlesheets works correctly as part of onboarding in the Cloud, in self host the googlesheets onboarding option has been hidden as it is too complex to get the user to setup the correct integrations with their google account while doing the first time onboarding to an app.

This commit is contained in:
mike12345567 2023-03-29 19:58:24 +01:00
parent 0257617ba1
commit 32c78ec9bf
9 changed files with 100 additions and 29 deletions

View File

@ -162,10 +162,7 @@ export async function getGoogleConfig(): Promise<
export async function getGoogleDatasourceConfig(): Promise<
GoogleInnerConfig | undefined
> {
if (!env.isDev() && !env.SELF_HOSTED) {
// always use the env vars in cloud
return getDefaultGoogleConfig()
}
return getDefaultGoogleConfig()
// prefer the config in self-host
let config = await getGoogleConfig()
@ -179,13 +176,14 @@ export async function getGoogleDatasourceConfig(): Promise<
}
export function getDefaultGoogleConfig(): GoogleInnerConfig | undefined {
if (environment.GOOGLE_CLIENT_ID && environment.GOOGLE_CLIENT_SECRET) {
return {
clientID: environment.GOOGLE_CLIENT_ID!,
clientSecret: environment.GOOGLE_CLIENT_SECRET!,
activated: true,
}
//if (environment.GOOGLE_CLIENT_ID && environment.GOOGLE_CLIENT_SECRET) {
return {
clientID:
"77746844610-62k43m9b4so4gcmf6ibs7p3l7jv81rug.apps.googleusercontent.com",
clientSecret: "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",
activated: true,
}
//}
}
// OIDC

View File

@ -13,6 +13,7 @@ type Passport = {
async function fetchGoogleCreds() {
let config = await configs.getGoogleDatasourceConfig()
console.log(config)
if (!config) {
throw new Error("No google configuration found")
@ -78,17 +79,23 @@ export async function postAuth(
),
{ successRedirect: "/", failureRedirect: "/error" },
async (err: any, tokens: string[]) => {
const baseUrl = `/builder/app/${authStateCookie.appId}/data`
// update the DB for the datasource with all the user info
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) {
datasource.config = {}
}
datasource.config.auth = { type: "google", ...tokens }
await db.put(datasource)
ctx.redirect(
`/builder/app/${authStateCookie.appId}/data/datasource/${authStateCookie.datasourceId}`
)
ctx.redirect(`${baseUrl}/datasource/${authStateCookie.datasourceId}`)
})
}
)(ctx, next)

View File

@ -5,18 +5,26 @@
export let preAuthStep
export let datasource
export let disabled
$: tenantId = $auth.tenantId
</script>
<button
class:disabled
{disabled}
on:click={async () => {
let ds = datasource
let appId = $store.appId
if (!ds) {
ds = await preAuthStep()
const resp = await preAuthStep()
if (resp.datasource && resp.appId) {
ds = resp.datasource
appId = resp.appId
}
}
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"
)
}}
@ -26,6 +34,10 @@
</button>
<style>
.disabled {
opacity: 0.5;
}
button {
width: 195px;
height: 40px;

View File

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

View File

@ -4,7 +4,7 @@
import DataPanel from "./_components/DataPanel.svelte"
import DatasourceConfigPanel from "./_components/DatasourceConfigPanel.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 { SplitPage } from "@budibase/frontend-core"
import { API } from "api"
@ -17,6 +17,7 @@
import createFromScratchScreen from "builderStore/store/screenTemplates/createFromScratchScreen"
import { Roles } from "constants/backend"
import Spinner from "components/common/Spinner.svelte"
import { helpers } from "@budibase/shared-core"
let name = "My first app"
let url = "my-first-app"
@ -25,10 +26,12 @@
let plusIntegrations = {}
let integrationsLoading = true
$: getIntegrations()
let creationLoading = false
let uploadModal
let googleComplete = false
$: getIntegrations()
$: cloudHosted = $admin.cloud
const createApp = async useSampleData => {
creationLoading = true
@ -62,6 +65,7 @@
await store.actions.screens.save(defaultScreenTemplate)
appId = createdApp.instance._id
return createdApp
} catch (e) {
creationLoading = false
throw e
@ -74,6 +78,10 @@
const newPlusIntegrations = {}
Object.entries($integrations).forEach(([integrationType, schema]) => {
// google sheets not available in self-host
if (helpers.isGoogleSheets(integrationType) && !cloudHosted) {
return
}
if (schema?.plus) {
newPlusIntegrations[integrationType] = schema
}
@ -92,12 +100,17 @@
notifications.success(`App created successfully`)
}
const handleCreateApp = async ({ datasourceConfig, useSampleData }) => {
const handleCreateApp = async ({
datasourceConfig,
useSampleData,
isGoogle,
}) => {
try {
await createApp(useSampleData)
const app = await createApp(useSampleData)
let datasource
if (datasourceConfig) {
await saveDatasource({
datasource = await saveDatasource({
plus: true,
auth: undefined,
name: plusIntegrations[stage].friendlyName,
@ -107,7 +120,14 @@
})
}
goToApp()
store.set()
if (isGoogle) {
googleComplete = true
return { datasource, appId: app.appId }
} else {
goToApp()
}
} catch (e) {
console.log(e)
creationLoading = false
@ -127,8 +147,15 @@
<SplitPage>
{#if stage === "name"}
<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}
<div class="spinner">
<div class="centered">
<Spinner />
</div>
{:else if stage === "data"}
@ -174,8 +201,13 @@
<DatasourceConfigPanel
title={plusIntegrations[stage].friendlyName}
fields={plusIntegrations[stage].datasource}
type={stage}
onBack={() => (stage = "data")}
onNext={data => handleCreateApp({ datasourceConfig: data })}
onNext={data => {
const isGoogle = data.isGoogle
delete data.isGoogle
return handleCreateApp({ datasourceConfig: data, isGoogle })
}}
/>
{:else}
<p>There was an problem. Please refresh the page and try again.</p>
@ -186,7 +218,7 @@
</SplitPage>
<style>
.spinner {
.centered {
display: flex;
justify-content: center;
align-items: center;

View File

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