@rancher/shell 0.3.7 → 0.3.9
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/assets/translations/en-us.yaml +55 -14
- package/babel.config.js +17 -4
- package/components/CodeMirror.vue +146 -14
- package/components/ContainerResourceLimit.vue +14 -1
- package/components/CruResource.vue +21 -5
- package/components/ExplorerProjectsNamespaces.vue +5 -1
- package/components/GroupPanel.vue +57 -0
- package/components/Inactivity.vue +229 -0
- package/components/YamlEditor.vue +2 -2
- package/components/form/ArrayList.vue +1 -1
- package/components/form/KeyValue.vue +34 -1
- package/components/form/MatchExpressions.vue +120 -21
- package/components/form/NodeAffinity.vue +54 -4
- package/components/form/PodAffinity.vue +160 -47
- package/components/form/Tolerations.vue +40 -4
- package/components/form/__tests__/ArrayList.test.ts +3 -3
- package/components/form/__tests__/MatchExpressions.test.ts +1 -1
- package/components/nav/Header.vue +2 -0
- package/config/settings.ts +10 -1
- package/core/plugins-loader.js +0 -2
- package/creators/app/files/.gitignore +73 -0
- package/creators/app/init +1 -0
- package/edit/configmap.vue +33 -6
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +326 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +63 -15
- package/edit/workload/mixins/workload.js +12 -4
- package/layouts/blank.vue +4 -0
- package/layouts/default.vue +3 -0
- package/layouts/home.vue +4 -1
- package/layouts/plain.vue +4 -1
- package/mixins/chart.js +1 -1
- package/models/batch.cronjob.js +18 -3
- package/models/provisioning.cattle.io.cluster.js +24 -0
- package/models/workload.js +1 -1
- package/package.json +2 -3
- package/pages/auth/login.vue +1 -0
- package/pages/c/_cluster/explorer/index.vue +1 -4
- package/pages/c/_cluster/settings/performance.vue +61 -7
- package/pages/prefs.vue +18 -2
- package/pkg/vue.config.js +0 -1
- package/plugins/codemirror.js +158 -0
- package/public/index.html +1 -1
- package/store/index.js +36 -21
- package/types/shell/index.d.ts +20 -1
- package/utils/create-yaml.js +105 -8
- package/utils/settings.ts +12 -0
- package/vue.config.js +2 -2
package/pkg/vue.config.js
CHANGED
|
@@ -82,7 +82,6 @@ module.exports = function(dir) {
|
|
|
82
82
|
// These modules will be externalised and not included with the build of a package library
|
|
83
83
|
// This helps reduce the package size, but these dependencies must be provided by the hosting application
|
|
84
84
|
config.externals = {
|
|
85
|
-
jquery: '$',
|
|
86
85
|
jszip: '__jszip',
|
|
87
86
|
'js-yaml': '__jsyaml'
|
|
88
87
|
};
|
package/plugins/codemirror.js
CHANGED
|
@@ -167,3 +167,161 @@ CodeMirror.registerHelper('fold', 'yamlcomments', (cm, start) => {
|
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
169
|
});
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* It display a dot for each space character in the text;
|
|
173
|
+
* used in combination with 'as-text-area' css properties in CodeMirror.vue to display line break markdowns
|
|
174
|
+
*/
|
|
175
|
+
CodeMirror.defineOption('showMarkdownLineBreaks', false, (codeMirror) => {
|
|
176
|
+
codeMirror.addOverlay({
|
|
177
|
+
name: 'show-markdown-line-breaks',
|
|
178
|
+
token: (stream) => {
|
|
179
|
+
if (stream.string[stream.pos].match(/\s/)) {
|
|
180
|
+
stream.next();
|
|
181
|
+
|
|
182
|
+
return stream.pos % 2 === 0 ? 'markdown-single-trailing-space-even' : 'markdown-single-trailing-space-odd';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
stream.next();
|
|
186
|
+
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* It enables the text color selection in CodeMirror.vue
|
|
194
|
+
* references:
|
|
195
|
+
* demo: https://codemirror.net/5/demo/markselection.html#
|
|
196
|
+
* add-on: https://codemirror.net/5/doc/manual.html#addon_mark-selection
|
|
197
|
+
* source: https://codemirror.net/5/addon/selection/mark-selection.js
|
|
198
|
+
*/
|
|
199
|
+
CodeMirror.defineOption('styleSelectedText', false, (cm, val, old) => {
|
|
200
|
+
const prev = old && old !== CodeMirror.Init;
|
|
201
|
+
|
|
202
|
+
if (val && !prev) {
|
|
203
|
+
cm.state.markedSelection = [];
|
|
204
|
+
cm.state.markedSelectionStyle = typeof val === 'string' ? val : 'CodeMirror-selectedtext';
|
|
205
|
+
reset(cm);
|
|
206
|
+
cm.on('cursorActivity', onCursorActivity);
|
|
207
|
+
cm.on('change', onChange);
|
|
208
|
+
} else if (!val && prev) {
|
|
209
|
+
cm.off('cursorActivity', onCursorActivity);
|
|
210
|
+
cm.off('change', onChange);
|
|
211
|
+
clear(cm);
|
|
212
|
+
cm.state.markedSelection = cm.state.markedSelectionStyle = null;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
function onCursorActivity(cm) {
|
|
217
|
+
if (cm.state.markedSelection) {
|
|
218
|
+
cm.operation(() => {
|
|
219
|
+
update(cm);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function onChange(cm) {
|
|
225
|
+
if (cm.state.markedSelection && cm.state.markedSelection.length) {
|
|
226
|
+
cm.operation(() => {
|
|
227
|
+
clear(cm);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const CHUNK_SIZE = 8;
|
|
233
|
+
const Pos = CodeMirror.Pos;
|
|
234
|
+
const cmp = CodeMirror.cmpPos;
|
|
235
|
+
|
|
236
|
+
function coverRange(cm, from, to, addAt) {
|
|
237
|
+
if (cmp(from, to) === 0) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const array = cm.state.markedSelection;
|
|
241
|
+
const cls = cm.state.markedSelectionStyle;
|
|
242
|
+
|
|
243
|
+
for (let line = from.line;;) {
|
|
244
|
+
const start = line === from.line ? from : Pos(line, 0);
|
|
245
|
+
const endLine = line + CHUNK_SIZE; const atEnd = endLine >= to.line;
|
|
246
|
+
const end = atEnd ? to : Pos(endLine, 0);
|
|
247
|
+
const mark = cm.markText(start, end, { className: cls });
|
|
248
|
+
|
|
249
|
+
if (addAt === null || addAt === undefined) {
|
|
250
|
+
array.push(mark);
|
|
251
|
+
} else {
|
|
252
|
+
array.splice(addAt++, 0, mark);
|
|
253
|
+
}
|
|
254
|
+
if (atEnd) {
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
line = endLine;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function clear(cm) {
|
|
262
|
+
const array = cm.state.markedSelection;
|
|
263
|
+
|
|
264
|
+
for (let i = 0; i < array.length; ++i) {
|
|
265
|
+
array[i].clear();
|
|
266
|
+
}
|
|
267
|
+
array.length = 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function reset(cm) {
|
|
271
|
+
clear(cm);
|
|
272
|
+
const ranges = cm.listSelections();
|
|
273
|
+
|
|
274
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
275
|
+
coverRange(cm, ranges[i].from(), ranges[i].to());
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function update(cm) {
|
|
280
|
+
if (!cm.somethingSelected()) {
|
|
281
|
+
return clear(cm);
|
|
282
|
+
}
|
|
283
|
+
if (cm.listSelections().length > 1) {
|
|
284
|
+
return reset(cm);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const from = cm.getCursor('start'); const to = cm.getCursor('end');
|
|
288
|
+
|
|
289
|
+
const array = cm.state.markedSelection;
|
|
290
|
+
|
|
291
|
+
if (!array.length) {
|
|
292
|
+
return coverRange(cm, from, to);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
let coverStart = array[0].find(); let coverEnd = array[array.length - 1].find();
|
|
296
|
+
|
|
297
|
+
if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
|
|
298
|
+
cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) {
|
|
299
|
+
return reset(cm);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
while (cmp(from, coverStart.from) > 0) {
|
|
303
|
+
array.shift().clear();
|
|
304
|
+
coverStart = array[0].find();
|
|
305
|
+
}
|
|
306
|
+
if (cmp(from, coverStart.from) < 0) {
|
|
307
|
+
if (coverStart.to.line - from.line < CHUNK_SIZE) {
|
|
308
|
+
array.shift().clear();
|
|
309
|
+
coverRange(cm, from, coverStart.to, 0);
|
|
310
|
+
} else {
|
|
311
|
+
coverRange(cm, from, coverStart.from, 0);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
while (cmp(to, coverEnd.to) < 0) {
|
|
316
|
+
array.pop().clear();
|
|
317
|
+
coverEnd = array[array.length - 1].find();
|
|
318
|
+
}
|
|
319
|
+
if (cmp(to, coverEnd.to) > 0) {
|
|
320
|
+
if (to.line - coverEnd.from.line < CHUNK_SIZE) {
|
|
321
|
+
array.pop().clear();
|
|
322
|
+
coverRange(cm, coverEnd.from, to);
|
|
323
|
+
} else {
|
|
324
|
+
coverRange(cm, coverEnd.to, to);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
package/public/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta charset="utf-8">
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
7
7
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
8
|
-
<link rel="shortcut icon" type="image/x-icon" href="/
|
|
8
|
+
<link rel="shortcut icon" type="image/x-icon" href="/favicon.png">
|
|
9
9
|
<title>Rancher</title>
|
|
10
10
|
</head>
|
|
11
11
|
|
package/store/index.js
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
COUNT, NAMESPACE, NORMAN, MANAGEMENT, FLEET, UI, VIRTUAL_HARVESTER_PROVIDER, DEFAULT_WORKSPACE
|
|
4
|
-
} from '@shell/config/types';
|
|
5
|
-
import { CLUSTER as CLUSTER_PREF, NAMESPACE_FILTERS, LAST_NAMESPACE, WORKSPACE } from '@shell/store/prefs';
|
|
6
|
-
import { allHash, allHashSettled } from '@shell/utils/promise';
|
|
7
|
-
import { ClusterNotFoundError, ApiError } from '@shell/utils/error';
|
|
8
|
-
import { sortBy } from '@shell/utils/sort';
|
|
9
|
-
import { filterBy, findBy } from '@shell/utils/array';
|
|
10
|
-
import { BOTH, CLUSTER_LEVEL, NAMESPACED } from '@shell/store/type-map';
|
|
11
|
-
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
12
|
-
import { TIMED_OUT, LOGGED_OUT, _FLAGGED, UPGRADED } from '@shell/config/query-params';
|
|
1
|
+
import { BACK_TO } from '@shell/config/local-storage';
|
|
13
2
|
import { setBrand, setVendor } from '@shell/config/private-label';
|
|
14
|
-
import {
|
|
3
|
+
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
4
|
+
import { LOGGED_OUT, TIMED_OUT, UPGRADED, _FLAGGED } from '@shell/config/query-params';
|
|
15
5
|
import { SETTING } from '@shell/config/settings';
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
import {
|
|
7
|
+
COUNT,
|
|
8
|
+
DEFAULT_WORKSPACE,
|
|
9
|
+
FLEET,
|
|
10
|
+
MANAGEMENT,
|
|
11
|
+
NAMESPACE, NORMAN,
|
|
12
|
+
UI, VIRTUAL_HARVESTER_PROVIDER
|
|
13
|
+
} from '@shell/config/types';
|
|
19
14
|
import { BY_TYPE } from '@shell/plugins/dashboard-store/classify';
|
|
15
|
+
import Steve from '@shell/plugins/steve';
|
|
16
|
+
import { STEVE_MODEL_TYPES } from '@shell/plugins/steve/getters';
|
|
17
|
+
import { CLUSTER as CLUSTER_PREF, LAST_NAMESPACE, NAMESPACE_FILTERS, WORKSPACE } from '@shell/store/prefs';
|
|
18
|
+
import { BOTH, CLUSTER_LEVEL, NAMESPACED } from '@shell/store/type-map';
|
|
19
|
+
import { filterBy, findBy } from '@shell/utils/array';
|
|
20
|
+
import { ApiError, ClusterNotFoundError } from '@shell/utils/error';
|
|
21
|
+
import { gcActions, gcGetters } from '@shell/utils/gc/gc-root-store';
|
|
20
22
|
import {
|
|
21
|
-
NAMESPACE_FILTER_ALL_USER as ALL_USER,
|
|
22
|
-
NAMESPACE_FILTER_ALL_SYSTEM as ALL_SYSTEM,
|
|
23
23
|
NAMESPACE_FILTER_ALL_ORPHANS as ALL_ORPHANS,
|
|
24
|
-
|
|
24
|
+
NAMESPACE_FILTER_ALL_SYSTEM as ALL_SYSTEM,
|
|
25
|
+
NAMESPACE_FILTER_ALL_USER as ALL_USER,
|
|
25
26
|
NAMESPACE_FILTER_NAMESPACED_NO as NAMESPACED_NO,
|
|
26
27
|
NAMESPACE_FILTER_NAMESPACED_PREFIX as NAMESPACED_PREFIX,
|
|
28
|
+
NAMESPACE_FILTER_NAMESPACED_YES as NAMESPACED_YES,
|
|
27
29
|
splitNamespaceFilterKey,
|
|
28
30
|
} from '@shell/utils/namespace-filter';
|
|
29
|
-
import {
|
|
31
|
+
import { allHash, allHashSettled } from '@shell/utils/promise';
|
|
32
|
+
import { sortBy } from '@shell/utils/sort';
|
|
33
|
+
import { addParam } from '@shell/utils/url';
|
|
34
|
+
import semver from 'semver';
|
|
30
35
|
|
|
31
36
|
// Disables strict mode for all store instances to prevent warning about changing state outside of mutations
|
|
32
37
|
// because it's more efficient to do that sometimes.
|
|
@@ -591,7 +596,6 @@ export const mutations = {
|
|
|
591
596
|
state.isMultiCluster = isMultiCluster;
|
|
592
597
|
state.isRancher = isRancher;
|
|
593
598
|
},
|
|
594
|
-
|
|
595
599
|
clusterReady(state, ready) {
|
|
596
600
|
state.clusterReady = ready;
|
|
597
601
|
},
|
|
@@ -1122,5 +1126,16 @@ export const actions = {
|
|
|
1122
1126
|
commit(`setIsSingleProduct`, isSingleProduct);
|
|
1123
1127
|
},
|
|
1124
1128
|
|
|
1129
|
+
unsubscribe( { state, dispatch }) {
|
|
1130
|
+
// It would be nice to grab all vuex module stores that we've registered, apparently this is only possible via the
|
|
1131
|
+
// internal properties store._modules.root._children.
|
|
1132
|
+
// So instead loop through all state entries to find stores
|
|
1133
|
+
return Object.entries(state).filter(([storeName, storeState]) => {
|
|
1134
|
+
if (storeState?.allowStreaming) {
|
|
1135
|
+
dispatch(`${ storeName }/unsubscribe`);
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
},
|
|
1139
|
+
|
|
1125
1140
|
...gcActions
|
|
1126
1141
|
};
|
package/types/shell/index.d.ts
CHANGED
|
@@ -2491,10 +2491,29 @@ export default _default;
|
|
|
2491
2491
|
// @shell/utils/create-yaml
|
|
2492
2492
|
|
|
2493
2493
|
declare module '@shell/utils/create-yaml' {
|
|
2494
|
-
export function
|
|
2494
|
+
export function createYamlWithOptions(schemas: any, type: any, data: any, options: any): string;
|
|
2495
|
+
export function createYaml(schemas: any, type: any, data: any, processAlwaysAdd?: boolean, depth?: number, path?: string, rootType?: any, dataOptions?: {}): string;
|
|
2495
2496
|
export function typeRef(type: any, str: any): any;
|
|
2496
2497
|
export function typeMunge(type: any): any;
|
|
2497
2498
|
export function saferDump(obj: any): any;
|
|
2499
|
+
/**
|
|
2500
|
+
* Handles newlines indicators in the multiline blocks.
|
|
2501
|
+
*
|
|
2502
|
+
* this is required since jsyaml.dump doesn't support chomping and scalar style at the moment.
|
|
2503
|
+
* see: https://github.com/nodeca/js-yaml/issues/171
|
|
2504
|
+
*
|
|
2505
|
+
* @param {*} data the multiline block
|
|
2506
|
+
* @param {*} options blocks indicators, see: https://yaml-multiline.info
|
|
2507
|
+
*
|
|
2508
|
+
* - scalarStyle:
|
|
2509
|
+
* one of '|', '>'
|
|
2510
|
+
* default '|'
|
|
2511
|
+
* - chomping:
|
|
2512
|
+
* one of: null, '-', '+'
|
|
2513
|
+
* default: null
|
|
2514
|
+
* @returns the result of jsyaml.dump with the addition of multiline indicators
|
|
2515
|
+
*/
|
|
2516
|
+
export function dumpBlock(data: any, options?: any): any;
|
|
2498
2517
|
export const SIMPLE_TYPES: string[];
|
|
2499
2518
|
export const NEVER_ADD: string[];
|
|
2500
2519
|
export const ACTIVELY_REMOVE: string[];
|
package/utils/create-yaml.js
CHANGED
|
@@ -65,7 +65,26 @@ export const ACTIVELY_REMOVE = [
|
|
|
65
65
|
|
|
66
66
|
const INDENT = 2;
|
|
67
67
|
|
|
68
|
-
export function
|
|
68
|
+
export function createYamlWithOptions(schemas, type, data, options) {
|
|
69
|
+
return createYaml(
|
|
70
|
+
schemas,
|
|
71
|
+
type,
|
|
72
|
+
data,
|
|
73
|
+
true, 0, '', null,
|
|
74
|
+
options
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function createYaml(
|
|
79
|
+
schemas,
|
|
80
|
+
type,
|
|
81
|
+
data,
|
|
82
|
+
processAlwaysAdd = true,
|
|
83
|
+
depth = 0,
|
|
84
|
+
path = '',
|
|
85
|
+
rootType = null,
|
|
86
|
+
dataOptions = {}
|
|
87
|
+
) {
|
|
69
88
|
const schema = findBy(schemas, 'id', type);
|
|
70
89
|
|
|
71
90
|
if ( !rootType ) {
|
|
@@ -220,25 +239,25 @@ export function createYaml(schemas, type, data, processAlwaysAdd = true, depth =
|
|
|
220
239
|
if (data[key]) {
|
|
221
240
|
try {
|
|
222
241
|
const cleaned = cleanUp(data);
|
|
223
|
-
const parsedData =
|
|
242
|
+
const parsedData = dumpBlock(cleaned[key], dataOptions[key]);
|
|
224
243
|
|
|
225
|
-
out += `\n${ indent(parsedData
|
|
244
|
+
out += `\n${ indent(parsedData) }`;
|
|
226
245
|
} catch (e) {
|
|
227
246
|
console.error(`Error: Unable to parse map data for yaml of type: ${ type }`, e); // eslint-disable-line no-console
|
|
228
247
|
}
|
|
229
248
|
}
|
|
230
249
|
|
|
231
250
|
if ( SIMPLE_TYPES.includes(mapOf) ) {
|
|
232
|
-
out +=
|
|
251
|
+
out += `# key: ${ mapOf }`;
|
|
233
252
|
} else {
|
|
234
253
|
// If not a simple type ie some sort of object/array, recusively build out commented fields (note data = null here) per the type's (mapOf's) schema
|
|
235
|
-
const chunk = createYaml(schemas, mapOf, null, processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType);
|
|
254
|
+
const chunk = createYaml(schemas, mapOf, null, processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions);
|
|
236
255
|
let indented = indent(chunk);
|
|
237
256
|
|
|
238
257
|
// convert "# foo" to "#foo"
|
|
239
258
|
indented = indented.replace(/^(#)?\s\s\s\s/, '$1');
|
|
240
259
|
|
|
241
|
-
out +=
|
|
260
|
+
out += `${ indented }`;
|
|
242
261
|
}
|
|
243
262
|
|
|
244
263
|
return out;
|
|
@@ -263,7 +282,7 @@ export function createYaml(schemas, type, data, processAlwaysAdd = true, depth =
|
|
|
263
282
|
if ( SIMPLE_TYPES.includes(arrayOf) ) {
|
|
264
283
|
out += `\n# - ${ arrayOf }`;
|
|
265
284
|
} else {
|
|
266
|
-
const chunk = createYaml(schemas, arrayOf, null, false, depth + 1, (path ? `${ path }.${ key }` : key), rootType);
|
|
285
|
+
const chunk = createYaml(schemas, arrayOf, null, false, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions);
|
|
267
286
|
let indented = indent(chunk, 2);
|
|
268
287
|
|
|
269
288
|
// turn "# foo" into "# - foo"
|
|
@@ -318,7 +337,7 @@ export function createYaml(schemas, type, data, processAlwaysAdd = true, depth =
|
|
|
318
337
|
let chunk;
|
|
319
338
|
|
|
320
339
|
if (subDef?.resourceFields && !isEmpty(subDef?.resourceFields)) {
|
|
321
|
-
chunk = createYaml(schemas, type, data[key], processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType);
|
|
340
|
+
chunk = createYaml(schemas, type, data[key], processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions);
|
|
322
341
|
} else if (data[key]) {
|
|
323
342
|
// if there are no fields defined on the schema but there are in the data, just format data as yaml and add to output yaml
|
|
324
343
|
try {
|
|
@@ -351,6 +370,43 @@ function serializeSimpleValue(data) {
|
|
|
351
370
|
return jsyaml.dump(data).trim();
|
|
352
371
|
}
|
|
353
372
|
|
|
373
|
+
function getBlockDescriptor(value, key) {
|
|
374
|
+
const header = getBlockHeader(value, key);
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
header,
|
|
378
|
+
indentation: getBlockIndentation(header),
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
*
|
|
384
|
+
* @param {string} value the block of text to be parsed
|
|
385
|
+
* @param {*} blockKey the key of the block
|
|
386
|
+
* @returns the key + the block scalar indicators, see https://yaml-multiline.info - Block Scalars
|
|
387
|
+
*/
|
|
388
|
+
function getBlockHeader(value, blockKey) {
|
|
389
|
+
const card = `(${ blockKey })[\\:][\\s|\\t]+[\\|\\>][\\d]*[\\-\\+]?`;
|
|
390
|
+
const re = new RegExp(card, 'gi');
|
|
391
|
+
|
|
392
|
+
const found = value.match(re);
|
|
393
|
+
|
|
394
|
+
return found?.[0] || '';
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
*
|
|
399
|
+
* @param {string} blockHeader the key + the block scalar indicators
|
|
400
|
+
* @returns the indentation indicator from the block header, see https://yaml-multiline.info - Indentation
|
|
401
|
+
*/
|
|
402
|
+
function getBlockIndentation(blockHeader) {
|
|
403
|
+
const blockScalars = blockHeader.substr(blockHeader.indexOf(':') + 1);
|
|
404
|
+
|
|
405
|
+
const indentation = blockScalars.match(/\d+/);
|
|
406
|
+
|
|
407
|
+
return indentation?.[0] || '';
|
|
408
|
+
}
|
|
409
|
+
|
|
354
410
|
export function typeRef(type, str) {
|
|
355
411
|
const re = new RegExp(`^${ type }\\[(.*)\\]$`);
|
|
356
412
|
const match = str.match(re);
|
|
@@ -381,3 +437,44 @@ export function saferDump(obj) {
|
|
|
381
437
|
|
|
382
438
|
return out;
|
|
383
439
|
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Handles newlines indicators in the multiline blocks.
|
|
443
|
+
*
|
|
444
|
+
* this is required since jsyaml.dump doesn't support chomping and scalar style at the moment.
|
|
445
|
+
* see: https://github.com/nodeca/js-yaml/issues/171
|
|
446
|
+
*
|
|
447
|
+
* @param {*} data the multiline block
|
|
448
|
+
* @param {*} options blocks indicators, see: https://yaml-multiline.info
|
|
449
|
+
*
|
|
450
|
+
* - scalarStyle:
|
|
451
|
+
* one of '|', '>'
|
|
452
|
+
* default '|'
|
|
453
|
+
* - chomping:
|
|
454
|
+
* one of: null, '-', '+'
|
|
455
|
+
* default: null
|
|
456
|
+
* @returns the result of jsyaml.dump with the addition of multiline indicators
|
|
457
|
+
*/
|
|
458
|
+
export function dumpBlock(data, options = {}) {
|
|
459
|
+
const parsed = jsyaml.dump(data);
|
|
460
|
+
|
|
461
|
+
let out = parsed;
|
|
462
|
+
|
|
463
|
+
const blockFields = Object.keys(data).filter(k => data[k].includes('\n'));
|
|
464
|
+
|
|
465
|
+
if (blockFields.length) {
|
|
466
|
+
for (const key of blockFields) {
|
|
467
|
+
const scalarStyle = options[key]?.scalarStyle ?? '|';
|
|
468
|
+
const chomping = options[key]?.chomping ?? '';
|
|
469
|
+
|
|
470
|
+
const desc = getBlockDescriptor(out, key);
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Replace the original block indicators with the ones provided in the options param
|
|
474
|
+
*/
|
|
475
|
+
out = out.replace(desc.header, `${ key }: ${ scalarStyle }${ chomping }${ desc.indentation }`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return out;
|
|
480
|
+
}
|
package/utils/settings.ts
CHANGED
|
@@ -22,6 +22,18 @@ export const fetchOrCreateSetting = async(store: Store<any>, id: string, val: st
|
|
|
22
22
|
return setting;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Fetch a specific setting that might not exist
|
|
27
|
+
* We fetch all settings - reality is Rancher will have done this already, so there's no overhead in doing
|
|
28
|
+
* this - but if we fetch a specific setting that does not exist, we will get a 404, which we don't want
|
|
29
|
+
*/
|
|
30
|
+
export const fetchSetting = async(store: Store<any>, id: string) => {
|
|
31
|
+
const all = await store.dispatch('management/findAll', { type: MANAGEMENT.SETTING });
|
|
32
|
+
const setting = (all || []).find((setting: any) => setting.id === id);
|
|
33
|
+
|
|
34
|
+
return setting;
|
|
35
|
+
};
|
|
36
|
+
|
|
25
37
|
export const setSetting = async(store: Store<any>, id: string, val: string): Promise<any> => {
|
|
26
38
|
const setting = await fetchOrCreateSetting(store, id, val, false);
|
|
27
39
|
|
package/vue.config.js
CHANGED
|
@@ -408,8 +408,8 @@ module.exports = function(dir, _appConfig) {
|
|
|
408
408
|
}),
|
|
409
409
|
}));
|
|
410
410
|
|
|
411
|
-
// The static assets need to be in the built
|
|
412
|
-
config.plugins.push(new CopyWebpackPlugin([{ from: path.join(SHELL_ABS, 'static'), to: '
|
|
411
|
+
// The static assets need to be in the built assets directory in order to get served (primarily the favicon)
|
|
412
|
+
config.plugins.push(new CopyWebpackPlugin([{ from: path.join(SHELL_ABS, 'static'), to: '.' }]));
|
|
413
413
|
|
|
414
414
|
config.resolve.extensions.push(...['.tsx', '.ts', '.js', '.vue', '.scss']);
|
|
415
415
|
config.watchOptions = config.watchOptions || {};
|