(props: { integrations: readonly Integration[] })
| 550 | // --------------------------------------------------------------------------- |
| 551 | |
| 552 | function IntegrationGrid(props: { integrations: readonly Integration[] }) { |
| 553 | const integrationPlugins = useIntegrationPlugins(); |
| 554 | const pluginByKind = useMemo(() => { |
| 555 | const out = new Map<string, IntegrationPlugin>(); |
| 556 | for (const p of integrationPlugins) out.set(p.key, p); |
| 557 | return out; |
| 558 | }, [integrationPlugins]); |
| 559 | |
| 560 | const items = useMemo(() => groupIntegrations(props.integrations), [props.integrations]); |
| 561 | |
| 562 | const renderEntry = (integration: Integration) => { |
| 563 | const pluginKey = KIND_TO_PLUGIN_KEY[integration.kind] ?? integration.kind; |
| 564 | const plugin = pluginByKind.get(pluginKey); |
| 565 | const SummaryComponent = plugin?.summary; |
| 566 | const slug = String(integration.slug); |
| 567 | const name = integration.name || slug; |
| 568 | return ( |
| 569 | <CardStackEntry key={slug} asChild searchText={`${name} ${slug} ${integration.kind}`}> |
| 570 | <Link |
| 571 | to="/{-$orgSlug}/integrations/$namespace" |
| 572 | params={{ namespace: slug }} |
| 573 | data-testid={`integration-entry-${slug}`} |
| 574 | > |
| 575 | <IntegrationIconWithAccount |
| 576 | icon={integrationPresetIconUrl( |
| 577 | { id: slug, kind: integration.kind, name, url: integration.displayUrl }, |
| 578 | integrationPlugins, |
| 579 | )} |
| 580 | integrationId={slug} |
| 581 | url={integration.displayUrl ?? integrationInferredUrl({ id: slug, name }) ?? undefined} |
| 582 | /> |
| 583 | <CardStackEntryContent> |
| 584 | <CardStackEntryTitle>{name}</CardStackEntryTitle> |
| 585 | <CardStackEntryDescription>{slug}</CardStackEntryDescription> |
| 586 | </CardStackEntryContent> |
| 587 | <CardStackEntryActions> |
| 588 | {SummaryComponent && ( |
| 589 | <Suspense fallback={null}> |
| 590 | <SummaryComponent integrationId={slug} /> |
| 591 | </Suspense> |
| 592 | )} |
| 593 | <IntegrationHealthSummary integration={integration.slug} /> |
| 594 | </CardStackEntryActions> |
| 595 | </Link> |
| 596 | </CardStackEntry> |
| 597 | ); |
| 598 | }; |
| 599 | |
| 600 | const rendered: ReactNode[] = []; |
| 601 | let flatRun: Integration[] = []; |
| 602 | const flushFlat = () => { |
| 603 | if (flatRun.length === 0) return; |
| 604 | const run = flatRun; |
| 605 | flatRun = []; |
| 606 | rendered.push( |
| 607 | <CardStack key={`flat-${String(run[0]!.slug)}`} searchable> |
| 608 | <CardStackContent>{run.map(renderEntry)}</CardStackContent> |
| 609 | </CardStack>, |
nothing calls this directly
no test coverage detected