@appscode/design-system 1.0.43-alpha.10 → 1.0.43-alpha.103

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 (84) hide show
  1. package/base/utilities/_default.scss +275 -20
  2. package/base/utilities/_derived-variables.scss +0 -13
  3. package/base/utilities/_initial-variables.scss +78 -56
  4. package/base/utilities/_mixin.scss +10 -17
  5. package/base/utilities/_typography.scss +23 -7
  6. package/base/utilities/dark-theme.scss +25 -0
  7. package/components/_ac-accordion.scss +1 -0
  8. package/components/_ac-alert-box.scss +18 -10
  9. package/components/_ac-card.scss +55 -20
  10. package/components/_ac-code-highlight.scss +7 -1
  11. package/components/_ac-content-layout.scss +4 -4
  12. package/components/_ac-drag.scss +6 -6
  13. package/components/_ac-input.scss +74 -39
  14. package/components/_ac-modal.scss +5 -4
  15. package/components/_ac-multi-select.scss +196 -14
  16. package/components/_ac-options.scss +31 -16
  17. package/components/_ac-select-box.scss +15 -5
  18. package/components/_ac-table.scss +42 -33
  19. package/components/_ac-tabs.scss +72 -23
  20. package/components/_ac-tags.scss +2 -2
  21. package/components/_ac-terminal.scss +272 -0
  22. package/components/_app-drawer.scss +6 -6
  23. package/components/_breadcumb.scss +7 -2
  24. package/components/_buttons.scss +61 -28
  25. package/components/_card-body-wrapper.scss +3 -3
  26. package/components/_dashboard-header.scss +1 -1
  27. package/components/_direct-deploy.scss +69 -0
  28. package/components/_go-to-top.scss +1 -1
  29. package/components/_graph.scss +45 -0
  30. package/components/_image-upload.scss +6 -4
  31. package/components/_left-sidebar-menu.scss +200 -46
  32. package/components/_monaco-editor.scss +1 -1
  33. package/components/_navbar.scss +103 -26
  34. package/components/_overview-info.scss +4 -4
  35. package/components/_overview-page.scss +1 -2
  36. package/components/_pagination.scss +10 -2
  37. package/components/_payment-card.scss +28 -12
  38. package/components/_preview-modal.scss +8 -8
  39. package/components/_pricing-table.scss +1 -1
  40. package/components/_progress-bar.scss +5 -5
  41. package/components/_subscription-card.scss +15 -8
  42. package/components/_table-of-content.scss +1 -1
  43. package/components/_tfa.scss +69 -0
  44. package/components/_widget-menu.scss +9 -9
  45. package/components/_wizard.scss +32 -20
  46. package/components/ac-toaster/_ac-toasted.scss +5 -5
  47. package/components/bbum/_card-team.scss +18 -10
  48. package/components/bbum/_information-center.scss +19 -5
  49. package/components/bbum/_mobile-desktop.scss +6 -6
  50. package/components/bbum/_post.scss +5 -4
  51. package/components/bbum/_sign-up-notification.scss +6 -6
  52. package/components/bbum/_single-post-preview.scss +9 -9
  53. package/components/bbum/_user-profile.scss +97 -90
  54. package/components/ui-builder/_ui-builder.scss +29 -10
  55. package/components/ui-builder/_vue-open-api.scss +98 -0
  56. package/layouts/_404.scss +2 -1
  57. package/layouts/_code-preview.scss +14 -7
  58. package/main.scss +4 -0
  59. package/package.json +2 -7
  60. package/plugins/theme.js +142 -0
  61. package/vue-components/v2/breadcrumbs/Breadcrumb.vue +95 -0
  62. package/vue-components/v2/card/PaymentCards.vue +11 -2
  63. package/vue-components/v2/editor/Editor.vue +37 -17
  64. package/vue-components/v2/editor/ResourceKeyValueEditor.vue +232 -0
  65. package/vue-components/v2/modal/Modal.vue +30 -11
  66. package/vue-components/v2/navbar/Appdrawer.vue +10 -9
  67. package/vue-components/v2/navbar/ThemeMode.vue +120 -0
  68. package/vue-components/v2/navbar/User.vue +3 -0
  69. package/vue-components/v2/preloader/Preloader.vue +5 -5
  70. package/vue-components/v2/sidebar/ClusterSwitcher.vue +126 -0
  71. package/vue-components/v2/sidebar/SidebarItem.vue +23 -1
  72. package/vue-components/v2/table/TableRow.vue +17 -8
  73. package/vue-components/v2/table/table-cell/CellValue.vue +10 -1
  74. package/vue-components/v2/tabs/EditorTabs.vue +1 -1
  75. package/vue-components/v3/dropdown/DropdownMenu.vue +1 -1
  76. package/vue-components/v3/editor/Editor.vue +39 -19
  77. package/vue-components/v3/modal/Modal.vue +10 -1
  78. package/vue-components/v3/navbar/Appdrawer.vue +12 -7
  79. package/vue-components/v3/navbar/ThemeMode.vue +128 -0
  80. package/vue-components/v3/sidebar/ClusterSwitcher.vue +133 -0
  81. package/vue-components/v3/sidebar/SidebarItemWithDropDown.vue +120 -0
  82. package/vue-components/v3/table/TableRow.vue +1 -1
  83. package/vue-components/v3/table/table-cell/CellValue.vue +9 -0
  84. package/vue-components/v3/tabs/EditorTabs.vue +1 -1
@@ -0,0 +1,232 @@
1
+ <template>
2
+ <content-table :table-title="title" :searchable="isSearchable">
3
+ <template #content-controls>
4
+ <header-item v-if="showHideBtn">
5
+ <ac-button
6
+ modifier-classes="is-square is-primary"
7
+ :icon-class="hideValue ? 'eye-slash' : 'eye'"
8
+ @click.prevent="hideValue = !hideValue"
9
+ />
10
+ </header-item>
11
+ <header-item v-if="showCopyBtn">
12
+ <ac-button
13
+ modifier-classes="is-square is-primary"
14
+ icon-class="copy"
15
+ v-clipboard:copy="decode(previewYamls[activeKey])"
16
+ v-clipboard:success="onCopy"
17
+ v-clipboard:error="onError"
18
+ />
19
+ </header-item>
20
+ <header-item v-if="showDownloadBtn">
21
+ <download-btn
22
+ :file-data="decode(previewYamls[activeKey])"
23
+ :file-name="activePreview"
24
+ />
25
+ </header-item>
26
+ <header-item v-if="showUpdateBtn && !isEditorReadOnly">
27
+ <ac-button
28
+ modifier-classes="is-square is-primary"
29
+ icon-class="pencil-square-o"
30
+ @click.prevent="
31
+ $emit('updateData', activeKey, previewYamls[activeKey])
32
+ "
33
+ />
34
+ </header-item>
35
+ <header-item v-if="showDeleteBtn">
36
+ <ac-button
37
+ modifier-classes="is-square is-danger"
38
+ icon-class="trash"
39
+ @click.prevent="showDeleteDataModal = true"
40
+ />
41
+ <delete-confirmation-modal
42
+ title="Delete Resource"
43
+ message="Do you want to delete "
44
+ :itemName="activePreview"
45
+ :open="showDeleteDataModal"
46
+ @delete-confirmation-modal$confirm="confirmDelete"
47
+ @closemodal="showDeleteDataModal = false"
48
+ />
49
+ </header-item>
50
+ <slot name="content-action" />
51
+ </template>
52
+ <template #content>
53
+ <div class="ac-preview is-active is-not-fixed">
54
+ <div class="ac-preview-inner">
55
+ <!-- preview body start -->
56
+ <div class="ac-preview-body mt-0 pt-15 pl-20">
57
+ <div
58
+ v-if="isPreviewLoading || (!isPreviewLoading && previewYamls)"
59
+ class="left-content"
60
+ >
61
+ <div class="ac-files">
62
+ <ul v-if="!isPreviewLoading">
63
+ <li
64
+ v-for="(previewYaml, idx) in previewYamls"
65
+ :key="previewYaml.name + idx"
66
+ :class="{ 'is-active': activePreview === previewYaml.name }"
67
+ >
68
+ <a @click.prevent="setActivePreview(previewYaml, idx)">
69
+ <span>
70
+ <img
71
+ src="~@appscode/design-system-images/icons/file-icon.svg"
72
+ alt=""
73
+ />
74
+ </span>
75
+ <span>{{ previewYaml.name }}</span>
76
+ </a>
77
+ </li>
78
+ </ul>
79
+ <sidebar-loader v-else />
80
+ </div>
81
+ </div>
82
+ <div class="right-content">
83
+ <div class="right-content">
84
+ <resource-loader v-if="isPreviewLoading" />
85
+ <editor
86
+ v-else-if="!isPreviewLoading && !hideValue"
87
+ v-model="activeFile.content"
88
+ :original-value="activeFile.content"
89
+ :language="activeFile.format"
90
+ :read-only="isEditorReadOnly"
91
+ :editor-height="60"
92
+ :show-minimap="false"
93
+ />
94
+ <span v-else> *************** </span>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </template>
101
+ </content-table>
102
+ </template>
103
+ <script>
104
+ export default {
105
+ components: {
106
+ AcButton: () =>
107
+ import("@appscode/design-system/vue-components/v2/button/Button"),
108
+ Editor: () =>
109
+ import("@appscode/design-system/vue-components/v2/editor/Editor.vue"),
110
+ ContentTable: () =>
111
+ import(
112
+ "@appscode/design-system/vue-components/v2/content/ContentTable.vue"
113
+ ),
114
+ HeaderItem: () =>
115
+ import("@appscode/design-system/vue-components/v2/header/HeaderItem.vue"),
116
+ AcButton: () =>
117
+ import("@appscode/design-system/vue-components/v2/button/Button"),
118
+ DownloadBtn: () => import("@/components/buttons/DownloadBtn.vue"),
119
+ DeleteConfirmationModal: () =>
120
+ import("@/components/modals/DeleteConfirmationModal.vue"),
121
+ ResourceLoader: () => import("@/components/loaders/ResourceLoader.vue"),
122
+ SidebarLoader: () => import("@/components/loaders/SidebarLoader.vue"),
123
+ },
124
+ props: {
125
+ title: {
126
+ type: String,
127
+ default: "Title",
128
+ },
129
+ isSearchable: {
130
+ type: Boolean,
131
+ default: false,
132
+ },
133
+ isPreviewLoading: {
134
+ type: Boolean,
135
+ default: false,
136
+ },
137
+ isEditorReadOnly: {
138
+ type: Boolean,
139
+ default: false,
140
+ },
141
+ previewYamls: {
142
+ type: Array,
143
+ default: () => {
144
+ [];
145
+ },
146
+ },
147
+ visibleBtn: {
148
+ type: Object,
149
+ default: () => {
150
+ return {};
151
+ },
152
+ },
153
+ },
154
+ data() {
155
+ return {
156
+ activePreview: "",
157
+ activeKey: 0,
158
+ hideValue: "",
159
+ showDeleteDataModal: false,
160
+ };
161
+ },
162
+ computed: {
163
+ activeFile() {
164
+ const activeFile = this.previewYamls.find(
165
+ (p) => p.name === this.activePreview
166
+ );
167
+
168
+ return activeFile || { content: "", format: "yaml" };
169
+ },
170
+ showCopyBtn() {
171
+ if (this.visibleBtn.showCopyBtn) return true;
172
+ else return false;
173
+ },
174
+ showHideBtn() {
175
+ if (this.visibleBtn.showHideBtn) return true;
176
+ else return false;
177
+ },
178
+ showUpdateBtn() {
179
+ if (this.visibleBtn.showUpdateBtn) return true;
180
+ else return false;
181
+ },
182
+ showDownloadBtn() {
183
+ if (this.visibleBtn.showDownloadBtn) return true;
184
+ else return false;
185
+ },
186
+ showDeleteBtn() {
187
+ if (this.visibleBtn.showDeleteBtn) return true;
188
+ else return false;
189
+ },
190
+ },
191
+ methods: {
192
+ initActivePreview() {
193
+ this.activePreview = this.previewYamls[0] && this.previewYamls[0].name;
194
+ this.hideValue = this.previewYamls[0].isSecret;
195
+ this.activeKey = 0;
196
+ },
197
+ setActivePreview(previewYaml, idx) {
198
+ this.activePreview = previewYaml.name;
199
+ this.hideValue = previewYaml.isSecret;
200
+ this.activeKey = idx;
201
+ },
202
+ onCopy() {
203
+ this.$toasted.global.success("Value copied successfully").goAway(1000);
204
+ },
205
+ onError() {
206
+ this.$toasted.global.error("Copying failed").goAway(1000);
207
+ },
208
+ decode(str) {
209
+ if (this.hideValue === false) return str.content;
210
+ else return "";
211
+ },
212
+ encode(str) {
213
+ if (this.hideValue === false) return str.content;
214
+ else return "";
215
+ },
216
+ confirmDelete(flag) {
217
+ if (flag) this.$emit("deleteResource", this.activeKey);
218
+ },
219
+ },
220
+ watch: {
221
+ previewYamls: {
222
+ deep: true,
223
+ immediate: true,
224
+ handler(n) {
225
+ if (n.length) {
226
+ this.initActivePreview();
227
+ }
228
+ },
229
+ },
230
+ },
231
+ };
232
+ </script>
@@ -6,7 +6,7 @@
6
6
  v-if="showModal"
7
7
  class="ac-modal is-middle-alignment"
8
8
  :class="modifierClasses"
9
- @click.self="destroyModal"
9
+ @click.self="onModalOutsideClick"
10
10
  >
11
11
  <div class="ac-modal-inner">
12
12
  <!-- modal header start -->
@@ -17,6 +17,7 @@
17
17
  <header-item>
18
18
  <ac-button
19
19
  modifier-classes="is-square is-transparent"
20
+ :disabled="isCloseOptionDisabled"
20
21
  :icon-image="require('@/assets/images/icons/close-icon.svg')"
21
22
  @click.stop="destroyModal"
22
23
  />
@@ -36,7 +37,12 @@
36
37
  <!-- modal body end -->
37
38
 
38
39
  <!-- modal footer start -->
39
- <div class="ac-modal-footer action-footer">
40
+ <div
41
+ class="ac-modal-footer action-footer is-flex is-align-items-center is-justify-content-space-between"
42
+ >
43
+ <div>
44
+ <slot name="modal-footer-left" />
45
+ </div>
40
46
  <buttons class="has-text-right is-block">
41
47
  <slot name="modal-footer-controls" />
42
48
  </buttons>
@@ -52,28 +58,36 @@ export default {
52
58
  props: {
53
59
  open: {
54
60
  type: Boolean,
55
- default: false,
61
+ default: false
56
62
  },
57
63
  title: {
58
64
  type: String,
59
- default: "Modal",
65
+ default: "Modal"
60
66
  },
61
67
  modifierClasses: {
62
68
  type: String,
63
- default: "",
69
+ default: ""
70
+ },
71
+ isCloseOptionDisabled: {
72
+ type: Boolean,
73
+ default: false
64
74
  },
75
+ ignoreOutsideClick: {
76
+ type: Boolean,
77
+ default: false
78
+ }
65
79
  },
66
80
 
67
81
  components: {
68
82
  HeaderItems: () => import("../header/HeaderItems.vue"),
69
83
  HeaderItem: () => import("../header/HeaderItem.vue"),
70
84
  Buttons: () => import("../button/Buttons.vue"),
71
- AcButton: () => import("../button/Button.vue"),
85
+ AcButton: () => import("../button/Button.vue")
72
86
  },
73
87
 
74
88
  data() {
75
89
  return {
76
- showModal: false,
90
+ showModal: false
77
91
  };
78
92
  },
79
93
 
@@ -86,8 +100,8 @@ export default {
86
100
  } else {
87
101
  this.destroyModal();
88
102
  }
89
- },
90
- },
103
+ }
104
+ }
91
105
  },
92
106
 
93
107
  methods: {
@@ -97,16 +111,21 @@ export default {
97
111
  this.destroyModal();
98
112
  }
99
113
  },
114
+ onModalOutsideClick() {
115
+ if (this.ignoreOutsideClick) return;
116
+ this.destroyModal();
117
+ },
100
118
  initializeModal() {
101
119
  this.showModal = true;
102
120
  document.addEventListener("keydown", this.onKeyDown);
103
121
  },
104
122
  destroyModal() {
123
+ if (this.isCloseOptionDisabled) return;
105
124
  this.showModal = false;
106
125
  document.removeEventListener("keydown", this.onKeyDown);
107
126
 
108
127
  this.$emit("closemodal", true);
109
- },
110
- },
128
+ }
129
+ }
111
130
  };
112
131
  </script>
@@ -1,10 +1,13 @@
1
1
  <template>
2
- <div class="app-drawer-wrapper d-table-cell">
3
- <div class="drawer-icon">
2
+ <div class="app-drawer-wrapper is-flex">
3
+ <div
4
+ class="drawer-icon is-flex is-justify-content-center is-align-items-center"
5
+ >
4
6
  <svg
5
7
  class="gb_We"
6
8
  focusable="false"
7
9
  viewBox="0 0 24 24"
10
+ style="width: 22px;margin-top: 2px;"
8
11
  :style="{ fill: 'white' }"
9
12
  >
10
13
  <path
@@ -20,16 +23,14 @@
20
23
  <article class="media">
21
24
  <figure class="media-left">
22
25
  <p class="image">
23
- <img
24
- :src="app.icon_url"
25
- />
26
+ <img :src="app.icon_url" />
26
27
  </p>
27
28
  </figure>
28
29
  <div class="media-content">
29
30
  <div class="content">
30
31
  <p>
31
- <strong>{{app.title}}</strong>
32
- <span>{{app.sub_title}}</span>
32
+ <strong>{{ app.title }}</strong>
33
+ <span>{{ app.sub_title }}</span>
33
34
  </p>
34
35
  </div>
35
36
  </div>
@@ -50,7 +51,7 @@ export default {
50
51
  }
51
52
  },
52
53
  components: {
53
- NavbarItemContent: () => import("./NavbarItemContent.vue"),
54
- },
54
+ NavbarItemContent: () => import("./NavbarItemContent.vue")
55
+ }
55
56
  };
56
57
  </script>
@@ -0,0 +1,120 @@
1
+ <template>
2
+ <div>
3
+ <button
4
+ v-if="themeMode"
5
+ class="button ac-nav-button"
6
+ style="color: #ffffff; font-size: 15px;"
7
+ @click="toggleTheme"
8
+ :title="themeModes[themeMode].displayName"
9
+ >
10
+ <i :class="`fa ${themeModes[themeMode].iconClass}`" />
11
+ </button>
12
+ <div class="ac-menu-content theme-choice">
13
+ <ul class="is-flex is-flex-direction-row is-justify-content-space-around">
14
+ <li
15
+ v-for="theme of Object.keys(themeModes)"
16
+ :title="themeModes[theme].displayName"
17
+ @click="themeMode = theme"
18
+ :class="{'is-active': themeMode === theme}"
19
+ :key="theme"
20
+ >
21
+ <i :class="['fa', themeModes[theme].iconClass]" />
22
+ </li>
23
+ </ul>
24
+ </div>
25
+ </div>
26
+ </template>
27
+ <script>
28
+ export default {
29
+ data() {
30
+ return {
31
+ themeMode: "",
32
+ themeModes: {
33
+ system: {
34
+ displayName: "System Theme",
35
+ iconClass: "fa-desktop",
36
+ },
37
+ light: {
38
+ displayName: "Light Theme",
39
+ iconClass: "fa-sun-o",
40
+ },
41
+ dark: {
42
+ displayName: "Dark Theme",
43
+ iconClass: "fa-moon-o",
44
+ }
45
+ }
46
+ };
47
+ },
48
+
49
+ mounted() {
50
+ // get theme mode from localStorage or set default one
51
+ this.themeMode = localStorage.getItem("themeMode") || "light";
52
+ },
53
+
54
+ destroyed() {
55
+ this.removeColorSchemeEventListener();
56
+ },
57
+
58
+ watch: {
59
+ themeMode: {
60
+ handler(n) {
61
+ this.onThemeModeChange(n);
62
+ }
63
+ }
64
+ },
65
+
66
+ methods: {
67
+ // handle theme mode button click
68
+ toggleTheme() {
69
+ if (this.themeMode === "light") this.themeMode = "dark";
70
+ else if (this.themeMode === "dark") this.themeMode = "system";
71
+ else if (this.themeMode === "system") this.themeMode = "light";
72
+ },
73
+
74
+ // triggered when theme mode is updated
75
+ onThemeModeChange(n) {
76
+ localStorage.setItem("themeMode", n);
77
+
78
+ let theme = n;
79
+ if (n === "system") {
80
+ const isDarkMode =
81
+ window.matchMedia &&
82
+ window.matchMedia("(prefers-color-scheme: dark)").matches;
83
+ this.addColorSchemeEventListener();
84
+ theme = isDarkMode ? "dark" : "light";
85
+ } else {
86
+ this.removeColorSchemeEventListener();
87
+ }
88
+ this.$emit("set:theme", theme);
89
+ this.handleDarkThemeClass(theme);
90
+ },
91
+
92
+ // add proper css class to update the ui theme
93
+ handleDarkThemeClass(currentTheme) {
94
+ if (currentTheme === "light") {
95
+ document.documentElement.classList.remove("is-dark-theme");
96
+ } else {
97
+ document.documentElement.classList.add("is-dark-theme");
98
+ }
99
+ },
100
+
101
+ // add system theme listener event
102
+ addColorSchemeEventListener() {
103
+ window
104
+ .matchMedia("(prefers-color-scheme: dark)")
105
+ .addEventListener("change", this.handleSystemThemeChange);
106
+ },
107
+
108
+ // remove system theme listener event
109
+ removeColorSchemeEventListener() {
110
+ window
111
+ .matchMedia("(prefers-color-scheme: dark)")
112
+ .removeEventListener("change", this.handleSystemThemeChange);
113
+ },
114
+
115
+ handleSystemThemeChange() {
116
+ this.onThemeModeChange(this.themeMode);
117
+ }
118
+ }
119
+ };
120
+ </script>
@@ -28,6 +28,9 @@
28
28
  <a :href="`${serverDomain}/admin`"> Site Administration </a>
29
29
  </li>
30
30
  </template>
31
+ <li>
32
+ <a :href="`${serverDomain}/dashboard`"> Dashboard </a>
33
+ </li>
31
34
  <li>
32
35
  <a :href="`${serverDomain}/user/logout`"> Sign out </a>
33
36
  </li>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- class="is-flex is-justify-content-center is-align-items-center is-flex-direction-column"
3
+ class="is-flex is-justify-content-center is-align-items-center is-flex-direction-column ac-preloader"
4
4
  style="height: calc(100vh - 200px);"
5
5
  >
6
6
  <span v-if="showSpinner" class="spinner"></span>
@@ -15,12 +15,12 @@ export default {
15
15
  props: {
16
16
  showSpinner: {
17
17
  type: Boolean,
18
- default: true,
18
+ default: true
19
19
  },
20
20
  message: {
21
21
  type: String,
22
- default: "Fetching! Please wait for sometime...",
23
- },
24
- },
22
+ default: "Fetching! Please wait for sometime..."
23
+ }
24
+ }
25
25
  };
26
26
  </script>
@@ -0,0 +1,126 @@
1
+ <template>
2
+ <div class="is-cluster-logo" v-if="sidebarCollapsed">
3
+ <img
4
+ width="40"
5
+ :src="getProviderIcon(selectedCluster && selectedCluster.provider)"
6
+ onerror="this.onerror=null;this.src='https://cdn.appscode.com/images/cloud-provider-icons/Generic.png';"
7
+ alt="provider-icon"
8
+ />
9
+ </div>
10
+ <multiselect
11
+ v-else
12
+ v-model="selectedCluster"
13
+ placeholder="Selected Cluster"
14
+ label="name"
15
+ track-by="name"
16
+ :options="clusterOptions"
17
+ :allow-empty="false"
18
+ deselectLabel=""
19
+ selectLabel=""
20
+ selectedLabel=""
21
+ >
22
+ <template slot="singleLabel" slot-scope="props">
23
+ <div class="is-flex is-align-items-center">
24
+ <img
25
+ :src="getProviderIcon(props.option.provider)"
26
+ onerror="this.onerror=null;this.src='https://cdn.appscode.com/images/cloud-provider-icons/Generic.png';"
27
+ alt="No cluster selected"
28
+ /><span
29
+ ><span>{{ props.option.displayName }}</span></span
30
+ >
31
+ </div>
32
+ </template>
33
+ <template slot="option" slot-scope="props">
34
+ <div class="is-flex is-align-items-center">
35
+ <img
36
+ class="mr-15"
37
+ :src="getProviderIcon(props.option.provider)"
38
+ onerror="this.onerror=null;this.src='https://cdn.appscode.com/images/cloud-provider-icons/Generic.png';"
39
+ alt="No cluster selected"
40
+ />
41
+ <div>
42
+ <p>{{ props.option.displayName }}</p>
43
+ <p class="location">{{ props.option.location }}</p>
44
+ </div>
45
+ </div>
46
+ </template>
47
+ </multiselect>
48
+ </template>
49
+
50
+ <script>
51
+ export default {
52
+ props: {
53
+ sidebarCollapsed: {
54
+ type: Boolean,
55
+ default: false,
56
+ },
57
+ mouseHover: {
58
+ type: Boolean,
59
+ default: false,
60
+ },
61
+ clusterOptions: {
62
+ type: Array,
63
+ default: [],
64
+ },
65
+ value: {
66
+ type: String,
67
+ default: "",
68
+ }
69
+ },
70
+
71
+ components: {
72
+ Multiselect: () => import("vue-multiselect"),
73
+ },
74
+
75
+ data() {
76
+ return {
77
+ selectedCluster: null,
78
+ selectedClusterName: "",
79
+ };
80
+ },
81
+
82
+ methods: {
83
+ getProviderIcon(provider) {
84
+ return `https://cdn.appscode.com/images/cloud-provider-icons/${provider}.png`;
85
+ },
86
+ },
87
+
88
+ watch: {
89
+ value: {
90
+ immediate: true,
91
+ handler(n) {
92
+ this.selectedClusterName = n;
93
+ },
94
+ },
95
+ selectedCluster: {
96
+ deep: true,
97
+ handler(n) {
98
+ this.selectedClusterName = n.name;
99
+ },
100
+ },
101
+ selectedClusterName(n) {
102
+ if (this.selectedCluster && n !== this.selectedCluster.name) {
103
+ this.clusterOptions.forEach((item) => {
104
+ if (this.selectedClusterName === item.name) {
105
+ this.selectedCluster = item;
106
+ }
107
+ });
108
+ }
109
+ this.$emit("input", n);
110
+ },
111
+ clusterOptions: {
112
+ deep: true,
113
+ immediate: true,
114
+ async handler(list) {
115
+ if (list) {
116
+ list.forEach(async (item) => {
117
+ if(item.name === this.selectedClusterName) {
118
+ this.selectedCluster = item;
119
+ }
120
+ });
121
+ }
122
+ },
123
+ },
124
+ },
125
+ };
126
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <li>
2
+ <li ref="sidebarItem">
3
3
  <router-link
4
4
  :id="id"
5
5
  :title="title"
@@ -38,5 +38,27 @@ export default {
38
38
  default: "@/assets/images/icons/basic.svg",
39
39
  },
40
40
  },
41
+ watch: {
42
+ isActive: {
43
+ immediate: true,
44
+ handler(n) {
45
+ if (n) {
46
+ this.$nextTick(() => {
47
+ setTimeout(() => {
48
+ const top = (this.$refs.sidebarItem && this.$refs.sidebarItem.getBoundingClientRect().top) || 0;
49
+ // preventing scroll to options that are already visible
50
+ if (top > window.innerHeight - 200) {
51
+ // scroll to selected option item
52
+ this.$refs.sidebarItem.scrollIntoView({
53
+ behavior: 'smooth',
54
+ block: "center"
55
+ });
56
+ }
57
+ }, 500);
58
+ });
59
+ }
60
+ }
61
+ }
62
+ }
41
63
  };
42
64
  </script>