From 89780322367b1f26c848360ce7e23d7d0591db36 Mon Sep 17 00:00:00 2001 From: Adrian Galvan Date: Wed, 20 May 2026 17:02:49 -0700 Subject: [PATCH] Production-readiness improvements for GraphQL PoC frontend - Drop @defer; use separate DashboardAgentBriefing query - Update endpoint to /api/v1/plus/graphql - Scope ApolloProvider inside ProtectedRoute - Regenerate types (no @defer fragments) - Remove custom /graphql rewrite (covered by /api/v1/* rule) Co-Authored-By: Claude Opus 4.6 (1M context) --- clients/admin-ui/next.config.js | 7 - clients/admin-ui/schema.graphql | 7 - .../__generated__/graphql/fragment-masking.ts | 82 +- .../admin-ui/src/__generated__/graphql/gql.ts | 16 +- .../src/__generated__/graphql/graphql.ts | 885 +++--------------- .../src/__generated__/graphql/index.ts | 2 +- .../dashboard-graphql/apolloClient.ts | 6 +- .../src/features/dashboard-graphql/hooks.ts | 45 +- .../dashboard-graphql/queries.graphql | 19 +- .../dashboard-graphql/schema-string.ts | 3 +- .../src/mocks/dashboard-graphql/handlers.ts | 2 +- clients/admin-ui/src/pages/_app.tsx | 32 +- clients/package-lock.json | 60 +- 13 files changed, 266 insertions(+), 900 deletions(-) diff --git a/clients/admin-ui/next.config.js b/clients/admin-ui/next.config.js index f375e76a34b..e5376928c95 100644 --- a/clients/admin-ui/next.config.js +++ b/clients/admin-ui/next.config.js @@ -67,13 +67,6 @@ const nextConfig = { source: `/health`, destination: `${process.env.NEXT_PUBLIC_FIDESCTL_API_SERVER}/health`, }, - // GraphQL PoC: the Strawberry endpoint is mounted at /graphql (not under - // /api/v1), so proxy it to the backend for the real-BE path. In mock - // mode MSW intercepts /graphql before it reaches this rewrite. - { - source: `/graphql`, - destination: `${process.env.NEXT_PUBLIC_FIDESCTL_API_SERVER}/graphql`, - }, ]; }, }; diff --git a/clients/admin-ui/schema.graphql b/clients/admin-ui/schema.graphql index 411a1d172f2..21503068ff9 100644 --- a/clients/admin-ui/schema.graphql +++ b/clients/admin-ui/schema.graphql @@ -1,10 +1,3 @@ -directive @defer( - if: Boolean - label: String -) on FRAGMENT_SPREAD | INLINE_FRAGMENT - -directive @stream(if: Boolean, label: String, initialCount: Int = 0) on FIELD - enum ActionSeverity { critical high diff --git a/clients/admin-ui/src/__generated__/graphql/fragment-masking.ts b/clients/admin-ui/src/__generated__/graphql/fragment-masking.ts index 39ab74bd201..743a364fe18 100644 --- a/clients/admin-ui/src/__generated__/graphql/fragment-masking.ts +++ b/clients/admin-ui/src/__generated__/graphql/fragment-masking.ts @@ -1,111 +1,87 @@ /* eslint-disable */ -import type { - ResultOf, - DocumentTypeDecoration, - TypedDocumentNode, -} from "@graphql-typed-document-node/core"; -import type { FragmentDefinitionNode } from "graphql"; -import type { Incremental } from "./graphql"; +import type { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core'; +import type { FragmentDefinitionNode } from 'graphql'; +import type { Incremental } from './graphql'; -export type FragmentType< - TDocumentType extends DocumentTypeDecoration, -> = - TDocumentType extends DocumentTypeDecoration - ? [TType] extends [{ " $fragmentName"?: infer TKey }] - ? TKey extends string - ? { " $fragmentRefs"?: { [key in TKey]: TType } } - : never + +export type FragmentType> = TDocumentType extends DocumentTypeDecoration< + infer TType, + any +> + ? [TType] extends [{ ' $fragmentName'?: infer TKey }] + ? TKey extends string + ? { ' $fragmentRefs'?: { [key in TKey]: TType } } : never - : never; + : never + : never; // return non-nullable if `fragmentType` is non-nullable export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: FragmentType>, + fragmentType: FragmentType> ): TType; // return nullable if `fragmentType` is undefined export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: FragmentType> | undefined, + fragmentType: FragmentType> | undefined ): TType | undefined; // return nullable if `fragmentType` is nullable export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: FragmentType> | null, + fragmentType: FragmentType> | null ): TType | null; // return nullable if `fragmentType` is nullable or undefined export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: - | FragmentType> - | null - | undefined, + fragmentType: FragmentType> | null | undefined ): TType | null | undefined; // return array of non-nullable if `fragmentType` is array of non-nullable export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: Array>>, + fragmentType: Array>> ): Array; // return array of nullable if `fragmentType` is array of nullable export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: - | Array>> - | null - | undefined, + fragmentType: Array>> | null | undefined ): Array | null | undefined; // return readonly array of non-nullable if `fragmentType` is array of non-nullable export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: ReadonlyArray>>, + fragmentType: ReadonlyArray>> ): ReadonlyArray; // return readonly array of nullable if `fragmentType` is array of nullable export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: - | ReadonlyArray>> - | null - | undefined, + fragmentType: ReadonlyArray>> | null | undefined ): ReadonlyArray | null | undefined; export function useFragment( _documentNode: DocumentTypeDecoration, - fragmentType: - | FragmentType> - | Array>> - | ReadonlyArray>> - | null - | undefined, + fragmentType: FragmentType> | Array>> | ReadonlyArray>> | null | undefined ): TType | Array | ReadonlyArray | null | undefined { return fragmentType as any; } + export function makeFragmentData< F extends DocumentTypeDecoration, - FT extends ResultOf, + FT extends ResultOf >(data: FT, _fragment: F): FragmentType { return data as FragmentType; } export function isFragmentReady( queryNode: DocumentTypeDecoration, fragmentNode: TypedDocumentNode, - data: - | FragmentType, any>> - | null - | undefined, + data: FragmentType, any>> | null | undefined ): data is FragmentType { - const deferredFields = ( - queryNode as { - __meta__?: { deferredFields: Record }; - } - ).__meta__?.deferredFields; + const deferredFields = (queryNode as { __meta__?: { deferredFields: Record } }).__meta__ + ?.deferredFields; if (!deferredFields) return true; - const fragDef = fragmentNode.definitions[0] as - | FragmentDefinitionNode - | undefined; + const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined; const fragName = fragDef?.name?.value; const fields = (fragName && deferredFields[fragName]) || []; - return fields.length > 0 && fields.every((field) => data && field in data); + return fields.length > 0 && fields.every(field => data && field in data); } diff --git a/clients/admin-ui/src/__generated__/graphql/gql.ts b/clients/admin-ui/src/__generated__/graphql/gql.ts index ac6b9eae3c2..46774d0e913 100644 --- a/clients/admin-ui/src/__generated__/graphql/gql.ts +++ b/clients/admin-ui/src/__generated__/graphql/gql.ts @@ -1,6 +1,6 @@ /* eslint-disable */ -import * as types from "./graphql"; -import type { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-node/core"; +import * as types from './graphql'; +import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; /** * Map of all GraphQL operations in the project. @@ -14,11 +14,10 @@ import type { TypedDocumentNode as DocumentNode } from "@graphql-typed-document- * Learn more about it here: https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#reducing-bundle-size */ type Documents = { - 'query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n ... @defer(label: "agentBriefing") {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}': typeof types.DashboardOverviewDocument; + "query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n}\n\nquery DashboardAgentBriefing {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}": typeof types.DashboardOverviewDocument, }; const documents: Documents = { - 'query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n ... @defer(label: "agentBriefing") {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}': - types.DashboardOverviewDocument, + "query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n}\n\nquery DashboardAgentBriefing {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}": types.DashboardOverviewDocument, }; /** @@ -38,13 +37,10 @@ export function gql(source: string): unknown; /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function gql( - source: 'query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n ... @defer(label: "agentBriefing") {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}', -): (typeof documents)['query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n ... @defer(label: "agentBriefing") {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}']; +export function gql(source: "query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n}\n\nquery DashboardAgentBriefing {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}"): (typeof documents)["query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) {\n posture {\n score\n band\n diffPercent\n diffDirection\n agentAnnotation\n dimensions {\n dimension\n label\n weight\n score\n band\n }\n }\n trends(period: $trendPeriod) {\n period\n metrics {\n key\n value\n history\n metadata\n diff\n }\n }\n systemCoverage {\n totalSystems\n fullyClassified\n partiallyClassified\n unclassified\n withoutSteward\n coveragePercentage\n }\n privacyRequests {\n activeCount\n overdueCount\n statuses {\n inProgress\n pendingAction\n awaitingApproval\n }\n slaHealth {\n label\n onTrack\n approaching\n overdue\n }\n }\n astralis {\n activeConversations\n completedAssessments\n awaitingResponse\n risksIdentified\n }\n}\n\nquery DashboardAgentBriefing {\n agentBriefing {\n briefing\n quickActions {\n label\n actionType\n severity\n actionData\n }\n }\n}\n\nquery DashboardPriorityActions($page: Int! = 1, $size: Int! = 25, $dimension: String) {\n priorityActions(page: $page, size: $size, dimension: $dimension) {\n items {\n id\n type\n severity\n title\n message\n agentSummary\n dueDate\n actionData\n status\n }\n total\n page\n size\n pages\n }\n}\n\nquery DashboardActivityFeed($page: Int! = 1, $size: Int! = 20) {\n activityFeed(page: $page, size: $size) {\n items {\n actorType\n message\n timestamp\n }\n total\n page\n size\n pages\n }\n}"]; export function gql(source: string) { return (documents as any)[source] ?? {}; } -export type DocumentType> = - TDocumentNode extends DocumentNode ? TType : never; +export type DocumentType> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never; \ No newline at end of file diff --git a/clients/admin-ui/src/__generated__/graphql/graphql.ts b/clients/admin-ui/src/__generated__/graphql/graphql.ts index 344127e7e71..e2d8afbacdd 100644 --- a/clients/admin-ui/src/__generated__/graphql/graphql.ts +++ b/clients/admin-ui/src/__generated__/graphql/graphql.ts @@ -1,167 +1,154 @@ /* eslint-disable */ -import type { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-node/core"; +import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { - [K in keyof T]: T[K]; -}; -export type MakeOptional = Omit & { - [SubKey in K]?: Maybe; -}; -export type MakeMaybe = Omit & { - [SubKey in K]: Maybe; -}; -export type MakeEmpty< - T extends { [key: string]: unknown }, - K extends keyof T, -> = { [_ in K]?: never }; -export type Incremental = - | T - | { - [P in keyof T]?: P extends " $fragmentName" | "__typename" ? T[P] : never; - }; +export type Exact = { [K in keyof T]: T[K] }; +export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; +export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +export type MakeEmpty = { [_ in K]?: never }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } /** Date with time (isoformat) */ - DateTime: { input: string; output: string }; + DateTime: { input: string; output: string; } /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). */ - JSON: { input: Record; output: Record }; + JSON: { input: Record; output: Record; } }; export enum ActionSeverity { - Critical = "critical", - High = "high", - Low = "low", - Medium = "medium", + Critical = 'critical', + High = 'high', + Low = 'low', + Medium = 'medium' } export type ActivityFeedItem = { - __typename?: "ActivityFeedItem"; + __typename?: 'ActivityFeedItem'; actorType: ActorType; - message: Scalars["String"]["output"]; - timestamp: Scalars["DateTime"]["output"]; + message: Scalars['String']['output']; + timestamp: Scalars['DateTime']['output']; }; export type ActivityFeedPage = { - __typename?: "ActivityFeedPage"; + __typename?: 'ActivityFeedPage'; items: Array; - page: Scalars["Int"]["output"]; - pages: Scalars["Int"]["output"]; - size: Scalars["Int"]["output"]; - total: Scalars["Int"]["output"]; + page: Scalars['Int']['output']; + pages: Scalars['Int']['output']; + size: Scalars['Int']['output']; + total: Scalars['Int']['output']; }; export enum ActorType { - Agent = "agent", - User = "user", + Agent = 'agent', + User = 'user' } export type AgentBriefing = { - __typename?: "AgentBriefing"; - briefing: Scalars["String"]["output"]; + __typename?: 'AgentBriefing'; + briefing: Scalars['String']['output']; quickActions: Array; }; export type Astralis = { - __typename?: "Astralis"; - activeConversations: Scalars["Int"]["output"]; - awaitingResponse: Scalars["Int"]["output"]; - completedAssessments: Scalars["Int"]["output"]; - risksIdentified: Scalars["Int"]["output"]; + __typename?: 'Astralis'; + activeConversations: Scalars['Int']['output']; + awaitingResponse: Scalars['Int']['output']; + completedAssessments: Scalars['Int']['output']; + risksIdentified: Scalars['Int']['output']; }; export enum DashboardActionStatus { - Completed = "completed", - InProgress = "in_progress", - Pending = "pending", + Completed = 'completed', + InProgress = 'in_progress', + Pending = 'pending' } export enum DashboardActionType { - ClassificationReview = "classification_review", - ConsentAnomaly = "consent_anomaly", - DsrAction = "dsr_action", - PiaUpdate = "pia_update", - PolicyViolation = "policy_violation", - StewardAssignment = "steward_assignment", - SystemReview = "system_review", + ClassificationReview = 'classification_review', + ConsentAnomaly = 'consent_anomaly', + DsrAction = 'dsr_action', + PiaUpdate = 'pia_update', + PolicyViolation = 'policy_violation', + StewardAssignment = 'steward_assignment', + SystemReview = 'system_review' } export enum DiffDirection { - Down = "down", - Unchanged = "unchanged", - Up = "up", + Down = 'down', + Unchanged = 'unchanged', + Up = 'up' } export type Posture = { - __typename?: "Posture"; - agentAnnotation: Scalars["String"]["output"]; + __typename?: 'Posture'; + agentAnnotation: Scalars['String']['output']; band: PostureBand; diffDirection: DiffDirection; - diffPercent: Scalars["Float"]["output"]; + diffPercent: Scalars['Float']['output']; dimensions: Array; - score: Scalars["Float"]["output"]; + score: Scalars['Float']['output']; }; export enum PostureBand { - AtRisk = "at_risk", - Critical = "critical", - Excellent = "excellent", - Good = "good", + AtRisk = 'at_risk', + Critical = 'critical', + Excellent = 'excellent', + Good = 'good' } export type PostureDimension = { - __typename?: "PostureDimension"; + __typename?: 'PostureDimension'; band: PostureBand; - dimension: Scalars["String"]["output"]; - label: Scalars["String"]["output"]; - score: Scalars["Float"]["output"]; - weight: Scalars["Float"]["output"]; + dimension: Scalars['String']['output']; + label: Scalars['String']['output']; + score: Scalars['Float']['output']; + weight: Scalars['Float']['output']; }; export type PriorityAction = { - __typename?: "PriorityAction"; - actionData: Scalars["JSON"]["output"]; - agentSummary: Scalars["String"]["output"]; - dueDate?: Maybe; - id: Scalars["ID"]["output"]; - message: Scalars["String"]["output"]; + __typename?: 'PriorityAction'; + actionData: Scalars['JSON']['output']; + agentSummary: Scalars['String']['output']; + dueDate?: Maybe; + id: Scalars['ID']['output']; + message: Scalars['String']['output']; severity: ActionSeverity; status: DashboardActionStatus; - title: Scalars["String"]["output"]; + title: Scalars['String']['output']; type: DashboardActionType; }; export type PriorityActionsPage = { - __typename?: "PriorityActionsPage"; + __typename?: 'PriorityActionsPage'; items: Array; - page: Scalars["Int"]["output"]; - pages: Scalars["Int"]["output"]; - size: Scalars["Int"]["output"]; - total: Scalars["Int"]["output"]; + page: Scalars['Int']['output']; + pages: Scalars['Int']['output']; + size: Scalars['Int']['output']; + total: Scalars['Int']['output']; }; export type PrivacyRequestStatuses = { - __typename?: "PrivacyRequestStatuses"; - awaitingApproval: Scalars["Int"]["output"]; - inProgress: Scalars["Int"]["output"]; - pendingAction: Scalars["Int"]["output"]; + __typename?: 'PrivacyRequestStatuses'; + awaitingApproval: Scalars['Int']['output']; + inProgress: Scalars['Int']['output']; + pendingAction: Scalars['Int']['output']; }; export type PrivacyRequests = { - __typename?: "PrivacyRequests"; - activeCount: Scalars["Int"]["output"]; - overdueCount: Scalars["Int"]["output"]; + __typename?: 'PrivacyRequests'; + activeCount: Scalars['Int']['output']; + overdueCount: Scalars['Int']['output']; slaHealth: Array; statuses: PrivacyRequestStatuses; }; export type Query = { - __typename?: "Query"; + __typename?: 'Query'; activityFeed: ActivityFeedPage; agentBriefing: AgentBriefing; astralis: Astralis; @@ -172,66 +159,69 @@ export type Query = { trends: Trends; }; + export type QueryActivityFeedArgs = { - page?: Scalars["Int"]["input"]; - size?: Scalars["Int"]["input"]; + page?: Scalars['Int']['input']; + size?: Scalars['Int']['input']; }; + export type QueryPriorityActionsArgs = { action?: InputMaybe; - dimension?: InputMaybe; - page?: Scalars["Int"]["input"]; - size?: Scalars["Int"]["input"]; + dimension?: InputMaybe; + page?: Scalars['Int']['input']; + size?: Scalars['Int']['input']; status?: InputMaybe; }; + export type QueryTrendsArgs = { period?: TrendPeriod; }; export type QuickAction = { - __typename?: "QuickAction"; - actionData: Scalars["JSON"]["output"]; + __typename?: 'QuickAction'; + actionData: Scalars['JSON']['output']; actionType: DashboardActionType; - label: Scalars["String"]["output"]; + label: Scalars['String']['output']; severity: ActionSeverity; }; export type SlaHealthBucket = { - __typename?: "SLAHealthBucket"; - approaching: Scalars["Int"]["output"]; - label: Scalars["String"]["output"]; - onTrack: Scalars["Int"]["output"]; - overdue: Scalars["Int"]["output"]; + __typename?: 'SLAHealthBucket'; + approaching: Scalars['Int']['output']; + label: Scalars['String']['output']; + onTrack: Scalars['Int']['output']; + overdue: Scalars['Int']['output']; }; export type SystemCoverage = { - __typename?: "SystemCoverage"; - coveragePercentage: Scalars["Float"]["output"]; - fullyClassified: Scalars["Int"]["output"]; - partiallyClassified: Scalars["Int"]["output"]; - totalSystems: Scalars["Int"]["output"]; - unclassified: Scalars["Int"]["output"]; - withoutSteward: Scalars["Int"]["output"]; + __typename?: 'SystemCoverage'; + coveragePercentage: Scalars['Float']['output']; + fullyClassified: Scalars['Int']['output']; + partiallyClassified: Scalars['Int']['output']; + totalSystems: Scalars['Int']['output']; + unclassified: Scalars['Int']['output']; + withoutSteward: Scalars['Int']['output']; }; export type TrendMetric = { - __typename?: "TrendMetric"; - diff: Scalars["Float"]["output"]; - history: Array; - key: Scalars["String"]["output"]; - metadata: Scalars["JSON"]["output"]; - value: Scalars["Float"]["output"]; + __typename?: 'TrendMetric'; + diff: Scalars['Float']['output']; + history: Array; + key: Scalars['String']['output']; + metadata: Scalars['JSON']['output']; + value: Scalars['Float']['output']; }; export enum TrendPeriod { - NinetyDays = "ninety_days", - SixtyDays = "sixty_days", - ThirtyDays = "thirty_days", + NinetyDays = 'ninety_days', + SixtyDays = 'sixty_days', + ThirtyDays = 'thirty_days' } export type Trends = { - __typename?: "Trends"; + __typename?: 'Trends'; metrics: Array; period: TrendPeriod; }; @@ -240,640 +230,33 @@ export type DashboardOverviewQueryVariables = Exact<{ trendPeriod?: TrendPeriod; }>; -export type DashboardOverviewQuery = { - __typename?: "Query"; - posture: { - __typename?: "Posture"; - score: number; - band: PostureBand; - diffPercent: number; - diffDirection: DiffDirection; - agentAnnotation: string; - dimensions: Array<{ - __typename?: "PostureDimension"; - dimension: string; - label: string; - weight: number; - score: number; - band: PostureBand; - }>; - }; - trends: { - __typename?: "Trends"; - period: TrendPeriod; - metrics: Array<{ - __typename?: "TrendMetric"; - key: string; - value: number; - history: Array; - metadata: Record; - diff: number; - }>; - }; - systemCoverage: { - __typename?: "SystemCoverage"; - totalSystems: number; - fullyClassified: number; - partiallyClassified: number; - unclassified: number; - withoutSteward: number; - coveragePercentage: number; - }; - privacyRequests: { - __typename?: "PrivacyRequests"; - activeCount: number; - overdueCount: number; - statuses: { - __typename?: "PrivacyRequestStatuses"; - inProgress: number; - pendingAction: number; - awaitingApproval: number; - }; - slaHealth: Array<{ - __typename?: "SLAHealthBucket"; - label: string; - onTrack: number; - approaching: number; - overdue: number; - }>; - }; - astralis: { - __typename?: "Astralis"; - activeConversations: number; - completedAssessments: number; - awaitingResponse: number; - risksIdentified: number; - }; -} & ( - | { - __typename?: "Query"; - agentBriefing: { - __typename?: "AgentBriefing"; - briefing: string; - quickActions: Array<{ - __typename?: "QuickAction"; - label: string; - actionType: DashboardActionType; - severity: ActionSeverity; - actionData: Record; - }>; - }; - } - | { __typename?: "Query"; agentBriefing?: never } -); + +export type DashboardOverviewQuery = { __typename?: 'Query', posture: { __typename?: 'Posture', score: number, band: PostureBand, diffPercent: number, diffDirection: DiffDirection, agentAnnotation: string, dimensions: Array<{ __typename?: 'PostureDimension', dimension: string, label: string, weight: number, score: number, band: PostureBand }> }, trends: { __typename?: 'Trends', period: TrendPeriod, metrics: Array<{ __typename?: 'TrendMetric', key: string, value: number, history: Array, metadata: Record, diff: number }> }, systemCoverage: { __typename?: 'SystemCoverage', totalSystems: number, fullyClassified: number, partiallyClassified: number, unclassified: number, withoutSteward: number, coveragePercentage: number }, privacyRequests: { __typename?: 'PrivacyRequests', activeCount: number, overdueCount: number, statuses: { __typename?: 'PrivacyRequestStatuses', inProgress: number, pendingAction: number, awaitingApproval: number }, slaHealth: Array<{ __typename?: 'SLAHealthBucket', label: string, onTrack: number, approaching: number, overdue: number }> }, astralis: { __typename?: 'Astralis', activeConversations: number, completedAssessments: number, awaitingResponse: number, risksIdentified: number } }; + +export type DashboardAgentBriefingQueryVariables = Exact<{ [key: string]: never; }>; + + +export type DashboardAgentBriefingQuery = { __typename?: 'Query', agentBriefing: { __typename?: 'AgentBriefing', briefing: string, quickActions: Array<{ __typename?: 'QuickAction', label: string, actionType: DashboardActionType, severity: ActionSeverity, actionData: Record }> } }; export type DashboardPriorityActionsQueryVariables = Exact<{ - page?: Scalars["Int"]["input"]; - size?: Scalars["Int"]["input"]; - dimension?: InputMaybe; + page?: Scalars['Int']['input']; + size?: Scalars['Int']['input']; + dimension?: InputMaybe; }>; -export type DashboardPriorityActionsQuery = { - __typename?: "Query"; - priorityActions: { - __typename?: "PriorityActionsPage"; - total: number; - page: number; - size: number; - pages: number; - items: Array<{ - __typename?: "PriorityAction"; - id: string; - type: DashboardActionType; - severity: ActionSeverity; - title: string; - message: string; - agentSummary: string; - dueDate?: string | null; - actionData: Record; - status: DashboardActionStatus; - }>; - }; -}; + +export type DashboardPriorityActionsQuery = { __typename?: 'Query', priorityActions: { __typename?: 'PriorityActionsPage', total: number, page: number, size: number, pages: number, items: Array<{ __typename?: 'PriorityAction', id: string, type: DashboardActionType, severity: ActionSeverity, title: string, message: string, agentSummary: string, dueDate?: string | null, actionData: Record, status: DashboardActionStatus }> } }; export type DashboardActivityFeedQueryVariables = Exact<{ - page?: Scalars["Int"]["input"]; - size?: Scalars["Int"]["input"]; + page?: Scalars['Int']['input']; + size?: Scalars['Int']['input']; }>; -export type DashboardActivityFeedQuery = { - __typename?: "Query"; - activityFeed: { - __typename?: "ActivityFeedPage"; - total: number; - page: number; - size: number; - pages: number; - items: Array<{ - __typename?: "ActivityFeedItem"; - actorType: ActorType; - message: string; - timestamp: string; - }>; - }; -}; -export const DashboardOverviewDocument = { - kind: "Document", - definitions: [ - { - kind: "OperationDefinition", - operation: "query", - name: { kind: "Name", value: "DashboardOverview" }, - variableDefinitions: [ - { - kind: "VariableDefinition", - variable: { - kind: "Variable", - name: { kind: "Name", value: "trendPeriod" }, - }, - type: { - kind: "NonNullType", - type: { - kind: "NamedType", - name: { kind: "Name", value: "TrendPeriod" }, - }, - }, - defaultValue: { kind: "EnumValue", value: "thirty_days" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "posture" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "score" } }, - { kind: "Field", name: { kind: "Name", value: "band" } }, - { kind: "Field", name: { kind: "Name", value: "diffPercent" } }, - { - kind: "Field", - name: { kind: "Name", value: "diffDirection" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "agentAnnotation" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "dimensions" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "dimension" }, - }, - { kind: "Field", name: { kind: "Name", value: "label" } }, - { - kind: "Field", - name: { kind: "Name", value: "weight" }, - }, - { kind: "Field", name: { kind: "Name", value: "score" } }, - { kind: "Field", name: { kind: "Name", value: "band" } }, - ], - }, - }, - ], - }, - }, - { - kind: "Field", - name: { kind: "Name", value: "trends" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "period" }, - value: { - kind: "Variable", - name: { kind: "Name", value: "trendPeriod" }, - }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "period" } }, - { - kind: "Field", - name: { kind: "Name", value: "metrics" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "key" } }, - { kind: "Field", name: { kind: "Name", value: "value" } }, - { - kind: "Field", - name: { kind: "Name", value: "history" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "metadata" }, - }, - { kind: "Field", name: { kind: "Name", value: "diff" } }, - ], - }, - }, - ], - }, - }, - { - kind: "Field", - name: { kind: "Name", value: "systemCoverage" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "totalSystems" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "fullyClassified" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "partiallyClassified" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "unclassified" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "withoutSteward" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "coveragePercentage" }, - }, - ], - }, - }, - { - kind: "Field", - name: { kind: "Name", value: "privacyRequests" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "activeCount" } }, - { - kind: "Field", - name: { kind: "Name", value: "overdueCount" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "statuses" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "inProgress" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "pendingAction" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "awaitingApproval" }, - }, - ], - }, - }, - { - kind: "Field", - name: { kind: "Name", value: "slaHealth" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "label" } }, - { - kind: "Field", - name: { kind: "Name", value: "onTrack" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "approaching" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "overdue" }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "Field", - name: { kind: "Name", value: "astralis" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "activeConversations" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "completedAssessments" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "awaitingResponse" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "risksIdentified" }, - }, - ], - }, - }, - { - kind: "InlineFragment", - directives: [ - { - kind: "Directive", - name: { kind: "Name", value: "defer" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "label" }, - value: { - kind: "StringValue", - value: "agentBriefing", - block: false, - }, - }, - ], - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "agentBriefing" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "briefing" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "quickActions" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "label" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "actionType" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "severity" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "actionData" }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - DashboardOverviewQuery, - DashboardOverviewQueryVariables ->; -export const DashboardPriorityActionsDocument = { - kind: "Document", - definitions: [ - { - kind: "OperationDefinition", - operation: "query", - name: { kind: "Name", value: "DashboardPriorityActions" }, - variableDefinitions: [ - { - kind: "VariableDefinition", - variable: { kind: "Variable", name: { kind: "Name", value: "page" } }, - type: { - kind: "NonNullType", - type: { kind: "NamedType", name: { kind: "Name", value: "Int" } }, - }, - defaultValue: { kind: "IntValue", value: "1" }, - }, - { - kind: "VariableDefinition", - variable: { kind: "Variable", name: { kind: "Name", value: "size" } }, - type: { - kind: "NonNullType", - type: { kind: "NamedType", name: { kind: "Name", value: "Int" } }, - }, - defaultValue: { kind: "IntValue", value: "25" }, - }, - { - kind: "VariableDefinition", - variable: { - kind: "Variable", - name: { kind: "Name", value: "dimension" }, - }, - type: { kind: "NamedType", name: { kind: "Name", value: "String" } }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "priorityActions" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "page" }, - value: { - kind: "Variable", - name: { kind: "Name", value: "page" }, - }, - }, - { - kind: "Argument", - name: { kind: "Name", value: "size" }, - value: { - kind: "Variable", - name: { kind: "Name", value: "size" }, - }, - }, - { - kind: "Argument", - name: { kind: "Name", value: "dimension" }, - value: { - kind: "Variable", - name: { kind: "Name", value: "dimension" }, - }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "items" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "type" } }, - { - kind: "Field", - name: { kind: "Name", value: "severity" }, - }, - { kind: "Field", name: { kind: "Name", value: "title" } }, - { - kind: "Field", - name: { kind: "Name", value: "message" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "agentSummary" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "dueDate" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "actionData" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "status" }, - }, - ], - }, - }, - { kind: "Field", name: { kind: "Name", value: "total" } }, - { kind: "Field", name: { kind: "Name", value: "page" } }, - { kind: "Field", name: { kind: "Name", value: "size" } }, - { kind: "Field", name: { kind: "Name", value: "pages" } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - DashboardPriorityActionsQuery, - DashboardPriorityActionsQueryVariables ->; -export const DashboardActivityFeedDocument = { - kind: "Document", - definitions: [ - { - kind: "OperationDefinition", - operation: "query", - name: { kind: "Name", value: "DashboardActivityFeed" }, - variableDefinitions: [ - { - kind: "VariableDefinition", - variable: { kind: "Variable", name: { kind: "Name", value: "page" } }, - type: { - kind: "NonNullType", - type: { kind: "NamedType", name: { kind: "Name", value: "Int" } }, - }, - defaultValue: { kind: "IntValue", value: "1" }, - }, - { - kind: "VariableDefinition", - variable: { kind: "Variable", name: { kind: "Name", value: "size" } }, - type: { - kind: "NonNullType", - type: { kind: "NamedType", name: { kind: "Name", value: "Int" } }, - }, - defaultValue: { kind: "IntValue", value: "20" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "activityFeed" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "page" }, - value: { - kind: "Variable", - name: { kind: "Name", value: "page" }, - }, - }, - { - kind: "Argument", - name: { kind: "Name", value: "size" }, - value: { - kind: "Variable", - name: { kind: "Name", value: "size" }, - }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "items" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "actorType" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "message" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "timestamp" }, - }, - ], - }, - }, - { kind: "Field", name: { kind: "Name", value: "total" } }, - { kind: "Field", name: { kind: "Name", value: "page" } }, - { kind: "Field", name: { kind: "Name", value: "size" } }, - { kind: "Field", name: { kind: "Name", value: "pages" } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode< - DashboardActivityFeedQuery, - DashboardActivityFeedQueryVariables ->; +export type DashboardActivityFeedQuery = { __typename?: 'Query', activityFeed: { __typename?: 'ActivityFeedPage', total: number, page: number, size: number, pages: number, items: Array<{ __typename?: 'ActivityFeedItem', actorType: ActorType, message: string, timestamp: string }> } }; + + +export const DashboardOverviewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DashboardOverview"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"trendPeriod"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"TrendPeriod"}}},"defaultValue":{"kind":"EnumValue","value":"thirty_days"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"posture"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"score"}},{"kind":"Field","name":{"kind":"Name","value":"band"}},{"kind":"Field","name":{"kind":"Name","value":"diffPercent"}},{"kind":"Field","name":{"kind":"Name","value":"diffDirection"}},{"kind":"Field","name":{"kind":"Name","value":"agentAnnotation"}},{"kind":"Field","name":{"kind":"Name","value":"dimensions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"dimension"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"score"}},{"kind":"Field","name":{"kind":"Name","value":"band"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"trends"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"period"},"value":{"kind":"Variable","name":{"kind":"Name","value":"trendPeriod"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"period"}},{"kind":"Field","name":{"kind":"Name","value":"metrics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"history"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"}},{"kind":"Field","name":{"kind":"Name","value":"diff"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"systemCoverage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalSystems"}},{"kind":"Field","name":{"kind":"Name","value":"fullyClassified"}},{"kind":"Field","name":{"kind":"Name","value":"partiallyClassified"}},{"kind":"Field","name":{"kind":"Name","value":"unclassified"}},{"kind":"Field","name":{"kind":"Name","value":"withoutSteward"}},{"kind":"Field","name":{"kind":"Name","value":"coveragePercentage"}}]}},{"kind":"Field","name":{"kind":"Name","value":"privacyRequests"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeCount"}},{"kind":"Field","name":{"kind":"Name","value":"overdueCount"}},{"kind":"Field","name":{"kind":"Name","value":"statuses"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inProgress"}},{"kind":"Field","name":{"kind":"Name","value":"pendingAction"}},{"kind":"Field","name":{"kind":"Name","value":"awaitingApproval"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slaHealth"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"onTrack"}},{"kind":"Field","name":{"kind":"Name","value":"approaching"}},{"kind":"Field","name":{"kind":"Name","value":"overdue"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"astralis"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeConversations"}},{"kind":"Field","name":{"kind":"Name","value":"completedAssessments"}},{"kind":"Field","name":{"kind":"Name","value":"awaitingResponse"}},{"kind":"Field","name":{"kind":"Name","value":"risksIdentified"}}]}}]}}]} as unknown as DocumentNode; +export const DashboardAgentBriefingDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DashboardAgentBriefing"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"agentBriefing"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"briefing"}},{"kind":"Field","name":{"kind":"Name","value":"quickActions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"actionType"}},{"kind":"Field","name":{"kind":"Name","value":"severity"}},{"kind":"Field","name":{"kind":"Name","value":"actionData"}}]}}]}}]}}]} as unknown as DocumentNode; +export const DashboardPriorityActionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DashboardPriorityActions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"page"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"1"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"size"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"25"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"dimension"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"priorityActions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"page"},"value":{"kind":"Variable","name":{"kind":"Name","value":"page"}}},{"kind":"Argument","name":{"kind":"Name","value":"size"},"value":{"kind":"Variable","name":{"kind":"Name","value":"size"}}},{"kind":"Argument","name":{"kind":"Name","value":"dimension"},"value":{"kind":"Variable","name":{"kind":"Name","value":"dimension"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"severity"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"agentSummary"}},{"kind":"Field","name":{"kind":"Name","value":"dueDate"}},{"kind":"Field","name":{"kind":"Name","value":"actionData"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}},{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"page"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"pages"}}]}}]}}]} as unknown as DocumentNode; +export const DashboardActivityFeedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DashboardActivityFeed"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"page"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"1"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"size"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"20"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activityFeed"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"page"},"value":{"kind":"Variable","name":{"kind":"Name","value":"page"}}},{"kind":"Argument","name":{"kind":"Name","value":"size"},"value":{"kind":"Variable","name":{"kind":"Name","value":"size"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"actorType"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}}]}},{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"page"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"pages"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/clients/admin-ui/src/__generated__/graphql/index.ts b/clients/admin-ui/src/__generated__/graphql/index.ts index 0ea4a91cf8a..f51599168fb 100644 --- a/clients/admin-ui/src/__generated__/graphql/index.ts +++ b/clients/admin-ui/src/__generated__/graphql/index.ts @@ -1,2 +1,2 @@ export * from "./fragment-masking"; -export * from "./gql"; +export * from "./gql"; \ No newline at end of file diff --git a/clients/admin-ui/src/features/dashboard-graphql/apolloClient.ts b/clients/admin-ui/src/features/dashboard-graphql/apolloClient.ts index 8208d3754f8..c383cf403db 100644 --- a/clients/admin-ui/src/features/dashboard-graphql/apolloClient.ts +++ b/clients/admin-ui/src/features/dashboard-graphql/apolloClient.ts @@ -8,12 +8,8 @@ import { setContext } from "@apollo/client/link/context"; import { addCommonHeaders } from "~/features/common/CommonHeaders"; -// The Strawberry endpoint is mounted at the app root (/graphql), NOT under -// the /api/v1 prefix that NEXT_PUBLIC_FIDESCTL_API points at. Post to the -// relative /graphql path: in dev the Next rewrite proxies it to the backend, -// and in mock mode MSW intercepts it. const httpLink = createHttpLink({ - uri: "/graphql", + uri: "/api/v1/plus/graphql", }); /** diff --git a/clients/admin-ui/src/features/dashboard-graphql/hooks.ts b/clients/admin-ui/src/features/dashboard-graphql/hooks.ts index cd5c69d0691..c2b5eca159f 100644 --- a/clients/admin-ui/src/features/dashboard-graphql/hooks.ts +++ b/clients/admin-ui/src/features/dashboard-graphql/hooks.ts @@ -1,34 +1,29 @@ /** * Drop-in GraphQL replacements for the dashboard RTK Query hooks (Apollo). * - * The six static read-only cards share **one** combined `DashboardOverview` - * query with `@defer` on `agentBriefing`. Apollo deduplicates concurrent - * `useQuery(DashboardOverviewDocument)` calls with identical variables into - * a single network request, so all six hooks below issue exactly one POST - * — verify in DevTools → Network. The slow LLM-backed `agentBriefing` - * arrives in a second `multipart/mixed` chunk and re-renders only the - * banner; the rest of the dashboard paints from the initial chunk. + * The five static read-only cards share one combined `DashboardOverview` + * query. Apollo deduplicates concurrent `useQuery(DashboardOverviewDocument)` + * calls with identical variables into a single network request, so all five + * hooks below issue exactly one POST. * - * `priorityActions` and `activityFeed` keep their own per-card queries — - * their interactive variables (dimension filter, infinite-scroll - * pagination) make them poor combined-query candidates. + * `agentBriefing` is a separate query because the LLM-backed briefing is + * slow and should not block the rest of the dashboard from painting. + * + * `priorityActions` and `activityFeed` keep their own per-card queries -- + * their interactive variables (dimension filter, infinite-scroll pagination) + * make them poor combined-query candidates. * * Each hook keeps the exact name, call signature, and return shape of its * counterpart in ~/features/dashboard/dashboard.slice and maps the * camelCase GraphQL response back onto the existing snake_case * ~/features/dashboard/types interfaces. Cards change by one import line. - * - * The mapped result is memoised on the raw query slice. Apollo returns a - * stable `data` reference until the result changes, so the mapped object - * identity is stable too — without this, consumers that key effects on - * `data` (e.g. useInfiniteActivityFeed) re-fire setState every render and - * React throws "Maximum update depth exceeded". */ import { useQuery } from "@apollo/client"; import { useMemo } from "react"; import { DashboardActivityFeedDocument, + DashboardAgentBriefingDocument, DashboardOverviewDocument, DashboardPriorityActionsDocument, TrendPeriod as GqlTrendPeriod, @@ -51,25 +46,19 @@ import { TrendPeriod, } from "~/features/dashboard/types"; -// REST TrendPeriod values ("30d") differ from the GraphQL enum names -// ("thirty_days"); the rest of the enums share the same string values. const TREND_PERIOD_TO_GQL: Record = { [TrendPeriod.THIRTY_DAYS]: GqlTrendPeriod.ThirtyDays, [TrendPeriod.SIXTY_DAYS]: GqlTrendPeriod.SixtyDays, [TrendPeriod.NINETY_DAYS]: GqlTrendPeriod.NinetyDays, }; -// All six static hooks call the combined query with the same default -// trendPeriod so Apollo merges them into one request. The trends hook -// accepts a `period` param for drop-in parity; passing a non-default -// period would (correctly) refetch the whole combined query. const useDashboardOverview = (period: TrendPeriod = TrendPeriod.THIRTY_DAYS) => useQuery(DashboardOverviewDocument, { variables: { trendPeriod: TREND_PERIOD_TO_GQL[period] }, }); export const useGetAgentBriefingQuery = () => { - const { data } = useDashboardOverview(); + const { data, loading } = useQuery(DashboardAgentBriefingDocument); const briefing = data?.agentBriefing; const mapped = useMemo( () => @@ -86,9 +75,7 @@ export const useGetAgentBriefingQuery = () => { : undefined, [briefing], ); - // agentBriefing is @defer'd — it stays absent until the second multipart - // chunk arrives, so the dashboard renders without waiting on it. - return { data: mapped, isLoading: !briefing }; + return { data: mapped, isLoading: loading }; }; export const useGetDashboardPostureQuery = () => { @@ -277,15 +264,11 @@ interface ActivityFeedParams { interface ActivityFeedOptions { pollingInterval?: number; - // Accept (and ignore) the other RTK Query options the call site passes - // (skipPollingIfUnfocused, refetchOnMountOrArgChange, ...). [key: string]: unknown; } export const useGetActivityFeedQuery = ( params?: ActivityFeedParams | void, - // RTK polling options are accepted for signature parity. Polling maps to - // Apollo's pollInterval; the rest are no-ops for the PoC. options?: ActivityFeedOptions, ) => { const { page, size } = params ?? {}; @@ -300,8 +283,6 @@ export const useGetActivityFeedQuery = ( af ? { items: af.items.map((i) => ({ - // The GraphQL ActivityFeedItem has no id; synthesise a stable - // one so the infinite-scroll dedupe keeps working unchanged. id: `${i.timestamp}__${i.message}`, actor_type: i.actorType as unknown as "user" | "system", message: i.message, diff --git a/clients/admin-ui/src/features/dashboard-graphql/queries.graphql b/clients/admin-ui/src/features/dashboard-graphql/queries.graphql index 82fbf082c15..d3c6e9e5e35 100644 --- a/clients/admin-ui/src/features/dashboard-graphql/queries.graphql +++ b/clients/admin-ui/src/features/dashboard-graphql/queries.graphql @@ -52,15 +52,16 @@ query DashboardOverview($trendPeriod: TrendPeriod! = thirty_days) { awaitingResponse risksIdentified } - ... @defer(label: "agentBriefing") { - agentBriefing { - briefing - quickActions { - label - actionType - severity - actionData - } +} + +query DashboardAgentBriefing { + agentBriefing { + briefing + quickActions { + label + actionType + severity + actionData } } } diff --git a/clients/admin-ui/src/features/dashboard-graphql/schema-string.ts b/clients/admin-ui/src/features/dashboard-graphql/schema-string.ts index e90d06b19ff..af50d631064 100644 --- a/clients/admin-ui/src/features/dashboard-graphql/schema-string.ts +++ b/clients/admin-ui/src/features/dashboard-graphql/schema-string.ts @@ -2,5 +2,4 @@ // AUTOGENERATED by scripts/sync-graphql-sdl.mjs. Do not edit by hand. // Run `npm run graphql:generate` to refresh. -export const dashboardSchemaSDL = - 'directive @defer(if: Boolean, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT\n\ndirective @stream(if: Boolean, label: String, initialCount: Int = 0) on FIELD\n\nenum ActionSeverity {\n critical\n high\n medium\n low\n}\n\ntype ActivityFeedItem {\n actorType: ActorType!\n message: String!\n timestamp: DateTime!\n}\n\ntype ActivityFeedPage {\n items: [ActivityFeedItem!]!\n total: Int!\n page: Int!\n size: Int!\n pages: Int!\n}\n\nenum ActorType {\n user\n agent\n}\n\ntype AgentBriefing {\n briefing: String!\n quickActions: [QuickAction!]!\n}\n\ntype Astralis {\n activeConversations: Int!\n completedAssessments: Int!\n awaitingResponse: Int!\n risksIdentified: Int!\n}\n\nenum DashboardActionStatus {\n pending\n in_progress\n completed\n}\n\nenum DashboardActionType {\n classification_review\n dsr_action\n system_review\n steward_assignment\n consent_anomaly\n policy_violation\n pia_update\n}\n\n"""Date with time (isoformat)"""\nscalar DateTime\n\nenum DiffDirection {\n up\n down\n unchanged\n}\n\n"""\nThe `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf).\n"""\nscalar JSON @specifiedBy(url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf")\n\ntype Posture {\n score: Float!\n band: PostureBand!\n diffPercent: Float!\n diffDirection: DiffDirection!\n agentAnnotation: String!\n dimensions: [PostureDimension!]!\n}\n\nenum PostureBand {\n critical\n at_risk\n good\n excellent\n}\n\ntype PostureDimension {\n dimension: String!\n label: String!\n weight: Float!\n score: Float!\n band: PostureBand!\n}\n\ntype PriorityAction {\n id: ID!\n type: DashboardActionType!\n severity: ActionSeverity!\n title: String!\n message: String!\n agentSummary: String!\n dueDate: DateTime\n actionData: JSON!\n status: DashboardActionStatus!\n}\n\ntype PriorityActionsPage {\n items: [PriorityAction!]!\n total: Int!\n page: Int!\n size: Int!\n pages: Int!\n}\n\ntype PrivacyRequestStatuses {\n inProgress: Int!\n pendingAction: Int!\n awaitingApproval: Int!\n}\n\ntype PrivacyRequests {\n activeCount: Int!\n statuses: PrivacyRequestStatuses!\n overdueCount: Int!\n slaHealth: [SLAHealthBucket!]!\n}\n\ntype Query {\n agentBriefing: AgentBriefing!\n posture: Posture!\n trends(period: TrendPeriod! = thirty_days): Trends!\n astralis: Astralis!\n activityFeed(page: Int! = 1, size: Int! = 20): ActivityFeedPage!\n privacyRequests: PrivacyRequests!\n systemCoverage: SystemCoverage!\n priorityActions(page: Int! = 1, size: Int! = 8, action: DashboardActionType = null, status: DashboardActionStatus = null, dimension: String = null): PriorityActionsPage!\n}\n\ntype QuickAction {\n label: String!\n actionType: DashboardActionType!\n actionData: JSON!\n severity: ActionSeverity!\n}\n\ntype SLAHealthBucket {\n label: String!\n onTrack: Int!\n approaching: Int!\n overdue: Int!\n}\n\ntype SystemCoverage {\n totalSystems: Int!\n fullyClassified: Int!\n partiallyClassified: Int!\n unclassified: Int!\n withoutSteward: Int!\n coveragePercentage: Float!\n}\n\ntype TrendMetric {\n key: String!\n value: Float!\n history: [Float!]!\n metadata: JSON!\n diff: Float!\n}\n\nenum TrendPeriod {\n thirty_days\n sixty_days\n ninety_days\n}\n\ntype Trends {\n period: TrendPeriod!\n metrics: [TrendMetric!]!\n}\n'; +export const dashboardSchemaSDL = "enum ActionSeverity {\n critical\n high\n medium\n low\n}\n\ntype ActivityFeedItem {\n actorType: ActorType!\n message: String!\n timestamp: DateTime!\n}\n\ntype ActivityFeedPage {\n items: [ActivityFeedItem!]!\n total: Int!\n page: Int!\n size: Int!\n pages: Int!\n}\n\nenum ActorType {\n user\n agent\n}\n\ntype AgentBriefing {\n briefing: String!\n quickActions: [QuickAction!]!\n}\n\ntype Astralis {\n activeConversations: Int!\n completedAssessments: Int!\n awaitingResponse: Int!\n risksIdentified: Int!\n}\n\nenum DashboardActionStatus {\n pending\n in_progress\n completed\n}\n\nenum DashboardActionType {\n classification_review\n dsr_action\n system_review\n steward_assignment\n consent_anomaly\n policy_violation\n pia_update\n}\n\n\"\"\"\nDate with time (isoformat)\n\"\"\"\nscalar DateTime\n\nenum DiffDirection {\n up\n down\n unchanged\n}\n\n\"\"\"\nThe `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf).\n\"\"\"\nscalar JSON\n @specifiedBy(\n url: \"https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf\"\n )\n\ntype Posture {\n score: Float!\n band: PostureBand!\n diffPercent: Float!\n diffDirection: DiffDirection!\n agentAnnotation: String!\n dimensions: [PostureDimension!]!\n}\n\nenum PostureBand {\n critical\n at_risk\n good\n excellent\n}\n\ntype PostureDimension {\n dimension: String!\n label: String!\n weight: Float!\n score: Float!\n band: PostureBand!\n}\n\ntype PriorityAction {\n id: ID!\n type: DashboardActionType!\n severity: ActionSeverity!\n title: String!\n message: String!\n agentSummary: String!\n dueDate: DateTime\n actionData: JSON!\n status: DashboardActionStatus!\n}\n\ntype PriorityActionsPage {\n items: [PriorityAction!]!\n total: Int!\n page: Int!\n size: Int!\n pages: Int!\n}\n\ntype PrivacyRequestStatuses {\n inProgress: Int!\n pendingAction: Int!\n awaitingApproval: Int!\n}\n\ntype PrivacyRequests {\n activeCount: Int!\n statuses: PrivacyRequestStatuses!\n overdueCount: Int!\n slaHealth: [SLAHealthBucket!]!\n}\n\ntype Query {\n agentBriefing: AgentBriefing!\n posture: Posture!\n trends(period: TrendPeriod! = thirty_days): Trends!\n astralis: Astralis!\n activityFeed(page: Int! = 1, size: Int! = 20): ActivityFeedPage!\n privacyRequests: PrivacyRequests!\n systemCoverage: SystemCoverage!\n priorityActions(\n page: Int! = 1\n size: Int! = 8\n action: DashboardActionType = null\n status: DashboardActionStatus = null\n dimension: String = null\n ): PriorityActionsPage!\n}\n\ntype QuickAction {\n label: String!\n actionType: DashboardActionType!\n actionData: JSON!\n severity: ActionSeverity!\n}\n\ntype SLAHealthBucket {\n label: String!\n onTrack: Int!\n approaching: Int!\n overdue: Int!\n}\n\ntype SystemCoverage {\n totalSystems: Int!\n fullyClassified: Int!\n partiallyClassified: Int!\n unclassified: Int!\n withoutSteward: Int!\n coveragePercentage: Float!\n}\n\ntype TrendMetric {\n key: String!\n value: Float!\n history: [Float!]!\n metadata: JSON!\n diff: Float!\n}\n\nenum TrendPeriod {\n thirty_days\n sixty_days\n ninety_days\n}\n\ntype Trends {\n period: TrendPeriod!\n metrics: [TrendMetric!]!\n}\n"; diff --git a/clients/admin-ui/src/mocks/dashboard-graphql/handlers.ts b/clients/admin-ui/src/mocks/dashboard-graphql/handlers.ts index 1041f361318..6d5e26d8550 100644 --- a/clients/admin-ui/src/mocks/dashboard-graphql/handlers.ts +++ b/clients/admin-ui/src/mocks/dashboard-graphql/handlers.ts @@ -102,7 +102,7 @@ const mockedSchema = addMocksToSchema({ }); export const dashboardGraphqlHandlers = () => [ - rest.post(/\/graphql$/, async (req, res, ctx) => { + rest.post(/\/api\/v1\/plus\/graphql$/, async (req, res, ctx) => { const body = (await req.json()) as { query?: string; operationName?: string; diff --git a/clients/admin-ui/src/pages/_app.tsx b/clients/admin-ui/src/pages/_app.tsx index 2b1ba575846..fe8d3faef9e 100644 --- a/clients/admin-ui/src/pages/_app.tsx +++ b/clients/admin-ui/src/pages/_app.tsx @@ -51,19 +51,15 @@ const MyApp = ({ Component, pageProps }: AppProps) => { - - - - {Component === Login || - Component === LoginWithOIDC || - Component === ForgotPassword ? ( - // Only the login page is accessible while logged out. If there is - // a use case for more unprotected routes, Next has a guide for - // per-page layouts: - // https://nextjs.org/docs/basic-features/layouts#per-page-layouts - - ) : ( - + + + {Component === Login || + Component === LoginWithOIDC || + Component === ForgotPassword ? ( + + ) : ( + + @@ -76,11 +72,11 @@ const MyApp = ({ Component, pageProps }: AppProps) => { - - )} - - - + + + )} + + diff --git a/clients/package-lock.json b/clients/package-lock.json index 403cf864419..327d17c4d2e 100644 --- a/clients/package-lock.json +++ b/clients/package-lock.json @@ -8085,6 +8085,7 @@ "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", "hasInstallScript": true, "optional": true, + "peer": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -8125,6 +8126,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8144,6 +8146,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8163,6 +8166,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8182,6 +8186,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8201,6 +8206,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8220,6 +8226,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8239,6 +8246,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8258,6 +8266,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8277,6 +8286,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8296,6 +8306,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8315,6 +8326,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8334,6 +8346,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -8353,6 +8366,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -9360,6 +9374,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "android" @@ -9372,6 +9387,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -9384,6 +9400,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -9396,6 +9413,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -9408,6 +9426,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -9420,6 +9439,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -9432,6 +9452,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9444,6 +9465,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9456,6 +9478,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9468,6 +9491,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9480,6 +9504,7 @@ "cpu": [ "loong64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9492,6 +9517,7 @@ "cpu": [ "loong64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9504,6 +9530,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9516,6 +9543,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9528,6 +9556,7 @@ "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9540,6 +9569,7 @@ "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9552,6 +9582,7 @@ "cpu": [ "s390x" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9564,6 +9595,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9576,6 +9608,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -9588,6 +9621,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "openbsd" @@ -9600,6 +9634,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "openharmony" @@ -9612,6 +9647,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -9624,6 +9660,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -9636,6 +9673,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -9648,6 +9686,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -16102,6 +16141,7 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "optional": true, + "peer": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -16493,6 +16533,7 @@ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "dev": true, "optional": true, + "peer": true, "dependencies": { "prr": "~1.0.1" }, @@ -18646,6 +18687,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -20020,6 +20062,7 @@ "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", "dev": true, "optional": true, + "peer": true, "bin": { "image-size": "bin/image-size.js" }, @@ -22580,6 +22623,7 @@ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "optional": true, + "peer": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -22594,6 +22638,7 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -22604,6 +22649,7 @@ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "optional": true, + "peer": true, "bin": { "semver": "bin/semver" } @@ -22614,6 +22660,7 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -24389,6 +24436,7 @@ "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", "dev": true, "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.3", "sax": "^1.2.4" @@ -24406,6 +24454,7 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -24531,7 +24580,8 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "optional": true + "optional": true, + "peer": true }, "node_modules/node-domexception": { "version": "1.0.0", @@ -26878,7 +26928,8 @@ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "dev": true, - "optional": true + "optional": true, + "peer": true }, "node_modules/psl": { "version": "1.15.0", @@ -28453,7 +28504,8 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "dev": true, - "optional": true + "optional": true, + "peer": true }, "node_modules/saxes": { "version": "6.0.0", @@ -32199,7 +32251,7 @@ "version": "8.20.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0"