♻️ (builder) Change to features-centric folder structure
This commit is contained in:
committed by
Baptiste Arnaud
parent
3686465a85
commit
643571fe7d
52
apps/builder/src/lib/googleSheets.ts
Normal file
52
apps/builder/src/lib/googleSheets.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Credentials as CredentialsFromDb } from 'db'
|
||||
import { OAuth2Client, Credentials } from 'google-auth-library'
|
||||
import { GoogleSheetsCredentialsData } from 'models'
|
||||
import { isDefined } from 'utils'
|
||||
import { decrypt, encrypt } from 'utils/api'
|
||||
import prisma from './prisma'
|
||||
|
||||
export const oauth2Client = new OAuth2Client(
|
||||
process.env.GOOGLE_CLIENT_ID,
|
||||
process.env.GOOGLE_CLIENT_SECRET,
|
||||
`${process.env.NEXTAUTH_URL}/api/credentials/google-sheets/callback`
|
||||
)
|
||||
|
||||
export const getAuthenticatedGoogleClient = async (
|
||||
userId: string,
|
||||
credentialsId: string
|
||||
): Promise<
|
||||
{ client: OAuth2Client; credentials: CredentialsFromDb } | undefined
|
||||
> => {
|
||||
const credentials = (await prisma.credentials.findFirst({
|
||||
where: { id: credentialsId, workspace: { members: { some: { userId } } } },
|
||||
})) as CredentialsFromDb | undefined
|
||||
if (!credentials) return
|
||||
const data = decrypt(
|
||||
credentials.data,
|
||||
credentials.iv
|
||||
) as GoogleSheetsCredentialsData
|
||||
|
||||
oauth2Client.setCredentials(data)
|
||||
oauth2Client.on('tokens', updateTokens(credentialsId, data))
|
||||
return { client: oauth2Client, credentials }
|
||||
}
|
||||
|
||||
const updateTokens =
|
||||
(credentialsId: string, existingCredentials: GoogleSheetsCredentialsData) =>
|
||||
async (credentials: Credentials) => {
|
||||
if (
|
||||
isDefined(existingCredentials.id_token) &&
|
||||
credentials.id_token !== existingCredentials.id_token
|
||||
)
|
||||
return
|
||||
const newCredentials: GoogleSheetsCredentialsData = {
|
||||
...existingCredentials,
|
||||
expiry_date: credentials.expiry_date,
|
||||
access_token: credentials.access_token,
|
||||
}
|
||||
const { encryptedData, iv } = encrypt(newCredentials)
|
||||
await prisma.credentials.update({
|
||||
where: { id: credentialsId },
|
||||
data: { data: encryptedData, iv },
|
||||
})
|
||||
}
|
||||
47
apps/builder/src/lib/plate.tsx
Normal file
47
apps/builder/src/lib/plate.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
createBoldPlugin,
|
||||
createItalicPlugin,
|
||||
createUnderlinePlugin,
|
||||
} from '@udecode/plate-basic-marks'
|
||||
import { createPlugins } from '@udecode/plate-core'
|
||||
import { createLinkPlugin, ELEMENT_LINK } from '@udecode/plate-link'
|
||||
import { PlateFloatingLink } from '@udecode/plate-ui-link'
|
||||
|
||||
export const editorStyle: React.CSSProperties = {
|
||||
flex: 1,
|
||||
padding: '1rem',
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '0.25rem',
|
||||
}
|
||||
|
||||
export const platePlugins = createPlugins(
|
||||
[
|
||||
createBoldPlugin(),
|
||||
createItalicPlugin(),
|
||||
createUnderlinePlugin(),
|
||||
createLinkPlugin({
|
||||
renderAfterEditable: PlateFloatingLink,
|
||||
options: {
|
||||
isUrl: (url: string) =>
|
||||
url.startsWith('http') ||
|
||||
url.startsWith('mailto') ||
|
||||
url.startsWith('tel') ||
|
||||
url.startsWith('sms'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
{
|
||||
components: {
|
||||
[ELEMENT_LINK]: (props) => (
|
||||
<a
|
||||
href={props.element.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={props.className}
|
||||
>
|
||||
{props.children}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
}
|
||||
)
|
||||
15
apps/builder/src/lib/prisma.ts
Normal file
15
apps/builder/src/lib/prisma.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { PrismaClient } from 'db'
|
||||
|
||||
declare const global: { prisma: PrismaClient }
|
||||
let prisma: PrismaClient
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
prisma = new PrismaClient()
|
||||
} else {
|
||||
if (!global.prisma) {
|
||||
global.prisma = new PrismaClient()
|
||||
}
|
||||
prisma = global.prisma
|
||||
}
|
||||
|
||||
export default prisma
|
||||
22
apps/builder/src/lib/routerProgressBar.tsx
Normal file
22
apps/builder/src/lib/routerProgressBar.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import Router from 'next/router'
|
||||
import NProgress from 'nprogress'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export const useRouterProgressBar = () =>
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
NProgress.configure({ showSpinner: false })
|
||||
|
||||
Router.events.on('routeChangeStart', () => {
|
||||
NProgress.start()
|
||||
})
|
||||
|
||||
Router.events.on('routeChangeComplete', () => {
|
||||
NProgress.done()
|
||||
})
|
||||
|
||||
Router.events.on('routeChangeError', () => {
|
||||
NProgress.done()
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
110
apps/builder/src/lib/theme.ts
Normal file
110
apps/builder/src/lib/theme.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { extendTheme } from '@chakra-ui/react'
|
||||
|
||||
const fonts = {
|
||||
heading: 'Outfit',
|
||||
body: 'Open Sans',
|
||||
}
|
||||
|
||||
export const colors = {
|
||||
gray: {
|
||||
50: '#F9FAFB',
|
||||
100: '#F3F4F6',
|
||||
200: '#E5E7EB',
|
||||
300: '#D1D5DB',
|
||||
400: '#9CA3AF',
|
||||
500: '#6B7280',
|
||||
600: '#4B5563',
|
||||
700: '#374151',
|
||||
800: '#1F2937',
|
||||
900: '#111827',
|
||||
},
|
||||
blue: {
|
||||
50: '#e0edff',
|
||||
100: '#b0caff',
|
||||
200: '#7ea6ff',
|
||||
300: '#4b83ff',
|
||||
400: '#1a5fff',
|
||||
500: '#0042da',
|
||||
600: '#0036b4',
|
||||
700: '#002782',
|
||||
800: '#001751',
|
||||
900: '#1a202c',
|
||||
},
|
||||
orange: {
|
||||
50: '#fff1da',
|
||||
100: '#ffd7ae',
|
||||
200: '#ffbf7d',
|
||||
300: '#ffa54c',
|
||||
400: '#ff8b1a',
|
||||
500: '#e67200',
|
||||
600: '#b45800',
|
||||
700: '#813e00',
|
||||
800: '#4f2500',
|
||||
900: '#200b00',
|
||||
},
|
||||
yellow: {
|
||||
50: '#fff9da',
|
||||
100: '#ffedad',
|
||||
200: '#ffe17d',
|
||||
300: '#ffd54b',
|
||||
400: '#ffc91a',
|
||||
500: '#e6b000',
|
||||
600: '#b38800',
|
||||
700: '#806200',
|
||||
800: '#4e3a00',
|
||||
900: '#1d1400',
|
||||
},
|
||||
}
|
||||
|
||||
const components = {
|
||||
Spinner: {
|
||||
defaultProps: {
|
||||
colorScheme: 'blue',
|
||||
},
|
||||
},
|
||||
NumberInput: {
|
||||
defaultProps: {
|
||||
focusBorderColor: 'blue.200',
|
||||
},
|
||||
},
|
||||
Input: {
|
||||
defaultProps: {
|
||||
focusBorderColor: 'blue.200',
|
||||
},
|
||||
},
|
||||
Textarea: {
|
||||
defaultProps: {
|
||||
focusBorderColor: 'blue.200',
|
||||
},
|
||||
},
|
||||
Popover: {
|
||||
baseStyle: {
|
||||
popper: {
|
||||
width: 'fit-content',
|
||||
maxWidth: 'fit-content',
|
||||
},
|
||||
},
|
||||
},
|
||||
Link: {
|
||||
baseStyle: {
|
||||
_hover: { textDecoration: 'none' },
|
||||
},
|
||||
},
|
||||
Menu: {
|
||||
parts: ['list'],
|
||||
defaultProps: {
|
||||
list: {
|
||||
shadow: 'lg',
|
||||
},
|
||||
},
|
||||
},
|
||||
Tooltip: {
|
||||
defaultProps: {
|
||||
rounded: 'md',
|
||||
hasArrow: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const customTheme: any = extendTheme({ colors, fonts, components })
|
||||
Reference in New Issue
Block a user