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:
parent
0257617ba1
commit
32c78ec9bf
|
@ -162,10 +162,7 @@ export async function getGoogleConfig(): Promise<
|
||||||
export async function getGoogleDatasourceConfig(): Promise<
|
export async function getGoogleDatasourceConfig(): Promise<
|
||||||
GoogleInnerConfig | undefined
|
GoogleInnerConfig | undefined
|
||||||
> {
|
> {
|
||||||
if (!env.isDev() && !env.SELF_HOSTED) {
|
return getDefaultGoogleConfig()
|
||||||
// always use the env vars in cloud
|
|
||||||
return getDefaultGoogleConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer the config in self-host
|
// prefer the config in self-host
|
||||||
let config = await getGoogleConfig()
|
let config = await getGoogleConfig()
|
||||||
|
@ -179,13 +176,14 @@ export async function getGoogleDatasourceConfig(): Promise<
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDefaultGoogleConfig(): GoogleInnerConfig | undefined {
|
export function getDefaultGoogleConfig(): GoogleInnerConfig | undefined {
|
||||||
if (environment.GOOGLE_CLIENT_ID && environment.GOOGLE_CLIENT_SECRET) {
|
//if (environment.GOOGLE_CLIENT_ID && environment.GOOGLE_CLIENT_SECRET) {
|
||||||
return {
|
return {
|
||||||
clientID: environment.GOOGLE_CLIENT_ID!,
|
clientID:
|
||||||
clientSecret: environment.GOOGLE_CLIENT_SECRET!,
|
"77746844610-62k43m9b4so4gcmf6ibs7p3l7jv81rug.apps.googleusercontent.com",
|
||||||
activated: true,
|
clientSecret: "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",
|
||||||
}
|
activated: true,
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDC
|
// OIDC
|
||||||
|
|
|
@ -13,6 +13,7 @@ type Passport = {
|
||||||
|
|
||||||
async function fetchGoogleCreds() {
|
async function fetchGoogleCreds() {
|
||||||
let config = await configs.getGoogleDatasourceConfig()
|
let config = await configs.getGoogleDatasourceConfig()
|
||||||
|
console.log(config)
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new Error("No google configuration found")
|
throw new Error("No google configuration found")
|
||||||
|
@ -78,17 +79,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)
|
||||||
|
|
|
@ -5,18 +5,26 @@
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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 +34,10 @@
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 195px;
|
width: 195px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
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"
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
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,12 @@
|
||||||
|
|
||||||
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()
|
||||||
|
$: cloudHosted = $admin.cloud
|
||||||
|
|
||||||
const createApp = async useSampleData => {
|
const createApp = async useSampleData => {
|
||||||
creationLoading = true
|
creationLoading = true
|
||||||
|
@ -62,6 +65,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 +78,10 @@
|
||||||
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) && !cloudHosted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (schema?.plus) {
|
if (schema?.plus) {
|
||||||
newPlusIntegrations[integrationType] = schema
|
newPlusIntegrations[integrationType] = schema
|
||||||
}
|
}
|
||||||
|
@ -92,12 +100,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 +120,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 +147,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 +201,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 +218,7 @@
|
||||||
</SplitPage>
|
</SplitPage>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.spinner {
|
.centered {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -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> = {}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./helpers"
|
||||||
|
export * from "./integrations"
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { SourceName } from "@budibase/types"
|
||||||
|
|
||||||
|
export function isGoogleSheets(type: SourceName) {
|
||||||
|
return type === SourceName.GOOGLE_SHEETS
|
||||||
|
}
|
Loading…
Reference in New Issue