@anyshift/backstage-plugin-anyshift 0.1.0-beta.2 → 0.1.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +14 -1
  3. package/dist/api/AnyshiftApi.esm.js +61 -7
  4. package/dist/api/AnyshiftApi.esm.js.map +1 -1
  5. package/dist/components/ask/AskAnyshiftCard.esm.js +348 -0
  6. package/dist/components/ask/AskAnyshiftCard.esm.js.map +1 -0
  7. package/dist/components/ask/askPresenters.esm.js +1203 -0
  8. package/dist/components/ask/askPresenters.esm.js.map +1 -0
  9. package/dist/components/ask/askScope.esm.js +27 -0
  10. package/dist/components/ask/askScope.esm.js.map +1 -0
  11. package/dist/components/ask/askSuggestions.esm.js +41 -0
  12. package/dist/components/ask/askSuggestions.esm.js.map +1 -0
  13. package/dist/components/cloud/CloudImpactSection.esm.js +54 -0
  14. package/dist/components/cloud/CloudImpactSection.esm.js.map +1 -0
  15. package/dist/components/cloud/CloudPage.esm.js +104 -0
  16. package/dist/components/cloud/CloudPage.esm.js.map +1 -0
  17. package/dist/components/cloud/CloudRelationshipSections.esm.js +43 -0
  18. package/dist/components/cloud/CloudRelationshipSections.esm.js.map +1 -0
  19. package/dist/components/cloud/CloudResourceContent.esm.js +495 -0
  20. package/dist/components/cloud/CloudResourceContent.esm.js.map +1 -0
  21. package/dist/components/entity/AnyshiftEntityContent.esm.js +128 -23
  22. package/dist/components/entity/AnyshiftEntityContent.esm.js.map +1 -1
  23. package/dist/components/entity/ArchitectureOperationDetails.esm.js +107 -0
  24. package/dist/components/entity/ArchitectureOperationDetails.esm.js.map +1 -0
  25. package/dist/components/entity/BriefSections.esm.js +24 -4
  26. package/dist/components/entity/BriefSections.esm.js.map +1 -1
  27. package/dist/components/entity/DatadogLiveSignal.esm.js +85 -23
  28. package/dist/components/entity/DatadogLiveSignal.esm.js.map +1 -1
  29. package/dist/components/entity/MermaidArchitecture.esm.js +202 -43
  30. package/dist/components/entity/MermaidArchitecture.esm.js.map +1 -1
  31. package/dist/components/entity/SectionPresenters.esm.js +145 -82
  32. package/dist/components/entity/SectionPresenters.esm.js.map +1 -1
  33. package/dist/components/entity/architectureDiagram.esm.js +48 -15
  34. package/dist/components/entity/architectureDiagram.esm.js.map +1 -1
  35. package/dist/components/entity/architectureGraph.esm.js +145 -0
  36. package/dist/components/entity/architectureGraph.esm.js.map +1 -0
  37. package/dist/components/entity/entityIdentity.esm.js +40 -0
  38. package/dist/components/entity/entityIdentity.esm.js.map +1 -0
  39. package/dist/components/entity/relatedCatalogEntities.esm.js +60 -0
  40. package/dist/components/entity/relatedCatalogEntities.esm.js.map +1 -0
  41. package/dist/components/explorer/AnyshiftExplorerPage.esm.js +222 -21
  42. package/dist/components/explorer/AnyshiftExplorerPage.esm.js.map +1 -1
  43. package/dist/components/explorer/DatadogOperationsRadar.esm.js +92 -31
  44. package/dist/components/explorer/DatadogOperationsRadar.esm.js.map +1 -1
  45. package/dist/index.d.ts +26 -102
  46. package/dist/index.esm.js +1 -1
  47. package/dist/package.json.esm.js +10 -10
  48. package/dist/plugin.esm.js +51 -8
  49. package/dist/plugin.esm.js.map +1 -1
  50. package/dist/routes.esm.js +2 -1
  51. package/dist/routes.esm.js.map +1 -1
  52. package/package.json +11 -11
@@ -1,21 +1,39 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { useState, useRef, useCallback, useEffect } from 'react';
2
+ import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
3
3
  import { Typography, Box, Chip, Button, CircularProgress, Grid } from '@material-ui/core';
4
4
  import { Progress } from '@backstage/core-components';
5
- import { useApi } from '@backstage/frontend-plugin-api';
6
- import { ANYSHIFT_KIND_ANNOTATION, ANYSHIFT_TARGET_ANNOTATION, GITHUB_PROJECT_SLUG_ANNOTATION } from '@anyshift/backstage-plugin-anyshift-common';
7
- import { useEntity } from '@backstage/plugin-catalog-react';
5
+ import { useApi, useApiHolder } from '@backstage/frontend-plugin-api';
6
+ import { ANYSHIFT_KIND_ANNOTATION, ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION, ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION, ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION, ANYSHIFT_RESOURCE_ID_ANNOTATION } from '@anyshift/backstage-plugin-anyshift-common';
7
+ import { useEntity, catalogApiRef } from '@backstage/plugin-catalog-react';
8
8
  import { anyshiftApiRef } from '../../api/AnyshiftApi.esm.js';
9
- import { OverviewSection, DatadogSignalSection, ArchitectureSection, DependencySection, BriefRail, TimelineSection } from './BriefSections.esm.js';
9
+ import { AskAnyshiftCard } from '../ask/AskAnyshiftCard.esm.js';
10
+ import { askScopeForEntity } from '../ask/askScope.esm.js';
11
+ import { CloudAnyshiftEntityContent } from '../cloud/CloudResourceContent.esm.js';
12
+ import { isCloudResourceEntity, entityTarget } from './entityIdentity.esm.js';
13
+ import { resolveRelatedCatalogEntities } from './relatedCatalogEntities.esm.js';
14
+ import { OverviewSection, WhyNowSection, DatadogSignalSection, ArchitectureSection, DependencySection, BriefRail, TimelineSection } from './BriefSections.esm.js';
10
15
 
11
16
  const AnyshiftEntityContent = () => {
17
+ const { entity } = useEntity();
18
+ return isCloudResourceEntity(entity) ? /* @__PURE__ */ jsx(CloudAnyshiftEntityContent, {}) : /* @__PURE__ */ jsx(ServiceAnyshiftEntityContent, {});
19
+ };
20
+ const ServiceAnyshiftEntityContent = () => {
12
21
  const { entity } = useEntity();
13
22
  const api = useApi(anyshiftApiRef);
23
+ const catalogApi = useApiHolder().get(catalogApiRef);
14
24
  const annotations = entity.metadata.annotations ?? {};
15
25
  const target = entityTarget(entity);
16
26
  const kind = annotations[ANYSHIFT_KIND_ANNOTATION] || "workload";
17
27
  const namespace = entity.metadata.namespace;
28
+ const configurationEndpoints = annotations[ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION];
29
+ const configurationDependencies = annotations[ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION];
30
+ const configurationTarget = annotations[ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION] ?? annotations[ANYSHIFT_RESOURCE_ID_ANNOTATION];
18
31
  const [brief, setBrief] = useState();
32
+ const [catalogEntities, setCatalogEntities] = useState([]);
33
+ const [capabilities, setCapabilities] = useState({
34
+ askEnabled: false,
35
+ queryEnabled: false
36
+ });
19
37
  const [error, setError] = useState();
20
38
  const [refreshingAll, setRefreshingAll] = useState(false);
21
39
  const [refreshing, setRefreshing] = useState(
@@ -27,7 +45,13 @@ const AnyshiftEntityContent = () => {
27
45
  setError(void 0);
28
46
  if (refresh) setRefreshingAll(true);
29
47
  try {
30
- const next = await api.brief(kind, target, { namespace, refresh });
48
+ const next = await api.brief(kind, target, {
49
+ namespace,
50
+ refresh,
51
+ configurationEndpoints,
52
+ configurationDependencies,
53
+ configurationTarget
54
+ });
31
55
  if (active.current) setBrief(next);
32
56
  } catch (cause) {
33
57
  if (active.current)
@@ -36,7 +60,15 @@ const AnyshiftEntityContent = () => {
36
60
  if (active.current) setRefreshingAll(false);
37
61
  }
38
62
  },
39
- [api, kind, namespace, target]
63
+ [
64
+ api,
65
+ configurationDependencies,
66
+ configurationEndpoints,
67
+ configurationTarget,
68
+ kind,
69
+ namespace,
70
+ target
71
+ ]
40
72
  );
41
73
  const retrySection = useCallback(
42
74
  async (section) => {
@@ -44,7 +76,10 @@ const AnyshiftEntityContent = () => {
44
76
  try {
45
77
  const response = await api.briefSection(kind, target, section, {
46
78
  namespace,
47
- refresh: true
79
+ refresh: true,
80
+ configurationEndpoints,
81
+ configurationDependencies,
82
+ configurationTarget
48
83
  });
49
84
  if (active.current) {
50
85
  setBrief(
@@ -66,7 +101,15 @@ const AnyshiftEntityContent = () => {
66
101
  }
67
102
  }
68
103
  },
69
- [api, kind, namespace, target]
104
+ [
105
+ api,
106
+ configurationDependencies,
107
+ configurationEndpoints,
108
+ configurationTarget,
109
+ kind,
110
+ namespace,
111
+ target
112
+ ]
70
113
  );
71
114
  useEffect(() => {
72
115
  active.current = true;
@@ -75,28 +118,71 @@ const AnyshiftEntityContent = () => {
75
118
  active.current = false;
76
119
  };
77
120
  }, [load]);
78
- if (error && !brief) return /* @__PURE__ */ jsx(Typography, { color: "error", children: error });
79
- if (!brief) return /* @__PURE__ */ jsx(Progress, {});
121
+ useEffect(() => {
122
+ let cancelled = false;
123
+ if (!catalogApi) {
124
+ setCatalogEntities([]);
125
+ return () => {
126
+ cancelled = true;
127
+ };
128
+ }
129
+ catalogApi.getEntities({
130
+ filter: [{ kind: "Component" }, { kind: "Resource" }],
131
+ fields: ["kind", "metadata.name", "metadata.namespace"]
132
+ }).then((response) => {
133
+ if (!cancelled) setCatalogEntities(response.items);
134
+ }).catch(() => {
135
+ if (!cancelled) setCatalogEntities([]);
136
+ });
137
+ return () => {
138
+ cancelled = true;
139
+ };
140
+ }, [catalogApi]);
141
+ useEffect(() => {
142
+ api.capabilities().then((next) => {
143
+ if (active.current) setCapabilities(next);
144
+ }).catch(() => {
145
+ if (active.current) {
146
+ setCapabilities({ askEnabled: false, queryEnabled: false });
147
+ }
148
+ });
149
+ }, [api]);
150
+ const resolvedBrief = useMemo(() => {
151
+ if (!brief || brief.impact.state !== "data" || !brief.impact.data)
152
+ return brief;
153
+ const impactData = brief.impact.data;
154
+ return {
155
+ ...brief,
156
+ impact: {
157
+ ...brief.impact,
158
+ data: {
159
+ ...impactData,
160
+ relatedEntities: resolveRelatedCatalogEntities(
161
+ impactData.relatedEntities,
162
+ catalogEntities
163
+ )
164
+ }
165
+ }
166
+ };
167
+ }, [brief, catalogEntities]);
168
+ if (error && !resolvedBrief)
169
+ return /* @__PURE__ */ jsx(Typography, { color: "error", children: error });
170
+ if (!resolvedBrief) return /* @__PURE__ */ jsx(Progress, {});
80
171
  return /* @__PURE__ */ jsx(
81
172
  ServiceBriefView,
82
173
  {
83
- brief,
174
+ brief: resolvedBrief,
84
175
  onRetry: retrySection,
85
176
  refreshing,
86
177
  onRefresh: () => void load(true),
87
178
  refreshingAll,
88
- refreshError: error
179
+ refreshError: error,
180
+ askEnabled: capabilities.askEnabled,
181
+ askScope: askScopeForEntity(entity),
182
+ askScopeLabel: target
89
183
  }
90
184
  );
91
185
  };
92
- function entityTarget(entity) {
93
- const annotations = entity.metadata.annotations ?? {};
94
- const explicit = annotations[ANYSHIFT_TARGET_ANNOTATION]?.trim();
95
- if (explicit) return explicit;
96
- const slug = annotations[GITHUB_PROJECT_SLUG_ANNOTATION]?.trim();
97
- const repository = slug?.split("/").filter(Boolean).at(-1);
98
- return repository || entity.metadata.name;
99
- }
100
186
  const ServiceBriefView = ({
101
187
  brief,
102
188
  onRetry,
@@ -104,7 +190,10 @@ const ServiceBriefView = ({
104
190
  onRefresh = () => {
105
191
  },
106
192
  refreshingAll = false,
107
- refreshError
193
+ refreshError,
194
+ askEnabled = false,
195
+ askScope,
196
+ askScopeLabel
108
197
  }) => /* @__PURE__ */ jsxs(Fragment, { children: [
109
198
  /* @__PURE__ */ jsxs(
110
199
  Box,
@@ -169,6 +258,22 @@ const ServiceBriefView = ({
169
258
  refreshing: refreshing.has("overview")
170
259
  }
171
260
  ) }),
261
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
262
+ WhyNowSection,
263
+ {
264
+ section: brief.whyNow,
265
+ onRetry,
266
+ refreshing: refreshing.has("whyNow")
267
+ }
268
+ ) }),
269
+ askEnabled && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
270
+ AskAnyshiftCard,
271
+ {
272
+ context: "entity",
273
+ scope: askScope,
274
+ scopeLabel: askScopeLabel
275
+ }
276
+ ) }),
172
277
  /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
173
278
  DatadogSignalSection,
174
279
  {
@@ -209,5 +314,5 @@ function formatTimestamp(value) {
209
314
  return Number.isNaN(parsed) ? value : new Date(parsed).toLocaleString();
210
315
  }
211
316
 
212
- export { AnyshiftEntityContent, ServiceBriefView, entityTarget };
317
+ export { AnyshiftEntityContent, ServiceAnyshiftEntityContent, ServiceBriefView };
213
318
  //# sourceMappingURL=AnyshiftEntityContent.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AnyshiftEntityContent.esm.js","sources":["../../../src/components/entity/AnyshiftEntityContent.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { useApi } from '@backstage/frontend-plugin-api';\nimport {\n ANYSHIFT_KIND_ANNOTATION,\n ANYSHIFT_TARGET_ANNOTATION,\n GITHUB_PROJECT_SLUG_ANNOTATION,\n} from '@anyshift/backstage-plugin-anyshift-common';\nimport type { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { anyshiftApiRef } from '../../api/AnyshiftApi';\nimport type { BriefSectionName, ServiceBrief } from '../../api/types';\nimport {\n ArchitectureSection,\n BriefRail,\n DatadogSignalSection,\n DependencySection,\n OverviewSection,\n TimelineSection,\n} from './BriefSections';\n\nexport const AnyshiftEntityContent = () => {\n const { entity } = useEntity();\n const api = useApi(anyshiftApiRef);\n const annotations = entity.metadata.annotations ?? {};\n const target = entityTarget(entity);\n const kind = annotations[ANYSHIFT_KIND_ANNOTATION] || 'workload';\n const namespace = entity.metadata.namespace;\n const [brief, setBrief] = useState<ServiceBrief>();\n const [error, setError] = useState<string>();\n const [refreshingAll, setRefreshingAll] = useState(false);\n const [refreshing, setRefreshing] = useState<Set<BriefSectionName>>(\n new Set(),\n );\n const active = useRef(true);\n\n const load = useCallback(\n async (refresh = false) => {\n setError(undefined);\n if (refresh) setRefreshingAll(true);\n try {\n const next = await api.brief(kind, target, { namespace, refresh });\n if (active.current) setBrief(next);\n } catch (cause) {\n if (active.current)\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n if (active.current) setRefreshingAll(false);\n }\n },\n [api, kind, namespace, target],\n );\n\n const retrySection = useCallback(\n async (section: BriefSectionName) => {\n setRefreshing(current => new Set(current).add(section));\n try {\n const response = await api.briefSection(kind, target, section, {\n namespace,\n refresh: true,\n });\n if (active.current) {\n setBrief(current =>\n current\n ? {\n ...current,\n [section]: response.value,\n refreshedAt: response.refreshedAt,\n ...(response.observedService\n ? { observedService: response.observedService }\n : {}),\n }\n : current,\n );\n }\n } finally {\n if (active.current) {\n setRefreshing(current => {\n const next = new Set(current);\n next.delete(section);\n return next;\n });\n }\n }\n },\n [api, kind, namespace, target],\n );\n\n useEffect(() => {\n active.current = true;\n void load();\n return () => {\n active.current = false;\n };\n }, [load]);\n\n if (error && !brief) return <Typography color=\"error\">{error}</Typography>;\n if (!brief) return <Progress />;\n return (\n <ServiceBriefView\n brief={brief}\n onRetry={retrySection}\n refreshing={refreshing}\n onRefresh={() => void load(true)}\n refreshingAll={refreshingAll}\n refreshError={error}\n />\n );\n};\n\nexport function entityTarget(entity: Entity): string {\n const annotations = entity.metadata.annotations ?? {};\n const explicit = annotations[ANYSHIFT_TARGET_ANNOTATION]?.trim();\n if (explicit) return explicit;\n\n const slug = annotations[GITHUB_PROJECT_SLUG_ANNOTATION]?.trim();\n const repository = slug?.split('/').filter(Boolean).at(-1);\n return repository || entity.metadata.name;\n}\n\nexport const ServiceBriefView = ({\n brief,\n onRetry,\n refreshing = new Set(),\n onRefresh = () => {},\n refreshingAll = false,\n refreshError,\n}: {\n brief: ServiceBrief;\n onRetry: (section: BriefSectionName) => void;\n refreshing?: ReadonlySet<BriefSectionName>;\n onRefresh?: () => void;\n refreshingAll?: boolean;\n refreshError?: string;\n}) => (\n <>\n <Box\n mb={3}\n px={2.5}\n py={2}\n borderLeft={4}\n borderColor=\"primary.main\"\n bgcolor=\"background.paper\"\n >\n <Box display=\"flex\" justifyContent=\"space-between\" gridGap={16}>\n <Box>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Anyshift evidence trace\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8}>\n <Chip size=\"small\" label={`Workload · ${brief.target}`} />\n <Typography aria-hidden=\"true\" color=\"primary\">\n →\n </Typography>\n <Chip\n size=\"small\"\n color=\"primary\"\n label={`Observed service · ${\n brief.observedService || 'Not resolved'\n }`}\n />\n </Box>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Runtime namespace: {brief.namespace || 'Not set'} · Refreshed{' '}\n {formatTimestamp(brief.refreshedAt)}\n </Typography>\n </Box>\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRefresh}\n disabled={refreshingAll}\n startIcon={refreshingAll ? <CircularProgress size={14} /> : undefined}\n >\n {refreshingAll ? 'Refreshing…' : 'Refresh brief'}\n </Button>\n </Box>\n {refreshError && (\n <Typography color=\"error\" variant=\"caption\">\n Refresh failed: {refreshError}. Existing evidence is still shown.\n </Typography>\n )}\n </Box>\n\n <Grid container spacing={3} alignItems=\"stretch\">\n <Grid item xs={12}>\n <OverviewSection\n section={brief.overview}\n onRetry={onRetry}\n refreshing={refreshing.has('overview')}\n />\n </Grid>\n <Grid item xs={12}>\n <DatadogSignalSection\n section={brief.observability}\n onRetry={onRetry}\n refreshing={refreshing.has('observability')}\n />\n </Grid>\n <Grid item xs={12}>\n <ArchitectureSection\n section={brief.architecture}\n onRetry={onRetry}\n refreshing={refreshing.has('architecture')}\n />\n </Grid>\n <Grid item xs={12} md={8}>\n <DependencySection\n section={brief.topology}\n onRetry={onRetry}\n refreshing={refreshing.has('topology')}\n />\n </Grid>\n <Grid item xs={12} md={4}>\n <BriefRail brief={brief} onRetry={onRetry} refreshing={refreshing} />\n </Grid>\n <Grid item xs={12}>\n <TimelineSection\n section={brief.timeline}\n onRetry={onRetry}\n refreshing={refreshing.has('timeline')}\n />\n </Grid>\n </Grid>\n </>\n);\n\nfunction formatTimestamp(value: string): string {\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? value : new Date(parsed).toLocaleString();\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AnyshiftEntityContent.esm.js","sources":["../../../src/components/entity/AnyshiftEntityContent.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { useApi, useApiHolder } from '@backstage/frontend-plugin-api';\nimport type { Entity } from '@backstage/catalog-model';\nimport {\n ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION,\n ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION,\n ANYSHIFT_KIND_ANNOTATION,\n ANYSHIFT_RESOURCE_ID_ANNOTATION,\n ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION,\n} from '@anyshift/backstage-plugin-anyshift-common';\nimport { catalogApiRef, useEntity } from '@backstage/plugin-catalog-react';\nimport { anyshiftApiRef } from '../../api/AnyshiftApi';\nimport type {\n AnyshiftCapabilities,\n AskScope,\n BriefSectionName,\n ServiceBrief,\n} from '../../api/types';\nimport { AskAnyshiftCard } from '../ask/AskAnyshiftCard';\nimport { askScopeForEntity } from '../ask/askScope';\nimport { CloudAnyshiftEntityContent } from '../cloud/CloudResourceContent';\nimport { entityTarget, isCloudResourceEntity } from './entityIdentity';\nimport { resolveRelatedCatalogEntities } from './relatedCatalogEntities';\nimport {\n ArchitectureSection,\n BriefRail,\n DatadogSignalSection,\n DependencySection,\n OverviewSection,\n TimelineSection,\n WhyNowSection,\n} from './BriefSections';\n\nexport const AnyshiftEntityContent = () => {\n const { entity } = useEntity();\n return isCloudResourceEntity(entity) ? (\n <CloudAnyshiftEntityContent />\n ) : (\n <ServiceAnyshiftEntityContent />\n );\n};\n\nexport const ServiceAnyshiftEntityContent = () => {\n const { entity } = useEntity();\n const api = useApi(anyshiftApiRef);\n const catalogApi = useApiHolder().get(catalogApiRef);\n const annotations = entity.metadata.annotations ?? {};\n const target = entityTarget(entity);\n const kind = annotations[ANYSHIFT_KIND_ANNOTATION] || 'workload';\n const namespace = entity.metadata.namespace;\n const configurationEndpoints =\n annotations[ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION];\n const configurationDependencies =\n annotations[ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION];\n const configurationTarget =\n annotations[ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION] ??\n annotations[ANYSHIFT_RESOURCE_ID_ANNOTATION];\n const [brief, setBrief] = useState<ServiceBrief>();\n const [catalogEntities, setCatalogEntities] = useState<Entity[]>([]);\n const [capabilities, setCapabilities] = useState<AnyshiftCapabilities>({\n askEnabled: false,\n queryEnabled: false,\n });\n const [error, setError] = useState<string>();\n const [refreshingAll, setRefreshingAll] = useState(false);\n const [refreshing, setRefreshing] = useState<Set<BriefSectionName>>(\n new Set(),\n );\n const active = useRef(true);\n\n const load = useCallback(\n async (refresh = false) => {\n setError(undefined);\n if (refresh) setRefreshingAll(true);\n try {\n const next = await api.brief(kind, target, {\n namespace,\n refresh,\n configurationEndpoints,\n configurationDependencies,\n configurationTarget,\n });\n if (active.current) setBrief(next);\n } catch (cause) {\n if (active.current)\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n if (active.current) setRefreshingAll(false);\n }\n },\n [\n api,\n configurationDependencies,\n configurationEndpoints,\n configurationTarget,\n kind,\n namespace,\n target,\n ],\n );\n\n const retrySection = useCallback(\n async (section: BriefSectionName) => {\n setRefreshing(current => new Set(current).add(section));\n try {\n const response = await api.briefSection(kind, target, section, {\n namespace,\n refresh: true,\n configurationEndpoints,\n configurationDependencies,\n configurationTarget,\n });\n if (active.current) {\n setBrief(current =>\n current\n ? {\n ...current,\n [section]: response.value,\n refreshedAt: response.refreshedAt,\n ...(response.observedService\n ? { observedService: response.observedService }\n : {}),\n }\n : current,\n );\n }\n } finally {\n if (active.current) {\n setRefreshing(current => {\n const next = new Set(current);\n next.delete(section);\n return next;\n });\n }\n }\n },\n [\n api,\n configurationDependencies,\n configurationEndpoints,\n configurationTarget,\n kind,\n namespace,\n target,\n ],\n );\n\n useEffect(() => {\n active.current = true;\n void load();\n return () => {\n active.current = false;\n };\n }, [load]);\n\n useEffect(() => {\n let cancelled = false;\n if (!catalogApi) {\n setCatalogEntities([]);\n return () => {\n cancelled = true;\n };\n }\n catalogApi\n .getEntities({\n filter: [{ kind: 'Component' }, { kind: 'Resource' }],\n fields: ['kind', 'metadata.name', 'metadata.namespace'],\n })\n .then(response => {\n if (!cancelled) setCatalogEntities(response.items);\n })\n .catch(() => {\n if (!cancelled) setCatalogEntities([]);\n });\n return () => {\n cancelled = true;\n };\n }, [catalogApi]);\n\n useEffect(() => {\n api\n .capabilities()\n .then(next => {\n if (active.current) setCapabilities(next);\n })\n .catch(() => {\n if (active.current) {\n setCapabilities({ askEnabled: false, queryEnabled: false });\n }\n });\n }, [api]);\n\n const resolvedBrief = useMemo<ServiceBrief | undefined>(() => {\n if (!brief || brief.impact.state !== 'data' || !brief.impact.data)\n return brief;\n const impactData = brief.impact.data;\n return {\n ...brief,\n impact: {\n ...brief.impact,\n data: {\n ...impactData,\n relatedEntities: resolveRelatedCatalogEntities(\n impactData.relatedEntities,\n catalogEntities,\n ),\n },\n },\n };\n }, [brief, catalogEntities]);\n\n if (error && !resolvedBrief)\n return <Typography color=\"error\">{error}</Typography>;\n if (!resolvedBrief) return <Progress />;\n return (\n <ServiceBriefView\n brief={resolvedBrief}\n onRetry={retrySection}\n refreshing={refreshing}\n onRefresh={() => void load(true)}\n refreshingAll={refreshingAll}\n refreshError={error}\n askEnabled={capabilities.askEnabled}\n askScope={askScopeForEntity(entity)}\n askScopeLabel={target}\n />\n );\n};\n\nexport const ServiceBriefView = ({\n brief,\n onRetry,\n refreshing = new Set(),\n onRefresh = () => {},\n refreshingAll = false,\n refreshError,\n askEnabled = false,\n askScope,\n askScopeLabel,\n}: {\n brief: ServiceBrief;\n onRetry: (section: BriefSectionName) => void;\n refreshing?: ReadonlySet<BriefSectionName>;\n onRefresh?: () => void;\n refreshingAll?: boolean;\n refreshError?: string;\n askEnabled?: boolean;\n askScope?: AskScope;\n askScopeLabel?: string;\n}) => (\n <>\n <Box\n mb={3}\n px={2.5}\n py={2}\n borderLeft={4}\n borderColor=\"primary.main\"\n bgcolor=\"background.paper\"\n >\n <Box display=\"flex\" justifyContent=\"space-between\" gridGap={16}>\n <Box>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Anyshift evidence trace\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8}>\n <Chip size=\"small\" label={`Workload · ${brief.target}`} />\n <Typography aria-hidden=\"true\" color=\"primary\">\n →\n </Typography>\n <Chip\n size=\"small\"\n color=\"primary\"\n label={`Observed service · ${\n brief.observedService || 'Not resolved'\n }`}\n />\n </Box>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Runtime namespace: {brief.namespace || 'Not set'} · Refreshed{' '}\n {formatTimestamp(brief.refreshedAt)}\n </Typography>\n </Box>\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRefresh}\n disabled={refreshingAll}\n startIcon={refreshingAll ? <CircularProgress size={14} /> : undefined}\n >\n {refreshingAll ? 'Refreshing…' : 'Refresh brief'}\n </Button>\n </Box>\n {refreshError && (\n <Typography color=\"error\" variant=\"caption\">\n Refresh failed: {refreshError}. Existing evidence is still shown.\n </Typography>\n )}\n </Box>\n\n <Grid container spacing={3} alignItems=\"stretch\">\n <Grid item xs={12}>\n <OverviewSection\n section={brief.overview}\n onRetry={onRetry}\n refreshing={refreshing.has('overview')}\n />\n </Grid>\n <Grid item xs={12}>\n <WhyNowSection\n section={brief.whyNow}\n onRetry={onRetry}\n refreshing={refreshing.has('whyNow')}\n />\n </Grid>\n {askEnabled && (\n <Grid item xs={12}>\n <AskAnyshiftCard\n context=\"entity\"\n scope={askScope}\n scopeLabel={askScopeLabel}\n />\n </Grid>\n )}\n <Grid item xs={12}>\n <DatadogSignalSection\n section={brief.observability}\n onRetry={onRetry}\n refreshing={refreshing.has('observability')}\n />\n </Grid>\n <Grid item xs={12}>\n <ArchitectureSection\n section={brief.architecture}\n onRetry={onRetry}\n refreshing={refreshing.has('architecture')}\n />\n </Grid>\n <Grid item xs={12} md={8}>\n <DependencySection\n section={brief.topology}\n onRetry={onRetry}\n refreshing={refreshing.has('topology')}\n />\n </Grid>\n <Grid item xs={12} md={4}>\n <BriefRail brief={brief} onRetry={onRetry} refreshing={refreshing} />\n </Grid>\n <Grid item xs={12}>\n <TimelineSection\n section={brief.timeline}\n onRetry={onRetry}\n refreshing={refreshing.has('timeline')}\n />\n </Grid>\n </Grid>\n </>\n);\n\nfunction formatTimestamp(value: string): string {\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? value : new Date(parsed).toLocaleString();\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { Box, Typography, Chip } from '@material-ui/core';
3
+
4
+ const formatObservationTime = (value, now = Date.now()) => {
5
+ if (!value) return { relative: "Observation time unavailable" };
6
+ const timestamp = Date.parse(value);
7
+ if (Number.isNaN(timestamp)) {
8
+ return { relative: "Observation time unavailable" };
9
+ }
10
+ const minutes = Math.round((timestamp - now) / 6e4);
11
+ const [amount, unit] = Math.abs(minutes) < 60 ? [minutes, "minute"] : Math.abs(minutes) < 2880 ? [Math.round(minutes / 60), "hour"] : [Math.round(minutes / 1440), "day"];
12
+ const relative = new Intl.RelativeTimeFormat("en", {
13
+ numeric: "auto"
14
+ }).format(amount, unit);
15
+ return {
16
+ relative: `Observed ${relative}`,
17
+ exact: new Date(timestamp).toISOString()
18
+ };
19
+ };
20
+ const isUsableOperation = (operation) => operation.method !== null || operation.pathTemplate !== null;
21
+ const usableOperations = (relationship) => relationship.operationSources.flatMap((source) => source.operations).filter(isUsableOperation);
22
+ const usableOperationCount = (relationship) => usableOperations(relationship).length;
23
+ const operationPreview = (relationship) => {
24
+ const operations = usableOperations(relationship);
25
+ const operation = operations[0];
26
+ if (relationship.operationCount === 0 || !operation) return "";
27
+ const summary = [
28
+ operation.method ?? "Method unavailable",
29
+ operation.pathTemplate ?? "Path unavailable"
30
+ ].join(" ");
31
+ const remaining = relationship.operationCount - 1;
32
+ return remaining > 0 ? `${summary} \xB7 +${remaining} ${remaining === 1 ? "operation" : "operations"}` : summary;
33
+ };
34
+ const ArchitectureOperationDetails = ({
35
+ relationship,
36
+ onClose,
37
+ now
38
+ }) => {
39
+ if (relationship.operationCount === 0 || usableOperationCount(relationship) === 0) {
40
+ return null;
41
+ }
42
+ return /* @__PURE__ */ jsxs(Box, { border: 1, borderColor: "divider", borderRadius: 4, p: 2, children: [
43
+ /* @__PURE__ */ jsxs(
44
+ Box,
45
+ {
46
+ display: "flex",
47
+ justifyContent: "space-between",
48
+ alignItems: "flex-start",
49
+ children: [
50
+ /* @__PURE__ */ jsxs(Typography, { component: "h3", variant: "h6", children: [
51
+ relationship.fromLabel,
52
+ " to ",
53
+ relationship.toLabel
54
+ ] }),
55
+ /* @__PURE__ */ jsx(
56
+ "button",
57
+ {
58
+ "aria-label": "Close HTTP operation details",
59
+ onClick: onClose,
60
+ type: "button",
61
+ children: "Close"
62
+ }
63
+ )
64
+ ]
65
+ }
66
+ ),
67
+ relationship.operationSources.map((source) => /* @__PURE__ */ jsxs(Box, { mt: 2, children: [
68
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: source.source }),
69
+ source.operations.filter(isUsableOperation).map((operation, index) => {
70
+ const observed = formatObservationTime(operation.observedAt, now);
71
+ return /* @__PURE__ */ jsxs(
72
+ Box,
73
+ {
74
+ display: "flex",
75
+ flexWrap: "wrap",
76
+ alignItems: "center",
77
+ gridGap: 8,
78
+ mt: 0.5,
79
+ children: [
80
+ operation.method ? /* @__PURE__ */ jsx(
81
+ Chip,
82
+ {
83
+ label: operation.method,
84
+ size: "small",
85
+ variant: "outlined"
86
+ }
87
+ ) : /* @__PURE__ */ jsx(Typography, { variant: "body2", children: "Method unavailable" }),
88
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: operation.pathTemplate ?? "Path unavailable" }),
89
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: /* @__PURE__ */ jsxs("time", { dateTime: operation.observedAt ?? void 0, children: [
90
+ /* @__PURE__ */ jsx("span", { children: observed.relative }),
91
+ observed.exact && /* @__PURE__ */ jsxs(Fragment, { children: [
92
+ " \xB7 ",
93
+ /* @__PURE__ */ jsx("span", { children: observed.exact })
94
+ ] })
95
+ ] }) })
96
+ ]
97
+ },
98
+ `${operation.method ?? ""}\0${operation.pathTemplate ?? ""}\0${index}`
99
+ );
100
+ }),
101
+ source.hasIncompleteOperations && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", component: "p", children: "Operation details incomplete" })
102
+ ] }, source.source))
103
+ ] });
104
+ };
105
+
106
+ export { ArchitectureOperationDetails, formatObservationTime, operationPreview };
107
+ //# sourceMappingURL=ArchitectureOperationDetails.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArchitectureOperationDetails.esm.js","sources":["../../../src/components/entity/ArchitectureOperationDetails.tsx"],"sourcesContent":["import { Box, Chip, Typography } from '@material-ui/core';\nimport type { ArchitectureDiagramRelationship } from './architectureDiagram';\n\nexport const formatObservationTime = (\n value: string | null,\n now = Date.now(),\n): { relative: string; exact?: string } => {\n if (!value) return { relative: 'Observation time unavailable' };\n\n const timestamp = Date.parse(value);\n if (Number.isNaN(timestamp)) {\n return { relative: 'Observation time unavailable' };\n }\n\n const minutes = Math.round((timestamp - now) / 60_000);\n const [amount, unit] =\n Math.abs(minutes) < 60\n ? ([minutes, 'minute'] as const)\n : Math.abs(minutes) < 2_880\n ? ([Math.round(minutes / 60), 'hour'] as const)\n : ([Math.round(minutes / 1_440), 'day'] as const);\n const relative = new Intl.RelativeTimeFormat('en', {\n numeric: 'auto',\n }).format(amount, unit);\n\n return {\n relative: `Observed ${relative}`,\n exact: new Date(timestamp).toISOString(),\n };\n};\n\nconst isUsableOperation = (operation: {\n method: string | null;\n pathTemplate: string | null;\n}) => operation.method !== null || operation.pathTemplate !== null;\n\nconst usableOperations = (relationship: ArchitectureDiagramRelationship) =>\n relationship.operationSources\n .flatMap(source => source.operations)\n .filter(isUsableOperation);\n\nconst usableOperationCount = (relationship: ArchitectureDiagramRelationship) =>\n usableOperations(relationship).length;\n\nexport const operationPreview = (\n relationship: ArchitectureDiagramRelationship,\n): string => {\n const operations = usableOperations(relationship);\n const operation = operations[0];\n if (relationship.operationCount === 0 || !operation) return '';\n\n const summary = [\n operation.method ?? 'Method unavailable',\n operation.pathTemplate ?? 'Path unavailable',\n ].join(' ');\n const remaining = relationship.operationCount - 1;\n return remaining > 0\n ? `${summary} · +${remaining} ${\n remaining === 1 ? 'operation' : 'operations'\n }`\n : summary;\n};\n\nexport const ArchitectureOperationDetails = ({\n relationship,\n onClose,\n now,\n}: {\n relationship: ArchitectureDiagramRelationship;\n onClose: () => void;\n now?: number;\n}) => {\n if (\n relationship.operationCount === 0 ||\n usableOperationCount(relationship) === 0\n ) {\n return null;\n }\n\n return (\n <Box border={1} borderColor=\"divider\" borderRadius={4} p={2}>\n <Box\n display=\"flex\"\n justifyContent=\"space-between\"\n alignItems=\"flex-start\"\n >\n <Typography component=\"h3\" variant=\"h6\">\n {relationship.fromLabel} to {relationship.toLabel}\n </Typography>\n <button\n aria-label=\"Close HTTP operation details\"\n onClick={onClose}\n type=\"button\"\n >\n Close\n </button>\n </Box>\n\n {relationship.operationSources.map(source => (\n <Box key={source.source} mt={2}>\n <Typography variant=\"subtitle2\">{source.source}</Typography>\n {source.operations\n .filter(isUsableOperation)\n .map((operation, index) => {\n const observed = formatObservationTime(operation.observedAt, now);\n return (\n <Box\n key={`${operation.method ?? ''}\\u0000${\n operation.pathTemplate ?? ''\n }\\u0000${index}`}\n display=\"flex\"\n flexWrap=\"wrap\"\n alignItems=\"center\"\n gridGap={8}\n mt={0.5}\n >\n {operation.method ? (\n <Chip\n label={operation.method}\n size=\"small\"\n variant=\"outlined\"\n />\n ) : (\n <Typography variant=\"body2\">Method unavailable</Typography>\n )}\n <Typography variant=\"body2\">\n {operation.pathTemplate ?? 'Path unavailable'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n <time dateTime={operation.observedAt ?? undefined}>\n <span>{observed.relative}</span>\n {observed.exact && (\n <>\n {' · '}\n <span>{observed.exact}</span>\n </>\n )}\n </time>\n </Typography>\n </Box>\n );\n })}\n {source.hasIncompleteOperations && (\n <Typography variant=\"caption\" color=\"textSecondary\" component=\"p\">\n Operation details incomplete\n </Typography>\n )}\n </Box>\n ))}\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { Box, Grid, Typography, Button, CircularProgress } from '@material-ui/core';
3
3
  import { InfoCard } from '@backstage/core-components';
4
- import { OverviewPresenter, ArchitecturePresenter, DependencyFootprintPresenter, OperationalPosturePresenter, LatestChangePresenter, SafeguardsPresenter, TimelinePresenter } from './SectionPresenters.esm.js';
4
+ import { OverviewPresenter, WhyNowPresenter, ArchitecturePresenter, DependencyFootprintPresenter, AffectedFootprintPresenter, LatestChangePresenter, SafeguardsPresenter, TimelinePresenter } from './SectionPresenters.esm.js';
5
5
  import { DatadogSignalStripPresenter } from './DatadogLiveSignal.esm.js';
6
6
 
7
7
  const OverviewSection = ({
@@ -58,6 +58,26 @@ const DatadogSignalSection = ({
58
58
  renderData: (data) => /* @__PURE__ */ jsx(DatadogSignalStripPresenter, { data })
59
59
  }
60
60
  ) }) });
61
+ const WhyNowSection = ({
62
+ section,
63
+ onRetry,
64
+ refreshing
65
+ }) => /* @__PURE__ */ jsx(
66
+ SectionCard,
67
+ {
68
+ title: "Why now?",
69
+ subheader: "Current symptoms and evidence-backed suspects",
70
+ children: /* @__PURE__ */ jsx(
71
+ DataSection,
72
+ {
73
+ section,
74
+ onRetry: () => onRetry("whyNow"),
75
+ refreshing,
76
+ renderData: (data) => /* @__PURE__ */ jsx(WhyNowPresenter, { data })
77
+ }
78
+ )
79
+ }
80
+ );
61
81
  const BriefRail = ({
62
82
  brief,
63
83
  onRetry,
@@ -66,11 +86,11 @@ const BriefRail = ({
66
86
  /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
67
87
  CompactSection,
68
88
  {
69
- title: "Operational posture",
89
+ title: "Affected footprint",
70
90
  section: brief.impact,
71
91
  onRetry: () => onRetry("impact"),
72
92
  refreshing: refreshing.has("impact"),
73
- renderData: (data) => /* @__PURE__ */ jsx(OperationalPosturePresenter, { data })
93
+ renderData: (data) => /* @__PURE__ */ jsx(AffectedFootprintPresenter, { data })
74
94
  }
75
95
  ) }),
76
96
  /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
@@ -214,5 +234,5 @@ const RetryControl = ({
214
234
  }
215
235
  );
216
236
 
217
- export { ArchitectureSection, BriefRail, DatadogSignalSection, DependencySection, OverviewSection, TimelineSection };
237
+ export { ArchitectureSection, BriefRail, DatadogSignalSection, DependencySection, OverviewSection, TimelineSection, WhyNowSection };
218
238
  //# sourceMappingURL=BriefSections.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BriefSections.esm.js","sources":["../../../src/components/entity/BriefSections.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport {\n Box,\n Button,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { InfoCard } from '@backstage/core-components';\nimport type {\n BriefSection,\n BriefSectionName,\n SafeguardResult,\n ServiceBrief,\n ServiceOverview,\n} from '../../api/types';\nimport {\n ArchitecturePresenter,\n DependencyFootprintPresenter,\n LatestChangePresenter,\n OperationalPosturePresenter,\n OverviewPresenter,\n SafeguardsPresenter,\n TimelinePresenter,\n} from './SectionPresenters';\nimport { DatadogSignalStripPresenter } from './DatadogLiveSignal';\n\nexport type RetrySection = (section: BriefSectionName) => void;\n\nexport const OverviewSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection<ServiceOverview>;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n <Box px={2} py={2}>\n <DataSection\n section={section}\n onRetry={() => onRetry('overview')}\n refreshing={refreshing}\n renderData={data => <OverviewPresenter data={data} />}\n />\n </Box>\n </InfoCard>\n);\n\nexport const DependencySection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Dependency footprint\"\n subheader=\"Direct traffic and transitive reach\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('topology')}\n refreshing={refreshing}\n renderData={data => <DependencyFootprintPresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const DatadogSignalSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n {section.state === 'data' && section.data !== undefined ? (\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n ) : (\n <Box px={2} py={1.5}>\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n </Box>\n )}\n </InfoCard>\n);\n\nexport const BriefRail = ({\n brief,\n onRetry,\n refreshing = new Set(),\n}: {\n brief: ServiceBrief;\n onRetry: RetrySection;\n refreshing?: ReadonlySet<BriefSectionName>;\n}) => (\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <CompactSection\n title=\"Operational posture\"\n section={brief.impact}\n onRetry={() => onRetry('impact')}\n refreshing={refreshing.has('impact')}\n renderData={data => <OperationalPosturePresenter data={data} />}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection\n title=\"Latest change\"\n section={brief.latestChange}\n onRetry={() => onRetry('latestChange')}\n refreshing={refreshing.has('latestChange')}\n renderData={data => <LatestChangePresenter data={data} />}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection<SafeguardResult[]>\n title=\"Runtime safeguards\"\n section={brief.safeguards}\n onRetry={() => onRetry('safeguards')}\n refreshing={refreshing.has('safeguards')}\n renderData={data => <SafeguardsPresenter data={data} />}\n />\n </Grid>\n </Grid>\n);\n\nexport const TimelineSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Change intelligence\"\n subheader=\"Runtime changes in the last 24 hours\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('timeline')}\n refreshing={refreshing}\n renderData={data => <TimelinePresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const ArchitectureSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard title=\"Service map\" subheader=\"Cross-layer C4 graph evidence\">\n <DataSection\n section={section}\n onRetry={() => onRetry('architecture')}\n refreshing={refreshing}\n renderData={data => <ArchitecturePresenter data={data} />}\n />\n </SectionCard>\n);\n\nconst SectionCard = ({\n title,\n subheader,\n children,\n}: {\n title: string;\n subheader?: string;\n children: ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n subheader={subheader}\n >\n {children}\n </InfoCard>\n);\n\nconst CompactSection = <T,>({\n title,\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n title: string;\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n noPadding\n >\n <Box p={2}>\n <DataSection\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n renderData={renderData}\n />\n </Box>\n </InfoCard>\n);\n\nconst DataSection = <T,>({\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => {\n if (section.state === 'data' && section.data !== undefined) {\n return (\n <>\n {renderData(section.data)}\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n );\n }\n return (\n <SectionStateContent\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n />\n );\n};\n\nconst SectionStateContent = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <>\n <Typography\n color={section.state === 'error' ? 'error' : 'textSecondary'}\n variant=\"body2\"\n >\n {section.message || 'No graph evidence is available.'}\n </Typography>\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n);\n\nconst RetryControl = ({\n onRetry,\n refreshing,\n}: {\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRetry}\n disabled={refreshing}\n startIcon={refreshing ? <CircularProgress size={14} /> : undefined}\n style={{ marginTop: 8 }}\n >\n {refreshing ? 'Retrying…' : 'Retry'}\n </Button>\n);\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BriefSections.esm.js","sources":["../../../src/components/entity/BriefSections.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport {\n Box,\n Button,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { InfoCard } from '@backstage/core-components';\nimport type {\n BriefSection,\n BriefSectionName,\n EntityImpact,\n SafeguardResult,\n ServiceBrief,\n ServiceOverview,\n WhyNowAssessment,\n} from '../../api/types';\nimport {\n AffectedFootprintPresenter,\n ArchitecturePresenter,\n DependencyFootprintPresenter,\n LatestChangePresenter,\n OverviewPresenter,\n SafeguardsPresenter,\n TimelinePresenter,\n WhyNowPresenter,\n} from './SectionPresenters';\nimport { DatadogSignalStripPresenter } from './DatadogLiveSignal';\n\nexport type RetrySection = (section: BriefSectionName) => void;\n\nexport const OverviewSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection<ServiceOverview>;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n <Box px={2} py={2}>\n <DataSection\n section={section}\n onRetry={() => onRetry('overview')}\n refreshing={refreshing}\n renderData={data => <OverviewPresenter data={data} />}\n />\n </Box>\n </InfoCard>\n);\n\nexport const DependencySection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Dependency footprint\"\n subheader=\"Direct traffic and transitive reach\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('topology')}\n refreshing={refreshing}\n renderData={data => <DependencyFootprintPresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const DatadogSignalSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n {section.state === 'data' && section.data !== undefined ? (\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n ) : (\n <Box px={2} py={1.5}>\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n </Box>\n )}\n </InfoCard>\n);\n\nexport const WhyNowSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection<WhyNowAssessment>;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Why now?\"\n subheader=\"Current symptoms and evidence-backed suspects\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('whyNow')}\n refreshing={refreshing}\n renderData={data => <WhyNowPresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const BriefRail = ({\n brief,\n onRetry,\n refreshing = new Set(),\n}: {\n brief: ServiceBrief;\n onRetry: RetrySection;\n refreshing?: ReadonlySet<BriefSectionName>;\n}) => (\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <CompactSection\n title=\"Affected footprint\"\n section={brief.impact}\n onRetry={() => onRetry('impact')}\n refreshing={refreshing.has('impact')}\n renderData={(data: EntityImpact) => (\n <AffectedFootprintPresenter data={data} />\n )}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection\n title=\"Latest change\"\n section={brief.latestChange}\n onRetry={() => onRetry('latestChange')}\n refreshing={refreshing.has('latestChange')}\n renderData={data => <LatestChangePresenter data={data} />}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection<SafeguardResult[]>\n title=\"Runtime safeguards\"\n section={brief.safeguards}\n onRetry={() => onRetry('safeguards')}\n refreshing={refreshing.has('safeguards')}\n renderData={data => <SafeguardsPresenter data={data} />}\n />\n </Grid>\n </Grid>\n);\n\nexport const TimelineSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Change intelligence\"\n subheader=\"Runtime changes in the last 24 hours\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('timeline')}\n refreshing={refreshing}\n renderData={data => <TimelinePresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const ArchitectureSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard title=\"Service map\" subheader=\"Cross-layer C4 graph evidence\">\n <DataSection\n section={section}\n onRetry={() => onRetry('architecture')}\n refreshing={refreshing}\n renderData={data => <ArchitecturePresenter data={data} />}\n />\n </SectionCard>\n);\n\nconst SectionCard = ({\n title,\n subheader,\n children,\n}: {\n title: string;\n subheader?: string;\n children: ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n subheader={subheader}\n >\n {children}\n </InfoCard>\n);\n\nconst CompactSection = <T,>({\n title,\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n title: string;\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n noPadding\n >\n <Box p={2}>\n <DataSection\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n renderData={renderData}\n />\n </Box>\n </InfoCard>\n);\n\nconst DataSection = <T,>({\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => {\n if (section.state === 'data' && section.data !== undefined) {\n return (\n <>\n {renderData(section.data)}\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n );\n }\n return (\n <SectionStateContent\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n />\n );\n};\n\nconst SectionStateContent = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <>\n <Typography\n color={section.state === 'error' ? 'error' : 'textSecondary'}\n variant=\"body2\"\n >\n {section.message || 'No graph evidence is available.'}\n </Typography>\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n);\n\nconst RetryControl = ({\n onRetry,\n refreshing,\n}: {\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRetry}\n disabled={refreshing}\n startIcon={refreshing ? <CircularProgress size={14} /> : undefined}\n style={{ marginTop: 8 }}\n >\n {refreshing ? 'Retrying…' : 'Retry'}\n </Button>\n);\n"],"names":[],"mappings":"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"}