Skip to content
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

feat(webapp): Show integration issues in their settings #3044

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
716cd13
More config validation
nalanj Nov 21, 2024
67efd89
More progress on showing missing config fields
nalanj Nov 21, 2024
4c83d9d
Merge branch 'master' into alan/nan-2168-surface-integrationsconnecti…
nalanj Nov 22, 2024
40e80d7
Merge branch 'master' into alan/nan-2168-surface-integrationsconnecti…
nalanj Nov 22, 2024
802a76a
Add missing fields column to db
nalanj Nov 22, 2024
ca8fb04
Move validation logic over and make it more functional per Thomas' fe…
nalanj Nov 22, 2024
1ef4ac4
Add missing_fields to _nango_config table and set them on update and …
nalanj Nov 22, 2024
796dd48
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 22, 2024
683e00b
Backfill missing fields on configs
nalanj Nov 22, 2024
40dbef7
Fix some type errors
nalanj Nov 25, 2024
5ddca13
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 25, 2024
a1c7f1e
Clean up setting missing fields on create
nalanj Nov 25, 2024
b137bfb
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 25, 2024
7dc7bd3
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 25, 2024
81ff9b8
One more typing fix
nalanj Nov 25, 2024
4b25005
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 25, 2024
95bc2ad
Add validation on CUSTOM auth mode
nalanj Nov 25, 2024
eaefdc9
Switch to flatMap
nalanj Nov 25, 2024
1f2cddc
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 25, 2024
a41f023
Merge branch 'master' into alan/nan-2168/integration-missing-fields
nalanj Nov 25, 2024
14ea864
Merge branch 'alan/nan-2168/integration-missing-fields' into alan/nan…
nalanj Nov 25, 2024
25fb4d6
Merge branch 'alan/nan-2168/missing-fields-backfill' into alan/nan-21…
nalanj Nov 25, 2024
57e563e
Show integration missing field warnings for all auto modes
nalanj Nov 25, 2024
2de006d
Add errors to integration list
nalanj Nov 25, 2024
6175ebe
Merge branch 'master' into alan/nan-2168-surface-integrationsconnecti…
nalanj Nov 27, 2024
2fca22a
Merge branch 'master' into alan/nan-2168-surface-integrationsconnecti…
nalanj Nov 27, 2024
c2f8497
Clean up field output based on feedback from Thomas
nalanj Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/server/lib/controllers/config.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface Integration {
creationDate: Date | undefined;
connectionConfigParams?: string[];
credentialParams?: string[];
missing_fields_count: number;
}

export interface ListIntegration {
Expand Down Expand Up @@ -131,7 +132,8 @@ class ConfigController {
provider: config.provider,
scripts: activeFlows.length,
connection_count: Number(config.connection_count),
creationDate: config.created_at
creationDate: config.created_at,
missing_fields_count: config.missing_fields.length
nalanj marked this conversation as resolved.
Show resolved Hide resolved
};

// Used by legacy connection create
Expand Down
5 changes: 3 additions & 2 deletions packages/webapp/src/components/ErrorCircle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { IconExclamationMark, IconLock, IconRefresh } from '@tabler/icons-react'
import type React from 'react';

export type ErrorCircleIcon = '!' | 'sync' | 'auth';
export const ErrorCircle: React.FC<{ icon?: ErrorCircleIcon }> = ({ icon = '!' }) => {
export type ErrorCircleVariant = 'error' | 'warning';
export const ErrorCircle: React.FC<{ icon?: ErrorCircleIcon; variant?: ErrorCircleVariant }> = ({ icon = '!', variant = 'error' }) => {
return (
<span className="mx-1 cursor-auto flex h-4 w-4 rounded-full ring-red-base/[.35] ring-4">
<span className="flex items-center rounded-full bg-red-base h-4 w-4">
<span className={`flex items-center rounded-full ${variant === 'warning' ? 'bg-yellow-base' : 'bg-red-base'} h-4 w-4`}>
{icon === '!' && <IconExclamationMark className="ml-[2px] h-3 w-3 text-pure-black" />}
{icon === 'sync' && <IconRefresh className="ml-[2px] h-3 w-3 text-pure-black" />}
{icon === 'auth' && <IconLock className="ml-[2px] h-3 w-3 text-pure-black" />}
Expand Down
9 changes: 8 additions & 1 deletion packages/webapp/src/pages/Integrations/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import IntegrationLogo from '../../components/ui/IntegrationLogo';

import { useStore } from '../../store';
import { useListIntegration } from '../../hooks/useIntegration';
import { ErrorCircle } from '../../components/ErrorCircle';
import { SimpleTooltip } from '../../components/SimpleTooltip';
import { Helmet } from 'react-helmet';
import { ErrorPageComponent } from '../../components/ErrorComponent';

Expand Down Expand Up @@ -61,7 +63,7 @@ export default function IntegrationList() {
<div className="w-1/3">Connections</div>
<div className="w-24">Active Scripts</div>
</div>
{integrations?.map(({ uniqueKey, provider, connection_count, scripts }) => (
{integrations?.map(({ uniqueKey, provider, connection_count, scripts, missing_fields_count }) => (
<div
key={`tr-${uniqueKey}`}
className={`flex gap-4 ${
Expand All @@ -76,6 +78,11 @@ export default function IntegrationList() {
<IntegrationLogo provider={provider} height={7} width={7} />
</div>
<p className="truncate">{uniqueKey}</p>
{missing_fields_count > 0 && (
<SimpleTooltip tooltipContent="Missing configuration">
<ErrorCircle icon="!" variant="warning" />
</SimpleTooltip>
)}
</div>
<div className="flex items-center w-1/3">
<p className="">{connection_count}</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,49 @@ import { InfoBloc } from '../../../../../components/InfoBloc';
import { CopyButton } from '../../../../../components/ui/button/CopyButton';
import SecretInput from '../../../../../components/ui/input/SecretInput';
import type { EnvironmentAndAccount } from '@nangohq/server';
import { Info } from '../../../../../components/Info';

export const SettingsGeneral: React.FC<{ data: GetIntegration['Success']['data']; environment: EnvironmentAndAccount['environment'] }> = ({
data: { integration, meta, template },
environment
}) => {
const FIELD_DISPLAY_NAMES: Record<string, Record<string, string>> = {
OAUTH1: {
oauth_client_id: 'Client ID',
oauth_client_secret: 'Client Secret'
},
OAUTH2: {
oauth_client_id: 'Client ID',
oauth_client_secret: 'Client Secret'
},
TBA: {
oauth_client_id: 'Client ID',
oauth_client_secret: 'Client Secret'
},
APP: {
oauth_client_id: 'App ID',
oauth_client_secret: 'App Private Key',
app_link: 'App Public Link'
},
CUSTOM: {
oauth_client_id: 'Client ID',
oauth_client_secret: 'Client Secret',
app_link: 'App Public Link',
app_id: 'App ID',
private_key: 'App Private Key'
}
} as const;

function missingFieldsMessage(
template: GetIntegration['Success']['data']['template'],
integration: GetIntegration['Success']['data']['integration']
): string | null {
const mappings = FIELD_DISPLAY_NAMES[template.auth_mode];
if (!mappings) return null;

return integration.missing_fields.map((field) => mappings[field] || field).join(', ');
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might have been more user friendly to display a global message and a message near each fields instead


export const SettingsGeneral: React.FC<{
data: GetIntegration['Success']['data'];
environment: EnvironmentAndAccount['environment'];
}> = ({ data: { integration, meta, template }, environment }) => {
const { toast } = useToast();
const navigate = useNavigate();

Expand Down Expand Up @@ -59,6 +97,12 @@ export const SettingsGeneral: React.FC<{ data: GetIntegration['Success']['data']

return (
<div className="flex flex-col gap-8">
{integration.missing_fields.length > 0 && (
<Info variant="warning">
This integration cannot create connections until the following fields are configured: {missingFieldsMessage(template, integration)}
</Info>
)}

<div className="grid grid-cols-2 gap-10">
<InfoBloc title="API Provider">{integration?.provider}</InfoBloc>
<InfoBloc title="Integration ID">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ export const ShowIntegration: React.FC = () => {
<Button variant={tab === 'home' ? 'active' : 'zombie'}>Endpoints</Button>
</Link>
<Link to="./settings">
<Button variant={tab === 'settings' ? 'active' : 'zombie'}>Settings</Button>
<Button variant={tab === 'settings' ? 'active' : 'zombie'}>
Settings
{data.integration.missing_fields.length > 0 && <span className="ml-2 bg-yellow-base h-1.5 w-1.5 rounded-full inline-block"></span>}
</Button>
</Link>
</nav>
<Routes>
Expand Down
Loading