@appscode/design-system 1.0.43-alpha.21 → 1.0.43-alpha.211

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 (132) hide show
  1. package/base/utilities/_all.scss +7 -0
  2. package/base/utilities/_customize-bulma.scss +191 -0
  3. package/base/utilities/_default.scss +313 -67
  4. package/base/utilities/_derived-variables.scss +6 -1
  5. package/base/utilities/_grid.scss +29 -0
  6. package/base/utilities/_initial-variables.scss +27 -17
  7. package/base/utilities/_mixin.scss +1 -17
  8. package/base/utilities/_typography.scss +18 -14
  9. package/base/utilities/dark-theme.scss +9 -145
  10. package/components/_ac-accordion.scss +14 -5
  11. package/components/_ac-alert-box.scss +41 -7
  12. package/components/_ac-card.scss +48 -10
  13. package/components/_ac-code-highlight.scss +5 -1
  14. package/components/_ac-content-layout.scss +2 -2
  15. package/components/_ac-drag.scss +2 -0
  16. package/components/_ac-input.scss +64 -23
  17. package/components/_ac-modal.scss +1 -1
  18. package/components/_ac-multi-select.scss +247 -9
  19. package/components/_ac-options.scss +24 -9
  20. package/components/_ac-select-box.scss +13 -3
  21. package/components/_ac-table.scss +7 -5
  22. package/components/_ac-tabs.scss +46 -5
  23. package/components/_ac-terminal.scss +270 -0
  24. package/components/_all.scss +27 -0
  25. package/components/_app-drawer.scss +2 -2
  26. package/components/_breadcumb.scss +2 -0
  27. package/components/_buttons.scss +50 -37
  28. package/components/_card-body-wrapper.scss +2 -2
  29. package/components/_dashboard-header.scss +32 -0
  30. package/components/_direct-deploy.scss +69 -0
  31. package/components/_go-to-top.scss +1 -1
  32. package/components/_graph.scss +45 -0
  33. package/components/_image-upload.scss +5 -3
  34. package/components/_left-sidebar-menu.scss +124 -73
  35. package/components/_monaco-editor.scss +1 -1
  36. package/components/_navbar.scss +170 -10
  37. package/components/_overview-info.scss +3 -3
  38. package/components/_pagination.scss +8 -0
  39. package/components/_payment-card.scss +10 -1
  40. package/components/_preview-modal.scss +18 -5
  41. package/components/_pricing-table.scss +1 -1
  42. package/components/_progress-bar.scss +4 -4
  43. package/components/_subscription-card.scss +11 -4
  44. package/components/_table-of-content.scss +1 -1
  45. package/components/_tfa.scss +69 -0
  46. package/components/_transitions.scss +261 -0
  47. package/components/_wizard.scss +16 -3
  48. package/components/bbum/_all.scss +9 -0
  49. package/components/bbum/_card-team.scss +1 -1
  50. package/components/bbum/_information-center.scss +15 -1
  51. package/components/bbum/_sign-up-notification.scss +1 -1
  52. package/components/bbum/_single-post-preview.scss +2 -2
  53. package/components/bbum/_user-profile.scss +2 -3
  54. package/components/ui-builder/_ui-builder.scss +76 -1
  55. package/components/ui-builder/_vue-open-api.scss +104 -0
  56. package/layouts/_all.scss +2 -0
  57. package/layouts/_code-preview.scss +5 -2
  58. package/main.scss +6 -54
  59. package/package.json +2 -7
  60. package/plugins/theme.js +4 -0
  61. package/plugins/time-convert.js +49 -0
  62. package/plugins/vue-toaster.js +3 -0
  63. package/vue-components/v2/banner/Banner.vue +2 -2
  64. package/vue-components/v2/breadcrumbs/Breadcrumb.vue +97 -0
  65. package/vue-components/v2/button/Button.vue +5 -0
  66. package/vue-components/v2/button/DownloadBtn.vue +45 -0
  67. package/vue-components/v2/card/Card.vue +1 -0
  68. package/vue-components/v2/card/PaymentCards.vue +11 -2
  69. package/vue-components/v2/content/ContentTable.vue +12 -7
  70. package/vue-components/v2/editor/Editor.vue +43 -24
  71. package/vue-components/v2/editor/FilteredFileEditor.vue +189 -0
  72. package/vue-components/v2/editor/MonacoEditor.vue +125 -0
  73. package/vue-components/v2/editor/ResourceKeyValueEditor.vue +209 -0
  74. package/vue-components/v2/form-fields/Input.vue +1 -1
  75. package/vue-components/v2/loaders/ResourceLoader.vue +101 -0
  76. package/vue-components/v2/loaders/SidebarLoader.vue +43 -0
  77. package/vue-components/v2/modal/Modal.vue +38 -4
  78. package/vue-components/v2/modals/DeleteConfirmationModal.vue +79 -0
  79. package/vue-components/v2/modals/JsonShowModal.vue +12 -2
  80. package/vue-components/v2/navbar/Appdrawer.vue +10 -9
  81. package/vue-components/v2/navbar/ThemeMode.vue +50 -44
  82. package/vue-components/v2/navbar/User.vue +229 -17
  83. package/vue-components/v2/notification/Notification.vue +101 -0
  84. package/vue-components/v2/notification/NotificationItem.vue +44 -0
  85. package/vue-components/v2/pagination/Pagination.vue +16 -3
  86. package/vue-components/v2/preloader/Preloader.vue +5 -5
  87. package/vue-components/v2/sidebar/ClusterSwitcher.vue +126 -0
  88. package/vue-components/v2/sidebar/SidebarItem.vue +23 -1
  89. package/vue-components/v2/sidebar/SidebarItemWithDropDown.vue +19 -20
  90. package/vue-components/v2/tab/TabItem.vue +1 -1
  91. package/vue-components/v2/table/Table.vue +44 -8
  92. package/vue-components/v2/table/TableRow.vue +12 -2
  93. package/vue-components/v2/table/table-cell/CellValue.vue +33 -4
  94. package/vue-components/v2/table/table-cell/GenericCell.vue +56 -0
  95. package/vue-components/v2/table/table-cell/ObjectCell.vue +4 -1
  96. package/vue-components/v2/tabs/EditorTabs.vue +1 -1
  97. package/vue-components/v3/button/Button.vue +6 -1
  98. package/vue-components/v3/content/ContentTable.vue +17 -2
  99. package/vue-components/v3/editor/Editor.vue +42 -33
  100. package/vue-components/v3/editor/FilteredFileEditor.vue +186 -0
  101. package/vue-components/v3/editor/MonacoEditor.vue +131 -0
  102. package/vue-components/v3/editor/ResourceKeyValueEditor.vue +125 -0
  103. package/vue-components/v3/form/Form.vue +63 -0
  104. package/vue-components/v3/form-fields/Input.vue +11 -10
  105. package/vue-components/v3/header/HeaderItem.vue +5 -0
  106. package/vue-components/v3/header/HeaderItems.vue +5 -0
  107. package/vue-components/v3/loaders/ResourceLoader.vue +83 -0
  108. package/vue-components/v3/loaders/SidebarLoader.vue +34 -0
  109. package/vue-components/v3/long-running-tasks/LongRunningTaskItem.vue +92 -0
  110. package/vue-components/v3/modal/Modal.vue +38 -6
  111. package/vue-components/v3/modals/DeleteConfirmationModal.vue +85 -0
  112. package/vue-components/v3/modals/JsonShowModal.vue +25 -16
  113. package/vue-components/v3/modals/LongRunningTasksModal.vue +337 -0
  114. package/vue-components/v3/navbar/Appdrawer.vue +12 -7
  115. package/vue-components/v3/navbar/ThemeMode.vue +49 -47
  116. package/vue-components/v3/navbar/User.vue +242 -18
  117. package/vue-components/v3/notification/Notification.vue +98 -0
  118. package/vue-components/v3/notification/NotificationItem.vue +52 -0
  119. package/vue-components/v3/pagination/Pagination.vue +16 -3
  120. package/vue-components/v3/sidebar/ClusterSwitcher.vue +133 -0
  121. package/vue-components/v3/sidebar/SidebarItemWithDropDown.vue +120 -0
  122. package/vue-components/v3/tab/TabItem.vue +1 -1
  123. package/vue-components/v3/table/MultiInfoTable.vue +143 -0
  124. package/vue-components/v3/table/Table.vue +40 -12
  125. package/vue-components/v3/table/TableContainer.vue +34 -0
  126. package/vue-components/v3/table/TableRow.vue +62 -3
  127. package/vue-components/v3/table/table-cell/CellValue.vue +28 -3
  128. package/vue-components/v3/table/table-cell/GenericCell.vue +75 -0
  129. package/vue-components/v3/table/table-cell/ObjectCell.vue +5 -1
  130. package/vue-components/v3/tabs/EditorTabs.vue +1 -1
  131. package/vue-components/v3/tag/Tag.vue +1 -1
  132. package/vue-components/v3/terminal/LongRunningTaskTerminal.vue +148 -0
@@ -0,0 +1,120 @@
1
+ <template>
2
+ <li :class="`is-${dropDownStatus}`">
3
+ <a class="ac-dropdown-button" :title="title" @click="toggleDropDownStatus">
4
+ <span>
5
+ <img :src="icon" alt="icon" />
6
+ </span>
7
+ <strong>{{ title || "-" }}</strong>
8
+ <span class="ac-arrow-down">
9
+ <i class="fa fa-angle-down" aria-hidden="true"> </i>
10
+ </span>
11
+ </a>
12
+
13
+ <ul ref="sectionItems" :style="{ maxHeight: dropDownSectionHeight }">
14
+ <slot />
15
+ </ul>
16
+ </li>
17
+ </template>
18
+
19
+ <script>
20
+ import { defineComponent } from "vue";
21
+
22
+ export default defineComponent({
23
+ props: {
24
+ isDropDownOpen: {
25
+ type: Boolean,
26
+ default: false,
27
+ },
28
+ title: {
29
+ type: String,
30
+ default: "Sidebar Item",
31
+ },
32
+ icon: {
33
+ type: String,
34
+ default: "@/assets/images/icons/basic.svg",
35
+ },
36
+ },
37
+
38
+ emits: ["dropDownItemChange"],
39
+
40
+ data() {
41
+ return {
42
+ dropDownStatus: "close",
43
+ dropDownSectionHeight: null,
44
+ isCompMounted: false,
45
+ };
46
+ },
47
+
48
+ mounted() {
49
+ this.isCompMounted = true;
50
+ setTimeout(() => {
51
+ // for expanding dropdown
52
+ if (this.isDropDownOpen) {
53
+ this.setDropdownMaxHeight("open");
54
+ } else {
55
+ this.setDropdownMaxHeight("close");
56
+ }
57
+ }, 700);
58
+ },
59
+
60
+ watch: {
61
+ title(n, o) {
62
+ if (n && this.isCompMounted) {
63
+ this.$nextTick(() => {
64
+ // for expanding dropdown
65
+ this.setDropdownMaxHeight("open");
66
+ });
67
+ }
68
+
69
+ if (o && this.isCompMounted) {
70
+ this.$nextTick(() => {
71
+ // for expanding dropdown
72
+ this.setDropdownMaxHeight("close");
73
+ });
74
+ }
75
+ },
76
+ isDropDownOpen: {
77
+ immediate: true,
78
+ handler(n) {
79
+ if (n) {
80
+ this.dropDownStatus = "open";
81
+ } else this.dropDownStatus = "close";
82
+ },
83
+ },
84
+ dropDownStatus: {
85
+ immediate: true,
86
+ handler(n) {
87
+ if (n === "open") {
88
+ // emit event to close other drop down items
89
+ this.$emit("dropDownItemChange");
90
+
91
+ this.$nextTick(() => {
92
+ const dropDownUl = this.$refs["sectionItems"];
93
+ // debugger;
94
+ if (dropDownUl)
95
+ this.dropDownSectionHeight = `${dropDownUl.scrollHeight}px`;
96
+ });
97
+ } else {
98
+ // emit event to close other drop down items
99
+ this.dropDownSectionHeight = null;
100
+ }
101
+ },
102
+ },
103
+ },
104
+
105
+ methods: {
106
+ setDropdownMaxHeight(mode) {
107
+ if (mode === "open") {
108
+ this.dropDownSectionHeight = `${this.$refs["sectionItems"].scrollHeight}px`;
109
+ } else {
110
+ this.dropDownSectionHeight = null;
111
+ }
112
+ },
113
+ toggleDropDownStatus() {
114
+ if (this.dropDownStatus === "open") {
115
+ this.dropDownStatus = "close";
116
+ } else this.dropDownStatus = "open";
117
+ },
118
+ },
119
+ });
120
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <li :class="{ 'is-active': isActive }">
2
+ <li :class="{ 'is-active': isActive }" data-testid="tab-item">
3
3
  <slot />
4
4
  </li>
5
5
  </template>
@@ -0,0 +1,143 @@
1
+ <template>
2
+ <table-container>
3
+ <table
4
+ class="table ac-info-table is-fullwidth"
5
+ :class="{ 'pl-0 pr-0': removeContentPadding }"
6
+ >
7
+ <tbody v-if="isFullTableLoaderActive">
8
+ <table-row v-for="i in loaderCols" :key="i">
9
+ <table-cell>
10
+ <cell-value :is-loader-active="true" />
11
+ </table-cell>
12
+ <table-cell>
13
+ <cell-value :is-loader-active="true" />
14
+ </table-cell>
15
+ </table-row>
16
+ </tbody>
17
+ <tbody
18
+ v-else
19
+ :class="{
20
+ 'no-data-available has-text-centered p-10': isTableEmpty,
21
+ 'pl-0 pr-0': removeContentPadding,
22
+ }"
23
+ >
24
+ <template v-if="!isTableEmpty">
25
+ <table-row
26
+ v-for="(tableHeader, idx) in tableHeaders"
27
+ :key="headerLabels[idx]"
28
+ >
29
+ <table-cell>
30
+ <slot :name="`table-cell-icon-${idx}`" />
31
+ {{ headerLabels[idx] }}
32
+ </table-cell>
33
+ <table-cell v-if="isLoaderActive">
34
+ <cell-value :is-loader-active="true" />
35
+ </table-cell>
36
+ <slot v-else :name="`slot-${idx}`" />
37
+ </table-row>
38
+ </template>
39
+
40
+ <empty-table-info v-else />
41
+ </tbody>
42
+ </table>
43
+
44
+ <!-- pagination start -->
45
+ <slot name="table-pagination" />
46
+ <!-- pagination end -->
47
+ </table-container>
48
+ </template>
49
+
50
+ <script>
51
+ import { defineComponent, defineAsyncComponent } from "vue";
52
+
53
+ export default defineComponent({
54
+ props: {
55
+ isLoaderActive: {
56
+ type: Boolean,
57
+ default: false,
58
+ },
59
+ isTableEmpty: {
60
+ type: Boolean,
61
+ default: true,
62
+ },
63
+ tableHeaders: {
64
+ type: Array,
65
+ default: () => [],
66
+ },
67
+ removeContentPadding: {
68
+ type: Boolean,
69
+ default: false,
70
+ },
71
+ },
72
+
73
+ components: {
74
+ TableContainer: defineAsyncComponent(() =>
75
+ import("../../v2/table/TableContainer.vue").then(
76
+ (module) => module.default
77
+ )
78
+ ),
79
+ EmptyTableInfo: defineAsyncComponent(() =>
80
+ import("../../v2/table/EmptyTableInfo.vue").then(
81
+ (module) => module.default
82
+ )
83
+ ),
84
+ TableRow: defineAsyncComponent(() =>
85
+ import("./TableRow.vue").then((module) => module.default)
86
+ ),
87
+ TableCell: defineAsyncComponent(() =>
88
+ import("./TableCell.vue").then((module) => module.default)
89
+ ),
90
+ CellValue: defineAsyncComponent(() =>
91
+ import("./table-cell/CellValue.vue").then((module) => module.default)
92
+ ),
93
+ },
94
+
95
+ data() {
96
+ return {
97
+ loaderCols: 5,
98
+ headerSortables: [],
99
+ };
100
+ },
101
+
102
+ computed: {
103
+ isFullTableLoaderActive() {
104
+ return !this.tableHeaders.length;
105
+ },
106
+ headerLabels() {
107
+ return this.tableHeaders.map((th) =>
108
+ typeof th === "string" ? th : th?.name || "Label"
109
+ );
110
+ },
111
+ },
112
+
113
+ watch: {
114
+ tableHeaders: {
115
+ immediate: true,
116
+ handler(n) {
117
+ if (this.headerSortables.length === n.length) {
118
+ n.forEach((th, idx) => {
119
+ if (this.headerSortables[idx].enabled !== !!th?.sort?.enable) {
120
+ this.headerSortables[idx].enabled = !!th?.sort?.enable;
121
+ this.headerSortables[idx].mode = "";
122
+ }
123
+ });
124
+ } else {
125
+ this.headerSortables = n.map((th) => {
126
+ if (typeof th === "string") {
127
+ return {
128
+ enabled: false,
129
+ mode: "",
130
+ };
131
+ } else {
132
+ return {
133
+ enabled: !!th?.sort?.enable,
134
+ mode: "",
135
+ };
136
+ }
137
+ });
138
+ }
139
+ },
140
+ },
141
+ },
142
+ });
143
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <table-container>
2
+ <table-container ref="ac-table-container" @scroller="handleScroller">
3
3
  <table
4
4
  ref="ac-table"
5
5
  class="table ac-table ac-striped"
@@ -18,6 +18,7 @@
18
18
  </th>
19
19
  </table-row>
20
20
  <table-row v-else>
21
+ <th v-if="collapsible" style="width: 20px" />
21
22
  <th
22
23
  v-for="(tableHeader, idx) in tableHeaders"
23
24
  :key="idx"
@@ -25,10 +26,33 @@
25
26
  sorting: headerSortables[idx].enabled,
26
27
  'sorting-desc': headerSortables[idx].mode === 'desc',
27
28
  'sorting-asc': headerSortables[idx].mode === 'asc',
29
+ 'has-text-centered':
30
+ typeof tableHeader === 'string'
31
+ ? false
32
+ : tableHeader.textAlign === 'center',
33
+ 'has-text-left':
34
+ typeof tableHeader === 'string'
35
+ ? false
36
+ : tableHeader.textAlign === 'left',
37
+ 'has-text-right':
38
+ typeof tableHeader === 'string'
39
+ ? false
40
+ : tableHeader.textAlign === 'right',
28
41
  }"
29
42
  @click.prevent="headerSortables[idx].enabled && emitSortEvent(idx)"
30
43
  >
31
44
  {{ headerLabels[idx] }}
45
+ <span
46
+ v-if="
47
+ tableHeader.dashboard &&
48
+ tableHeader.dashboard.status &&
49
+ tableHeader.dashboard.status !== 'Success'
50
+ "
51
+ :title="tableHeader.dashboard && tableHeader.dashboard.message"
52
+ class="icon has-text-danger"
53
+ >
54
+ <i class="fa fa-exclamation-triangle" />
55
+ </span>
32
56
  </th>
33
57
  <th
34
58
  ref="action-section"
@@ -104,6 +128,10 @@ export default defineComponent({
104
128
  type: Array,
105
129
  default: () => [],
106
130
  },
131
+ collapsible: {
132
+ type: Boolean,
133
+ default: false,
134
+ },
107
135
  actionable: {
108
136
  type: Boolean,
109
137
  default: false,
@@ -117,12 +145,10 @@ export default defineComponent({
117
145
  default: 1920,
118
146
  },
119
147
  },
120
- emits: ["sort"],
148
+ emits: ["sort", "scroller"],
121
149
  components: {
122
150
  TableContainer: defineAsyncComponent(() =>
123
- import("../../v2/table/TableContainer.vue").then(
124
- (module) => module.default
125
- )
151
+ import("./TableContainer.vue").then((module) => module.default)
126
152
  ),
127
153
  TableRow: defineAsyncComponent(() =>
128
154
  import("./TableRow.vue").then((module) => module.default)
@@ -165,7 +191,7 @@ export default defineComponent({
165
191
  },
166
192
  headerLabels() {
167
193
  return this.tableHeaders.map((th) =>
168
- typeof th === "string" ? th : th?.label || "Label"
194
+ typeof th === "string" ? th : th?.name || "Label"
169
195
  );
170
196
  },
171
197
  },
@@ -176,8 +202,8 @@ export default defineComponent({
176
202
  handler(n) {
177
203
  if (this.headerSortables.length === n.length) {
178
204
  n.forEach((th, idx) => {
179
- if (this.headerSortables[idx].enabled !== !!th?.sortable) {
180
- this.headerSortables[idx].enabled = !!th?.sortable;
205
+ if (this.headerSortables[idx].enabled !== !!th?.sort?.enable) {
206
+ this.headerSortables[idx].enabled = !!th?.sort?.enable;
181
207
  this.headerSortables[idx].mode = "";
182
208
  }
183
209
  });
@@ -190,7 +216,7 @@ export default defineComponent({
190
216
  };
191
217
  } else {
192
218
  return {
193
- enabled: !!th?.sortable,
219
+ enabled: !!th?.sort?.enable,
194
220
  mode: "",
195
221
  };
196
222
  }
@@ -199,7 +225,6 @@ export default defineComponent({
199
225
  },
200
226
  },
201
227
  },
202
-
203
228
  updated() {
204
229
  this.$nextTick(() => {
205
230
  this.onWindowResize();
@@ -207,9 +232,12 @@ export default defineComponent({
207
232
  },
208
233
 
209
234
  methods: {
235
+ handleScroller(value) {
236
+ this.$emit("scroller", value);
237
+ },
210
238
  onWindowResize() {
211
239
  if (this.$refs["ac-table"] && this.isDynamicWidthTable) {
212
- const tableWidth = this.$refs["ac-table"].clientWidth;
240
+ const tableWidth = this.$refs["ac-table"]?.clientWidth;
213
241
  const d = this.fullWidth - tableWidth;
214
242
  this.fakeCellWidth = d;
215
243
  }
@@ -217,7 +245,7 @@ export default defineComponent({
217
245
  emitSortEvent(index) {
218
246
  const emitValue = {
219
247
  index,
220
- label: this.tableHeaders[index].label,
248
+ label: this.tableHeaders[index].name,
221
249
  mode: "",
222
250
  };
223
251
 
@@ -0,0 +1,34 @@
1
+ <template>
2
+ <div class="ac-table-container table-container" ref="tableContainer">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ import { emit } from 'process'
9
+ import { defineComponent, ref, onMounted, nextTick } from 'vue'
10
+
11
+ export default defineComponent({
12
+ emits: ['scroller'],
13
+
14
+ setup(props, { emit }) {
15
+ const tableContainer = ref(null)
16
+
17
+ function isScrollerShowing() {
18
+ return tableContainer.value?.scrollWidth > tableContainer.value?.clientWidth
19
+ }
20
+
21
+ onMounted(() => {
22
+ setTimeout(() => {
23
+ nextTick(() => {
24
+ emit('scroller', isScrollerShowing())
25
+ })
26
+ }, 50)
27
+ })
28
+
29
+ return {
30
+ tableContainer,
31
+ }
32
+ },
33
+ })
34
+ </script>
@@ -6,7 +6,19 @@
6
6
  custom
7
7
  v-slot="{ navigate }"
8
8
  >
9
- <tr @click="navigate" v-bind="$attrs">
9
+ <tr
10
+ class="is-link"
11
+ @click="navigate"
12
+ v-bind="$attrs"
13
+ data-testid="ac-table-row"
14
+ >
15
+ <table-cell v-if="collapsible">
16
+ <collapsible-button
17
+ @click.stop="toggleCollapse"
18
+ modifier-classes="is-square is-light height-20 width-20 is-rounded is-size-7"
19
+ :icon-class="isCollapsed ? 'chevron-right' : 'chevron-down'"
20
+ />
21
+ </table-cell>
10
22
  <slot />
11
23
  <fake-table-cell
12
24
  v-if="fakeCellWidth > 0"
@@ -16,15 +28,33 @@
16
28
  </router-link>
17
29
  <tr
18
30
  v-else
19
- :class="{ 'is-selected': isSelected, 'is-hoverless': !isSelected }"
31
+ v-bind="$attrs"
32
+ :class="{
33
+ 'is-selected': isSelected,
34
+ 'is-hoverless': !isSelected,
35
+ 'is-disabled': isDisabled,
36
+ }"
37
+ data-testid="ac-table-row"
20
38
  @click.prevent="$emit('rowselect', true)"
21
39
  >
40
+ <table-cell v-if="collapsible">
41
+ <collapsible-button
42
+ @click.stop="toggleCollapse"
43
+ modifier-classes="is-square is-tinny is-light"
44
+ :icon-class="isCollapsed ? 'chevron-right' : 'chevron-down'"
45
+ />
46
+ </table-cell>
22
47
  <slot />
23
48
  <fake-table-cell
24
49
  v-if="fakeCellWidth > 0"
25
50
  :fake-cell-width="fakeCellWidth"
26
51
  />
27
52
  </tr>
53
+ <tr v-if="collapsible && !isCollapsed" v-bind="$attrs">
54
+ <table-cell colspan="1000">
55
+ <slot name="collapsible-content" />
56
+ </table-cell>
57
+ </tr>
28
58
  </template>
29
59
 
30
60
  <script>
@@ -40,13 +70,21 @@ export default defineComponent({
40
70
  type: Boolean,
41
71
  default: false,
42
72
  },
73
+ isDisabled: {
74
+ type: Boolean,
75
+ default: false,
76
+ },
43
77
  fakeCellWidth: {
44
78
  type: Number,
45
79
  default: 0,
46
80
  },
81
+ collapsible: {
82
+ type: Boolean,
83
+ default: false,
84
+ },
47
85
  },
48
86
 
49
- emits: ["rowselect"],
87
+ emits: ["rowselect", "rowexpand"],
50
88
 
51
89
  components: {
52
90
  TableCell: defineAsyncComponent(() =>
@@ -55,6 +93,27 @@ export default defineComponent({
55
93
  FakeTableCell: defineAsyncComponent(() =>
56
94
  import("./FakeTableCell.vue").then((module) => module.default)
57
95
  ),
96
+ CollapsibleButton: defineAsyncComponent(() =>
97
+ import("../button/Button.vue")
98
+ ),
99
+ },
100
+
101
+ data() {
102
+ return {
103
+ isCollapsed: true,
104
+ };
105
+ },
106
+
107
+ methods: {
108
+ toggleCollapse() {
109
+ this.isCollapsed = !this.isCollapsed;
110
+ if (!this.isCollapsed) {
111
+ this.$emit("rowexpand", this.collapseRow);
112
+ }
113
+ },
114
+ collapseRow() {
115
+ this.isCollapsed = true;
116
+ },
58
117
  },
59
118
  });
60
119
  </script>
@@ -4,23 +4,27 @@
4
4
  :view-box="`0 0 ${computedCellWidth || 300} 10`"
5
5
  :speed="2"
6
6
  :key="computedCellWidth"
7
+ :primaryColor="primaryColor"
8
+ :secondaryColor="secondaryColor"
7
9
  />
8
10
  </div>
9
- <div v-else class="haha" ref="cellDiv">
11
+ <div v-else ref="cellDiv">
10
12
  <object-cell
11
13
  v-if="valueType === 'object'"
12
14
  :obj="value"
13
15
  :cell-title="cellTitle"
14
16
  :max-character-length="maxCharacterLength"
17
+ data-testid="object-cell-value"
15
18
  />
16
19
  <array-cell
17
20
  v-else-if="valueType === 'array'"
18
21
  :items="value"
19
22
  :cell-title="cellTitle"
20
23
  :max-character-length="maxCharacterLength"
24
+ data-testid="array-cell-value"
21
25
  />
22
26
  <template v-else>
23
- <span class="is-ellipsis-1" :title="value">{{
27
+ <span class="is-ellipsis-1" :title="tooltip" data-testid="cell-value">{{
24
28
  value || (value === 0 ? 0 : "-")
25
29
  }}</span>
26
30
  </template>
@@ -29,6 +33,12 @@
29
33
 
30
34
  <script>
31
35
  import { defineComponent, defineAsyncComponent } from "vue";
36
+ import {
37
+ loaderLightThemePrimaryColor,
38
+ loaderDarkThemePrimaryColor,
39
+ loaderLightThemeSecondaryColor,
40
+ loaderDarkThemeSecondaryColor,
41
+ } from "@appscode/design-system/plugins/theme";
32
42
 
33
43
  export default defineComponent({
34
44
  props: {
@@ -44,6 +54,10 @@ export default defineComponent({
44
54
  type: null,
45
55
  default: "",
46
56
  },
57
+ tooltip: {
58
+ type: String,
59
+ defualt: "",
60
+ },
47
61
  },
48
62
  components: {
49
63
  ContentLoader: defineAsyncComponent(() =>
@@ -60,13 +74,24 @@ export default defineComponent({
60
74
  computed: {
61
75
  valueType() {
62
76
  if (typeof this.value === "object") {
63
- if (Array.isArray(this.value)) return "array";
77
+ if (this.value === null) return "null";
78
+ else if (Array.isArray(this.value)) return "array";
64
79
  else return "object";
65
80
  } else return typeof this.value;
66
81
  },
67
82
  maxCharacterLength() {
68
83
  return Math.ceil(this.computedCellWidth / 8);
69
84
  },
85
+ primaryColor() {
86
+ return document.documentElement.classList.contains("is-dark-theme")
87
+ ? loaderDarkThemePrimaryColor
88
+ : loaderLightThemePrimaryColor;
89
+ },
90
+ secondaryColor() {
91
+ return document.documentElement.classList.contains("is-dark-theme")
92
+ ? loaderDarkThemeSecondaryColor
93
+ : loaderLightThemeSecondaryColor;
94
+ },
70
95
  },
71
96
 
72
97
  data() {
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <span
3
+ :class="{
4
+ 'is-flex': cellDescriptor.type !== 'object',
5
+ 'is-align-items-center': cellValue.icon,
6
+ 'is-justify-content-center': cellDescriptor.textAlign === 'center',
7
+ 'is-justify-content-left': cellDescriptor.textAlign === 'left',
8
+ 'is-justify-content-right': cellDescriptor.textAlign === 'right',
9
+ }"
10
+ >
11
+ <span v-if="cellValue.icon" class="icon p-0 mr-10">
12
+ <img width="15" :src="cellValue.icon" />
13
+ </span>
14
+ <a
15
+ v-if="cellValue.link && cellValue.link.startsWith('http')"
16
+ :href="getCellLink(cellValue)"
17
+ @click.prevent="redirectTo"
18
+ >
19
+ {{ cellValue.data }}
20
+ </a>
21
+ <router-link v-else-if="cellValue.link" :to="getCellLink(cellValue)">
22
+ {{ cellValue.data }}
23
+ </router-link>
24
+ <tag v-else-if="cellValue.color" :class="`is-${cellValue.color}`">
25
+ {{ cellValue.data }}
26
+ </tag>
27
+ <cell-value
28
+ v-else
29
+ :cell-title="cellDescriptor.name"
30
+ :value="cellValue.data || '-'"
31
+ :tooltip="cellValue.tooltip || JSON.stringify(cellValue.data)"
32
+ />
33
+ </span>
34
+ </template>
35
+
36
+ <script>
37
+ import { defineAsyncComponent, defineComponent } from "vue";
38
+ import { useRoute } from "vue-router";
39
+
40
+ export default defineComponent({
41
+ components: {
42
+ Tag: defineAsyncComponent(() => import("../../tag/Tag.vue")),
43
+ CellValue: defineAsyncComponent(() =>
44
+ import("../table-cell/CellValue.vue")
45
+ ),
46
+ },
47
+ props: {
48
+ cellDescriptor: {
49
+ type: Object,
50
+ default: () => ({}),
51
+ },
52
+ cellValue: {
53
+ type: Object,
54
+ default: () => ({}),
55
+ },
56
+ },
57
+ setup() {
58
+ const route = useRoute();
59
+ function getCellLink(cell) {
60
+ const inject = (str, obj) => str.replace(/\${(.*?)}/g, (x, g) => obj[g]);
61
+ const { user, cluster } = route.params;
62
+ const link = inject(cell.link || "", {
63
+ username: user,
64
+ clustername: cluster,
65
+ });
66
+ return link;
67
+ }
68
+ function redirectTo() {
69
+ const link = getCellLink(this.cellValue);
70
+ window.open(link, "_blank");
71
+ }
72
+ return { getCellLink, redirectTo };
73
+ },
74
+ });
75
+ </script>