@rancher/shell 0.3.11 → 0.3.12

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.
Files changed (87) hide show
  1. package/assets/translations/en-us.yaml +51 -5
  2. package/chart/monitoring/StorageClassSelector.vue +1 -0
  3. package/chart/monitoring/index.vue +4 -0
  4. package/chart/monitoring/prometheus/index.vue +6 -3
  5. package/components/ActionMenu.vue +1 -1
  6. package/components/DetailTop.vue +0 -2
  7. package/components/ExplorerMembers.vue +22 -10
  8. package/components/ExplorerProjectsNamespaces.vue +1 -0
  9. package/components/GrafanaDashboard.vue +2 -2
  10. package/components/Inactivity.vue +1 -0
  11. package/components/ModalWithCard.vue +1 -0
  12. package/components/Tabbed/index.vue +2 -0
  13. package/components/Wizard.vue +4 -3
  14. package/components/form/KeyValue.vue +12 -7
  15. package/components/form/NodeAffinity.vue +29 -7
  16. package/components/form/PodAffinity.vue +27 -7
  17. package/components/form/Taints.vue +6 -0
  18. package/components/formatter/ExtensionCache.vue +74 -0
  19. package/components/nav/Header.vue +1 -0
  20. package/components/nav/WindowManager/ContainerShell.vue +10 -0
  21. package/components/nav/WindowManager/index.vue +1 -0
  22. package/config/product/explorer.js +1 -10
  23. package/config/product/monitoring.js +2 -1
  24. package/config/router.js +3 -3
  25. package/config/table-headers.js +32 -24
  26. package/config/uiplugins.js +11 -0
  27. package/config/workload.ts +1 -0
  28. package/core/types.ts +25 -7
  29. package/creators/pkg/files/.github/workflows/build-container.yml +64 -0
  30. package/creators/pkg/init +13 -6
  31. package/detail/node.vue +2 -2
  32. package/detail/workload/index.vue +1 -1
  33. package/edit/__tests__/management.cattle.io.setting.test.ts +1 -1
  34. package/edit/autoscaling.horizontalpodautoscaler/metric-target.vue +0 -2
  35. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +43 -0
  36. package/edit/logging.banzaicloud.io.output/index.vue +8 -5
  37. package/edit/logging.banzaicloud.io.output/providers/__tests__/loki.test.ts +13 -0
  38. package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
  39. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +0 -2
  40. package/edit/monitoring.coreos.com.receiver/index.vue +32 -1
  41. package/edit/monitoring.coreos.com.receiver/types/email.vue +12 -4
  42. package/edit/namespace.vue +1 -0
  43. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +36 -6
  44. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +2 -2
  45. package/edit/provisioning.cattle.io.cluster/rke2.vue +58 -13
  46. package/middleware/authenticated.js +1 -0
  47. package/models/__tests__/batch.cronjob.test.ts +88 -0
  48. package/models/cluster/node.js +8 -0
  49. package/models/management.cattle.io.clusterroletemplatebinding.js +5 -1
  50. package/models/projectroletemplatebinding.js +9 -1
  51. package/models/workload.js +1 -1
  52. package/package.json +1 -1
  53. package/pages/__tests__/prefs.test.ts +96 -0
  54. package/pages/auth/setup.vue +13 -13
  55. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  56. package/pages/c/_cluster/apps/charts/install.vue +5 -2
  57. package/pages/c/_cluster/monitoring/index.vue +10 -5
  58. package/pages/c/_cluster/settings/performance.vue +2 -0
  59. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +601 -0
  60. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +183 -0
  61. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +50 -9
  62. package/pages/c/_cluster/uiplugins/index.vue +329 -224
  63. package/pages/fail-whale.vue +1 -1
  64. package/pages/home.vue +11 -0
  65. package/pages/prefs.vue +20 -1
  66. package/plugins/plugin.js +1 -1
  67. package/public/index.html +6 -1
  68. package/rancher-components/components/Card/Card.vue +1 -0
  69. package/rancher-components/components/Form/Radio/RadioGroup.vue +1 -0
  70. package/scripts/extension/bundle +20 -4
  71. package/scripts/extension/helm/charts/ui-plugin-server/.helmignore +23 -0
  72. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +20 -0
  73. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +52 -0
  74. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +12 -0
  75. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +6 -0
  76. package/scripts/extension/helm/package/Dockerfile +27 -0
  77. package/scripts/extension/helm/package/nginx.conf +17 -0
  78. package/scripts/extension/helm/scripts/package +23 -0
  79. package/scripts/extension/helm/scripts/patch +101 -0
  80. package/scripts/extension/helm/scripts/version +31 -0
  81. package/scripts/extension/helmpatch +3 -25
  82. package/scripts/extension/publish +47 -32
  83. package/types/shell/index.d.ts +30 -24
  84. package/utils/__tests__/grafana.test.ts +2 -2
  85. package/utils/error.js +11 -0
  86. package/utils/grafana.js +5 -4
  87. package/vue.config.js +3 -17
@@ -13,12 +13,15 @@ import Tabbed from '@shell/components/Tabbed/index.vue';
13
13
  import Tab from '@shell/components/Tabbed/Tab.vue';
14
14
  import IconMessage from '@shell/components/IconMessage.vue';
15
15
  import LazyImage from '@shell/components/LazyImage';
16
+ import { BadgeState } from '@components/BadgeState';
16
17
  import UninstallDialog from './UninstallDialog.vue';
17
18
  import InstallDialog from './InstallDialog.vue';
19
+ import CatalogLoadDialog from './CatalogList/CatalogLoadDialog.vue';
18
20
  import DeveloperInstallDialog from './DeveloperInstallDialog.vue';
19
21
  import PluginInfoPanel from './PluginInfoPanel.vue';
20
22
  import SetupUIPlugins from './SetupUIPlugins';
21
23
  import RemoveUIPlugins from './RemoveUIPlugins';
24
+ import CatalogList from './CatalogList/index.vue';
22
25
  import {
23
26
  isUIPlugin,
24
27
  uiPluginAnnotation,
@@ -27,7 +30,8 @@ import {
27
30
  isChartVersionAvailableForInstall,
28
31
  isChartVersionHigher,
29
32
  UI_PLUGIN_NAMESPACE,
30
- UI_PLUGIN_CHART_ANNOTATIONS
33
+ UI_PLUGIN_CHART_ANNOTATIONS,
34
+ UI_PLUGIN_LABELS
31
35
  } from '@shell/config/uiplugins';
32
36
 
33
37
  const MAX_DESCRIPTION_LENGTH = 200;
@@ -35,8 +39,11 @@ const MAX_DESCRIPTION_LENGTH = 200;
35
39
  export default {
36
40
  components: {
37
41
  ActionMenu,
42
+ BadgeState,
38
43
  DeveloperInstallDialog,
39
44
  IconMessage,
45
+ CatalogList,
46
+ CatalogLoadDialog,
40
47
  InstallDialog,
41
48
  LazyImage,
42
49
  PluginInfoPanel,
@@ -62,7 +69,8 @@ export default {
62
69
  hasService: false,
63
70
  defaultIcon: require('~shell/assets/images/generic-plugin.svg'),
64
71
  reloadRequired: false,
65
- rancherVersion: getVersionData()?.Version
72
+ rancherVersion: getVersionData()?.Version,
73
+ showCatalogList: false
66
74
  };
67
75
  },
68
76
 
@@ -85,6 +93,10 @@ export default {
85
93
  hash.helmOps = await this.$store.dispatch('management/findAll', { type: CATALOG.OPERATION });
86
94
  }
87
95
 
96
+ if (this.$store.getters['management/schemaFor'](CATALOG.CLUSTER_REPO)) {
97
+ hash.repos = await this.$store.dispatch('management/findAll', { type: CATALOG.CLUSTER_REPO });
98
+ }
99
+
88
100
  const res = await allHash(hash);
89
101
 
90
102
  this.plugins = res.plugins || [];
@@ -127,6 +139,15 @@ export default {
127
139
  enabled: true
128
140
  });
129
141
 
142
+ // Only show Manage Extension Catalogs when on main charts view
143
+ if (!this.showCatalogList) {
144
+ menuActions.push({
145
+ action: 'manageExtensionView',
146
+ label: this.t('plugins.manageCatalog.label'),
147
+ enabled: true
148
+ });
149
+ }
150
+
130
151
  // Only show Developer Load action if the user has this enabled in preferences
131
152
  if (this.pluginDeveloper) {
132
153
  menuActions.push( { divider: true });
@@ -195,7 +216,7 @@ export default {
195
216
  installed: false,
196
217
  builtin: false,
197
218
  experimental: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.EXPERIMENTAL, 'true'),
198
- certified: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER),
219
+ certified: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER)
199
220
  };
200
221
 
201
222
  item.versions = [...chart.versions];
@@ -260,6 +281,11 @@ export default {
260
281
  this.plugins.forEach((p) => {
261
282
  const chart = all.find(c => c.name === p.name);
262
283
 
284
+ // Plugin is a container image, do not add to charts
285
+ if (p.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE]) {
286
+ return;
287
+ }
288
+
263
289
  if (chart) {
264
290
  chart.installed = true;
265
291
  chart.uiplugin = p;
@@ -325,6 +351,10 @@ export default {
325
351
  // Sort by name
326
352
  return sortBy(all, 'name', false);
327
353
  },
354
+
355
+ pluginsFromCatalogImage() {
356
+ return this.plugins.filter(p => p.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE]);
357
+ }
328
358
  },
329
359
 
330
360
  watch: {
@@ -375,17 +405,21 @@ export default {
375
405
 
376
406
  neu.forEach((plugin) => {
377
407
  const existing = installed.find(p => !p.removed && p.name === plugin.name && p.version === plugin.version);
408
+ const isCustomImage = plugin.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE];
378
409
 
379
410
  if (!existing && plugin.isCached) {
380
- if (!this.uiErrors[plugin.name]) {
411
+ if (!this.uiErrors[plugin.name] && !isCustomImage) {
381
412
  changes++;
382
413
  }
414
+ if (isCustomImage) {
415
+ this.refreshCharts();
416
+ }
383
417
 
384
418
  this.updatePluginInstallStatus(plugin.name, false);
385
419
  }
386
420
  });
387
421
 
388
- if (changes > 0 ) {
422
+ if (changes > 0) {
389
423
  Vue.set(this, 'reloadRequired', true);
390
424
  }
391
425
  },
@@ -440,10 +474,14 @@ export default {
440
474
  },
441
475
 
442
476
  // Developer Load is in the action menu
443
- showDeveloperLoaddDialog() {
477
+ showDeveloperLoadDialog() {
444
478
  this.$refs.developerInstallDialog.showDialog();
445
479
  },
446
480
 
481
+ showCatalogLoadDialog() {
482
+ this.$refs.catalogLoadDialog.showDialog();
483
+ },
484
+
447
485
  showInstallDialog(plugin, mode, ev) {
448
486
  ev.target?.blur();
449
487
  ev.preventDefault();
@@ -464,6 +502,10 @@ export default {
464
502
  if (plugin) {
465
503
  this.updatePluginInstallStatus(plugin.name, 'uninstall');
466
504
 
505
+ if (plugin.catalog) {
506
+ this.refreshCharts();
507
+ }
508
+
467
509
  // Clear the load error, if there was one
468
510
  this.$store.dispatch('uiplugins/setError', { name: plugin.name, error: false });
469
511
  }
@@ -513,6 +555,10 @@ export default {
513
555
  resource: CATALOG.CLUSTER_REPO
514
556
  }
515
557
  });
558
+ },
559
+
560
+ manageExtensionView() {
561
+ this.showCatalogList = !this.showCatalogList;
516
562
  }
517
563
  }
518
564
  };
@@ -521,9 +567,32 @@ export default {
521
567
  <template>
522
568
  <div class="plugins">
523
569
  <div class="plugin-header">
524
- <h2 data-testid="extensions-page-title">
525
- {{ t('plugins.title') }}
526
- </h2>
570
+ <template v-if="showCatalogList">
571
+ <div class="catalog-title">
572
+ <h2
573
+ class="mb-0 mr-10"
574
+ data-testid="extensions-catalog-title"
575
+ >
576
+ <a
577
+ class="link"
578
+ @click="manageExtensionView()"
579
+ >
580
+ {{ t('plugins.manageCatalog.title') }}:
581
+ </a>
582
+ <t k="plugins.manageCatalog.subtitle" />
583
+ </h2>
584
+ <BadgeState
585
+ color="bg-warning"
586
+ :label="t('generic.experimental')"
587
+ class="badge"
588
+ />
589
+ </div>
590
+ </template>
591
+ <template v-else>
592
+ <h2 data-testid="extensions-page-title">
593
+ {{ t('plugins.title') }}
594
+ </h2>
595
+ </template>
527
596
  <div
528
597
  v-if="reloadRequired"
529
598
  class="plugin-reload-banner mr-20"
@@ -541,29 +610,33 @@ export default {
541
610
  {{ t('generic.reload') }}
542
611
  </button>
543
612
  </div>
544
- <button
613
+ <div
545
614
  v-if="hasService && hasMenuActions"
546
- ref="actions"
547
- aria-haspopup="true"
548
- type="button"
549
- class="btn actions role-secondary"
550
- data-testid="extensions-page-menu"
551
- @click="setMenu"
615
+ class="actions-container"
552
616
  >
553
- <i class="icon icon-actions" />
554
- </button>
555
- <ActionMenu
556
- v-if="hasService && hasMenuActions"
557
- :custom-actions="menuActions"
558
- :open="menuOpen"
559
- :use-custom-target-element="true"
560
- :custom-target-element="menuTargetElement"
561
- :custom-target-event="menuTargetEvent"
562
- @close="setMenu(false)"
563
- @devLoad="showDeveloperLoaddDialog"
564
- @removePluginSupport="removePluginSupport"
565
- @manageRepos="manageRepos"
566
- />
617
+ <button
618
+ ref="actions"
619
+ aria-haspopup="true"
620
+ type="button"
621
+ class="btn role-multi-action actions"
622
+ data-testid="extensions-page-menu"
623
+ @click="setMenu"
624
+ >
625
+ <i class="icon icon-actions" />
626
+ </button>
627
+ <ActionMenu
628
+ :custom-actions="menuActions"
629
+ :open="menuOpen"
630
+ :use-custom-target-element="true"
631
+ :custom-target-element="menuTargetElement"
632
+ :custom-target-event="menuTargetEvent"
633
+ @close="setMenu(false)"
634
+ @devLoad="showDeveloperLoadDialog"
635
+ @removePluginSupport="removePluginSupport"
636
+ @manageRepos="manageRepos"
637
+ @manageExtensionView="manageExtensionView"
638
+ />
639
+ </div>
567
640
  </div>
568
641
 
569
642
  <PluginInfoPanel ref="infoPanel" />
@@ -586,217 +659,228 @@ export default {
586
659
  />
587
660
  </div>
588
661
  <div v-else>
589
- <Tabbed
590
- ref="tabs"
591
- :tabs-only="true"
592
- data-testid="extension-tabs"
593
- @changed="filterChanged"
594
- >
595
- <Tab
596
- name="installed"
597
- data-testid="extension-tab-installed"
598
- label-key="plugins.tabs.installed"
599
- :weight="20"
600
- />
601
- <Tab
602
- name="available"
603
- data-testid="extension-tab-available"
604
- label-key="plugins.tabs.available"
605
- :weight="19"
606
- />
607
- <Tab
608
- name="updates"
609
- label-key="plugins.tabs.updates"
610
- :weight="18"
611
- :badge="updates.length"
612
- />
613
- <Tab
614
- name="all"
615
- label-key="plugins.tabs.all"
616
- :weight="17"
617
- />
618
- </Tabbed>
619
- <div
620
- v-if="loading"
621
- class="data-loading"
622
- >
623
- <i class="icon-spin icon icon-spinner" />
624
- <t
625
- k="generic.loading"
626
- :raw="true"
627
- />
628
- </div>
629
- <div
630
- v-else
631
- class="plugin-list"
632
- :class="{'v-margin': !list.length}"
633
- >
634
- <IconMessage
635
- v-if="list.length === 0"
636
- :vertical="true"
637
- :subtle="true"
638
- icon="icon-extension"
639
- :message="emptyMessage"
662
+ <template v-if="showCatalogList">
663
+ <CatalogList
664
+ :plugins="pluginsFromCatalogImage"
665
+ @showCatalogLoadDialog="showCatalogLoadDialog"
666
+ @showUninstallDialog="showUninstallDialog"
640
667
  />
641
- <template v-else>
668
+ </template>
669
+ <template v-else>
670
+ <Tabbed
671
+ ref="tabs"
672
+ :tabs-only="true"
673
+ data-testid="extension-tabs"
674
+ @changed="filterChanged"
675
+ >
676
+ <Tab
677
+ name="installed"
678
+ data-testid="extension-tab-installed"
679
+ label-key="plugins.tabs.installed"
680
+ :weight="20"
681
+ />
682
+ <Tab
683
+ name="available"
684
+ data-testid="extension-tab-available"
685
+ label-key="plugins.tabs.available"
686
+ :weight="19"
687
+ />
688
+ <Tab
689
+ name="updates"
690
+ label-key="plugins.tabs.updates"
691
+ :weight="18"
692
+ :badge="updates.length"
693
+ />
694
+ <Tab
695
+ name="all"
696
+ label-key="plugins.tabs.all"
697
+ :weight="17"
698
+ />
699
+ </Tabbed>
700
+ <template>
642
701
  <div
643
- v-for="plugin in list"
644
- :key="plugin.name"
645
- class="plugin"
646
- :data-testid="`extension-card-${plugin.name}`"
647
- @click="showPluginDetail(plugin)"
702
+ v-if="loading"
703
+ class="data-loading"
648
704
  >
649
- <!-- plugin icon -->
650
- <div
651
- class="plugin-icon"
652
- :class="applyDarkModeBg"
653
- >
654
- <LazyImage
655
- v-if="plugin.icon"
656
- :initial-src="defaultIcon"
657
- :error-src="defaultIcon"
658
- :src="plugin.icon"
659
- class="icon plugin-icon-img"
660
- />
661
- <img
662
- v-else
663
- :src="defaultIcon"
664
- class="icon plugin-icon-img"
665
- >
666
- </div>
667
- <!-- plugin card -->
668
- <div class="plugin-metadata">
669
- <!-- plugin basic info -->
670
- <div class="plugin-name">
671
- {{ plugin.label }}
672
- </div>
673
- <div>{{ plugin.description }}</div>
674
- <div class="plugin-version">
675
- <span
676
- v-if="plugin.installing"
677
- class="plugin-installing"
678
- >
679
- -
680
- </span>
681
- <span v-else>
682
- <span>{{ plugin.displayVersion }}</span>
683
- <span
684
- v-if="plugin.upgrade"
685
- v-clean-tooltip="t('plugins.upgradeAvailable')"
686
- > -> {{ plugin.upgrade }}</span>
687
- <p
688
- v-if="plugin.incompatibleDisclaimer"
689
- class="incompatible"
690
- >{{ plugin.incompatibleDisclaimer }}</p>
691
- </span>
692
- </div>
693
- <!-- plugin badges -->
694
- <div
695
- v-if="plugin.builtin"
696
- class="plugin-badges"
697
- >
698
- <div class="plugin-builtin">
699
- {{ t('plugins.labels.builtin') }}
700
- </div>
701
- </div>
705
+ <i class="icon-spin icon icon-spinner" />
706
+ <t
707
+ k="generic.loading"
708
+ :raw="true"
709
+ />
710
+ </div>
711
+ <div
712
+ v-else
713
+ class="plugin-list"
714
+ :class="{'v-margin': !list.length}"
715
+ >
716
+ <IconMessage
717
+ v-if="list.length === 0"
718
+ :vertical="true"
719
+ :subtle="true"
720
+ icon="icon-extension"
721
+ :message="emptyMessage"
722
+ />
723
+ <template v-else>
702
724
  <div
703
- v-else
704
- class="plugin-badges"
725
+ v-for="plugin in list"
726
+ :key="plugin.name"
727
+ class="plugin"
728
+ :data-testid="`extension-card-${plugin.name}`"
729
+ @click="showPluginDetail(plugin)"
705
730
  >
731
+ <!-- plugin icon -->
706
732
  <div
707
- v-if="!plugin.certified"
708
- v-clean-tooltip="t('plugins.descriptions.third-party')"
709
- >
710
- {{ t('plugins.labels.third-party') }}
711
- </div>
712
- <div
713
- v-if="plugin.experimental"
714
- v-clean-tooltip="t('plugins.descriptions.experimental')"
733
+ class="plugin-icon"
734
+ :class="applyDarkModeBg"
715
735
  >
716
- {{ t('plugins.labels.experimental') }}
717
- </div>
718
- </div>
719
- <div class="plugin-spacer" />
720
- <!-- plugin badges -->
721
- <div class="plugin-actions">
722
- <template v-if="plugin.error">
723
- <div
724
- v-clean-tooltip="plugin.error"
725
- class="plugin-error"
736
+ <LazyImage
737
+ v-if="plugin.icon"
738
+ :initial-src="defaultIcon"
739
+ :error-src="defaultIcon"
740
+ :src="plugin.icon"
741
+ class="icon plugin-icon-img"
742
+ />
743
+ <img
744
+ v-else
745
+ :src="defaultIcon"
746
+ class="icon plugin-icon-img"
726
747
  >
727
- <i class="icon icon-warning" />
728
- </div>
729
- </template>
730
- <!-- plugin status -->
731
- <div
732
- v-if="plugin.helmError"
733
- v-clean-tooltip="t('plugins.helmError')"
734
- class="plugin-error"
735
- >
736
- <i class="icon icon-warning" />
737
748
  </div>
738
-
739
- <div class="plugin-spacer" />
740
-
741
- <div
742
- v-if="plugin.installing"
743
- class="plugin-installing"
744
- >
745
- <i class="version-busy icon icon-spin icon-spinner" />
746
- <div v-if="plugin.installing ==='install'">
747
- {{ t('plugins.labels.installing') }}
749
+ <!-- plugin card -->
750
+ <div class="plugin-metadata">
751
+ <!-- plugin basic info -->
752
+ <div class="plugin-name">
753
+ {{ plugin.label }}
748
754
  </div>
749
- <div v-else>
750
- {{ t('plugins.labels.uninstalling') }}
755
+ <div>{{ plugin.description }}</div>
756
+ <div class="plugin-version">
757
+ <span
758
+ v-if="plugin.installing"
759
+ class="plugin-installing"
760
+ >
761
+ -
762
+ </span>
763
+ <span v-else>
764
+ <span>{{ plugin.displayVersion }}</span>
765
+ <span
766
+ v-if="plugin.upgrade"
767
+ v-clean-tooltip="t('plugins.upgradeAvailable')"
768
+ > -> {{ plugin.upgrade }}</span>
769
+ <p
770
+ v-if="plugin.incompatibleDisclaimer"
771
+ class="incompatible"
772
+ >{{ plugin.incompatibleDisclaimer }}</p>
773
+ </span>
751
774
  </div>
752
- </div>
753
- <!-- plugin buttons -->
754
- <div
755
- v-else-if="plugin.installed"
756
- class="plugin-buttons"
757
- >
758
- <button
759
- v-if="!plugin.builtin"
760
- class="btn role-secondary"
761
- :data-testid="`extension-card-uninstall-btn-${plugin.name}`"
762
- @click="showUninstallDialog(plugin, $event)"
763
- >
764
- {{ t('plugins.uninstall.label') }}
765
- </button>
766
- <button
767
- v-if="plugin.upgrade"
768
- class="btn role-secondary"
769
- :data-testid="`extension-card-update-btn-${plugin.name}`"
770
- @click="showInstallDialog(plugin, 'update', $event)"
771
- >
772
- {{ t('plugins.update.label') }}
773
- </button>
774
- <button
775
- v-if="!plugin.upgrade && plugin.installableVersions && plugin.installableVersions.length > 1"
776
- class="btn role-secondary"
777
- :data-testid="`extension-card-rollback-btn-${plugin.name}`"
778
- @click="showInstallDialog(plugin, 'rollback', $event)"
775
+ <!-- plugin badges -->
776
+ <div
777
+ v-if="plugin.builtin"
778
+ class="plugin-badges"
779
779
  >
780
- {{ t('plugins.rollback.label') }}
781
- </button>
782
- </div>
783
- <div
784
- v-else
785
- class="plugin-buttons"
786
- >
787
- <button
788
- class="btn role-secondary"
789
- :data-testid="`extension-card-install-btn-${plugin.name}`"
790
- @click="showInstallDialog(plugin, 'install', $event)"
780
+ <div class="plugin-builtin">
781
+ {{ t('plugins.labels.builtin') }}
782
+ </div>
783
+ </div>
784
+ <div
785
+ v-else
786
+ class="plugin-badges"
791
787
  >
792
- {{ t('plugins.install.label') }}
793
- </button>
788
+ <div
789
+ v-if="!plugin.certified"
790
+ v-clean-tooltip="t('plugins.descriptions.third-party')"
791
+ >
792
+ {{ t('plugins.labels.third-party') }}
793
+ </div>
794
+ <div
795
+ v-if="plugin.experimental"
796
+ v-clean-tooltip="t('plugins.descriptions.experimental')"
797
+ >
798
+ {{ t('plugins.labels.experimental') }}
799
+ </div>
800
+ </div>
801
+ <div class="plugin-spacer" />
802
+ <!-- plugin badges -->
803
+ <div class="plugin-actions">
804
+ <template v-if="plugin.error">
805
+ <div
806
+ v-clean-tooltip="plugin.error"
807
+ class="plugin-error"
808
+ >
809
+ <i class="icon icon-warning" />
810
+ </div>
811
+ </template>
812
+ <!-- plugin status -->
813
+ <div
814
+ v-if="plugin.helmError"
815
+ v-clean-tooltip="t('plugins.helmError')"
816
+ class="plugin-error"
817
+ >
818
+ <i class="icon icon-warning" />
819
+ </div>
820
+
821
+ <div class="plugin-spacer" />
822
+
823
+ <div
824
+ v-if="plugin.installing"
825
+ class="plugin-installing"
826
+ >
827
+ <i class="version-busy icon icon-spin icon-spinner" />
828
+ <div v-if="plugin.installing ==='install'">
829
+ {{ t('plugins.labels.installing') }}
830
+ </div>
831
+ <div v-else>
832
+ {{ t('plugins.labels.uninstalling') }}
833
+ </div>
834
+ </div>
835
+ <!-- plugin buttons -->
836
+ <div
837
+ v-else-if="plugin.installed"
838
+ class="plugin-buttons"
839
+ >
840
+ <button
841
+ v-if="!plugin.builtin"
842
+ class="btn role-secondary"
843
+ :data-testid="`extension-card-uninstall-btn-${plugin.name}`"
844
+ @click="showUninstallDialog(plugin, $event)"
845
+ >
846
+ {{ t('plugins.uninstall.label') }}
847
+ </button>
848
+ <button
849
+ v-if="plugin.upgrade"
850
+ class="btn role-secondary"
851
+ :data-testid="`extension-card-update-btn-${plugin.name}`"
852
+ @click="showInstallDialog(plugin, 'update', $event)"
853
+ >
854
+ {{ t('plugins.update.label') }}
855
+ </button>
856
+ <button
857
+ v-if="!plugin.upgrade && plugin.installableVersions && plugin.installableVersions.length > 1"
858
+ class="btn role-secondary"
859
+ :data-testid="`extension-card-rollback-btn-${plugin.name}`"
860
+ @click="showInstallDialog(plugin, 'rollback', $event)"
861
+ >
862
+ {{ t('plugins.rollback.label') }}
863
+ </button>
864
+ </div>
865
+ <div
866
+ v-else
867
+ class="plugin-buttons"
868
+ >
869
+ <button
870
+ class="btn role-secondary"
871
+ :data-testid="`extension-card-install-btn-${plugin.name}`"
872
+ @click="showInstallDialog(plugin, 'install', $event)"
873
+ >
874
+ {{ t('plugins.install.label') }}
875
+ </button>
876
+ </div>
877
+ </div>
794
878
  </div>
795
879
  </div>
796
- </div>
880
+ </template>
797
881
  </div>
798
882
  </template>
799
- </div>
883
+ </template>
800
884
  </div>
801
885
 
802
886
  <InstallDialog
@@ -809,6 +893,10 @@ export default {
809
893
  @closed="didUninstall"
810
894
  @update="updatePluginInstallStatus"
811
895
  />
896
+ <CatalogLoadDialog
897
+ ref="catalogLoadDialog"
898
+ @closed="didInstall"
899
+ />
812
900
  <DeveloperInstallDialog
813
901
  ref="developerInstallDialog"
814
902
  @closed="didInstall"
@@ -879,13 +967,30 @@ export default {
879
967
  .plugin-header {
880
968
  display: flex;
881
969
  align-items: center;
970
+ justify-content: space-between;
882
971
  margin-bottom: 10px;
883
972
 
973
+ .catalog-title {
974
+ display: flex;
975
+ flex-direction: row;
976
+ align-items: center;
977
+ }
978
+
884
979
  > h2 {
885
980
  flex: 1;
886
981
  margin-bottom: 0;
887
982
  }
888
983
 
984
+ .link {
985
+ cursor: pointer;
986
+ }
987
+
988
+ .actions-container {
989
+ display: flex;
990
+ flex-direction: row;
991
+ justify-content: flex-end;
992
+ }
993
+
889
994
  .btn.actions {
890
995
  line-height: 36px;
891
996
  min-height: 36px;