@rancher/shell 3.0.9-rc.5 → 3.0.9-rc.6

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 (142) hide show
  1. package/assets/images/providers/oci-open-containers.svg +22 -0
  2. package/assets/images/providers/traefik.png +0 -0
  3. package/assets/styles/themes/_dark.scss +2 -0
  4. package/assets/styles/themes/_light.scss +2 -0
  5. package/assets/styles/themes/_modern.scss +6 -0
  6. package/assets/translations/en-us.yaml +129 -25
  7. package/components/CruResource.vue +3 -1
  8. package/components/ExplorerProjectsNamespaces.vue +12 -12
  9. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +109 -0
  10. package/components/Resource/Detail/Card/StatusCard/index.vue +21 -4
  11. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +19 -2
  12. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +19 -11
  13. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +12 -0
  14. package/components/Resource/Detail/ResourcePopover/index.vue +2 -0
  15. package/components/Resource/Detail/ResourceRow.vue +2 -2
  16. package/components/ResourceList/index.vue +7 -4
  17. package/components/Window/ContainerLogs.vue +48 -37
  18. package/components/fleet/FleetClusterTargets/TargetsList.vue +2 -2
  19. package/components/fleet/FleetClusterTargets/index.vue +6 -1
  20. package/components/fleet/GitRepoAdvancedTab.vue +333 -0
  21. package/components/fleet/GitRepoMetadataTab.vue +43 -0
  22. package/components/fleet/GitRepoRepositoryTab.vue +101 -0
  23. package/components/fleet/GitRepoTargetTab.vue +77 -0
  24. package/components/fleet/HelmOpAdvancedTab.vue +247 -0
  25. package/components/fleet/HelmOpChartTab.vue +158 -0
  26. package/components/fleet/HelmOpMetadataTab.vue +46 -0
  27. package/components/fleet/HelmOpTargetTab.vue +84 -0
  28. package/components/fleet/HelmOpValuesTab.vue +147 -0
  29. package/components/fleet/__tests__/FleetClusterTargets.test.ts +119 -70
  30. package/components/form/NodeScheduling.vue +81 -7
  31. package/components/form/PodAffinity.vue +1 -36
  32. package/components/form/ResourceLabeledSelect.vue +8 -4
  33. package/components/form/ResourceQuota/Namespace.vue +30 -9
  34. package/components/form/ResourceQuota/NamespaceRow.vue +25 -7
  35. package/components/form/ResourceQuota/Project.vue +140 -82
  36. package/components/form/ResourceQuota/ResourceQuotaEntry.vue +145 -0
  37. package/components/form/ResourceQuota/__tests__/Namespace.test.ts +307 -0
  38. package/components/form/ResourceQuota/__tests__/NamespaceRow.test.ts +281 -0
  39. package/components/form/ResourceQuota/__tests__/Project.test.ts +274 -27
  40. package/components/form/ResourceQuota/__tests__/ResourceQuotaEntry.test.ts +215 -0
  41. package/components/form/SchedulingCustomization.vue +14 -6
  42. package/components/form/SelectOrCreateAuthSecret.vue +107 -18
  43. package/components/form/__tests__/NodeScheduling.test.ts +12 -9
  44. package/components/form/__tests__/PodAffinity.test.ts +21 -2
  45. package/components/form/__tests__/SchedulingCustomization.test.ts +240 -0
  46. package/components/formatter/ClusterLink.vue +8 -0
  47. package/components/formatter/SecretOrigin.vue +79 -0
  48. package/config/labels-annotations.js +7 -6
  49. package/config/pagination-table-headers.js +6 -4
  50. package/config/product/explorer.js +1 -11
  51. package/config/query-params.js +3 -0
  52. package/config/settings.ts +15 -2
  53. package/config/table-headers.js +21 -17
  54. package/config/types.js +23 -8
  55. package/detail/workload/index.vue +11 -16
  56. package/dialog/DeactivateDriverDialog.vue +1 -1
  57. package/dialog/Ipv6NetworkingDialog.vue +156 -0
  58. package/dialog/ScalePoolDownDialog.vue +2 -2
  59. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  60. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +1 -0
  61. package/edit/__tests__/management.cattle.io.project.test.js +56 -128
  62. package/edit/auth/oidc.vue +1 -1
  63. package/edit/catalog.cattle.io.clusterrepo.vue +155 -25
  64. package/edit/fleet.cattle.io.gitrepo.vue +153 -283
  65. package/edit/fleet.cattle.io.helmop.vue +190 -332
  66. package/edit/management.cattle.io.project.vue +5 -42
  67. package/edit/management.cattle.io.setting.vue +6 -0
  68. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +55 -24
  69. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +1 -103
  70. package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +13 -1
  71. package/edit/provisioning.cattle.io.cluster/__tests__/rke2-fleet-cluster-agent.test.ts +283 -0
  72. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -49
  73. package/edit/provisioning.cattle.io.cluster/ingress/IngressCards.vue +112 -0
  74. package/edit/provisioning.cattle.io.cluster/ingress/IngressConfiguration.vue +158 -0
  75. package/edit/provisioning.cattle.io.cluster/rke2.vue +171 -72
  76. package/edit/provisioning.cattle.io.cluster/shared.ts +36 -1
  77. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +2 -1
  78. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +55 -7
  79. package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +319 -0
  80. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +2 -1
  81. package/edit/provisioning.cattle.io.cluster/tabs/etcd/__tests__/S3Config.test.ts +13 -1
  82. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +10 -44
  83. package/edit/secret/index.vue +1 -1
  84. package/edit/token.vue +68 -29
  85. package/edit/workload/__tests__/index.test.ts +2 -37
  86. package/edit/workload/index.vue +6 -2
  87. package/edit/workload/mixins/workload.js +0 -32
  88. package/list/__tests__/management.cattle.io.setting.test.ts +198 -0
  89. package/list/management.cattle.io.setting.vue +13 -0
  90. package/list/provisioning.cattle.io.cluster.vue +50 -1
  91. package/list/secret.vue +4 -9
  92. package/list/service.vue +6 -8
  93. package/machine-config/amazonec2.vue +11 -4
  94. package/machine-config/components/EC2Networking.vue +46 -30
  95. package/machine-config/components/__tests__/EC2Networking.test.ts +7 -7
  96. package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +0 -9
  97. package/machine-config/digitalocean.vue +3 -3
  98. package/models/__tests__/namespace.test.ts +11 -0
  99. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +96 -0
  100. package/models/__tests__/workload.test.ts +42 -1
  101. package/models/catalog.cattle.io.clusterrepo.js +30 -4
  102. package/models/ext.cattle.io.token.js +48 -0
  103. package/models/kontainerdriver.js +2 -2
  104. package/models/namespace.js +7 -1
  105. package/models/nodedriver.js +2 -2
  106. package/models/provisioning.cattle.io.cluster.js +28 -7
  107. package/models/secret.js +0 -17
  108. package/models/service.js +44 -1
  109. package/models/token.js +4 -0
  110. package/models/workload.js +12 -6
  111. package/package.json +1 -1
  112. package/pages/account/index.vue +96 -67
  113. package/pages/auth/setup.vue +5 -14
  114. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +4 -1
  115. package/pages/c/_cluster/apps/charts/index.vue +93 -4
  116. package/pages/c/_cluster/apps/charts/install.vue +317 -42
  117. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -4
  118. package/pages/c/_cluster/settings/index.vue +3 -1
  119. package/plugins/dashboard-store/__tests__/getters.test.ts +108 -0
  120. package/plugins/dashboard-store/__tests__/resource-class.test.ts +27 -0
  121. package/plugins/dashboard-store/actions.js +3 -8
  122. package/plugins/dashboard-store/getters.js +7 -5
  123. package/plugins/dashboard-store/mutations.js +4 -1
  124. package/plugins/dashboard-store/resource-class.js +3 -3
  125. package/plugins/steve/__tests__/steve-class.test.ts +102 -141
  126. package/plugins/steve/steve-class.js +12 -3
  127. package/plugins/steve/steve-pagination-utils.ts +6 -2
  128. package/rancher-components/RcIcon/types.ts +2 -0
  129. package/rancher-components/RcItemCard/RcItemCard.vue +64 -19
  130. package/store/prefs.js +3 -0
  131. package/types/aws-sdk.d.ts +121 -0
  132. package/types/resources/node.ts +15 -0
  133. package/types/shell/index.d.ts +536 -506
  134. package/types/store/pagination.types.ts +5 -5
  135. package/utils/__tests__/array.test.ts +1 -29
  136. package/utils/__tests__/cluster-agent-configuration.test.ts +203 -0
  137. package/utils/array.ts +0 -11
  138. package/utils/aws.ts +21 -0
  139. package/utils/cluster.js +22 -2
  140. package/utils/selector-typed.ts +1 -1
  141. package/components/__tests__/ProjectRow.test.ts +0 -206
  142. package/components/form/ResourceQuota/ProjectRow.vue +0 -277
@@ -6,7 +6,12 @@ import { NAME as FLEET_NAME } from '@shell/config/product/fleet';
6
6
 
7
7
  const mockStore = {
8
8
  getters: {
9
- productId: 'PRODUCT_ID', clusterId: 'CLUSTER_ID', 'type-map/optionsFor': jest.fn(), currentCluster: 'CLUSTER_ID'
9
+ productId: 'PRODUCT_ID',
10
+ clusterId: 'CLUSTER_ID',
11
+ 'type-map/optionsFor': jest.fn(),
12
+ currentCluster: 'CLUSTER_ID',
13
+ currentStore: () => 'cluster',
14
+ 'cluster/canList': () => true,
10
15
  }
11
16
  };
12
17
  const mockRoute = { params: { cluster: 'CLUSTER', namespace: 'NAMESPACE' } };
@@ -32,7 +37,8 @@ describe('composables: IdentifyingFields', () => {
32
37
  expect(result).toBeUndefined();
33
38
  });
34
39
 
35
- it('should return a valid namespace row', () => {
40
+ it('should return a valid namespace row with ResourcePopover when user canList namespaces', () => {
41
+ mockStore.getters['cluster/canList'] = () => true;
36
42
  const resource = { namespace: 'NAMESPACE' };
37
43
  const result = useNamespace(resource);
38
44
 
@@ -42,6 +48,17 @@ describe('composables: IdentifyingFields', () => {
42
48
  expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.namespace');
43
49
  expect(result?.value.valueDataTestid).toStrictEqual('masthead-subheader-namespace');
44
50
  });
51
+
52
+ it('should return a plain text namespace row when user cannot canList namespaces', () => {
53
+ mockStore.getters['cluster/canList'] = () => false;
54
+ const resource = { namespace: 'NAMESPACE' };
55
+ const result = useNamespace(resource);
56
+
57
+ expect(result?.value.valueOverride).toBeUndefined();
58
+ expect(result?.value.value).toStrictEqual(resource.namespace);
59
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.namespace');
60
+ expect(result?.value.valueDataTestid).toStrictEqual('masthead-subheader-namespace');
61
+ });
45
62
  });
46
63
 
47
64
  describe('useWorkspace', () => {
@@ -24,18 +24,26 @@ export const useNamespace = (resource: any): ComputedRef<Row> | undefined => {
24
24
  }
25
25
 
26
26
  return computed(() => {
27
- return {
28
- label: i18n.t('component.resource.detail.metadata.identifyingInformation.namespace'),
29
- value: resourceValue.namespace,
30
- valueDataTestid: 'masthead-subheader-namespace',
31
- valueOverride: {
32
- component: markRaw(defineAsyncComponent(() => import('@shell/components/Resource/Detail/ResourcePopover/index.vue'))),
33
- props: {
34
- type: NAMESPACE,
35
- id: resourceValue.namespace,
36
- detailLocation: resourceValue.namespaceLocation
37
- }
27
+ const currentStore = store.getters['currentStore'](NAMESPACE);
28
+ const canList = store.getters[`${ currentStore }/canList`](NAMESPACE);
29
+
30
+ const label = i18n.t('component.resource.detail.metadata.identifyingInformation.namespace');
31
+ const value = resourceValue.namespace;
32
+ const valueDataTestid = 'masthead-subheader-namespace';
33
+ const valueOverride = canList ? {
34
+ component: markRaw(defineAsyncComponent(() => import('@shell/components/Resource/Detail/ResourcePopover/index.vue'))),
35
+ props: {
36
+ type: NAMESPACE,
37
+ id: resourceValue.namespace,
38
+ detailLocation: resourceValue.namespaceLocation
38
39
  }
40
+ } : undefined;
41
+
42
+ return {
43
+ label,
44
+ value,
45
+ valueDataTestid,
46
+ valueOverride,
39
47
  };
40
48
  });
41
49
  };
@@ -79,6 +79,18 @@ describe('component: ResourcePopover/index.vue', () => {
79
79
  expect(wrapper.find('.display').exists()).toBe(false);
80
80
  });
81
81
 
82
+ it('should show plain text and no PopoverCard when fetch fails', async() => {
83
+ mockClusterFind.mockRejectedValue(new Error('Not found'));
84
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
85
+
86
+ await wrapper.vm.$nextTick();
87
+ await wrapper.vm.$nextTick();
88
+ await wrapper.vm.$nextTick();
89
+
90
+ expect(wrapper.findComponent(PopoverCard).exists()).toBe(false);
91
+ expect(wrapper.text()).toBe('test-ns/test-pod');
92
+ });
93
+
82
94
  it('should fetch data using the default store', async() => {
83
95
  const wrapper = createWrapper();
84
96
 
@@ -58,6 +58,7 @@ const actionInvoked = () => {
58
58
 
59
59
  <template>
60
60
  <PopoverCard
61
+ v-if="!fetch.error"
61
62
  class="resource-popover"
62
63
  :card-title="nameDisplay"
63
64
  fallback-focus="[data-testid='resource-popover-action-menu']"
@@ -104,6 +105,7 @@ const actionInvoked = () => {
104
105
  />
105
106
  </template>
106
107
  </PopoverCard>
108
+ <span v-else>{{ props.id }}</span>
107
109
  </template>
108
110
 
109
111
  <style lang="scss" scoped>
@@ -47,7 +47,7 @@ const displayCounts = computed(() => {
47
47
  </SubtleLink>
48
48
  <span
49
49
  v-else
50
- class="text-muted"
50
+ class="text-deemphasized"
51
51
  >
52
52
  {{ label }}
53
53
  </span>
@@ -55,7 +55,7 @@ const displayCounts = computed(() => {
55
55
  <div class="right">
56
56
  <div
57
57
  v-if="!counts || counts.length == 0"
58
- class="text-muted"
58
+ class="text-deemphasized"
59
59
  >
60
60
  0
61
61
  </div>
@@ -87,11 +87,14 @@ export default {
87
87
  },
88
88
 
89
89
  beforeMount() {
90
- const inStore = this.$store.getters['currentStore'](this.resource);
91
- const canList = this.$store.getters[`${ inStore }/canList`](this.resource);
90
+ if (!this.hasListComponent) {
91
+ // If a list doesn't have a list component confirm via schema that the resource is listable
92
+ const inStore = this.$store.getters['currentStore'](this.resource);
93
+ const canList = this.$store.getters[`${ inStore }/canList`](this.resource);
92
94
 
93
- if (!canList) {
94
- this.$store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceListNotListable', { resource: this.schema.id }, true)));
95
+ if (!canList) {
96
+ this.$store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceListNotListable', { resource: this.schema?.id || this.resource || 'unknown' }, true)));
97
+ }
95
98
  }
96
99
  },
97
100
 
@@ -13,7 +13,6 @@ import LogItem from '@shell/components/LogItem';
13
13
  import ContainerLogsActions from '@shell/components/Window/ContainerLogsActions.vue';
14
14
  import { shallowRef } from 'vue';
15
15
  import { useStore } from 'vuex';
16
- import { debounce } from 'lodash';
17
16
  import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
18
17
 
19
18
  import { escapeRegex } from '@shell/utils/string';
@@ -110,12 +109,6 @@ export default {
110
109
  required: true,
111
110
  },
112
111
 
113
- // The height of the window
114
- height: {
115
- type: Number,
116
- required: true,
117
- },
118
-
119
112
  // The pod to connect to
120
113
  pod: {
121
114
  type: Object,
@@ -147,7 +140,6 @@ export default {
147
140
  socket: null,
148
141
  isOpen: false,
149
142
  isFollowing: true,
150
- scrollThreshold: 80,
151
143
  timestamps: this.$store.getters['prefs/get'](LOGS_TIME),
152
144
  wrap: this.$store.getters['prefs/get'](LOGS_WRAP),
153
145
  previous: false,
@@ -290,18 +282,6 @@ export default {
290
282
  container() {
291
283
  this.connect();
292
284
  },
293
-
294
- lines: {
295
- handler() {
296
- if (this.isFollowing) {
297
- this.$nextTick(() => {
298
- this.follow();
299
- });
300
- }
301
- },
302
- deep: true
303
- }
304
-
305
285
  },
306
286
 
307
287
  beforeUnmount() {
@@ -315,6 +295,35 @@ export default {
315
295
  },
316
296
 
317
297
  methods: {
298
+ onScrollToBottom() {
299
+ this.startFollowing();
300
+ },
301
+
302
+ onMouseWheel(ev) {
303
+ // On scroll up stop following
304
+ if (ev.deltaY < 0) {
305
+ this.stopFollowing();
306
+ }
307
+ },
308
+
309
+ onMouseDown() {
310
+ this.stopFollowing();
311
+ },
312
+
313
+ onMouseUp() {
314
+ const virtualList = this.$refs.virtualList;
315
+
316
+ if (!virtualList) {
317
+ return;
318
+ }
319
+
320
+ const isVirtualListScrolledToBottom = virtualList.getOffset() + virtualList.getClientSize() >= virtualList.getScrollSize();
321
+
322
+ if (isVirtualListScrolledToBottom) {
323
+ this.startFollowing();
324
+ }
325
+ },
326
+
318
327
  openContainerMenu() {
319
328
  this.isContainerMenuOpen = true;
320
329
  },
@@ -451,22 +460,21 @@ export default {
451
460
  if (maxLines && this.lines.length > maxLines) {
452
461
  this.lines = this.lines.slice(-maxLines);
453
462
  }
463
+
464
+ this.$nextTick(() => {
465
+ this.follow();
466
+ });
454
467
  }
455
468
  },
456
469
 
457
- updateFollowing: debounce(function() {
458
- const virtualList = this.$refs.virtualList;
459
-
460
- if (virtualList) {
461
- const scrollSize = virtualList.getScrollSize();
462
- const clientSize = virtualList.getClientSize();
463
- const offset = virtualList.getOffset();
464
-
465
- const distanceFromBottom = scrollSize - clientSize - offset;
470
+ stopFollowing() {
471
+ this.isFollowing = false;
472
+ },
466
473
 
467
- this.isFollowing = distanceFromBottom <= this.scrollThreshold;
468
- }
469
- }, 100),
474
+ startFollowing() {
475
+ this.isFollowing = true;
476
+ this.follow();
477
+ },
470
478
 
471
479
  parseRange(range) {
472
480
  range = `${ range }`.trim().toLowerCase();
@@ -537,9 +545,8 @@ export default {
537
545
  follow() {
538
546
  const virtualList = this.$refs.virtualList;
539
547
 
540
- if (virtualList) {
541
- virtualList.scrollToBottom();
542
- this.isFollowing = true;
548
+ if (virtualList && this.isFollowing) {
549
+ virtualList.scrollToOffset(virtualList.getScrollSize());
543
550
  }
544
551
  },
545
552
 
@@ -607,7 +614,7 @@ export default {
607
614
  :aria-label="t('wm.containerLogs.follow')"
608
615
  :aria-disabled="isFollowing"
609
616
  :disabled="isFollowing"
610
- @click="follow"
617
+ @click="startFollowing"
611
618
  >
612
619
  <t
613
620
  class="wm-btn-large"
@@ -762,7 +769,11 @@ export default {
762
769
  :data-component="logItem"
763
770
  direction="vertical"
764
771
  :keeps="200"
765
- @scroll="updateFollowing"
772
+ :bottom-threshold="200"
773
+ @tobottom="onScrollToBottom"
774
+ @wheel.passive="onMouseWheel"
775
+ @mousedown="onMouseDown"
776
+ @mouseup="onMouseUp"
766
777
  />
767
778
  <template v-if="!filtered.length">
768
779
  <div v-if="search">
@@ -67,13 +67,13 @@ export default {
67
67
  flex-direction: column;
68
68
  }
69
69
  .targets-list-list {
70
- overflow-y: scroll;
70
+ overflow-y: auto;
71
71
  }
72
72
  .link-main{
73
73
  word-spacing: 22px;
74
+ line-height: 17px; // To fit the icon size and make sure it doesnt resize
74
75
  }
75
76
  .link-icon {
76
- position: absolute;
77
77
  margin-left: -14px; // Remove the space of the icon to make it float to accomodate the underline
78
78
  display: none; // Make the icon disappear by default
79
79
  }
@@ -406,7 +406,10 @@ export default {
406
406
  :placeholder="t('fleet.clusterTargets.clusters.byName.placeholder')"
407
407
  @update:value="selectClusters"
408
408
  />
409
- <div class="mmt-6">
409
+ <div
410
+ v-if="!isView || (clusterSelectors && clusterSelectors.length > 0)"
411
+ class="mmt-6"
412
+ >
410
413
  <h4 class="m-0">
411
414
  {{ t('fleet.clusterTargets.clusters.byLabel.title') }}
412
415
  </h4>
@@ -427,6 +430,7 @@ export default {
427
430
  @update:value="updateMatchExpressions(i, $event, selector.key)"
428
431
  />
429
432
  <RcButton
433
+ v-if="!isView"
430
434
  size="small"
431
435
  variant="link"
432
436
  @click="removeMatchExpressions(selector.key)"
@@ -435,6 +439,7 @@ export default {
435
439
  </RcButton>
436
440
  </div>
437
441
  <RcButton
442
+ v-if="!isView"
438
443
  size="small"
439
444
  variant="secondary"
440
445
  class="mmt-4"
@@ -0,0 +1,333 @@
1
+ <script setup>
2
+ import { useStore } from 'vuex';
3
+ import { useI18n } from '@shell/composables/useI18n';
4
+ import { Banner } from '@components/Banner';
5
+ import { LabeledInput } from '@components/Form/LabeledInput';
6
+ import LabeledSelect from '@shell/components/form/LabeledSelect';
7
+ import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthSecret';
8
+ import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
9
+ import UnitInput from '@shell/components/form/UnitInput';
10
+ import FleetOCIStorageSecret from '@shell/components/fleet/FleetOCIStorageSecret.vue';
11
+
12
+ defineProps({
13
+ value: {
14
+ type: Object,
15
+ required: true
16
+ },
17
+ mode: {
18
+ type: String,
19
+ required: true
20
+ },
21
+ isView: {
22
+ type: Boolean,
23
+ default: false
24
+ },
25
+ workspace: {
26
+ type: String,
27
+ required: true
28
+ },
29
+ tlsMode: {
30
+ type: String,
31
+ required: true
32
+ },
33
+ tlsOptions: {
34
+ type: Array,
35
+ required: true
36
+ },
37
+ caBundle: {
38
+ type: String,
39
+ default: null
40
+ },
41
+ isTls: {
42
+ type: Boolean,
43
+ required: true
44
+ },
45
+ displayHelmRepoUrlRegex: {
46
+ type: Boolean,
47
+ required: true
48
+ },
49
+ tempCachedValues: {
50
+ type: Object,
51
+ required: true
52
+ },
53
+ correctDriftEnabled: {
54
+ type: Boolean,
55
+ required: true
56
+ },
57
+ pollingInterval: {
58
+ type: Number,
59
+ required: false,
60
+ default: undefined
61
+ },
62
+ showPollingIntervalWarning: {
63
+ type: Boolean,
64
+ required: true
65
+ },
66
+ specifyOption: {
67
+ type: String,
68
+ required: true
69
+ },
70
+ registerBeforeHook: {
71
+ type: Function,
72
+ required: true
73
+ },
74
+ isGithubDotComRepository: {
75
+ type: Boolean,
76
+ required: true,
77
+ },
78
+ isBasicAuthSelected: {
79
+ type: Boolean,
80
+ required: true,
81
+ }
82
+ });
83
+
84
+ const emit = defineEmits([
85
+ 'update:tls-mode',
86
+ 'update:ca-bundle',
87
+ 'update:auth',
88
+ 'update:cached-auth',
89
+ 'update:correct-drift',
90
+ 'update:polling-enabled',
91
+ 'update:polling-interval',
92
+ 'update:validate-polling-interval',
93
+ ]);
94
+
95
+ const store = useStore();
96
+ const { t } = useI18n(store);
97
+
98
+ const updateTlsMode = (event) => {
99
+ emit('update:tls-mode', event);
100
+ };
101
+
102
+ const updateCaBundle = (value) => {
103
+ emit('update:ca-bundle', value);
104
+ };
105
+
106
+ const updateAuth = (val, key) => {
107
+ emit('update:auth', { value: val, key });
108
+ };
109
+
110
+ const updateCachedAuthVal = (val, key) => {
111
+ emit('update:cached-auth', { value: val, key });
112
+ };
113
+
114
+ const updateCorrectDrift = (value) => {
115
+ emit('update:correct-drift', value);
116
+ };
117
+
118
+ const enablePolling = (value) => {
119
+ emit('update:polling-enabled', value);
120
+ };
121
+
122
+ const updatePollingInterval = (value) => {
123
+ emit('update:polling-interval', value);
124
+ };
125
+
126
+ const validatePollingInterval = () => {
127
+ emit('update:validate-polling-interval');
128
+ };
129
+ </script>
130
+
131
+ <template>
132
+ <div>
133
+ <Banner
134
+ v-if="!isView"
135
+ color="info"
136
+ label-key="fleet.gitRepo.add.steps.advanced.info"
137
+ data-testid="gitrepo-advanced-info"
138
+ />
139
+
140
+ <h2>{{ t('fleet.gitRepo.auth.title') }}</h2>
141
+ <Banner
142
+ v-if="isGithubDotComRepository && isBasicAuthSelected"
143
+ color="warning"
144
+ label-key="fleet.gitRepo.auth.githubdotcomPasswordBanner"
145
+ data-testid="gitrepo-githubdotcom-password-warning"
146
+ />
147
+ <SelectOrCreateAuthSecret
148
+ data-testid="gitrepo-git-auth"
149
+ :value="value.spec.clientSecretName"
150
+ :register-before-hook="registerBeforeHook"
151
+ :namespace="value.metadata.namespace"
152
+ :delegate-create-to-parent="true"
153
+ in-store="management"
154
+ :pre-select="tempCachedValues.clientSecretName"
155
+ :mode="mode"
156
+ generate-name="gitrepo-auth-"
157
+ label-key="fleet.gitRepo.auth.git"
158
+ :cache-secrets="true"
159
+ :show-ssh-known-hosts="true"
160
+ :is-github-dot-com-repository="isGithubDotComRepository"
161
+ @update:value="updateAuth($event, 'clientSecretName')"
162
+ @inputauthval="updateCachedAuthVal($event, 'clientSecretName')"
163
+ />
164
+ <SelectOrCreateAuthSecret
165
+ data-testid="gitrepo-helm-auth"
166
+ :value="value.spec.helmSecretName"
167
+ :register-before-hook="registerBeforeHook"
168
+ :namespace="value.metadata.namespace"
169
+ :delegate-create-to-parent="true"
170
+ in-store="management"
171
+ :mode="mode"
172
+ generate-name="helmrepo-auth-"
173
+ label-key="fleet.gitRepo.auth.helm"
174
+ :pre-select="tempCachedValues.helmSecretName"
175
+ :cache-secrets="true"
176
+ :show-ssh-known-hosts="true"
177
+ @update:value="updateAuth($event, 'helmSecretName')"
178
+ @inputauthval="updateCachedAuthVal($event, 'helmSecretName')"
179
+ />
180
+
181
+ <div
182
+ v-if="displayHelmRepoUrlRegex"
183
+ class="row mt-20"
184
+ >
185
+ <div
186
+ class="col span-6"
187
+ data-testid="gitrepo-helm-repo-url-regex"
188
+ >
189
+ <LabeledInput
190
+ v-model:value="value.spec.helmRepoURLRegex"
191
+ :mode="mode"
192
+ label-key="fleet.gitRepo.helmRepoURLRegex"
193
+ />
194
+ </div>
195
+ </div>
196
+
197
+ <template v-if="isTls">
198
+ <div class="row mt-20">
199
+ <div class="col span-6">
200
+ <LabeledSelect
201
+ :label="t('fleet.gitRepo.tls.label')"
202
+ :mode="mode"
203
+ :value="tlsMode"
204
+ :options="tlsOptions"
205
+ @update:value="updateTlsMode($event)"
206
+ />
207
+ </div>
208
+ <div
209
+ v-if="tlsMode === specifyOption"
210
+ class="col span-6"
211
+ >
212
+ <LabeledInput
213
+ :value="caBundle"
214
+ :mode="mode"
215
+ type="multiline"
216
+ label-key="fleet.gitRepo.caBundle.label"
217
+ placeholder-key="fleet.gitRepo.caBundle.placeholder"
218
+ @update:value="updateCaBundle"
219
+ />
220
+ </div>
221
+ </div>
222
+ </template>
223
+ <div class="spacer" />
224
+
225
+ <h2>
226
+ {{ t('fleet.gitRepo.ociStorageSecret.title') }}
227
+ </h2>
228
+ <div class="row mt-20">
229
+ <div class="col span-6">
230
+ <FleetOCIStorageSecret
231
+ :secret="value.spec.ociRegistrySecret"
232
+ :workspace="workspace"
233
+ :mode="mode"
234
+ @update:value="value.spec.ociRegistrySecret=$event"
235
+ />
236
+ </div>
237
+ </div>
238
+ <div class="spacer" />
239
+
240
+ <h2>
241
+ {{ t('fleet.gitRepo.resources.label') }}
242
+ </h2>
243
+ <div class="resource-handling">
244
+ <Checkbox
245
+ :value="correctDriftEnabled"
246
+ :tooltip="t('fleet.gitRepo.resources.correctDriftTooltip')"
247
+ data-testid="gitRepo-correctDrift-checkbox"
248
+ class="check"
249
+ type="checkbox"
250
+ label-key="fleet.gitRepo.resources.correctDrift"
251
+ :mode="mode"
252
+ @update:value="updateCorrectDrift"
253
+ />
254
+ <Checkbox
255
+ v-model:value="value.spec.keepResources"
256
+ :tooltip="t('fleet.gitRepo.resources.keepResourcesTooltip')"
257
+ data-testid="gitRepo-keepResources-checkbox"
258
+ class="check"
259
+ type="checkbox"
260
+ label-key="fleet.gitRepo.resources.keepResources"
261
+ :mode="mode"
262
+ />
263
+ </div>
264
+
265
+ <div class="spacer" />
266
+ <h2>
267
+ {{ t('fleet.gitRepo.polling.label') }}
268
+ </h2>
269
+ <div class="row polling">
270
+ <div class="col span-6">
271
+ <Checkbox
272
+ :value="value.isPollingEnabled"
273
+ data-testid="gitRepo-enablePolling-checkbox"
274
+ class="check"
275
+ type="checkbox"
276
+ label-key="fleet.gitRepo.polling.enable"
277
+ :mode="mode"
278
+ @update:value="enablePolling"
279
+ />
280
+ </div>
281
+ <template v-if="value.isPollingEnabled">
282
+ <div class="col">
283
+ <Banner
284
+ v-if="showPollingIntervalWarning"
285
+ color="warning"
286
+ label-key="fleet.gitRepo.polling.pollingInterval.minimumValueWarning"
287
+ data-testid="gitRepo-pollingInterval-minimumValueWarning"
288
+ />
289
+ <Banner
290
+ v-if="value.isWebhookConfigured"
291
+ color="warning"
292
+ label-key="fleet.gitRepo.polling.pollingInterval.webhookWarning"
293
+ data-testid="gitRepo-pollingInterval-webhookWarning"
294
+ />
295
+ </div>
296
+ <div class="col span-6">
297
+ <UnitInput
298
+ :value="pollingInterval"
299
+ data-testid="gitRepo-pollingInterval-input"
300
+ min="1"
301
+ :suffix="t('suffix.seconds', { count: pollingInterval })"
302
+ :label="t('fleet.gitRepo.polling.pollingInterval.label')"
303
+ :mode="mode"
304
+ tooltip-key="fleet.gitRepo.polling.pollingInterval.tooltip"
305
+ @update:value="updatePollingInterval"
306
+ @blur.capture="validatePollingInterval"
307
+ />
308
+ </div>
309
+ </template>
310
+ </div>
311
+ </div>
312
+ </template>
313
+
314
+ <style lang="scss" scoped>
315
+ .spacer {
316
+ padding: 30px 0 0 0;
317
+ }
318
+ :deep() .select-or-create-auth-secret {
319
+ .row {
320
+ margin-top: 10px !important;
321
+ }
322
+ }
323
+ .resource-handling {
324
+ display: flex;
325
+ flex-direction: column;
326
+ gap: 5px;
327
+ }
328
+ .polling {
329
+ display: flex;
330
+ flex-direction: column;
331
+ gap: 5px;
332
+ }
333
+ </style>