-
Notifications
You must be signed in to change notification settings - Fork 356
Created integrations settings page #1345
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
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Thank you for submitting your pull request! We'll review it as soon as possible. For further communication, join our discord server https://discord.gg/tSqtvHUJzE. |
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.
Pull request overview
This PR introduces a new integrations settings page with an initial OpenAI integration feature. The implementation follows the existing settings page pattern with a sidebar navigation and detail view, including responsive behavior for mobile devices. The refactoring also simplifies the settings module by replacing isSettingsDetailPage with direct activeSetting checks.
Changes:
- Created integrations route structure with OpenAI as the first integration
- Added responsive header component for integrations detail pages
- Refactored settings logic to use
activeSettingdirectly instead of derivedisSettingsDetailPagestate
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| client/src/shared/icons/openai.tsx | New OpenAI icon SVG component following existing icon pattern |
| client/src/modules/settings/v1/typings/index.ts | Added IntegrationSettingType interface for integration metadata |
| client/src/modules/settings/v1/index.tsx | Simplified conditional logic by using activeSetting directly |
| client/src/modules/settings/v1/hooks/index.ts | Removed unnecessary isSettingsDetailPage derived state |
| client/src/modules/settings/routes/index.tsx | Added integrations route and integrationsRoutes function, plus OpenAI integration definition |
| client/src/modules/settings/modules/integrations/v1/index.tsx | Main integrations page with sidebar and detail view layout |
| client/src/modules/settings/modules/integrations/v1/hooks/index.ts | Hook for managing integration state and active integration |
| client/src/modules/settings/modules/integrations/v1/components/integrations-header.tsx | Responsive header with back navigation for mobile |
| client/src/modules/settings/modules/integrations/modules/openai/v1/index.tsx | OpenAI integration UI with API key input (placeholder implementation) |
| client/src/modules/settings/modules/integrations/modules/openai/v1/hooks/index.ts | Hook for OpenAI integration state management (placeholder with TODOs) |
| client/src/modules/settings/modules/index.tsx | Added lazy-loaded exports for integrations components |
| client/src/modules/app/routes/constants/routes.ts | Added route constants for integrations |
client/src/modules/settings/modules/integrations/modules/openai/v1/hooks/index.ts
Show resolved
Hide resolved
client/src/modules/settings/modules/integrations/modules/openai/v1/index.tsx
Outdated
Show resolved
Hide resolved
client/src/modules/settings/modules/integrations/modules/openai/v1/index.tsx
Outdated
Show resolved
Hide resolved
client/src/modules/settings/modules/integrations/modules/openai/v1/hooks/index.ts
Outdated
Show resolved
Hide resolved
client/src/modules/settings/modules/integrations/modules/openai/v1/hooks/index.ts
Show resolved
Hide resolved
| <Box | ||
| sx={{ | ||
| height: '100%', | ||
| width: { | ||
| xs: showSidebarOnMobile ? '100%' : 0, | ||
| md: SETTINGS_SIDEBAR_WIDTH, | ||
| }, | ||
| minWidth: { | ||
| xs: showSidebarOnMobile ? '100%' : 0, | ||
| md: SETTINGS_SIDEBAR_WIDTH, | ||
| }, | ||
| maxWidth: { | ||
| xs: showSidebarOnMobile ? '100%' : 0, | ||
| md: SETTINGS_SIDEBAR_WIDTH, | ||
| }, | ||
| display: { | ||
| xs: showSidebarOnMobile ? 'flex' : 'none', | ||
| md: 'flex', | ||
| }, | ||
| flexDirection: 'column', | ||
| justifyContent: 'flex-start', | ||
| alignItems: 'flex-start', | ||
| bgcolor: 'background.paper', | ||
| overflow: 'hidden', | ||
| }} | ||
| > | ||
| <Box | ||
| sx={{ | ||
| flex: 1, | ||
| width: '100%', | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| justifyContent: 'flex-start', | ||
| alignItems: 'flex-start', | ||
| overflow: 'hidden', | ||
| '&:hover': { | ||
| overflowY: 'auto', | ||
| '&::-webkit-scrollbar': { | ||
| width: '8px', | ||
| }, | ||
| '&::-webkit-scrollbar-track': { | ||
| bgcolor: 'transparent', | ||
| }, | ||
| '&::-webkit-scrollbar-thumb': { | ||
| bgcolor: 'divider', | ||
| borderRadius: '4px', | ||
| '&:hover': { | ||
| bgcolor: 'action.disabled', | ||
| }, | ||
| }, | ||
| }, | ||
| }} | ||
| > | ||
| {integrations.map( | ||
| (integration: IntegrationSettingType, index: number) => { | ||
| const { | ||
| id, | ||
| integrationSlug, | ||
| name, | ||
| icon, | ||
| description, | ||
| locked = false, | ||
| } = integration; | ||
| const absolutePath = `${ROUTES_V1.SETTINGS}${ROUTES_SETTINGS_V1.INTEGRATIONS}/${integrationSlug}`; | ||
| const isTabActive = integrationId === id; | ||
|
|
||
| return ( | ||
| <ButtonBase<'div'> | ||
| key={id || index} | ||
| component="div" | ||
| sx={{ | ||
| width: '100%', | ||
| p: 2, | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| justifyContent: 'flex-start', | ||
| alignItems: 'flex-start', | ||
| rowGap: 0.25, | ||
| borderBottom: | ||
| index < integrations.length - 1 | ||
| ? `1px solid ${theme.palette.divider}` | ||
| : 'none', | ||
| bgcolor: isTabActive | ||
| ? theme.palette.mode === 'dark' | ||
| ? 'rgba(59, 130, 246, 0.1)' | ||
| : 'rgba(240, 245, 240, 1)' | ||
| : 'transparent', | ||
| boxShadow: 'none', | ||
| outline: 'none', | ||
| transition: 'background-color 200ms ease-in-out', | ||
| '&:hover': { | ||
| bgcolor: isTabActive | ||
| ? theme.palette.mode === 'dark' | ||
| ? 'rgba(59, 130, 246, 0.15)' | ||
| : 'rgba(240, 245, 240, 0.68)' | ||
| : 'action.hover', | ||
| boxShadow: 'none', | ||
| outline: 'none', | ||
| }, | ||
| }} | ||
| disabled={locked} | ||
| onClick={() => { | ||
| if (locked) { | ||
| return; | ||
| } | ||
| navigate({ pathname: absolutePath }); | ||
| }} | ||
| > | ||
| <Box | ||
| sx={{ | ||
| width: '100%', | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center', | ||
| columnGap: 1.5, | ||
| }} | ||
| > | ||
| <Box | ||
| sx={{ | ||
| display: 'flex', | ||
| justifyContent: 'flex-start', | ||
| alignItems: 'center', | ||
| columnGap: 1.5, | ||
| }} | ||
| > | ||
| <Box | ||
| sx={{ | ||
| position: 'relative', | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| color: isTabActive | ||
| ? 'primary.main' | ||
| : 'text.secondary', | ||
| }} | ||
| > | ||
| {icon} | ||
| {locked && ( | ||
| <LockIcon | ||
| sx={{ | ||
| ml: 'auto', | ||
| height: 15, | ||
| width: 15, | ||
| bgcolor: 'background.default', | ||
| p: 0.25, | ||
| borderRadius: '50%', | ||
| border: `1px solid ${theme.palette.divider}`, | ||
| position: 'absolute', | ||
| right: -4, | ||
| top: -6, | ||
| fontSize: 15, | ||
| color: 'text.secondary', | ||
| }} | ||
| /> | ||
| )} | ||
| </Box> | ||
| <A2ZTypography | ||
| text={name} | ||
| variant="body1" | ||
| props={{ | ||
| sx: { | ||
| fontSize: 16, | ||
| fontWeight: 600, | ||
| color: isTabActive | ||
| ? 'primary.main' | ||
| : 'text.primary', | ||
| }, | ||
| 'data-testid': `integration-${name}`, | ||
| }} | ||
| /> | ||
| </Box> | ||
| </Box> | ||
| {description && ( | ||
| <A2ZTypography | ||
| text={description} | ||
| variant="body2" | ||
| props={{ | ||
| sx: { | ||
| fontSize: 14, | ||
| fontWeight: 400, | ||
| color: 'text.secondary', | ||
| pl: 'calc(20px + 12px)', | ||
| }, | ||
| }} | ||
| /> | ||
| )} | ||
| </ButtonBase> | ||
| ); | ||
| } | ||
| )} | ||
| </Box> | ||
| </Box> |
Copilot
AI
Jan 11, 2026
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.
Duplicate code between integrations and settings pages. The sidebar rendering logic (lines 38-229) is nearly identical to the settings page sidebar. Consider extracting this into a reusable component like SettingsSidebar that accepts a configuration object for tabs/integrations to reduce code duplication and improve maintainability.
|
@copilot open a new pull request to apply changes based on the comments in this thread |
|
@Avdhesh-Varshney I've opened a new pull request, #1346, to work on those changes. Once the pull request is ready, I'll request review from you. |
Pull Requests Review Criteria
Caution
PRs that fail to meet these review standards will be automatically flagged and may be rejected by maintainers.
mainDescribe the add-ons or changes you've made 📃
Screenshots 📷