@castlabs/ui 7.9.4 → 7.11.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.
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
+ // this contains general non-vue types
4
+
3
5
  declare module '@castlabs/ui/dist/castlabs-ui.module.js' {
4
6
  export function clScrollToId (id: string, smooth?: boolean): void
5
7
 
@@ -18,9 +20,6 @@ declare module '@castlabs/ui/dist/castlabs-ui.module.js' {
18
20
  export function clFormIsValidAsync (id: string): Promise<boolean>
19
21
  export function clFormFieldFocusFirstInvalid (id: string): void
20
22
  export function clFormAutofocus (id: string): void
21
- export function clRefClField (ref: unknown): any
22
- export function clRefClFieldGroup (ref: unknown): any
23
- export function clRefHTMLElement (ref: unknown): HTMLElement
24
23
 
25
24
  export function clFormatFilesize (bytes: number): string
26
25
  export function clFormatDate (date: Date): string
@@ -1,4 +1,4 @@
1
- /* @castlabs/ui v7.9.4 */
1
+ /* @castlabs/ui v7.11.0 */
2
2
 
3
3
  /*!
4
4
  * Bootstrap v5.3.8 (https://getbootstrap.com/)
@@ -337,6 +337,524 @@ export const CONST = {
337
337
  }
338
338
  }
339
339
 
340
+ // helpers that handle CS data
341
+
342
+ const ENV = {
343
+ DEV: 'DEV',
344
+ TEST: 'TEST',
345
+ STAG: 'STAG',
346
+ PROD: 'PROD'
347
+ }
348
+
349
+ const SERVICE = {
350
+ CP: 'Content Platform',
351
+ CP_TAGLINE: 'Access the Content Platform, manage, encode and watermark assets',
352
+ CP_URN: 'urn:janus:service:76b6e8558263431d9d766779987d6410',
353
+ CS: 'Castlabs hub',
354
+ CS_TAGLINE: 'Manage organizations, plans, downloads',
355
+ CS_URN: 'urn:janus:service:OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO',
356
+ DT: 'DRMtoday',
357
+ DT_TAGLINE: 'Cloud DRM & CAS licensing',
358
+ DT_URN: 'urn:janus:service:79a1092a0be44b1c95a4557b8d3ee2b7',
359
+ DTO: 'DRMtoday Onboard',
360
+ DTO_TAGLINE: 'DRMtoday Onboard',
361
+ DTO_URN: 'urn:janus:service:442f84ee6cc942188cb24486d7208289',
362
+ DTS: 'DRMtoday Staging',
363
+ DTS_TAGLINE: 'Cloud DRM & CAS licensing',
364
+ DTS_URN: 'urn:janus:service:17edeac267d84703ab0ddd7a33d85706',
365
+ PP: 'PRESTOplay',
366
+ PP_TAGLINE: 'Cross-platform video players (via Castlabs hub)',
367
+ PP_URN: 'urn:janus:service:a0682fd65f234a6793c526dc33131bab',
368
+ PP_URN_ANDROID: 'urn:janus:service:95841e63952149408c71c650c9659fb7',
369
+ PP_URN_BROWSER: 'urn:janus:service:852e1377df314c1a80003a9f67b98dfe',
370
+ PP_URN_GSTREAMER: 'urn:janus:service:76b6e8558263431d9d766779987d64c1',
371
+ PP_URN_IOS: 'urn:janus:service:2187beecaae44a01ac7eb353f5095f0f',
372
+ PP_URN_REACTNATIVE: 'urn:janus:service:6efecac3ac04477e9b36d3d14e0ae257',
373
+ PP_URN_WEBRTC: 'urn:janus:service:250402eb2e2d47118422ba4f2334ee54',
374
+ VTK: 'Video Toolkit',
375
+ VTK_TAGLINE: 'Cloud encoding, packaging, watermarking',
376
+ VTK_URN: 'urn:janus:service:a50e21d6a5e246809b636854abfbd34d',
377
+ WM: 'STARDUSTmark',
378
+ WM_TAGLINE: 'Video & image forensic watermarking',
379
+ WM_URN: 'urn:janus:service:76b6e8558263431d9d766779987d64c4'
380
+ }
381
+
382
+ const ROLE = {
383
+ CS_READONLY: 'Read-Only',
384
+ CS_READONLY_URN: 'urn:janus:role:b9d0931a01034fa095aa1a18ec303bac',
385
+
386
+ CS_ADMIN: 'Admin',
387
+ CS_ADMIN_URN: 'urn:janus:role:ab0cc31ad04a4090b41b0e552f7a3742',
388
+ CS_BILLING: 'Billing',
389
+ CS_BILLING_URN: 'urn:janus:role:2f4a76d16c9a47609255a253d873135c',
390
+ CS_REPORTS: 'Reports',
391
+ CS_REPORTS_URN: 'urn:janus:role:076e6514fe1f4d5abf307dc9fee7bbeb',
392
+
393
+ PP_ADMIN: 'PRESTOplay admin',
394
+ PP_ADMIN_URN: 'urn:janus:role:b79b1a10741f43b2bc0d1302d61b5865',
395
+ PP_USER: 'PRESTOplay user',
396
+ PP_USER_URN: 'urn:janus:role:7f2c7c7ee74d46e8936461d57180a1d3',
397
+
398
+ DT_MEMBERS: 'Members',
399
+ DT_MEMBERS_URN: 'urn:janus:role:2e5cfd4579d1485ca7e5f8cc97bdfe32',
400
+ DT_SUBORGS: 'Sub-organizations',
401
+ DT_SUBORGS_URN: 'urn:janus:role:2042447e1ae944c5a2bb75c9dd7077f3',
402
+ DT_CONFIGURATION: 'Configuration',
403
+ DT_CONFIGURATION_URN: 'urn:janus:role:07ac6d78216e41528d1b04a0ad737bc6',
404
+ DT_KEYS_DELETE: 'Key delete',
405
+ DT_KEYS_DELETE_URN: 'urn:janus:role:a79f863667944cca89588f69ea9d61dc',
406
+ DT_KEYS_INGEST: 'Key ingest',
407
+ DT_KEYS_INGEST_URN: 'urn:janus:role:08b9f5a98f084dd59d766be7039b504d',
408
+ DT_ASSETS: 'Assets',
409
+ DT_ASSETS_URN: 'urn:janus:role:4a2551570d644c08abb2795ccb8474cc',
410
+ DT_DELIVERIES: 'Deliveries',
411
+ DT_DELIVERIES_URN: 'urn:janus:role:7e23400fa5b84a38bbeca2ee515e5c9d',
412
+
413
+ DTO_DEVICES: 'Devices',
414
+ DTO_DEVICES_URN: 'urn:janus:role:c4e5556c769f4b23af3e502f9c589511',
415
+ DTO_KEYBOX: 'Keyboxes',
416
+ DTO_KEYBOX_URN: 'urn:janus:role:0658721525624ccc8fa612add5152d03',
417
+ DTO_DOWNLOAD: 'Downloads',
418
+ DTO_DOWNLOAD_URN: 'urn:janus:role:50905ceedf494b5e8d4379c0edce4b00',
419
+ DTO_REPORTS: 'Reports',
420
+ DTO_REPORTS_URN: 'urn:janus:role:50905ceedf494b5e8d4379c0edce4b01',
421
+ DTO_CONFIGURATION: 'Configuration',
422
+ DTO_CONFIGURATION_URN: 'urn:janus:role:50905ceedf494b5e8d4379c0edce4b02',
423
+
424
+ DTS_MEMBERS: 'Members',
425
+ DTS_MEMBERS_URN: 'urn:janus:role:36f4f90309294ceaa4f94e56953c1726',
426
+ DTS_SUBORGS: 'Sub-organizations',
427
+ DTS_SUBORGS_URN: 'urn:janus:role:471fe9be7e5d46feb6d84dd52e308b71',
428
+ DTS_CONFIGURATION: 'Configuration',
429
+ DTS_CONFIGURATION_URN: 'urn:janus:role:ff16e9fd5acc48e8a9acc078d2b72e7d',
430
+ DTS_KEYS_DELETE: 'Key delete',
431
+ DTS_KEYS_DELETE_URN: 'urn:janus:role:3f8dc55d3dbb4a4e893ba33ced829642',
432
+ DTS_KEYS_INGEST: 'Key ingest',
433
+ DTS_KEYS_INGEST_URN: 'urn:janus:role:471c6826d37f4d3aaa43cb3a3fda63ae',
434
+ DTS_ASSETS: 'Assets',
435
+ DTS_ASSETS_URN: 'urn:janus:role:f7c9335c70f14e4bb15d3f30761b8626',
436
+ DTS_DELIVERIES: 'Deliveries',
437
+ DTS_DELIVERIES_URN: 'urn:janus:role:e79a8f99a96a45238283b3c049e7374b',
438
+
439
+ VTK_ADMIN: 'Video Toolkit admin',
440
+ VTK_ADMIN_URN: 'urn:janus:role:8ff40a162b834e96a36f7ddbfda475ef',
441
+ VTK_USER: 'Video Toolkit user',
442
+ VTK_USER_URN: 'urn:janus:role:33c9c2001ca14dde9c3b310d0748b8b4',
443
+
444
+ CP_USER: 'Content Platform user',
445
+ CP_USER_URN: 'urn:janus:role:33c9c2001ca14dde9c3b310d0748b871',
446
+
447
+ WM_DEMO: 'Demo',
448
+ WM_DEMO_URN: 'urn:janus:role:33c9c2001ca14dde9c3b310d0748b850',
449
+ WM_EXTRACTION: 'Extraction',
450
+ WM_EXTRACTION_URN: 'urn:janus:role:33c9c2001ca14dde9c3b310d0748b851'
451
+ }
452
+
453
+ const STATE = {
454
+ UNKNOWN: null,
455
+ ACTIVE: 0,
456
+ PENDING: 1,
457
+ DELETED: 2,
458
+ SUSPENDED: 3
459
+ }
460
+
461
+ const LICENSE_STATE = {
462
+ ...STATE,
463
+ APPROVAL_REQUIRED: 4,
464
+ APPROVAL_DENIED: 5,
465
+ APPROVAL_REVOKED: 6
466
+ }
467
+
468
+ const PLAN = {
469
+ UNKNOWN: null,
470
+ TRIAL: 0,
471
+ STARTER: 1,
472
+ ENTERPRISE: 2,
473
+ CUSTOM: 3
474
+ }
475
+
476
+ const APPS = {
477
+ CP: {
478
+ id: 'CP',
479
+ subtitle: SERVICE.CP_TAGLINE,
480
+ title: SERVICE.CP,
481
+ services: [SERVICE.CP_URN],
482
+ roles: [ROLE.CP_USER_URN],
483
+ urlManage: (env, oid) =>
484
+ getEnvUrl(
485
+ env,
486
+ `https://platform.content.castlabs.com/#/o/${oid ?? ''}`,
487
+ `https://platform.content-stag.castlabs.com/#/o/${oid ?? ''}`
488
+ ),
489
+ urlPlan: (env, oid) => urlCS(env, oid),
490
+ sidenav: false
491
+ },
492
+
493
+ CS: {
494
+ id: 'CS',
495
+ subtitle: SERVICE.CS_TAGLINE,
496
+ title: SERVICE.CS,
497
+ services: [SERVICE.CS_URN],
498
+ roles: [],
499
+ urlManage: (env, oid) => urlCS(env, oid),
500
+ urlPlan: (env, oid) => urlCS(env, oid),
501
+ sidenav: true
502
+ },
503
+
504
+ DT: {
505
+ id: 'DT',
506
+ subtitle: SERVICE.DT_TAGLINE,
507
+ title: SERVICE.DT,
508
+ services: [SERVICE.DT_URN],
509
+ roles: [
510
+ ROLE.DT_MEMBERS_URN,
511
+ ROLE.DT_SUBORGS_URN,
512
+ ROLE.DT_CONFIGURATION_URN,
513
+ ROLE.DT_KEYS_DELETE_URN,
514
+ ROLE.DT_KEYS_INGEST_URN,
515
+ ROLE.DT_ASSETS_URN,
516
+ ROLE.DT_DELIVERIES_URN
517
+ ],
518
+ urlManage: (env, oid) =>
519
+ getDevTestUrl(
520
+ env,
521
+ `https://fe.test.drmtoday.com/dashboard/${oid ? `${oid}/` : ''}index`,
522
+ `https://fe.drmtoday.com/dashboard/${oid ? `${oid}/` : ''}index`
523
+ ),
524
+ urlPlan: (env, oid) => urlCS(env, oid, '/plans/drmtoday'),
525
+ sidenav: true
526
+ },
527
+
528
+ DTO: {
529
+ id: 'DTO',
530
+ subtitle: SERVICE.DTO_TAGLINE,
531
+ title: SERVICE.DTO,
532
+ services: [SERVICE.DTO_URN],
533
+ roles: [
534
+ ROLE.DTO_DEVICES_URN,
535
+ ROLE.DTO_KEYBOX_URN,
536
+ ROLE.DTO_DOWNLOAD_URN,
537
+ ROLE.DTO_CONFIGURATION_URN,
538
+ ROLE.DTO_REPORTS_URN
539
+ ],
540
+ urlManage: (env, oid) => `https://onboard.castlabs.com/o/${oid ?? ''}/devices`,
541
+ urlPlan: (env, oid) => urlCS(env, oid),
542
+ sidenav: false
543
+ },
544
+
545
+ DTS: {
546
+ id: 'DTS',
547
+ subtitle: SERVICE.DTS_TAGLINE,
548
+ title: SERVICE.DTS,
549
+ services: [SERVICE.DTS_URN],
550
+ roles: [
551
+ ROLE.DTS_MEMBERS_URN,
552
+ ROLE.DTS_SUBORGS_URN,
553
+ ROLE.DTS_CONFIGURATION_URN,
554
+ ROLE.DTS_KEYS_DELETE_URN,
555
+ ROLE.DTS_KEYS_INGEST_URN,
556
+ ROLE.DTS_ASSETS_URN,
557
+ ROLE.DTS_DELIVERIES_URN
558
+ ],
559
+ urlManage: (env, oid) =>
560
+ getDevTestUrl(
561
+ env,
562
+ `https://fe.test.drmtoday.com/dashboard/${oid ? `${oid}/` : ''}index`,
563
+ `https://fe.staging.drmtoday.com/dashboard/${oid ? `${oid}/` : ''}index`
564
+ ),
565
+ urlPlan: (env, oid) => urlCS(env, oid, '/plans/drmtoday'),
566
+ sidenav: false
567
+ },
568
+
569
+ PP: {
570
+ id: 'PP',
571
+ subtitle: SERVICE.PP_TAGLINE,
572
+ title: SERVICE.PP,
573
+ services: [
574
+ SERVICE.PP_URN,
575
+ SERVICE.PP_URN_ANDROID,
576
+ SERVICE.PP_URN_BROWSER,
577
+ SERVICE.PP_URN_GSTREAMER,
578
+ SERVICE.PP_URN_IOS,
579
+ SERVICE.PP_URN_REACTNATIVE,
580
+ SERVICE.PP_URN_WEBRTC
581
+ ],
582
+ roles: [ROLE.PP_USER_URN, ROLE.PP_ADMIN_URN],
583
+ urlManage: (env, oid) =>
584
+ getEnvUrl(
585
+ env,
586
+ `https://account.castlabs.com/o/${oid}/prestoplay`,
587
+ `https://account.test.cs.castlabs.com/o/${oid}/prestoplay`
588
+ ),
589
+ urlPlan: (env, oid) => urlCS(env, oid, '/plans/prestoplay'),
590
+ sidenav: true
591
+ },
592
+ WM: {
593
+ id: 'WM',
594
+ subtitle: SERVICE.WM_TAGLINE,
595
+ title: SERVICE.WM,
596
+ services: [SERVICE.WM_URN],
597
+ roles: [ROLE.WM_DEMO_URN, ROLE.WM_EXTRACTION_URN],
598
+ urlManage: (env, oid) =>
599
+ getEnvUrl(
600
+ env,
601
+ `https://watermark.castlabs.com/#/o/${oid}`,
602
+ `https://demo-stag.fwm.castlabs.com/#/o/${oid}`
603
+ ),
604
+ urlPlan: (env, oid) => urlCS(env, oid, '/plans/wm'),
605
+ sidenav: true
606
+ },
607
+
608
+ VTK: {
609
+ id: 'VTK',
610
+ subtitle: SERVICE.VTK_TAGLINE,
611
+ services: [SERVICE.VTK_URN],
612
+ roles: [ROLE.VTK_USER_URN, ROLE.VTK_ADMIN_URN],
613
+ title: SERVICE.VTK,
614
+ urlManage: (env, oid) =>
615
+ getEnvUrl(env, `https://vtk.castlabs.com/${oid}`, `https://vtks.castlabs.com/${oid}`),
616
+ urlPlan: (env, oid) => urlCS(env, oid, '/plans/vtk'),
617
+ sidenav: true
618
+ }
619
+ }
620
+
621
+ // ----------------------------------------------------------------------------------------
622
+
623
+ export const CS = {
624
+ SERVICE,
625
+ ROLE,
626
+ STATE,
627
+ LICENSE_STATE,
628
+ PLAN,
629
+ APPS
630
+ }
631
+
632
+ // ----------------------------------------------------------------------------------------
633
+
634
+ function urlCS (env, oid, path) {
635
+ return getDevTestUrl(
636
+ env,
637
+ `https://account.test.cs.castlabs.com/o/${oid ?? ''}${path ?? ''}`,
638
+ `https://account.castlabs.com/o/${oid ?? ''}${path ?? ''}`
639
+ )
640
+ }
641
+
642
+ function getDevTestUrl (env, urlDevTest, urlOther) {
643
+ return getEnvUrl(env, urlDevTest, urlOther, [ENV.DEV, ENV.TEST])
644
+ }
645
+
646
+ function getEnvUrl (env, urlEnv, urlOther, envs = [ENV.PROD]) {
647
+ return envs.includes(env) ? urlEnv : urlOther
648
+ }
649
+
650
+ // ----------------------------------------------------------------------------------------
651
+
652
+ function csGetBestOrgLicense (membership, sids) {
653
+ // sometimes multiple licenes apply to a service (e.g. PP-android, PP-ios, ...)
654
+ // in that case we choose the license with the highest service level to be used
655
+ // for sidenav link calulation
656
+ let best = null
657
+ for (const sid of sids) {
658
+ const license = csGetOrgLicense(membership, sid)
659
+ if (!license) continue
660
+ if (
661
+ best === null ||
662
+ (best.status === CS.LICENSE_STATE.APPROVAL_REQUIRED &&
663
+ license.status === CS.LICENSE_STATE.ACTIVE) ||
664
+ (best.plan === CS.PLAN.TRIAL && license.plan !== CS.PLAN.TRIAL)
665
+ ) {
666
+ best = license
667
+ }
668
+ }
669
+ return best
670
+ }
671
+
672
+ function csGetOrgLicense (membership, sid) {
673
+ for (const license of membership.organization?.licenses ?? []) {
674
+ if (
675
+ license.service === sid &&
676
+ [CS.LICENSE_STATE.ACTIVE, CS.LICENSE_STATE.APPROVAL_REQUIRED].includes(license.status)
677
+ ) {
678
+ return license
679
+ }
680
+ }
681
+ return null
682
+ }
683
+
684
+ function basic (service) {
685
+ // basic sidenav entry
686
+ return {
687
+ id: service.id,
688
+ title: service.title,
689
+ subtitle: service.subtitle,
690
+ url: '#',
691
+ locked: false,
692
+ disabled: false,
693
+ badge: undefined
694
+ }
695
+ }
696
+
697
+ function disabled (service) {
698
+ // sidenav entry in org-unavailable mode
699
+ return {
700
+ ...basic(service),
701
+ locked: true,
702
+ disabled: true
703
+ }
704
+ }
705
+
706
+ function subscribed (service, oid, env) {
707
+ // sidenav entry in subscribed mode
708
+ return {
709
+ ...basic(service),
710
+ url: service.urlManage(env, oid)
711
+ }
712
+ }
713
+
714
+ function trial (service, oid, env) {
715
+ // sidenav entry in TRIAL mode
716
+ return {
717
+ ...subscribed(service, oid, env),
718
+ badge: 'Trial'
719
+ }
720
+ }
721
+
722
+ function subscribe (service, oid, env) {
723
+ // sidenav entry in SUBSCRIBE mode
724
+ return {
725
+ ...basic(service),
726
+ url: service.urlPlan(env, oid),
727
+ badge: 'Subscribe',
728
+ locked: true
729
+ }
730
+ }
731
+
732
+ function pending (service, oid, env) {
733
+ // sidenav entry in PENDING mode
734
+ return {
735
+ ...basic(service),
736
+ url: service.urlPlan(env, oid),
737
+ badge: 'Pending',
738
+ locked: true
739
+ }
740
+ }
741
+
742
+ function variant (service, license, oid, env, hasRole) {
743
+ // no license = show subscribe ad
744
+ if (!license) {
745
+ // some items are hidden if there is no license
746
+ if ([APPS.DTS.id].includes(service.id)) return null
747
+
748
+ // other items we hint the user to subscribe
749
+ return subscribe(service, oid, env)
750
+ }
751
+
752
+ // pending license = show pending badge
753
+ if ([CS.LICENSE_STATE.APPROVAL_REQUIRED].includes(license.status))
754
+ return pending(service, oid, env)
755
+
756
+ // trial license = show trial badge
757
+ if (license.plan === CS.PLAN.TRIAL) return trial(service, oid, env)
758
+
759
+ // any other license and a matching role = manage link
760
+ if (hasRole) return subscribed(service, oid, env)
761
+
762
+ // license but no role = disabled
763
+ return disabled(service)
764
+ }
765
+
766
+ function csGetNavVariant (membership, service, oid, env) {
767
+ const license = csGetBestOrgLicense(membership, service.services)
768
+ return variant(
769
+ service,
770
+ license,
771
+ oid,
772
+ env,
773
+ !!membership.roles.find(r => service.roles.includes(r.role_urn))
774
+ )
775
+ }
776
+
777
+ function csParseMembership (membership, oid, env) {
778
+ const nav = [subscribed(APPS.CS, oid, env)]
779
+
780
+ nav.push(csGetNavVariant(membership, APPS.DT, oid, env))
781
+ const dts = csGetNavVariant(membership, APPS.DTS, oid, env)
782
+ if (dts) nav.push(dts)
783
+ nav.push(csGetNavVariant(membership, APPS.PP, oid, env))
784
+ nav.push(csGetNavVariant(membership, APPS.WM, oid, env))
785
+ nav.push(csGetNavVariant(membership, APPS.VTK, oid, env))
786
+
787
+ return nav
788
+ }
789
+
790
+ /**
791
+ * Filters and returns services to be shown in the sidenav based on licenses and user roles for a given org id. The expected
792
+ * JSON object corresponds to an memberships property from a CS UserInfo object retrieved via
793
+ * https://auth.castlabs.com/api/v1/userinfo
794
+ * (@see https://auth.castlabs.com/api/v1/docs#tag/User/operation/janus:UserInfo)
795
+ *
796
+ * @param {CsMembership[]} memberships Memberships.
797
+ * @param {string} oid Organization urn.
798
+ * @param {string} env Environment to generate links for (PROD, STAG, TEST, DEV).
799
+ * @returns Array of service navigation objects that the user has access to, in proper order to display in sidenav's service-drawer.
800
+ */
801
+ export function csGetNav (memberships, oid, env) {
802
+ for (const membership of memberships) {
803
+ if (membership.organization?.organization_urn === oid) {
804
+ return csParseMembership(membership, oid, env)
805
+ }
806
+ }
807
+
808
+ return [
809
+ // static nav
810
+ subscribed(APPS.CS),
811
+ disabled(APPS.DT),
812
+ disabled(APPS.PP),
813
+ disabled(APPS.WM),
814
+ disabled(APPS.VTK)
815
+ ]
816
+ }
817
+
818
+ /**
819
+ * Filters membership array of CS API to only contain memberships for a given service and role.
820
+ *
821
+ * @param {CsMembership[]} memberships Memberships.
822
+ * @param {string} rid Role urn (optional).
823
+ * @param {string} sid Service urn (optional).
824
+ * @returns Array of memberships that match sid and rid. If any id was null, it was considered as 'any'.
825
+ */
826
+ export function csFilterMemberships (memberships, rid, sid) {
827
+ let clone = JSON.parse(JSON.stringify(memberships))
828
+
829
+ // only keep orgs with licenses for required service
830
+ if (sid) {
831
+ clone = clone.filter(membership =>
832
+ membership.organization.licenses.find(license => license.service === sid)
833
+ )
834
+ }
835
+
836
+ // only keep orgs with required role
837
+ if (rid) {
838
+ clone = clone.filter(membership => membership.roles.find(role => role.role_urn === rid))
839
+ }
840
+
841
+ return clone
842
+ }
843
+
844
+ /**
845
+ * Get the link to the current user's account page in CS.
846
+ *
847
+ * @param {string} env Environment to generate links for (PROD, STAG, TEST, DEV).
848
+ * @returns {string} Full url to account page.
849
+ */
850
+ export function csGetAccountUrl (env) {
851
+ return getDevTestUrl(
852
+ env,
853
+ 'https://account.test.cs.castlabs.com/account',
854
+ 'https://account.castlabs.com/account'
855
+ )
856
+ }
857
+
340
858
  import bootstrap from 'bootstrap/dist/js/bootstrap.bundle.min'
341
859
 
342
860
  // -----------------------------------------------------------------------------
@@ -1121,19 +1639,3 @@ export function clReload (component, forced = [], optional = [], loading = true)
1121
1639
  export function clSleep (ms) {
1122
1640
  return new Promise(resolve => setTimeout(resolve, ms))
1123
1641
  }
1124
-
1125
- // -----------------------------------------------------------------------------
1126
- // --- $ref typescript cast methods --------------------------------------------
1127
- // -----------------------------------------------------------------------------
1128
-
1129
- export function clRefClField (ref) {
1130
- return ref
1131
- }
1132
-
1133
- export function clRefClFieldGroup (ref) {
1134
- return ref
1135
- }
1136
-
1137
- export function clRefHTMLElement (ref) {
1138
- return ref
1139
- }