Skip to content

Commit

Permalink
Add Salesforce plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Sakib25800 committed Nov 29, 2024
1 parent be95dcd commit 8b68c63
Show file tree
Hide file tree
Showing 57 changed files with 5,357 additions and 58 deletions.
1,197 changes: 1,139 additions & 58 deletions package-lock.json

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions plugins/salesforce/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies

/node_modules
/.pnp
.pnp.js
.yarn

# misc

.DS_Store
\*.pem

# files

my-plugin
dev-plugin
dist

# debug

npm-debug.log*
yarn-debug.log*
yarn-error.log\*

# local env files

.env\*.local

# Packed plugin

plugin.zip
19 changes: 19 additions & 0 deletions plugins/salesforce/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Framer Plugin Template

This is a template for using the Framer Plugin API in a TypeScript project.

## Quickstart

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Learn more: https://www.framer.com/developers/plugins/introduction
25 changes: 25 additions & 0 deletions plugins/salesforce/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import js from "@eslint/js"
import globals from "globals"
import reactHooks from "eslint-plugin-react-hooks"
import reactRefresh from "eslint-plugin-react-refresh"
import tseslint from "typescript-eslint"

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2022,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
},
}
)
6 changes: 6 additions & 0 deletions plugins/salesforce/framer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "0fb97d",
"name": "Salesforce",
"modes": ["canvas", "configureManagedCollection", "syncManagedCollection"],
"icon": "/salesforce.svg"
}
14 changes: 14 additions & 0 deletions plugins/salesforce/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Salesforce</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

43 changes: 43 additions & 0 deletions plugins/salesforce/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "salesforce",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"pack": "npx framer-plugin-tools@latest pack"
},
"dependencies": {
"@tanstack/react-query": "^5.59.20",
"classnames": "^2.5.1",
"framer-motion": "^11.11.11",
"framer-plugin": "^2.0.4",
"react": "^18",
"react-dom": "^18",
"react-error-boundary": "^4.1.2",
"usehooks-ts": "^3.1.0",
"vite-plugin-mkcert": "^1",
"wouter": "^3.3.5"
},
"devDependencies": {
"@eslint/js": "^9",
"@types/react": "^18",
"@types/react-dom": "^18",
"@vitejs/plugin-react": "^4.3.1",
"@vitejs/plugin-react-swc": "^3",
"autoprefixer": "^10.4.20",
"eslint": "^9.9.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.14",
"typescript": "^5.3",
"typescript-eslint": "^8.0.1",
"vite": "^5",
"vite-plugin-framer": "^1"
}
}
6 changes: 6 additions & 0 deletions plugins/salesforce/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
4 changes: 4 additions & 0 deletions plugins/salesforce/public/salesforce.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
211 changes: 211 additions & 0 deletions plugins/salesforce/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { framer } from "framer-plugin"
import { useEffect, useState } from "react"
import { useLocation } from "wouter"
import { Router, Route } from "./router"
import { getPluginContext, PluginContext, shouldSyncImmediately, syncAllRecords } from "./cms"
import { assert } from "./utils"
import auth from "./auth"
import {
Account,
AccountEngagementForms,
AccountEngagementFormHandlers,
Auth,
BusinessUnitId,
Messaging,
Sync,
Menu,
ObjectSearch,
Tracking,
TrackingMID,
WebForm,
WebFormFields,
DomainConnection,
} from "./pages"

const routes: Route[] = [
{
path: "/",
element: Auth,
},
{
path: "/business-unit-id",
element: BusinessUnitId,
},
{
path: "/menu",
element: Menu,
size: {
height: 530,
},
},
{
path: "/account",
element: Account,
title: "Account",
size: {
height: 459,
},
children: [
{
path: "/domain-connection",
element: DomainConnection,
title: "Domain Connection",
size: {
height: 190,
},
},
],
},
{
path: "/messaging",
element: Messaging,
title: "Messaging",
size: {
height: 361,
},
},
{
path: "/web-form",
element: WebForm,
title: () => `${history.state.title} Form`,
size: {
height: 233,
},
children: [
{
path: "/fields",
element: WebFormFields,
title: () => `${history.state.title} Fields`,
size: {
height: 387,
},
},
],
},
{
path: "/account-engagement-forms",
title: "Account Engagement Forms",
element: AccountEngagementForms,
children: [
{
path: "/handlers",
element: AccountEngagementFormHandlers,
title: "Form Handlers",
},
],
},
{
path: "/object-search",
element: ObjectSearch,
title: () => history.state?.title,
size: {
height: 400,
},
},
{
path: "/tracking",
title: "Tracking",
element: Tracking,
size: {
height: 170,
},
children: [
{
path: "/mid",
element: TrackingMID,
title: "Tracking MID",
size: {
height: 215,
},
},
],
},
{
path: "/sync",
element: Sync,
size: {
width: 340,
height: 425,
},
},
]

export function App() {
const [, navigate] = useLocation()
const [isLoading, setIsLoading] = useState(true)
const [pluginContext, setPluginContext] = useState<PluginContext | null>(null)

const isAuthenticated = auth.isAuthenticated()

useEffect(() => {
const mode = framer.mode
const isInCMSModes = mode === "syncManagedCollection" || mode === "configureManagedCollection"

async function handleCMSModes() {
const context = await getPluginContext()
const shouldSync = shouldSyncImmediately(context) && mode === "syncManagedCollection"

setPluginContext(context)

if (context.type === "update") {
const { objectId, objectLabel, includedFieldIds, collectionFields, slugFieldId, fieldConfigs } = context

if (shouldSync) {
assert(slugFieldId)

return syncAllRecords({
objectId,
objectLabel,
fields: collectionFields,
includedFieldIds,
slugFieldId,
fieldConfigs,
onProgress: () => {
// TODO: Progress indicator.
},
}).then(() => framer.closePlugin())
}

// Manage collection
navigate(`/sync?objectName=${objectId}&objectLabel=${objectLabel}`)
return
}

// Create collection
navigate("/object-search?redirect=/sync")
}

async function getContext() {
if (!isAuthenticated) {
navigate("/")
return
}

if (isInCMSModes) {
return handleCMSModes()
}

const businessUnitId = auth.getBusinessUnitId()

// Authenticated but has not completed the setup
if (businessUnitId === null) {
navigate("/business-unit-id")
return
}

navigate("/menu")
}

getContext()
.then(() => setIsLoading(false))
.catch(e => framer.closePlugin(e instanceof Error ? e.message : "Unknown error", { variant: "error" }))
}, [isAuthenticated, navigate])

if (isLoading) return null

return (
<div className="w-full h-full">
<Router routes={routes} pluginContext={pluginContext} />
</div>
)
}
15 changes: 15 additions & 0 deletions plugins/salesforce/src/PluginError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type ErrorType = "auth"

export class PluginError extends Error {
title: string
type?: ErrorType

constructor(title: string, message: string, type?: ErrorType) {
super(message)

Object.setPrototypeOf(this, PluginError.prototype)

this.title = title
this.type = type
}
}
Loading

0 comments on commit 8b68c63

Please sign in to comment.