Skip to content

Commit

Permalink
bunch of changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Sakib25800 committed Nov 29, 2024
1 parent b1bd42d commit da97a92
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 61 deletions.
74 changes: 41 additions & 33 deletions plugins/salesforce/src/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import auth from "./auth"
import { API_URL } from "./constants"
import { BACKEND_URL } from "./constants"
import { PluginError } from "./PluginError"

/**
Expand Down Expand Up @@ -214,7 +214,7 @@ export const request = async <T = unknown>(
if (!businessUnitId) {
throw new PluginError(
"Access Denied",
"You do not have access to the Salesforce Account Engagement feature."
"You have not set your Business Unit ID. Please logout and add it."
)
}

Expand Down Expand Up @@ -478,36 +478,6 @@ export const useObjectsQuery = () => {
})
}

/**
* Retrieve or generate a webhook endpoint to create/update a new
* Salesforce object
*/
export const useWebFormWebhookQuery = (objectName: string) => {
return useQuery<NewForm>({
queryKey: ["web-form-webhook", objectName],
enabled: !!objectName,
queryFn: async () => {
const tokens = auth.tokens.getOrThrow()
const res = await fetch(`${API_URL}/api/forms/web/create`, {
method: "POST",
body: JSON.stringify({ objectName }),
headers: {
Authorization: `Bearer ${tokens.accessToken}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})

if (!res.ok) {
const data: FramerSalesforceAPIErrorResponse = await res.json()
throw new PluginError("Webhook Creation Failed", data.error.message)
}

return res.json()
},
})
}

/**
* Retrieve all messaging for web embedded services
*/
Expand All @@ -516,7 +486,7 @@ export const useMessagingEmbeddedServices = () => {
queryKey: ["embedded-services"],
queryFn: () => {
// IsFieldServiceEnabled=True indicates 'Appointment Embed' - we ignore that as we
// only want 'Messaging for In-App and Web'
// only want 'Messaging for In-App and Web' embeds
return request<SFQueryResult<EmbeddedService>>({
path: "/query",
query: {
Expand Down Expand Up @@ -604,3 +574,41 @@ export const useAccountEngagementForms = () => {
select: data => data.values,
})
}

/**
* Retrieve or generate a webhook endpoint to create/update a new
* Salesforce object
*/
export const useWebFormWebhookQuery = (objectName: string) => {
return useQuery<NewForm>({
queryKey: ["web-form-webhook", objectName],
enabled: !!objectName,
queryFn: async () => {
const tokens = auth.tokens.getOrThrow()
const res = await fetch(`${BACKEND_URL}/api/forms/web/create`, {
method: "POST",
body: JSON.stringify({ objectName }),
headers: {
Authorization: `Bearer ${tokens.accessToken}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})

if (!res.ok) {
const data: FramerSalesforceAPIErrorResponse = await res.json()
throw new PluginError("Webhook Creation Failed", data.error.message)
}

return res.json()
},
})
}

export const useLogoutMutation = ({ onSuccess, onError }: { onSuccess?: () => void; onError?: (e: Error) => void }) => {
return useMutation({
mutationFn: () => auth.logout(),
onSuccess,
onError,
})
}
20 changes: 13 additions & 7 deletions plugins/salesforce/src/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { API_URL, BUSINESS_UNIT_ID_KEY } from "./constants"
import { FramerSalesforceAPIErrorResponse } from "./api"
import { BACKEND_URL, BUSINESS_UNIT_ID_KEY } from "./constants"
import { PluginError } from "./PluginError"

export interface Tokens {
Expand Down Expand Up @@ -36,7 +37,7 @@ class Auth {
try {
const tokens = this.tokens.getOrThrow()

const res = await fetch(`${API_URL}/auth/refresh?code=${tokens.refreshToken}`, {
const res = await fetch(`${BACKEND_URL}/auth/refresh?code=${tokens.refreshToken}`, {
method: "POST",
})

Expand All @@ -55,7 +56,7 @@ class Auth {
}

async fetchTokens(readKey: string) {
const res = await fetch(`${API_URL}/auth/poll?readKey=${readKey}`, {
const res = await fetch(`${BACKEND_URL}/auth/poll?readKey=${readKey}`, {
method: "POST",
})

Expand All @@ -71,7 +72,7 @@ class Auth {
}

async authorize() {
const response = await fetch(`${API_URL}/auth/authorize`, {
const response = await fetch(`${BACKEND_URL}/auth/authorize`, {
method: "POST",
})

Expand All @@ -85,12 +86,17 @@ class Auth {
}

async logout() {
const response = await fetch(`${API_URL}/auth/logout`, {
const tokens = this.tokens.getOrThrow()
const res = await fetch(`${BACKEND_URL}/auth/logout`, {
method: "POST",
headers: {
Authorization: `Bearer ${tokens.accessToken}`,
},
})

if (response.status !== 200) {
throw new PluginError("Auth Error", "Failed to logout.")
if (res.status !== 200) {
const data: FramerSalesforceAPIErrorResponse = await res.json()
throw new PluginError("Auth Error", data.error.message)
}

this.tokens.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ export const PageErrorBoundaryFallback = ({ children }: PropsWithChildren) => (
className="text-framer-blue"
onClick={async e => {
e.preventDefault()
auth.logout().then(() => framer.closePlugin())
auth.logout()
.then(() => framer.closePlugin())
.catch(e =>
framer.notify(e instanceof Error ? e.message : JSON.stringify(e))
)
}}
>
logout
Expand Down
8 changes: 3 additions & 5 deletions plugins/salesforce/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
const isLocal = () => window.location.hostname.includes("localhost")

export const API_URL = isLocal()
? "https://framer-salesforce-api.sakibulislam25800.workers.dev"
: "https://localhost:8787"
export const BACKEND_URL = window.location.hostname.includes("localhost")
? "https://localhost:8787"
: "https://framer-salesforce-api.sakibulislam25800.workers.dev"

export const BUSINESS_UNIT_ID_KEY = "businessUnitId"
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import auth from "@/auth"
import { CenteredSpinner } from "@/components/CenteredSpinner"
import { CopyIcon, TickIcon } from "@/components/Icons"
import { useState } from "react"
import { API_URL } from "@/constants"
import { BACKEND_URL } from "@/constants"
import { framer } from "framer-plugin"
import { Message } from "@/components/Message"

export default function AccountEngagementFormHandlers() {
const { data: handlers, isLoading } = useAccountEngagementFormHandlers()
const [copiedIndex, setCopiedIndex] = useState<number | null>(null)

const handleCopy = (handler: string, index: number) => {
navigator.clipboard.writeText(`${API_URL}/api/forms/account-engagement/forward?handler=${handler}`)
const handleCopy = async (handler: string, index: number) => {
await navigator.clipboard.writeText(`${BACKEND_URL}/api/forms/account-engagement/forward?handler=${handler}`)
framer.notify("Paste the webhook into your Framer Form webhook settings")
setCopiedIndex(index)
setTimeout(() => setCopiedIndex(null), 2000)
Expand Down
17 changes: 7 additions & 10 deletions plugins/salesforce/src/pages/account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
SFTrustedSitesList,
useCorsWhitelistMutation,
useCorsWhitelistQuery,
useLogoutMutation,
useOrgQuery,
useRemoveCorsWhitelistMutation,
useRemoveTrustedSiteMutation,
Expand Down Expand Up @@ -117,18 +118,14 @@ export default function Account() {
const { data: corsWhitelist, isLoading: isLoadingCorsWhitelist } = useCorsWhitelistQuery()
const { data: user, isLoading: isLoadingUser } = useUserQuery()
const { data: org, isLoading: isLoadingOrg } = useOrgQuery(user?.organization_id || "")
const { mutate: logout, isPending: isLoggingOut } = useLogoutMutation({
onSuccess: () => framer.closePlugin("To completely remove Framer, uninstall the app from Salesforce"),
onError: e => framer.notify(e instanceof Error ? e.message : JSON.stringify(e)),
})

const trustedSiteUrls = trustedSites?.records.map(site => site.EndpointUrl) || []
const corsWhitelistUrls = corsWhitelist?.records.map(entry => entry.UrlPattern) || []

const handleLogout = async () => {
auth.logout().then(() =>
framer.closePlugin(
"To completely remove Framer, uninstall the app from the Salesforce Setup > Installed Packages page"
)
)
}

if (isLoadingUser || isLoadingOrg) return <CenteredSpinner />

if (!user || !org) return null
Expand Down Expand Up @@ -196,9 +193,9 @@ export default function Account() {
</div>
</div>
<hr />
<button className="framer-button-destructive w-full" onClick={handleLogout}>
<Button className="w-full" variant="destructive" onClick={() => logout()} isLoading={isLoggingOut}>
Logout
</button>
</Button>
</main>
)
}
4 changes: 2 additions & 2 deletions plugins/salesforce/src/pages/web-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useWebFormWebhookQuery } from "@/api"
import { Button } from "@/components/Button"
import { InternalLink } from "@/components/Link"
import auth from "@/auth"
import { API_URL } from "@/constants"
import { BACKEND_URL } from "@/constants"
import { PluginError } from "@/PluginError"

export default function WebForm() {
Expand All @@ -31,7 +31,7 @@ export default function WebForm() {
.
</p>
<CopyInput
value={isPending ? API_URL : form?.webhook || ""}
value={isPending ? BACKEND_URL : form?.webhook || ""}
isLoading={isPending}
message="Paste the webhook into your Framer Form webhook settings"
/>
Expand Down

0 comments on commit da97a92

Please sign in to comment.