@backstage-community/plugin-apiiro 0.1.0 → 1.0.0
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.
- package/CHANGELOG.md +23 -0
- package/README.md +91 -12
- package/config.d.ts +14 -0
- package/dist/App.esm.js +96 -4
- package/dist/App.esm.js.map +1 -1
- package/dist/api/index.esm.js +6 -0
- package/dist/api/index.esm.js.map +1 -1
- package/dist/assets/SettingIcon.esm.js +1 -0
- package/dist/assets/SettingIcon.esm.js.map +1 -1
- package/dist/components/ApiiroSidebar.esm.js.map +1 -1
- package/dist/components/CalendarDatePicker.esm.js.map +1 -1
- package/dist/components/DataGrid/DataGrid.esm.js +1 -0
- package/dist/components/DataGrid/DataGrid.esm.js.map +1 -1
- package/dist/components/MetricsGroup/TabMetricsGroup.esm.js +28 -4
- package/dist/components/MetricsGroup/TabMetricsGroup.esm.js.map +1 -1
- package/dist/components/MetricsGroup/WidgetMetricsGroup.esm.js +30 -7
- package/dist/components/MetricsGroup/WidgetMetricsGroup.esm.js.map +1 -1
- package/dist/components/RiskLevel.esm.js +1 -0
- package/dist/components/RiskLevel.esm.js.map +1 -1
- package/dist/components/charts/GaugeChart.esm.js +8 -6
- package/dist/components/charts/GaugeChart.esm.js.map +1 -1
- package/dist/components/common/StatusContainer.esm.js +123 -0
- package/dist/components/common/StatusContainer.esm.js.map +1 -0
- package/dist/components/filters/DiscoveredOnFilter.esm.js +1 -1
- package/dist/components/filters/DiscoveredOnFilter.esm.js.map +1 -1
- package/dist/components/tiles/MttrVsSLATile.esm.js +31 -14
- package/dist/components/tiles/MttrVsSLATile.esm.js.map +1 -1
- package/dist/components/tiles/RiskOverTimeTile.esm.js +15 -12
- package/dist/components/tiles/RiskOverTimeTile.esm.js.map +1 -1
- package/dist/components/tiles/SLAAdherenceTile.esm.js +15 -12
- package/dist/components/tiles/SLAAdherenceTile.esm.js.map +1 -1
- package/dist/components/tiles/StatusTile.esm.js +98 -66
- package/dist/components/tiles/StatusTile.esm.js.map +1 -1
- package/dist/components/tiles/TopLanguagesTile.esm.js +1 -0
- package/dist/components/tiles/TopLanguagesTile.esm.js.map +1 -1
- package/dist/components/tiles/TopRiskTile.esm.js +19 -16
- package/dist/components/tiles/TopRiskTile.esm.js.map +1 -1
- package/dist/index.d.ts +31 -6
- package/dist/index.esm.js +2 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/pages/Applications/Applications.esm.js +104 -0
- package/dist/pages/Applications/Applications.esm.js.map +1 -0
- package/dist/pages/Applications/tableConfig.esm.js +147 -0
- package/dist/pages/Applications/tableConfig.esm.js.map +1 -0
- package/dist/pages/Repositories/Repositories.esm.js +26 -26
- package/dist/pages/Repositories/Repositories.esm.js.map +1 -1
- package/dist/pages/Repositories/tableConfig.esm.js +3 -2
- package/dist/pages/Repositories/tableConfig.esm.js.map +1 -1
- package/dist/pages/Risks/Risks.esm.js +9 -3
- package/dist/pages/Risks/Risks.esm.js.map +1 -1
- package/dist/pages/Risks/tableConfig.esm.js +25 -11
- package/dist/pages/Risks/tableConfig.esm.js.map +1 -1
- package/dist/pages/tab/ComponentTab.esm.js +72 -0
- package/dist/pages/tab/ComponentTab.esm.js.map +1 -0
- package/dist/pages/tab/SystemTab.esm.js +159 -0
- package/dist/pages/tab/SystemTab.esm.js.map +1 -0
- package/dist/pages/tab/TabProvider.esm.js +9 -3
- package/dist/pages/tab/TabProvider.esm.js.map +1 -1
- package/dist/pages/widget/ComponentWidget.esm.js +67 -0
- package/dist/pages/widget/ComponentWidget.esm.js.map +1 -0
- package/dist/pages/widget/SystemWidget.esm.js +81 -0
- package/dist/pages/widget/SystemWidget.esm.js.map +1 -0
- package/dist/pages/widget/WidgetProvider.esm.js +9 -3
- package/dist/pages/widget/WidgetProvider.esm.js.map +1 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/queries/application.queries.esm.js +64 -0
- package/dist/queries/application.queries.esm.js.map +1 -0
- package/dist/queries/mttr-statistics.queries.esm.js +19 -12
- package/dist/queries/mttr-statistics.queries.esm.js.map +1 -1
- package/dist/queries/repository.queries.esm.js +19 -8
- package/dist/queries/repository.queries.esm.js.map +1 -1
- package/dist/queries/risk-score-over-time.queries.esm.js +19 -12
- package/dist/queries/risk-score-over-time.queries.esm.js.map +1 -1
- package/dist/queries/risks.queries.esm.js +19 -7
- package/dist/queries/risks.queries.esm.js.map +1 -1
- package/dist/queries/sla-breach.queries.esm.js +22 -11
- package/dist/queries/sla-breach.queries.esm.js.map +1 -1
- package/dist/queries/top-risks.queries.esm.js +19 -7
- package/dist/queries/top-risks.queries.esm.js.map +1 -1
- package/dist/theme/themeUtils.esm.js +5 -2
- package/dist/theme/themeUtils.esm.js.map +1 -1
- package/dist/utils/utils.esm.js +3 -2
- package/dist/utils/utils.esm.js.map +1 -1
- package/package.json +12 -12
- package/dist/pages/tab/Tab.esm.js +0 -147
- package/dist/pages/tab/Tab.esm.js.map +0 -1
- package/dist/pages/widget/Widget.esm.js +0 -161
- package/dist/pages/widget/Widget.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @backstage-community/plugin-apiiro
|
|
2
2
|
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- ff337ee: Implemented Application View functionality to enable risk display and navigation for System Entities.
|
|
8
|
+
Fixed the UI component to support the Informational risk level type.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies [ff337ee]
|
|
13
|
+
- @backstage-community/plugin-apiiro-common@1.0.0
|
|
14
|
+
|
|
15
|
+
## 0.2.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- cd2ccac: Backstage version bump to v1.48.2
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [cd2ccac]
|
|
24
|
+
- @backstage-community/plugin-apiiro-common@0.2.0
|
|
25
|
+
|
|
3
26
|
## 0.1.0
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
The Apiiro plugin for Backstage integrates Apiiro's application risk management capabilities directly into your Backstage developer portal. This plugin empowers developers to code securely by automatically checking for security vulnerabilities and enables them to review and address newly introduced vulnerabilities directly in Backstage.
|
|
4
4
|
|
|
5
|
-
## Plugin Compatibility
|
|
6
|
-
|
|
7
|
-
The plugin has been successfully tested with Backstage v1.44.0 If you are using a newer version of Backstage, please file an issue, and we will provide guidance on the best integration practices for your specific version.
|
|
8
|
-
|
|
9
5
|
## Features
|
|
10
6
|
|
|
11
7
|
- **Dashboard View**: Repository list with statistics sourced from Apiiro
|
|
12
|
-
- **
|
|
8
|
+
- **Application List**: Comprehensive list of all applications integrated with Apiiro
|
|
9
|
+
- **Apiiro Tab**: In-depth view of open risks and detailed metrics of repositories and applications
|
|
13
10
|
- **Apiiro Widget**: High-level overview widget that can be embedded in custom entity tabs
|
|
14
11
|
- **Permission Control**: Conditional permissions for fine-grained access control to Apiiro metrics
|
|
15
12
|
|
|
13
|
+
> [!NOTE]
|
|
14
|
+
> The Application List and Apiiro Tab (System) require the Backstage connector to be configured in Apiiro to function properly.
|
|
15
|
+
|
|
16
16
|
## Views
|
|
17
17
|
|
|
18
18
|
### Dashboard – Repository List
|
|
@@ -21,18 +21,36 @@ Displays the list of integrated repositories along with statistics sourced from
|
|
|
21
21
|
|
|
22
22
|

|
|
23
23
|
|
|
24
|
-
### Apiiro Tab
|
|
24
|
+
### Apiiro Tab (Component)
|
|
25
25
|
|
|
26
|
-
Provides an in-depth look at each repository's open risks and detailed metrics retrieved from Apiiro.
|
|
26
|
+
Provides an in-depth look at each repository's open risks and detailed metrics retrieved from Apiiro. The risk view links and "Go to Apiiro" button redirect to the development risks tab in Apiiro.
|
|
27
27
|
|
|
28
28
|

|
|
29
29
|
|
|
30
30
|
### Apiiro Widget
|
|
31
31
|
|
|
32
|
-
Offers a high-level overview of the repository, including programming languages and top risk details. Can be added to any custom entity tab.
|
|
32
|
+
Offers a high-level overview of the repository, including programming languages and top risk details. Can be added to any custom entity tab. "Go to Apiiro" button redirect to the development risks tab in Apiiro.
|
|
33
33
|
|
|
34
34
|

|
|
35
35
|
|
|
36
|
+
### Application List
|
|
37
|
+
|
|
38
|
+
Displays a comprehensive list of all applications integrated with Apiiro, including risk scores, repository counts, and key metrics. This view is available when the applications view is enabled in the configuration.
|
|
39
|
+
|
|
40
|
+
> [!NOTE]
|
|
41
|
+
> This feature requires the Backstage connector to be configured in Apiiro.
|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
### Apiiro Tab (System)
|
|
46
|
+
|
|
47
|
+
Provides a detailed view of applications with comprehensive risk insights, associated repositories, and security metrics. This tab displays application-level statistics and allows navigation between repositories and risks within the application context. The risks view links and "Go to Apiiro" button redirect to the development risks tab in Apiiro.
|
|
48
|
+
|
|
49
|
+
> [!NOTE]
|
|
50
|
+
> This feature requires the Backstage connector to be configured in Apiiro.
|
|
51
|
+
|
|
52
|
+

|
|
53
|
+
|
|
36
54
|
## Prerequisites
|
|
37
55
|
|
|
38
56
|
- The entity for a repository must be present within Backstage to see Apiiro results
|
|
@@ -51,17 +69,32 @@ Offers a high-level overview of the repository, including programming languages
|
|
|
51
69
|
Add the following annotation into your catalog.
|
|
52
70
|
To be able to use the Apiiro plugin you need to add the following annotation to any entities you want to use it with:
|
|
53
71
|
|
|
72
|
+
**For Component entities (repositories):**
|
|
73
|
+
|
|
54
74
|
```yaml
|
|
55
75
|
apiiro.com/repo-id: <apiiro-repo-key>
|
|
56
|
-
apiiro.com/allow-metrics-view: "true" or "false" (controls whether the Metrics view appears in the Apiiro tab and Apiiro widget)
|
|
76
|
+
apiiro.com/allow-metrics-view: "true" or "false" (controls whether the Metrics view appears in the Component Apiiro tab and Apiiro widget)
|
|
57
77
|
```
|
|
58
78
|
|
|
59
|
-
|
|
79
|
+
**For System entities (applications):**
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
apiiro.com/application-id: <apiiro-application-key>
|
|
83
|
+
apiiro.com/allow-metrics-view: "true" or "false" (controls whether the Metrics view and repository list appears in the System Apiiro tab and Apiiro widget)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> [!NOTE]
|
|
87
|
+
> Application annotations require the Backstage connector to be configured in Apiiro and `enableApplicationsView` set to `true` in the configuration.
|
|
88
|
+
|
|
89
|
+
Let's break this down:
|
|
90
|
+
|
|
91
|
+
- `<apiiro-repo-key>` is the key of your repository in Apiiro
|
|
92
|
+
- `<apiiro-application-key>` is the key of your application in Apiiro
|
|
60
93
|
|
|
61
94
|
Here's what that will look like in action:
|
|
62
95
|
|
|
63
96
|
```yaml
|
|
64
|
-
# Example catalog-info.yaml
|
|
97
|
+
# Example catalog-info.yaml for Component entity
|
|
65
98
|
apiVersion: backstage.io/v1alpha1
|
|
66
99
|
kind: Component
|
|
67
100
|
metadata:
|
|
@@ -69,6 +102,15 @@ metadata:
|
|
|
69
102
|
annotations:
|
|
70
103
|
apiiro.com/repo-id: my-repo-key
|
|
71
104
|
apiiro.com/allow-metrics-view: 'true'
|
|
105
|
+
---
|
|
106
|
+
# Example catalog-info.yaml for System entity
|
|
107
|
+
apiVersion: backstage.io/v1alpha1
|
|
108
|
+
kind: System
|
|
109
|
+
metadata:
|
|
110
|
+
name: my-application
|
|
111
|
+
annotations:
|
|
112
|
+
apiiro.com/application-id: my-application-key
|
|
113
|
+
apiiro.com/allow-metrics-view: 'true'
|
|
72
114
|
```
|
|
73
115
|
|
|
74
116
|
Please find the steps to add the annotation automatically [here](../apiiro-backend/README.md#automatically-adding-apiiro-annotations-optional).
|
|
@@ -91,6 +133,8 @@ Add your Apiiro Access Token to your `app-config.yaml` or `app-config.production
|
|
|
91
133
|
apiiro:
|
|
92
134
|
accessToken: ${APIIRO_TOKEN}
|
|
93
135
|
defaultAllowMetricsView: true
|
|
136
|
+
enableApplicationsView: false
|
|
137
|
+
redirectDevView: false
|
|
94
138
|
# Optional: Configure default risk filters for the Apiiro Risk Table (Example configuration)
|
|
95
139
|
defaultRiskFilters:
|
|
96
140
|
RiskLevel:
|
|
@@ -114,6 +158,8 @@ Where:
|
|
|
114
158
|
|
|
115
159
|
- `accessToken` is your Apiiro Access Token
|
|
116
160
|
- `defaultAllowMetricsView` is a boolean value that controls whether the Metrics view appears in the Apiiro Tab and Apiiro Widget by default. If annotation is not set, this value will be used. Default value is `true`.
|
|
161
|
+
- `enableApplicationsView` is a boolean value that enables the Application List and Apiiro Tab on System Entity. Default value is `false`. **Note:** This feature requires the Backstage connector to be configured in Apiiro.
|
|
162
|
+
- `redirectDevView` (optional) redirects to the development view of risks in Apiiro. Default value is `false`.
|
|
117
163
|
- `defaultRiskFilters` (optional) configures default filters for the Apiiro Risk Table. Please refer to the [backend documentation](../apiiro-backend/README.md#configure-default-risk-filters-optional) for more details.
|
|
118
164
|
|
|
119
165
|
**How to Retrieve an Access Token from Apiiro:**
|
|
@@ -199,7 +245,40 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
|
|
|
199
245
|
);
|
|
200
246
|
```
|
|
201
247
|
|
|
202
|
-
### 6. Add Apiiro
|
|
248
|
+
### 6. Add Apiiro Tab to System Entity Page (Optional)
|
|
249
|
+
|
|
250
|
+
To enable application-level insights for System entities, add the Apiiro Tab to your system entity page.
|
|
251
|
+
|
|
252
|
+
In `packages/app/src/components/Catalog/EntityPage.tsx`:
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
// Import the Apiiro tab
|
|
256
|
+
import {
|
|
257
|
+
ApiiroTab,
|
|
258
|
+
isApiiroApplicationAvailable,
|
|
259
|
+
} from '@backstage-community/plugin-apiiro';
|
|
260
|
+
|
|
261
|
+
// Add the route to your system page
|
|
262
|
+
const systemPage = (
|
|
263
|
+
<EntityLayout>
|
|
264
|
+
<EntityLayout.Route path="/" title="Overview">
|
|
265
|
+
{/* ... other elements */}
|
|
266
|
+
</EntityLayout.Route>
|
|
267
|
+
|
|
268
|
+
<EntityLayout.Route
|
|
269
|
+
if={isApiiroApplicationAvailable}
|
|
270
|
+
path="/apiiro"
|
|
271
|
+
title="Apiiro"
|
|
272
|
+
>
|
|
273
|
+
<ApiiroTab />
|
|
274
|
+
</EntityLayout.Route>
|
|
275
|
+
|
|
276
|
+
{/* ... other elements */}
|
|
277
|
+
</EntityLayout>
|
|
278
|
+
);
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 7. Add Apiiro Widget to Custom Entity Tab (Optional)
|
|
203
282
|
|
|
204
283
|
The Apiiro plugin for Backstage includes a widget that can be embedded in a custom tab of the Backstage entity. This widget provides an overview of the risk associated with that entity, alongside your other valuable insights.
|
|
205
284
|
To add the widget, include the following component in your custom entity tab:
|
package/config.d.ts
CHANGED
|
@@ -26,5 +26,19 @@ export interface Config {
|
|
|
26
26
|
* @default true
|
|
27
27
|
*/
|
|
28
28
|
defaultAllowMetricsView?: boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Default value for the enable applications view annotation
|
|
32
|
+
* @visibility frontend
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
enableApplicationsView?: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Configuration to enable the devView for risks after redirect from Backstage to Apiiro
|
|
39
|
+
* @visibility frontend
|
|
40
|
+
* @default false
|
|
41
|
+
*/
|
|
42
|
+
redirectDevView?: boolean;
|
|
29
43
|
};
|
|
30
44
|
}
|
package/dist/App.esm.js
CHANGED
|
@@ -1,11 +1,103 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { Routes, Route } from 'react-router-dom';
|
|
3
|
-
import {
|
|
4
|
+
import { Page, Content } from '@backstage/core-components';
|
|
5
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
6
|
+
import Tab from '@mui/material/Tab';
|
|
7
|
+
import Tabs from '@mui/material/Tabs';
|
|
8
|
+
import Box from '@mui/material/Box';
|
|
9
|
+
import Typography from '@mui/material/Typography';
|
|
10
|
+
import { Repositories, RepositoriesContent } from './pages/Repositories/Repositories.esm.js';
|
|
11
|
+
import { Applications } from './pages/Applications/Applications.esm.js';
|
|
12
|
+
import { Header } from './components/Header.esm.js';
|
|
4
13
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
5
|
-
import { queryClient } from './api/index.esm.js';
|
|
14
|
+
import { queryClient, apiiroApiRef } from './api/index.esm.js';
|
|
6
15
|
|
|
16
|
+
const TabbedHome = () => {
|
|
17
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
18
|
+
const handleTabChange = (_, newValue) => {
|
|
19
|
+
setActiveTab(newValue);
|
|
20
|
+
};
|
|
21
|
+
return /* @__PURE__ */ jsxs(Page, { themeId: "tool", children: [
|
|
22
|
+
/* @__PURE__ */ jsx(Header, {}),
|
|
23
|
+
/* @__PURE__ */ jsxs(Content, { children: [
|
|
24
|
+
/* @__PURE__ */ jsx(Box, { sx: { borderBottom: 1, borderColor: "divider", mb: 2 }, children: /* @__PURE__ */ jsxs(
|
|
25
|
+
Tabs,
|
|
26
|
+
{
|
|
27
|
+
value: activeTab,
|
|
28
|
+
onChange: handleTabChange,
|
|
29
|
+
"aria-label": "Apiiro navigation tabs",
|
|
30
|
+
textColor: "inherit",
|
|
31
|
+
TabIndicatorProps: {
|
|
32
|
+
style: { backgroundColor: "currentColor" }
|
|
33
|
+
},
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ jsx(
|
|
36
|
+
Tab,
|
|
37
|
+
{
|
|
38
|
+
label: /* @__PURE__ */ jsx(
|
|
39
|
+
Typography,
|
|
40
|
+
{
|
|
41
|
+
variant: "h5",
|
|
42
|
+
sx: {
|
|
43
|
+
color: "text.primary",
|
|
44
|
+
opacity: activeTab === 0 ? 1 : 0.6
|
|
45
|
+
},
|
|
46
|
+
children: "Applications"
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
sx: {
|
|
50
|
+
textTransform: "none",
|
|
51
|
+
minWidth: "auto",
|
|
52
|
+
px: 2,
|
|
53
|
+
"&:hover": {
|
|
54
|
+
backgroundColor: "action.hover"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
Tab,
|
|
61
|
+
{
|
|
62
|
+
label: /* @__PURE__ */ jsx(
|
|
63
|
+
Typography,
|
|
64
|
+
{
|
|
65
|
+
variant: "h5",
|
|
66
|
+
sx: {
|
|
67
|
+
color: "text.primary",
|
|
68
|
+
opacity: activeTab === 1 ? 1 : 0.6
|
|
69
|
+
},
|
|
70
|
+
children: "Repositories"
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
sx: {
|
|
74
|
+
textTransform: "none",
|
|
75
|
+
minWidth: "auto",
|
|
76
|
+
px: 2,
|
|
77
|
+
"&:hover": {
|
|
78
|
+
backgroundColor: "action.hover"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
) }),
|
|
86
|
+
activeTab === 0 && /* @__PURE__ */ jsx(Applications, {}),
|
|
87
|
+
activeTab === 1 && /* @__PURE__ */ jsx(RepositoriesContent, {})
|
|
88
|
+
] })
|
|
89
|
+
] });
|
|
90
|
+
};
|
|
91
|
+
const AppContent = () => {
|
|
92
|
+
const connectApi = useApi(apiiroApiRef);
|
|
93
|
+
const enableApplicationsView = connectApi.getEnableApplicationsView();
|
|
94
|
+
if (enableApplicationsView) {
|
|
95
|
+
return /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsx(Route, { path: "/", element: /* @__PURE__ */ jsx(TabbedHome, {}) }) });
|
|
96
|
+
}
|
|
97
|
+
return /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsx(Route, { path: "/", element: /* @__PURE__ */ jsx(Repositories, {}) }) });
|
|
98
|
+
};
|
|
7
99
|
const App = () => {
|
|
8
|
-
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(
|
|
100
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(AppContent, {}) });
|
|
9
101
|
};
|
|
10
102
|
|
|
11
103
|
export { App };
|
package/dist/App.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.esm.js","sources":["../src/App.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Routes, Route } from 'react-router-dom';\nimport { Repositories } from './pages/Repositories';\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { queryClient } from './api';\n\
|
|
1
|
+
{"version":3,"file":"App.esm.js","sources":["../src/App.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState } from 'react';\nimport { Routes, Route } from 'react-router-dom';\nimport { Content, Page } from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\nimport Tab from '@mui/material/Tab';\nimport Tabs from '@mui/material/Tabs';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport { Repositories, RepositoriesContent } from './pages/Repositories';\nimport { Applications } from './pages/Applications';\nimport { Header } from './components/Header';\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { queryClient, apiiroApiRef } from './api';\n\nconst TabbedHome = () => {\n const [activeTab, setActiveTab] = useState(0);\n\n const handleTabChange = (_: React.SyntheticEvent, newValue: number) => {\n setActiveTab(newValue);\n };\n\n return (\n <Page themeId=\"tool\">\n <Header />\n <Content>\n <Box sx={{ borderBottom: 1, borderColor: 'divider', mb: 2 }}>\n <Tabs\n value={activeTab}\n onChange={handleTabChange}\n aria-label=\"Apiiro navigation tabs\"\n textColor=\"inherit\"\n TabIndicatorProps={{\n style: { backgroundColor: 'currentColor' },\n }}\n >\n <Tab\n label={\n <Typography\n variant=\"h5\"\n sx={{\n color: 'text.primary',\n opacity: activeTab === 0 ? 1 : 0.6,\n }}\n >\n Applications\n </Typography>\n }\n sx={{\n textTransform: 'none',\n minWidth: 'auto',\n px: 2,\n '&:hover': {\n backgroundColor: 'action.hover',\n },\n }}\n />\n <Tab\n label={\n <Typography\n variant=\"h5\"\n sx={{\n color: 'text.primary',\n opacity: activeTab === 1 ? 1 : 0.6,\n }}\n >\n Repositories\n </Typography>\n }\n sx={{\n textTransform: 'none',\n minWidth: 'auto',\n px: 2,\n '&:hover': {\n backgroundColor: 'action.hover',\n },\n }}\n />\n </Tabs>\n </Box>\n\n {activeTab === 0 && <Applications />}\n {activeTab === 1 && <RepositoriesContent />}\n </Content>\n </Page>\n );\n};\n\nconst AppContent = () => {\n const connectApi = useApi(apiiroApiRef);\n const enableApplicationsView = connectApi.getEnableApplicationsView();\n\n if (enableApplicationsView) {\n return (\n <Routes>\n <Route path=\"/\" element={<TabbedHome />} />\n </Routes>\n );\n }\n\n return (\n <Routes>\n <Route path=\"/\" element={<Repositories />} />\n </Routes>\n );\n};\n\nexport const App = () => {\n return (\n <QueryClientProvider client={queryClient}>\n <AppContent />\n </QueryClientProvider>\n );\n};\n"],"names":[],"mappings":"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"}
|
package/dist/api/index.esm.js
CHANGED
|
@@ -14,6 +14,12 @@ class ApiiroClient {
|
|
|
14
14
|
getDefaultAllowMetricsView() {
|
|
15
15
|
return this.configApi.getOptionalBoolean("apiiro.defaultAllowMetricsView") ?? true;
|
|
16
16
|
}
|
|
17
|
+
getEnableApplicationsView() {
|
|
18
|
+
return this.configApi.getOptionalBoolean("apiiro.enableApplicationsView") ?? false;
|
|
19
|
+
}
|
|
20
|
+
getRedirectDevView() {
|
|
21
|
+
return this.configApi.getOptionalBoolean("apiiro.redirectDevView") ?? false;
|
|
22
|
+
}
|
|
17
23
|
}
|
|
18
24
|
const queryClient = new QueryClient();
|
|
19
25
|
function assembleUri(uri, params) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { QueryClient } from '@tanstack/react-query';\nimport {\n ConfigApi,\n createApiRef,\n DiscoveryApi,\n} from '@backstage/core-plugin-api';\n\n/**\n * Plugin API\n */\nexport type ApiiroApi = {\n discoveryApi: DiscoveryApi;\n getDefaultAllowMetricsView: () => boolean;\n};\n\nexport const apiiroApiRef = createApiRef<ApiiroApi>({\n id: 'plugin.apiiro.service',\n});\n\nexport class ApiiroClient implements ApiiroApi {\n discoveryApi: DiscoveryApi;\n private readonly configApi: ConfigApi;\n\n constructor(options: { discoveryApi: DiscoveryApi; configApi: ConfigApi }) {\n this.discoveryApi = options.discoveryApi;\n this.configApi = options.configApi;\n }\n\n getDefaultAllowMetricsView(): boolean {\n return (\n this.configApi.getOptionalBoolean('apiiro.defaultAllowMetricsView') ??\n true\n );\n }\n}\n\n/**\n * React Query Client\n */\nexport const queryClient = new QueryClient();\n\n/**\n * Fetch: GET, POST\n */\ntype QueryParams = Record<string, string>;\n\ntype RequestHeaders = Record<string, string>;\n\nenum ApiHeaders {\n CONTENT_TYPE = 'Content-Type',\n}\n\nenum REQUEST_METHOD {\n GET = 'GET',\n POST = 'POST',\n}\n\ninterface RequestOptions {\n body?: any;\n headers?: RequestHeaders;\n params?: Record<string, any> | null;\n signal?: AbortSignal;\n}\n\nfunction assembleUri(uri: string, params?: QueryParams): string {\n if (!params) {\n return uri;\n }\n\n const queryString = new URLSearchParams(params).toString();\n return `${uri}?${queryString}`;\n}\n\nfunction buildHeaders(optionHeaders: RequestHeaders): Headers {\n const headers = new Headers();\n headers.set(ApiHeaders.CONTENT_TYPE, 'application/json');\n\n Object.keys(optionHeaders).forEach(header => {\n const headerValue = optionHeaders[header];\n if (headerValue) {\n headers.set(header, headerValue);\n }\n });\n\n return headers;\n}\n\nfunction fetchRequest(\n fetchApi: typeof fetch,\n method: REQUEST_METHOD,\n url: string,\n opts: RequestOptions,\n): Promise<any> {\n const { params, body, headers, signal } = opts;\n\n const requestURL = params ? assembleUri(url, params) : url;\n\n const requestParams: RequestInit = {\n headers: buildHeaders(headers || {}),\n method,\n signal,\n };\n\n if (body) {\n requestParams.body = typeof body === 'string' ? body : JSON.stringify(body);\n }\n\n return fetchApi(requestURL, requestParams);\n}\n\nfunction toJson(response: Response): Promise<any> {\n if (response.status === 204 || response.body === null) {\n return Promise.resolve({});\n }\n\n return response.json().then(json => {\n return response.ok ? json : Promise.reject(json);\n });\n}\n\nconst defaultOpts: RequestOptions = {\n body: null,\n headers: {},\n params: null,\n};\n\nexport function get<T>(\n fetchApi: typeof fetch,\n url: string,\n opts: RequestOptions = defaultOpts,\n): Promise<T> {\n return fetchRequest(fetchApi, REQUEST_METHOD.GET, url, opts).then(toJson);\n}\n\nexport function post<T>(\n fetchApi: typeof fetch,\n url: string,\n opts: RequestOptions = defaultOpts,\n): Promise<T> {\n return fetchRequest(fetchApi, REQUEST_METHOD.POST, url, opts).then(toJson);\n}\n"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { QueryClient } from '@tanstack/react-query';\nimport {\n ConfigApi,\n createApiRef,\n DiscoveryApi,\n} from '@backstage/core-plugin-api';\n\n/**\n * Plugin API\n */\nexport type ApiiroApi = {\n discoveryApi: DiscoveryApi;\n getDefaultAllowMetricsView: () => boolean;\n getEnableApplicationsView: () => boolean;\n getRedirectDevView: () => boolean;\n};\n\nexport const apiiroApiRef = createApiRef<ApiiroApi>({\n id: 'plugin.apiiro.service',\n});\n\nexport class ApiiroClient implements ApiiroApi {\n discoveryApi: DiscoveryApi;\n private readonly configApi: ConfigApi;\n\n constructor(options: { discoveryApi: DiscoveryApi; configApi: ConfigApi }) {\n this.discoveryApi = options.discoveryApi;\n this.configApi = options.configApi;\n }\n\n getDefaultAllowMetricsView(): boolean {\n return (\n this.configApi.getOptionalBoolean('apiiro.defaultAllowMetricsView') ??\n true\n );\n }\n\n getEnableApplicationsView(): boolean {\n return (\n this.configApi.getOptionalBoolean('apiiro.enableApplicationsView') ??\n false\n );\n }\n\n getRedirectDevView(): boolean {\n return this.configApi.getOptionalBoolean('apiiro.redirectDevView') ?? false;\n }\n}\n\n/**\n * React Query Client\n */\nexport const queryClient = new QueryClient();\n\n/**\n * Fetch: GET, POST\n */\ntype QueryParams = Record<string, string>;\n\ntype RequestHeaders = Record<string, string>;\n\nenum ApiHeaders {\n CONTENT_TYPE = 'Content-Type',\n}\n\nenum REQUEST_METHOD {\n GET = 'GET',\n POST = 'POST',\n}\n\ninterface RequestOptions {\n body?: any;\n headers?: RequestHeaders;\n params?: Record<string, any> | null;\n signal?: AbortSignal;\n}\n\nfunction assembleUri(uri: string, params?: QueryParams): string {\n if (!params) {\n return uri;\n }\n\n const queryString = new URLSearchParams(params).toString();\n return `${uri}?${queryString}`;\n}\n\nfunction buildHeaders(optionHeaders: RequestHeaders): Headers {\n const headers = new Headers();\n headers.set(ApiHeaders.CONTENT_TYPE, 'application/json');\n\n Object.keys(optionHeaders).forEach(header => {\n const headerValue = optionHeaders[header];\n if (headerValue) {\n headers.set(header, headerValue);\n }\n });\n\n return headers;\n}\n\nfunction fetchRequest(\n fetchApi: typeof fetch,\n method: REQUEST_METHOD,\n url: string,\n opts: RequestOptions,\n): Promise<any> {\n const { params, body, headers, signal } = opts;\n\n const requestURL = params ? assembleUri(url, params) : url;\n\n const requestParams: RequestInit = {\n headers: buildHeaders(headers || {}),\n method,\n signal,\n };\n\n if (body) {\n requestParams.body = typeof body === 'string' ? body : JSON.stringify(body);\n }\n\n return fetchApi(requestURL, requestParams);\n}\n\nfunction toJson(response: Response): Promise<any> {\n if (response.status === 204 || response.body === null) {\n return Promise.resolve({});\n }\n\n return response.json().then(json => {\n return response.ok ? json : Promise.reject(json);\n });\n}\n\nconst defaultOpts: RequestOptions = {\n body: null,\n headers: {},\n params: null,\n};\n\nexport function get<T>(\n fetchApi: typeof fetch,\n url: string,\n opts: RequestOptions = defaultOpts,\n): Promise<T> {\n return fetchRequest(fetchApi, REQUEST_METHOD.GET, url, opts).then(toJson);\n}\n\nexport function post<T>(\n fetchApi: typeof fetch,\n url: string,\n opts: RequestOptions = defaultOpts,\n): Promise<T> {\n return fetchRequest(fetchApi, REQUEST_METHOD.POST, url, opts).then(toJson);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import '../components/common/ChartBox.esm.js';
|
|
|
4
4
|
import { CustomTooltip } from '../components/common/CustomTooltip.esm.js';
|
|
5
5
|
import '@mui/material/Box';
|
|
6
6
|
import '@mui/material/Typography';
|
|
7
|
+
import '../components/common/StatusContainer.esm.js';
|
|
7
8
|
|
|
8
9
|
const StyledSvg = styled("svg")({
|
|
9
10
|
cursor: "pointer",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingIcon.esm.js","sources":["../../src/assets/SettingIcon.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useTheme } from '@mui/material/styles';\nimport { styled } from '@mui/material/styles';\nimport { CustomTooltip } from '../components/common';\n\nconst StyledSvg = styled('svg')({\n cursor: 'pointer',\n '&:hover': {\n '& path': {\n opacity: 0.8,\n },\n },\n});\n\nexport const SettingIcon = () => {\n const theme = useTheme();\n const iconColor = theme.palette.text.secondary;\n\n return (\n <CustomTooltip\n title=\"Configure branches via connection page\"\n placement=\"top\"\n >\n <StyledSvg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n data-name=\"Settings\"\n data-size=\"small\"\n >\n <path\n fill=\"none\"\n stroke={iconColor}\n strokeWidth=\"1.2\"\n d=\"m9.479 5.423.613-1.537c.103-.26.284-.484.52-.642s.517-.243.804-.244h1.168c.287 0 .567.086.803.244s.418.382.521.642l.613 1.537 2.08 1.163 1.68-.25c.28-.036.565.009.818.13.254.12.465.312.606.55l.57.969a1.355 1.355 0 0 1-.114 1.564l-1.04 1.288v2.326l1.069 1.288a1.353 1.353 0 0 1 .114 1.565l-.57.969a1.4 1.4 0 0 1-.606.55 1.46 1.46 0 0 1-.818.128l-1.681-.25-2.08 1.164-.612 1.537c-.103.26-.285.484-.521.642a1.45 1.45 0 0 1-.804.244h-1.196c-.287 0-.567-.086-.803-.244a1.4 1.4 0 0 1-.521-.642l-.613-1.537-2.08-1.163-1.68.25a1.46 1.46 0 0 1-.818-.13 1.4 1.4 0 0 1-.606-.55l-.57-.969a1.35 1.35 0 0 1 .114-1.564l1.04-1.288v-2.326L3.81 9.549a1.354 1.354 0 0 1-.114-1.565l.57-.969a1.4 1.4 0 0 1 .606-.55 1.46 1.46 0 0 1 .818-.128l1.681.25 2.08-1.163zM9.151 12c0 .548.168 1.083.48 1.539.314.455.758.81 1.279 1.02s1.093.264 1.646.157a2.87 2.87 0 0 0 1.458-.758c.399-.387.67-.88.78-1.418a2.7 2.7 0 0 0-.162-1.6 2.8 2.8 0 0 0-1.05-1.243A2.9 2.9 0 0 0 12 9.231a2.9 2.9 0 0 0-2.014.81 2.73 2.73 0 0 0-.835 1.96z\"\n />\n </StyledSvg>\n </CustomTooltip>\n );\n};\n\nexport default SettingIcon;\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SettingIcon.esm.js","sources":["../../src/assets/SettingIcon.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useTheme } from '@mui/material/styles';\nimport { styled } from '@mui/material/styles';\nimport { CustomTooltip } from '../components/common';\n\nconst StyledSvg = styled('svg')({\n cursor: 'pointer',\n '&:hover': {\n '& path': {\n opacity: 0.8,\n },\n },\n});\n\nexport const SettingIcon = () => {\n const theme = useTheme();\n const iconColor = theme.palette.text.secondary;\n\n return (\n <CustomTooltip\n title=\"Configure branches via connection page\"\n placement=\"top\"\n >\n <StyledSvg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n data-name=\"Settings\"\n data-size=\"small\"\n >\n <path\n fill=\"none\"\n stroke={iconColor}\n strokeWidth=\"1.2\"\n d=\"m9.479 5.423.613-1.537c.103-.26.284-.484.52-.642s.517-.243.804-.244h1.168c.287 0 .567.086.803.244s.418.382.521.642l.613 1.537 2.08 1.163 1.68-.25c.28-.036.565.009.818.13.254.12.465.312.606.55l.57.969a1.355 1.355 0 0 1-.114 1.564l-1.04 1.288v2.326l1.069 1.288a1.353 1.353 0 0 1 .114 1.565l-.57.969a1.4 1.4 0 0 1-.606.55 1.46 1.46 0 0 1-.818.128l-1.681-.25-2.08 1.164-.612 1.537c-.103.26-.285.484-.521.642a1.45 1.45 0 0 1-.804.244h-1.196c-.287 0-.567-.086-.803-.244a1.4 1.4 0 0 1-.521-.642l-.613-1.537-2.08-1.163-1.68.25a1.46 1.46 0 0 1-.818-.13 1.4 1.4 0 0 1-.606-.55l-.57-.969a1.35 1.35 0 0 1 .114-1.564l1.04-1.288v-2.326L3.81 9.549a1.354 1.354 0 0 1-.114-1.565l.57-.969a1.4 1.4 0 0 1 .606-.55 1.46 1.46 0 0 1 .818-.128l1.681.25 2.08-1.163zM9.151 12c0 .548.168 1.083.48 1.539.314.455.758.81 1.279 1.02s1.093.264 1.646.157a2.87 2.87 0 0 0 1.458-.758c.399-.387.67-.88.78-1.418a2.7 2.7 0 0 0-.162-1.6 2.8 2.8 0 0 0-1.05-1.243A2.9 2.9 0 0 0 12 9.231a2.9 2.9 0 0 0-2.014.81 2.73 2.73 0 0 0-.835 1.96z\"\n />\n </StyledSvg>\n </CustomTooltip>\n );\n};\n\nexport default SettingIcon;\n"],"names":[],"mappings":";;;;;;;;AAmBA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAK,CAAA,CAAE;AAAA,EAC9B,MAAA,EAAQ,SAAA;AAAA,EACR,SAAA,EAAW;AAAA,IACT,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA;AACX;AAEJ,CAAC,CAAA;AAEM,MAAM,cAAc,MAAM;AAC/B,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAErC,EAAA,uBACE,GAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,wCAAA;AAAA,MACN,SAAA,EAAU,KAAA;AAAA,MAEV,QAAA,kBAAA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAM,4BAAA;AAAA,UACN,KAAA,EAAM,IAAA;AAAA,UACN,MAAA,EAAO,IAAA;AAAA,UACP,OAAA,EAAQ,WAAA;AAAA,UACR,WAAA,EAAU,UAAA;AAAA,UACV,WAAA,EAAU,OAAA;AAAA,UAEV,QAAA,kBAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,MAAA;AAAA,cACL,MAAA,EAAQ,SAAA;AAAA,cACR,WAAA,EAAY,KAAA;AAAA,cACZ,CAAA,EAAE;AAAA;AAAA;AACJ;AAAA;AACF;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiiroSidebar.esm.js","sources":["../../src/components/ApiiroSidebar.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { SidebarItem } from '@backstage/core-components';\nimport { ApiiroSidebar as ApiiroSidebarIcon } from '../assets/apiiroLogo/apiiroSidebar';\n\n
|
|
1
|
+
{"version":3,"file":"ApiiroSidebar.esm.js","sources":["../../src/components/ApiiroSidebar.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { SidebarItem } from '@backstage/core-components';\nimport { ApiiroSidebar as ApiiroSidebarIcon } from '../assets/apiiroLogo/apiiroSidebar';\n\n/**\n * Sidebar navigation item for the Apiiro plugin.\n * Displays the Apiiro icon and links to the Apiiro page.\n * @public\n */\nexport const ApiiroSidebar = (): JSX.Element => {\n return <SidebarItem icon={ApiiroSidebarIcon} to=\"apiiro\" text=\"apiiro\" />;\n};\n"],"names":["ApiiroSidebarIcon"],"mappings":";;;;AAuBO,MAAM,gBAAgB,MAAmB;AAC9C,EAAA,2BAAQ,WAAA,EAAA,EAAY,IAAA,EAAMA,iBAAmB,EAAA,EAAG,QAAA,EAAS,MAAK,QAAA,EAAS,CAAA;AACzE;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CalendarDatePicker.esm.js","sources":["../../src/components/CalendarDatePicker.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport 'react-calendar/dist/Calendar.css';\n\nimport { forwardRef, useCallback, useMemo } from 'react';\nimport { CalendarProps } from 'react-calendar';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport ChevronLeftIcon from '@mui/icons-material/ChevronLeft';\nimport ChevronRightIcon from '@mui/icons-material/ChevronRight';\nimport { useTheme } from '@mui/material/styles';\nimport {\n CalendarContainer,\n StyledCalendar,\n QuickRangeList,\n QuickRangeItem,\n QuickRangeText,\n} from './CalendarDatePicker.styles';\nimport { LooseValue } from 'react-calendar/dist/cjs/shared/types';\n\ntype Value = Date | Date[] | null;\n\nexport type CalendarDateValue = Date | [Date, Date] | [];\n\nexport type CalendarQuickRange = {\n label: string;\n value: string;\n getRange: () => CalendarDateValue | null;\n};\n\ntype CalendarDatePickerProps = {\n value?: CalendarDateValue;\n onChange?: (date: CalendarDateValue) => void;\n quickRanges?: CalendarQuickRange[];\n selectedQuickRange?: string;\n onQuickRangeSelect?: (quickRange: CalendarQuickRange) => void;\n showQuickRanges?: boolean;\n tileStyle?: (args: {\n date: Date;\n view: string;\n }) => globalThis.React.CSSProperties;\n} & Pick<\n CalendarProps,\n | 'activeStartDate'\n | 'minDate'\n | 'maxDate'\n | 'tileClassName'\n | 'tileContent'\n | 'tileDisabled'\n | 'selectRange'\n | 'onActiveStartDateChange'\n>;\n\nexport const createDefaultQuickRanges = (): CalendarQuickRange[] => {\n const today = new Date();\n\n const startOfDay = (date: Date) => {\n const copy = new Date(date);\n copy.setHours(0, 0, 0, 0);\n return copy;\n };\n\n const endOfDay = (date: Date) => {\n const copy = new Date(date);\n copy.setHours(23, 59, 59, 999);\n return copy;\n };\n\n const subtractDays = (amount: number) => {\n const date = new Date();\n date.setDate(date.getDate() - amount);\n return date;\n };\n\n return [\n {\n label: 'All Dates',\n value: 'all',\n getRange: () => [subtractDays(365 * 10), endOfDay(new Date())],\n },\n {\n label: 'Last 7 days',\n value: 'last-7-days',\n getRange: () => [startOfDay(subtractDays(6)), endOfDay(today)],\n },\n {\n label: 'Last 14 days',\n value: 'last-14-days',\n getRange: () => [startOfDay(subtractDays(13)), endOfDay(today)],\n },\n {\n label: 'Last 30 days',\n value: 'last-30-days',\n getRange: () => [startOfDay(subtractDays(29)), endOfDay(today)],\n },\n {\n label: 'Last 90 days',\n value: 'last-90-days',\n getRange: () => [startOfDay(subtractDays(89)), endOfDay(today)],\n },\n {\n label: 'Custom',\n value: 'custom',\n getRange: () => [],\n },\n ];\n};\n\nexport const CalendarDatePicker = forwardRef<\n HTMLDivElement,\n CalendarDatePickerProps\n>(\n (\n {\n selectRange = true,\n showQuickRanges = true,\n quickRanges,\n selectedQuickRange,\n onQuickRangeSelect,\n value,\n onChange,\n ...props\n },\n ref,\n ) => {\n const theme = useTheme();\n\n const computedQuickRanges = useMemo(\n () => quickRanges ?? createDefaultQuickRanges(),\n [quickRanges],\n );\n\n const formatShortWeekday = useCallback(\n (locale: string | undefined, date: Date) =>\n date\n .toLocaleDateString(locale || 'en-US', { weekday: 'short' })\n .slice(0, 1),\n [],\n );\n\n const handleCalendarChange = useCallback(\n (calendarValue: Value) => {\n if (onChange) {\n onChange(calendarValue as CalendarDateValue);\n }\n },\n [onChange],\n );\n\n const handleQuickRangeSelect = (range: CalendarQuickRange) => {\n if (onQuickRangeSelect) {\n onQuickRangeSelect(range);\n }\n const nextValue = range.getRange();\n if (nextValue && onChange) {\n onChange(nextValue);\n }\n };\n\n return (\n <CalendarContainer ref={ref}>\n <StyledCalendar\n value={value as LooseValue}\n onChange={handleCalendarChange as any}\n selectRange={selectRange}\n formatShortWeekday={formatShortWeekday}\n prev2Label={null}\n next2Label={null}\n prevLabel={<ChevronLeftIcon />}\n nextLabel={<ChevronRightIcon />}\n minDetail=\"decade\"\n {...props}\n />\n {showQuickRanges && (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 1,\n backgroundColor: theme.palette.background.paper,\n }}\n >\n <Typography\n variant=\"subtitle2\"\n sx={{\n color: theme.palette.text.secondary,\n fontWeight: 600,\n mb: 0.5,\n }}\n >\n Presets\n </Typography>\n <QuickRangeList>\n {computedQuickRanges.map(range => (\n <QuickRangeItem\n key={range.value}\n $selected={selectedQuickRange === range.value}\n onClick={() => handleQuickRangeSelect(range)}\n >\n <QuickRangeText primary={range.label} />\n </QuickRangeItem>\n ))}\n </QuickRangeList>\n </Box>\n )}\n </CalendarContainer>\n );\n },\n);\n\nCalendarDatePicker.displayName = 'CalendarDatePicker';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CalendarDatePicker.esm.js","sources":["../../src/components/CalendarDatePicker.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport 'react-calendar/dist/Calendar.css';\n\nimport { forwardRef, useCallback, useMemo } from 'react';\nimport { CalendarProps } from 'react-calendar';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport ChevronLeftIcon from '@mui/icons-material/ChevronLeft';\nimport ChevronRightIcon from '@mui/icons-material/ChevronRight';\nimport { useTheme } from '@mui/material/styles';\nimport {\n CalendarContainer,\n StyledCalendar,\n QuickRangeList,\n QuickRangeItem,\n QuickRangeText,\n} from './CalendarDatePicker.styles';\n\ntype Value = Date | Date[] | null;\n\nexport type CalendarDateValue = Date | [Date, Date] | [];\n\nexport type CalendarQuickRange = {\n label: string;\n value: string;\n getRange: () => CalendarDateValue | null;\n};\n\ntype CalendarDatePickerProps = {\n value?: CalendarDateValue;\n onChange?: (date: CalendarDateValue) => void;\n quickRanges?: CalendarQuickRange[];\n selectedQuickRange?: string;\n onQuickRangeSelect?: (quickRange: CalendarQuickRange) => void;\n showQuickRanges?: boolean;\n tileStyle?: (args: {\n date: Date;\n view: string;\n }) => globalThis.React.CSSProperties;\n} & Pick<\n CalendarProps,\n | 'activeStartDate'\n | 'minDate'\n | 'maxDate'\n | 'tileClassName'\n | 'tileContent'\n | 'tileDisabled'\n | 'selectRange'\n | 'onActiveStartDateChange'\n>;\n\nexport const createDefaultQuickRanges = (): CalendarQuickRange[] => {\n const today = new Date();\n\n const startOfDay = (date: Date) => {\n const copy = new Date(date);\n copy.setHours(0, 0, 0, 0);\n return copy;\n };\n\n const endOfDay = (date: Date) => {\n const copy = new Date(date);\n copy.setHours(23, 59, 59, 999);\n return copy;\n };\n\n const subtractDays = (amount: number) => {\n const date = new Date();\n date.setDate(date.getDate() - amount);\n return date;\n };\n\n return [\n {\n label: 'All Dates',\n value: 'all',\n getRange: () => [subtractDays(365 * 10), endOfDay(new Date())],\n },\n {\n label: 'Last 7 days',\n value: 'last-7-days',\n getRange: () => [startOfDay(subtractDays(6)), endOfDay(today)],\n },\n {\n label: 'Last 14 days',\n value: 'last-14-days',\n getRange: () => [startOfDay(subtractDays(13)), endOfDay(today)],\n },\n {\n label: 'Last 30 days',\n value: 'last-30-days',\n getRange: () => [startOfDay(subtractDays(29)), endOfDay(today)],\n },\n {\n label: 'Last 90 days',\n value: 'last-90-days',\n getRange: () => [startOfDay(subtractDays(89)), endOfDay(today)],\n },\n {\n label: 'Custom',\n value: 'custom',\n getRange: () => [],\n },\n ];\n};\n\nexport const CalendarDatePicker = forwardRef<\n HTMLDivElement,\n CalendarDatePickerProps\n>(\n (\n {\n selectRange = true,\n showQuickRanges = true,\n quickRanges,\n selectedQuickRange,\n onQuickRangeSelect,\n value,\n onChange,\n ...props\n },\n ref,\n ) => {\n const theme = useTheme();\n\n const computedQuickRanges = useMemo(\n () => quickRanges ?? createDefaultQuickRanges(),\n [quickRanges],\n );\n\n const formatShortWeekday = useCallback(\n (locale: string | undefined, date: Date) =>\n date\n .toLocaleDateString(locale || 'en-US', { weekday: 'short' })\n .slice(0, 1),\n [],\n );\n\n const handleCalendarChange = useCallback(\n (calendarValue: Value) => {\n if (onChange) {\n onChange(calendarValue as CalendarDateValue);\n }\n },\n [onChange],\n );\n\n const handleQuickRangeSelect = (range: CalendarQuickRange) => {\n if (onQuickRangeSelect) {\n onQuickRangeSelect(range);\n }\n const nextValue = range.getRange();\n if (nextValue && onChange) {\n onChange(nextValue);\n }\n };\n\n return (\n <CalendarContainer ref={ref}>\n <StyledCalendar\n value={value as any}\n onChange={handleCalendarChange as any}\n selectRange={selectRange}\n formatShortWeekday={formatShortWeekday}\n prev2Label={null}\n next2Label={null}\n prevLabel={<ChevronLeftIcon />}\n nextLabel={<ChevronRightIcon />}\n minDetail=\"decade\"\n {...props}\n />\n {showQuickRanges && (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 1,\n backgroundColor: theme.palette.background.paper,\n }}\n >\n <Typography\n variant=\"subtitle2\"\n sx={{\n color: theme.palette.text.secondary,\n fontWeight: 600,\n mb: 0.5,\n }}\n >\n Presets\n </Typography>\n <QuickRangeList>\n {computedQuickRanges.map(range => (\n <QuickRangeItem\n key={range.value}\n $selected={selectedQuickRange === range.value}\n onClick={() => handleQuickRangeSelect(range)}\n >\n <QuickRangeText primary={range.label} />\n </QuickRangeItem>\n ))}\n </QuickRangeList>\n </Box>\n )}\n </CalendarContainer>\n );\n },\n);\n\nCalendarDatePicker.displayName = 'CalendarDatePicker';\n"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import '../common/ChartBox.esm.js';
|
|
|
10
10
|
import 'react-dom';
|
|
11
11
|
import { NotFound } from '../common/NotFound.esm.js';
|
|
12
12
|
import '@mui/material/Typography';
|
|
13
|
+
import '../common/StatusContainer.esm.js';
|
|
13
14
|
import { LogoSpinner } from '../common/logoSpinner.esm.js';
|
|
14
15
|
|
|
15
16
|
function DataGrid({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGrid.esm.js","sources":["../../../src/components/DataGrid/DataGrid.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useEffect, useState, useCallback } from 'react';\nimport {\n DataGrid as DataGridMUI,\n GridColDef,\n GridPaginationModel,\n useGridApiRef,\n GridValidRowModel,\n} from '@mui/x-data-grid';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport { CustomColumnMenu } from './CustomColumnMenu';\nimport { CustomPagination } from './CustomPagination';\nimport { CustomSearchToolbar } from './CustomSearchToolbar';\nimport { DataGridProps, GridLayout } from './types';\nimport { NotFound } from '../common';\nimport { LogoSpinner } from '../common/logoSpinner';\n\nexport function DataGrid<T extends GridValidRowModel>({\n // Required props\n tableKey,\n columns: propColumns,\n rows: propRows,\n\n // Optional configuration\n dataLabel = 'items',\n searchBarPlaceHolder = 'Search',\n features = {},\n styling = {},\n\n // Pagination\n initialPageSize = 20,\n pageSizeOptions = [20, 50, 100],\n\n // Event handlers\n onRowClick,\n onSelectionChange,\n\n // Custom components\n customFilters,\n columnVisibility,\n\n // Loading state\n loading,\n\n // custom Row ID\n getRowId,\n\n // Initial Table state\n initialState,\n}: DataGridProps<T>) {\n const theme = useTheme();\n const apiRef = useGridApiRef();\n\n // Default feature flags\n const {\n quickSearch = true,\n columnPinning = true,\n columnReordering = true,\n customPagination = true,\n columnMenu = true,\n persistLayout = true,\n } = features;\n\n // Default styling\n const {\n borderRadius = '12px',\n headerBackgroundColor = theme.palette.mode === 'dark'\n ? theme.palette.background.paper\n : theme.palette.grey[100],\n backgroundColor = theme.palette.background.paper,\n height = 'auto',\n } = styling;\n\n const [columns, setColumns] = useState<GridColDef<T>[]>(propColumns);\n const [pinned, setPinned] = useState<string[]>([]);\n const [dragCol, setDragCol] = useState<string | null>(null);\n const [dropTarget, setDropTarget] = useState<string | null>(null);\n const [dropSide, setDropSide] = useState<'left' | 'right' | null>(null);\n const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({\n page: 0,\n pageSize: initialPageSize,\n });\n\n const [columnVisibilityModel, setColumnVisibilityModel] = useState<\n Record<string, boolean>\n >(columnVisibility || {});\n\n // Load saved layout\n useEffect(() => {\n if (!persistLayout) return;\n\n try {\n const saved = localStorage.getItem(`apiiro-gridLayout-${tableKey}`);\n if (saved) {\n const {\n order,\n pinned: savedPinned,\n columnVisibility: savedVisibility,\n } = JSON.parse(saved) as GridLayout;\n setPinned(savedPinned || []);\n\n // Restore column visibility if saved\n if (savedVisibility) {\n setColumnVisibilityModel(savedVisibility);\n }\n\n const orderedColumns = order\n .map(field => propColumns.find(c => c.field === field))\n .filter((c): c is GridColDef<T> => !!c);\n setColumns(orderedColumns);\n }\n } catch (error) {\n // Failed to load grid layout - using default\n }\n }, [propColumns, persistLayout, tableKey]);\n\n const saveLayout = useCallback(\n (\n cols: GridColDef<T>[],\n pinnedCols: string[],\n visibility?: Record<string, boolean>,\n ) => {\n if (!persistLayout) return;\n\n const layout: GridLayout = {\n order: cols.map(c => c.field),\n pinned: pinnedCols,\n columnVisibility: visibility || columnVisibilityModel,\n };\n localStorage.setItem(\n `apiiro-gridLayout-${tableKey}`,\n JSON.stringify(layout),\n );\n },\n [persistLayout, tableKey, columnVisibilityModel],\n );\n\n // Save column visibility changes to gridLayout\n useEffect(() => {\n if (persistLayout) {\n saveLayout(columns, pinned, columnVisibilityModel);\n }\n }, [columnVisibilityModel, persistLayout, saveLayout, columns, pinned]);\n\n const handleDragStart = (field: string) => setDragCol(field);\n\n const handleDragOver = (\n e: React.DragEvent<HTMLDivElement>,\n targetField: string,\n ) => {\n e.preventDefault();\n if (dragCol === targetField) return;\n const targetRect = e.currentTarget.getBoundingClientRect();\n const x = e.clientX - targetRect.left;\n setDropTarget(targetField);\n setDropSide(x < targetRect.width / 2 ? 'left' : 'right');\n };\n\n const handleDragLeave = () => setDropTarget(null);\n\n const handleDrop = (targetField: string) => {\n if (!dragCol || dragCol === targetField) return;\n\n const dragIsPinned = pinned.includes(dragCol);\n const targetIsPinned = pinned.includes(targetField);\n\n if (dragIsPinned !== targetIsPinned) {\n setDragCol(null);\n setDropTarget(null);\n return;\n }\n\n const currentList = dragIsPinned\n ? columns.filter(c => pinned.includes(c.field))\n : columns.filter(c => !pinned.includes(c.field));\n\n const dragIndex = currentList.findIndex(c => c.field === dragCol);\n const targetIndex = currentList.findIndex(c => c.field === targetField);\n\n const newIndex = dropSide === 'left' ? targetIndex : targetIndex + 1;\n const reordered = [...currentList];\n const [moved] = reordered.splice(dragIndex, 1);\n reordered.splice(newIndex, 0, moved);\n\n const finalColumns = dragIsPinned\n ? [...reordered, ...columns.filter(c => !pinned.includes(c.field))]\n : [...columns.filter(c => pinned.includes(c.field)), ...reordered];\n\n setColumns(finalColumns);\n setDragCol(null);\n setDropTarget(null);\n saveLayout(finalColumns, pinned);\n };\n\n const togglePin = useCallback(\n (field: string) => {\n setPinned(prev => {\n const next = prev.includes(field)\n ? prev.filter(f => f !== field)\n : [...prev, field];\n saveLayout(columns, next);\n return next;\n });\n },\n [columns, saveLayout],\n );\n\n const CustomColumnMenuWithProps = useCallback(\n (props: any) => {\n return (\n <CustomColumnMenu\n {...props}\n isPinned={pinned.includes(props.colDef.field)}\n onTogglePin={togglePin}\n />\n );\n },\n [pinned, togglePin],\n );\n\n const CustomPaginationComponent = useCallback(\n () => (\n <CustomPagination\n onPageSizeChange={pageSize => setPaginationModel({ page: 0, pageSize })}\n pageSizeOptions={pageSizeOptions}\n dataLabel={dataLabel}\n />\n ),\n [dataLabel, pageSizeOptions],\n );\n\n const finalColumns = columnReordering\n ? columns.map(col => ({\n ...col,\n renderHeader: () => (\n <Box\n draggable={columnReordering}\n onDragStart={() => handleDragStart(col.field)}\n onDragOver={e => handleDragOver(e, col.field)}\n onDragLeave={handleDragLeave}\n onDrop={() => handleDrop(col.field)}\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n cursor: columnReordering ? 'grab' : 'default',\n userSelect: 'none',\n position: 'relative',\n fontWeight:\n columnPinning && pinned.includes(col.field) ? 'bold' : 'normal',\n px: 1,\n '&::before': columnReordering\n ? {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n bottom: 0,\n left:\n dropTarget === col.field && dropSide === 'left'\n ? 0\n : 'auto',\n right:\n dropTarget === col.field && dropSide === 'right'\n ? 0\n : 'auto',\n width: '3px',\n backgroundColor:\n dropTarget === col.field\n ? theme.palette.primary.main\n : 'transparent',\n transition: 'background 0.1s ease',\n }\n : {},\n }}\n >\n {col.headerName}\n </Box>\n ),\n }))\n : columns;\n\n const orderedColumns = columnPinning\n ? [\n ...finalColumns\n .filter(c => pinned.includes(c.field))\n .map(col => ({ ...col, resizable: false })),\n ...finalColumns.filter(c => !pinned.includes(c.field)),\n ]\n : finalColumns;\n\n // Sticky offsets\n const pinnedOffsets: Record<string, number> = {};\n let leftOffset = 0;\n for (const col of orderedColumns) {\n if (pinned.includes(col.field)) {\n pinnedOffsets[col.field] = leftOffset;\n leftOffset += col.minWidth || col.width || 200;\n }\n }\n\n // Create pinned column styles\n const pinnedColumnStyles: Record<string, any> = {};\n if (columnPinning) {\n pinned.forEach(field => {\n pinnedColumnStyles[`& [data-field=\"${field}\"]`] = {\n position: 'sticky',\n left: pinnedOffsets[field],\n zIndex: 9999,\n backgroundColor: backgroundColor,\n boxShadow: '2px 0 2px rgba(0,0,0,0.05)',\n };\n });\n }\n\n return (\n <Box\n sx={{\n height,\n width: '100%',\n overflowX: 'auto',\n }}\n >\n {quickSearch && (\n <CustomSearchToolbar\n apiRef={apiRef}\n placeholder={searchBarPlaceHolder}\n customFilters={customFilters}\n />\n )}\n <DataGridMUI\n key={tableKey}\n apiRef={apiRef}\n rows={propRows}\n columns={orderedColumns}\n initialState={{\n ...initialState,\n }}\n columnVisibilityModel={columnVisibilityModel}\n onColumnVisibilityModelChange={setColumnVisibilityModel}\n disableVirtualization\n getRowId={getRowId}\n loading={loading}\n paginationModel={paginationModel}\n onPaginationModelChange={setPaginationModel}\n pageSizeOptions={pageSizeOptions}\n onRowClick={onRowClick ? params => onRowClick(params.row) : undefined}\n onRowSelectionModelChange={\n onSelectionChange\n ? selectionModel => {\n const selectedIds = selectionModel.ids\n ? Array.from(selectionModel.ids)\n : [];\n const selectedRows = propRows.filter(row =>\n selectedIds.some(\n id =>\n String(getRowId ? getRowId(row) : row.id) === String(id),\n ),\n );\n onSelectionChange(selectedRows);\n }\n : undefined\n }\n slots={{\n ...(columnMenu && { columnMenu: CustomColumnMenuWithProps }),\n ...(customPagination && { pagination: CustomPaginationComponent }),\n noResultsOverlay: () => <NotFound />,\n loadingOverlay: () => (\n <Box\n display=\"flex\"\n height=\"100%\"\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <LogoSpinner />\n </Box>\n ),\n }}\n slotProps={{\n loadingOverlay: {\n variant: 'linear-progress',\n noRowsVariant: 'skeleton',\n },\n columnsManagement: {\n disableResetButton: true,\n searchInputProps: {\n type: 'text',\n },\n },\n }}\n sx={{\n backgroundColor,\n '&.MuiDataGrid-root': {\n borderRadius,\n minWidth: 'auto',\n },\n '& .MuiDataGrid-columnHeader:focus, & .MuiDataGrid-columnHeader:focus-within':\n {\n outline: 'none',\n },\n '&.MuiDataGrid-root .MuiDataGrid-columnHeader, &.MuiDataGrid-root .MuiDataGrid-filler':\n {\n backgroundColor: headerBackgroundColor,\n },\n // Column resize line styling\n '& .MuiDataGrid-columnSeparator--resizable': {\n '&:hover': {\n color: theme.palette.primary.main,\n },\n },\n '& .MuiDataGrid-columnSeparator--resizing': {\n color: theme.palette.primary.main,\n opacity: 1,\n },\n ...pinnedColumnStyles,\n }}\n />\n </Box>\n );\n}\n"],"names":["orderedColumns","finalColumns","DataGridMUI"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataGrid.esm.js","sources":["../../../src/components/DataGrid/DataGrid.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useEffect, useState, useCallback } from 'react';\nimport {\n DataGrid as DataGridMUI,\n GridColDef,\n GridPaginationModel,\n useGridApiRef,\n GridValidRowModel,\n} from '@mui/x-data-grid';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport { CustomColumnMenu } from './CustomColumnMenu';\nimport { CustomPagination } from './CustomPagination';\nimport { CustomSearchToolbar } from './CustomSearchToolbar';\nimport { DataGridProps, GridLayout } from './types';\nimport { NotFound } from '../common';\nimport { LogoSpinner } from '../common/logoSpinner';\n\nexport function DataGrid<T extends GridValidRowModel>({\n // Required props\n tableKey,\n columns: propColumns,\n rows: propRows,\n\n // Optional configuration\n dataLabel = 'items',\n searchBarPlaceHolder = 'Search',\n features = {},\n styling = {},\n\n // Pagination\n initialPageSize = 20,\n pageSizeOptions = [20, 50, 100],\n\n // Event handlers\n onRowClick,\n onSelectionChange,\n\n // Custom components\n customFilters,\n columnVisibility,\n\n // Loading state\n loading,\n\n // custom Row ID\n getRowId,\n\n // Initial Table state\n initialState,\n}: DataGridProps<T>) {\n const theme = useTheme();\n const apiRef = useGridApiRef();\n\n // Default feature flags\n const {\n quickSearch = true,\n columnPinning = true,\n columnReordering = true,\n customPagination = true,\n columnMenu = true,\n persistLayout = true,\n } = features;\n\n // Default styling\n const {\n borderRadius = '12px',\n headerBackgroundColor = theme.palette.mode === 'dark'\n ? theme.palette.background.paper\n : theme.palette.grey[100],\n backgroundColor = theme.palette.background.paper,\n height = 'auto',\n } = styling;\n\n const [columns, setColumns] = useState<GridColDef<T>[]>(propColumns);\n const [pinned, setPinned] = useState<string[]>([]);\n const [dragCol, setDragCol] = useState<string | null>(null);\n const [dropTarget, setDropTarget] = useState<string | null>(null);\n const [dropSide, setDropSide] = useState<'left' | 'right' | null>(null);\n const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({\n page: 0,\n pageSize: initialPageSize,\n });\n\n const [columnVisibilityModel, setColumnVisibilityModel] = useState<\n Record<string, boolean>\n >(columnVisibility || {});\n\n // Load saved layout\n useEffect(() => {\n if (!persistLayout) return;\n\n try {\n const saved = localStorage.getItem(`apiiro-gridLayout-${tableKey}`);\n if (saved) {\n const {\n order,\n pinned: savedPinned,\n columnVisibility: savedVisibility,\n } = JSON.parse(saved) as GridLayout;\n setPinned(savedPinned || []);\n\n // Restore column visibility if saved\n if (savedVisibility) {\n setColumnVisibilityModel(savedVisibility);\n }\n\n const orderedColumns = order\n .map(field => propColumns.find(c => c.field === field))\n .filter((c): c is GridColDef<T> => !!c);\n setColumns(orderedColumns);\n }\n } catch (error) {\n // Failed to load grid layout - using default\n }\n }, [propColumns, persistLayout, tableKey]);\n\n const saveLayout = useCallback(\n (\n cols: GridColDef<T>[],\n pinnedCols: string[],\n visibility?: Record<string, boolean>,\n ) => {\n if (!persistLayout) return;\n\n const layout: GridLayout = {\n order: cols.map(c => c.field),\n pinned: pinnedCols,\n columnVisibility: visibility || columnVisibilityModel,\n };\n localStorage.setItem(\n `apiiro-gridLayout-${tableKey}`,\n JSON.stringify(layout),\n );\n },\n [persistLayout, tableKey, columnVisibilityModel],\n );\n\n // Save column visibility changes to gridLayout\n useEffect(() => {\n if (persistLayout) {\n saveLayout(columns, pinned, columnVisibilityModel);\n }\n }, [columnVisibilityModel, persistLayout, saveLayout, columns, pinned]);\n\n const handleDragStart = (field: string) => setDragCol(field);\n\n const handleDragOver = (\n e: React.DragEvent<HTMLDivElement>,\n targetField: string,\n ) => {\n e.preventDefault();\n if (dragCol === targetField) return;\n const targetRect = e.currentTarget.getBoundingClientRect();\n const x = e.clientX - targetRect.left;\n setDropTarget(targetField);\n setDropSide(x < targetRect.width / 2 ? 'left' : 'right');\n };\n\n const handleDragLeave = () => setDropTarget(null);\n\n const handleDrop = (targetField: string) => {\n if (!dragCol || dragCol === targetField) return;\n\n const dragIsPinned = pinned.includes(dragCol);\n const targetIsPinned = pinned.includes(targetField);\n\n if (dragIsPinned !== targetIsPinned) {\n setDragCol(null);\n setDropTarget(null);\n return;\n }\n\n const currentList = dragIsPinned\n ? columns.filter(c => pinned.includes(c.field))\n : columns.filter(c => !pinned.includes(c.field));\n\n const dragIndex = currentList.findIndex(c => c.field === dragCol);\n const targetIndex = currentList.findIndex(c => c.field === targetField);\n\n const newIndex = dropSide === 'left' ? targetIndex : targetIndex + 1;\n const reordered = [...currentList];\n const [moved] = reordered.splice(dragIndex, 1);\n reordered.splice(newIndex, 0, moved);\n\n const finalColumns = dragIsPinned\n ? [...reordered, ...columns.filter(c => !pinned.includes(c.field))]\n : [...columns.filter(c => pinned.includes(c.field)), ...reordered];\n\n setColumns(finalColumns);\n setDragCol(null);\n setDropTarget(null);\n saveLayout(finalColumns, pinned);\n };\n\n const togglePin = useCallback(\n (field: string) => {\n setPinned(prev => {\n const next = prev.includes(field)\n ? prev.filter(f => f !== field)\n : [...prev, field];\n saveLayout(columns, next);\n return next;\n });\n },\n [columns, saveLayout],\n );\n\n const CustomColumnMenuWithProps = useCallback(\n (props: any) => {\n return (\n <CustomColumnMenu\n {...props}\n isPinned={pinned.includes(props.colDef.field)}\n onTogglePin={togglePin}\n />\n );\n },\n [pinned, togglePin],\n );\n\n const CustomPaginationComponent = useCallback(\n () => (\n <CustomPagination\n onPageSizeChange={pageSize => setPaginationModel({ page: 0, pageSize })}\n pageSizeOptions={pageSizeOptions}\n dataLabel={dataLabel}\n />\n ),\n [dataLabel, pageSizeOptions],\n );\n\n const finalColumns = columnReordering\n ? columns.map(col => ({\n ...col,\n renderHeader: () => (\n <Box\n draggable={columnReordering}\n onDragStart={() => handleDragStart(col.field)}\n onDragOver={e => handleDragOver(e, col.field)}\n onDragLeave={handleDragLeave}\n onDrop={() => handleDrop(col.field)}\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n cursor: columnReordering ? 'grab' : 'default',\n userSelect: 'none',\n position: 'relative',\n fontWeight:\n columnPinning && pinned.includes(col.field) ? 'bold' : 'normal',\n px: 1,\n '&::before': columnReordering\n ? {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n bottom: 0,\n left:\n dropTarget === col.field && dropSide === 'left'\n ? 0\n : 'auto',\n right:\n dropTarget === col.field && dropSide === 'right'\n ? 0\n : 'auto',\n width: '3px',\n backgroundColor:\n dropTarget === col.field\n ? theme.palette.primary.main\n : 'transparent',\n transition: 'background 0.1s ease',\n }\n : {},\n }}\n >\n {col.headerName}\n </Box>\n ),\n }))\n : columns;\n\n const orderedColumns = columnPinning\n ? [\n ...finalColumns\n .filter(c => pinned.includes(c.field))\n .map(col => ({ ...col, resizable: false })),\n ...finalColumns.filter(c => !pinned.includes(c.field)),\n ]\n : finalColumns;\n\n // Sticky offsets\n const pinnedOffsets: Record<string, number> = {};\n let leftOffset = 0;\n for (const col of orderedColumns) {\n if (pinned.includes(col.field)) {\n pinnedOffsets[col.field] = leftOffset;\n leftOffset += col.minWidth || col.width || 200;\n }\n }\n\n // Create pinned column styles\n const pinnedColumnStyles: Record<string, any> = {};\n if (columnPinning) {\n pinned.forEach(field => {\n pinnedColumnStyles[`& [data-field=\"${field}\"]`] = {\n position: 'sticky',\n left: pinnedOffsets[field],\n zIndex: 9999,\n backgroundColor: backgroundColor,\n boxShadow: '2px 0 2px rgba(0,0,0,0.05)',\n };\n });\n }\n\n return (\n <Box\n sx={{\n height,\n width: '100%',\n overflowX: 'auto',\n }}\n >\n {quickSearch && (\n <CustomSearchToolbar\n apiRef={apiRef}\n placeholder={searchBarPlaceHolder}\n customFilters={customFilters}\n />\n )}\n <DataGridMUI\n key={tableKey}\n apiRef={apiRef}\n rows={propRows}\n columns={orderedColumns}\n initialState={{\n ...initialState,\n }}\n columnVisibilityModel={columnVisibilityModel}\n onColumnVisibilityModelChange={setColumnVisibilityModel}\n disableVirtualization\n getRowId={getRowId}\n loading={loading}\n paginationModel={paginationModel}\n onPaginationModelChange={setPaginationModel}\n pageSizeOptions={pageSizeOptions}\n onRowClick={onRowClick ? params => onRowClick(params.row) : undefined}\n onRowSelectionModelChange={\n onSelectionChange\n ? selectionModel => {\n const selectedIds = selectionModel.ids\n ? Array.from(selectionModel.ids)\n : [];\n const selectedRows = propRows.filter(row =>\n selectedIds.some(\n id =>\n String(getRowId ? getRowId(row) : row.id) === String(id),\n ),\n );\n onSelectionChange(selectedRows);\n }\n : undefined\n }\n slots={{\n ...(columnMenu && { columnMenu: CustomColumnMenuWithProps }),\n ...(customPagination && { pagination: CustomPaginationComponent }),\n noResultsOverlay: () => <NotFound />,\n loadingOverlay: () => (\n <Box\n display=\"flex\"\n height=\"100%\"\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <LogoSpinner />\n </Box>\n ),\n }}\n slotProps={{\n loadingOverlay: {\n variant: 'linear-progress',\n noRowsVariant: 'skeleton',\n },\n columnsManagement: {\n disableResetButton: true,\n searchInputProps: {\n type: 'text',\n },\n },\n }}\n sx={{\n backgroundColor,\n '&.MuiDataGrid-root': {\n borderRadius,\n minWidth: 'auto',\n },\n '& .MuiDataGrid-columnHeader:focus, & .MuiDataGrid-columnHeader:focus-within':\n {\n outline: 'none',\n },\n '&.MuiDataGrid-root .MuiDataGrid-columnHeader, &.MuiDataGrid-root .MuiDataGrid-filler':\n {\n backgroundColor: headerBackgroundColor,\n },\n // Column resize line styling\n '& .MuiDataGrid-columnSeparator--resizable': {\n '&:hover': {\n color: theme.palette.primary.main,\n },\n },\n '& .MuiDataGrid-columnSeparator--resizing': {\n color: theme.palette.primary.main,\n opacity: 1,\n },\n ...pinnedColumnStyles,\n }}\n />\n </Box>\n );\n}\n"],"names":["orderedColumns","finalColumns","DataGridMUI"],"mappings":"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"}
|