@spotify/backstage-plugin-soundcheck 0.9.1 → 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 CHANGED
@@ -1,5 +1,28 @@
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
+
3
26
  ## 0.9.1
4
27
 
5
28
  ### Patch Changes
package/README.md CHANGED
@@ -300,6 +300,8 @@ Soundcheck’s No-Code UI integrates with Backstage’s permission framework on
300
300
 
301
301
  ![Soundcheck RBAC](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-rbac-setup.png)
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
+ ![Soundcheck Campaigns Library](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/campaign-tab.png)
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
+ ![Soundcheck Campaign Creation](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/campaign-creation.png)
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
+ ![Soundcheck Campaign Overview Page Progress](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/campaign-overview.png)
458
+ ![Soundcheck Campaign Progress](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/campaign-progress.png)
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
+ ![Soundcheck Campaign Notification](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/campaign-notification.png)
package/config.d.ts CHANGED
@@ -11,14 +11,5 @@ export interface Config {
11
11
  * @visibility frontend
12
12
  */
13
13
  reporting?: boolean;
14
- /**
15
- * @visibility frontend
16
- */
17
- campaigns?: {
18
- /**
19
- * @visibility frontend
20
- */
21
- enable?: boolean;
22
- };
23
14
  };
24
15
  }
@@ -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
@@ -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-c3aebdd7.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-a31faa1d.esm.js.map
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