@rancher/shell 3.0.7 → 3.0.8-rc.2

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 (123) hide show
  1. package/assets/images/vendor/githubapp.svg +13 -0
  2. package/assets/styles/base/_typography.scss +1 -1
  3. package/assets/styles/global/_layout.scss +21 -35
  4. package/assets/styles/themes/_modern.scss +5 -5
  5. package/assets/translations/en-us.yaml +102 -17
  6. package/assets/translations/zh-hans.yaml +0 -4
  7. package/components/EmberPage.vue +1 -1
  8. package/components/Inactivity.vue +222 -106
  9. package/components/InstallHelmCharts.vue +2 -2
  10. package/components/Resource/Detail/CopyToClipboard.vue +1 -1
  11. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
  12. package/components/Resource/Detail/TitleBar/index.vue +10 -6
  13. package/components/ResourceDetail/index.vue +4 -1
  14. package/components/SortableTable/index.vue +18 -2
  15. package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
  16. package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
  17. package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
  18. package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
  19. package/components/fleet/FleetConfigMapSelector.vue +117 -0
  20. package/components/fleet/FleetSecretSelector.vue +127 -0
  21. package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
  22. package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
  23. package/components/form/FileImageSelector.vue +13 -4
  24. package/components/form/FileSelector.vue +11 -2
  25. package/components/form/ResourceLabeledSelect.vue +1 -0
  26. package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
  27. package/components/nav/Header.vue +34 -13
  28. package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
  29. package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
  30. package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
  31. package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
  32. package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
  33. package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
  34. package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
  35. package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
  36. package/components/nav/WindowManager/constants.ts +23 -0
  37. package/components/nav/WindowManager/index.vue +61 -575
  38. package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
  39. package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
  40. package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
  41. package/components/templates/default.vue +4 -40
  42. package/components/templates/home.vue +31 -5
  43. package/config/product/auth.js +1 -0
  44. package/config/query-params.js +1 -0
  45. package/config/settings.ts +8 -1
  46. package/config/store.js +4 -2
  47. package/config/types.js +2 -0
  48. package/detail/pod.vue +1 -0
  49. package/dialog/AddonConfigConfirmationDialog.vue +45 -1
  50. package/directives/ui-context.ts +97 -0
  51. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
  52. package/edit/auth/AuthProviderWarningBanners.vue +14 -1
  53. package/edit/auth/github-app-steps.vue +97 -0
  54. package/edit/auth/github-steps.vue +75 -0
  55. package/edit/auth/github.vue +94 -65
  56. package/edit/fleet.cattle.io.helmop.vue +51 -2
  57. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
  58. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
  59. package/edit/provisioning.cattle.io.cluster/rke2.vue +56 -9
  60. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
  61. package/initialize/install-directives.js +2 -0
  62. package/list/projectsecret.vue +1 -1
  63. package/machine-config/azure.vue +1 -1
  64. package/mixins/chart.js +1 -1
  65. package/models/__tests__/chart.test.ts +17 -9
  66. package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
  67. package/models/catalog.cattle.io.app.js +1 -1
  68. package/models/chart.js +3 -1
  69. package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
  70. package/models/management.cattle.io.authconfig.js +1 -0
  71. package/package.json +2 -2
  72. package/pages/auth/login.vue +5 -2
  73. package/pages/auth/verify.vue +1 -1
  74. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
  75. package/pages/c/_cluster/apps/charts/chart.vue +2 -2
  76. package/pages/c/_cluster/explorer/EventsTable.vue +89 -3
  77. package/pages/c/_cluster/explorer/tools/index.vue +3 -3
  78. package/pages/c/_cluster/settings/performance.vue +12 -25
  79. package/pages/home.vue +313 -12
  80. package/plugins/axios.js +2 -1
  81. package/plugins/dashboard-store/actions.js +1 -1
  82. package/plugins/dashboard-store/resource-class.js +17 -2
  83. package/plugins/steve/steve-pagination-utils.ts +2 -2
  84. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
  85. package/scripts/extension/publish +1 -1
  86. package/store/auth.js +8 -3
  87. package/store/aws.js +8 -6
  88. package/store/features.js +1 -0
  89. package/store/index.js +9 -3
  90. package/store/prefs.js +6 -0
  91. package/store/ui-context.ts +86 -0
  92. package/store/wm.ts +244 -0
  93. package/types/kube/kube-api.ts +2 -1
  94. package/types/rancher/index.d.ts +1 -0
  95. package/types/resources/settings.d.ts +29 -7
  96. package/types/shell/index.d.ts +59 -0
  97. package/types/window-manager.ts +22 -0
  98. package/utils/__tests__/cluster.test.ts +379 -1
  99. package/utils/cluster.js +157 -3
  100. package/utils/dynamic-content/__tests__/config.test.ts +187 -0
  101. package/utils/dynamic-content/__tests__/index.test.ts +390 -0
  102. package/utils/dynamic-content/__tests__/info.test.ts +263 -0
  103. package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
  104. package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
  105. package/utils/dynamic-content/__tests__/util.test.ts +235 -0
  106. package/utils/dynamic-content/config.ts +55 -0
  107. package/utils/dynamic-content/index.ts +273 -0
  108. package/utils/dynamic-content/info.ts +219 -0
  109. package/utils/dynamic-content/new-release.ts +126 -0
  110. package/utils/dynamic-content/support-notice.ts +169 -0
  111. package/utils/dynamic-content/types.d.ts +101 -0
  112. package/utils/dynamic-content/util.ts +122 -0
  113. package/utils/dynamic-importer.js +2 -2
  114. package/utils/inactivity.ts +104 -0
  115. package/utils/pagination-utils.ts +19 -4
  116. package/utils/release-notes.ts +1 -1
  117. package/assets/images/icons/document.svg +0 -3
  118. package/store/wm.js +0 -95
  119. /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
  120. /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
  121. /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
  122. /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
  123. /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
@@ -0,0 +1,265 @@
1
+ <script setup lang="ts">
2
+ import { PropType } from 'vue';
3
+ import { BOTTOM } from '@shell/utils/position';
4
+ import { Position } from '@shell/types/window-manager';
5
+ import TabBodyContainer from './TabBodyContainer.vue';
6
+ import usePanelHandler from '../composables/usePanelHandler';
7
+
8
+ const props = defineProps({
9
+ position: {
10
+ type: String as PropType<Position>,
11
+ default: BOTTOM,
12
+ },
13
+ });
14
+
15
+ const {
16
+ tabs,
17
+ activeTab,
18
+ isTabsHeaderEnabled,
19
+ dragOverPositionsActive,
20
+ dragOverTabBarActive,
21
+ setTabActive,
22
+ onTabReady,
23
+ onTabClose,
24
+ mouseResizeYStart,
25
+ keyboardResizeY,
26
+ onTabBarDragOver,
27
+ onTabBarDragLeave,
28
+ onTabBarDrop,
29
+ onDragPositionStart,
30
+ onDragPositionEnd,
31
+ lockedPosition,
32
+ } = usePanelHandler({ position: props.position });
33
+ </script>
34
+
35
+ <template>
36
+ <div
37
+ id="horizontal-window-manager"
38
+ data-testid="horizontal-window-manager"
39
+ class="horizontal-window-manager wm"
40
+ :class="{
41
+ 'drag-start': dragOverPositionsActive,
42
+ 'drag-end': !dragOverPositionsActive,
43
+ 'tabs-header-enabled': isTabsHeaderEnabled,
44
+ }"
45
+ >
46
+ <div
47
+ v-if="isTabsHeaderEnabled"
48
+ :class="['tabs', { 'tab-bar-highlight': dragOverTabBarActive }]"
49
+ role="tablist"
50
+ @dragover="onTabBarDragOver"
51
+ @dragleave="onTabBarDragLeave"
52
+ @drop="onTabBarDrop"
53
+ >
54
+ <div
55
+ v-for="(tab, i) in tabs"
56
+ :key="i"
57
+ class="tab"
58
+ :class="{
59
+ 'active': tab.id === activeTab[props.position],
60
+ 'draggable': !lockedPosition,
61
+ }"
62
+ :draggable="tab.id === activeTab[props.position] && !lockedPosition"
63
+ role="tab"
64
+ :aria-selected="tab.id === activeTab[props.position]"
65
+ :aria-label="tab.label"
66
+ :aria-controls="`panel-${tab.id}`"
67
+ tabindex="0"
68
+ @click="setTabActive({ position: props.position, id: tab.id })"
69
+ @keyup.enter.space="setTabActive({ position: props.position, id: tab.id })"
70
+ @dragstart="onDragPositionStart({ event: $event, tab })"
71
+ @dragend="onDragPositionEnd({ event: $event, tab })"
72
+ >
73
+ <i
74
+ v-if="tab.icon"
75
+ class="icon"
76
+ :class="{
77
+ ['icon-'+ tab.icon]: true,
78
+ }"
79
+ :alt="t('wm.tabIcon')"
80
+ />
81
+ <span
82
+ class="tab-label"
83
+ >
84
+ {{ tab.label }}
85
+ </span>
86
+ <i
87
+ data-testid="wm-tab-close-button"
88
+ class="closer icon icon-x wm-closer-button"
89
+ :alt="t('wm.closeTab', { tabId: tab.label })"
90
+ tabindex="0"
91
+ :aria-label="t('wm.closeTab', { tabId: tab.id })"
92
+ @click.stop="onTabClose(tab.id)"
93
+ @keyup.enter.space.stop="onTabClose(tab.id)"
94
+ />
95
+ </div>
96
+ <div
97
+ class="resizer resizer-y"
98
+ role="button"
99
+ tabindex="0"
100
+ :aria-label="t('wm.resize', {arrow1: 'up', arrow2: 'down'})"
101
+ aria-expanded="true"
102
+ @mousedown.prevent.stop="mouseResizeYStart($event)"
103
+ @touchstart.prevent.stop="mouseResizeYStart($event)"
104
+ @keyup.up.prevent.stop="keyboardResizeY(true)"
105
+ @keyup.down.prevent.stop="keyboardResizeY(false)"
106
+ >
107
+ <i
108
+ class="icon icon-sort"
109
+ :alt="t('wm.resize', {arrow1: 'up', arrow2: 'down'})"
110
+ />
111
+ </div>
112
+ </div>
113
+ <TabBodyContainer
114
+ v-for="tab in tabs"
115
+ v-show="tab.id === activeTab[props.position]"
116
+ :id="tab.id"
117
+ :key="`${ props.position }-${ tab.id }`"
118
+ :position="props.position"
119
+ @ready="onTabReady({ tab, containerId: $event })"
120
+ />
121
+ </div>
122
+ </template>
123
+
124
+ <style lang="scss" scoped>
125
+ .horizontal-window-manager {
126
+ display: grid;
127
+ // z-index: var(--drag-area-wm-z-index);
128
+
129
+ grid-template-areas:
130
+ "body";
131
+ grid-template-rows: auto;
132
+
133
+ &.tabs-header-enabled {
134
+ grid-template-areas:
135
+ "tabs"
136
+ "body";
137
+
138
+ grid-template-rows: var(--wm-tab-height) auto;
139
+ }
140
+
141
+ &.vm {
142
+ height: var(--wm-height, 0);
143
+ }
144
+
145
+ .tabs, .body {
146
+ max-width: 100%;
147
+ }
148
+
149
+ .tabs {
150
+ grid-area: tabs;
151
+ background-color: var(--wm-tabs-bg);
152
+ border-top: 1px solid var(--wm-border);
153
+ border-bottom: 1px solid var(--wm-border);
154
+
155
+ display: flex;
156
+ align-content: stretch;
157
+
158
+ .tab {
159
+ cursor: pointer;
160
+ user-select: none;
161
+ border-top: 1px solid var(--wm-border);
162
+ border-right: 1px solid var(--wm-border);
163
+ border-left: 1px solid var(--wm-border);
164
+ padding: 5px 10px;
165
+ overflow: hidden;
166
+ text-overflow: ellipsis;
167
+ margin: 0;
168
+ display: flex;
169
+ min-width: 0;
170
+
171
+ .tab-label {
172
+ overflow: hidden;
173
+ text-overflow: ellipsis;
174
+ }
175
+
176
+ &.active {
177
+ position: relative;
178
+ background-color: var(--wm-body-bg);
179
+ outline: 1px solid var(--wm-body-bg);
180
+ z-index: 1;
181
+ }
182
+
183
+ &.draggable {
184
+ cursor: grab;
185
+ }
186
+
187
+ &:focus-visible {
188
+ @include focus-outline;
189
+ outline-offset: -3px;
190
+ }
191
+
192
+ .closer {
193
+ margin-left: 5px;
194
+ border: 1px solid var(--body-text);
195
+ border-radius: var(--border-radius);
196
+ line-height: 12px;
197
+ font-size: 10px;
198
+ width: 14px;
199
+ align-self: center;
200
+ display: flex;
201
+ justify-content: center;
202
+ cursor: pointer;
203
+
204
+ &:hover {
205
+ border-color: var(--link-border);
206
+ color: var(--link-border);
207
+ }
208
+
209
+ &:focus-visible {
210
+ @include focus-outline;
211
+ outline-offset: 1px;
212
+ }
213
+ }
214
+ }
215
+
216
+ .resizer {
217
+ width: var(--wm-tab-height);
218
+ padding: 0 5px;
219
+ margin: 0 0 0 1px;
220
+ text-align: center;
221
+ border-left: 1px solid var(--wm-border);
222
+ border-right: 1px solid var(--wm-border);
223
+ line-height: var(--wm-tab-height);
224
+ height: calc(var(--wm-tab-height) + 1px);
225
+ flex-grow: 0;
226
+
227
+ &:hover {
228
+ background-color: var(--wm-closer-hover-bg);
229
+ }
230
+ }
231
+
232
+ .resizer-y {
233
+ cursor: ns-resize;
234
+ }
235
+ }
236
+
237
+ .body {
238
+ grid-area: body;
239
+ background-color: var(--wm-body-bg);
240
+ display: none;
241
+ overflow: hidden;
242
+
243
+ &.active {
244
+ display: block;
245
+ height: 100%;
246
+ }
247
+ }
248
+ }
249
+
250
+ .drag-start {
251
+ z-index: var(--drag-area-wm-z-index);
252
+ opacity: 0.5;
253
+ transition: opacity .3s ease;
254
+ }
255
+
256
+ .drag-end {
257
+ opacity: 1;
258
+ }
259
+
260
+ .tab-bar-highlight {
261
+ transition: height .5s ease;
262
+ background-image: linear-gradient(to top, var(--drag-over-inner-bg), var(--drag-over-outer-bg));
263
+ border-style: dashed hidden hidden hidden;
264
+ }
265
+ </style>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <div
3
+ :id="contentId"
4
+ class="body active teleport-target"
5
+ role="tabpanel"
6
+ />
7
+ </template>
8
+
9
+ <script setup>
10
+ import { onMounted, defineProps, defineEmits } from 'vue';
11
+
12
+ /**
13
+ * This component serves as a container for the body of a tab within a window manager panel.
14
+ *
15
+ * Props:
16
+ * - id: The unique identifier for the tab.
17
+ * - position: The position of the panel (e.g., left, right, bottom).
18
+ *
19
+ * Behavior:
20
+ * - On mounting, it emits a 'ready' event with the generated content ID for the tab body.
21
+ * This is necessary for teleporting the tab content to the correct location in the DOM, ONLY when the body container DIV is mounted.
22
+ */
23
+ const props = defineProps({
24
+ id: {
25
+ type: String,
26
+ required: true
27
+ },
28
+ position: {
29
+ type: String,
30
+ required: true
31
+ }
32
+ });
33
+
34
+ const emit = defineEmits(['ready']);
35
+
36
+ const contentId = `wm-panel-body-${ props.position }-${ props.id.replace(/[^a-zA-Z0-9_-]/g, '-') }`;
37
+
38
+ onMounted(() => emit('ready', contentId));
39
+ </script>
@@ -0,0 +1,308 @@
1
+ <script setup lang="ts">
2
+ import { RIGHT, LEFT } from '@shell/utils/position';
3
+ import { PropType } from 'vue';
4
+ import { Position } from '@shell/types/window-manager';
5
+ import TabBodyContainer from './TabBodyContainer.vue';
6
+ import usePanelHandler from '../composables/usePanelHandler';
7
+
8
+ const props = defineProps({
9
+ position: {
10
+ type: String as PropType<Position>,
11
+ default: RIGHT,
12
+ },
13
+ });
14
+
15
+ const {
16
+ tabs,
17
+ activeTab,
18
+ isTabsHeaderEnabled,
19
+ dragOverPositionsActive,
20
+ dragOverTabBarActive,
21
+ setTabActive,
22
+ onTabReady,
23
+ onTabClose,
24
+ mouseResizeXStart,
25
+ keyboardResizeX,
26
+ lockedPosition,
27
+ onTabBarDragOver,
28
+ onTabBarDragLeave,
29
+ onTabBarDrop,
30
+ onDragPositionStart,
31
+ onDragPositionEnd,
32
+ } = usePanelHandler({ position: props.position });
33
+ </script>
34
+
35
+ <template>
36
+ <div
37
+ id="vertical-window-manager"
38
+ data-testid="vertical-window-manager"
39
+ class="vertical-window-manager"
40
+ :class="{
41
+ 'wm-vr': props.position === RIGHT,
42
+ 'wm-vl': props.position === LEFT,
43
+ 'drag-start': dragOverPositionsActive,
44
+ 'drag-end': !dragOverPositionsActive,
45
+ 'tabs-header-enabled': isTabsHeaderEnabled,
46
+ }"
47
+ >
48
+ <div
49
+ v-if="isTabsHeaderEnabled"
50
+ :class="[
51
+ 'tabs',
52
+ {
53
+ 'tab-bar-highlight': dragOverTabBarActive,
54
+ 'resizer-left': props.position === LEFT,
55
+ }
56
+ ]"
57
+ role="tablist"
58
+ @dragover="onTabBarDragOver"
59
+ @dragleave="onTabBarDragLeave"
60
+ @drop="onTabBarDrop"
61
+ >
62
+ <div
63
+ v-if="props.position === RIGHT"
64
+ class="resizer resizer-x"
65
+ role="button"
66
+ tabindex="0"
67
+ :aria-label="t('wm.resize', {arrow1: 'left', arrow2: 'right'})"
68
+ aria-expanded="true"
69
+ @mousedown.prevent.stop="mouseResizeXStart($event)"
70
+ @touchstart.prevent.stop="mouseResizeXStart($event)"
71
+ @keyup.left.prevent.stop="keyboardResizeX(true)"
72
+ @keyup.right.prevent.stop="keyboardResizeX(false)"
73
+ >
74
+ <i
75
+ class="icon icon-code"
76
+ :alt="t('wm.resize', {arrow1: 'left', arrow2: 'right'})"
77
+ />
78
+ </div>
79
+ <div
80
+ v-for="(tab, i) in tabs"
81
+ :key="i"
82
+ class="tab"
83
+ :class="{
84
+ 'active': tab.id === activeTab[props.position],
85
+ 'draggable': !lockedPosition,
86
+ }"
87
+ :draggable="tab.id === activeTab[props.position] && !lockedPosition"
88
+ role="tab"
89
+ :aria-selected="tab.id === activeTab[props.position]"
90
+ :aria-label="tab.label"
91
+ :aria-controls="`panel-${tab.id}`"
92
+ tabindex="0"
93
+ @click="setTabActive({ position: props.position, id: tab.id })"
94
+ @keyup.enter.space="setTabActive({ position: props.position, id: tab.id })"
95
+ @dragstart="onDragPositionStart({ event: $event, tab })"
96
+ @dragend="onDragPositionEnd({ event: $event, tab })"
97
+ >
98
+ <i
99
+ v-if="tab.icon"
100
+ class="icon"
101
+ :class="{
102
+ ['icon-'+ tab.icon]: true,
103
+ }"
104
+ :alt="t('wm.tabIcon')"
105
+ />
106
+ <span
107
+ class="tab-label"
108
+ >
109
+ {{ tab.label }}
110
+ </span>
111
+ <i
112
+ data-testid="wm-tab-close-button"
113
+ class="closer icon icon-x wm-closer-button"
114
+ :alt="t('wm.closeTab', { tabId: tab.label })"
115
+ tabindex="0"
116
+ :aria-label="t('wm.closeTab', { tabId: tab.id })"
117
+ @click.stop="onTabClose(tab.id)"
118
+ @keyup.enter.space.stop="onTabClose(tab.id)"
119
+ />
120
+ </div>
121
+ <div
122
+ v-if="props.position === LEFT"
123
+ class="resizer resizer-x resizer-align-right"
124
+ role="button"
125
+ tabindex="0"
126
+ :aria-label="t('wm.resize', {arrow1: 'left', arrow2: 'right'})"
127
+ aria-expanded="true"
128
+ @mousedown.prevent.stop="mouseResizeXStart($event)"
129
+ @touchstart.prevent.stop="mouseResizeXStart($event)"
130
+ @keyup.left.prevent.stop="keyboardResizeX(true)"
131
+ @keyup.right.prevent.stop="keyboardResizeX(false)"
132
+ >
133
+ <i
134
+ class="icon icon-code"
135
+ :alt="t('wm.resize', {arrow1: 'left', arrow2: 'right'})"
136
+ />
137
+ </div>
138
+ </div>
139
+ <TabBodyContainer
140
+ v-for="tab in tabs"
141
+ v-show="tab.id === activeTab[props.position]"
142
+ :id="tab.id"
143
+ :key="`${ props.position }-${ tab.id }`"
144
+ :position="props.position"
145
+ @ready="onTabReady({ tab, containerId: $event })"
146
+ />
147
+ </div>
148
+ </template>
149
+
150
+ <style lang="scss" scoped>
151
+ .vertical-window-manager {
152
+ display: grid;
153
+ // z-index: var(--drag-area-wm-z-index);
154
+
155
+ grid-template-areas:
156
+ "body";
157
+ grid-template-rows: auto;
158
+
159
+ &.tabs-header-enabled {
160
+ grid-template-areas:
161
+ "tabs"
162
+ "body";
163
+
164
+ grid-template-rows: var(--wm-tab-height) auto;
165
+ }
166
+
167
+ &.wm-vr {
168
+ width: var(--wm-vr-width, 0);
169
+ border-left: var(--nav-border-size) solid var(--nav-border);
170
+ }
171
+
172
+ &.wm-vl {
173
+ width: var(--wm-vl-width, 0);
174
+ border-right: var(--nav-border-size) solid var(--nav-border);
175
+ }
176
+
177
+ .tabs, .body {
178
+ max-width: 100%;
179
+ }
180
+
181
+ .tabs {
182
+ grid-area: tabs;
183
+ background-color: var(--wm-tabs-bg);
184
+ border-top: 1px solid var(--wm-border);
185
+ border-bottom: 1px solid var(--wm-border);
186
+
187
+ display: flex;
188
+ align-content: stretch;
189
+
190
+ .tab {
191
+ cursor: pointer;
192
+ user-select: none;
193
+ border-top: 1px solid var(--wm-border);
194
+ border-right: 1px solid var(--wm-border);
195
+ border-left: 1px solid var(--wm-border);
196
+ padding: 5px 10px;
197
+ overflow: hidden;
198
+ text-overflow: ellipsis;
199
+ margin: 0;
200
+ display: flex;
201
+ min-width: 0;
202
+
203
+ .tab-label {
204
+ overflow: hidden;
205
+ text-overflow: ellipsis;
206
+ }
207
+
208
+ &.active {
209
+ position: relative;
210
+ background-color: var(--wm-body-bg);
211
+ outline: 1px solid var(--wm-body-bg);
212
+ z-index: 1;
213
+ }
214
+
215
+ &.draggable {
216
+ cursor: grab;
217
+ }
218
+
219
+ &:focus-visible {
220
+ @include focus-outline;
221
+ outline-offset: -3px;
222
+ }
223
+
224
+ .closer {
225
+ margin-left: 5px;
226
+ border: 1px solid var(--body-text);
227
+ border-radius: var(--border-radius);
228
+ line-height: 12px;
229
+ font-size: 10px;
230
+ width: 14px;
231
+ align-self: center;
232
+ display: flex;
233
+ justify-content: center;
234
+ cursor: pointer;
235
+
236
+ &:hover {
237
+ border-color: var(--link-border);
238
+ color: var(--link-border);
239
+ }
240
+
241
+ &:focus-visible {
242
+ @include focus-outline;
243
+ outline-offset: 1px;
244
+ }
245
+ }
246
+ }
247
+
248
+ .resizer {
249
+ width: var(--wm-tab-height);
250
+ padding: 0 5px;
251
+ margin: 0 0 0 1px;
252
+ text-align: center;
253
+ border-left: 1px solid var(--wm-border);
254
+ border-right: 1px solid var(--wm-border);
255
+ line-height: var(--wm-tab-height);
256
+ height: calc(var(--wm-tab-height) + 1px);
257
+ flex-grow: 0;
258
+
259
+ &:hover {
260
+ background-color: var(--wm-closer-hover-bg);
261
+ }
262
+ }
263
+
264
+ .resizer-x {
265
+ cursor: col-resize;
266
+ }
267
+
268
+ .resizer-align-right {
269
+ margin-left: auto;
270
+ }
271
+
272
+ &.resizer-left {
273
+ display: flex;
274
+ flex-direction: row;
275
+ justify-content: space-between;
276
+ }
277
+ }
278
+
279
+ .body {
280
+ grid-area: body;
281
+ background-color: var(--wm-body-bg);
282
+ display: none;
283
+ overflow: hidden;
284
+
285
+ &.active {
286
+ display: block;
287
+ height: 100%;
288
+ }
289
+ }
290
+ }
291
+
292
+ .drag-start {
293
+ z-index: var(--drag-area-wm-z-index);
294
+ opacity: 0.5;
295
+ transition: opacity .3s ease;
296
+ }
297
+
298
+ .drag-end {
299
+ opacity: 1;
300
+ }
301
+
302
+ .tab-bar-highlight {
303
+ transition: height .5s ease;
304
+ background-image: linear-gradient(to top, var(--drag-over-inner-bg), var(--drag-over-outer-bg));
305
+ border-style: dashed hidden hidden hidden;
306
+ }
307
+
308
+ </style>
@@ -19,14 +19,13 @@ import Brand from '@shell/mixins/brand';
19
19
  import FixedBanner from '@shell/components/FixedBanner';
20
20
  import AwsComplianceBanner from '@shell/components/AwsComplianceBanner';
21
21
  import AzureWarning from '@shell/components/auth/AzureWarning';
22
- import DraggableZone from '@shell/components/DraggableZone';
23
22
  import { MANAGEMENT } from '@shell/config/types';
24
23
  import { markSeenReleaseNotes } from '@shell/utils/version';
25
24
  import PageHeaderActions from '@shell/mixins/page-actions';
26
25
  import BrowserTabVisibility from '@shell/mixins/browser-tab-visibility';
27
26
  import { getClusterFromRoute, getProductFromRoute } from '@shell/utils/router';
28
- import { BOTTOM } from '@shell/utils/position';
29
27
  import SideNav from '@shell/components/SideNav';
28
+ import { Layout } from '@shell/types/window-manager';
30
29
 
31
30
  const SET_LOGIN_ACTION = 'set-as-login';
32
31
 
@@ -45,7 +44,6 @@ export default {
45
44
  FixedBanner,
46
45
  AwsComplianceBanner,
47
46
  AzureWarning,
48
- DraggableZone,
49
47
  Inactivity,
50
48
  SideNav,
51
49
  },
@@ -55,11 +53,9 @@ export default {
55
53
  // Note - This will not run on route change
56
54
  data() {
57
55
  return {
56
+ layout: Layout.default,
58
57
  noLocaleShortcut: process.env.dev || false,
59
58
  wantNavSync: false,
60
- unwatchPin: undefined,
61
- wmPin: null,
62
- draggable: false,
63
59
  };
64
60
  },
65
61
 
@@ -108,25 +104,6 @@ export default {
108
104
  return this.clusterReady &&
109
105
  this.clusterId === getClusterFromRoute(this.$route) && routeReady;
110
106
  },
111
-
112
- pinClass() {
113
- return `pin-${ this.wmPin }`;
114
- },
115
-
116
- },
117
-
118
- mounted() {
119
- this.wmPin = window.localStorage.getItem('wm-pin') || BOTTOM;
120
-
121
- // two-way binding this.wmPin <-> draggableZone.pin
122
- this.$refs.draggableZone.pin = this.wmPin;
123
- this.unwatchPin = this.$watch('$refs.draggableZone.pin', (pin) => {
124
- this.wmPin = pin;
125
- });
126
- },
127
-
128
- unmounted() {
129
- this.unwatchPin();
130
107
  },
131
108
 
132
109
  methods: {
@@ -190,7 +167,7 @@ export default {
190
167
  <div
191
168
  v-if="managementReady"
192
169
  class="dashboard-content"
193
- :class="{[pinClass]: true, 'dashboard-padding-left': showTopLevelMenu}"
170
+ :class="{'dashboard-padding-left': showTopLevelMenu}"
194
171
  >
195
172
  <Header />
196
173
  <SideNav
@@ -245,24 +222,11 @@ export default {
245
222
  class="outlet"
246
223
  />
247
224
  </main>
248
- <div
249
- v-if="$refs.draggableZone"
250
- class="wm"
251
- :class="{
252
- 'drag-end': !$refs.draggableZone.drag.active,
253
- 'drag-start': $refs.draggableZone.drag.active,
254
- }"
255
- :draggable="draggable"
256
- @dragstart="$refs.draggableZone.onDragStart($event)"
257
- @dragend="$refs.draggableZone.onDragEnd($event)"
258
- >
259
- <WindowManager @draggable="draggable=$event" />
260
- </div>
225
+ <WindowManager :layout="layout" />
261
226
  </div>
262
227
  <FixedBanner :footer="true" />
263
228
  <GrowlManager />
264
229
  <SlideInPanelManager />
265
230
  <Inactivity />
266
- <DraggableZone ref="draggableZone" />
267
231
  </div>
268
232
  </template>