@spotify/backstage-plugin-soundcheck 0.9.0 → 0.10.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 +38 -4
- package/README.md +102 -0
- package/config.d.ts +0 -9
- package/dist/esm/EntitySoundcheckContent-fddf6ba7.esm.js +2 -0
- package/dist/esm/OverviewPageContent-8f5b5b64.esm.js +2 -0
- package/dist/esm/{RefetchingIndicator-3707a744.esm.js → RefetchingIndicator-fd4435c2.esm.js} +2 -2
- package/dist/esm/index-277bccda.esm.js +2 -0
- package/dist/esm/index-76a92dde.esm.js +2 -0
- package/dist/esm/index-88bfe2d5.esm.js +456 -0
- package/dist/esm/{index-01c3a9f5.esm.js → index-df582cac.esm.js} +2 -2
- package/dist/images/empty-state.svg +1 -0
- package/dist/images/no-results.svg +42 -0
- package/dist/images/pagerduty.svg +3 -0
- package/dist/index.esm.js +1 -1
- package/package.json +23 -17
- package/dist/esm/EntitySoundcheckContent-aecd6416.esm.js +0 -2
- package/dist/esm/OverviewPageContent-433c8dc6.esm.js +0 -2
- package/dist/esm/index-29e115b6.esm.js +0 -2
- package/dist/esm/index-6e141f2f.esm.js +0 -429
- package/dist/esm/index-a224cc6f.esm.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @spotify/backstage-plugin-soundcheck
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- We are thrilled to introduce Campaigns within Soundcheck. Soundcheck's Campaigns feature equips organizations to strategically target and manage specific short-term initiatives including built-in Slack notifications when the status of a campaign changes.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Added note to the `README` to mention adding the plugin to the `permissionedPlugins` list for RBAC integration
|
|
12
|
+
- Updated dependency `@graphql-codegen/typescript-react-apollo` to `^4.0.0`.
|
|
13
|
+
Updated dependency `@graphql-codegen/near-operation-file-preset` to `^3.0.0`.
|
|
14
|
+
Updated dependency `@graphql-codegen/typescript-graphql-files-modules` to `^3.0.0`.
|
|
15
|
+
Updated dependency `@graphql-codegen/typescript-graphql-request` to `^6.0.0`.
|
|
16
|
+
- Bug fix for switching to the card view on the Tech Health Checks tab.
|
|
17
|
+
- Checks created through the UI now properly support boolean values.
|
|
18
|
+
- Resolved an issue that could prevent filters from being applied to Github fact collections configured through the UI.
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @spotify/backstage-plugin-soundcheck-common@0.10.0
|
|
25
|
+
|
|
26
|
+
## 0.9.1
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Upgraded Backstage to `v1.20.3`.
|
|
31
|
+
- Updated dependency `cross-fetch` to `^4.0.0`.
|
|
32
|
+
- Added Track owner select to Track form.
|
|
33
|
+
- Checks are now linkable by id via the following url format `soundcheck/checks/:checkId`. Pages will now properly link to the check instead of the checks list page.
|
|
34
|
+
- Renamed Soundcheck menu options for Checks, Tracks, and Collectors to include "Library".
|
|
35
|
+
- Tracks are now linkable by id via the following url format `soundcheck/tracks/:trackId`. Pages will now properly link to the track instead of the tracks list page.
|
|
36
|
+
- Check descriptions, check passed messages, check failed messages, and track descriptions now support markdown in the UI.
|
|
37
|
+
- Updated dependencies
|
|
38
|
+
- @spotify/backstage-plugin-soundcheck-common@0.9.1
|
|
39
|
+
- @spotify/backstage-plugin-core@0.5.8
|
|
40
|
+
|
|
3
41
|
## 0.9.0
|
|
4
42
|
|
|
5
43
|
### Minor Changes
|
|
@@ -84,10 +122,6 @@
|
|
|
84
122
|
- Resolved an issue where newly added Checks would not immediately show up in the Track UI.
|
|
85
123
|
- Resolved an issue where the text for warning messages on the Soundcheck Group page was not accurate.
|
|
86
124
|
- Tooltips in the overview table now support Markdown in check descriptions.
|
|
87
|
-
- Updated dependencies
|
|
88
|
-
- Updated dependencies
|
|
89
|
-
- Updated dependencies
|
|
90
|
-
- Updated dependencies
|
|
91
125
|
- Updated dependencies
|
|
92
126
|
- @spotify/backstage-plugin-soundcheck-common@0.8.0
|
|
93
127
|
- @spotify/backstage-plugin-core@0.5.6
|
package/README.md
CHANGED
|
@@ -300,6 +300,8 @@ Soundcheck’s No-Code UI integrates with Backstage’s permission framework on
|
|
|
300
300
|
|
|
301
301
|

|
|
302
302
|
|
|
303
|
+
> Note: For the Soundcheck permissions to display as you see above sure you have added `soundcheck` to the list of `permissionedPlugins` in your `app-config.yaml`. For more details, [click here](https://www.npmjs.com/package/@spotify/backstage-plugin-rbac-backend#3-configure-permissioned-plugins).
|
|
304
|
+
|
|
303
305
|
Take a look at the [RBAC Integration](https://backstage.spotify.com/plugins/rbac/) for details and [RBAC Readme](https://www.npmjs.com/package/@spotify/backstage-plugin-rbac) for steps.
|
|
304
306
|
|
|
305
307
|
## Soundcheck Tech Health Page
|
|
@@ -326,6 +328,8 @@ The check result and certification data can be aggregated by:
|
|
|
326
328
|
tracks/levels, and entities based on the selections.
|
|
327
329
|
- `Teams`: Pass rates for teams, either organization-wide or filtered by specific checks,
|
|
328
330
|
tracks/levels, and entities based on the selections.
|
|
331
|
+
- `Campaigns`: Pass rates for campaigns, either organization-wide or filtered by specific checks,
|
|
332
|
+
tracks/levels, teams, and entities based on the selections.
|
|
329
333
|
|
|
330
334
|
### Filters
|
|
331
335
|
|
|
@@ -369,3 +373,101 @@ Check result history and certification history must be enabled in order to be ab
|
|
|
369
373
|
The aggregated data from each Tech Health Page tab can be exported into a Comma-Separated Values (CSV)
|
|
370
374
|
file format. The CSV format is widely supported and can be easily imported into various data analysis
|
|
371
375
|
tools, spreadsheets, and databases.
|
|
376
|
+
|
|
377
|
+
## Campaigns in Soundcheck
|
|
378
|
+
|
|
379
|
+
Soundcheck Campaigns provide a structured approach for organizations to drive focused initiatives, such as software updates or system transitions. They offer a way to create, manage, and monitor these initiatives within the Soundcheck framework.
|
|
380
|
+
|
|
381
|
+
### Key features include:
|
|
382
|
+
|
|
383
|
+
- **Initiation of Campaigns**: Users can create campaigns with specific goals, ownership, and timelines.
|
|
384
|
+
- **Focused Initiatives**: Campaigns enable targeting specific organizational objectives, like updating a software library.
|
|
385
|
+
- **Notification System**: Alerts are optionally sent out via Slack when there are changes in check statuses or certification levels, aiding prompt action.
|
|
386
|
+
- **Dashboard Tracking**: Progress of campaigns across different teams or the entire organization is visually trackable.
|
|
387
|
+
- **Archiving Feature**: Completed campaigns can be archived for historical reference.
|
|
388
|
+
|
|
389
|
+
Campaigns are designed to enhance awareness and actionability in focused initiatives, providing an additional capability within Soundcheck to manage initiatives that run for shorter periods. Some example use cases include:
|
|
390
|
+
|
|
391
|
+
**Examples include:**
|
|
392
|
+
|
|
393
|
+
- There is a need to Upgrade Spring Libraries to use a specific version of Spring Boot.
|
|
394
|
+
- When your organization wants to remove unneeded data endpoints to save cost.
|
|
395
|
+
|
|
396
|
+
### Campaigns Library
|
|
397
|
+
|
|
398
|
+
The Campaigns Library in Soundcheck serves as the central dashboard for all campaign-related activities. It is designed to provide users with a comprehensive overview of campaigns as well as control over various campaigns within the organization. Here, users can engage in several key activities:
|
|
399
|
+
|
|
400
|
+
- **Navigate to Individual Campaign Details**: Users can view detailed information about each campaign, including its objectives, current status, assigned teams or individuals, and progress metrics. This detailed view helps in monitoring and managing specific campaigns more effectively.
|
|
401
|
+
- **Create New Campaigns**: This function allows users to initiate new campaigns. Users can define the campaign's objectives, set timelines, assign owners, and specify other relevant parameters. The creation process is designed to be intuitive, guiding users through each step to ensure all necessary information is captured.
|
|
402
|
+
- **Edit Campaigns**: Campaign creators have the flexibility to modify the details of existing campaigns. This includes changing objectives, timelines, ownership, and other critical campaign parameters. This feature is crucial for adapting to changing conditions or requirements within a project or organization.
|
|
403
|
+
- **Delete Campaigns**: In cases where a campaign is no longer relevant or has been created by mistake, users can remove it from the system. This helps in maintaining a clean and up-to-date campaign dashboard.
|
|
404
|
+
- **Archive Completed Campaigns**: Once a campaign has reached its conclusion or its goals have been met, users can archive the campaign. This feature keeps the main dashboard focused on active campaigns, while still preserving the data of completed initiatives for future reference or analysis.
|
|
405
|
+
|
|
406
|
+

|
|
407
|
+
|
|
408
|
+
### Campaign Creation
|
|
409
|
+
|
|
410
|
+
Creating campaigns in Soundcheck is a feature accessible to all users,
|
|
411
|
+
allowing them to initiate new campaigns. This process is divided into four structured steps.
|
|
412
|
+
|
|
413
|
+
#### Step 1: Campaign Details
|
|
414
|
+
|
|
415
|
+
In this initial step, users establish the foundational elements of the campaign:
|
|
416
|
+
|
|
417
|
+
- **Campaign Name**: Assign a unique and descriptive name for easy identification.
|
|
418
|
+
- **Campaign Description**: Provide a detailed description of the campaign’s objectives and scope.
|
|
419
|
+
- **Campaign Owner**: Designate the individual or team responsible for overseeing the campaign.
|
|
420
|
+
- **Support Channel**: Optionally specify the Slack channel for campaign-related notifications.
|
|
421
|
+
- **Start and End Dates**: Set definitive start and end dates to establish a clear timeline for the campaign.
|
|
422
|
+
|
|
423
|
+
#### Step 2: Selecting Checks
|
|
424
|
+
|
|
425
|
+
This step involves choosing specific checks that the campaign will use to track progress against.
|
|
426
|
+
|
|
427
|
+
#### Step 3: Applying Filters
|
|
428
|
+
|
|
429
|
+
Filters are used to determine which entities the campaign targets.
|
|
430
|
+
|
|
431
|
+
#### Step 4: Defining Milestones
|
|
432
|
+
|
|
433
|
+
Milestones are set to track progress and achieve specific targets within the campaign.
|
|
434
|
+
Each milestone includes a name, description, and a defined pass rate, providing clear targets for
|
|
435
|
+
campaign progression.
|
|
436
|
+
|
|
437
|
+

|
|
438
|
+
|
|
439
|
+
### Campaign Archival
|
|
440
|
+
|
|
441
|
+
The Soundcheck Campaign Library which lists all active campaigns offers users tools for finalizing and
|
|
442
|
+
archiving campaigns, ensuring the completion of objectives is clearly documented.
|
|
443
|
+
Admins and authorized users can view archived campaigns, providing a historical perspective on past initiatives.
|
|
444
|
+
|
|
445
|
+
### Campaign Progress and Milestones
|
|
446
|
+
|
|
447
|
+
Milestones are an important part of campaigns, serving as tangible markers of progress and success.
|
|
448
|
+
Each milestone’s progress is monitored, with updates provided on completion rates and remaining tasks.
|
|
449
|
+
|
|
450
|
+
Campaign progress is monitored and displayed in various sections within Soundcheck:
|
|
451
|
+
|
|
452
|
+
- **Overview Tab**: A dedicated section in the Overview tab provides a snapshot of all ongoing campaigns.
|
|
453
|
+
- **Tech Health Page**: The Tech Health Page includes a tab for campaigns, showcasing detailed analytics and progress for each campaign. This helps in understanding the broader impact of campaigns on organizational tech health.
|
|
454
|
+
- **Entity-Specific Progress**: For each entity page in Soundcheck, there's a section that displays the campaign progress related to that particular entity.
|
|
455
|
+
- **Group-Specific Progress**: Similar to entity pages, each group page in Soundcheck includes a section that shows the campaign progress for the group.
|
|
456
|
+
|
|
457
|
+

|
|
458
|
+

|
|
459
|
+
|
|
460
|
+
### Campaign Notifications
|
|
461
|
+
|
|
462
|
+
The optional notification feature for campaigns is designed to keep users informed and responsive to changes and developments within their software environment. They act as a proactive communication tool, enhancing awareness and efficiency in managing software health and compliance.
|
|
463
|
+
|
|
464
|
+
For detailed documentation on getting notifications set up, refer to the [Slack Notifications section](../../plugins/soundcheck-backend/README.md#5-slack-notifications) of the Soundcheck Backend README.
|
|
465
|
+
|
|
466
|
+
#### Scenarios for Receiving Notifications
|
|
467
|
+
|
|
468
|
+
During campaign creation, the creator has the option to set up a Slack channel to be used for campaign notifications. If specified, campaign notifications will be sent to the provided channel.
|
|
469
|
+
|
|
470
|
+
- **Assigned Campaigns**: When a new campaign is created, the campaign specific channel will receive a notification to acknowledge and start addressing the goals of the campaign.
|
|
471
|
+
- **Campaign Updates**: Alerts are issued for any changes to a campaigns, including the checks associated with the campaign, the milestones of the campaign, or any related metadata.
|
|
472
|
+
|
|
473
|
+

|
package/config.d.ts
CHANGED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e,{useState as W,useEffect as O}from"react";import{Link as Q,useParams as $,Routes as j,Route as k,Navigate as I}from"react-router-dom";import{makeStyles as p,Typography as f,Box as G,Tab as T,Tabs as L,Paper as U,Divider as V}from"@material-ui/core";import{SpotifyLicenseBanner as Y}from"@spotify/backstage-plugin-core";import{useEntity as u}from"@backstage/plugin-catalog-react";import{R as q}from"./RefetchingIndicator-fd4435c2.esm.js";import{s as H,R as c,A as y,F as x,a as J,u as B,b as K,C as X,c as C,d as g,N as Z,e as _,f as ee,i as te,g as F,S as ae}from"./index-88bfe2d5.esm.js";import{Skeleton as s}from"@material-ui/lab";import{MarkdownContent as P}from"@backstage/core-components";import{stringifyEntityRef as ne}from"@backstage/catalog-model";import{useApi as re,useRouteRef as b,useRouteRefParams as ie}from"@backstage/core-plugin-api";import{useQuery as le}from"@tanstack/react-query";import oe from"react-use/lib/useMeasure";import A from"react-use/lib/usePrevious";import ce from"react-confetti";import"react-use/lib/useDebounce";import"graphql-request";import"graphql-tag";import"lodash";import"@material-ui/core/styles/makeStyles";import"classnames";import"@material-ui/icons/Schedule";import"luxon";import"@material-ui/icons/Check";import"@material-ui/icons/Close";import"@material-ui/icons/RemoveCircleOutline";import"@material-ui/icons/HelpOutline";import"../images/empty-state.svg";function se(t,n,a){const r=re(H),i=ne(t);return le(["soundcheck/check-details",i,n,a],async()=>r.getCheckResultDetails(i,n,a),{enabled:!!n&&!!a})}const me=p({markdownContent:{"& :last-child":{marginBottom:0}}}),de=({state:t,notes:n})=>{const a=me(),r={[c.Passed]:"success",[c.Failed]:"error",[c.NotReported]:"info",[c.NotApplicable]:"info"}[t],i={[c.Passed]:"Check passed",[c.Failed]:"Check did not pass",[c.NotReported]:"Check not reported",[c.NotApplicable]:"Check not applicable"}[t];return e.createElement(y,{severity:r,title:i},n?e.createElement(P,{className:a.markdownContent,content:n}):null)},pe=()=>{const t=D();return e.createElement(x,null,e.createElement("div",{className:t.root,"data-testid":"check-details-view"},e.createElement("div",{className:t.topBar},e.createElement(f,{variant:"h2",className:t.title},e.createElement(s,{width:300,height:32})),e.createElement(s,{width:100,height:32})),e.createElement(s,{variant:"rect",height:120}),e.createElement("div",{"data-testid":"soundcheck-check-details-description"},e.createElement(f,{variant:"h3"},e.createElement(s,null)),e.createElement(s,null),e.createElement(s,null),e.createElement(s,null))))},D=p(t=>({root:{padding:`${t.spacing(3)}px ${t.spacing(5)}px`},title:{fontWeight:"normal",fontSize:t.typography.h5.fontSize},description:{padding:`${t.spacing(3)}px 0`},subtitle:{fontWeight:"normal",fontSize:t.typography.h6.fontSize},topBar:{display:"flex",justifyContent:"space-between",marginBottom:t.spacing(2)}})),ue=({programId:t,checkId:n})=>{const a=D(),{entity:r}=u(),{data:i,isLoading:o,isError:l}=se(r,t,n);if(l)return e.createElement(G,{padding:2},e.createElement(y,{severity:"error",title:"Error loading check details"}));if(o||!t||!n)return e.createElement(pe,null);if(!i)return null;const{name:h,description:d,result:v,timestamp:m,notes:E}=i;return e.createElement("div",{className:a.root,"data-testid":"check-details-view"},e.createElement("div",{className:a.topBar},e.createElement(f,{variant:"h2",className:a.title},h),m?e.createElement(J,{timestamp:m,description:"Last updated"}):null),e.createElement(de,{state:v,notes:E}),e.createElement("div",{className:a.description,"data-testid":"soundcheck-check-details-description"},e.createElement(f,{variant:"h3",className:a.subtitle},"Description"),e.createElement(P,{content:d})))},he=p(()=>({root:{position:"absolute",width:"100%",height:"100%"}})),Ee=({programId:t})=>{var n,a;const r=he(),{entity:i}=u(),{data:o,isLoading:l}=B(i,t),[h,{width:d,height:v}]=oe(),m=l?void 0:(a=(n=o==null?void 0:o.highestLevel)==null?void 0:n.ordinal)!=null?a:-1,E=A(m),N=A(t),[M,S]=W(!1);return O(()=>{typeof E!="undefined"&&typeof m!="undefined"&&t===N&&m>E&&S(!0)},[m,E,t,N]),M?e.createElement("div",{ref:h,className:r.root},e.createElement(ce,{width:d,height:v,numberOfPieces:1e3,gravity:1,initialVelocityY:20,recycle:!1,onConfettiComplete:()=>S(!1)})):null},z=p(t=>({root:{maxWidth:"80ch",textTransform:"uppercase",paddingTop:t.spacing(2),paddingBottom:t.spacing(2)},wrapper:{display:"inline-block",textOverflow:"ellipsis",whiteSpace:"nowrap",overflow:"hidden"},badge:{marginRight:t.spacing(1)}})),fe=({id:t,name:n,badge:a,href:r,selected:i=!1})=>{const o=z(),{data:l}=K(t);return e.createElement(T,{className:o.root,classes:{wrapper:o.wrapper},value:t,label:e.createElement(e.Fragment,null,e.createElement(X,{badge:a,isCampaign:!(l!=null&&l.totalCount),className:o.badge}),n),component:Q,to:r,selected:i})},w=()=>{const t=z();return e.createElement(T,{className:t.root,classes:{wrapper:t.wrapper},label:e.createElement(s,{width:180})})},ge=()=>e.createElement(x,null,e.createElement(L,{value:!1,indicatorColor:"primary"},e.createElement(w,null),e.createElement(w,null),e.createElement(w,null)));function ve(t=[],n){const a=t.findIndex(r=>r.program.id===n);return a<0?!1:a}const ke=({trackId:t})=>{const{entity:n}=u(),{isLoading:a,data:r}=C(n),i=b(g);if(a||!t)return e.createElement(ge,null);const o=ve(r,t);return e.createElement(L,{value:o,indicatorColor:"primary","aria-label":"Certifications",variant:"scrollable"},r&&r.map(({program:{id:l,name:h},highestLevel:d})=>e.createElement(fe,{key:l,id:l,name:h,badge:d==null?void 0:d.badge,selected:l===t,href:i({trackId:l})})))},ye=p({paper:{overflow:"hidden",position:"relative"},view:{display:"grid",gridTemplateColumns:"1fr 2fr"}}),Ce=()=>{const{trackId:t,checkId:n}=$(),a=ye(),{entity:r}=u(),{isError:i,isFetched:o,data:l}=C(r);return i?e.createElement(y,{severity:"error",title:"Error loading certifications"}):o&&!(l!=null&&l.length)?e.createElement(Z,null):e.createElement(U,{className:a.paper},e.createElement(q,null),e.createElement(ke,{trackId:t}),e.createElement(V,null),e.createElement("div",{"data-testid":"soundcheck-certification-view",className:a.view},e.createElement(_,{trackId:t,checkId:n}),e.createElement(ue,{programId:t,checkId:n}),e.createElement(Ee,{programId:t})))},be=p(t=>({root:{"&:not(:first-child)":{marginTop:t.spacing(2)}}})),R=()=>{const t=be();return e.createElement(e.Fragment,null,e.createElement(Y,{backend:ee,invalidLicenseMessage:te,inline:!0}),e.createElement("div",{className:t.root},e.createElement(Ce,null)))},we=()=>{var t;const{entity:n}=u(),a=b(g),{data:r}=C(n),i=(t=r==null?void 0:r[0])==null?void 0:t.program.id;return i?e.createElement(I,{to:a({trackId:i}),replace:!0}):null},Re=()=>{var t,n;const{entity:a}=u(),{trackId:r}=ie(g),i=b(F),{data:o}=B(a,r),l=(n=(t=o==null?void 0:o.levels[0])==null?void 0:t.checks[0])==null?void 0:n.id;return l?e.createElement(I,{to:i({trackId:r,checkId:l}),replace:!0}):null},Ne=()=>e.createElement(j,null,e.createElement(k,{path:"/",element:e.createElement(e.Fragment,null,e.createElement(R,null),e.createElement(we,null))}),e.createElement(k,{path:g.path,element:e.createElement(e.Fragment,null,e.createElement(R,null),e.createElement(Re,null))}),e.createElement(k,{path:F.path,element:e.createElement(R,null)})),Se=()=>e.createElement(ae,null,e.createElement(Ne,null));export{Se as EntitySoundcheckContent};
|
|
2
|
+
//# sourceMappingURL=EntitySoundcheckContent-fddf6ba7.esm.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import t,{useState as F,useEffect as R,useMemo as A,useCallback as J,createContext as xe,useContext as $e,memo as x,Fragment as Te}from"react";import{useSearchParams as Ie,useNavigate as Le}from"react-router-dom";import{makeStyles as h,alpha as X,TextField as Be,CircularProgress as Pe,Tooltip as Y,LinearProgress as Oe,withStyles as Se,Grid as v,Typography as f,Button as Fe,Menu as Ae,MenuItem as q,Card as ze}from"@material-ui/core";import Ge from"@material-ui/lab/Autocomplete";import{stringifyEntityRef as W,parseEntityRef as $}from"@backstage/catalog-model";import{useApi as k,identityApiRef as Z,useRouteRef as T,configApiRef as Me}from"@backstage/core-plugin-api";import{useQuery as w}from"@tanstack/react-query";import{s as j,Q as D,R as I,j as He,B as We,L as ee,k as te,l as ae,A as je,N as De,m as Ve,n as Ke,o as Ue,p as Qe}from"./index-88bfe2d5.esm.js";import{catalogApiRef as z,humanizeEntityRef as G,entityRouteRef as V}from"@backstage/plugin-catalog-react";import _e from"react-use/lib/useAsync";import{HeaderTabs as ne,MarkdownContent as Je,Link as M,EmptyState as Xe,LinearGauge as Ye}from"@backstage/core-components";import{R as qe}from"./RefetchingIndicator-fd4435c2.esm.js";import Ze,{countBy as re}from"lodash";import{Skeleton as K}from"@material-ui/lab";import{VariableSizeGrid as et}from"react-window";import{DateTime as le}from"luxon";import tt from"@material-ui/icons/ArrowDropUp";import at from"@material-ui/icons/ArrowDropDown";import{motion as oe}from"framer-motion";function ie(e,a){const n=k(j);return w(["soundcheck/track-overview-for-owner",e,a],async()=>n.getProgramOverviewForOwner(e,a),{enabled:!!e&&!!(a!=null&&a.kind)})}function se(){const e=k(z);return w(["soundcheck/all-groups"],async()=>{const{items:a}=await e.getEntities({filter:{kind:"Group"},fields:["spec.profile.displayName","metadata.title","metadata.name","metadata.namespace","kind"]});return a.filter(n=>(n==null?void 0:n.kind)==="Group").map(n=>{var r,l,i,o;return{name:(o=(i=(l=(r=n.spec)==null?void 0:r.profile)==null?void 0:l.displayName)!=null?i:n.metadata.title)!=null?o:n.metadata.name,ref:W(n)}})},{staleTime:5*60*1e3,refetchInterval:!1,refetchOnWindowFocus:!1})}function nt(){const e=k(Z),a=k(z);return w(["soundcheck/user-groups-claims"],async()=>{const{ownershipEntityRefs:n}=await e.getBackstageIdentity();return(await a.getEntitiesByRefs({entityRefs:n})).items.filter(r=>(r==null?void 0:r.kind)==="Group").map(r=>{var l,i,o,d;return{name:(d=(o=(i=(l=r.spec)==null?void 0:l.profile)==null?void 0:i.displayName)!=null?o:r.metadata.title)!=null?d:r.metadata.name,ref:W(r)}})})}function ce(e){const a=k(j);return w([D.GetCampaigns,JSON.stringify(e)],async()=>a.getCampaigns(e),{staleTime:5*60*1e3,refetchInterval:!1,refetchOnWindowFocus:!1})}function rt(e){const a=k(j);return w(["soundcheck/facets-for-owner",e],async()=>a.getFacetsForOwner(e),{enabled:!!e})}const lt=()=>{const[e,a]=Ie(),n=Object.fromEntries(e.entries()),[r,l]=F(n);return R(()=>{a(r,{replace:!0})},[r]),[r,l]},de=e=>{const a=k(j);return w([D.GetIndividualEntityPassRate,e],async()=>a.getIndividualEntityPassRates(e),{staleTime:5*60*1e3,refetchInterval:!1,refetchOnWindowFocus:!1})},me=()=>{const{data:e,isLoading:a,isError:n}=nt(),{data:r,isLoading:l,isError:i}=se();return{options:A(()=>{const o=new Map;return e&&e.forEach(({name:d,ref:s})=>{o.set(`${s}`,{name:d,ref:s,key:"My Groups"})}),r&&r.forEach(({name:d,ref:s})=>{o.has(`${s}`)||o.set(`${s}`,{name:d,ref:s,key:"All Groups"})}),[...o.values()]},[e,r]),isLoading:a||l,isError:n||i}},ot=h(e=>({root:{width:"100%",minWidth:250},textField:{"& $notchedOutline":{borderColor:X(e.page.fontColor,.25)},"&:hover $notchedOutline":{borderColor:e.page.fontColor}},input:{backgroundColor:"transparent",color:e.page.fontColor},clearIndicator:{color:e.page.fontColor},popupIndicator:{color:e.page.fontColor},notchedOutline:{}})),it=e=>{const{onChange:a,initialValue:n,setError:r}=e,{options:l,isLoading:i,isError:o}=me(),d=ot(),[s,c]=F(null);R(()=>{if(!i&&l!=null&&l.length&&!s){const p=n?l.find(m=>m.ref===n):l[0];p&&(c(p),a==null||a(p.ref))}},[i,l,s,a,n]);const u=J((p,m)=>{c(m),a==null||a(m==null?void 0:m.ref)},[a,c]);return R(()=>{r==null||r(o?new Error("Error loading groups"):void 0)},[o,r]),o?null:t.createElement(Ge,{"aria-label":"Current group",className:d.root,classes:{clearIndicator:d.clearIndicator,popupIndicator:d.popupIndicator},disableClearable:!0,options:l!=null?l:[],loading:i,groupBy:p=>p.key,value:s,freeSolo:!1,onChange:u,getOptionLabel:p=>p.name,renderInput:p=>t.createElement(Be,{...p,variant:"outlined",placeholder:i?"Loading":"Select a group",className:d.textField,InputProps:{...p.InputProps,className:d.input,classes:{notchedOutline:d.notchedOutline},endAdornment:t.createElement(t.Fragment,null,i?t.createElement(Pe,{color:"inherit",size:20}):null,p.InputProps.endAdornment)}})})},pe={loading:!1},ue=xe(pe),st=()=>$e(ue),ct=({children:e})=>{const[a,n]=F(pe),r=k(z),l=k(Z),{value:i,loading:o,error:d}=_e(async()=>{const[{token:s},c]=await Promise.all([l.getCredentials(),l.getBackstageIdentity()]);return s?await r.getEntityByRef(c.userEntityRef):null},[r,l]);return R(()=>{if(i){const s=W(i);n({user:i,userEntityRef:s,loading:o,error:d})}else n({loading:o,error:d})},[i,o,d]),t.createElement(ue.Provider,{value:a},e)},dt=e=>({key:`skeleton${e}`,label:"",id:`skeleton${e}`}),mt=()=>{const e=Array.from({length:4},(a,n)=>dt(n));return t.createElement(ne,{tabs:e})},pt=h(e=>({root:{borderTop:`1px solid ${e.palette.divider}`,borderBottom:`1px solid ${e.palette.divider}`},tab:{textTransform:"uppercase",paddingTop:e.spacing(2),paddingBottom:e.spacing(2)}})),ut=({unfilteredFacets:e,onChange:a,kind:n,type:r})=>{var l,i,o;const d=pt(),s={types:(l=e==null?void 0:e.types.filter(({count:m})=>m>0))!=null?l:[]},c=J(m=>{var g;a((g=s==null?void 0:s.types[m].kind)!=null?g:"",s==null?void 0:s.types[m].type)},[s==null?void 0:s.types,a]);R(()=>{var m,g,E;const y=(s==null?void 0:s.types)&&s.types.length>=0,b=!n&&y,B=n&&y&&!(s!=null&&s.types.find(({kind:P,type:N})=>n===P&&(!r&&!N||r===N)));(b||B)&&a((g=(m=s==null?void 0:s.types[0])==null?void 0:m.kind)!=null?g:"",(E=s==null?void 0:s.types[0])==null?void 0:E.type)},[n,r,s==null?void 0:s.types,a]);const u=(i=s==null?void 0:s.types.map(({kind:m,type:g,count:E})=>{const y=`${m}|${g!=null?g:""}`;return{key:y,label:`${g!=null?g:m} (${E>50?"50+":E})`,id:y,tabProps:{className:d.tab}}}))!=null?i:[];if(!u.length)return null;const p=(o=s==null?void 0:s.types.findIndex(m=>m.kind===n&&(!m.type&&!r||m.type===r)))!=null?o:-1;return t.createElement(t.Fragment,null,t.createElement(qe,null),t.createElement(ne,{onChange:c,tabs:u,selectedIndex:p>-1?p:void 0}))},gt=h(e=>({root:{height:"8px",minWidth:"64px",marginLeft:e.spacing(2),borderRadius:"100vh",backgroundColor:e.palette.background.default},bar:{backgroundColor:e.palette.success.main,transition:"none"}})),ge=e=>{var a,n;const r=gt(e),l=A(()=>Object.entries(e.progress).reduce((o,[,d])=>o+d,0),[e.progress]);if(l===0)return null;const i=(a=e.progress[I.Passed])!=null?a:0;return t.createElement(Y,{arrow:!0,title:`Check passing for ${i} of ${l} ${l===1?"entity":"entities"}`,enterDelay:0,placement:"top"},t.createElement(Oe,{variant:"determinate",value:((n=e.progress[I.Passed])!=null?n:0)/l*100,classes:{root:r.root,bar:r.bar}}))},ft=h(e=>({headerWrapper:{marginTop:e.spacing(.5)},entityRefName:{fontWeight:"bold"},iconWrapper:{padding:e.spacing(1.5,.5),display:"flex",alignItems:"center",justifyContent:"center"}})),yt=({check:{name:e,description:a},icon:n,entityRef:r})=>{const l=ft(),i=$(r);return t.createElement(v,{spacing:1},t.createElement(v,{container:!0,direction:"row",spacing:1,wrap:"nowrap"},t.createElement("div",{className:l.iconWrapper},n),t.createElement(f,{variant:"h6",className:l.headerWrapper,noWrap:!0},e)),t.createElement(v,{item:!0,wrap:"nowrap"},t.createElement(f,{variant:"subtitle2",className:l.entityRefName},G(i,{defaultKind:i.kind}))),t.createElement(Je,{content:a}))},ht=Se(e=>{const a=e.palette.type==="dark"?e.palette.common.black:e.palette.grey[300];return{tooltip:{backgroundColor:a,color:e.palette.type==="dark"?e.palette.common.white:e.palette.grey[700]},arrow:{color:a}}})(Y),Et=({children:e,check:a,icon:n,entityRef:r})=>t.createElement(ht,{arrow:!0,title:t.createElement(yt,{check:a,icon:n,entityRef:r}),enterDelay:150,placement:"top"},e),vt=h(e=>({root:{padding:0},iconWrapper:{padding:e.spacing(1.5),display:"flex",alignItems:"center",justifyContent:"center"},link:{"&:hover $iconWrapper, &:active $iconWrapper, &:focus $iconWrapper":{backgroundColor:e.palette.infoBackground}},icon:{width:"17px",height:"17px"},virtualized:{borderBottom:`1px solid ${e.palette.divider}`,borderRight:`1px solid ${e.palette.divider}`}})),fe=x(({programId:e,check:a,entityRef:n,result:r,entityRoute:l,isVirtualized:i})=>{const o=vt();if(typeof n!="string"){const u=t.createElement("div",{className:o.iconWrapper},t.createElement("div",{className:o.icon}));return i?t.createElement("div",{className:`${o.root} ${o.virtualized}`,"aria-hidden":!0},u):t.createElement("td",{className:o.root,"aria-hidden":!0},u)}const d=t.createElement(He,{className:o.icon,result:r!=null?r:I.NotReported}),s=t.createElement("div",{className:o.iconWrapper},d),c=r&&r===I.NotApplicable?s:t.createElement(M,{className:o.link,to:`${l($(n))}/soundcheck/${e}/${a.id}`},s);return i?t.createElement("div",{className:`${o.root} ${o.virtualized}`},t.createElement(Et,{check:a,icon:d,entityRef:n},c)):t.createElement("td",{className:`${o.root}`},c)}),ye=8,kt=16,L={programTitle:70,levelTitle:30,check:42,entityRefFooter:100},U={programTitle:350+kt*2,checkResult:42},bt=e=>e.reduce((a,n)=>a+n.height,0),Ct=e=>e*U.checkResult+U.programTitle,Nt=e=>e.filter(a=>a!==void 0).map(a=>{const n=$(a);return G(n,{defaultKind:n.kind})}).reduce((a,n)=>a.length>n.length?a:n,""),Rt=e=>ye*e+ye,he="NoLevel",wt=e=>({name:he,badge:{options:{level:0,color:""},variant:We.Medal},entityRef:e,ordinal:0}),Ee=h(e=>({checkNameCell:{padding:0,backgroundColor:e.palette.background.paper},checkNameContent:{padding:`0 ${e.spacing(2)}px`,display:"flex",justifyContent:"space-between",alignItems:"center"},checkNameTypography:{overflow:"hidden",textOverflow:"ellipsis"},checkIndicator:{flexBasis:e.spacing(8)},checkNameCellVirtualized:{height:`${L.check}px`,lineHeight:`${L.check}px`,borderBottom:`1px solid ${e.palette.divider}`,borderRight:`1px solid ${e.palette.divider}`}})),xt=x(({programId:e,programName:a,check:n,entityRefs:r,results:l,entityRoute:i})=>{const o=Ee(),d=A(()=>re(l.filter(({result:c})=>c!==I.NotApplicable),"result"),[l]),s=new Map(l.map(c=>[c.entityRef,c.result]));return t.createElement("tr",{"data-testid":"track-check-row"},t.createElement("th",{scope:"row",className:o.checkNameCell,"aria-label":`${n.name} check for ${a} track`},t.createElement("div",{className:o.checkNameContent},t.createElement(f,{className:o.checkNameTypography,variant:"subtitle2",component:"p"},n.name),t.createElement(ge,{className:o.checkIndicator,progress:d}))),r.map((c,u)=>t.createElement(fe,{key:u,programId:e,check:n,entityRef:c,result:typeof c=="string"?s.get(c):void 0,entityRoute:i})))}),$t=({name:e,progress:a})=>{const n=Ee();return t.createElement("div",{className:n.checkNameCell,"aria-label":`${e} check`},t.createElement("div",{className:`${n.checkNameContent} ${n.checkNameCellVirtualized}`},t.createElement(f,{variant:"subtitle2",component:"p",className:n.checkNameTypography},e),t.createElement(ge,{className:n.checkIndicator,progress:a})))},Tt=h(e=>({virtualized:{borderRight:`1px solid ${e.palette.divider}`,height:`${L.programTitle}px`,display:"flex",justifyContent:"center",alignItems:"center"}})),It=x(({entityRef:e,highestLevels:a,trackType:n})=>{const r=a.find(i=>i.entityRef===e);let l=r!=null&&r.badge?t.createElement(ee,{badge:r.badge}):t.createElement(te,null);return n==="campaign"&&(l=t.createElement(ae,null)),l}),Lt=({highestLevel:e,trackType:a})=>{const n=Tt();if(!(e!=null&&e.badge))return t.createElement("div",{className:n.virtualized},"\xA0");let r=e.name!==he?t.createElement(ee,{badge:e.badge}):t.createElement(te,null);return a==="campaign"&&(r=t.createElement(ae,null)),t.createElement("div",{className:n.virtualized},r)},ve=h(e=>({programNameCell:{padding:0,position:"sticky",backgroundColor:e.palette.background.paper},programNameContent:{padding:e.spacing(2)},programNameTypography:{overflow:"hidden",textOverflow:"ellipsis"},badgeCellContent:{display:"flex",justifyContent:"center",alignItems:"center"},programNameCellVirtualized:{borderRight:`1px solid ${e.palette.divider}`}})),Bt=x(({program:e,entityRefs:a,highestLevels:n})=>{const r=ve();return t.createElement("tr",{"data-testid":"track-title-row"},t.createElement("th",{scope:"row",className:r.programNameCell},t.createElement("div",{className:r.programNameContent},t.createElement(f,{className:r.programNameTypography,variant:"h5",component:"p"},e.name))),a.map((l,i)=>{var o;return typeof l!="string"?t.createElement("td",{key:i,"aria-hidden":!0}):t.createElement("td",{key:i,"data-testid":"track-certification-cell"},t.createElement("div",{className:r.badgeCellContent},t.createElement(It,{entityRef:l,highestLevels:n,trackType:(o=e.type)!=null?o:void 0})))}))}),Pt=x(({name:e})=>{const a=ve();return t.createElement("div",{className:`${a.programNameCell} ${a.programNameCellVirtualized}`},t.createElement("div",{className:a.programNameContent},t.createElement(f,{className:a.programNameTypography,variant:"h5",component:"p"},e)))}),_=h(e=>{const a=e.palette.type==="dark"?e.palette.grey[700]:e.palette.grey[100];return{root:{color:X(e.palette.getContrastText(a),.8),backgroundColor:a},levelContent:{padding:`${e.spacing(.5)}px ${e.spacing(2)}px`,backgroundColor:a},levelTypography:{overflow:"hidden",textOverflow:"ellipsis"},levelHeaderCell:{padding:`${e.spacing(.5)}px ${e.spacing(2)}px`,borderRight:`1px solid ${e.palette.divider}`,height:`${L.levelTitle}px`}}}),Ot=x(({level:e,entityRefs:a,programName:n})=>{const r=_();return t.createElement("tr",{className:r.root,"data-testid":"track-level-row"},t.createElement("th",{scope:"row",className:r.root},t.createElement("div",{className:r.levelContent},t.createElement(f,{className:r.levelTypography,variant:"subtitle2",component:"p","aria-label":`${e.name} for ${n} track`},e.name))),a.map((l,i)=>t.createElement("td",{key:i,className:r.root,"aria-hidden":!0})))}),St=({name:e})=>{const a=_();return t.createElement("div",{className:`${a.levelHeaderCell} ${a.root}`,"aria-label":`${e}`},t.createElement(f,{variant:"subtitle2",component:"p",className:a.levelTypography},e))},Ft=()=>{const e=_();return t.createElement("div",{className:`${e.levelHeaderCell} ${e.root}`},"\xA0")},At=({program:e,highestLevels:a,levels:n,entityRefs:r,entityRoute:l})=>t.createElement("tbody",null,t.createElement(Bt,{program:e,entityRefs:r,highestLevels:a}),n.map((i,o)=>t.createElement(Te,{key:o},t.createElement(Ot,{entityRefs:r,level:i,programName:e.name}),i.checks.map(({check:d,results:s},c)=>t.createElement(xt,{key:c,check:d,programId:e.id,programName:e.name,entityRefs:r,results:s,entityRoute:l}))))),ke=e=>{const a=k(z);return w([D.EntityByRef,e],async()=>a.getEntityByRef(e),{onError:()=>{},enabled:!!e})},zt=e=>{const a=k(z);return w([D.EntitiesByRefs,e],async()=>a.getEntitiesByRefs({entityRefs:e.entityRefs,fields:e.fields}),{onError:()=>{},enabled:!!e.entityRefs})},be=h(e=>({root:{position:"sticky",bottom:"-1px",backgroundColor:e.palette.background.default,boxShadow:`0 -1px ${e.palette.divider}`,"& td$cell, & th$cell":{border:0,padding:e.spacing(1)},"& td$cell":{backgroundColor:e.palette.background.default}},row:{boxShadow:`1px 0 ${e.palette.background.default}, -1px 0 ${e.palette.background.default}`},cell:{verticalAlign:"top"},cellInner:{textOrientation:"mixed",writingMode:"vertical-lr",transform:"rotate(-20deg)",transformOrigin:`100% ${e.spacing(1)}px`,wordBreak:"keep-all",fontWeight:"bold",overflow:"hidden",textOverflow:"ellipsis",maxHeight:"max(15vh, 175px)"}})),Gt=({entityRefs:e})=>{const a=T(V),n=be(),{data:r}=zt({entityRefs:Ze.compact(e),fields:["kind","metadata.name","metadata.namespace","metadata.title"]});return t.createElement("tfoot",{className:n.root,"data-testid":"results-table-footer"},t.createElement("tr",{className:n.row},t.createElement("td",{className:n.cell}),e.map((l,i)=>{if(typeof l!="string")return t.createElement("th",{key:i,className:n.cell,"aria-hidden":!0});const o=$(l),d=r==null?void 0:r.items.find(s=>s&&W(s)===l);return t.createElement("th",{scope:"col",key:i,className:n.cell},t.createElement("div",{className:n.cellInner},t.createElement(M,{to:a(o)},d!=null&&d.metadata.title?d.metadata.title:G(o,{defaultKind:o.kind}))))})))},Mt=({entityRef:e})=>{const{data:a}=ke(e),n=T(V),r=be(),l=e?$(e):void 0,i=l?t.createElement(M,{to:n(l)},a!=null&&a.metadata.title?a.metadata.title:G(l,{defaultKind:l.kind})):t.createElement(t.Fragment,null);return t.createElement("div",{className:r.cell},t.createElement("div",{className:r.cellInner},i))},Ht=h(e=>({table:{backgroundColor:e.palette.background.paper,borderCollapse:"collapse",whiteSpace:"nowrap","& th, & td":{border:`1px solid ${e.palette.divider}`,borderCollapse:"collapse"},paddingBottom:e.spacing(2)},programTitle:{padding:e.spacing(2)},checkResult:{padding:e.spacing(1.5)},title:{padding:`${e.spacing(1)}px ${e.spacing(2)}px`},header:{backgroundColor:e.palette.type==="dark"?e.palette.grey[700]:e.palette.grey[100]}})),Ce=()=>{const e=Ht(),a=new Array(25).fill(void 0),n=new Array(5).fill(void 0),r=new Array(3).fill(void 0);return t.createElement("table",{className:e.table},t.createElement("tbody",null,t.createElement("tr",null,t.createElement("td",{className:e.programTitle},t.createElement(K,{width:180,height:40})),a.map((l,i)=>t.createElement("td",{key:i}))),r.map((l,i)=>t.createElement(t.Fragment,{key:i},t.createElement("tr",{className:e.header},t.createElement("td",{className:e.title},t.createElement(K,{width:180})),a.map((o,d)=>t.createElement("td",{key:d}))),n.map((o,d)=>t.createElement("tr",{key:d},t.createElement("td",{className:e.title},t.createElement(K,{width:240})),a.map((s,c)=>t.createElement("td",{key:c,className:e.checkResult},t.createElement(K,{width:18,height:18,variant:"rect"})))))))))},Wt=h(e=>({root:{width:"100%"},table:{overflow:"auto",backgroundColor:e.palette.background.paper,borderCollapse:"collapse",whiteSpace:"nowrap",textAlign:"left","& th, & td":{border:`1px solid ${e.palette.divider}`,borderCollapse:"collapse"},"& th:first-of-type":{position:"sticky",left:0,zIndex:1,maxWidth:"60ch"},"& tfoot":{bottom:0,zIndex:1e3},"& tbody td:first-of-type":{border:`1px solid ${e.palette.divider}`,boxShadow:`1px 0 ${e.palette.background.default}, -1px 0 ${e.palette.background.default}`}}})),jt=x(e=>{const{setError:a,kind:n,type:r,ownerEntityRef:l}=e,i=Wt(),o=T(V),{data:d,isLoading:s,isError:c}=ie(l,{kind:n,type:r});if(R(()=>{a==null||a(c?new Error("Error loading track overview"):void 0)},[c,a]),s)return t.createElement(Ce,null);if(!d||!l)return null;const{programs:u,entityRefs:p}=d;if(!s&&!u.length)return t.createElement(Xe,{missing:"data",title:"Missing tracks",description:t.createElement(t.Fragment,null,"Looks like the group"," ",G($(l),{defaultKind:"Group"})," ","doesn't own any ",r!=null?r:n," components that have Soundcheck tracks set up.",t.createElement("br",null),t.createElement("br",null),"If you're an administrator, you can learn more about configuring and filtering tracks in the"," ",t.createElement(M,{to:"https://www.npmjs.com/package/@spotify/backstage-plugin-soundcheck-backend#entity-filter"},"docs"),".")});if(c)return null;const m=p.length>=25?p:[...p,...Array.from({length:25-p.length},()=>{})];return t.createElement("div",{className:i.root},t.createElement("table",{className:i.table,"aria-label":"Check results"},u.map(({program:g,levels:E,highestLevels:y},b)=>t.createElement(At,{key:b,program:g,entityRefs:m,levels:E,highestLevels:y,entityRoute:o})),t.createElement(Gt,{entityRefs:m})))}),Dt=e=>t.createElement(Pt,{name:e}),Vt=e=>({type:"ProgramHeader",render:()=>Dt(e)}),Kt=e=>e?t.createElement(St,{name:e}):t.createElement(Ft,null),Ne=e=>({type:"LevelHeader",render:()=>Kt(e)}),Ut=(e,a)=>t.createElement($t,{name:e,progress:a}),Qt=(e,a)=>({type:"CheckTitle",render:()=>Ut(e,a)}),_t=(e,a,n,r,l)=>t.createElement(fe,{check:a,entityRef:n,entityRoute:l,programId:e,result:r,isVirtualized:!0}),Jt=(e,a,n,r,l)=>({type:"CheckResult",render:()=>_t(e,a,n,r,l)}),Xt=e=>t.createElement(Mt,{entityRef:e}),Re=e=>({type:"EntityHeader",render:()=>Xt(e)}),Yt=(e,a)=>t.createElement(Lt,{highestLevel:e,trackType:a}),qt=(e,a)=>({type:"LevelBadge",render:()=>Yt(e,a)}),Zt=e=>a=>{const n=e[a.rowIndex].cells[a.columnIndex];return n?t.createElement("div",{style:a.style},n.render()):t.createElement("div",{style:a.style})},ea=(e,a,n)=>{var r;const l=[];for(const{program:o,levels:d,highestLevels:s}of e){l.push({height:L.programTitle,cells:[Vt(o.name),...a.map(c=>{var u;const p=c?s.find(m=>m.entityRef===c)||wt(c):void 0;return qt(p,(u=o.type)!=null?u:void 0)})]});for(const c of d){l.push({height:L.levelTitle,cells:[Ne(c.name),...a.map(u=>Ne(""))]});for(const{check:u,results:p}of c.checks)l.push({height:L.check,cells:[Qt(u.name,re(p.filter(({result:m})=>m!==I.NotApplicable),"result")),...a.map(m=>{var g,E;return Jt(o.id,u,m,(E=(g=p.find(y=>y.entityRef===m))==null?void 0:g.result)!=null?E:I.NotApplicable,n)})]})}}const i=Nt(a!=null?a:[]);return l.push({height:Rt((r=i.length)!=null?r:1),cells:[Re(""),...a.map(o=>Re(o||""))]}),l},ta=h(e=>({table:{backgroundColor:e.palette.background.paper,borderCollapse:"collapse",whiteSpace:"nowrap",textAlign:"left",overflow:"auto"}})),aa=e=>{const{setError:a,kind:n,type:r,ownerEntityRef:l}=e,i=ta(),o=T(V),{data:d,isLoading:s,isError:c}=ie(l,{kind:n,type:r});if(R(()=>{a==null||a(c?new Error("Error loading program overview"):void 0)},[c,a]),s)return t.createElement(Ce,null);if(!d||!l)return null;const{programs:u,entityRefs:p}=d,m=p.length>=25?p:[...p,...Array.from({length:25-p.length},()=>{})],g=ea(u,m,o),E=Zt(g);return t.createElement(v,{"aria-label":`Check results for ${r!=null?r:n}`,key:`${n}|${r!=null?r:""}`,item:!0,xs:12},t.createElement(et,{className:i.table,columnCount:m.length+1,columnWidth:y=>y===0?U.programTitle:U.checkResult,rowCount:g.length,rowHeight:y=>g[y].height,height:bt(g),width:Ct(m.length)},E))},na=({facets:e,ownerEntityRef:a,kind:n,type:r,setError:l})=>{const i=A(()=>{const o=new Map;return e.types.forEach(({kind:d,type:s})=>{const c=`${d}|${s!=null?s:""}`;o.set(c,t.createElement(aa,{key:c,ownerEntityRef:a,kind:d,type:s,setError:l}))}),o},[e,a,l]);return t.createElement("div",null,i.get(`${n}|${r!=null?r:""}`))},ra=h(()=>({scrollContainer:{overflow:"auto"}})),la=({facets:e,ownerEntityRef:a,hasError:n,kind:r,type:l,setError:i,useVirtualizedResultsTable:o,isFixedGroup:d})=>{var s,c,u;const p=ra();if(n)return t.createElement(je,{severity:"error",title:n.message});const m="Use the groups drop-down list at the top-right of the page to select another group.";return e&&((c=(s=e.types)==null?void 0:s.length)!=null?c:0)>0?(u=e.types)!=null&&u.find(g=>g.count>0)?t.createElement("div",{className:p.scrollContainer},o?t.createElement(na,{facets:e,kind:r,type:l,setError:i,ownerEntityRef:a,hasError:n}):t.createElement(jt,{ownerEntityRef:a,kind:r,type:l,setError:i})):t.createElement(De,{ownerEntityRef:a,selectGroupHint:m}):t.createElement(Ve,{ownerEntityRef:a,selectGroupHint:d?void 0:m})};function oa({angle:e,arc:a,direction:n,dist:r,emoji:l,delay:i,fontSize:o,speed:d}){return t.createElement(oe.div,{style:{position:"absolute",fontSize:o},initial:{top:0,left:"50%",x:"-50%",y:"-100%",rotate:0,originX:`${a*n}px`,originY:`${a}px`},animate:{opacity:[0,1,0,0,0,0],y:`${-r}px`,rotate:e*n},transition:{delay:i,duration:d,ease:[.2,.83,.46,.63],repeat:1/0}},l)}const ia=["\u{1F4C8}","\u{1F4CA}","\u{1F4C9}","\u{1F680}","\u2B50\uFE0F"],sa=h(()=>({container:{position:"relative"}}));function ca({angle:e=125,density:a=20,emojis:n=ia,fontSizeMin:r=6,fontSizeMax:l=24,size:i=300,speed:o=4}){const d=sa(),s=A(()=>Array.from({length:a*n.length}).map((c,u)=>({emoji:n[Math.floor(Math.random()*n.length)],arc:Math.random()*i*.5,delay:Math.random()*o,dist:Math.random()*i,direction:u%2?1:-1,fontSize:Math.random()*(l-r)+r,angle:e,speed:o})),[a,n,o,i,e,l,r]);return t.createElement("div",{className:d.container},t.createElement(f,{variant:"h1"},"\u{1F469}\u200D\u{1F4BB}"),s.map((c,u)=>t.createElement(oa,{key:`${c.emoji}-${u}`,...c})))}const da=h(()=>({container:{position:"relative",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",flex:1,height:"100%"},textContainer:{position:"relative",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"}}));function we({title:e,subtitle:a}){const n=da();return t.createElement("div",{className:n.container},t.createElement("div",{className:n.textContainer},t.createElement(ca,null),t.createElement(oe.div,{animate:{y:0,opacity:1},initial:{y:100,opacity:0}},e&&t.createElement(f,{align:"center",variant:"h6"},e),a&&t.createElement(f,{align:"center",variant:"subtitle2"},a))))}const ma=h(e=>({campaignCards:{display:"flex",flexDirection:"column",gap:e.spacing(1)},campaignCard:{border:`1px solid ${e.palette.border}`,padding:e.spacing(2),borderRadius:e.shape.borderRadius},actions:{display:"flex",alignItems:"center",gap:e.spacing(1)},actionsText:{textTransform:"lowercase","&:first-letter":{textTransform:"uppercase"}},actionsIcon:{display:"flex"},campaignText:{display:"flex",flexDirection:"column"},campaignDescription:{textOverflow:"ellipsis",whiteSpace:"nowrap",overflow:"hidden"},entityProgress:{display:"flex",flexDirection:"column"},progress:{display:"flex",alignItems:"center",gap:e.spacing(1),width:"90%"},progressBar:{display:"flex",width:"90%",height:e.spacing(3),"& > span":{display:"flex",margin:"auto",width:"100%",height:e.spacing(2)}},daysLeft:{display:"flex",flexDirection:"column"}})),pa=({campaign:e})=>{var a;const n=ma(),r=T(Ke),l=T(Ue),i=Le(),[o,d]=F(null),{data:s,isLoading:c,isError:u}=de({tracks:[{trackId:e.track.id}]}),p=(a=s==null?void 0:s.individualEntityPassRates)!=null?a:[],m=le.fromISO(e.startDate,{zone:"utc"}),g=le.fromISO(e.targetCompletionDate,{zone:"utc"}),E=Math.round(g.diff(m,"days").days),y=O=>{d(O.currentTarget)},b=()=>{d(null)},B=()=>{i(l({campaignId:e.id}))},P=()=>{i(r({campaignId:e.id}))};if(c)return t.createElement(we,null);if(u)return t.createElement(f,{color:"error"},"Failed to load campaigns progress");let N;return p.length?N=p.map(({id:O,snapshotPassRate:H})=>t.createElement("div",{key:O,className:n.entityProgress},t.createElement(f,{variant:"body2"},$(O).name),t.createElement("div",{className:n.progress},t.createElement("div",{className:n.progressBar},t.createElement(Ye,{value:H/100,getColor:({value:S,palette:C})=>S<0?"":C.primary.main})),t.createElement("div",null,H,"%")))):N=t.createElement(f,{variant:"body2"},"No campaign progress found."),t.createElement("div",{className:n.campaignCards},t.createElement("div",{className:n.campaignCard},t.createElement(v,{container:!0,spacing:4,alignItems:"flex-start"},t.createElement(v,{item:!0,xs:12,md:4},t.createElement("div",{className:n.campaignText},t.createElement(f,{variant:"subtitle2"},e.name),t.createElement(f,{variant:"body2",className:n.campaignDescription},e.description))),t.createElement(v,{item:!0,xs:12,md:4},N),t.createElement(v,{item:!0,xs:6,md:2},t.createElement("div",{className:n.daysLeft},t.createElement(f,{variant:"subtitle2"},"Days left"),t.createElement(f,{variant:"body2"},E))),t.createElement(v,{item:!0,xs:6,md:2},t.createElement("div",null,t.createElement(Fe,{variant:"text","aria-controls":"menu","aria-haspopup":"true",onClick:y},t.createElement("div",{className:n.actions},t.createElement("div",{className:n.actionsText},"Actions"),t.createElement("div",{className:n.actionsIcon},o?t.createElement(tt,{fontSize:"small"}):t.createElement(at,{fontSize:"small"})))),t.createElement(Ae,{id:"campaign-menu",anchorEl:o,keepMounted:!0,open:!!o,onClose:b},t.createElement(q,{onClick:P},"View"),t.createElement(q,{onClick:B},"Edit")))))))},ua=h(e=>({tableContainer:{padding:0,backgroundColor:"transparent"},campaignsGrid:{margin:`0 0 ${e.spacing(3)}px`},campaignsCard:{padding:e.spacing(2),gap:e.spacing(2)},campaignsLink:{textAlign:"center",margin:`${e.spacing(1)}rem 0 ${e.spacing(1)}`}})),ga=({groupSelectorError:e,searchParams:a,setSearchParams:n,isFixedGroup:r=!1})=>{var l;const{group:i,kind:o,type:d}=a,s=T(Qe),[c,u]=F(void 0),[p,m]=F(void 0);R(()=>{((c==null?void 0:c.kind)!==o||(c==null?void 0:c.type)!==d)&&u({kind:o,type:d})},[o,d,c]);const{data:g,isLoading:E}=rt(i),{data:y}=ce({orderAlphabetical:"default",searchByOwner:i,searchByStatus:"active"}),b=y==null?void 0:y.edges.map(C=>C.campaign),B=3,P=b==null?void 0:b.slice(0,B),N=(l=k(Me).getOptionalBoolean("soundcheck.virtualizeOverviewPage"))!=null?l:!0,O=p||e,H=(C,Q)=>{C&&(u({kind:C,type:Q}),Q?n({...a,kind:C,type:Q}):(a!=null&&a.hasOwnProperty("type")&&delete a.type,n({...a,kind:C})))},S=ua();return t.createElement(v,{container:!0,spacing:0},b&&b.length>0&&t.createElement(v,{item:!0,xs:12,className:S.campaignsGrid},t.createElement(ze,{className:S.campaignsCard},t.createElement(f,{variant:"h5"},"Campaigns"),P==null?void 0:P.map(C=>t.createElement("div",{key:C.id},t.createElement(pa,{campaign:C}))),b.length>B&&t.createElement(M,{to:s(),className:S.campaignsLink},"More Campaigns"))),t.createElement(v,{item:!0,xs:12},E?t.createElement(mt,null):t.createElement(ut,{unfilteredFacets:g,kind:c==null?void 0:c.kind,type:c==null?void 0:c.type,onChange:H})),t.createElement(v,{item:!0,xs:12,className:S.tableContainer},!E&&t.createElement(la,{facets:g,kind:c==null?void 0:c.kind,type:c==null?void 0:c.type,setError:m,hasError:O,ownerEntityRef:i,useVirtualizedResultsTable:N,isFixedGroup:r})))};export{it as G,we as L,ga as O,ct as U,me as a,st as b,se as c,ke as d,de as e,ce as f,lt as u};
|
|
2
|
+
//# sourceMappingURL=OverviewPageContent-8f5b5b64.esm.js.map
|
package/dist/esm/{RefetchingIndicator-3707a744.esm.js → RefetchingIndicator-fd4435c2.esm.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t,{useState as n}from"react";import{makeStyles as a,LinearProgress as m}from"@material-ui/core";import s from"react-use/lib/useDebounce";import"@backstage/catalog-model";import"@backstage/core-plugin-api";import{useIsFetching as c}from"@tanstack/react-query";import{F as d}from"./index-
|
|
2
|
-
//# sourceMappingURL=RefetchingIndicator-
|
|
1
|
+
import t,{useState as n}from"react";import{makeStyles as a,LinearProgress as m}from"@material-ui/core";import s from"react-use/lib/useDebounce";import"@backstage/catalog-model";import"@backstage/core-plugin-api";import{useIsFetching as c}from"@tanstack/react-query";import{F as d}from"./index-88bfe2d5.esm.js";import"@backstage/plugin-catalog-react";import"react-router-dom";const p=a(e=>({indicator:{position:"absolute",width:"100%",zIndex:e.zIndex.speedDial}})),l=()=>{const e=c(),i=p(),[r,o]=n(!!e);return s(()=>{o(!!e)},250,[e]),r?t.createElement(d,null,t.createElement("div",{className:i.indicator},t.createElement(m,{variant:"indeterminate","data-testid":"refetching-indicator"}))):null};export{l as R};
|
|
2
|
+
//# sourceMappingURL=RefetchingIndicator-fd4435c2.esm.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e,{useState as n}from"react";import{Page as g,Header as f}from"@backstage/core-components";import{SpotifyLicenseBanner as s}from"@spotify/backstage-plugin-core";import{u as h,U as P,G as S,O as p}from"./OverviewPageContent-8f5b5b64.esm.js";import{S as c,w as y,f as l,i as u}from"./index-88bfe2d5.esm.js";import{stringifyEntityRef as k}from"@backstage/catalog-model";import"@backstage/core-plugin-api";import"@tanstack/react-query";import{useEntity as w}from"@backstage/plugin-catalog-react";import{Routes as C,Route as G}from"react-router-dom";import{makeStyles as L}from"@material-ui/core";import"@material-ui/lab/Autocomplete";import"react-use/lib/useAsync";import"./RefetchingIndicator-fd4435c2.esm.js";import"react-use/lib/useDebounce";import"lodash";import"@material-ui/lab";import"react-window";import"luxon";import"@material-ui/icons/ArrowDropUp";import"@material-ui/icons/ArrowDropDown";import"framer-motion";import"graphql-request";import"graphql-tag";import"@material-ui/core/styles/makeStyles";import"classnames";import"@material-ui/icons/Schedule";import"@material-ui/icons/Check";import"@material-ui/icons/Close";import"@material-ui/icons/RemoveCircleOutline";import"@material-ui/icons/HelpOutline";import"../images/empty-state.svg";const O=L(t=>({overviewContainer:{padding:t.spacing(1,3)}})),b=t=>{const{title:i="Soundcheck"}=t,o=O(),[r,m]=h(),{group:d}=r,[E,v]=n(void 0);return e.createElement(c,null,e.createElement(P,null,e.createElement(y,null,e.createElement(g,{themeId:"website"},e.createElement(s,{backend:l,invalidLicenseMessage:u}),e.createElement(f,{title:i},e.createElement(S,{onChange:a=>{a&&m({...r,group:a})},initialValue:d,setError:v})),e.createElement("div",{className:o.overviewContainer},e.createElement(p,{groupSelectorError:E,searchParams:r,setSearchParams:m}))))))},x=()=>{const{entity:t}=w(),i={group:k(t)},[o,r]=n(i);return e.createElement(c,null,e.createElement(C,null,e.createElement(G,{path:"/*",element:e.createElement(e.Fragment,null,e.createElement(s,{backend:l,invalidLicenseMessage:u,inline:!0}),e.createElement(p,{searchParams:o,setSearchParams:r,isFixedGroup:!0}))})))};export{x as FixedGroupOverviewPage,b as OverviewPage};
|
|
2
|
+
//# sourceMappingURL=index-277bccda.esm.js.map
|