@appscode/design-system 1.0.43-alpha.99 → 1.1.0-alpha.10

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 (103) hide show
  1. package/base/utilities/_all.scss +8 -0
  2. package/base/utilities/_customize-bulma.scss +191 -0
  3. package/base/utilities/_default.scss +58 -124
  4. package/base/utilities/_derived-variables.scss +6 -0
  5. package/base/utilities/_extended.scss +38 -0
  6. package/base/utilities/_grid.scss +29 -0
  7. package/base/utilities/_initial-variables.scss +14 -10
  8. package/base/utilities/_typography.scss +6 -12
  9. package/base/utilities/dark-theme.scss +1 -0
  10. package/components/_ac-accordion.scss +14 -5
  11. package/components/_ac-alert-box.scss +32 -6
  12. package/components/_ac-card.scss +17 -5
  13. package/components/_ac-drag.scss +2 -0
  14. package/components/_ac-input.scss +19 -11
  15. package/components/_ac-modal.scss +1 -1
  16. package/components/_ac-multi-select.scss +60 -4
  17. package/components/_ac-report.scss +53 -0
  18. package/components/_ac-table.scss +60 -2
  19. package/components/_ac-tabs.scss +16 -2
  20. package/components/_ac-tags.scss +85 -0
  21. package/components/_ac-terminal.scss +1 -3
  22. package/components/_all.scss +29 -0
  23. package/components/_basic-card.scss +128 -0
  24. package/components/_buttons.scss +14 -33
  25. package/components/_dashboard-header.scss +32 -0
  26. package/components/_left-sidebar-menu.scss +9 -9
  27. package/components/_navbar.scss +89 -4
  28. package/components/_preview-modal.scss +14 -1
  29. package/components/_transitions.scss +296 -0
  30. package/components/_wizard.scss +1 -0
  31. package/components/bbum/_all.scss +9 -0
  32. package/components/bbum/_single-post-preview.scss +1 -1
  33. package/components/ui-builder/_ui-builder.scss +65 -1
  34. package/components/ui-builder/_vue-open-api.scss +6 -0
  35. package/layouts/_all.scss +2 -0
  36. package/layouts/_code-preview.scss +5 -2
  37. package/main.scss +5 -56
  38. package/package.json +4 -2
  39. package/plugins/caching.ts +243 -0
  40. package/plugins/time-convert.js +49 -0
  41. package/plugins/vue-toaster.js +3 -0
  42. package/vue-components/v2/banner/Banner.vue +2 -2
  43. package/vue-components/v2/breadcrumbs/Breadcrumb.vue +97 -0
  44. package/vue-components/v2/button/Button.vue +5 -0
  45. package/vue-components/v2/button/DownloadBtn.vue +45 -0
  46. package/vue-components/v2/card/Card.vue +1 -0
  47. package/vue-components/v2/content/ContentTable.vue +10 -0
  48. package/vue-components/v2/editor/Editor.vue +37 -24
  49. package/vue-components/v2/editor/FilteredFileEditor.vue +189 -0
  50. package/vue-components/v2/editor/MonacoEditor.vue +125 -0
  51. package/vue-components/v2/editor/ResourceKeyValueEditor.vue +209 -0
  52. package/vue-components/v2/form-fields/Input.vue +1 -1
  53. package/vue-components/v2/loaders/ResourceLoader.vue +101 -0
  54. package/vue-components/v2/loaders/SidebarLoader.vue +43 -0
  55. package/vue-components/v2/modal/Modal.vue +31 -5
  56. package/vue-components/v2/modals/DeleteConfirmationModal.vue +79 -0
  57. package/vue-components/v2/modals/JsonShowModal.vue +12 -2
  58. package/vue-components/v2/navbar/User.vue +229 -17
  59. package/vue-components/v2/notification/Notification.vue +101 -0
  60. package/vue-components/v2/notification/NotificationItem.vue +44 -0
  61. package/vue-components/v2/pagination/Pagination.vue +16 -3
  62. package/vue-components/v2/preloader/Preloader.vue +1 -1
  63. package/vue-components/v2/sidebar/SidebarItemWithDropDown.vue +19 -20
  64. package/vue-components/v2/tab/TabItem.vue +1 -1
  65. package/vue-components/v2/table/Table.vue +49 -8
  66. package/vue-components/v2/table/TableRow.vue +12 -2
  67. package/vue-components/v2/table/table-cell/CellValue.vue +29 -9
  68. package/vue-components/v2/table/table-cell/GenericCell.vue +56 -0
  69. package/vue-components/v2/table/table-cell/ObjectCell.vue +4 -1
  70. package/vue-components/v3/button/Button.vue +6 -1
  71. package/vue-components/v3/content/ContentHeader.vue +2 -1
  72. package/vue-components/v3/content/ContentTable.vue +25 -2
  73. package/vue-components/v3/editor/Editor.vue +36 -33
  74. package/vue-components/v3/editor/FilteredFileEditor.vue +186 -0
  75. package/vue-components/v3/editor/MonacoEditor.vue +131 -0
  76. package/vue-components/v3/editor/ResourceKeyValueEditor.vue +125 -0
  77. package/vue-components/v3/form/Form.vue +63 -0
  78. package/vue-components/v3/form-fields/Input.vue +11 -10
  79. package/vue-components/v3/header/HeaderItem.vue +5 -0
  80. package/vue-components/v3/header/HeaderItems.vue +5 -0
  81. package/vue-components/v3/loaders/ResourceLoader.vue +83 -0
  82. package/vue-components/v3/loaders/SidebarLoader.vue +34 -0
  83. package/vue-components/v3/long-running-tasks/LongRunningTaskItem.vue +92 -0
  84. package/vue-components/v3/modal/Modal.vue +35 -7
  85. package/vue-components/v3/modals/DeleteConfirmationModal.vue +85 -0
  86. package/vue-components/v3/modals/JsonShowModal.vue +25 -16
  87. package/vue-components/v3/modals/LongRunningTasksModal.vue +400 -0
  88. package/vue-components/v3/navbar/ThemeMode.vue +41 -49
  89. package/vue-components/v3/navbar/User.vue +242 -18
  90. package/vue-components/v3/notification/AlertBox.vue +61 -0
  91. package/vue-components/v3/notification/Notification.vue +98 -0
  92. package/vue-components/v3/notification/NotificationItem.vue +52 -0
  93. package/vue-components/v3/pagination/Pagination.vue +16 -3
  94. package/vue-components/v3/sidebar/SidebarItemWithDropDown.vue +120 -0
  95. package/vue-components/v3/tab/TabItem.vue +1 -1
  96. package/vue-components/v3/table/MultiInfoTable.vue +143 -0
  97. package/vue-components/v3/table/Table.vue +55 -14
  98. package/vue-components/v3/table/TableContainer.vue +34 -0
  99. package/vue-components/v3/table/TableRow.vue +93 -6
  100. package/vue-components/v3/table/table-cell/CellValue.vue +23 -7
  101. package/vue-components/v3/table/table-cell/GenericCell.vue +75 -0
  102. package/vue-components/v3/table/table-cell/ObjectCell.vue +7 -2
  103. package/vue-components/v3/terminal/LongRunningTaskTerminal.vue +148 -0
@@ -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,14 +1,16 @@
1
1
  <template>
2
- <table-container>
2
+ <table-container ref="ac-table-container" @scroller="handleScroller">
3
3
  <table
4
4
  ref="ac-table"
5
- class="table ac-table ac-striped"
5
+ class="table ac-table"
6
6
  :class="{
7
7
  'is-fullwidth':
8
8
  !isDynamicWidthTable ||
9
9
  isFullTableLoaderActive ||
10
10
  isTableEmpty ||
11
11
  isLoaderActive,
12
+ 'ac-striped': !columnStriped,
13
+ 'ac-label-texted': columnStriped,
12
14
  }"
13
15
  >
14
16
  <thead>
@@ -18,6 +20,7 @@
18
20
  </th>
19
21
  </table-row>
20
22
  <table-row v-else>
23
+ <th v-if="collapsible" style="width: 20px" />
21
24
  <th
22
25
  v-for="(tableHeader, idx) in tableHeaders"
23
26
  :key="idx"
@@ -25,10 +28,33 @@
25
28
  sorting: headerSortables[idx].enabled,
26
29
  'sorting-desc': headerSortables[idx].mode === 'desc',
27
30
  'sorting-asc': headerSortables[idx].mode === 'asc',
31
+ 'has-text-centered':
32
+ typeof tableHeader === 'string'
33
+ ? false
34
+ : tableHeader.textAlign === 'center',
35
+ 'has-text-left':
36
+ typeof tableHeader === 'string'
37
+ ? false
38
+ : tableHeader.textAlign === 'left',
39
+ 'has-text-right':
40
+ typeof tableHeader === 'string'
41
+ ? false
42
+ : tableHeader.textAlign === 'right',
28
43
  }"
29
44
  @click.prevent="headerSortables[idx].enabled && emitSortEvent(idx)"
30
45
  >
31
46
  {{ headerLabels[idx] }}
47
+ <span
48
+ v-if="
49
+ tableHeader.dashboard &&
50
+ tableHeader.dashboard.status &&
51
+ tableHeader.dashboard.status !== 'Success'
52
+ "
53
+ :title="tableHeader.dashboard && tableHeader.dashboard.message"
54
+ class="icon has-text-danger"
55
+ >
56
+ <i class="fa fa-exclamation-triangle" />
57
+ </span>
32
58
  </th>
33
59
  <th
34
60
  ref="action-section"
@@ -71,7 +97,9 @@
71
97
  <table-row class="is-hoverless">
72
98
  <table-cell
73
99
  :colspan="
74
- actionable ? tableHeaders.length + 1 : tableHeaders.length
100
+ tableHeaders.length +
101
+ (actionable ? 1 : 0) +
102
+ (collapsible ? 1 : 0)
75
103
  "
76
104
  class="no-data-available has-text-centered"
77
105
  >
@@ -81,6 +109,11 @@
81
109
  </tbody>
82
110
  </template>
83
111
  </table>
112
+
113
+ <!-- table footer info start -->
114
+ <slot name="table-footer-info" />
115
+ <!-- table footer info end -->
116
+
84
117
  <!-- pagination start -->
85
118
  <slot name="table-pagination" />
86
119
  <!-- pagination end -->
@@ -104,6 +137,10 @@ export default defineComponent({
104
137
  type: Array,
105
138
  default: () => [],
106
139
  },
140
+ collapsible: {
141
+ type: Boolean,
142
+ default: false,
143
+ },
107
144
  actionable: {
108
145
  type: Boolean,
109
146
  default: false,
@@ -116,13 +153,15 @@ export default defineComponent({
116
153
  type: Number,
117
154
  default: 1920,
118
155
  },
156
+ columnStriped: {
157
+ type: Boolean,
158
+ default: false,
159
+ },
119
160
  },
120
- emits: ["sort"],
161
+ emits: ["sort", "scroller"],
121
162
  components: {
122
163
  TableContainer: defineAsyncComponent(() =>
123
- import("../../v2/table/TableContainer.vue").then(
124
- (module) => module.default
125
- )
164
+ import("./TableContainer.vue").then((module) => module.default)
126
165
  ),
127
166
  TableRow: defineAsyncComponent(() =>
128
167
  import("./TableRow.vue").then((module) => module.default)
@@ -165,7 +204,7 @@ export default defineComponent({
165
204
  },
166
205
  headerLabels() {
167
206
  return this.tableHeaders.map((th) =>
168
- typeof th === "string" ? th : th?.label || "Label"
207
+ typeof th === "string" ? th : th?.name || "Label"
169
208
  );
170
209
  },
171
210
  },
@@ -176,8 +215,8 @@ export default defineComponent({
176
215
  handler(n) {
177
216
  if (this.headerSortables.length === n.length) {
178
217
  n.forEach((th, idx) => {
179
- if (this.headerSortables[idx].enabled !== !!th?.sortable) {
180
- this.headerSortables[idx].enabled = !!th?.sortable;
218
+ if (this.headerSortables[idx].enabled !== !!th?.sort?.enable) {
219
+ this.headerSortables[idx].enabled = !!th?.sort?.enable;
181
220
  this.headerSortables[idx].mode = "";
182
221
  }
183
222
  });
@@ -190,7 +229,7 @@ export default defineComponent({
190
229
  };
191
230
  } else {
192
231
  return {
193
- enabled: !!th?.sortable,
232
+ enabled: !!th?.sort?.enable,
194
233
  mode: "",
195
234
  };
196
235
  }
@@ -199,7 +238,6 @@ export default defineComponent({
199
238
  },
200
239
  },
201
240
  },
202
-
203
241
  updated() {
204
242
  this.$nextTick(() => {
205
243
  this.onWindowResize();
@@ -207,9 +245,12 @@ export default defineComponent({
207
245
  },
208
246
 
209
247
  methods: {
248
+ handleScroller(value) {
249
+ this.$emit("scroller", value);
250
+ },
210
251
  onWindowResize() {
211
252
  if (this.$refs["ac-table"] && this.isDynamicWidthTable) {
212
- const tableWidth = this.$refs["ac-table"].clientWidth;
253
+ const tableWidth = this.$refs["ac-table"]?.clientWidth;
213
254
  const d = this.fullWidth - tableWidth;
214
255
  this.fakeCellWidth = d;
215
256
  }
@@ -217,7 +258,7 @@ export default defineComponent({
217
258
  emitSortEvent(index) {
218
259
  const emitValue = {
219
260
  index,
220
- label: this.tableHeaders[index].label,
261
+ label: this.tableHeaders[index].name,
221
262
  mode: "",
222
263
  };
223
264
 
@@ -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>
@@ -1,12 +1,24 @@
1
1
  <template>
2
2
  <router-link
3
3
  v-if="link"
4
+ v-slot="{ navigate }"
4
5
  event="click"
5
6
  :to="link"
6
7
  custom
7
- v-slot="{ navigate }"
8
8
  >
9
- <tr class="is-link" @click="navigate" v-bind="$attrs">
9
+ <tr
10
+ class="is-link"
11
+ v-bind="$attrs"
12
+ data-testid="ac-table-row"
13
+ @click="navigate"
14
+ >
15
+ <table-cell v-if="collapsible">
16
+ <collapsible-button
17
+ modifier-classes="is-square is-light height-20 width-20 is-rounded is-size-7"
18
+ :icon-class="isCollapsed ? 'chevron-right' : 'chevron-down'"
19
+ @click.stop="toggleCollapse"
20
+ />
21
+ </table-cell>
10
22
  <slot />
11
23
  <fake-table-cell
12
24
  v-if="fakeCellWidth > 0"
@@ -16,15 +28,37 @@
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
+ modifier-classes="is-square is-light height-20 width-20 is-rounded is-size-7"
43
+ :icon-class="isCollapsed ? 'chevron-right' : 'chevron-down'"
44
+ @click.stop="toggleCollapse"
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
+ <transition name="slide-down" mode="out-in" appear>
54
+ <tr v-if="collapsible && !isCollapsed" v-bind="$attrs">
55
+ <table-cell colspan="1000" class="table-inner-shadow">
56
+ <div ref="collapsibleRow" class="collapsible-row">
57
+ <slot name="collapsible-content" />
58
+ </div>
59
+ </table-cell>
60
+ </tr>
61
+ </transition>
28
62
  </template>
29
63
 
30
64
  <script>
@@ -40,21 +74,74 @@ export default defineComponent({
40
74
  type: Boolean,
41
75
  default: false,
42
76
  },
77
+ isDisabled: {
78
+ type: Boolean,
79
+ default: false,
80
+ },
43
81
  fakeCellWidth: {
44
82
  type: Number,
45
83
  default: 0,
46
84
  },
85
+ collapsible: {
86
+ type: Boolean,
87
+ default: false,
88
+ },
47
89
  },
48
90
 
49
- emits: ["rowselect"],
91
+ emits: ["rowselect", "rowexpand", "rowcollapse"],
50
92
 
51
93
  components: {
52
94
  TableCell: defineAsyncComponent(() =>
53
- import("./TableCell.vue").then((module) => module.default)
95
+ import(
96
+ "@appscode/design-system/vue-components/v3/table/TableCell.vue"
97
+ ).then((module) => module.default)
54
98
  ),
55
99
  FakeTableCell: defineAsyncComponent(() =>
56
- import("./FakeTableCell.vue").then((module) => module.default)
100
+ import(
101
+ "@appscode/design-system/vue-components/v3/table/FakeTableCell.vue"
102
+ ).then((module) => module.default)
103
+ ),
104
+ CollapsibleButton: defineAsyncComponent(() =>
105
+ import("@appscode/design-system/vue-components/v3/button/Button.vue")
57
106
  ),
58
107
  },
108
+
109
+ data() {
110
+ return {
111
+ isCollapsed: true,
112
+ };
113
+ },
114
+
115
+ methods: {
116
+ toggleCollapse() {
117
+ const newVal = !this.isCollapsed;
118
+ if (!newVal) {
119
+ this.isCollapsed = newVal;
120
+ // show expand animation
121
+ this.$nextTick(() => {
122
+ setTimeout(() => {
123
+ if (this.$refs.collapsibleRow) {
124
+ this.$refs.collapsibleRow.classList.remove("is-closed");
125
+ this.$refs.collapsibleRow.classList.add("is-active");
126
+ }
127
+ this.$emit("rowexpand", this.collapseRow);
128
+ }, 0);
129
+ });
130
+ } else {
131
+ if (this.$refs.collapsibleRow) {
132
+ this.$refs.collapsibleRow.classList.remove("is-active");
133
+ this.$refs.collapsibleRow.classList.add("is-closed");
134
+ }
135
+ setTimeout(() => {
136
+ // remove row after animation finish
137
+ this.isCollapsed = newVal;
138
+ this.$emit("rowcollapse");
139
+ }, 100);
140
+ }
141
+ },
142
+ collapseRow() {
143
+ this.isCollapsed = true;
144
+ },
145
+ },
59
146
  });
60
147
  </script>
@@ -8,21 +8,23 @@
8
8
  :secondaryColor="secondaryColor"
9
9
  />
10
10
  </div>
11
- <div v-else class="haha" ref="cellDiv">
11
+ <div v-else ref="cellDiv">
12
12
  <object-cell
13
13
  v-if="valueType === 'object'"
14
14
  :obj="value"
15
15
  :cell-title="cellTitle"
16
16
  :max-character-length="maxCharacterLength"
17
+ data-testid="object-cell-value"
17
18
  />
18
19
  <array-cell
19
20
  v-else-if="valueType === 'array'"
20
21
  :items="value"
21
22
  :cell-title="cellTitle"
22
23
  :max-character-length="maxCharacterLength"
24
+ data-testid="array-cell-value"
23
25
  />
24
26
  <template v-else>
25
- <span class="is-ellipsis-1" :title="value">{{
27
+ <span class="is-ellipsis-1" :title="tooltip" data-testid="cell-value">{{
26
28
  value || (value === 0 ? 0 : "-")
27
29
  }}</span>
28
30
  </template>
@@ -31,7 +33,12 @@
31
33
 
32
34
  <script>
33
35
  import { defineComponent, defineAsyncComponent } from "vue";
34
- import { loaderLightThemePrimaryColor, loaderDarkThemePrimaryColor, loaderLightThemeSecondaryColor, loaderDarkThemeSecondaryColor } from "@appscode/design-system/plugins/theme";
36
+ import {
37
+ loaderLightThemePrimaryColor,
38
+ loaderDarkThemePrimaryColor,
39
+ loaderLightThemeSecondaryColor,
40
+ loaderDarkThemeSecondaryColor,
41
+ } from "@appscode/design-system/plugins/theme";
35
42
 
36
43
  export default defineComponent({
37
44
  props: {
@@ -47,6 +54,10 @@ export default defineComponent({
47
54
  type: null,
48
55
  default: "",
49
56
  },
57
+ tooltip: {
58
+ type: String,
59
+ defualt: "",
60
+ },
50
61
  },
51
62
  components: {
52
63
  ContentLoader: defineAsyncComponent(() =>
@@ -63,7 +74,8 @@ export default defineComponent({
63
74
  computed: {
64
75
  valueType() {
65
76
  if (typeof this.value === "object") {
66
- if (Array.isArray(this.value)) return "array";
77
+ if (this.value === null) return "null";
78
+ else if (Array.isArray(this.value)) return "array";
67
79
  else return "object";
68
80
  } else return typeof this.value;
69
81
  },
@@ -71,11 +83,15 @@ export default defineComponent({
71
83
  return Math.ceil(this.computedCellWidth / 8);
72
84
  },
73
85
  primaryColor() {
74
- return document.documentElement.classList.contains("is-dark-theme") ? loaderDarkThemePrimaryColor : loaderLightThemePrimaryColor;
86
+ return document.documentElement.classList.contains("is-dark-theme")
87
+ ? loaderDarkThemePrimaryColor
88
+ : loaderLightThemePrimaryColor;
75
89
  },
76
90
  secondaryColor() {
77
- return document.documentElement.classList.contains("is-dark-theme") ? loaderDarkThemeSecondaryColor : loaderLightThemeSecondaryColor;
78
- }
91
+ return document.documentElement.classList.contains("is-dark-theme")
92
+ ? loaderDarkThemeSecondaryColor
93
+ : loaderLightThemeSecondaryColor;
94
+ },
79
95
  },
80
96
 
81
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>
@@ -6,6 +6,7 @@
6
6
  indexOfCharacterLengthExceed
7
7
  )"
8
8
  :key="printableStringOb.key"
9
+ modifierClasses="is-info is-light"
9
10
  >
10
11
  <value-with-modal
11
12
  v-if="printableStringOb.exceededLength"
@@ -16,7 +17,7 @@
16
17
  <template v-else> {{ printableStringOb.print }} </template>
17
18
  </tag>
18
19
 
19
- <tag v-if="indexOfCharacterLengthExceed !== printableStringObjs.length">
20
+ <tag modifierClasses="is-info is-light" v-if="indexOfCharacterLengthExceed !== printableStringObjs.length">
20
21
  <a @click.prevent.stop="showFullData = true">
21
22
  <ellipsis-icon />
22
23
  <json-show-modal
@@ -79,7 +80,10 @@ export default defineComponent({
79
80
  },
80
81
  printableStringObjs() {
81
82
  return this.objKeys.map((key) => {
82
- const value = this.obj[key];
83
+ let value = this.obj[key];
84
+ if (typeof value === "object" && value !== null) {
85
+ value = JSON.stringify(value);
86
+ }
83
87
  const keyValue = `${key}: ${value}`;
84
88
  const exceededLength = keyValue.length > 30;
85
89
  const print = exceededLength ? key : keyValue;
@@ -103,3 +107,4 @@ export default defineComponent({
103
107
  },
104
108
  });
105
109
  </script>
110
+