@spotify/backstage-plugin-soundcheck 0.5.0 → 0.6.1

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,49 @@
1
1
  # @spotify/backstage-plugin-soundcheck
2
2
 
3
+ ## 0.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated view track to not render non-applicable components.
8
+ - Resolved an issue with removing all filters from a track.
9
+ - Resolved an issue that could cause an error alert to display when viewing a check.
10
+ - Long check/track names are now truncated on the Checks/Tracks UI.
11
+ - Resolved an issue that could cause check/track filters not to populate.
12
+ - Adds pagination controls to the 'Checks' view for Soundcheck.
13
+ - Resolved an issue that would cause an error if an invalid fact reference was typed into a rule.
14
+ - Resolved an issue loading rules with nested conditions when viewing or editing a check in No Code UI.
15
+ - Resolves an issue that was causing a full page refresh after creating/editing checks or tracks
16
+
17
+ ## 0.6.0
18
+
19
+ ### Minor Changes
20
+
21
+ - Added support for Soundcheck's No-Code UI.
22
+ - Added `GroupSoundcheckContent` react component that can be added to a group page type within Backstage `EntityPage`:
23
+
24
+ ```tsx
25
+ // packages/app/src/components/catalog/EntityPage.tsx
26
+ import { GroupSoundcheckContent } from '@spotify/backstage-plugin-soundcheck';
27
+
28
+ const groupPage = (
29
+ <EntityLayout>
30
+ {/* existing tabs... */}
31
+
32
+ <EntityLayout.Route path="/soundcheck" title="Soundcheck">
33
+ <GroupSoundcheckContent />
34
+ </EntityLayout.Route>
35
+ </EntityLayout>
36
+ );
37
+ ```
38
+
39
+ ### Patch Changes
40
+
41
+ - Added "No certifications available" warning on Soundcheck Overview page in case a selected group doesn't own any entities that have applicable tracks configured.
42
+ - Upgraded Backstage to `v1.16.0`
43
+ - Updated dependencies
44
+ - @spotify/backstage-plugin-soundcheck-common@0.7.0
45
+ - @spotify/backstage-plugin-core@0.5.4
46
+
3
47
  ## 0.5.0
4
48
 
5
49
  ### Minor Changes
@@ -12,7 +56,6 @@
12
56
  - Upgraded to Backstage `v1.15.0`
13
57
  - Updated dependency `graphql-request` to `6.1.0`.
14
58
  - Updated dependency `@types/node` to `^18.0.0`.
15
- - Updated dependencies
16
59
  - Updated dependencies
17
60
  - @spotify/backstage-plugin-core@0.5.3
18
61
 
package/README.md CHANGED
@@ -8,7 +8,7 @@ There are 5 fundamental elements that make up Soundcheck:
8
8
 
9
9
  - **Check**: A standard or best practice a component is graded against.
10
10
  - **Check Result**: The result of running a check against a component. Results are either pass or fail.
11
- - **Program**: A long-term tech health initiative.
11
+ - **Track**: A long-term tech health initiative.
12
12
  - **Level**: A group of checks that represent a milestone within a program.
13
13
  - **Certification**: The outcome of passing all checks within a level.
14
14
 
@@ -80,11 +80,11 @@ const serviceEntityPage = (
80
80
  );
81
81
  ```
82
82
 
83
- ### 3. Install Soundcheck Overview Page
83
+ ### 3. Install Soundcheck Routing Page
84
84
 
85
- Add a new Route element with the path `/soundcheck` and element of `<SoundcheckOverviewPage />`.
85
+ Add a new Route element with the path `/soundcheck` and element of `<SoundcheckRoutingPage />`.
86
86
 
87
- `<SoundcheckOverviewPage />` supports the following props:
87
+ `<SoundcheckRoutingPage />` supports the following props:
88
88
 
89
89
  ```tsx
90
90
  {
@@ -96,7 +96,7 @@ The route should look something like this:
96
96
 
97
97
  ```tsx
98
98
  // packages/app/src/App.tsx
99
- import { SoundcheckOverviewPage } from '@spotify/backstage-plugin-soundcheck';
99
+ import { SoundcheckRoutingPage } from '@spotify/backstage-plugin-soundcheck';
100
100
 
101
101
  const routes = (
102
102
  <FlatRoutes>
@@ -104,7 +104,7 @@ const routes = (
104
104
 
105
105
  <Route
106
106
  path="/soundcheck"
107
- element={<SoundcheckOverviewPage title="My Optional Title" />}
107
+ element={<SoundcheckRoutingPage title="My Optional Title" />}
108
108
  />
109
109
  </FlatRoutes>
110
110
  );
@@ -134,10 +134,100 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
134
134
  );
135
135
  ```
136
136
 
137
- ### 5. Check everything is working
137
+ ### 5. Install Soundcheck Group Content Page
138
+
139
+ The Soundcheck Group Content Page is a Soundcheck Overview Page that can be pinned to a selected group entity.
140
+ It can only be added to a group page type within your Backstage `EntityPage`.
141
+
142
+ ```tsx
143
+ // packages/app/src/components/catalog/EntityPage.tsx
144
+ import { GroupSoundcheckContent } from '@spotify/backstage-plugin-soundcheck';
145
+
146
+ const groupPage = (
147
+ <EntityLayout>
148
+ {/* existing tabs... */}
149
+
150
+ <EntityLayout.Route path="/soundcheck" title="Soundcheck">
151
+ <GroupSoundcheckContent />
152
+ </EntityLayout.Route>
153
+ </EntityLayout>
154
+ );
155
+ ```
156
+
157
+ ### 6. Check everything is working
138
158
 
139
159
  If you have followed all steps up to this point, Soundcheck is set up and
140
160
  running. The backend successfully starts up if the program config is valid, and
141
161
  when you navigate to a catalog page for one of the entity types you configured
142
162
  above, you'll see the Soundcheck tab containing the applicable programs for the
143
163
  current entity. If you visit `/soundcheck` or click the "Soundcheck" entry on the sidebar, you should see the overview page.
164
+
165
+ # Product Documentation
166
+
167
+ ## No-Code UI for checks and tracks management
168
+
169
+ No-Code UI is a powerful user interface built into the Soundcheck plugin that allows users to manage checks and tracks without writing YAML code. Prior to No-Code UI, users had to write YAML code to configure a new check or track. Now, non-programmers can add checks and tracks too – thereby making it easier for everyone to work within Soundcheck.
170
+
171
+ No-Code UI has the same capabilities as its YAML configuration analog, however this capability simplifies and visualizes the process of managing checks and tracks. Checks and tracks created via No-Code UI are stored in the central Backstage database, or a [plugin-specific database](https://backstage.io/docs/tutorials/configuring-plugin-databases?__hstc=71158991.ce8f00825b31a2e008e99e7bf8c61d36.1687962480385.1687962480385.1687962480385.1&__hssc=71158991.1.1687962480385&__hsfp=2924083047#connection-configuration-per-plugin) if configured.
172
+
173
+ The No-Code UI will allow non-programmers to easily manage checks and programs via the Soundcheck UI without needing to write code. However, if a user wishes to, they can still continue to create checks and tracks through Soundcheck’s YAML configuration.
174
+
175
+ ## Using the No-Code UI
176
+
177
+ ### Checks
178
+
179
+ A check is a comparison between a defined acceptable outcome and the actual outcome of a given process. Checks indicate where the software aligns to or deviates from organizational standards and best practices.
180
+
181
+ ![Soundcheck Checks](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-checks.png)
182
+
183
+ Checks consist of four components: facts, paths, operators, and values. These components are then organized via a Boolean calculator in the UI. You can see an example of the rule layout a user will see when creating a check in the image below.
184
+
185
+ ![Soundcheck Boolean Calculator](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-boolean-calculator.png)
186
+
187
+ #### Creating a new check
188
+
189
+ To create a check, select the facts that you want to use, organize them into rules and give your check a meaningful name and a description. The rules are what defines a check and what a track will use in determining if an entity passes or fails. Simple expressions can be combined using Any Of / All Of to create more complex rules. You also have the option of adding Pass/Fail messages for additional details of why something passed/failed.
190
+
191
+ ![Soundcheck Create Check](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-new-check.png)
192
+
193
+ #### Editing a check
194
+
195
+ Once a check is created, you will be able to manage and edit your check on its detail page. You’ll find no differences in how the pages look when creating/editing a check. From the checks listing page, you will see an option to edit you check, which will bring you to the details page shown below.
196
+
197
+ ![Soundcheck Edit Check](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-edit-check.png)
198
+
199
+ You can make as many changes as desired, but just keep in mind that changes are reflected in tracks that may already have said check assigned. Checks can also be a part of multiple tracks, which could have the unintentional effect of causing some tracks to start failing. While the track you want the check updated in may pass, a track setup somewhere else may fail.
200
+
201
+ ### Tracks
202
+
203
+ Tracks are composed of levels and checks. Tracks encourage alignment to architectural best practices and standards and are analogous to an organization’s long-term tech health initiatives. Tracks are composed of one or more levels, and each level is composed of one or more checks. Each level of checks sets the standard for an organization and how they want to determine what passes and what fails in the individual track.
204
+
205
+ ![Soundcheck Tracks](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-tracks.png)
206
+
207
+ #### Creating a new track
208
+
209
+ To create a track, give your track a meaningful name and a description, and select the filters and checks that you want to use.
210
+
211
+ ![Soundcheck Create Track](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-create-track.png)
212
+
213
+ Filters allow a user further customization for their tracks to only be applicable to specific entities in the Software Catalog. This allows users to tie their tracks to specific tags such as “Java”, “service” or “production” to name a few. You can have as many or as few selections per type as you want to include in each track. Each type of filter will display a dropdown menu with your choice for selection. You can select any number of filters per section as desired.
214
+
215
+ Checks are searchable, and can be dragged-and-dropped from the list of checks into the level(s) of the track. Levels can be added to a track with the “+ Add Level” button shown above. Organizing checks into levels allows for a more nuanced read of what checks cleared and which ones didn’t. Most use levels by order of difficulty to clear, where level one means hardest to pass, level two is medium hard to pass, and level three is relatively easy to pass.
216
+
217
+ #### Editing a track
218
+
219
+ Once a track is created, you will be able to manage and edit your track on its detail page. From the tracks listing page, you will see an option to edit your track, which will bring you to the details page shown below.
220
+
221
+ ![Soundcheck Edit Track](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-edit-track.png)
222
+
223
+ As with checks, you can make as many changes as desired when editing tracks. Just make sure to save your track in order for changes to take effect. Also, similar to checks,, editing a track and saving will immediately reflect onto anything that has been assigned to said track.
224
+
225
+ ## RBAC Integration
226
+
227
+ Along with the No Code UI release, we have recently integrated Soundcheck with the [RBAC plugin](https://backstage.spotify.com/plugins/rbac/). Admins can now use the RBAC plugin to manage (allow and restrict) what individual users or groups can do within Soundcheck.
228
+
229
+ Soundcheck’s No-Code UI integrates with Backstage’s permission framework on the RBAC plugin. This integration enables restricting which users/groups can Create, Read, Update, or Delete (CRUD) Soundcheck checks and tracks.
230
+
231
+ ![Soundcheck RBAC](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/soundcheck-rbac-setup.png)
232
+
233
+ 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.
package/config.d.ts CHANGED
@@ -7,9 +7,5 @@ export interface Config {
7
7
  * @visibility frontend
8
8
  */
9
9
  virtualizeOverviewPage?: boolean;
10
- /**
11
- * @visibility frontend
12
- */
13
- noCodeUI?: boolean;
14
10
  };
15
11
  }
@@ -0,0 +1,2 @@
1
+ import e,{useState as W,useEffect as $}from"react";import{Link as O,useParams as Q,Routes as j,Route as k,Navigate as I}from"react-router-dom";import{makeStyles as p,Typography as f,Box as U,Tab as L,Tabs as T,Paper as V,Divider as Y}from"@material-ui/core";import{SpotifyLicenseBanner as q}from"@spotify/backstage-plugin-core";import{useEntity as u}from"@backstage/plugin-catalog-react";import{R as G}from"./RefetchingIndicator-b344d8b2.esm.js";import{s as H,R as o,A as y,F as B,a as J,u as x,L as K,N as X,b as C,c as g,d as Z,C as _,e as ee,i as te,f as F,S as ae}from"./index-104979d0.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 ce from"react-use/lib/useMeasure";import A from"react-use/lib/usePrevious";import oe 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";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={[o.Passed]:"success",[o.Failed]:"error",[o.NotReported]:"info",[o.NotApplicable]:"info"}[t],i={[o.Passed]:"Check passed",[o.Failed]:"Check did not pass",[o.NotReported]:"Check not reported",[o.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(B,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:l,isError:c}=se(r,t,n);if(c)return e.createElement(U,{padding:2},e.createElement(y,{severity:"error",title:"Error loading check details"}));if(l||!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:l,isLoading:c}=x(i,t),[h,{width:d,height:v}]=ce(),m=c?void 0:(a=(n=l==null?void 0:l.highestLevel)==null?void 0:n.ordinal)!=null?a:-1,E=A(m),R=A(t),[M,S]=W(!1);return $(()=>{typeof E!="undefined"&&typeof m!="undefined"&&t===R&&m>E&&S(!0)},[m,E,t,R]),M?e.createElement("div",{ref:h,className:r.root},e.createElement(oe,{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 l=z();return e.createElement(L,{className:l.root,classes:{wrapper:l.wrapper},value:t,label:e.createElement(e.Fragment,null,a?e.createElement(K,{badge:a,className:l.badge}):e.createElement(X,{className:l.badge}),n),component:O,to:r,selected:i})},w=()=>{const t=z();return e.createElement(L,{className:t.root,classes:{wrapper:t.wrapper},label:e.createElement(s,{width:180})})},ge=()=>e.createElement(B,null,e.createElement(T,{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 l=ve(r,t);return e.createElement(T,{value:l,indicatorColor:"primary","aria-label":"Certifications",variant:"scrollable"},r&&r.map(({program:{id:c,name:h},highestLevel:d})=>e.createElement(fe,{key:c,id:c,name:h,badge:d==null?void 0:d.badge,selected:c===t,href:i({trackId:c})})))},ye=p({paper:{overflow:"hidden",position:"relative"},view:{display:"grid",gridTemplateColumns:"1fr 2fr"}}),Ce=()=>{const{trackId:t,checkId:n}=Q(),a=ye(),{entity:r}=u(),{isError:i,isFetched:l,data:c}=C(r);return i?e.createElement(y,{severity:"error",title:"Error loading certifications"}):l&&!(c!=null&&c.length)?e.createElement(Z,null):e.createElement(V,{className:a.paper},e.createElement(G,null),e.createElement(ke,{trackId:t}),e.createElement(Y,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)}}})),N=()=>{const t=be();return e.createElement(e.Fragment,null,e.createElement(q,{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},Ne=()=>{var t,n;const{entity:a}=u(),{trackId:r}=ie(g),i=b(F),{data:l}=x(a,r),c=(n=(t=l==null?void 0:l.levels[0])==null?void 0:t.checks[0])==null?void 0:n.id;return c?e.createElement(I,{to:i({trackId:r,checkId:c}),replace:!0}):null},Re=()=>e.createElement(j,null,e.createElement(k,{path:"/",element:e.createElement(e.Fragment,null,e.createElement(N,null),e.createElement(we,null))}),e.createElement(k,{path:g.path,element:e.createElement(e.Fragment,null,e.createElement(N,null),e.createElement(Ne,null))}),e.createElement(k,{path:F.path,element:e.createElement(N,null)})),Se=()=>e.createElement(ae,null,e.createElement(Re,null));export{Se as EntitySoundcheckContent};
2
+ //# sourceMappingURL=EntitySoundcheckContent-846ac504.esm.js.map
@@ -0,0 +1,2 @@
1
+ import t,{useState as I,useEffect as k,useMemo as P,useCallback as j,createContext as pe,useContext as me,memo as b,Fragment as ue}from"react";import{useSearchParams as ge}from"react-router-dom";import{makeStyles as f,alpha as M,TextField as he,CircularProgress as fe,Tooltip as K,LinearProgress as ye,withStyles as ve,Grid as C,Typography as v}from"@material-ui/core";import ke from"@material-ui/lab/Autocomplete";import{stringifyEntityRef as H,parseEntityRef as w}from"@backstage/catalog-model";import{useApi as E,identityApiRef as U,useRouteRef as O,configApiRef as Ee}from"@backstage/core-plugin-api";import{useQuery as A}from"@tanstack/react-query";import{s as D,R as N,h as be,B as Ce,L as _,N as Q,A as we,d as Ne,j as Re}from"./index-104979d0.esm.js";import{catalogApiRef as W,humanizeEntityRef as x,entityRouteRef as B}from"@backstage/plugin-catalog-react";import $e from"react-use/lib/useAsync";import{HeaderTabs as q,Link as S,EmptyState as xe}from"@backstage/core-components";import{R as Te}from"./RefetchingIndicator-b344d8b2.esm.js";import{countBy as J}from"lodash";import{Skeleton as F}from"@material-ui/lab";import{VariableSizeGrid as Le}from"react-window";function Ie(){const e=E(W);return A(["soundcheck/all-groups"],async()=>{const{items:r}=await e.getEntities({filter:{kind:"Group"}});return r.filter(a=>(a==null?void 0:a.kind)==="Group").map(a=>{var n,l,o,i;return{name:(i=(o=(l=(n=a.spec)==null?void 0:n.profile)==null?void 0:l.displayName)!=null?o:a.metadata.title)!=null?i:a.metadata.name,ref:H(a)}})})}function Pe(e){const r=E(D);return A(["soundcheck/facets-for-owner",e],async()=>r.getFacetsForOwner(e),{enabled:!!e})}function X(e,r){const a=E(D);return A(["soundcheck/track-overview-for-owner",e,r],async()=>a.getProgramOverviewForOwner(e,r),{enabled:!!e&&!!(r!=null&&r.kind)})}function Oe(){const e=E(U),r=E(W);return A(["soundcheck/user-groups-claims"],async()=>{const{ownershipEntityRefs:a}=await e.getBackstageIdentity();return(await r.getEntitiesByRefs({entityRefs:a})).items.filter(n=>(n==null?void 0:n.kind)==="Group").map(n=>{var l,o,i,s;return{name:(s=(i=(o=(l=n.spec)==null?void 0:l.profile)==null?void 0:o.displayName)!=null?i:n.metadata.title)!=null?s:n.metadata.name,ref:H(n)}})})}const Ae=()=>{const[e,r]=ge(),a=Object.fromEntries(e.entries()),[n,l]=I(a);return k(()=>{r(n,{replace:!0})},[n]),[n,l]},Y=()=>{const{data:e,isLoading:r,isError:a}=Oe(),{data:n,isLoading:l,isError:o}=Ie();return{options:P(()=>{const i=[];return e&&i.push(...e.map(({name:s,ref:c})=>({name:s,ref:c,key:"My Groups"}))),n&&i.push(...n.map(({name:s,ref:c})=>({name:s,ref:c,key:"All Groups"}))),i},[e,n]),isLoading:r||l,isError:a||o}},Be=f(e=>({root:{width:"100%",minWidth:250},textField:{"& $notchedOutline":{borderColor:M(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:{}})),Se=e=>{const{onChange:r,initialValue:a,setError:n}=e,{options:l,isLoading:o,isError:i}=Y(),s=Be(),[c,d]=I(null);k(()=>{if(!o&&l!=null&&l.length&&!c){const p=a?l.find(m=>m.ref===a):l[0];p&&(d(p),r==null||r(p.ref))}},[o,l,c,r,a]);const u=j((p,m)=>{d(m),r==null||r(m==null?void 0:m.ref)},[r,d]);return k(()=>{n==null||n(i?new Error("Error loading groups"):void 0)},[i,n]),i?null:t.createElement(ke,{"aria-label":"Current group",className:s.root,classes:{clearIndicator:s.clearIndicator,popupIndicator:s.popupIndicator},disableClearable:!0,options:l!=null?l:[],loading:o,groupBy:p=>p.key,value:c,freeSolo:!1,onChange:u,getOptionLabel:p=>p.name,renderInput:p=>t.createElement(he,{...p,variant:"outlined",placeholder:o?"Loading":"Select a group",className:s.textField,InputProps:{...p.InputProps,className:s.input,classes:{notchedOutline:s.notchedOutline},endAdornment:t.createElement(t.Fragment,null,o?t.createElement(fe,{color:"inherit",size:20}):null,p.InputProps.endAdornment)}})})},Z={loading:!1},ee=pe(Z),Fe=()=>me(ee),ze=({children:e})=>{const[r,a]=I(Z),n=E(W),l=E(U),{value:o,loading:i,error:s}=$e(async()=>{const[{token:c},d]=await Promise.all([l.getCredentials(),l.getBackstageIdentity()]);return c?await n.getEntityByRef(d.userEntityRef):null},[n,l]);return k(()=>{if(o){const c=H(o);a({user:o,userEntityRef:c,loading:i,error:s})}else a({loading:i,error:s})},[o,i,s]),t.createElement(ee.Provider,{value:r},e)},He=e=>({key:`skeleton${e}`,label:"",id:`skeleton${e}`}),We=()=>{const e=Array.from({length:4},(r,a)=>He(a));return t.createElement(q,{tabs:e})},Ge=f(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)}})),Ve=({unfilteredFacets:e,onChange:r,kind:a,type:n})=>{var l,o,i;const s=Ge(),c={types:(l=e==null?void 0:e.types.filter(({count:m})=>m>0))!=null?l:[]},d=j(m=>{var g;r((g=c==null?void 0:c.types[m].kind)!=null?g:"",c==null?void 0:c.types[m].type)},[c==null?void 0:c.types,r]);k(()=>{var m,g,y;const h=(c==null?void 0:c.types)&&c.types.length>=0,T=!a&&h,$=a&&h&&!(c!=null&&c.types.find(({kind:L,type:V})=>a===L&&(!n&&!V||n===V)));(T||$)&&r((g=(m=c==null?void 0:c.types[0])==null?void 0:m.kind)!=null?g:"",(y=c==null?void 0:c.types[0])==null?void 0:y.type)},[a,n,c==null?void 0:c.types,r]);const u=(o=c==null?void 0:c.types.map(({kind:m,type:g,count:y})=>{const h=`${m}|${g!=null?g:""}`;return{key:h,label:`${g!=null?g:m} (${y>50?"50+":y})`,id:h,tabProps:{className:s.tab}}}))!=null?o:[];if(!u.length)return null;const p=(i=c==null?void 0:c.types.findIndex(m=>m.kind===a&&(!m.type&&!n||m.type===n)))!=null?i:-1;return t.createElement(t.Fragment,null,t.createElement(Te,null),t.createElement(q,{onChange:d,tabs:u,selectedIndex:p>-1?p:void 0}))},je=f(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"}})),te=e=>{var r,a;const n=je(e),l=P(()=>Object.entries(e.progress).reduce((i,[,s])=>i+s,0),[e.progress]);if(l===0)return null;const o=(r=e.progress[N.Passed])!=null?r:0;return t.createElement(K,{arrow:!0,title:`Check passing for ${o} of ${l} ${l===1?"entity":"entities"}`,enterDelay:0,placement:"top"},t.createElement(ye,{variant:"determinate",value:((a=e.progress[N.Passed])!=null?a:0)/l*100,classes:{root:n.root,bar:n.bar}}))},Me=f(e=>({headerWrapper:{marginTop:e.spacing(.5)},entityRefName:{fontWeight:"bold"},iconWrapper:{padding:e.spacing(1.5,.5),display:"flex",alignItems:"center",justifyContent:"center"}})),Ke=({check:{name:e,description:r},icon:a,entityRef:n})=>{const l=Me(),o=w(n);return t.createElement(C,{spacing:1},t.createElement(C,{container:!0,direction:"row",spacing:1,wrap:"nowrap"},t.createElement("div",{className:l.iconWrapper},a),t.createElement(v,{variant:"h6",className:l.headerWrapper,noWrap:!0},e)),t.createElement(C,{item:!0,wrap:"nowrap"},t.createElement(v,{variant:"subtitle2",className:l.entityRefName},x(o,{defaultKind:o.kind}))),t.createElement(v,{variant:"caption"},r))},Ue=ve(e=>{const r=e.palette.type==="dark"?e.palette.common.black:e.palette.grey[300];return{tooltip:{backgroundColor:r,color:e.palette.type==="dark"?e.palette.common.white:e.palette.grey[700]},arrow:{color:r}}})(K),De=({children:e,check:r,icon:a,entityRef:n})=>t.createElement(Ue,{arrow:!0,title:t.createElement(Ke,{check:r,icon:a,entityRef:n}),enterDelay:150,placement:"top"},e),_e=f(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}`}})),re=b(({programId:e,check:r,entityRef:a,result:n,entityRoute:l,isVirtualized:o})=>{const i=_e();if(typeof a!="string"){const u=t.createElement("div",{className:i.iconWrapper},t.createElement("div",{className:i.icon}));return o?t.createElement("div",{className:`${i.root} ${i.virtualized}`,"aria-hidden":!0},u):t.createElement("td",{className:i.root,"aria-hidden":!0},u)}const s=t.createElement(be,{className:i.icon,result:n!=null?n:N.NotReported}),c=t.createElement("div",{className:i.iconWrapper},s),d=n&&n===N.NotApplicable?c:t.createElement(S,{className:i.link,to:`${l(w(a))}/soundcheck/${e}/${r.id}`},c);return o?t.createElement("div",{className:`${i.root} ${i.virtualized}`},t.createElement(De,{check:r,icon:s,entityRef:a},d)):t.createElement("td",{className:`${i.root}`},d)}),ae=8,Qe=16,R={programTitle:70,levelTitle:30,check:42,entityRefFooter:100},z={programTitle:350+Qe*2,checkResult:42},qe=e=>e.reduce((r,a)=>r+a.height,0),Je=e=>e*z.checkResult+z.programTitle,Xe=e=>e.filter(r=>r!==void 0).map(r=>{const a=w(r);return x(a,{defaultKind:a.kind})}).reduce((r,a)=>r.length>a.length?r:a,""),Ye=e=>ae*e+ae,ne="NoLevel",Ze=e=>({name:ne,badge:{options:{level:0,color:""},variant:Ce.Medal},entityRef:e,ordinal:0}),le=f(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:`${R.check}px`,lineHeight:`${R.check}px`,borderBottom:`1px solid ${e.palette.divider}`,borderRight:`1px solid ${e.palette.divider}`}})),et=b(({programId:e,programName:r,check:a,entityRefs:n,results:l,entityRoute:o})=>{const i=le(),s=P(()=>J(l.filter(({result:d})=>d!==N.NotApplicable),"result"),[l]),c=new Map(l.map(d=>[d.entityRef,d.result]));return t.createElement("tr",{"data-testid":"track-check-row"},t.createElement("th",{scope:"row",className:i.checkNameCell,"aria-label":`${a.name} check for ${r} track`},t.createElement("div",{className:i.checkNameContent},t.createElement(v,{className:i.checkNameTypography,variant:"subtitle2",component:"p"},a.name),t.createElement(te,{className:i.checkIndicator,progress:s}))),n.map((d,u)=>t.createElement(re,{key:u,programId:e,check:a,entityRef:d,result:typeof d=="string"?c.get(d):void 0,entityRoute:o})))}),tt=({name:e,progress:r})=>{const a=le();return t.createElement("div",{className:a.checkNameCell,"aria-label":`${e} check`},t.createElement("div",{className:`${a.checkNameContent} ${a.checkNameCellVirtualized}`},t.createElement(v,{variant:"subtitle2",component:"p",className:a.checkNameTypography},e),t.createElement(te,{className:a.checkIndicator,progress:r})))},rt=f(e=>({virtualized:{borderRight:`1px solid ${e.palette.divider}`,height:`${R.programTitle}px`,display:"flex",justifyContent:"center",alignItems:"center"}})),at=b(({entityRef:e,highestLevels:r})=>{const a=r.find(n=>n.entityRef===e);return t.createElement(t.Fragment,null,a!=null&&a.badge?t.createElement(_,{badge:a.badge}):t.createElement(Q,null))}),nt=({highestLevel:e})=>{const r=rt();if(!(e!=null&&e.badge))return t.createElement("div",{className:r.virtualized},"\xA0");const a=e.name!==ne;return t.createElement("div",{className:r.virtualized},a?t.createElement(_,{badge:e.badge}):t.createElement(Q,null))},oe=f(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}`}})),lt=b(({program:e,entityRefs:r,highestLevels:a})=>{const n=oe();return t.createElement("tr",{"data-testid":"track-title-row"},t.createElement("th",{scope:"row",className:n.programNameCell},t.createElement("div",{className:n.programNameContent},t.createElement(v,{className:n.programNameTypography,variant:"h5",component:"p"},e.name))),r.map((l,o)=>typeof l!="string"?t.createElement("td",{key:o,"aria-hidden":!0}):t.createElement("td",{key:o,"data-testid":"track-certification-cell"},t.createElement("div",{className:n.badgeCellContent},t.createElement(at,{entityRef:l,highestLevels:a})))))}),ot=b(({name:e})=>{const r=oe();return t.createElement("div",{className:`${r.programNameCell} ${r.programNameCellVirtualized}`},t.createElement("div",{className:r.programNameContent},t.createElement(v,{className:r.programNameTypography,variant:"h5",component:"p"},e)))}),G=f(e=>{const r=e.palette.type==="dark"?e.palette.grey[700]:e.palette.grey[100];return{root:{color:M(e.palette.getContrastText(r),.8),backgroundColor:r},levelContent:{padding:`${e.spacing(.5)}px ${e.spacing(2)}px`,backgroundColor:r},levelTypography:{overflow:"hidden",textOverflow:"ellipsis"},levelHeaderCell:{padding:`${e.spacing(.5)}px ${e.spacing(2)}px`,borderRight:`1px solid ${e.palette.divider}`,height:`${R.levelTitle}px`}}}),it=b(({level:e,entityRefs:r,programName:a})=>{const n=G();return t.createElement("tr",{className:n.root,"data-testid":"track-level-row"},t.createElement("th",{scope:"row",className:n.root},t.createElement("div",{className:n.levelContent},t.createElement(v,{className:n.levelTypography,variant:"subtitle2",component:"p","aria-label":`${e.name} for ${a} track`},e.name))),r.map((l,o)=>t.createElement("td",{key:o,className:n.root,"aria-hidden":!0})))}),st=({name:e})=>{const r=G();return t.createElement("div",{className:`${r.levelHeaderCell} ${r.root}`,"aria-label":`${e}`},t.createElement(v,{variant:"subtitle2",component:"p",className:r.levelTypography},e))},ct=()=>{const e=G();return t.createElement("div",{className:`${e.levelHeaderCell} ${e.root}`},"\xA0")},dt=({program:e,highestLevels:r,levels:a,entityRefs:n,entityRoute:l})=>t.createElement("tbody",null,t.createElement(lt,{program:e,entityRefs:n,highestLevels:r}),a.map((o,i)=>t.createElement(ue,{key:i},t.createElement(it,{entityRefs:n,level:o,programName:e.name}),o.checks.map(({check:s,results:c},d)=>t.createElement(et,{key:d,check:s,programId:e.id,programName:e.name,entityRefs:n,results:c,entityRoute:l}))))),ie=f(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)"}})),pt=({entityRefs:e})=>{const r=O(B),a=ie();return t.createElement("tfoot",{className:a.root,"data-testid":"results-table-footer"},t.createElement("tr",{className:a.row},t.createElement("td",{className:a.cell}),e.map((n,l)=>{if(typeof n!="string")return t.createElement("th",{key:l,className:a.cell,"aria-hidden":!0});const o=w(n);return t.createElement("th",{scope:"col",key:l,className:a.cell},t.createElement("div",{className:a.cellInner},t.createElement(S,{to:r(o)},x(o,{defaultKind:o.kind}))))})))},mt=({entityRef:e})=>{const r=O(B),a=ie(),n=e?w(e):void 0,l=n?t.createElement(S,{to:r(n)},x(n,{defaultKind:n.kind})):t.createElement(t.Fragment,null);return t.createElement("div",{className:a.cell},t.createElement("div",{className:a.cellInner},l))},ut=f(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]}})),se=()=>{const e=ut(),r=new Array(25).fill(void 0),a=new Array(5).fill(void 0),n=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(F,{width:180,height:40})),r.map((l,o)=>t.createElement("td",{key:o}))),n.map((l,o)=>t.createElement(t.Fragment,{key:o},t.createElement("tr",{className:e.header},t.createElement("td",{className:e.title},t.createElement(F,{width:180})),r.map((i,s)=>t.createElement("td",{key:s}))),a.map((i,s)=>t.createElement("tr",{key:s},t.createElement("td",{className:e.title},t.createElement(F,{width:240})),r.map((c,d)=>t.createElement("td",{key:d,className:e.checkResult},t.createElement(F,{width:18,height:18,variant:"rect"})))))))))},gt=f(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}`}}})),ht=b(e=>{const{setError:r,kind:a,type:n,ownerEntityRef:l}=e,o=gt(),i=O(B),{data:s,isLoading:c,isError:d}=X(l,{kind:a,type:n});if(k(()=>{r==null||r(d?new Error("Error loading track overview"):void 0)},[d,r]),c)return t.createElement(se,null);if(!s||!l)return null;const{programs:u,entityRefs:p}=s;if(!c&&!u.length)return t.createElement(xe,{missing:"data",title:"Missing tracks",description:t.createElement(t.Fragment,null,"Looks like the group"," ",x(w(l),{defaultKind:"Group"})," ","doesn't own any ",n!=null?n:a," 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(S,{to:"https://www.npmjs.com/package/@spotify/backstage-plugin-soundcheck-backend#entity-filter"},"docs"),".")});if(d)return null;const m=p.length>=25?p:[...p,...Array.from({length:25-p.length},()=>{})];return t.createElement("div",{className:o.root},t.createElement("table",{className:o.table,"aria-label":"Check results"},u.map(({program:g,levels:y,highestLevels:h},T)=>t.createElement(dt,{key:T,program:g,entityRefs:m,levels:y,highestLevels:h,entityRoute:i})),t.createElement(pt,{entityRefs:m})))}),ft=e=>t.createElement(ot,{name:e}),yt=e=>({type:"ProgramHeader",render:()=>ft(e)}),vt=e=>e?t.createElement(st,{name:e}):t.createElement(ct,null),ce=e=>({type:"LevelHeader",render:()=>vt(e)}),kt=(e,r)=>t.createElement(tt,{name:e,progress:r}),Et=(e,r)=>({type:"CheckTitle",render:()=>kt(e,r)}),bt=(e,r,a,n,l)=>t.createElement(re,{check:r,entityRef:a,entityRoute:l,programId:e,result:n,isVirtualized:!0}),Ct=(e,r,a,n,l)=>({type:"CheckResult",render:()=>bt(e,r,a,n,l)}),wt=e=>t.createElement(mt,{entityRef:e}),de=e=>({type:"EntityHeader",render:()=>wt(e)}),Nt=e=>t.createElement(nt,{highestLevel:e}),Rt=e=>({type:"LevelBadge",render:()=>Nt(e)}),$t=e=>r=>{const a=e[r.rowIndex].cells[r.columnIndex];return a?t.createElement("div",{style:r.style},a.render()):t.createElement("div",{style:r.style})},xt=(e,r,a)=>{var n;const l=[];for(const{program:i,levels:s,highestLevels:c}of e){l.push({height:R.programTitle,cells:[yt(i.name),...r.map(d=>{const u=d?c.find(p=>p.entityRef===d)||Ze(d):void 0;return Rt(u)})]});for(const d of s){l.push({height:R.levelTitle,cells:[ce(d.name),...r.map(u=>ce(""))]});for(const{check:u,results:p}of d.checks)l.push({height:R.check,cells:[Et(u.name,J(p.filter(({result:m})=>m!==N.NotApplicable),"result")),...r.map(m=>{var g,y;return Ct(i.id,u,m,(y=(g=p.find(h=>h.entityRef===m))==null?void 0:g.result)!=null?y:N.NotApplicable,a)})]})}}const o=Xe(r!=null?r:[]);return l.push({height:Ye((n=o.length)!=null?n:1),cells:[de(""),...r.map(i=>de(i||""))]}),l},Tt=f(e=>({table:{backgroundColor:e.palette.background.paper,borderCollapse:"collapse",whiteSpace:"nowrap",textAlign:"left",overflow:"auto"}})),Lt=e=>{const{setError:r,kind:a,type:n,ownerEntityRef:l}=e,o=Tt(),i=O(B),{data:s,isLoading:c,isError:d}=X(l,{kind:a,type:n});if(k(()=>{r==null||r(d?new Error("Error loading program overview"):void 0)},[d,r]),c)return t.createElement(se,null);if(!s||!l)return null;const{programs:u,entityRefs:p}=s,m=p.length>=25?p:[...p,...Array.from({length:25-p.length},()=>{})],g=xt(u,m,i),y=$t(g);return t.createElement(C,{"aria-label":`Check results for ${n!=null?n:a}`,key:`${a}|${n!=null?n:""}`,item:!0,xs:12},t.createElement(Le,{className:o.table,columnCount:m.length+1,columnWidth:h=>h===0?z.programTitle:z.checkResult,rowCount:g.length,rowHeight:h=>g[h].height,height:qe(g),width:Je(m.length)},y))},It=({facets:e,ownerEntityRef:r,kind:a,type:n,setError:l})=>{const o=P(()=>{const i=new Map;return e.types.forEach(({kind:s,type:c})=>{const d=`${s}|${c!=null?c:""}`;i.set(d,t.createElement(Lt,{key:d,ownerEntityRef:r,kind:s,type:c,setError:l}))}),i},[e,r,l]);return t.createElement("div",null,o.get(`${a}|${n!=null?n:""}`))},Pt=f(()=>({scrollContainer:{overflow:"auto"}})),Ot=({facets:e,ownerEntityRef:r,hasError:a,kind:n,type:l,setError:o,useVirtualizedResultsTable:i})=>{var s,c,d;const u=Pt();return a?t.createElement(we,{severity:"error",title:a.message}):e&&((c=(s=e.types)==null?void 0:s.length)!=null?c:0)>0?(d=e.types)!=null&&d.find(p=>p.count>0)?t.createElement("div",{className:u.scrollContainer},i?t.createElement(It,{facets:e,kind:n,type:l,setError:o,ownerEntityRef:r,hasError:a}):t.createElement(ht,{ownerEntityRef:r,kind:n,type:l,setError:o})):t.createElement(Ne,{description:t.createElement(t.Fragment,null,"Looks like the group"," ",x(w(r),{defaultKind:"Group"})," ","doesn't own any entities that have any applicable tracks configured.",t.createElement("br",null),t.createElement("br",null),"Please select another group from the dropdown in the corner of the header.")}):t.createElement(Re,{ownerEntityRef:r})},At=f(()=>({tableContainer:{padding:0,backgroundColor:"transparent"}})),Bt=({groupSelectorError:e,searchParams:r,setSearchParams:a})=>{var n;const{group:l,kind:o,type:i}=r,[s,c]=I(void 0),[d,u]=I(void 0);k(()=>{((s==null?void 0:s.kind)!==o||(s==null?void 0:s.type)!==i)&&c({kind:o,type:i})},[o,i,s]);const{data:p,isLoading:m}=Pe(l),g=(n=E(Ee).getOptionalBoolean("soundcheck.virtualizeOverviewPage"))!=null?n:!1,y=d||e,h=($,L)=>{$&&(c({kind:$,type:L}),L?a({...r,kind:$,type:L}):(r!=null&&r.hasOwnProperty("type")&&delete r.type,a({...r,kind:$})))},T=At();return t.createElement(C,{container:!0,spacing:0},t.createElement(C,{item:!0,xs:12},m?t.createElement(We,null):t.createElement(Ve,{unfilteredFacets:p,kind:s==null?void 0:s.kind,type:s==null?void 0:s.type,onChange:h})),t.createElement(C,{item:!0,xs:12,className:T.tableContainer},!m&&t.createElement(Ot,{facets:p,kind:s==null?void 0:s.kind,type:s==null?void 0:s.type,setError:u,hasError:y,ownerEntityRef:l,useVirtualizedResultsTable:g})))};export{Se as G,Bt as O,ze as U,Y as a,Fe as b,Ae as u};
2
+ //# sourceMappingURL=OverviewPageContent-6a667a18.esm.js.map
@@ -0,0 +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-104979d0.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-b344d8b2.esm.js.map
@@ -0,0 +1,2 @@
1
+ import e,{useState as n}from"react";import{Page as E,Header as d}from"@backstage/core-components";import{SpotifyLicenseBanner as a}from"@spotify/backstage-plugin-core";import{u as g,U as v,G as f,O as h}from"./OverviewPageContent-6a667a18.esm.js";import{S as l,w as P,e as p,i as s}from"./index-104979d0.esm.js";import{stringifyEntityRef as S}from"@backstage/catalog-model";import"@backstage/core-plugin-api";import"@tanstack/react-query";import{useEntity as k}from"@backstage/plugin-catalog-react";import{Routes as y,Route as w}from"react-router-dom";import"@material-ui/core";import"@material-ui/lab/Autocomplete";import"react-use/lib/useAsync";import"./RefetchingIndicator-b344d8b2.esm.js";import"react-use/lib/useDebounce";import"lodash";import"@material-ui/lab";import"react-window";import"graphql-request";import"graphql-tag";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";const L=r=>{const{title:i="Soundcheck"}=r,[t,o]=g(),{group:c}=t,u=n(void 0)[1];return e.createElement(l,null,e.createElement(v,null,e.createElement(P,null,e.createElement(E,{themeId:"website"},e.createElement(a,{backend:p,invalidLicenseMessage:s}),e.createElement(d,{title:i},e.createElement(f,{onChange:m=>{m&&o({...t,group:m})},initialValue:c,setError:u}))))))},O=()=>{const{entity:r}=k(),i={group:S(r)},[t,o]=n(i);return e.createElement(l,null,e.createElement(y,null,e.createElement(w,{path:"/*",element:e.createElement(e.Fragment,null,e.createElement(a,{backend:p,invalidLicenseMessage:s,inline:!0}),e.createElement(h,{searchParams:t,setSearchParams:o}))})))};export{O as FixedGroupOverviewPage,L as OverviewPage};
2
+ //# sourceMappingURL=index-04b68ff9.esm.js.map
@@ -0,0 +1,306 @@
1
+ import{createApiRef as Fe,createRouteRef as S,createSubRouteRef as C,createPlugin as Le,createApiFactory as Ae,discoveryApiRef as xe,fetchApiRef as Oe,createRoutableExtension as $,createComponentExtension as qe,useApi as B,errorApiRef as Te,useRouteRef as j}from"@backstage/core-plugin-api";import{GraphQLClient as Be}from"graphql-request";import s from"graphql-tag";import a,{createContext as V,useState as P,useCallback as E,useContext as K,useRef as Me,useEffect as ze,Fragment as Ge}from"react";import{QueryClient as Ue,QueryClientProvider as We,useQuery as _}from"@tanstack/react-query";import{memoize as He}from"lodash";import Qe from"@material-ui/core/styles/makeStyles";import{makeStyles as p,Typography as u,Modal as je,Box as J,Button as X,Fade as Ve,alpha as w,Tooltip as Ke,withStyles as N,Divider as _e}from"@material-ui/core";import{MarkdownContent as Y,Link as Z,EmptyState as ee,InfoCard as Je}from"@backstage/core-components";import{useEntity as te,humanizeEntityRef as Xe}from"@backstage/plugin-catalog-react";import{useAutoUpdatingRelativeTime as Ye,SpotifyLicenseBanner as Ze}from"@spotify/backstage-plugin-core";import{stringifyEntityRef as re,parseEntityRef as et}from"@backstage/catalog-model";import{Alert as tt,Skeleton as f}from"@material-ui/lab";import{Link as rt}from"react-router-dom";import I from"classnames";import at from"@material-ui/icons/Schedule";import{DateTime as ae}from"luxon";import nt from"@material-ui/icons/Check";import it from"@material-ui/icons/Close";import ot from"@material-ui/icons/RemoveCircleOutline";import ct from"@material-ui/icons/HelpOutline";var ne=(e=>(e.Medal="MEDAL",e))(ne||{}),g=(e=>(e.Failed="FAILED",e.NotApplicable="NOT_APPLICABLE",e.NotReported="NOT_REPORTED",e.Passed="PASSED",e))(g||{});const st=s`
2
+ fragment CertificationSummary on Certification {
3
+ entityRef
4
+ program {
5
+ id
6
+ name
7
+ }
8
+ highestLevel {
9
+ ordinal
10
+ name
11
+ description
12
+ badge {
13
+ ... on BadgeVariantMedal {
14
+ variant
15
+ options {
16
+ level
17
+ color
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ `,lt=s`
24
+ fragment check on Check {
25
+ id
26
+ name
27
+ description
28
+ }
29
+ `,mt=s`
30
+ fragment level on Level {
31
+ ordinal
32
+ name
33
+ description
34
+ checks {
35
+ ...check
36
+ }
37
+ }
38
+ ${lt}`,dt=s`
39
+ fragment CheckResultSummary on CheckResult {
40
+ id
41
+ name
42
+ result
43
+ timestamp
44
+ }
45
+ `,ut=s`
46
+ fragment LevelResultDetails on LevelResult {
47
+ ordinal
48
+ name
49
+ description
50
+ badge {
51
+ ... on BadgeVariantMedal {
52
+ variant
53
+ options {
54
+ level
55
+ color
56
+ }
57
+ }
58
+ }
59
+ certified
60
+ checks {
61
+ ...CheckResultSummary
62
+ }
63
+ }
64
+ ${dt}`,pt=s`
65
+ fragment CheckResultDetails on CheckResult {
66
+ id
67
+ name
68
+ description
69
+ result
70
+ timestamp
71
+ notes
72
+ }
73
+ `,ht=s`
74
+ fragment OverviewLevelResult on OverviewLevelResult {
75
+ ordinal
76
+ name
77
+ checks {
78
+ check {
79
+ id
80
+ name
81
+ description
82
+ }
83
+ results {
84
+ id
85
+ entityRef
86
+ result
87
+ }
88
+ }
89
+ }
90
+ `,ie=s`
91
+ fragment HighestLevel on LevelResult {
92
+ entityRef
93
+ ordinal
94
+ name
95
+ badge {
96
+ ... on BadgeVariantMedal {
97
+ variant
98
+ options {
99
+ color
100
+ level
101
+ }
102
+ }
103
+ }
104
+ }
105
+ `,gt=s`
106
+ mutation createCheck($input: CheckerInput!) {
107
+ check: createChecker(input: $input) {
108
+ id
109
+ filter
110
+ name
111
+ description
112
+ }
113
+ }
114
+ `,ft=s`
115
+ mutation createProgram($input: ProgramInput!) {
116
+ program: createProgram(input: $input) {
117
+ id
118
+ ownerEntityRef
119
+ name
120
+ description
121
+ documentationURL
122
+ }
123
+ }
124
+ `,kt=s`
125
+ mutation deleteChecker($checkerId: String!) {
126
+ deleteChecker(checkerId: $checkerId)
127
+ }
128
+ `,yt=s`
129
+ mutation deleteProgram($programId: String!) {
130
+ programDeleted: deleteProgram(programId: $programId)
131
+ }
132
+ `,vt=s`
133
+ mutation updateCheck($input: CheckerInput!) {
134
+ check: updateChecker(input: $input) {
135
+ id
136
+ filter
137
+ name
138
+ description
139
+ }
140
+ }
141
+ `,Ct=s`
142
+ mutation updateProgram($input: ProgramInput!) {
143
+ program: updateProgram(input: $input) {
144
+ id
145
+ ownerEntityRef
146
+ name
147
+ description
148
+ documentationURL
149
+ }
150
+ }
151
+ `,Et=s`
152
+ query getAllCertifications($entityRef: String!) {
153
+ certifications(entityRef: $entityRef, includeFilteredChecks: false) {
154
+ ...CertificationSummary
155
+ }
156
+ }
157
+ ${st}`,wt=s`
158
+ query getAllPrograms($programIds: [String!], $first: Int, $after: String) {
159
+ programs(programIds: $programIds, first: $first, after: $after) {
160
+ totalCount
161
+ endCursor
162
+ hasNextPage
163
+ edges {
164
+ cursor
165
+ program {
166
+ id
167
+ ownerEntityRef
168
+ name
169
+ description
170
+ documentationURL
171
+ filter
172
+ levels {
173
+ ...level
174
+ }
175
+ isEditable
176
+ }
177
+ }
178
+ }
179
+ }
180
+ ${mt}`,Rt=s`
181
+ query getCertificationDetails($entityRef: String!, $programId: String!) {
182
+ programCertification(
183
+ entityRef: $entityRef
184
+ programId: $programId
185
+ includeFilteredChecks: false
186
+ ) {
187
+ program {
188
+ id
189
+ name
190
+ description
191
+ documentationURL
192
+ }
193
+ highestLevel {
194
+ ...HighestLevel
195
+ }
196
+ levels {
197
+ ...LevelResultDetails
198
+ }
199
+ }
200
+ }
201
+ ${ie}
202
+ ${ut}`,bt=s`
203
+ query getCheckResultDetails($entityRef: String!, $programId: String!, $checkId: String!) {
204
+ checkResult(entityRef: $entityRef, programId: $programId, checkId: $checkId) {
205
+ ...CheckResultDetails
206
+ }
207
+ }
208
+ ${pt}`,St=s`
209
+ query getCheckers($ids: [String!], $first: Int, $after: String, $orderAlphabetical: String, $searchByOwner: String, $searchByName: String) {
210
+ checkers(
211
+ ids: $ids
212
+ first: $first
213
+ after: $after
214
+ orderAlphabetical: $orderAlphabetical
215
+ searchByOwner: $searchByOwner
216
+ searchByName: $searchByName
217
+ ) {
218
+ totalCount
219
+ endCursor
220
+ hasNextPage
221
+ edges {
222
+ cursor
223
+ checker {
224
+ id
225
+ ownerEntityRef
226
+ supportChannel
227
+ name
228
+ description
229
+ rule
230
+ passedMessage
231
+ failedMessage
232
+ filter
233
+ isEditable
234
+ schedule
235
+ }
236
+ }
237
+ }
238
+ }
239
+ `,$t=s`
240
+ query getFacetsForOwner($ownerEntityRef: String!) {
241
+ facetsForOwner(ownerEntityRef: $ownerEntityRef) {
242
+ types {
243
+ kind
244
+ type
245
+ count
246
+ }
247
+ }
248
+ }
249
+ `,Pt=s`
250
+ query getCollectors($ids: [String!]) {
251
+ collectors(ids: $ids) {
252
+ id
253
+ factNames
254
+ collectionConfigs {
255
+ factRefs
256
+ filter
257
+ frequency
258
+ cache {
259
+ ... on HumanDuration {
260
+ years
261
+ months
262
+ weeks
263
+ days
264
+ hours
265
+ minutes
266
+ seconds
267
+ milliseconds
268
+ }
269
+ ... on CacheBoolean {
270
+ cache
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+ `,Nt=s`
277
+ query getFactSchemas($collectorId: String!, $factName: String!) {
278
+ factSchema(collectorId: $collectorId, factName: $factName) {
279
+ schema
280
+ }
281
+ }
282
+ `,It=s`
283
+ query getProgramOverviewForOwner($ownerEntityRef: String!, $facet: FacetInput) {
284
+ programOverviewForOwner(
285
+ ownerEntityRef: $ownerEntityRef
286
+ facet: $facet
287
+ includeFilteredChecks: false
288
+ ) {
289
+ programs {
290
+ program {
291
+ id
292
+ name
293
+ }
294
+ highestLevels {
295
+ ...HighestLevel
296
+ }
297
+ levels {
298
+ ...OverviewLevelResult
299
+ }
300
+ }
301
+ entityRefs
302
+ }
303
+ }
304
+ ${ie}
305
+ ${ht}`,Dt=(e,t,r)=>e();function Ft(e,t=Dt){return{createCheck(r,n){return t(i=>e.request(gt,r,{...n,...i}),"createCheck","mutation")},createProgram(r,n){return t(i=>e.request(ft,r,{...n,...i}),"createProgram","mutation")},deleteChecker(r,n){return t(i=>e.request(kt,r,{...n,...i}),"deleteChecker","mutation")},deleteProgram(r,n){return t(i=>e.request(yt,r,{...n,...i}),"deleteProgram","mutation")},updateCheck(r,n){return t(i=>e.request(vt,r,{...n,...i}),"updateCheck","mutation")},updateProgram(r,n){return t(i=>e.request(Ct,r,{...n,...i}),"updateProgram","mutation")},getAllCertifications(r,n){return t(i=>e.request(Et,r,{...n,...i}),"getAllCertifications","query")},getAllPrograms(r,n){return t(i=>e.request(wt,r,{...n,...i}),"getAllPrograms","query")},getCertificationDetails(r,n){return t(i=>e.request(Rt,r,{...n,...i}),"getCertificationDetails","query")},getCheckResultDetails(r,n){return t(i=>e.request(bt,r,{...n,...i}),"getCheckResultDetails","query")},getCheckers(r,n){return t(i=>e.request(St,r,{...n,...i}),"getCheckers","query")},getFacetsForOwner(r,n){return t(i=>e.request($t,r,{...n,...i}),"getFacetsForOwner","query")},getCollectors(r,n){return t(i=>e.request(Pt,r,{...n,...i}),"getCollectors","query")},getFactSchemas(r,n){return t(i=>e.request(Nt,r,{...n,...i}),"getFactSchemas","query")},getProgramOverviewForOwner(r,n){return t(i=>e.request(It,r,{...n,...i}),"getProgramOverviewForOwner","query")}}}var oe=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)},o=(e,t,r)=>(oe(e,t,"read from private field"),r?r.call(e):t.get(e)),R=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},M=(e,t,r,n)=>(oe(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r),D,F,m,z,d;const L=Fe({id:"plugin.soundcheck"}),Lt=e=>"response"in e&&"errors"in e.response,At=e=>"response"in e&&"message"in e.response;class xt{constructor(t){R(this,D,void 0),R(this,F,void 0),R(this,m,void 0),R(this,z,n=>{var i,c,l;return Lt(n)?(l=(c=(i=n.response)==null?void 0:i.errors)==null?void 0:c[0].message)!=null?l:`${n}`:At(n)?n.response.message:`${n}`}),R(this,d,async n=>{try{return await n()}catch(i){throw new Error(`Error from Soundcheck backend: ${o(this,z).call(this,i)}`)}}),M(this,D,t.fetchApi),M(this,F,t.discoveryApi);const r=new Be("/graphql",{fetch:async(n,i)=>{const c=`${await o(this,F).getBaseUrl("soundcheck")}${n}`;return o(this,D).fetch(c,i)}});M(this,m,Ft(r))}async getAllCertifications(t){return o(this,d).call(this,async()=>{const{certifications:r}=await o(this,m).getAllCertifications({entityRef:t});return r})}async getCertificationDetails(t,r){return o(this,d).call(this,async()=>{const{programCertification:n}=await o(this,m).getCertificationDetails({entityRef:t,programId:r});return n})}async getCheckResultDetails(t,r,n){return o(this,d).call(this,async()=>{const{checkResult:i}=await o(this,m).getCheckResultDetails({entityRef:t,programId:r,checkId:n});return i})}async getFacetsForOwner(t){return o(this,d).call(this,async()=>{const{facetsForOwner:r}=await o(this,m).getFacetsForOwner({ownerEntityRef:t});return r})}async getProgramOverviewForOwner(t,r){return o(this,d).call(this,async()=>{const{programOverviewForOwner:n}=await o(this,m).getProgramOverviewForOwner({ownerEntityRef:t,facet:r});return n})}async getAllPrograms(t,r,n){return o(this,d).call(this,async()=>{const{programs:i}=await o(this,m).getAllPrograms({programIds:t,first:r,after:n});return i})}async createProgram(t){return o(this,d).call(this,async()=>{const{program:r}=await o(this,m).createProgram({input:t});return r})}async updateProgram(t){return o(this,d).call(this,async()=>{const{program:r}=await o(this,m).updateProgram({input:t});return r})}async deleteProgram(t){return o(this,d).call(this,async()=>{const{programDeleted:r}=await o(this,m).deleteProgram({programId:t});return r})}async getChecks(t,r,n){return o(this,d).call(this,async()=>{const{checkers:i}=await o(this,m).getCheckers({ids:t,first:r,after:n});return i})}async createCheck(t){return o(this,d).call(this,async()=>{const{check:r}=await o(this,m).createCheck({input:t});return r})}async updateCheck(t){return o(this,d).call(this,async()=>{const{check:r}=await o(this,m).updateCheck({input:t});return r})}async deleteCheck(t){return o(this,d).call(this,async()=>await o(this,m).deleteChecker({checkerId:t}))}async getCollectors(t){return o(this,d).call(this,async()=>{const{collectors:r}=await o(this,m).getCollectors({ids:t});return r})}async getFactSchema(t,r){if(!(!t||!r))return o(this,d).call(this,async()=>{const{factSchema:n}=await o(this,m).getFactSchemas({collectorId:t,factName:r});return n})}}D=new WeakMap,F=new WeakMap,m=new WeakMap,z=new WeakMap,d=new WeakMap;const A=S({id:"soundcheck-entity"}),Ot=S({id:"soundcheck-group"}),ce=C({id:"soundcheck-entity-certification-track-redirect",parent:A,path:"/:trackId"}),se=C({id:"soundcheck-entity-certification",parent:A,path:"/:trackId/:checkId"}),qt=S({id:"soundcheck-overview"}),x=S({id:"soundcheck"});C({id:"soundcheck-checks",parent:x,path:"/checks"}),C({id:"soundcheck-tracks",parent:x,path:"/tracks"}),C({id:"soundcheck-track-details",parent:x,path:"/tracks/:trackId"});const y=Le({id:"soundcheck",apis:[Ae({api:L,deps:{discoveryApi:xe,fetchApi:Oe},factory:e=>new xt(e)})],routes:{entityContent:A}}),Tt=y.provide($({name:"EntitySoundcheckContent",component:()=>import("./EntitySoundcheckContent-846ac504.esm.js").then(e=>e.EntitySoundcheckContent),mountPoint:A})),Bt=y.provide(qe({name:"EntitySoundcheckCard",component:{lazy:()=>import("./index-ddb40786.esm.js").then(e=>e.EntitySoundcheckCard)}})),Mt=y.provide($({name:"GroupSoundcheckContent",component:()=>import("./index-04b68ff9.esm.js").then(e=>e.FixedGroupOverviewPage),mountPoint:Ot})),zt=y.provide($({name:"SoundcheckOverviewPage",component:()=>import("./index-04b68ff9.esm.js").then(e=>e.OverviewPage),mountPoint:qt})),Gt=y.provide($({name:"SoundcheckRoutingPage",component:()=>import("./index-62a0beb1.esm.js").then(e=>e.RoutingPage),mountPoint:x})),Ut=He(e=>new Ue({defaultOptions:{queries:{refetchInterval:6e4,refetchIntervalInBackground:!1,refetchOnWindowFocus:"always",retry:2,retryDelay:t=>{const r=450+Math.ceil(Math.random()*100);return Math.min(r*2**t,3e4)},onError:t=>e.post(t)}}})),Wt=e=>{const t=B(Te),r=Ut(t);return a.createElement(We,{client:r},e.children)};function le(e){const t=B(L),r=re(e);return _(["soundcheck/certifications",r],async()=>t.getAllCertifications(r))}function me(e,t){const r=B(L),n=re(e);return _(["soundcheck/certifications",n,t],async()=>r.getCertificationDetails(n,t),{enabled:!!t})}var de=(e=>(e.GetAllPrograms="soundcheck/programs",e.GetChecks="soundcheck/checks",e.GetCollectors="soundcheck/collectors",e.GetFactSchema="soundcheck/collectors/schema",e.GetEntityFacets="soundcheck/catalog/facets",e))(de||{}),ue=(e=>(e.DeleteCheck="soundcheck/deleteCheck",e.CreateCheck="soundcheck/createCheck",e.UpdateCheck="soundcheck/updateCheck",e.DeleteProgram="soundcheck/deleteProgram",e.CreateProgram="soundcheck/createProgram",e.UpdateProgram="soundcheck/updateProgram",e))(ue||{});const Ht=p(e=>({root:{padding:e.spacing(3)},icon:{display:"none"},message:{padding:0},type:{fontWeight:700,lineHeight:1.75}})),O=e=>{const{type:t,...r}=Ht();return a.createElement(tt,{severity:e.severity,elevation:1,classes:r,onClose:e.onClose},a.createElement(u,{classes:{root:t}},e.title),e.children)},pe=V({}),Qt=e=>{const[t,r]=P(),n=E(c=>{r(c)},[]),i=E(()=>{r(null)},[]);return a.createElement(pe.Provider,{value:{showAlert:n,clearAlert:i}},t&&a.createElement(O,{severity:t.severity,title:t.title,onClose:i},t.message),e.children)},jt=()=>K(pe),Vt=p(e=>({modalContent:{position:"absolute",top:"50%",left:"50%",transform:"translate(-50%, -50%)",padding:"25px",backgroundColor:e.palette.type==="dark"?e.palette.grey[800]:e.palette.grey[200]},modalButtons:{display:"flex",justifyContent:"space-evenly","& button":{width:"40%",maxWidth:"185px"}},modalMessage:{margin:"15px 0 35px"}})),he=V({}),Kt=e=>{const t=Vt(),[r,n]=P(!1),[i,c]=P(),l=Me(),h=E(({title:b,message:Ne,error:Ie})=>(c({title:b,message:Ne,error:Ie}),n(!0),new Promise(De=>{l.current=De})),[]),v=E(()=>{l.current&&l.current(!0),n(!1)},[]),k=E(()=>{l.current&&l.current(!1),n(!1)},[]);return a.createElement(he.Provider,{value:{showModal:h}},e.children,i&&a.createElement(je,{open:r,onClose:k,"aria-labelledby":"confirmation-modal-title","aria-describedby":"confirmation-modal-description"},a.createElement(J,{className:t.modalContent},a.createElement(u,{id:"confirmation-modal-title",variant:"h6"},i.title),a.createElement(u,{className:t.modalMessage,id:"confirmation-modal-description",variant:"body1"},i.message),a.createElement("div",{className:t.modalButtons},!i.error&&a.createElement(X,{onClick:k,variant:"contained","aria-label":"cancel"},"Cancel"),a.createElement(X,{color:"primary",onClick:v,variant:"contained","aria-label":"confirm"},i.error?"Ok":"Confirm")))))},_t=()=>K(he),ge=24,Jt=11,G=e=>e==="small"?1:2,Xt=p({root:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",borderRadius:"50%",borderWidth:"2px",fontWeight:700,width:({size:e})=>`${ge*G(e)}px`,height:({size:e})=>`${ge*G(e)}px`,fontSize:({size:e})=>`${Jt*G(e)}px`}}),fe=({className:e,label:t,size:r="small"})=>{const n=Xt({size:r});return a.createElement("span",{className:I(e,n.root),role:"img","aria-label":`${t} badge`},t)},Yt=p(e=>({root:{background:({color:t})=>t,color:e.palette.common.black,borderColor:e.palette.common.black,borderStyle:"solid","&::after":{position:"absolute",display:"block",content:'""',top:0,left:0,width:"100%",height:"100%",borderRadius:"50%",boxShadow:["inset 0 -0.18em 0 0 rgba(0, 0, 0, 0.25)","inset 0px 0.18em 0px 0px rgba(255, 255, 255, 0.5)","inset 0px 1.3em 0px -0.5em rgba(255, 255, 255, 0.2)"].join(",")}}})),U=({className:e,badge:t,size:r="small"})=>{const n=Yt({color:t.options.color,size:r});return a.createElement(fe,{className:I(e,n.root),size:r,label:`L${t.options.level}`})},Zt=p({root:{borderColor:"currentColor",borderStyle:"dashed"}}),ke=({className:e,size:t="small"})=>{const r=Zt();return a.createElement(fe,{className:I(e,r.root),size:t,label:"NL"})},W=p(e=>({description:{padding:0,margin:0,display:"block","& p":{margin:0}},root:{padding:e.spacing(2),margin:0,display:"grid",gridTemplateColumns:"min-content auto",gridGap:e.spacing(2)},title:{fontSize:e.typography.pxToRem(18),fontWeight:700,lineHeight:1.235,marginBottom:"6px"},level:{textTransform:"uppercase",color:e.palette.text.secondary,fontWeight:700,letterSpacing:"1px"}}));function er({description:e,documentationUrl:t}){const r=W();return t?a.createElement("div",{className:r.description},a.createElement(Y,{content:e}),a.createElement(Z,{to:t},"Learn more")):a.createElement("div",{className:r.description},a.createElement(Y,{content:e}))}const ye=({name:e,level:t,badge:r,description:n,documentationUrl:i})=>{const c=W();return a.createElement("div",{className:c.root},r?a.createElement(U,{size:"large",badge:r}):a.createElement(ke,{size:"large"}),a.createElement("div",null,a.createElement(u,{variant:"caption",className:c.level},t!=null?t:"No Level"),a.createElement(u,{className:c.title},e),n&&a.createElement(er,{description:n,documentationUrl:i})))},q=({children:e})=>{const[t,r]=P(!1);return ze(()=>{const n=setTimeout(()=>{r(!0)},250);return()=>clearTimeout(n)},[]),a.createElement(Ve,{in:t,timeout:250},e)},H=({hideDescription:e=!1})=>{const t=W();return a.createElement(q,null,a.createElement("div",{className:t.root},a.createElement(f,{width:44,height:44}),a.createElement("div",null,a.createElement(u,{variant:"caption",className:t.level},a.createElement(f,{width:100})),a.createElement(u,{variant:"h4",className:t.title},a.createElement(f,{width:300})),!e&&a.createElement(u,{variant:"body2"},a.createElement(f,null)))))},ve=p(e=>{const t=e.palette.type==="dark"?e.palette.grey[700]:e.palette.grey[100];return{wrapper:{backgroundColor:t,color:w(e.palette.getContrastText(t),.8),fontSize:e.typography.caption.fontSize,minHeight:"auto",borderTop:`1px solid ${e.palette.divider}`,borderBottom:`1px solid ${e.palette.divider}`,padding:e.spacing(1),display:"grid",gridTemplateAreas:({badge:r})=>[`"${r?"badge":"title"} title"`,`"${r?".":"description"} description"`].join(" "),gridTemplateColumns:"auto 1fr"},title:{gridArea:"title",textTransform:"uppercase",fontWeight:"bold",color:w(e.palette.getContrastText(t),.8),fontSize:e.typography.body2.fontSize,paddingTop:e.spacing(.5),paddingBottom:e.spacing(.5),lineHeight:1},badge:{gridArea:"badge",marginRight:e.spacing(1)},description:{gridArea:"description",color:w(e.palette.getContrastText(t),.8),fontSize:e.typography.subtitle2.fontSize,marginTop:e.spacing(1)}}}),tr=e=>{const t=ve({badge:e.badge});return a.createElement("div",{className:t.wrapper},e.badge?a.createElement(U,{className:t.badge,badge:e.badge}):null,a.createElement(u,{className:t.title},e.title),e.description?a.createElement(u,{className:t.description},e.description):null)},rr=()=>{const e=ve({});return a.createElement(q,null,a.createElement("div",{className:e.wrapper},a.createElement(f,{className:e.title}),a.createElement(u,{className:e.description},a.createElement(f,null))))},ar=p(e=>({root:{display:"inline-flex",alignItems:"center",gap:e.spacing(1)}})),Ce=({timestamp:e,description:t})=>{const r=ar(),n=ae.fromISO(e).toLocaleString(ae.DATETIME_FULL),i=Ye(e),c=t?`${t}: ${i}`:void 0;return a.createElement("div",{className:r.root},a.createElement(Ke,{title:n},a.createElement(u,{variant:"caption","aria-label":c},i)),a.createElement(at,null))},nr=e=>({[g.Passed]:"Check passed",[g.NotReported]:"Check not reported",[g.Failed]:"Check failed",[g.NotApplicable]:"Check not applicable"})[e],ir=N(e=>({root:{color:e.palette.success.main}}))(nt),or=N(e=>({root:{color:e.palette.error.main}}))(it),cr=N(e=>({root:{color:e.palette.info.main}}))(ct),sr=N(e=>({root:{color:e.palette.text.disabled}}))(ot),Ee=({result:e,className:t})=>{const r={className:t,"aria-label":nr(e),"aria-hidden":!1};return e===g.Passed?a.createElement(ir,{...r}):e===g.NotReported?a.createElement(cr,{...r}):e===g.Failed?a.createElement(or,{...r}):e===g.NotApplicable?a.createElement(sr,{...r}):null},we=p(e=>({root:{display:"grid",width:"100%",gridTemplateColumns:"auto 1fr auto",gridColumnGap:e.spacing(1),padding:e.spacing(1),alignItems:"center","&.selected":{backgroundColor:w(e.palette.primary[e.palette.type],.2)},"&:hover, &:active, &:focus":{backgroundColor:w(e.palette.primary[e.palette.type],.3)}}})),lr=({className:e,href:t,children:r})=>t?a.createElement(rt,{to:t,className:e},r):a.createElement("div",{className:e},r),mr=({result:e,name:t,timestamp:r,selected:n=!1,href:i})=>{const c=we(),l=I(c.root,{selected:n});return a.createElement(lr,{href:i,className:l},a.createElement(Ee,{result:e}),a.createElement(u,{variant:"body2"},t),r?a.createElement(Ce,{timestamp:r}):null)},Q=()=>{const e=we();return a.createElement(q,null,a.createElement("div",{className:e.root},a.createElement(f,{width:24,height:24}),a.createElement(u,{variant:"body2"},a.createElement(f,null)),a.createElement(f,{width:100,height:24})))},dr=()=>{const e=Re();return a.createElement("div",{className:e.root},a.createElement(H,null),new Array(3).fill(null).map((t,r)=>a.createElement(a.Fragment,{key:`skeleton-level-${r}`},a.createElement(rr,null),a.createElement("ul",{className:e.checks},a.createElement(Q,null),a.createElement(Q,null),a.createElement(Q,null)))))},ur=p(e=>({noChecks:{padding:e.spacing(1)},checks:{padding:0,margin:0,flex:1,listStyle:"none"},checkItem:{borderBottom:`1px solid ${e.palette.divider}`,"&:last-of-type":{borderBottom:"0"}}})),pr=({checks:e,trackId:t,checkId:r})=>{const n=ur(),i=j(se);return e.length?a.createElement("ul",{className:n.checks},e.map(c=>a.createElement("li",{key:c.id,className:n.checkItem},a.createElement(mr,{...c,selected:c.id===r,href:i({trackId:t,checkId:c.id})})))):a.createElement(u,{variant:"body2",className:n.noChecks},"No applicable checks at this level.")},hr=({level:e,checkId:t,trackId:r})=>{var n;return a.createElement(a.Fragment,null,a.createElement(tr,{badge:e.badge,title:e.name,description:e.description}),a.createElement(pr,{checks:(n=e.checks)!=null?n:[],trackId:r,checkId:t}))},Re=p(e=>({root:{borderRight:`1px solid ${e.palette.divider}`},checks:{padding:0,margin:0,flex:1,listStyle:"none"}})),gr=({trackId:e,checkId:t})=>{var r,n;const i=Re(),{entity:c}=te(),{data:l,isLoading:h,isError:v}=me(c,e);return v?a.createElement("div",{className:i.root},a.createElement(J,{padding:2},a.createElement(O,{severity:"error",title:"Error loading certification"}))):h||!e?a.createElement(dr,null):l?a.createElement("div",{className:i.root},a.createElement(ye,{name:l.program.name,level:(r=l.highestLevel)==null?void 0:r.name,badge:(n=l.highestLevel)==null?void 0:n.badge,description:l.program.description,documentationUrl:l.program.documentationURL}),l==null?void 0:l.levels.map(k=>a.createElement(hr,{key:k.ordinal,level:k,checkId:t,trackId:e}))):null},fr=()=>a.createElement(a.Fragment,null,a.createElement(H,{hideDescription:!0}),a.createElement(H,{hideDescription:!0})),be=({className:e,description:t="There are no tracks configured that apply to this entity."})=>a.createElement("div",{className:e},a.createElement(ee,{title:"No certifications available",missing:"data",description:t})),kr=({ownerEntityRef:e})=>e?a.createElement(ee,{missing:"data",title:"Missing entities",description:a.createElement(a.Fragment,null,"Looks like the group"," ",Xe(et(e),{defaultKind:"Group"})," ","doesn't own any entities.",a.createElement("br",null),a.createElement("br",null),"Please select another group from the dropdown in the corner of the header.")}):null,Se="soundcheck",$e="Submitted check results will still be stored, but it will not be possible to view certifications or individual results until a valid license is present.",Pe=Qe(e=>({certificationWrapper:{display:"flex",justifyContent:"space-between",alignItems:"center"},infoCard:{display:"grid",gridRowGap:e.spacing(2)},emptyState:{"& > div":{backgroundColor:e.palette.background.paper}}})),T=({children:e,title:t})=>{const r=Pe();return a.createElement(Je,{title:t},a.createElement("div",{className:r.infoCard},a.createElement(Ze,{inline:!0,backend:Se,invalidLicenseMessage:$e}),e))},yr=({title:e="Soundcheck"})=>{const{entity:t}=te(),r=Pe(),{data:n,isError:i,isLoading:c}=le(t),l=j(ce);return i?a.createElement(T,{title:e},a.createElement(O,{severity:"error",title:"Error loading certifications"})):c||!n?a.createElement(T,{title:e},a.createElement(fr,null)):n.length===0?a.createElement(T,{title:e},a.createElement(be,{className:r.emptyState})):a.createElement(T,{title:e},n.map((h,v)=>{var k,b;return a.createElement(Ge,{key:h.program.name},a.createElement("div",{className:r.certificationWrapper,"data-testid":"soundcheck-track-row"},a.createElement(ye,{key:h.program.id,name:h.program.name,badge:(k=h.highestLevel)==null?void 0:k.badge,level:(b=h.highestLevel)==null?void 0:b.name}),a.createElement(Z,{to:l({trackId:h.program.id})},"View Details")),v<n.length-1?a.createElement(_e,null):null)}))};export{O as A,ne as B,gr as C,Tt as E,q as F,Mt as G,U as L,ue as M,ke as N,de as Q,g as R,Wt as S,Ce as a,le as b,ce as c,be as d,Se as e,se as f,yr as g,Ee as h,$e as i,kr as j,jt as k,_t as l,Qt as m,y as n,Bt as o,zt as p,Gt as q,L as s,me as u,Kt as w};
306
+ //# sourceMappingURL=index-104979d0.esm.js.map