-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Making the catalog for embedded in tegration connections #246
Conversation
Your Render PR Server URL is https://panora-backend-api-pr-246.onrender.com. Follow its progress at https://dashboard.render.com/web/srv-cmsrc5gl6cac73arhoq0. |
|
WalkthroughThe project has undergone significant changes to enhance the React application's development and user interaction. It introduced Tailwind CSS for styling, optimized compilation with SWC, and added new components and hooks for managing providers and linked users. Additionally, it improved the API by adding a new method to retrieve linked users based on their origin ID. Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
🚮 Removed packages: npm/@vitejs/[email protected] |
🚨 Potential security issues detected. Learn more about Socket for GitHub ↗︎ To accept the risk, merge this PR and you will not be notified again.
Next stepsWhat is an install script?Install scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts. Packages should not be running non-essential scripts during install and there are often solutions to problems people solve with install scripts that can be run at publish time instead. Take a deeper look at the dependencyTake a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev. Remove the packageIf you happen to install a dependency that Socket reports as Known Malware you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency. Mark a package as acceptable riskTo ignore an alert, reply with a comment starting with
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files ignored due to path filters (8)
apps/embedded-catalog/react/package.json
is excluded by:!**/*.json
apps/embedded-catalog/react/public/vite.svg
is excluded by:!**/*.svg
apps/embedded-catalog/react/src/assets/react.svg
is excluded by:!**/*.svg
apps/embedded-catalog/react/tsconfig.json
is excluded by:!**/*.json
apps/embedded-catalog/react/tsconfig.node.json
is excluded by:!**/*.json
packages/api/swagger/swagger-spec.json
is excluded by:!**/*.json
pnpm-lock.yaml
is excluded by:!**/*.yaml
pnpm-workspace.yaml
is excluded by:!**/*.yaml
Files selected for processing (6)
- apps/embedded-catalog/react/postcss.config.js (1 hunks)
- apps/embedded-catalog/react/src/App.tsx (1 hunks)
- apps/embedded-catalog/react/src/index.css (1 hunks)
- apps/embedded-catalog/react/tailwind.config.js (1 hunks)
- apps/embedded-catalog/react/vite.config.ts (1 hunks)
- apps/webapp/src/components/connections/ConnectionTable.tsx (1 hunks)
Files skipped from review due to trivial changes (2)
- apps/embedded-catalog/react/postcss.config.js
- apps/embedded-catalog/react/src/index.css
Additional comments: 4
apps/embedded-catalog/react/vite.config.ts (1)
- 2-2: The switch to
@vitejs/plugin-react-swc
from@vitejs/plugin-react
is correctly implemented. This change should enhance the build performance by utilizing SWC's faster compilation capabilities.apps/embedded-catalog/react/tailwind.config.js (1)
- 1-11: The Tailwind CSS configuration is correctly set up with appropriate content paths and an empty theme extension. This setup ensures that Tailwind can correctly purge unused styles in production and extend the theme as needed.
apps/embedded-catalog/react/src/App.tsx (1)
- 1-17: The
App
component is correctly implemented with a basic structure and uses Tailwind CSS for styling. This serves as a good starting point for further UI development.apps/webapp/src/components/connections/ConnectionTable.tsx (1)
- 82-82: The modification to the dialog box opening condition in
ConnectionTable.tsx
is a logical improvement. It now considers theisGenerated
state more effectively, enhancing the user experience by making the UI behavior more intuitive. However, ensure that thesetIsGenerated
function is correctly handling state changes to avoid potential issues with dialog state management.
Hard-Coded Secrets (2)
More info on how to fix Hard-Coded Secrets in General. 👉 Go to the dashboard for detailed results. 📥 Happy? Share your feedback with us. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files ignored due to path filters (14)
apps/embedded-catalog/react/package.json
is excluded by:!**/*.json
apps/embedded-catalog/react/public/assets/accounting/clearbooksLogo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/accounting/freeagent.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/accounting/freshbooks.jpeg
is excluded by:!**/*.jpeg
apps/embedded-catalog/react/public/assets/accounting/pennylanelogo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/accounting/sageLogo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/crm/hubspot_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/crm/pipedrive_logo.jpeg
is excluded by:!**/*.jpeg
apps/embedded-catalog/react/public/assets/crm/zendesk_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/crm/zoho_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/ticketing/front.png
is excluded by:!**/*.png
apps/embedded-catalog/react/tsconfig.json
is excluded by:!**/*.json
apps/frontend-snippet/package.json
is excluded by:!**/*.json
pnpm-lock.yaml
is excluded by:!**/*.yaml
Files selected for processing (10)
- apps/embedded-catalog/react/src/App.tsx (1 hunks)
- apps/embedded-catalog/react/src/helpers/config.ts (1 hunks)
- apps/embedded-catalog/react/src/helpers/utils.ts (1 hunks)
- apps/embedded-catalog/react/src/hooks/mutations/useLinkedUserMutation.tsx (1 hunks)
- apps/embedded-catalog/react/src/hooks/queries/useLinkedUserId.tsx (1 hunks)
- apps/embedded-catalog/react/src/hooks/useOAuth.tsx (1 hunks)
- apps/embedded-catalog/react/src/lib/index.tsx (1 hunks)
- apps/embedded-catalog/react/vite.config.ts (1 hunks)
- packages/api/src/@core/linked-users/linked-users.controller.ts (1 hunks)
- packages/api/src/@core/linked-users/linked-users.service.ts (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- apps/embedded-catalog/react/vite.config.ts
Additional comments: 10
apps/embedded-catalog/react/src/helpers/config.ts (1)
- 1-6: The configuration file correctly exports a
config
object containing environment variables for API URLs. Ensure that these environment variables are properly defined in the project's environment configuration files (e.g.,.env
files) to avoid runtime errors.apps/embedded-catalog/react/src/App.tsx (1)
- 1-21: The
App
component is correctly structured and usesQueryClientProvider
from@tanstack/react-query
to provide a React Query configuration context. Ensure thatProviderCard
is imported correctly from./lib
and that it is the intended component to be rendered within this context.apps/embedded-catalog/react/src/hooks/queries/useLinkedUserId.tsx (1)
- 1-17: The
useLinkedUser
hook correctly usesuseQuery
from@tanstack/react-query
to fetch linked user data. Ensure that thelinked_users
import fromapi
is correctly set up and that the API URL constructed withconfig.API_URL
is valid and accessible. Also, consider handling the JSON parsing with a try-catch block to gracefully handle any potential parsing errors.apps/embedded-catalog/react/src/hooks/mutations/useLinkedUserMutation.tsx (1)
- 1-40: The
useLinkedUserMutation
hook correctly usesuseMutation
from@tanstack/react-query
for performing a POST request to add a linked user. Ensure that the API endpoint${config.API_URL}/linked-users/create
is correct and that the server is configured to accept and process the JSON payload. Additionally, consider adding error handling logic in theonError
callback to provide more detailed feedback to the user or system.packages/api/src/@core/linked-users/linked-users.service.ts (1)
- 31-41: The
getLinkedUserV2
method correctly uses Prisma to fetch a linked user based onoriginId
. Ensure that thelinked_user_origin_id
field is correctly indexed in the database for optimal query performance. Also, the use ofhandleServiceError
for error handling is appropriate, but ensure that it logs sufficient information for debugging purposes.packages/api/src/@core/linked-users/linked-users.controller.ts (1)
- 52-61: The
getLinkedUserV2
method inLinkedUsersController
is correctly implemented with appropriate API documentation using NestJS decorators. Ensure that theoriginId
query parameter is validated to prevent potential injection attacks or errors. Additionally, consider adding more detailed response types in the@ApiResponse
decorator for better API documentation.apps/embedded-catalog/react/src/hooks/useOAuth.tsx (1)
- 1-83: The
useOAuth
hook is well-structured for constructing OAuth URLs and handling the OAuth flow in a modal window. Ensure that theprovidersConfig
andfindProviderVertical
functions are correctly implemented to support the OAuth configurations. Additionally, consider handling potential errors or edge cases, such as whenauthUrl
isnull
or when the provider configuration is missing.apps/embedded-catalog/react/src/lib/index.tsx (2)
- 9-34: The
LoadingOverlay
component is correctly implemented to display a loading state with provider-specific information. Ensure that theprovider
object is always defined to avoid potential runtime errors when accessing properties likelogoPath
andname
.- 47-120: The
ProviderCard
component is well-implemented, using custom hooks for mutation and query operations, and handling OAuth flow. Ensure that themutate
function fromuseLinkedUserMutation
and thedata
fromuseLinkedUser
are correctly handled, especially in cases where the mutation or query might fail. Additionally, consider adding error handling for these operations to improve user experience.apps/embedded-catalog/react/src/helpers/utils.ts (1)
- 1-146: The utility file correctly defines configurations for various OAuth providers and includes functions for accessing these configurations. Ensure that all client IDs and scopes are correctly configured and that any placeholders like in the
freshsales
configuration are replaced with actual values before deployment. Additionally, consider validating thevertical
parameter inprovidersArray
to ensure it matches one of the defined categories to prevent runtime errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 1
Configuration used: CodeRabbit UI
Files selected for processing (4)
- apps/embedded-catalog/react/.env.example (1 hunks)
- apps/embedded-catalog/react/src/helpers/utils.ts (1 hunks)
- apps/embedded-catalog/react/src/index.css (1 hunks)
- apps/embedded-catalog/react/src/lib/index.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (2)
- apps/embedded-catalog/react/src/helpers/utils.ts
- apps/embedded-catalog/react/src/index.css
Additional comments: 3
apps/embedded-catalog/react/.env.example (1)
- 1-1: The addition of
VITE_BACKEND_DOMAIN
in the.env.example
file is a good practice, as it provides a clear example for developers on how to set up their local environment variables. However, ensure that this URL is intended only for development or example purposes and not used in production environments to avoid security risks.apps/embedded-catalog/react/src/lib/index.tsx (2)
- 1-6: The imports are well-organized and follow a consistent pattern, using alias paths for better readability and maintainability. This is a good practice as it makes the codebase easier to navigate.
- 9-19: Defining interfaces
RemoteUserInfo
andProviderCardProp
enhances the type safety and readability of the component. This is a good practice in TypeScript development. Ensure that all properties are indeed required; otherwise, consider marking optional properties with?
.
const ProviderCard = ({name, projectId, linkedUserIdOrRemoteUserInfo}: ProviderCardProp) => { | ||
const [providerClicked, setProviderClicked] = useState(false); | ||
const [originId, setOriginId] = useState("") | ||
|
||
const { mutate } = useLinkedUserMutation(); | ||
const {data: linkedUser} = useLinkedUser(originId); | ||
|
||
|
||
let linkedUserId: string; | ||
if (typeof linkedUserIdOrRemoteUserInfo === 'string') { | ||
linkedUserId = linkedUserIdOrRemoteUserInfo; | ||
} else { | ||
//create a new linkedUser based on the user data of the saas | ||
mutate({ | ||
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem, | ||
alias: linkedUserIdOrRemoteUserInfo.companyName, | ||
id_project: projectId | ||
}); | ||
setOriginId(linkedUserIdOrRemoteUserInfo?.userIdInYourSystem) | ||
//fetch the linkedId | ||
linkedUserId = linkedUser!.id_linked_user | ||
} | ||
|
||
const { open, isReady } = useOAuth({ | ||
providerName: name.toLowerCase(), | ||
returnUrl: config.ML_FRONTEND_URL, // TODO: Replace with the actual return URL | ||
projectId: projectId, | ||
linkedUserId: linkedUserId, | ||
onSuccess: () => console.log('OAuth successful'), | ||
}); | ||
|
||
const onWindowClose = () => { | ||
} | ||
|
||
useEffect(() => { | ||
if (providerClicked && isReady) { | ||
open(onWindowClose); | ||
} | ||
}, [providerClicked, isReady, open]); | ||
|
||
|
||
const handleClick = () => { | ||
setProviderClicked(true); | ||
}; | ||
|
||
return ( | ||
<div | ||
className="max-w-sm p-6 bg-white border-[0.007em] border-gray-200 rounded-lg shadow dark:bg-zinc-800 hover:border-zinc-900 hover:border-[0.1em] transition-colors duration-200" | ||
> | ||
<div className="text-center flex items-center"> | ||
<img src={`public/assets/crm/${name}_logo.png`} width={"35px"} className="pb-5 mr-3 rounded-sm"/> | ||
<a href="#"> | ||
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">Integrate with {name}</h5> | ||
</a> | ||
</div> | ||
|
||
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">{getDescription(name.toLowerCase())}</p> | ||
<a | ||
href="#" className="inline-flex items-center text-indigo-600 hover:underline" | ||
onClick={handleClick} | ||
> | ||
Integrate in one click | ||
<svg className="w-3 h-3 ms-2.5 rtl:rotate-[270deg]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> | ||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"/> | ||
</svg> | ||
</a> | ||
</div> | ||
) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ProviderCard
component is well-structured, utilizing React hooks for state management and effects. However, there are a few areas for improvement:
- The
mutate
function is called directly within the component's render logic (lines 33-37). This side effect should be encapsulated within auseEffect
hook or a callback function to avoid unintended mutations on each render. - The
linkedUserId
is being set after a mutation call without checking if the mutation was successful (lines 38-40). Consider handling the mutation's success or failure states to ensurelinkedUserId
is set correctly. - The
TODO
comment on line 45 suggests that thereturnUrl
is hardcoded. Ensure this is addressed before production deployment to avoid redirect issues. - The
onWindowClose
function (lines 51-52) is empty. If it's intended to have logic, implement it; otherwise, remove it to clean up the code.
Consider refactoring to address these points for better maintainability and reliability.
- mutate({
+ useEffect(() => {
+ if (!originId) {
+ mutate({
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem,
alias: linkedUserIdOrRemoteUserInfo.companyName,
id_project: projectId
- });
+ });
+ }
+ }, [linkedUserIdOrRemoteUserInfo, mutate, originId, projectId]);
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
const ProviderCard = ({name, projectId, linkedUserIdOrRemoteUserInfo}: ProviderCardProp) => { | |
const [providerClicked, setProviderClicked] = useState(false); | |
const [originId, setOriginId] = useState("") | |
const { mutate } = useLinkedUserMutation(); | |
const {data: linkedUser} = useLinkedUser(originId); | |
let linkedUserId: string; | |
if (typeof linkedUserIdOrRemoteUserInfo === 'string') { | |
linkedUserId = linkedUserIdOrRemoteUserInfo; | |
} else { | |
//create a new linkedUser based on the user data of the saas | |
mutate({ | |
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem, | |
alias: linkedUserIdOrRemoteUserInfo.companyName, | |
id_project: projectId | |
}); | |
setOriginId(linkedUserIdOrRemoteUserInfo?.userIdInYourSystem) | |
//fetch the linkedId | |
linkedUserId = linkedUser!.id_linked_user | |
} | |
const { open, isReady } = useOAuth({ | |
providerName: name.toLowerCase(), | |
returnUrl: config.ML_FRONTEND_URL, // TODO: Replace with the actual return URL | |
projectId: projectId, | |
linkedUserId: linkedUserId, | |
onSuccess: () => console.log('OAuth successful'), | |
}); | |
const onWindowClose = () => { | |
} | |
useEffect(() => { | |
if (providerClicked && isReady) { | |
open(onWindowClose); | |
} | |
}, [providerClicked, isReady, open]); | |
const handleClick = () => { | |
setProviderClicked(true); | |
}; | |
return ( | |
<div | |
className="max-w-sm p-6 bg-white border-[0.007em] border-gray-200 rounded-lg shadow dark:bg-zinc-800 hover:border-zinc-900 hover:border-[0.1em] transition-colors duration-200" | |
> | |
<div className="text-center flex items-center"> | |
<img src={`public/assets/crm/${name}_logo.png`} width={"35px"} className="pb-5 mr-3 rounded-sm"/> | |
<a href="#"> | |
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">Integrate with {name}</h5> | |
</a> | |
</div> | |
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">{getDescription(name.toLowerCase())}</p> | |
<a | |
href="#" className="inline-flex items-center text-indigo-600 hover:underline" | |
onClick={handleClick} | |
> | |
Integrate in one click | |
<svg className="w-3 h-3 ms-2.5 rtl:rotate-[270deg]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> | |
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"/> | |
</svg> | |
</a> | |
</div> | |
) | |
}; | |
const ProviderCard = ({name, projectId, linkedUserIdOrRemoteUserInfo}: ProviderCardProp) => { | |
const [providerClicked, setProviderClicked] = useState(false); | |
const [originId, setOriginId] = useState("") | |
const { mutate } = useLinkedUserMutation(); | |
const {data: linkedUser} = useLinkedUser(originId); | |
let linkedUserId: string; | |
if (typeof linkedUserIdOrRemoteUserInfo === 'string') { | |
linkedUserId = linkedUserIdOrRemoteUserInfo; | |
} else { | |
useEffect(() => { | |
if (!originId) { | |
mutate({ | |
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem, | |
alias: linkedUserIdOrRemoteUserInfo.companyName, | |
id_project: projectId | |
}); | |
} | |
}, [linkedUserIdOrRemoteUserInfo, mutate, originId, projectId]); | |
setOriginId(linkedUserIdOrRemoteUserInfo?.userIdInYourSystem) | |
//fetch the linkedId | |
linkedUserId = linkedUser!.id_linked_user | |
} | |
const { open, isReady } = useOAuth({ | |
providerName: name.toLowerCase(), | |
returnUrl: config.ML_FRONTEND_URL, // TODO: Replace with the actual return URL | |
projectId: projectId, | |
linkedUserId: linkedUserId, | |
onSuccess: () => console.log('OAuth successful'), | |
}); | |
const onWindowClose = () => { | |
} | |
useEffect(() => { | |
if (providerClicked && isReady) { | |
open(onWindowClose); | |
} | |
}, [providerClicked, isReady, open]); | |
const handleClick = () => { | |
setProviderClicked(true); | |
}; | |
return ( | |
<div | |
className="max-w-sm p-6 bg-white border-[0.007em] border-gray-200 rounded-lg shadow dark:bg-zinc-800 hover:border-zinc-900 hover:border-[0.1em] transition-colors duration-200" | |
> | |
<div className="text-center flex items-center"> | |
<img src={`public/assets/crm/${name}_logo.png`} width={"35px"} className="pb-5 mr-3 rounded-sm"/> | |
<a href="#"> | |
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">Integrate with {name}</h5> | |
</a> | |
</div> | |
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">{getDescription(name.toLowerCase())}</p> | |
<a | |
href="#" className="inline-flex items-center text-indigo-600 hover:underline" | |
onClick={handleClick} | |
> | |
Integrate in one click | |
<svg className="w-3 h-3 ms-2.5 rtl:rotate-[270deg]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> | |
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"/> | |
</svg> | |
</a> | |
</div> | |
) | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- apps/embedded-catalog/react/src/lib/index.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- apps/embedded-catalog/react/src/lib/index.tsx
Your Render PR Server URL is https://frontend-pr-246-0dj2.onrender.com. Follow its progress at https://dashboard.render.com/static/srv-cmtiiqol6cac73asr6cg. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 1
Configuration used: CodeRabbit UI
Files ignored due to path filters (9)
apps/embedded-catalog/react/public/assets/accounting/clearbooks_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/accounting/freeagent_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/accounting/freshbooks_logo.jpeg
is excluded by:!**/*.jpeg
apps/embedded-catalog/react/public/assets/accounting/pennylane_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/accounting/sage_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/crm/freshsales_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/crm/pipedrive_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/ticketing/front_logo.png
is excluded by:!**/*.png
apps/embedded-catalog/react/public/assets/ticketing/zendesk_tcg_logo.png
is excluded by:!**/*.png
Files selected for processing (5)
- apps/embedded-catalog/react/index.ts (1 hunks)
- apps/embedded-catalog/react/src/App.tsx (1 hunks)
- apps/embedded-catalog/react/src/components/PanoraIntegrationCard.tsx (1 hunks)
- apps/embedded-catalog/react/src/components/index.ts (1 hunks)
- apps/embedded-catalog/react/src/helpers/utils.ts (1 hunks)
Files skipped from review as they are similar to previous changes (2)
- apps/embedded-catalog/react/src/App.tsx
- apps/embedded-catalog/react/src/helpers/utils.ts
Additional comments: 4
apps/embedded-catalog/react/src/components/index.ts (1)
- 1-1: The export statement is correctly formatted and follows standard ES6 module syntax.
apps/embedded-catalog/react/index.ts (1)
- 1-1: The export statement correctly re-exports the
PanoraIntegrationCard
from its location within thesrc/components
directory, maintaining a clean entry point for the package.apps/embedded-catalog/react/src/components/PanoraIntegrationCard.tsx (2)
- 1-5: Imports are well-organized, separating external libraries from internal utilities and hooks. This enhances readability and maintainability.
- 9-19: The component props are clearly defined with an interface, which is a good practice for type safety and readability in TypeScript.
export const PanoraIntegrationCard = ({name, projectId, returnUrl, linkedUserIdOrRemoteUserInfo}: ProviderCardProp) => { | ||
const [providerClicked, setProviderClicked] = useState(false); | ||
const [originId, setOriginId] = useState("") | ||
const [loading, setLoading] = useState(false) | ||
|
||
const vertical = findProviderVertical(name.toLowerCase()) | ||
console.log("vertical "+ vertical) | ||
const { mutate } = useLinkedUserMutation(); | ||
const {data: linkedUser} = useLinkedUser(originId); | ||
|
||
|
||
let linkedUserId: string; | ||
if (typeof linkedUserIdOrRemoteUserInfo === 'string') { | ||
linkedUserId = linkedUserIdOrRemoteUserInfo; | ||
} else { | ||
//create a new linkedUser based on the user data of the saas | ||
mutate({ | ||
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem, | ||
alias: linkedUserIdOrRemoteUserInfo.companyName, | ||
id_project: projectId | ||
}); | ||
setOriginId(linkedUserIdOrRemoteUserInfo?.userIdInYourSystem) | ||
//fetch the linkedId | ||
linkedUserId = linkedUser!.id_linked_user | ||
} | ||
|
||
const { open, isReady } = useOAuth({ | ||
providerName: name.toLowerCase(), | ||
returnUrl: returnUrl, // TODO: Replace with the actual return URL | ||
projectId: projectId, | ||
linkedUserId: linkedUserId, | ||
onSuccess: () => console.log('OAuth successful'), | ||
}); | ||
|
||
const onWindowClose = () => { | ||
setLoading(false); | ||
return; | ||
} | ||
|
||
useEffect(() => { | ||
if (loading && providerClicked && isReady) { | ||
open(onWindowClose); | ||
return; | ||
} | ||
}, [providerClicked, isReady, open, loading]); | ||
|
||
|
||
const handleClick = () => { | ||
setLoading(true); | ||
setProviderClicked(true); | ||
return; | ||
}; | ||
|
||
return ( | ||
<div | ||
className="max-w-sm p-6 bg-white border-[0.007em] border-gray-200 rounded-lg shadow dark:bg-zinc-800 hover:border-gray-200 transition-colors duration-200" | ||
> | ||
<div className=" flex items-center justify-center"> | ||
<img src={`public/assets/${vertical!.toLowerCase()}/${name}_logo.png`} width={"30px"} className="mx-3 mb-4 w-12 h-12 rounded-xl"/> | ||
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">Integrate with {name}</h5> | ||
|
||
</div> | ||
|
||
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">{getDescription(name.toLowerCase())}</p> | ||
{!loading ? | ||
<a | ||
href="#" className="inline-flex items-center text-indigo-600 hover:underline" | ||
onClick={handleClick} | ||
> | ||
Connect in one click | ||
<svg className="w-3 h-3 ms-2.5 rtl:rotate-[270deg]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> | ||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"/> | ||
</svg> | ||
</a> | ||
|
||
: | ||
<> | ||
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">Continue in {name} </p> | ||
<div className='flex justify-center items-center'> | ||
<TailSpin | ||
height="40" | ||
width="70" | ||
color="white" | ||
ariaLabel="tail-spin-loading" | ||
radius="1" | ||
wrapperStyle={{}} | ||
wrapperClass="" | ||
visible={true} | ||
/> | ||
</div> | ||
</> | ||
|
||
} | ||
</div> | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The component function PanoraIntegrationCard
is well-structured, utilizing React hooks for state management and effects. However, there are several areas for improvement:
- The console log on line 26 should be removed for production code to avoid leaking potentially sensitive information.
- The use of
!
(non-null assertion operator) on line 43 is risky without checking iflinkedUser
is null or undefined. Consider adding a guard clause or default value. - The comment on line 48 about replacing the actual return URL should be addressed or tracked with a TODO if it's pending future changes.
- The
href="#"
on line 86 should be replaced with a button element orpreventDefault
to avoid reloading the page on click.
- console.log("vertical "+ vertical)
+ // Consider removing console logs in production
- linkedUserId = linkedUser!.id_linked_user
+ linkedUserId = linkedUser ? linkedUser.id_linked_user : 'defaultId' // Example default value or handling
- href="#" className="inline-flex items-center text-indigo-600 hover:underline"
+ <button className="inline-flex items-center text-indigo-600 hover:underline" onClick={handleClick}>
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
export const PanoraIntegrationCard = ({name, projectId, returnUrl, linkedUserIdOrRemoteUserInfo}: ProviderCardProp) => { | |
const [providerClicked, setProviderClicked] = useState(false); | |
const [originId, setOriginId] = useState("") | |
const [loading, setLoading] = useState(false) | |
const vertical = findProviderVertical(name.toLowerCase()) | |
console.log("vertical "+ vertical) | |
const { mutate } = useLinkedUserMutation(); | |
const {data: linkedUser} = useLinkedUser(originId); | |
let linkedUserId: string; | |
if (typeof linkedUserIdOrRemoteUserInfo === 'string') { | |
linkedUserId = linkedUserIdOrRemoteUserInfo; | |
} else { | |
//create a new linkedUser based on the user data of the saas | |
mutate({ | |
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem, | |
alias: linkedUserIdOrRemoteUserInfo.companyName, | |
id_project: projectId | |
}); | |
setOriginId(linkedUserIdOrRemoteUserInfo?.userIdInYourSystem) | |
//fetch the linkedId | |
linkedUserId = linkedUser!.id_linked_user | |
} | |
const { open, isReady } = useOAuth({ | |
providerName: name.toLowerCase(), | |
returnUrl: returnUrl, // TODO: Replace with the actual return URL | |
projectId: projectId, | |
linkedUserId: linkedUserId, | |
onSuccess: () => console.log('OAuth successful'), | |
}); | |
const onWindowClose = () => { | |
setLoading(false); | |
return; | |
} | |
useEffect(() => { | |
if (loading && providerClicked && isReady) { | |
open(onWindowClose); | |
return; | |
} | |
}, [providerClicked, isReady, open, loading]); | |
const handleClick = () => { | |
setLoading(true); | |
setProviderClicked(true); | |
return; | |
}; | |
return ( | |
<div | |
className="max-w-sm p-6 bg-white border-[0.007em] border-gray-200 rounded-lg shadow dark:bg-zinc-800 hover:border-gray-200 transition-colors duration-200" | |
> | |
<div className=" flex items-center justify-center"> | |
<img src={`public/assets/${vertical!.toLowerCase()}/${name}_logo.png`} width={"30px"} className="mx-3 mb-4 w-12 h-12 rounded-xl"/> | |
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">Integrate with {name}</h5> | |
</div> | |
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">{getDescription(name.toLowerCase())}</p> | |
{!loading ? | |
<a | |
href="#" className="inline-flex items-center text-indigo-600 hover:underline" | |
onClick={handleClick} | |
> | |
Connect in one click | |
<svg className="w-3 h-3 ms-2.5 rtl:rotate-[270deg]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> | |
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"/> | |
</svg> | |
</a> | |
: | |
<> | |
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">Continue in {name} </p> | |
<div className='flex justify-center items-center'> | |
<TailSpin | |
height="40" | |
width="70" | |
color="white" | |
ariaLabel="tail-spin-loading" | |
radius="1" | |
wrapperStyle={{}} | |
wrapperClass="" | |
visible={true} | |
/> | |
</div> | |
</> | |
} | |
</div> | |
) | |
export const PanoraIntegrationCard = ({name, projectId, returnUrl, linkedUserIdOrRemoteUserInfo}: ProviderCardProp) => { | |
const [providerClicked, setProviderClicked] = useState(false); | |
const [originId, setOriginId] = useState("") | |
const [loading, setLoading] = useState(false) | |
const vertical = findProviderVertical(name.toLowerCase()) | |
// Consider removing console logs in production | |
const { mutate } = useLinkedUserMutation(); | |
const {data: linkedUser} = useLinkedUser(originId); | |
let linkedUserId: string; | |
if (typeof linkedUserIdOrRemoteUserInfo === 'string') { | |
linkedUserId = linkedUserIdOrRemoteUserInfo; | |
} else { | |
//create a new linkedUser based on the user data of the saas | |
mutate({ | |
linked_user_origin_id: linkedUserIdOrRemoteUserInfo.userIdInYourSystem, | |
alias: linkedUserIdOrRemoteUserInfo.companyName, | |
id_project: projectId | |
}); | |
setOriginId(linkedUserIdOrRemoteUserInfo?.userIdInYourSystem) | |
//fetch the linkedId | |
linkedUserId = linkedUser ? linkedUser.id_linked_user : 'defaultId' // Example default value or handling | |
} | |
const { open, isReady } = useOAuth({ | |
providerName: name.toLowerCase(), | |
returnUrl: returnUrl, // TODO: Replace with the actual return URL | |
projectId: projectId, | |
linkedUserId: linkedUserId, | |
onSuccess: () => console.log('OAuth successful'), | |
}); | |
const onWindowClose = () => { | |
setLoading(false); | |
return; | |
} | |
useEffect(() => { | |
if (loading && providerClicked && isReady) { | |
open(onWindowClose); | |
return; | |
} | |
}, [providerClicked, isReady, open, loading]); | |
const handleClick = (e) => { | |
e.preventDefault(); | |
setLoading(true); | |
setProviderClicked(true); | |
return; | |
}; | |
return ( | |
<div | |
className="max-w-sm p-6 bg-white border-[0.007em] border-gray-200 rounded-lg shadow dark:bg-zinc-800 hover:border-gray-200 transition-colors duration-200" | |
> | |
<div className=" flex items-center justify-center"> | |
<img src={`public/assets/${vertical!.toLowerCase()}/${name}_logo.png`} width={"30px"} className="mx-3 mb-4 w-12 h-12 rounded-xl"/> | |
<h5 className="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">Integrate with {name}</h5> | |
</div> | |
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">{getDescription(name.toLowerCase())}</p> | |
{!loading ? | |
<button className="inline-flex items-center text-indigo-600 hover:underline" onClick={handleClick}> | |
Connect in one click | |
<svg className="w-3 h-3 ms-2.5 rtl:rotate-[270deg]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> | |
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"/> | |
</svg> | |
</button> | |
: | |
<> | |
<p className="mb-3 font-normal text-gray-500 dark:text-gray-400">Continue in {name} </p> | |
<div className='flex justify-center items-center'> | |
<TailSpin | |
height="40" | |
width="70" | |
color="white" | |
ariaLabel="tail-spin-loading" | |
radius="1" | |
wrapperStyle={{}} | |
wrapperClass="" | |
visible={true} | |
/> | |
</div> | |
</> | |
} | |
</div> | |
) |
Summary by CodeRabbit
New Features
Refactor
@vitejs/plugin-react-swc
for improved performance in the React app's build process.Chores