Skip to content

Commit

Permalink
feat (gocardless): Handle changes for Gocardless integration (#523)
Browse files Browse the repository at this point in the history
* add base gocardless setup

* add gocardless details page

* update gcl details page

* finalise gcl details page with mutation that creates access token

* remove createCustomer property from organisation level

* update graphql.tsx

* update create/update customers form

* add webhook secret key support in integrations section

* fix helper text below payment provider field

* apply several smaller fixes

* fix translations

* fix linter issues

* use env variable for lago proxy

* fix jest file

* fix oauth proxy url

* fix env var usage

* update api keys developer page

* fix ApiKey page

Co-authored-by: Jeremy Denquin <[email protected]>
  • Loading branch information
lovrocolic and jdenquin committed Nov 17, 2022
1 parent 410fc54 commit 708e912
Show file tree
Hide file tree
Showing 21 changed files with 706 additions and 180 deletions.
2 changes: 2 additions & 0 deletions .env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ touch ./env-config.js

api_url_value=$(echo $API_URL)
app_env_value=$(echo $APP_ENV)
lago_oauth_proxy_url_value=$(echo $LAGO_OAUTH_PROXY_URL)
lago_disable_signup_value=$(echo $LAGO_DISABLE_SIGNUP)

echo "window.API_URL = \"$api_url_value\"" >> ./env-config.js
echo "window.APP_ENV = \"$app_env_value\"" >> ./env-config.js
echo "window.LAGO_OAUTH_PROXY_URL = \"$lago_oauth_proxy_url_value\"" >> ./env-config.js
echo "window.LAGO_DISABLE_SIGNUP = \"$lago_disable_signup_value\"" >> ./env-config.js
1 change: 1 addition & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ module.exports = {
APP_ENV: JSON.stringify('production'),
API_URL: JSON.stringify(process.env.API_URL),
LAGO_DISABLE_SIGNUP: process.env.LAGO_DISABLE_SIGNUP,
LAGO_OAUTH_PROXY_URL: process.env.LAGO_OAUTH_PROXY_URL,
APP_VERSION: JSON.stringify('0.0'),
})
)
Expand Down
29 changes: 24 additions & 5 deletions ditto/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,30 @@
"text_6304e74aab6dbc18d615f416": "{{lastRowFirstUnit}} x {{lastRowPerUnit}} + {{lastRowFlatFee}} = {{value}}",
"text_6304e74aab6dbc18d615f421": "Delete tier",
"text_6304e74aab6dbc18d615f420": "This tier overlap with another one, please put a value upper than {{value}}",
"text_634ea0ecc6147de10ddb6625": "GoCardless",
"text_634ea0ecc6147de10ddb6629": "GoCardless",
"text_634ea0ecc6147de10ddb662d": "Connected",
"text_634ea0ecc6147de10ddb6631": "Payment provider",
"text_634ea0ecc6147de10ddb6635": "Connection settings",
"text_635bd8acb686f18909a57c87": "Reconnect",
"text_634ea0ecc6147de10ddb663d": "OAuth connection",
"text_634ea0ecc6147de10ddb6641": "Lago is connected to GoCardless via an OAuth connection. From Lago, you can only reconnect the two apps, to remove this connection, please do it in GoCardless.",
"text_635bd8acb686f18909a57c89": "Secret key",
"text_635bd8acb686f18909a57c8d": "Secret key",
"text_635bd8acb686f18909a57c93": "Use this secret key to setup webhooks in GoCardless",
"text_634ea0ecc6147de10ddb6645": "GoCardless successfully connected",
"text_634ea0ecc6147de10ddb6643": "Payment provider",
"text_634ea0ecc6147de10ddb6646": "Connected",
"text_634ea0ecc6147de10ddb6648": "GoCardless",
"text_635bdbda84c98758f9bba8a0": "Connect Payment service provider in the <a href=\"{{link}}\">Integrations section</a>",
"text_635bdbda84c98758f9bba8aa": "Create automatically this customer in GoCardless",
"text_635bdbda84c98758f9bba8ae": "To create a customer in GoCardless, you must fill in an email address",
"text_635bdbda84c98758f9bba89e": "Create automatically this customer in Stripe",
"text_6360ddae753a8b3e11c80c66": "Copy text",
"text_6360ddae753a8b3e11c80c6c": "Secret key copied to clipboard",
"text_636df520279a9e1b3c68cc67": "API keys & ID",
"text_636df520279a9e1b3c68cc75": "Organization ID",
"text_636df520279a9e1b3c68cc7d": "Organization ID copy to clipboard",
"text_6295e58352f39200d902b01c": "Documentation",
"text_6295e58352f39200d902b02a": "Apply add-on",
"text_629781ec7c6c1500d94fbb00": "Apply an add-on to this customer",
Expand Down Expand Up @@ -649,10 +673,6 @@
"text_62b1edddbf5f461ab971275b": "API secret key",
"text_62b1edddbf5f461ab9712787": "Edit",
"text_62b1edddbf5f461ab971279f": "Delete",
"text_62b1edddbf5f461ab97127b4": "Other settings",
"text_62b1edddbf5f461ab97127c8": "Create Lago customers in Stripe",
"text_62b1edddbf5f461ab97127d8": "By switching on, customers from Lago will automatically be created in Stripe",
"text_62b1edddbf5f461ab9712819": "Settings successfully updated",
"text_62b1edddbf5f461ab971272d": "Edit Stripe API secret key",
"text_62b1edddbf5f461ab9712737": "By editing the API secret key, upcoming data will not be synchronised to the connected Stripe account.",
"text_62b1edddbf5f461ab9712754": "Type a new API secret key",
Expand Down Expand Up @@ -965,7 +985,6 @@
"text_62bb10ad2a10bd182d002077": "Invoice template information saved",
"text_6271200984178801ba8bdeac": "Developers",
"text_6271200984178801ba8bdebe": "Developers",
"text_6271200984178801ba8bdeca": "API keys",
"text_6271200984178801ba8bdede": "Webhooks",
"text_6271200984178801ba8bdef2": "Webhooks",
"text_6271200984178801ba8bdf06": "Provide real-time information to other applications",
Expand Down
2 changes: 2 additions & 0 deletions ditto/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,7 @@ projects:
id: 634687058efb4a10996fdbdc
- name: '⚙️ [WIP] - B.Metrics and Plans - Dimension'
id: 633b622919283cdbfb2f7233
- name: "\U0001F44D [Ready for dev] - Settings - Customers - Lago gocardless connection"
id: 634ea0e94c99df2bb59820d9
format: flat
variants: true
3 changes: 3 additions & 0 deletions ditto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,8 @@ module.exports = {
},
"project_6304e74718860633c15905f2": {
"base": require('./👍 [Ready for dev] - Plans - Add Volume in charge model__base.json')
},
"project_634ea0e94c99df2bb59820d9": {
"base": require('./👍 [Ready for dev] - Settings - Customers - Lago gocardless connection__base.json')
}
}
1 change: 1 addition & 0 deletions globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ declare type AppEnvEnum = import('./src/globalTypes').AppEnvEnum
declare var APP_ENV: AppEnvEnum
declare var API_URL: string;
declare var APP_VERSION: string;
declare var LAGO_OAUTH_PROXY_URL: string;
declare var LAGO_DISABLE_SIGNUP: string;

declare module "*.svg" {
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ module.exports = {
API_URL: 'http://localhost:3000',
APP_VERSION: '1.0.0',
IS_REACT_ACT_ENVIRONMENT: true,
LAGO_OAUTH_PROXY_URL: 'https://proxy.lago.dev',
LAGO_DISABLE_SIGNUP: 'false',
},
}
72 changes: 58 additions & 14 deletions src/components/customers/AddCustomerDrawer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { forwardRef, useEffect, RefObject } from 'react'
import { forwardRef, useEffect, useState, RefObject } from 'react'
import styled from 'styled-components'
import { useFormik } from 'formik'
import { object, string } from 'yup'

import { Drawer, Button, DrawerRef, Typography, Accordion } from '~/components/designSystem'
import { TextInputField, ComboBoxField } from '~/components/form'
import { Drawer, Button, DrawerRef, Typography, Accordion, Alert } from '~/components/designSystem'
import { TextInputField, ComboBoxField, Checkbox } from '~/components/form'
import { useInternationalization } from '~/hooks/core/useInternationalization'
import { hasDefinedGQLError } from '~/core/apolloClient'
import { theme, Card, DrawerTitle, DrawerContent, DrawerSubmitButton } from '~/styles'
Expand All @@ -18,6 +18,7 @@ import {
} from '~/generated/graphql'
import { useCreateEditCustomer } from '~/hooks/useCreateEditCustomer'
import CountryCodes from '~/public/countryCode.json'
import { INTEGRATIONS_ROUTE } from '~/core/router'

const countryData: { value: string; label: string }[] = Object.keys(CountryCodes).map(
(countryKey) => {
Expand Down Expand Up @@ -49,6 +50,7 @@ export const AddCustomerDrawer = forwardRef<DrawerRef, AddCustomerDrawerProps>(
const { isEdition, onSave } = useCreateEditCustomer({
customer,
})
const [isDisabled, setIsDisabled] = useState<boolean>(false)
const formikProps = useFormik<CreateCustomerInput | UpdateCustomerInput>({
initialValues: {
name: customer?.name ?? '',
Expand All @@ -64,8 +66,9 @@ export const AddCustomerDrawer = forwardRef<DrawerRef, AddCustomerDrawerProps>(
country: customer?.country ?? undefined,
city: customer?.city ?? undefined,
zipcode: customer?.zipcode ?? undefined,
stripeCustomer: {
providerCustomerId: customer?.stripeCustomer?.providerCustomerId ?? undefined,
providerCustomer: {
providerCustomerId: customer?.providerCustomer?.providerCustomerId ?? undefined,
syncWithProvider: customer?.providerCustomer?.syncWithProvider ?? false,
},
paymentProvider: customer?.paymentProvider ?? undefined,
},
Expand All @@ -91,7 +94,8 @@ export const AddCustomerDrawer = forwardRef<DrawerRef, AddCustomerDrawerProps>(
useEffect(() => {
if (!formikProps.values.paymentProvider) {
// If no payment provider, reset stripe customer
formikProps.setFieldValue('stripeCustomer.providerCustomerId', undefined)
formikProps.setFieldValue('providerCustomer.providerCustomerId', undefined)
formikProps.setFieldValue('providerCustomer.syncWithProvider', false)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [formikProps.values.paymentProvider])
Expand Down Expand Up @@ -125,8 +129,9 @@ export const AddCustomerDrawer = forwardRef<DrawerRef, AddCustomerDrawerProps>(
country: customer?.country ?? undefined,
city: customer?.city ?? undefined,
zipcode: customer?.zipcode ?? undefined,
stripeCustomer: {
providerCustomerId: customer?.stripeCustomer?.providerCustomerId ?? undefined,
providerCustomer: {
providerCustomerId: customer?.providerCustomer?.providerCustomerId ?? undefined,
syncWithProvider: customer?.providerCustomer?.syncWithProvider ?? false,
},
paymentProvider: customer?.paymentProvider ?? undefined,
},
Expand Down Expand Up @@ -276,14 +281,48 @@ export const AddCustomerDrawer = forwardRef<DrawerRef, AddCustomerDrawerProps>(
label={translate('text_62b328ead9a4caef81cd9c9c')}
placeholder={translate('text_62b328ead9a4caef81cd9c9e')}
formikProps={formikProps}
helperText={
!isEdition && (
<HelperText
html={translate('text_635bdbda84c98758f9bba8a0', {
link: INTEGRATIONS_ROUTE,
})}
/>
)
}
PopperProps={{ displayInDialog: true }}
/>
<TextInputField
name="stripeCustomer.providerCustomerId"
label={translate('text_62b328ead9a4caef81cd9ca0')}
placeholder={translate('text_62b328ead9a4caef81cd9ca2')}
formikProps={formikProps}
/>
{(formikProps.values.paymentProvider === ProviderTypeEnum.Gocardless ||
formikProps.values.paymentProvider === ProviderTypeEnum.Stripe) && (
<>
<TextInputField
name="providerCustomer.providerCustomerId"
disabled={isDisabled}
label={translate('text_62b328ead9a4caef81cd9ca0')}
placeholder={translate('text_62b328ead9a4caef81cd9ca2')}
formikProps={formikProps}
/>
<Checkbox
name="providerCustomer.syncWithProvider"
value={formikProps.values.providerCustomer?.syncWithProvider}
label={
formikProps.values.paymentProvider === ProviderTypeEnum.Gocardless
? translate('text_635bdbda84c98758f9bba8aa')
: translate('text_635bdbda84c98758f9bba89e')
}
onChange={(_, checked) => {
setIsDisabled(checked)
formikProps.setFieldValue('providerCustomer.syncWithProvider', checked)
if (!isEdition && checked) {
formikProps.setFieldValue('providerCustomer.providerCustomerId', undefined)
}
}}
/>
</>
)}
{isDisabled && formikProps.values.paymentProvider === ProviderTypeEnum.Gocardless && (
<Alert type="info">{translate('text_635bdbda84c98758f9bba8ae')}</Alert>
)}
</BillingBlock>
</Accordion>

Expand All @@ -307,6 +346,11 @@ export const AddCustomerDrawer = forwardRef<DrawerRef, AddCustomerDrawerProps>(
}
)

const HelperText = styled(Typography)`
font-size: 14px;
line-height: 20px;
`

const BillingBlock = styled.div<{ $first?: boolean }>`
margin-bottom: ${({ $first }) => ($first ? theme.spacing(6) : 0)};
Expand Down
16 changes: 12 additions & 4 deletions src/components/customers/CustomerMainInfos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ gql`
city
zipcode
paymentProvider
stripeCustomer {
providerCustomer {
id
providerCustomerId
}
Expand Down Expand Up @@ -74,7 +74,7 @@ export const CustomerMainInfos = ({ loading, customer, onEdit }: CustomerMainInf
city,
zipcode,
paymentProvider,
stripeCustomer,
providerCustomer,
} = customer

return (
Expand Down Expand Up @@ -146,10 +146,18 @@ export const CustomerMainInfos = ({ loading, customer, onEdit }: CustomerMainInf
</Typography>
</div>
)}
{!!stripeCustomer && !!stripeCustomer?.providerCustomerId && (
{paymentProvider === ProviderTypeEnum?.Gocardless && (
<div>
<Typography variant="caption">{translate('text_62b5c912506c4905fa755248')}</Typography>
<Typography color="textSecondary">
{translate('text_634ea0ecc6147de10ddb6648')}
</Typography>
</div>
)}
{!!providerCustomer && !!providerCustomer?.providerCustomerId && (
<div>
<Typography variant="caption">{translate('text_62b5c912506c4905fa75524c')}</Typography>
<Typography color="textSecondary">{stripeCustomer?.providerCustomerId}</Typography>
<Typography color="textSecondary">{providerCustomer?.providerCustomerId}</Typography>
</div>
)}
</DetailsBlock>
Expand Down
2 changes: 2 additions & 0 deletions src/core/apolloClient/reactiveVars/envGlobalVar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { AppEnvEnum } from '~/globalTypes'
interface EnvGlobal {
appEnv: AppEnvEnum
apiUrl: string
lagoOauthProxyUrl: string
disableSignUp: boolean
appVersion: string
}

export const envGlobalVar = makeVar<EnvGlobal>({
appEnv: window.APP_ENV || APP_ENV,
apiUrl: window.API_URL || API_URL,
lagoOauthProxyUrl: window.LAGO_OAUTH_PROXY_URL || LAGO_OAUTH_PROXY_URL,
disableSignUp: (window.LAGO_DISABLE_SIGNUP || LAGO_DISABLE_SIGNUP) === 'true',
appVersion: APP_VERSION,
})
12 changes: 12 additions & 0 deletions src/core/router/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ const Integrations = lazy(
const StripeIntegration = lazy(
() => import(/* webpackChunkName: 'stripe-integration' */ '~/pages/settings/StripeIntegration')
)
const GocardlessIntegration = lazy(
() =>
import(
/* webpackChunkName: 'gocardless-integration' */ '~/pages/settings/GocardlessIntegration'
)
)
const Members = lazy(() => import(/* webpackChunkName: 'members' */ '~/pages/settings/Members'))

const BillableMetricsList = lazy(
Expand Down Expand Up @@ -134,6 +140,7 @@ export const VAT_RATE_ROUTE = `${SETTINGS_ROUTE}/tax-rate`
export const ORGANIZATION_INFORMATIONS_ROUTE = `${SETTINGS_ROUTE}/organization-informations`
export const INTEGRATIONS_ROUTE = `${SETTINGS_ROUTE}/integrations`
export const STRIPE_INTEGRATION_ROUTE = `${SETTINGS_ROUTE}/integrations/stripe`
export const GOCARDLESS_INTEGRATION_ROUTE = `${SETTINGS_ROUTE}/integrations/gocardless`
export const MEMBERS_ROUTE = `${SETTINGS_ROUTE}/members`

// *********************** Route Available only on dev mode
Expand Down Expand Up @@ -214,6 +221,11 @@ export const routes: CustomRouteObject[] = [
private: true,
element: <StripeIntegration />,
},
{
path: GOCARDLESS_INTEGRATION_ROUTE,
private: true,
element: <GocardlessIntegration />,
},
{
path: PLANS_ROUTE,
private: true,
Expand Down
Loading

0 comments on commit 708e912

Please sign in to comment.