dashboard-shell-shell 1.0.113 → 1.0.115
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/components/ActionDropdown.vue +1 -1
- package/components/ActionMenu.vue +2 -2
- package/components/ActionMenuShell.vue +0 -1
- package/components/AppModal.vue +6 -78
- package/components/AssignTo.vue +11 -25
- package/components/AsyncButton.vue +7 -24
- package/components/BannerGraphic.vue +0 -1
- package/components/ButtonDropdown.vue +4 -26
- package/components/ButtonGroup.vue +0 -4
- package/components/ButtonMultiAction.vue +0 -1
- package/components/CommunityLinks.vue +3 -3
- package/components/ConsumptionGauge.vue +5 -24
- package/components/CopyToClipboardText.vue +1 -2
- package/components/CruResource.vue +7 -12
- package/components/CruResourceFooter.vue +2 -2
- package/components/DashboardOptions.vue +15 -21
- package/components/DetailText.vue +0 -5
- package/components/DisableAuthProviderModal.vue +0 -1
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +14 -56
- package/components/FixedBanner.vue +12 -19
- package/components/GlobalRoleBindings.vue +1 -5
- package/components/GrafanaDashboard.vue +4 -4
- package/components/GrowlManager.vue +1 -4
- package/components/HardwareResourceGauge.vue +3 -39
- package/components/InfoBox.vue +3 -3
- package/components/InputOrDisplay.vue +2 -28
- package/components/LabelValue.vue +1 -16
- package/components/LandingPagePreference.vue +3 -5
- package/components/LocaleSelector.vue +93 -39
- package/components/ModalWithCard.vue +0 -2
- package/components/MoveModal.vue +0 -1
- package/components/PromptChangePassword.vue +1 -1
- package/components/PromptModal.vue +2 -15
- package/components/PromptRemove.vue +8 -28
- package/components/PromptRestore.vue +0 -1
- package/components/ResourceCancelModal.vue +0 -1
- package/components/ResourceDetail/Masthead.vue +43 -188
- package/components/ResourceDetail/__tests__/Masthead.test.ts +1 -5
- package/components/ResourceDetail/index.vue +14 -49
- package/components/ResourceList/Masthead.vue +18 -80
- package/components/ResourceTable.vue +8 -3
- package/components/SideNav.vue +3 -2
- package/components/SortableTable/THead.vue +4 -10
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +537 -637
- package/components/SortableTable/selection.js +11 -0
- package/components/Tabbed/Tab.vue +3 -3
- package/components/Tabbed/index.vue +26 -44
- package/components/Wizard.vue +2 -2
- package/components/__tests__/AsyncButton.test.ts +2 -2
- package/components/__tests__/FixedBanner.test.ts +3 -3
- package/components/auth/Principal.vue +3 -10
- package/components/auth/__tests__/RoleDetailEdit.test.ts +2 -3
- package/components/form/ArrayList.vue +85 -123
- package/components/form/ArrayListGrouped.vue +2 -10
- package/components/form/Command.vue +15 -6
- package/components/form/EnvVars.vue +8 -16
- package/components/form/Footer.vue +5 -8
- package/components/form/HealthCheck.vue +3 -3
- package/components/form/HookOption.vue +16 -11
- package/components/form/KeyValue.vue +7 -16
- package/components/form/LabeledSelect.vue +76 -59
- package/components/form/LifecycleHooks.vue +3 -3
- package/components/form/MatchExpressions.vue +12 -35
- package/components/form/NameNsDescription.vue +115 -147
- package/components/form/Networking.vue +12 -20
- package/components/form/NodeAffinity.vue +23 -31
- package/components/form/NodeScheduling.vue +3 -13
- package/components/form/Password.vue +5 -11
- package/components/form/PodAffinity.vue +44 -43
- package/components/form/Probe.vue +66 -68
- package/components/form/ResourceQuota/Project.vue +1 -5
- package/components/form/ResourceSelector.vue +9 -7
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +3 -6
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +1 -12
- package/components/form/SSHKnownHosts/index.vue +2 -16
- package/components/form/Security.vue +56 -54
- package/components/form/Select.vue +7 -41
- package/components/form/ShellInput.vue +1 -5
- package/components/form/Tolerations.vue +1 -5
- package/components/form/UnitInput.vue +2 -2
- package/components/form/ValueFromResource.vue +121 -134
- package/components/form/WorkloadPorts.vue +18 -18
- package/components/form/__tests__/ArrayList.test.ts +2 -5
- package/components/form/__tests__/MatchExpressions.test.ts +12 -12
- package/components/form/__tests__/NameNsDescription.test.ts +14 -115
- package/components/form/__tests__/Probe.test.ts +8 -12
- package/components/form/__tests__/SSHKnownHosts.test.ts +0 -11
- package/components/form/__tests__/Select.test.ts +0 -37
- package/components/form/__tests__/UnitInput.test.ts +5 -4
- package/components/formatter/BadgeStateFormatter.vue +5 -8
- package/components/formatter/ExtensionCache.vue +74 -0
- package/components/formatter/InternalExternalIP.vue +0 -2
- package/components/formatter/Port.vue +24 -0
- package/components/formatter/SecretData.vue +7 -20
- package/components/formatter/SecretType.vue +41 -0
- package/components/nav/Favorite.vue +1 -5
- package/components/nav/Group.vue +3 -16
- package/components/nav/Header.vue +13 -39
- package/components/nav/Jump.vue +0 -7
- package/components/nav/NamespaceFilter.vue +8 -14
- package/components/nav/Pinned.vue +1 -1
- package/components/nav/TopLevelMenu.vue +17 -5
- package/components/nav/Type.vue +1 -14
- package/components/nav/__tests__/TopLevelMenu.test.ts +40 -0
- package/components/templates/blank.vue +1 -4
- package/components/templates/default.vue +0 -8
- package/components/templates/home.vue +1 -10
- package/components/templates/plain.vue +1 -10
- package/package.json +1 -1
- package/public/index.html +3 -3
- package/components/ActionDropdownShell.vue +0 -71
- package/components/DotState.vue +0 -84
- package/components/ModalManager.vue +0 -55
- package/components/SlideInPanelManager.vue +0 -126
- package/components/StatusBadge.vue +0 -77
- package/components/__tests__/ModalManager.spec.ts +0 -176
- package/components/__tests__/SlideInPanelManager.spec.ts +0 -166
|
@@ -340,6 +340,17 @@ export default {
|
|
|
340
340
|
if ( !isSelected ) {
|
|
341
341
|
this.update([node], this.selectedRows.slice());
|
|
342
342
|
}
|
|
343
|
+
|
|
344
|
+
let resources = this.selectedRows;
|
|
345
|
+
|
|
346
|
+
if ( this.mangleActionResources ) {
|
|
347
|
+
resources = await this.mangleActionResources(resources);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
this.$store.commit(`action-menu/show`, {
|
|
351
|
+
resources,
|
|
352
|
+
event: e,
|
|
353
|
+
});
|
|
343
354
|
},
|
|
344
355
|
|
|
345
356
|
keySelectRow(row, more = false) {
|
|
@@ -100,14 +100,14 @@ export default {
|
|
|
100
100
|
v-if="shouldShowHeader"
|
|
101
101
|
class="tab-header"
|
|
102
102
|
>
|
|
103
|
-
|
|
103
|
+
<h2>
|
|
104
104
|
{{ labelDisplay }}
|
|
105
105
|
<i
|
|
106
106
|
v-if="tooltip"
|
|
107
107
|
v-clean-tooltip="tooltip"
|
|
108
108
|
class="icon icon-info icon-lg"
|
|
109
109
|
/>
|
|
110
|
-
</h2>
|
|
110
|
+
</h2>
|
|
111
111
|
<slot name="tab-header-right" />
|
|
112
112
|
</div>
|
|
113
113
|
<slot v-bind="{active}" />
|
|
@@ -118,7 +118,7 @@ export default {
|
|
|
118
118
|
.tab-header {
|
|
119
119
|
display: flex;
|
|
120
120
|
justify-content: space-between;
|
|
121
|
-
|
|
121
|
+
margin-bottom: 15px;
|
|
122
122
|
align-items: center;
|
|
123
123
|
|
|
124
124
|
h2 {
|
|
@@ -367,6 +367,15 @@ export default {
|
|
|
367
367
|
margin: 0;
|
|
368
368
|
padding: 0;
|
|
369
369
|
|
|
370
|
+
&:focus-visible {
|
|
371
|
+
outline: none;
|
|
372
|
+
|
|
373
|
+
.tab.active {
|
|
374
|
+
@include focus-outline;
|
|
375
|
+
outline-offset: -2px;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
370
379
|
&.horizontal {
|
|
371
380
|
border: solid thin var(--border);
|
|
372
381
|
border-bottom: 0;
|
|
@@ -382,12 +391,8 @@ export default {
|
|
|
382
391
|
}
|
|
383
392
|
}
|
|
384
393
|
|
|
385
|
-
&:focus {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
& .tab.active a span {
|
|
389
|
-
text-decoration: none;
|
|
390
|
-
}
|
|
394
|
+
&:focus .tab.active a span {
|
|
395
|
+
text-decoration: underline;
|
|
391
396
|
}
|
|
392
397
|
|
|
393
398
|
.tab {
|
|
@@ -404,7 +409,7 @@ export default {
|
|
|
404
409
|
&:hover {
|
|
405
410
|
text-decoration: none;
|
|
406
411
|
span {
|
|
407
|
-
text-decoration:
|
|
412
|
+
text-decoration: underline;
|
|
408
413
|
}
|
|
409
414
|
}
|
|
410
415
|
}
|
|
@@ -474,68 +479,45 @@ export default {
|
|
|
474
479
|
|
|
475
480
|
.side-tabs {
|
|
476
481
|
display: flex;
|
|
477
|
-
|
|
478
|
-
/* box-shadow: 0 0 20px var(--shadow);
|
|
482
|
+
box-shadow: 0 0 20px var(--shadow);
|
|
479
483
|
border-radius: calc(var(--border-radius) * 2);
|
|
480
|
-
background-color: var(--tabbed-sidebar-bg);
|
|
481
|
-
|
|
484
|
+
background-color: var(--tabbed-sidebar-bg);
|
|
485
|
+
|
|
482
486
|
.tab-container {
|
|
483
487
|
padding: 20px;
|
|
484
488
|
}
|
|
485
489
|
|
|
486
490
|
& .tabs {
|
|
487
|
-
|
|
488
|
-
|
|
491
|
+
width: $sideways-tabs-width;
|
|
492
|
+
min-width: $sideways-tabs-width;
|
|
489
493
|
display: flex;
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
/* flex: 1 0; */
|
|
493
|
-
/* flex-direction: column; */
|
|
494
|
+
flex: 1 0;
|
|
495
|
+
flex-direction: column;
|
|
494
496
|
|
|
495
497
|
// &.vertical {
|
|
496
498
|
// .tab.active {
|
|
497
499
|
// background-color: var(--tabbed-container-bg);
|
|
498
500
|
// }
|
|
499
501
|
// }
|
|
502
|
+
|
|
500
503
|
& .tab {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
height: 36px;
|
|
504
|
-
/* border-top: solid 5px transparent; */
|
|
505
|
-
display: flex;
|
|
506
|
-
justify-content: center;
|
|
507
|
-
padding: 8px 16px;
|
|
508
|
-
box-sizing: border-box;
|
|
509
|
-
border: 1px solid #d7d7d7;
|
|
510
|
-
border-bottom: 0px;
|
|
511
|
-
margin-right: 5px;
|
|
512
|
-
border-radius: 2px;
|
|
504
|
+
width: 100%;
|
|
505
|
+
border-left: solid 5px transparent;
|
|
513
506
|
|
|
514
507
|
&.toggle A {
|
|
515
508
|
color: var(--primary);
|
|
516
|
-
padding: 0px;
|
|
517
509
|
}
|
|
518
510
|
|
|
519
511
|
A {
|
|
520
|
-
color: var(--
|
|
521
|
-
padding: 0px;
|
|
512
|
+
color: var(--primary);
|
|
522
513
|
}
|
|
523
514
|
|
|
524
515
|
&.active {
|
|
525
516
|
background-color: var(--body-bg);
|
|
526
|
-
border-
|
|
527
|
-
position: relative;
|
|
528
|
-
&.active::before{
|
|
529
|
-
position: absolute;
|
|
530
|
-
right: 0;
|
|
531
|
-
left: 0;
|
|
532
|
-
top: 34px;
|
|
533
|
-
border-bottom: 1px solid #fff;
|
|
534
|
-
content: '';
|
|
517
|
+
border-left: solid 5px var(--primary);
|
|
535
518
|
|
|
536
|
-
}
|
|
537
519
|
& A {
|
|
538
|
-
color: var(--
|
|
520
|
+
color: var(--input-label);
|
|
539
521
|
}
|
|
540
522
|
}
|
|
541
523
|
|
|
@@ -579,7 +561,7 @@ margin: 0px -20px;
|
|
|
579
561
|
&
|
|
580
562
|
|
|
581
563
|
.tab-container {
|
|
582
|
-
|
|
564
|
+
width: calc(100% - #{$sideways-tabs-width});
|
|
583
565
|
flex-grow: 1;
|
|
584
566
|
background-color: var(--body-bg);
|
|
585
567
|
}
|
package/components/Wizard.vue
CHANGED
|
@@ -426,7 +426,7 @@ export default {
|
|
|
426
426
|
</div>
|
|
427
427
|
<div
|
|
428
428
|
id="wizard-footer-controls"
|
|
429
|
-
class="controls-row"
|
|
429
|
+
class="controls-row pt-20"
|
|
430
430
|
>
|
|
431
431
|
<slot
|
|
432
432
|
name="cancel"
|
|
@@ -674,7 +674,7 @@ $spacer: 10px;
|
|
|
674
674
|
// We have to account for the absolute position of the .controls-row
|
|
675
675
|
.footer-error {
|
|
676
676
|
margin-top: -40px;
|
|
677
|
-
margin-bottom:
|
|
677
|
+
margin-bottom: 70px;
|
|
678
678
|
}
|
|
679
679
|
|
|
680
680
|
.controls-row {
|
|
@@ -42,7 +42,7 @@ describe('component: AsyncButton', () => {
|
|
|
42
42
|
expect(span.text()).toBe('some-string');
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
it('click on async button should emit click with a proper state of waiting,
|
|
45
|
+
it('click on async button should emit click with a proper state of waiting, disabled and spinning ::: CB true', () => {
|
|
46
46
|
jest.useFakeTimers();
|
|
47
47
|
|
|
48
48
|
const wrapper: VueWrapper<InstanceType<typeof AsyncButton>> = mount(AsyncButton, {
|
|
@@ -65,7 +65,7 @@ describe('component: AsyncButton', () => {
|
|
|
65
65
|
expect(wrapper.emitted('click')).toHaveLength(1);
|
|
66
66
|
expect(wrapper.vm.phase).toBe(ASYNC_BUTTON_STATES.WAITING);
|
|
67
67
|
expect(wrapper.vm.isSpinning).toBe(true);
|
|
68
|
-
expect(wrapper.vm.
|
|
68
|
+
expect(wrapper.vm.isDisabled).toBe(true);
|
|
69
69
|
// testing cb function has been emitted
|
|
70
70
|
expect(typeof wrapper.emitted('click')![0][0]).toBe('function');
|
|
71
71
|
|
|
@@ -40,7 +40,7 @@ describe('component: FixedBanner', () => {
|
|
|
40
40
|
expect(wrapper.vm.showHeader).toStrictEqual(true);
|
|
41
41
|
|
|
42
42
|
const bannerElem = wrapper.find('.banner');
|
|
43
|
-
const noArrayTextElem = wrapper.find('.banner
|
|
43
|
+
const noArrayTextElem = wrapper.find('.banner > p');
|
|
44
44
|
|
|
45
45
|
expect(bannerElem.exists()).toBe(true);
|
|
46
46
|
expect(bannerElem.classes()).not.toContain('banner-consent');
|
|
@@ -60,7 +60,7 @@ describe('component: FixedBanner', () => {
|
|
|
60
60
|
expect(wrapper.vm.showFooter).toStrictEqual(true);
|
|
61
61
|
|
|
62
62
|
const bannerElem = wrapper.find('.banner');
|
|
63
|
-
const noArrayTextElem = wrapper.find('.banner
|
|
63
|
+
const noArrayTextElem = wrapper.find('.banner > p');
|
|
64
64
|
|
|
65
65
|
expect(bannerElem.exists()).toBe(true);
|
|
66
66
|
expect(bannerElem.classes()).not.toContain('banner-consent');
|
|
@@ -84,7 +84,7 @@ describe('component: FixedBanner', () => {
|
|
|
84
84
|
const bannerDialogElem = wrapper.find('.banner-dialog');
|
|
85
85
|
const bannerDialogFrameElem = wrapper.find('.banner-dialog-frame');
|
|
86
86
|
const buttonDialog = wrapper.find('.banner-dialog button');
|
|
87
|
-
const noArrayTextElem = wrapper.find('.banner
|
|
87
|
+
const noArrayTextElem = wrapper.find('.banner > p');
|
|
88
88
|
|
|
89
89
|
expect(bannerElem.exists()).toBe(true);
|
|
90
90
|
expect(bannerDialogGlassElem.exists()).toBe(true);
|
|
@@ -90,7 +90,6 @@ export default {
|
|
|
90
90
|
<img
|
|
91
91
|
:src="principal.avatarSrc"
|
|
92
92
|
:class="{'round': principal.roundAvatar}"
|
|
93
|
-
:alt="t('principal.alt.avatar')"
|
|
94
93
|
>
|
|
95
94
|
</div>
|
|
96
95
|
<div
|
|
@@ -99,9 +98,9 @@ export default {
|
|
|
99
98
|
>
|
|
100
99
|
<table>
|
|
101
100
|
<tbody>
|
|
102
|
-
<tr><
|
|
103
|
-
<tr><
|
|
104
|
-
<tr><
|
|
101
|
+
<tr><td>{{ t('principal.name') }}: </td><td>{{ principal.name || principal.loginName }}</td></tr>
|
|
102
|
+
<tr><td>{{ t('principal.loginName') }}: </td><td>{{ principal.loginName }}</td></tr>
|
|
103
|
+
<tr><td>{{ t('principal.type') }}: </td><td>{{ principal.displayType }}</td></tr>
|
|
105
104
|
</tbody>
|
|
106
105
|
</table>
|
|
107
106
|
</div>
|
|
@@ -165,12 +164,6 @@ export default {
|
|
|
165
164
|
grid-template-rows: auto math.div($size, 2);
|
|
166
165
|
column-gap: 10px;
|
|
167
166
|
|
|
168
|
-
th {
|
|
169
|
-
text-align: left;
|
|
170
|
-
font-weight: normal;
|
|
171
|
-
padding-right: 10px;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
167
|
&.showLabels {
|
|
175
168
|
grid-template-areas:
|
|
176
169
|
"avatar name";
|
|
@@ -51,9 +51,8 @@ describe('component: RoleDetailEdit', () => {
|
|
|
51
51
|
const wrapper = mount(RoleDetailEdit, {
|
|
52
52
|
props: {
|
|
53
53
|
value: {
|
|
54
|
-
rules:
|
|
55
|
-
subtype:
|
|
56
|
-
metadata: { name: 'global-role-with-inherited' },
|
|
54
|
+
rules: [{ verbs }],
|
|
55
|
+
subtype: 'GLOBAL'
|
|
57
56
|
},
|
|
58
57
|
},
|
|
59
58
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { ref, watch, computed } from 'vue';
|
|
3
2
|
import debounce from 'lodash/debounce';
|
|
4
3
|
import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
5
4
|
import { removeAt } from '@shell/utils/array';
|
|
@@ -95,87 +94,22 @@ export default {
|
|
|
95
94
|
// we only want functions in the rules array
|
|
96
95
|
validator: (rules) => rules.every((rule) => ['function'].includes(typeof rule))
|
|
97
96
|
},
|
|
98
|
-
a11yLabel: {
|
|
99
|
-
type: String,
|
|
100
|
-
default: '',
|
|
101
|
-
},
|
|
102
|
-
componentTestid: {
|
|
103
|
-
type: String,
|
|
104
|
-
default: 'array-list',
|
|
105
|
-
}
|
|
106
97
|
},
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
const rows = ref([]);
|
|
98
|
+
data() {
|
|
99
|
+
const input = (Array.isArray(this.value) ? this.value : []).slice();
|
|
100
|
+
const rows = [];
|
|
111
101
|
|
|
112
102
|
for ( const value of input ) {
|
|
113
|
-
rows.
|
|
103
|
+
rows.push({ value });
|
|
114
104
|
}
|
|
115
|
-
if ( !rows.
|
|
116
|
-
const value =
|
|
105
|
+
if ( !rows.length && this.initialEmptyRow ) {
|
|
106
|
+
const value = this.defaultAddValue ? clone(this.defaultAddValue) : '';
|
|
117
107
|
|
|
118
|
-
rows.
|
|
108
|
+
rows.push({ value });
|
|
119
109
|
}
|
|
120
110
|
|
|
121
|
-
|
|
122
|
-
return props.mode === _VIEW;
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Cleanup rows and emit input
|
|
127
|
-
*/
|
|
128
|
-
const update = () => {
|
|
129
|
-
if ( isView.value ) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
const out = [];
|
|
133
|
-
|
|
134
|
-
for ( const row of rows.value ) {
|
|
135
|
-
const trim = !props.valueMultiline && (typeof row.value === 'string');
|
|
136
|
-
const value = trim ? row.value.trim() : row.value;
|
|
137
|
-
|
|
138
|
-
if ( typeof value !== 'undefined' ) {
|
|
139
|
-
out.push(value);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
emit('update:value', out);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const lastUpdateWasFromValue = ref(false);
|
|
146
|
-
const queueUpdate = debounce(update, 50);
|
|
147
|
-
|
|
148
|
-
watch(
|
|
149
|
-
rows,
|
|
150
|
-
() => {
|
|
151
|
-
// lastUpdateWasFromValue is used to break a cycle where when rows are updated
|
|
152
|
-
// this was called which then forced rows to updated again
|
|
153
|
-
if (!lastUpdateWasFromValue.value) {
|
|
154
|
-
queueUpdate();
|
|
155
|
-
}
|
|
156
|
-
lastUpdateWasFromValue.value = false;
|
|
157
|
-
},
|
|
158
|
-
{ deep: true }
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
watch(
|
|
162
|
-
() => props.value,
|
|
163
|
-
() => {
|
|
164
|
-
lastUpdateWasFromValue.value = true;
|
|
165
|
-
rows.value = (props.value || []).map((v) => ({ value: v }));
|
|
166
|
-
},
|
|
167
|
-
{ deep: true }
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
rows,
|
|
172
|
-
lastUpdateWasFromValue,
|
|
173
|
-
queueUpdate,
|
|
174
|
-
isView,
|
|
175
|
-
update,
|
|
176
|
-
};
|
|
111
|
+
return { rows, lastUpdateWasFromValue: false };
|
|
177
112
|
},
|
|
178
|
-
|
|
179
113
|
computed: {
|
|
180
114
|
_addLabel() {
|
|
181
115
|
return this.addLabel || this.t('generic.add');
|
|
@@ -183,6 +117,10 @@ export default {
|
|
|
183
117
|
_removeLabel() {
|
|
184
118
|
return this.removeLabel || this.t('generic.remove');
|
|
185
119
|
},
|
|
120
|
+
|
|
121
|
+
isView() {
|
|
122
|
+
return this.mode === _VIEW;
|
|
123
|
+
},
|
|
186
124
|
showAdd() {
|
|
187
125
|
return this.addAllowed;
|
|
188
126
|
},
|
|
@@ -203,7 +141,29 @@ export default {
|
|
|
203
141
|
return !this.valueMultiline && this.protip;
|
|
204
142
|
}
|
|
205
143
|
},
|
|
144
|
+
watch: {
|
|
145
|
+
value: {
|
|
146
|
+
deep: true,
|
|
147
|
+
handler() {
|
|
148
|
+
this.lastUpdateWasFromValue = true;
|
|
149
|
+
this.rows = (this.value || []).map((v) => ({ value: v }));
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
rows: {
|
|
154
|
+
deep: true,
|
|
155
|
+
handler(newValue, oldValue) {
|
|
156
|
+
// lastUpdateWasFromValue is used to break a cycle where when rows are updated
|
|
157
|
+
// this was called which then forced rows to updated again
|
|
158
|
+
if (!this.lastUpdateWasFromValue) {
|
|
159
|
+
this.queueUpdate();
|
|
160
|
+
}
|
|
161
|
+
this.lastUpdateWasFromValue = false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
206
165
|
created() {
|
|
166
|
+
this.queueUpdate = debounce(this.update, 50);
|
|
207
167
|
},
|
|
208
168
|
methods: {
|
|
209
169
|
add() {
|
|
@@ -229,6 +189,26 @@ export default {
|
|
|
229
189
|
this.queueUpdate();
|
|
230
190
|
},
|
|
231
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Cleanup rows and emit input
|
|
194
|
+
*/
|
|
195
|
+
update() {
|
|
196
|
+
if ( this.isView ) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const out = [];
|
|
200
|
+
|
|
201
|
+
for ( const row of this.rows ) {
|
|
202
|
+
const trim = !this.valueMultiline && (typeof row.value === 'string');
|
|
203
|
+
const value = trim ? row.value.trim() : row.value;
|
|
204
|
+
|
|
205
|
+
if ( typeof value !== 'undefined' ) {
|
|
206
|
+
out.push(value);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
this.$emit('update:value', out);
|
|
210
|
+
},
|
|
211
|
+
|
|
232
212
|
/**
|
|
233
213
|
* Handle paste event, e.g. split multiple lines in rows
|
|
234
214
|
*/
|
|
@@ -274,32 +254,7 @@ export default {
|
|
|
274
254
|
</h3>
|
|
275
255
|
</slot>
|
|
276
256
|
</div>
|
|
277
|
-
|
|
278
|
-
v-if="showAdd && !isView"
|
|
279
|
-
class="footer"
|
|
280
|
-
>
|
|
281
|
-
<slot
|
|
282
|
-
v-if="showAdd"
|
|
283
|
-
name="add"
|
|
284
|
-
:add="add"
|
|
285
|
-
>
|
|
286
|
-
<button
|
|
287
|
-
type="button"
|
|
288
|
-
class="btn role-primary add"
|
|
289
|
-
:disabled="loading || disableAdd"
|
|
290
|
-
:data-testid="`${componentTestid}-button`"
|
|
291
|
-
:aria-label="_addLabel"
|
|
292
|
-
role="button"
|
|
293
|
-
@click="add()"
|
|
294
|
-
>
|
|
295
|
-
<i
|
|
296
|
-
class="mr-5 icon"
|
|
297
|
-
:class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
|
|
298
|
-
/>
|
|
299
|
-
{{ _addLabel }}
|
|
300
|
-
</button>
|
|
301
|
-
</slot>
|
|
302
|
-
</div>
|
|
257
|
+
|
|
303
258
|
<template v-if="rows.length">
|
|
304
259
|
<div v-if="showHeader">
|
|
305
260
|
<slot name="column-headers">
|
|
@@ -311,7 +266,7 @@ export default {
|
|
|
311
266
|
<div
|
|
312
267
|
v-for="(row, idx) in rows"
|
|
313
268
|
:key="idx"
|
|
314
|
-
:data-testid="
|
|
269
|
+
:data-testid="`array-list-box${ idx }`"
|
|
315
270
|
class="box"
|
|
316
271
|
>
|
|
317
272
|
<slot
|
|
@@ -335,7 +290,7 @@ export default {
|
|
|
335
290
|
v-if="valueMultiline"
|
|
336
291
|
ref="value"
|
|
337
292
|
v-model:value="row.value"
|
|
338
|
-
:data-testid="
|
|
293
|
+
:data-testid="`textarea-${idx}`"
|
|
339
294
|
:placeholder="valuePlaceholder"
|
|
340
295
|
:mode="mode"
|
|
341
296
|
:disabled="disabled"
|
|
@@ -346,7 +301,7 @@ export default {
|
|
|
346
301
|
v-else-if="rules.length > 0"
|
|
347
302
|
ref="value"
|
|
348
303
|
v-model:value="row.value"
|
|
349
|
-
:data-testid="
|
|
304
|
+
:data-testid="`labeled-input-${idx}`"
|
|
350
305
|
:placeholder="valuePlaceholder"
|
|
351
306
|
:disabled="isView || disabled"
|
|
352
307
|
:rules="rules"
|
|
@@ -358,10 +313,9 @@ export default {
|
|
|
358
313
|
v-else
|
|
359
314
|
ref="value"
|
|
360
315
|
v-model="row.value"
|
|
361
|
-
:data-testid="
|
|
316
|
+
:data-testid="`input-${idx}`"
|
|
362
317
|
:placeholder="valuePlaceholder"
|
|
363
318
|
:disabled="isView || disabled"
|
|
364
|
-
:aria-label="a11yLabel ? a11yLabel : undefined"
|
|
365
319
|
@paste="onPaste(idx, $event)"
|
|
366
320
|
>
|
|
367
321
|
</slot>
|
|
@@ -381,9 +335,7 @@ export default {
|
|
|
381
335
|
type="button"
|
|
382
336
|
:disabled="isView"
|
|
383
337
|
class="btn role-link"
|
|
384
|
-
:data-testid="
|
|
385
|
-
:aria-label="`${_removeLabel} ${idx + 1}`"
|
|
386
|
-
role="button"
|
|
338
|
+
:data-testid="`remove-item-${idx}`"
|
|
387
339
|
@click="remove(row, idx)"
|
|
388
340
|
>
|
|
389
341
|
{{ _removeLabel }}
|
|
@@ -402,7 +354,30 @@ export default {
|
|
|
402
354
|
</div>
|
|
403
355
|
</slot>
|
|
404
356
|
</div>
|
|
405
|
-
|
|
357
|
+
<div
|
|
358
|
+
v-if="showAdd && !isView"
|
|
359
|
+
class="footer mt-20"
|
|
360
|
+
>
|
|
361
|
+
<slot
|
|
362
|
+
v-if="showAdd"
|
|
363
|
+
name="add"
|
|
364
|
+
:add="add"
|
|
365
|
+
>
|
|
366
|
+
<button
|
|
367
|
+
type="button"
|
|
368
|
+
class="btn role-tertiary add"
|
|
369
|
+
:disabled="loading || disableAdd"
|
|
370
|
+
data-testid="array-list-button"
|
|
371
|
+
@click="add()"
|
|
372
|
+
>
|
|
373
|
+
<i
|
|
374
|
+
class="mr-5 icon"
|
|
375
|
+
:class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
|
|
376
|
+
/>
|
|
377
|
+
{{ _addLabel }}
|
|
378
|
+
</button>
|
|
379
|
+
</slot>
|
|
380
|
+
</div>
|
|
406
381
|
</div>
|
|
407
382
|
</template>
|
|
408
383
|
|
|
@@ -423,12 +398,7 @@ export default {
|
|
|
423
398
|
.value {
|
|
424
399
|
flex: 1;
|
|
425
400
|
INPUT {
|
|
426
|
-
height: $input-height;
|
|
427
|
-
border: solid var(--border-width) var(--input-border);
|
|
428
|
-
padding: 4px 11px;
|
|
429
|
-
&:hover{
|
|
430
|
-
box-shadow: 0 4px 6px 0 var(--input-border-box-shadow);
|
|
431
|
-
}
|
|
401
|
+
height: $unlabeled-input-height;
|
|
432
402
|
}
|
|
433
403
|
}
|
|
434
404
|
}
|
|
@@ -436,7 +406,6 @@ export default {
|
|
|
436
406
|
text-align: right;
|
|
437
407
|
}
|
|
438
408
|
.footer {
|
|
439
|
-
margin-bottom: 24px;
|
|
440
409
|
.protip {
|
|
441
410
|
float: right;
|
|
442
411
|
padding: 5px 0;
|
|
@@ -446,11 +415,4 @@ export default {
|
|
|
446
415
|
.required {
|
|
447
416
|
color: var(--error);
|
|
448
417
|
}
|
|
449
|
-
:deep() .labeled-input.compact-input{
|
|
450
|
-
padding: 0px;
|
|
451
|
-
}
|
|
452
|
-
:deep() .box{
|
|
453
|
-
margin-bottom: 10px;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
418
|
</style>
|
|
@@ -127,16 +127,8 @@ export default {
|
|
|
127
127
|
& > .remove {
|
|
128
128
|
position: absolute;
|
|
129
129
|
|
|
130
|
-
top:
|
|
131
|
-
right:
|
|
132
|
-
& > .close{
|
|
133
|
-
width: 32px;
|
|
134
|
-
min-width: 32px !important;
|
|
135
|
-
color: var(--body-text);
|
|
136
|
-
&:hover{
|
|
137
|
-
color: var(--link);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
130
|
+
top: 0;
|
|
131
|
+
right: 0;
|
|
140
132
|
}
|
|
141
133
|
|
|
142
134
|
& > .info-box {
|
|
@@ -43,14 +43,23 @@ export default {
|
|
|
43
43
|
},
|
|
44
44
|
|
|
45
45
|
data() {
|
|
46
|
+
const {
|
|
47
|
+
command,
|
|
48
|
+
args,
|
|
49
|
+
workingDir,
|
|
50
|
+
stdin = false,
|
|
51
|
+
stdinOnce = false,
|
|
52
|
+
tty = false,
|
|
53
|
+
} = this.value;
|
|
54
|
+
|
|
46
55
|
return {
|
|
47
|
-
args
|
|
48
|
-
command
|
|
56
|
+
args,
|
|
57
|
+
command,
|
|
49
58
|
commandOptions: ['No', 'Once', 'Yes'],
|
|
50
|
-
stdin
|
|
51
|
-
stdinOnce
|
|
52
|
-
tty
|
|
53
|
-
workingDir
|
|
59
|
+
stdin,
|
|
60
|
+
stdinOnce,
|
|
61
|
+
tty,
|
|
62
|
+
workingDir,
|
|
54
63
|
};
|
|
55
64
|
},
|
|
56
65
|
|
|
@@ -39,10 +39,14 @@ export default {
|
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
data() {
|
|
42
|
+
const { env = [], envFrom = [] } = this.value;
|
|
43
|
+
|
|
44
|
+
const allEnv = [...env, ...envFrom].map((row) => {
|
|
45
|
+
return { value: row, id: randomStr(4) };
|
|
46
|
+
});
|
|
47
|
+
|
|
42
48
|
return {
|
|
43
|
-
env
|
|
44
|
-
envFrom: [],
|
|
45
|
-
allEnv: [],
|
|
49
|
+
env, envFrom, allEnv
|
|
46
50
|
};
|
|
47
51
|
},
|
|
48
52
|
|
|
@@ -59,18 +63,7 @@ export default {
|
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
},
|
|
62
|
-
|
|
63
66
|
created() {
|
|
64
|
-
const { env = [], envFrom = [] } = this.value;
|
|
65
|
-
|
|
66
|
-
const allEnv = [...env, ...envFrom].map((row) => {
|
|
67
|
-
return { value: row, id: randomStr(4) };
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
this.env = env;
|
|
71
|
-
this.envFrom = envFrom;
|
|
72
|
-
this.allEnv = allEnv;
|
|
73
|
-
|
|
74
67
|
this.queueUpdate = debounce(this.update, 500);
|
|
75
68
|
},
|
|
76
69
|
|
|
@@ -114,8 +107,7 @@ export default {
|
|
|
114
107
|
<div :style="{'width':'100%'}">
|
|
115
108
|
<div
|
|
116
109
|
v-for="(row, i) in allEnv"
|
|
117
|
-
:key="
|
|
118
|
-
:data-testid="`env-var-row-${i}`"
|
|
110
|
+
:key="i"
|
|
119
111
|
>
|
|
120
112
|
<ValueFromResource
|
|
121
113
|
v-model:value="row.value"
|