@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.
- package/base/utilities/_all.scss +8 -0
- package/base/utilities/_customize-bulma.scss +191 -0
- package/base/utilities/_default.scss +58 -124
- package/base/utilities/_derived-variables.scss +6 -0
- package/base/utilities/_extended.scss +38 -0
- package/base/utilities/_grid.scss +29 -0
- package/base/utilities/_initial-variables.scss +14 -10
- package/base/utilities/_typography.scss +6 -12
- package/base/utilities/dark-theme.scss +1 -0
- package/components/_ac-accordion.scss +14 -5
- package/components/_ac-alert-box.scss +32 -6
- package/components/_ac-card.scss +17 -5
- package/components/_ac-drag.scss +2 -0
- package/components/_ac-input.scss +19 -11
- package/components/_ac-modal.scss +1 -1
- package/components/_ac-multi-select.scss +60 -4
- package/components/_ac-report.scss +53 -0
- package/components/_ac-table.scss +60 -2
- package/components/_ac-tabs.scss +16 -2
- package/components/_ac-tags.scss +85 -0
- package/components/_ac-terminal.scss +1 -3
- package/components/_all.scss +29 -0
- package/components/_basic-card.scss +128 -0
- package/components/_buttons.scss +14 -33
- package/components/_dashboard-header.scss +32 -0
- package/components/_left-sidebar-menu.scss +9 -9
- package/components/_navbar.scss +89 -4
- package/components/_preview-modal.scss +14 -1
- package/components/_transitions.scss +296 -0
- package/components/_wizard.scss +1 -0
- package/components/bbum/_all.scss +9 -0
- package/components/bbum/_single-post-preview.scss +1 -1
- package/components/ui-builder/_ui-builder.scss +65 -1
- package/components/ui-builder/_vue-open-api.scss +6 -0
- package/layouts/_all.scss +2 -0
- package/layouts/_code-preview.scss +5 -2
- package/main.scss +5 -56
- package/package.json +4 -2
- package/plugins/caching.ts +243 -0
- package/plugins/time-convert.js +49 -0
- package/plugins/vue-toaster.js +3 -0
- package/vue-components/v2/banner/Banner.vue +2 -2
- package/vue-components/v2/breadcrumbs/Breadcrumb.vue +97 -0
- package/vue-components/v2/button/Button.vue +5 -0
- package/vue-components/v2/button/DownloadBtn.vue +45 -0
- package/vue-components/v2/card/Card.vue +1 -0
- package/vue-components/v2/content/ContentTable.vue +10 -0
- package/vue-components/v2/editor/Editor.vue +37 -24
- package/vue-components/v2/editor/FilteredFileEditor.vue +189 -0
- package/vue-components/v2/editor/MonacoEditor.vue +125 -0
- package/vue-components/v2/editor/ResourceKeyValueEditor.vue +209 -0
- package/vue-components/v2/form-fields/Input.vue +1 -1
- package/vue-components/v2/loaders/ResourceLoader.vue +101 -0
- package/vue-components/v2/loaders/SidebarLoader.vue +43 -0
- package/vue-components/v2/modal/Modal.vue +31 -5
- package/vue-components/v2/modals/DeleteConfirmationModal.vue +79 -0
- package/vue-components/v2/modals/JsonShowModal.vue +12 -2
- package/vue-components/v2/navbar/User.vue +229 -17
- package/vue-components/v2/notification/Notification.vue +101 -0
- package/vue-components/v2/notification/NotificationItem.vue +44 -0
- package/vue-components/v2/pagination/Pagination.vue +16 -3
- package/vue-components/v2/preloader/Preloader.vue +1 -1
- package/vue-components/v2/sidebar/SidebarItemWithDropDown.vue +19 -20
- package/vue-components/v2/tab/TabItem.vue +1 -1
- package/vue-components/v2/table/Table.vue +49 -8
- package/vue-components/v2/table/TableRow.vue +12 -2
- package/vue-components/v2/table/table-cell/CellValue.vue +29 -9
- package/vue-components/v2/table/table-cell/GenericCell.vue +56 -0
- package/vue-components/v2/table/table-cell/ObjectCell.vue +4 -1
- package/vue-components/v3/button/Button.vue +6 -1
- package/vue-components/v3/content/ContentHeader.vue +2 -1
- package/vue-components/v3/content/ContentTable.vue +25 -2
- package/vue-components/v3/editor/Editor.vue +36 -33
- package/vue-components/v3/editor/FilteredFileEditor.vue +186 -0
- package/vue-components/v3/editor/MonacoEditor.vue +131 -0
- package/vue-components/v3/editor/ResourceKeyValueEditor.vue +125 -0
- package/vue-components/v3/form/Form.vue +63 -0
- package/vue-components/v3/form-fields/Input.vue +11 -10
- package/vue-components/v3/header/HeaderItem.vue +5 -0
- package/vue-components/v3/header/HeaderItems.vue +5 -0
- package/vue-components/v3/loaders/ResourceLoader.vue +83 -0
- package/vue-components/v3/loaders/SidebarLoader.vue +34 -0
- package/vue-components/v3/long-running-tasks/LongRunningTaskItem.vue +92 -0
- package/vue-components/v3/modal/Modal.vue +35 -7
- package/vue-components/v3/modals/DeleteConfirmationModal.vue +85 -0
- package/vue-components/v3/modals/JsonShowModal.vue +25 -16
- package/vue-components/v3/modals/LongRunningTasksModal.vue +400 -0
- package/vue-components/v3/navbar/ThemeMode.vue +41 -49
- package/vue-components/v3/navbar/User.vue +242 -18
- package/vue-components/v3/notification/AlertBox.vue +61 -0
- package/vue-components/v3/notification/Notification.vue +98 -0
- package/vue-components/v3/notification/NotificationItem.vue +52 -0
- package/vue-components/v3/pagination/Pagination.vue +16 -3
- package/vue-components/v3/sidebar/SidebarItemWithDropDown.vue +120 -0
- package/vue-components/v3/tab/TabItem.vue +1 -1
- package/vue-components/v3/table/MultiInfoTable.vue +143 -0
- package/vue-components/v3/table/Table.vue +55 -14
- package/vue-components/v3/table/TableContainer.vue +34 -0
- package/vue-components/v3/table/TableRow.vue +93 -6
- package/vue-components/v3/table/table-cell/CellValue.vue +23 -7
- package/vue-components/v3/table/table-cell/GenericCell.vue +75 -0
- package/vue-components/v3/table/table-cell/ObjectCell.vue +7 -2
- package/vue-components/v3/terminal/LongRunningTaskTerminal.vue +148 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosResponse } from "axios";
|
|
2
|
+
import md5 from "crypto-js/md5";
|
|
3
|
+
import stringify from "fast-json-stable-stringify";
|
|
4
|
+
|
|
5
|
+
const resourceListApiRgx =
|
|
6
|
+
/^\/clusters\/([^/]+)\/([^/]+)\/proxy\/([^/]+)\/([^/]+)(\/namespaces\/([^/?]+))?\/([^/?]+)(.*)$/;
|
|
7
|
+
const usermenuUpdateApiRgx =
|
|
8
|
+
/^\/clusters\/([^/]+)\/([^/]+)\/proxy\/meta\.k8s\.appscode\.com\/([^/]+)\/usermenus\/cluster$/;
|
|
9
|
+
|
|
10
|
+
function getRequestInterceptor(config: AxiosRequestConfig) {
|
|
11
|
+
// get call
|
|
12
|
+
const { url, _recurringCall, params } = config;
|
|
13
|
+
const matchListApi = url?.match(resourceListApiRgx);
|
|
14
|
+
if (matchListApi) {
|
|
15
|
+
// url matches list / render api call
|
|
16
|
+
const [, user, cluster, group, version, , namespace, resource] =
|
|
17
|
+
matchListApi;
|
|
18
|
+
|
|
19
|
+
const suffix = `${user}.${cluster}.${group}.${version}.${resource}${
|
|
20
|
+
namespace ? ".ns." + namespace : ""
|
|
21
|
+
}${params ? ".q." + md5(stringify(params)).toString() : ""}`;
|
|
22
|
+
|
|
23
|
+
if (_recurringCall) {
|
|
24
|
+
// always send latest date time as ctag
|
|
25
|
+
return new Date().getTime();
|
|
26
|
+
} else {
|
|
27
|
+
// read ctag from local storage if exists
|
|
28
|
+
const storageKey = `ctag.${suffix}`;
|
|
29
|
+
// read local storage ctag
|
|
30
|
+
return localStorage.getItem(storageKey);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getResponseInterceptor(resp: AxiosResponse) {
|
|
36
|
+
// get call
|
|
37
|
+
const { config, headers } = resp;
|
|
38
|
+
const { url, _recurringCall, params } = config;
|
|
39
|
+
|
|
40
|
+
// queryParams without ctag
|
|
41
|
+
const queryParamsWithoutCtag = Object.keys(params).reduce((ob, key) => {
|
|
42
|
+
if (key !== "ctag") return { ...ob, [key]: params[key] };
|
|
43
|
+
else return { ...ob };
|
|
44
|
+
}, {});
|
|
45
|
+
|
|
46
|
+
const matchListApi = url?.match(resourceListApiRgx);
|
|
47
|
+
if (matchListApi) {
|
|
48
|
+
// url matches list / render api call
|
|
49
|
+
// window.console.log(matchListApi)
|
|
50
|
+
const [, user, cluster, group, version, , namespace, resource] =
|
|
51
|
+
matchListApi;
|
|
52
|
+
|
|
53
|
+
const suffix = `${user}.${cluster}.${group}.${version}.${resource}${
|
|
54
|
+
namespace ? ".ns." + namespace : ""
|
|
55
|
+
}${
|
|
56
|
+
params ? ".q." + md5(stringify(queryParamsWithoutCtag)).toString() : ""
|
|
57
|
+
}`;
|
|
58
|
+
|
|
59
|
+
const storageKey = `etag.${suffix}`;
|
|
60
|
+
// local storage etag
|
|
61
|
+
const eTag = localStorage.getItem(storageKey);
|
|
62
|
+
// etag in header
|
|
63
|
+
const headerEtag = headers?.["etag"];
|
|
64
|
+
|
|
65
|
+
// window.console.log({ eTag, headerEtag, _recurringCall, url });
|
|
66
|
+
|
|
67
|
+
if (_recurringCall) {
|
|
68
|
+
// for recurring api call
|
|
69
|
+
if (headerEtag && headerEtag !== eTag) {
|
|
70
|
+
// etag missmatch
|
|
71
|
+
if (params.ctag) {
|
|
72
|
+
// save request query parameter ctag into local storage
|
|
73
|
+
localStorage.setItem(`ctag.${suffix}`, params.ctag);
|
|
74
|
+
}
|
|
75
|
+
// update store etag with latest header etag
|
|
76
|
+
localStorage.setItem(`etag.${suffix}`, headerEtag);
|
|
77
|
+
|
|
78
|
+
if (namespace) {
|
|
79
|
+
// for namespaced list calls if etag missmatch happens
|
|
80
|
+
// update the ctag storage for all namespaces
|
|
81
|
+
// this will force the all namespaced list call to ignore disk cache
|
|
82
|
+
localStorage.setItem(
|
|
83
|
+
`etag.${user}.${cluster}.${group}.${version}.${resource}`,
|
|
84
|
+
new Date().getTime().toString()
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
// not recurring api call
|
|
90
|
+
if (eTag !== headerEtag && headerEtag) {
|
|
91
|
+
// if the etag missmatches, then the data has changed
|
|
92
|
+
// update local etag
|
|
93
|
+
localStorage.setItem(storageKey, headerEtag);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function putResponseInterceptor(resp: AxiosResponse) {
|
|
100
|
+
const { config } = resp;
|
|
101
|
+
const { url } = config;
|
|
102
|
+
const matchUsermenuUpdate = url?.match(usermenuUpdateApiRgx);
|
|
103
|
+
if (matchUsermenuUpdate) {
|
|
104
|
+
// user menu update api is called
|
|
105
|
+
const [, user, cluster, version] = matchUsermenuUpdate;
|
|
106
|
+
|
|
107
|
+
// calculate the local storage key
|
|
108
|
+
const renderStorageKey = `ctag.${user}.${cluster}.meta.k8s.appscode.com.${version}.rendermenus.q.${md5(
|
|
109
|
+
stringify({
|
|
110
|
+
apiVersion: `meta.k8s.appscode.com/${version}`,
|
|
111
|
+
kind: "RenderMenu",
|
|
112
|
+
request: {
|
|
113
|
+
menu: "cluster",
|
|
114
|
+
mode: "Accordion",
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
).toString()}`;
|
|
118
|
+
const availableMenuStorageKey = `ctag.${user}.${cluster}.meta.k8s.appscode.com.${version}.usermenus`;
|
|
119
|
+
|
|
120
|
+
// set new ctag to that storage key
|
|
121
|
+
// next time render menu is called, cached data won't be used
|
|
122
|
+
localStorage.setItem(renderStorageKey, new Date().getTime().toString());
|
|
123
|
+
// for all available menus api
|
|
124
|
+
localStorage.setItem(
|
|
125
|
+
availableMenuStorageKey,
|
|
126
|
+
new Date().getTime().toString()
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function handleCacheFromYamls(
|
|
132
|
+
yamls: Array<{
|
|
133
|
+
apiVersion: string;
|
|
134
|
+
kind: string;
|
|
135
|
+
metadata: { name: string; namespace: string };
|
|
136
|
+
}>,
|
|
137
|
+
user: string,
|
|
138
|
+
cluster: string,
|
|
139
|
+
gkToGvrMap: Record<string, string>
|
|
140
|
+
) {
|
|
141
|
+
return function () {
|
|
142
|
+
yamls.forEach((yaml) => {
|
|
143
|
+
const { apiVersion, kind, metadata } = yaml;
|
|
144
|
+
const { namespace } = metadata || {};
|
|
145
|
+
const apiVersionMatch = apiVersion.match(/^(([^/]+)\/)?([^/]+)$/);
|
|
146
|
+
if (apiVersionMatch) {
|
|
147
|
+
// separate the group and version
|
|
148
|
+
const [, , group] = apiVersionMatch;
|
|
149
|
+
const groupKind = `${group || "core"}/${kind}`;
|
|
150
|
+
const gvr = (gkToGvrMap && gkToGvrMap[groupKind]) || "";
|
|
151
|
+
|
|
152
|
+
const storageKeyPrefix = `ctag.${user}.${cluster}.${gvr.replaceAll(
|
|
153
|
+
"/",
|
|
154
|
+
"."
|
|
155
|
+
)}`;
|
|
156
|
+
|
|
157
|
+
// clear list cache for all namespaces
|
|
158
|
+
localStorage.setItem(
|
|
159
|
+
`${storageKeyPrefix}.q.${md5(
|
|
160
|
+
stringify({ convertToTable: true })
|
|
161
|
+
).toString()}`,
|
|
162
|
+
new Date().getTime().toString()
|
|
163
|
+
);
|
|
164
|
+
// clear list cache for specific namespace
|
|
165
|
+
localStorage.setItem(
|
|
166
|
+
`${storageKeyPrefix}.ns.${namespace || "default"}.q.${md5(
|
|
167
|
+
stringify({ convertToTable: true })
|
|
168
|
+
).toString()}`,
|
|
169
|
+
new Date().getTime().toString()
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// clear for genericresources and resourcesummaries
|
|
173
|
+
localStorage.setItem(
|
|
174
|
+
`ctag.${user}.${cluster}.core.k8s.appscode.com.v1alpha1.resourcesummaries.q.${md5(
|
|
175
|
+
stringify({
|
|
176
|
+
convertToTable: true,
|
|
177
|
+
labelSelector: `k8s.io/group=${group}`,
|
|
178
|
+
})
|
|
179
|
+
).toString()}`,
|
|
180
|
+
new Date().getTime().toString()
|
|
181
|
+
);
|
|
182
|
+
localStorage.setItem(
|
|
183
|
+
`ctag.${user}.${cluster}.core.k8s.appscode.com.v1alpha1.resourcesummaries.q.${md5(
|
|
184
|
+
stringify({
|
|
185
|
+
convertToTable: true,
|
|
186
|
+
labelSelector: `k8s.io/group-kind=${kind}.${group}`,
|
|
187
|
+
})
|
|
188
|
+
).toString()}`,
|
|
189
|
+
new Date().getTime().toString()
|
|
190
|
+
);
|
|
191
|
+
localStorage.setItem(
|
|
192
|
+
`ctag.${user}.${cluster}.core.k8s.appscode.com.v1alpha1.genericresources.q.${md5(
|
|
193
|
+
stringify({
|
|
194
|
+
convertToTable: true,
|
|
195
|
+
labelSelector: `k8s.io/group=${group}`,
|
|
196
|
+
})
|
|
197
|
+
).toString()}`,
|
|
198
|
+
new Date().getTime().toString()
|
|
199
|
+
);
|
|
200
|
+
localStorage.setItem(
|
|
201
|
+
`ctag.${user}.${cluster}.core.k8s.appscode.com.v1alpha1.genericresources.q.${md5(
|
|
202
|
+
stringify({
|
|
203
|
+
convertToTable: true,
|
|
204
|
+
labelSelector: `k8s.io/group-kind=${kind}.${group}`,
|
|
205
|
+
})
|
|
206
|
+
).toString()}`,
|
|
207
|
+
new Date().getTime().toString()
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export async function requestInterceptor(config: AxiosRequestConfig) {
|
|
215
|
+
// parse the request url
|
|
216
|
+
const { method, params } = config;
|
|
217
|
+
|
|
218
|
+
let ctag;
|
|
219
|
+
|
|
220
|
+
if (method === "get") {
|
|
221
|
+
ctag = getRequestInterceptor(config);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
...config,
|
|
226
|
+
params: { ...params, ctag },
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function responseInterceptor(resp: AxiosResponse) {
|
|
231
|
+
const { config } = resp;
|
|
232
|
+
// parse the request url
|
|
233
|
+
const { method } = config;
|
|
234
|
+
|
|
235
|
+
if (method === "get") {
|
|
236
|
+
// get call
|
|
237
|
+
getResponseInterceptor(resp);
|
|
238
|
+
} else if (method === "put") {
|
|
239
|
+
putResponseInterceptor(resp);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return resp;
|
|
243
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import moment from "moment";
|
|
2
|
+
import { useNow, useThrottleFn } from "@vueuse/core";
|
|
3
|
+
|
|
4
|
+
const getTime = option => {
|
|
5
|
+
if (parseInt(option.time, 10) < 0 || !option.time) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
let time = option.time;
|
|
9
|
+
|
|
10
|
+
// moment(option.time).valueOf('x') needs to convert pharmer's api date to epoch time
|
|
11
|
+
time = moment(option.time).valueOf("x")
|
|
12
|
+
? moment(option.time).valueOf("x")
|
|
13
|
+
: time * 1000;
|
|
14
|
+
|
|
15
|
+
return moment(time).format("MMM DD YYYY, h:mm A");
|
|
16
|
+
};
|
|
17
|
+
const getDayDifferences = options => {
|
|
18
|
+
const past = moment(options.past).isValid()
|
|
19
|
+
? moment(options.past).valueOf("x") / 1000
|
|
20
|
+
: options.past;
|
|
21
|
+
const now = Date.now() / 1000;
|
|
22
|
+
const diff = now - past;
|
|
23
|
+
if (parseInt(options.past, 10) > 10) {
|
|
24
|
+
let ret = Math.floor(diff / 86400);
|
|
25
|
+
let unit = "";
|
|
26
|
+
if (diff < 60) {
|
|
27
|
+
ret = parseInt(diff, 10);
|
|
28
|
+
unit = " Second";
|
|
29
|
+
} else if (diff < 3600) {
|
|
30
|
+
ret = parseInt(diff / 60, 10);
|
|
31
|
+
unit = " Minute";
|
|
32
|
+
} else if (diff < 86400) {
|
|
33
|
+
ret = parseInt(diff / 3600, 10);
|
|
34
|
+
unit = " Hour";
|
|
35
|
+
} else {
|
|
36
|
+
ret = parseInt(diff / 86400, 10);
|
|
37
|
+
unit = " Day";
|
|
38
|
+
}
|
|
39
|
+
unit += ret > 1 ? "s" : "";
|
|
40
|
+
return ret + unit;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default {
|
|
46
|
+
getTime,
|
|
47
|
+
// formatMoment,
|
|
48
|
+
getDayDifferences
|
|
49
|
+
};
|
package/plugins/vue-toaster.js
CHANGED
|
@@ -41,6 +41,7 @@ module.exports = {
|
|
|
41
41
|
},
|
|
42
42
|
options: {
|
|
43
43
|
icon: "fa-warning",
|
|
44
|
+
duration: 20000,
|
|
44
45
|
type: "error",
|
|
45
46
|
className: "ac-toast is-error",
|
|
46
47
|
},
|
|
@@ -56,6 +57,7 @@ module.exports = {
|
|
|
56
57
|
},
|
|
57
58
|
options: {
|
|
58
59
|
icon: "fa-info",
|
|
60
|
+
duration: 20000,
|
|
59
61
|
type: "info",
|
|
60
62
|
className: "ac-toast is-info",
|
|
61
63
|
},
|
|
@@ -73,6 +75,7 @@ module.exports = {
|
|
|
73
75
|
},
|
|
74
76
|
options: {
|
|
75
77
|
icon: "fa-warning",
|
|
78
|
+
duration: 2500,
|
|
76
79
|
type: "error",
|
|
77
80
|
className: "ac-toast is-warning",
|
|
78
81
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="sign-up-notification mb-20">
|
|
3
3
|
<div class="notification-inner has-text-centered">
|
|
4
|
-
<h3><slot name="banner-title"
|
|
5
|
-
<slot
|
|
4
|
+
<h3><slot name="banner-title">Error!</slot></h3>
|
|
5
|
+
<slot><p>Oops!! There was an error while loading!</p></slot>
|
|
6
6
|
</div>
|
|
7
7
|
</div>
|
|
8
8
|
</template>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ac-breadcrumb">
|
|
3
|
+
<nav aria-label="breadcrumbs" class="breadcrumb">
|
|
4
|
+
<ul>
|
|
5
|
+
<li
|
|
6
|
+
v-for="(item, idx) in list"
|
|
7
|
+
:key="idx"
|
|
8
|
+
:class="{ 'is-active': idx === list.length - 1 }"
|
|
9
|
+
>
|
|
10
|
+
<router-link
|
|
11
|
+
class="router-link-active"
|
|
12
|
+
:class="{ 'is-active': idx === list.length - 1 }"
|
|
13
|
+
:to="item.path"
|
|
14
|
+
>{{ item.name }}
|
|
15
|
+
</router-link>
|
|
16
|
+
</li>
|
|
17
|
+
</ul>
|
|
18
|
+
</nav>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
<script>
|
|
22
|
+
export default {
|
|
23
|
+
data() {
|
|
24
|
+
return {
|
|
25
|
+
list: []
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
methods: {
|
|
29
|
+
createBreadcrumbs(n) {
|
|
30
|
+
//Adding dynamic path to the route
|
|
31
|
+
const listPaths = this.$route.matched.map(element =>
|
|
32
|
+
this.pathReplaceWithParam(element.path)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
//Removing the last duplicate value from the listpaths array
|
|
36
|
+
listPaths.pop();
|
|
37
|
+
|
|
38
|
+
//Createing the breadcrumb name
|
|
39
|
+
const listName = this.createList(listPaths);
|
|
40
|
+
|
|
41
|
+
//Set the new breadcrumb name and path value to list
|
|
42
|
+
this.list = listName.map((element, index) => {
|
|
43
|
+
return {
|
|
44
|
+
name: element,
|
|
45
|
+
path: listPaths[index]
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
pathReplaceWithParam(path) {
|
|
50
|
+
//Split the path and remove the first and last empty block
|
|
51
|
+
let splitPath = path.split("/").filter(element => element !== "");
|
|
52
|
+
|
|
53
|
+
//Replace all element with query params where the element start with ":"
|
|
54
|
+
// Then again add them wthi "/" and return the path value
|
|
55
|
+
return splitPath.reduce((pval, cval) => {
|
|
56
|
+
if (cval[0] === ":") {
|
|
57
|
+
const cutIndex =
|
|
58
|
+
cval.indexOf("?") !== -1 ? cval.indexOf("?") : cval.length;
|
|
59
|
+
return (pval += this.$route.params[cval.slice(1, cutIndex)] + "/");
|
|
60
|
+
} else return (pval += cval + "/");
|
|
61
|
+
}, "/");
|
|
62
|
+
},
|
|
63
|
+
createList(paths) {
|
|
64
|
+
//Split all the path and remove all empty block
|
|
65
|
+
let spath = paths.map(element => {
|
|
66
|
+
return element.split("/").filter(word => word !== "");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Convert all the path arry in one arry where each element is the different fo previous element
|
|
70
|
+
return spath.reduce((prev, curr, currentIdx) => {
|
|
71
|
+
if (currentIdx === 0) return prev.concat([this.createVal(0, curr)]);
|
|
72
|
+
else
|
|
73
|
+
return prev.concat([
|
|
74
|
+
this.createVal(spath[currentIdx - 1].length, curr)
|
|
75
|
+
]);
|
|
76
|
+
}, []);
|
|
77
|
+
},
|
|
78
|
+
createVal(startIdx, paths) {
|
|
79
|
+
return paths.reduce((prev, curr, idx) => {
|
|
80
|
+
if (idx >= startIdx) {
|
|
81
|
+
if (idx + 1 === paths.length) return (prev += curr);
|
|
82
|
+
else return (prev += curr + " / ");
|
|
83
|
+
} else return prev + "";
|
|
84
|
+
}, "");
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
watch: {
|
|
88
|
+
"$route.path": {
|
|
89
|
+
deep: true,
|
|
90
|
+
immediate: true,
|
|
91
|
+
handler(n) {
|
|
92
|
+
this.createBreadcrumbs(n);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
</script>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
:class="`${modifierClasses}${isLoaderActive ? ' is-loading' : ''}`"
|
|
5
5
|
:disabled="disabled"
|
|
6
6
|
@click="handleClick"
|
|
7
|
+
:title="tooltip"
|
|
7
8
|
>
|
|
8
9
|
<span v-if="iconClass || iconImage" class="icon is-small">
|
|
9
10
|
<img
|
|
@@ -27,6 +28,10 @@ export default {
|
|
|
27
28
|
type: String,
|
|
28
29
|
default: "",
|
|
29
30
|
},
|
|
31
|
+
tooltip: {
|
|
32
|
+
type: String,
|
|
33
|
+
defualt: undefined
|
|
34
|
+
},
|
|
30
35
|
// for loader
|
|
31
36
|
isLoaderActive: {
|
|
32
37
|
type: Boolean,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ac-button
|
|
3
|
+
modifier-classes="is-primary is-square"
|
|
4
|
+
icon-class="download"
|
|
5
|
+
:is-loader-active="isFetching"
|
|
6
|
+
@click="download()"
|
|
7
|
+
/>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script>
|
|
11
|
+
import downloadFunc from "downloadjs";
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
components: {
|
|
15
|
+
AcButton: () => import("./../button/Button.vue")
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
fileData: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: ""
|
|
21
|
+
},
|
|
22
|
+
fileName: {
|
|
23
|
+
type: String,
|
|
24
|
+
default: ""
|
|
25
|
+
},
|
|
26
|
+
isFetching: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: false
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
data() {
|
|
32
|
+
return {
|
|
33
|
+
downloadIcon: "fa fa-cloud-download"
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
component: {
|
|
37
|
+
downloadFunc
|
|
38
|
+
},
|
|
39
|
+
methods: {
|
|
40
|
+
download() {
|
|
41
|
+
downloadFunc(this.fileData, this.fileName);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
</script>
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
<content-layout>
|
|
3
3
|
<template #content-header>
|
|
4
4
|
<content-header
|
|
5
|
+
v-if="!hideHeader"
|
|
5
6
|
:header-title="tableTitle"
|
|
6
7
|
:header-sub-title="tableSubTitle"
|
|
8
|
+
:remove-border-bottom="removeBorderBottom"
|
|
7
9
|
:class="{ 'pl-0 pr-0': removeTableHeaderPadding }"
|
|
8
10
|
>
|
|
9
11
|
<header-item>
|
|
@@ -35,6 +37,14 @@ export default {
|
|
|
35
37
|
type: Boolean,
|
|
36
38
|
default: true,
|
|
37
39
|
},
|
|
40
|
+
hideHeader: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
removeBorderBottom: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
38
48
|
},
|
|
39
49
|
components: {
|
|
40
50
|
ContentLayout: () => import("./ContentLayout.vue"),
|
|
@@ -7,21 +7,22 @@
|
|
|
7
7
|
/>
|
|
8
8
|
<monaco-editor
|
|
9
9
|
v-if="activeTab === 'edit'"
|
|
10
|
-
ref="monacoEditor"
|
|
11
10
|
@editorDidMount="onEditorMount"
|
|
12
11
|
key="edit"
|
|
13
12
|
:class="`vh-${editorHeight} is-clipped`"
|
|
14
|
-
|
|
13
|
+
:value="editorContent"
|
|
14
|
+
@change="onChange"
|
|
15
15
|
:language="language"
|
|
16
16
|
:options="{
|
|
17
17
|
minimap: {
|
|
18
|
-
enabled: calcShowMinimap
|
|
18
|
+
enabled: calcShowMinimap,
|
|
19
19
|
},
|
|
20
20
|
theme: theme,
|
|
21
21
|
readOnly: readOnly,
|
|
22
22
|
wordWrap: wordWrap,
|
|
23
|
-
scrollBeyondLastLine: false
|
|
23
|
+
scrollBeyondLastLine: false,
|
|
24
24
|
}"
|
|
25
|
+
data-testid="monaco-editor-edit-section"
|
|
25
26
|
/>
|
|
26
27
|
<monaco-editor
|
|
27
28
|
v-if="activeTab === 'preview'"
|
|
@@ -31,65 +32,75 @@
|
|
|
31
32
|
:language="language"
|
|
32
33
|
:options="{
|
|
33
34
|
minimap: {
|
|
34
|
-
enabled: calcShowMinimap
|
|
35
|
+
enabled: calcShowMinimap,
|
|
35
36
|
},
|
|
36
37
|
theme: theme,
|
|
37
38
|
readOnly: true,
|
|
38
39
|
wordWrap: wordWrap,
|
|
39
|
-
scrollBeyondLastLine: false
|
|
40
|
+
scrollBeyondLastLine: false,
|
|
40
41
|
}"
|
|
41
42
|
:original="originalEditorContent"
|
|
42
43
|
:diff-editor="true"
|
|
44
|
+
data-testid="monaco-editor-preview-section"
|
|
43
45
|
/>
|
|
44
46
|
</div>
|
|
45
47
|
</template>
|
|
46
48
|
|
|
47
49
|
<script>
|
|
50
|
+
import Preloader from "../preloader/Preloader.vue";
|
|
51
|
+
import Banner from "../banner/Banner.vue";
|
|
48
52
|
export default {
|
|
49
53
|
props: {
|
|
50
54
|
value: {
|
|
51
55
|
type: String,
|
|
52
|
-
default: ""
|
|
56
|
+
default: "",
|
|
53
57
|
},
|
|
54
58
|
originalValue: {
|
|
55
59
|
type: String,
|
|
56
|
-
default: ""
|
|
60
|
+
default: "",
|
|
57
61
|
},
|
|
58
62
|
readOnly: {
|
|
59
63
|
type: Boolean,
|
|
60
|
-
default: false
|
|
64
|
+
default: false,
|
|
61
65
|
},
|
|
62
66
|
language: {
|
|
63
67
|
type: String,
|
|
64
|
-
default: "yaml"
|
|
68
|
+
default: "yaml",
|
|
65
69
|
},
|
|
66
70
|
showMinimap: {
|
|
67
71
|
type: Boolean,
|
|
68
|
-
default: true
|
|
72
|
+
default: true,
|
|
69
73
|
},
|
|
70
74
|
editorHeight: {
|
|
71
75
|
type: Number,
|
|
72
|
-
default: 40
|
|
76
|
+
default: 40,
|
|
73
77
|
},
|
|
74
78
|
editorTheme: {
|
|
75
79
|
type: String,
|
|
76
|
-
default: ""
|
|
80
|
+
default: "",
|
|
77
81
|
},
|
|
78
82
|
wordWrap: {
|
|
79
83
|
type: String,
|
|
80
|
-
default: "off"
|
|
84
|
+
default: "off",
|
|
81
85
|
},
|
|
82
86
|
},
|
|
87
|
+
|
|
83
88
|
components: {
|
|
84
89
|
EditorTabs: () => import("../tabs/EditorTabs.vue"),
|
|
85
|
-
MonacoEditor: () =>
|
|
90
|
+
MonacoEditor: () => ({
|
|
91
|
+
component: import("./MonacoEditor.vue"),
|
|
92
|
+
loading: Preloader,
|
|
93
|
+
delay: 200,
|
|
94
|
+
error: Banner,
|
|
95
|
+
timeout: 100000,
|
|
96
|
+
}),
|
|
86
97
|
},
|
|
87
98
|
|
|
88
99
|
data() {
|
|
89
100
|
return {
|
|
90
101
|
activeTab: "edit",
|
|
91
102
|
editorContent: "",
|
|
92
|
-
originalEditorContent: ""
|
|
103
|
+
originalEditorContent: "",
|
|
93
104
|
};
|
|
94
105
|
},
|
|
95
106
|
|
|
@@ -105,7 +116,7 @@ export default {
|
|
|
105
116
|
? "vs-dark"
|
|
106
117
|
: "vs")
|
|
107
118
|
);
|
|
108
|
-
}
|
|
119
|
+
},
|
|
109
120
|
},
|
|
110
121
|
|
|
111
122
|
watch: {
|
|
@@ -115,7 +126,7 @@ export default {
|
|
|
115
126
|
if (this.editorContent !== n) {
|
|
116
127
|
this.editorContent = n;
|
|
117
128
|
}
|
|
118
|
-
}
|
|
129
|
+
},
|
|
119
130
|
},
|
|
120
131
|
originalValue: {
|
|
121
132
|
immediate: true,
|
|
@@ -123,18 +134,20 @@ export default {
|
|
|
123
134
|
if (this.originalEditorContent !== n) {
|
|
124
135
|
this.originalEditorContent = n;
|
|
125
136
|
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
137
|
+
},
|
|
138
|
+
},
|
|
128
139
|
},
|
|
129
140
|
|
|
130
141
|
methods: {
|
|
131
|
-
|
|
132
|
-
|
|
142
|
+
onChange(e) {
|
|
143
|
+
if (typeof e === "string") this.editorContent = e;
|
|
144
|
+
},
|
|
145
|
+
onEditorMount(editor) {
|
|
133
146
|
// add event listeners
|
|
134
147
|
editor.onDidBlurEditorText(() => {
|
|
135
148
|
this.$emit("input", this.editorContent);
|
|
136
149
|
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
139
152
|
};
|
|
140
153
|
</script>
|