8000 [VAULT-34808] UI: move the `radio` block in `FormField` under the HDS block by didoo · Pull Request #30555 · hashicorp/vault · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[VAULT-34808] UI: move the radio block in FormField under the HDS block #30555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
8000
Diff view
80 changes: 34 additions & 46 deletions ui/lib/core/addon/components/form-field.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,39 @@
{{! HDS COMPONENTS - START }}
{{! •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }}
{{#if @attr.options.possibleValues}}
{{#if (eq @attr.options.editType "checkboxList")}}
{{#if (eq @attr.options.editType "radio")}}
<Hds::Form::Radio::Group
@name={{@attr.name}}
@layout={{if (or this.hasRadioSubText this.hasRadioHelpText) "vertical" "horizontal"}}
data-test-input-group={{@attr.name}}
as |G|
>
{{#each (path-or-array @attr.options.possibleValues @model) as |val|}}
<G.RadioField
@id={{or val.id (this.radioValue val)}}
@value={{this.radioValue val}}
checked={{if (eq (this.radioValue val) (get @model this.valuePath)) "checked"}}
disabled={{and @attr.options.editDisabled (not @model.isNew)}}
{{on "change" (fn this.setAndBroadcastRadio val)}}
data-test-radio={{or val.id (this.radioValue val)}}
as |F|
>
<F.Label data-test-input-group-item-label={{or val.label val.value val}}>
{{or val.label val.value val}}
</F.Label>
{{! Note: if we have both `subText` and `helpText`, we display only the `subText` because in these situations, the helpText is likely there to clarify or improve upon the OpenAPI-generated text }}
{{#if this.hasRadioSubText}}
<F.HelperText data-test-help-text={{val.subText}}>{{val.subText}}</F.HelperText>
{{else if this.hasRadioHelpText}}
<F.HelperText data-test-help-text={{val.helpText}}>{{val.helpText}}</F.HelperText>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the @helpText instead of being hidden behind a tooltip, is exposed as field's helper text (better for accessibility). See thread for context: https://hashicorp.slack.com/archives/C05DGFEBCP2/p1746701234173239

{{/if}}
</G.RadioField>
{{/each}}
{{#if this.validationError}}
<G.Error data-test-validation-error={{this.valuePath}}>{{this.validationError}}</G.Error>
{{/if}}
</Hds::Form::Radio::Group>
{{else if (eq @attr.options.editType "checkboxList")}}
<Hds::Form::Checkbox::Group @name={{@attr.name}} data-test-input-group={{@attr.name}} as |G|>
{{#if this.labelString}}
<G.Legend data-test-form-field-label>{{this.labelString}}</G.Legend>
Expand Down Expand Up @@ -143,51 +175,7 @@
@docLink={{@attr.options.docLink}}
/>
{{/unless}}
{{#if @attr.options.possibleValues}}
{{#if (eq @attr.options.editType "radio")}}
<div class="control {{unless this.hasRadioSubText 'columns'}}" data-test-radio-input>
{{#each (path-or-array @attr.options.possibleValues @model) as |val|}}
<div
class="is-flex-center
{{if this.hasRadioSubText 'has-top-padding-xs has-bottom-padding-s' 'column is-narrow has-right-margin-s'}}"
data-test-input={{@attr.name}}
>
<RadioButton
class="radio"
name={{@attr.name}}
id={{or val.id (this.radioValue val)}}
value={{this.radioValue val}}
@value={{this.radioValue val}}
@>
@groupValue={{get @model this.valuePath}}
@disabled={{and @attr.options.editDisabled (not @model.isNew)}}
data-test-radio={{or val.id (this.radioValue val)}}
/>
<div class="has-left-margin-xs">
<label
for={{or val.id (this.radioValue val)}}
value={{this.radioValue val}}
class="has-left-margin-xs is-size-7"
data-test-radio-label={{or val.label val.value val}}
>
{{or val.label val.value val}}
{{#if val.helpText}}
<Hds::TooltipButton @text={{val.helpText}} aria-label="More information">
<Hds::Icon @name="info" @isInline={{true}} />
</Hds::TooltipButton>
{{/if}}
{{#if this.hasRadioSubText}}
<p class="has-left-margin-xs has-text-grey is-size-8" data-test-radio-subText={{val.subText}}>
{{val.subText}}
</p>
{{/if}}
</label>
</div>
</div>
{{/each}}
</div>
{{/if}}
{{else if (eq @attr.options.editType "dateTimeLocal")}}
{{#if (eq @attr.options.editType "dateTimeLocal")}}
<Input
@type="datetime-local"
@value={{date-format (get @model this.valuePath) "yyyy-MM-dd'T'HH:mm"}}
Expand Down
20 changes: 13 additions & 7 deletions ui/lib/core/addon/components/form-field.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,7 @@ export default class FormFieldComponent extends Component {

// here we replicate the logic in the template, to make sure we don't change the order in which the "ifs" are evaluated
if (options?.possibleValues?.length > 0) {
// we still have to migrate the `radio` use case
if (options?.editType === 'radio') {
return false;
} else {
return true;
}
return true;
} else {
if (type === 'number' || type === 'string') {
if (options?.editType === 'password') {
Expand All @@ -116,10 +111,15 @@ export default class FormFieldComponent extends Component {
}

get hasRadioSubText() {
// for 'radio' editType, check to see if every of the possibleValues has a subText and label
// for 'radio' editType, check to see if any of the possibleValues has a subText
return this.args?.attr?.options?.possibleValues?.any((v) => v.subText);
}

get hasRadioHelpText() {
// for 'radio' editType, check to see if any of the possibleValues has a helpText
return this.args?.attr?.options?.possibleValues?.any((v) => v.helpText);
}

get hideLabel() {
const { type, options } = this.args.attr;
if (type === 'boolean' || type === 'object' || options?.isSectionHeader) {
Expand Down Expand Up @@ -205,6 +205,12 @@ export default class FormFieldComponent extends Component {
this.setAndBroadcast(updatedValue);
}
@action
setAndBroadcastRadio(item) {
// we want to read the original value instead of `event.target.value` so we have `false` (boolean) and not `"false"` (string)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for the comment!

const valueToSet = this.radioValue(item);
this.setAndBroadcast(valueToSet);
}
@action
setAndBroadcastTtl(value) {
const alwaysSendValue = this.valuePath === 'expiry' || this.valuePath === 'safetyBuffer';
const attrOptions = this.args.attr.options || {};
Expand Down
2 changes: 1 addition & 1 deletion ui/tests/acceptance/secrets/backend/totp/key-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module('Acceptance | totp key backend', function (hooks) {
};

const createNonVaultKey = async (keyName, issuer, accountName, url, key) => {
await click('[data-test-radio="Other service"]');
await click(GENERAL.radioByAttr('Other service'));
await fillIn(GENERAL.inputByAttr('name'), keyName);
await fillIn(GENERAL.inputByAttr('issuer'), issuer);
await fillIn(GENERAL.inputByAttr('accountName'), accountName);
Expand Down
2 changes: 1 addition & 1 deletion ui/tests/acceptance/sync/secrets/destinations-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module('Acceptance | sync | destinations (plural)', function (hooks) {
// check default values
const attr = 'granularity';
assert
.dom(`${ts.inputByAttr(attr)} input#${defaultValues[attr]}`)
.dom(`${ts.inputGroupByAttr(attr)} input#${defaultValues[attr]}`)
.isChecked(`${defaultValues[attr]} is checked`);
});
}
Expand Down
1 change: 1 addition & 0 deletions ui/tests/helpers/general-selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const GENERAL = {
inputGroupByAttr: (attr: string) => `[data-test-input-group="${attr}"]`,
labelById: (id: string) => `label[id="${id}"]`,
labelByGroupControlIndex: (index: number) => `.hds-form-group__control-field:nth-of-type(${index}) label`,
radioByAttr: (attr: string) => `[data-test-radio="${attr}"]`,
selectByAttr: (attr: string) => `[data-test-select="${attr}"]`,
textToggle: '[data-test-text-toggle]',
textToggleTextarea: '[data-test-text-file-textarea]',
Expand Down
8 changes: 4 additions & 4 deletions ui/tests/helpers/sync/sync-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,17 @@ export const PAGE = {
// for handling more complex form input elements by attr name
switch (attr) {
case 'granularity':
return await click(`[data-test-radio="secret-key"]`);
return await click(`${GENERAL.radioByAttr('secret-key')}`);
case 'credentials':
await click('[data-test-text-toggle]');
return fillIn('[data-test-text-file-textarea]', value);
case 'customTags':
await fillIn('[data-test-kv-key="0"]', 'foo');
return fillIn('[data-test-kv-value="0"]', value);
case 'deploymentEnvironments':
await click('[data-test-input-group="deploymentEnvironments"] input#development');
await click('[data-test-input-group="deploymentEnvironments"] input#preview');
return await click('[data-test-input-group="deploymentEnvironments"] input#production');
await click(`${GENERAL.inputGroupByAttr('deploymentEnvironments')} input#development`);
await click(`${GENERAL.inputGroupByAttr('deploymentEnvironments')} input#preview`);
return await click(`${GENERAL.inputGroupByAttr('deploymentEnvironments')} input#production`);
default:
return fillIn(`[data-test-input="${attr}"]`, value);
}
Expand Down
Loading
Loading
0