Icu 12567 add new field credential mapping overrides (#2156)

* chore: 🤖 add credential type select list
This commit is contained in:
Dharini Jeeva authored and GitHub committed 2024-02-23 10:07:52 -08:00
1 parent 956f6fd04d
commit 93c8d481fd
14 files changed
+517 -36

No files matched your search

@@ -113,7 +113,7 @@
@width='100%'
name='credential_type'
disabled={{or form.disabled (not @model.isNew)}}
{{on 'input' (set-from-event @model 'credential_type')}}
{{on 'input' this.selectCredentialType}}
as |F|
>
<F.Label>
@@ -140,6 +140,46 @@
{{/if}}
</Hds::Form::Select::Field>
{{#if @model.credential_type}}
<Form::Field::ListWrapper
@layout='horizontal'
@isOptional={{true}}
@disabled={{form.disabled}}
>
<:fieldset as |F|>
<F.Legend>
{{t
'resources.credential-library.form.credential_mapping_overrides.label'
}}
</F.Legend>
<F.HelperText>
{{t
'resources.credential-library.form.credential_mapping_overrides.help'
}}
</F.HelperText>
{{#if @model.errors.credential_mapping_overrides}}
<F.Error as |E|>
{{#each @model.errors.credential_mapping_overrides as |error|}}
<E.Message>{{error.message}}</E.Message>
{{/each}}
</F.Error>
{{/if}}
</:fieldset>
<:field as |F|>
<F.SelectText
@name='credential_mapping_overrides'
@selectOptions={{this.mappingOverrides}}
@model={{@model}}
@disabled={{form.disabled}}
@removeDuplicates={{true}}
@width='400px'
/>
</:field>
</Form::Field::ListWrapper>
{{/if}}
<Hds::Form::Radio::Group
disabled={{form.disabled}}
{{on 'input' (set-from-event @model 'http_method')}}
@@ -8,7 +8,7 @@ import {
options,
TYPES_CREDENTIAL_LIBRARY,
} from 'api/models/credential-library';
import { action } from '@ember/object';
export default class FormCredentialLibraryVaultGenericComponent extends Component {
// =properties
/**
@@ -30,4 +30,17 @@ export default class FormCredentialLibraryVaultGenericComponent extends Componen
get isHttpRequestBodyAllowed() {
return this.args.model.http_method?.match(/post/i);
}
get mappingOverrides() {
return options.mapping_overrides[this.args.model.credential_type];
}
/**
* Clear the previously selected key value pair when toggling between credential types on a new form
*/
@action
selectCredentialType({ target: { value } }) {
this.args.model.credential_mapping_overrides = {};
this.args.model.credential_type = value;
}
}
@@ -25,6 +25,9 @@
'form/field/list-wrapper/textarea' disabled=@disabled
)
Select=(component 'form/field/list-wrapper/select' disabled=@disabled)
SelectText=(component
'form/field/list-wrapper/select-text' disabled=@disabled
)
)
to='field'
}}
@@ -0,0 +1,116 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
{{#let (unique-id) (unique-id) as |keyHeaderID valueHeaderID|}}
<Hds::Table class='list-wrapper-field' name={{@name}}>
<:head as |H|>
<H.Tr>
<H.Th id={{keyHeaderID}}>{{t 'form.key.label'}}</H.Th>
<H.Th id={{valueHeaderID}}>{{t 'form.value.label'}}</H.Th>
<H.Th>
{{t 'titles.actions'}}
</H.Th>
</H.Tr>
</:head>
<:body as |B|>
{{#each-in this.options as |select val|}}
<B.Tr>
<B.Td>
<Hds::Form::Select::Base
@value={{select}}
disabled={{@disabled}}
@width={{@width}}
aria-labelledby={{keyHeaderID}}
{{on 'change' (fn this.selectChange select val)}}
as |F|
>
<F.Options>
{{#each-in @selectOptions as |key value|}}
<option value={{key}} selected={{eq select key}}>
{{value}}
</option>
{{/each-in}}
</F.Options>
</Hds::Form::Select::Base>
</B.Td>
<B.Td>
<Hds::Form::TextInput::Field
@value={{val}}
@type='text'
@width={{@width}}
disabled={{@disabled}}
aria-labelledby={{valueHeaderID}}
{{on 'change' (fn this.updateInput select)}}
/>
</B.Td>
<B.Td>
{{#if this.removeOptionByKey}}
<Hds::Button
data-test-remove-button={{select}}
@text={{t 'actions.remove'}}
@color='critical'
@icon='trash'
@isIconOnly={{true}}
disabled={{@disabled}}
{{on 'click' (fn this.removeOptionByKey select)}}
/>
{{/if}}
</B.Td>
</B.Tr>
{{/each-in}}
{{#if this.showNewRow}}
<B.Tr>
<B.Td>
<Hds::Form::Select::Base
@value={{this.newOptionKey}}
disabled={{@disabled}}
aria-labelledby={{keyHeaderID}}
@width={{@width}}
{{on 'change' (set-from-event this 'newOptionKey')}}
as |F|
>
<F.Options>
<option hidden selected value=''>
{{t 'titles.choose-an-option'}}
</option>
{{#each-in this.selectOptions as |key value|}}
<option value={{key}} selected={{eq key this.newOptionKey}}>
{{value}}
</option>
{{/each-in}}
</F.Options>
</Hds::Form::Select::Base>
</B.Td>
<B.Td>
<Hds::Form::TextInput::Field
@value={{this.newOptionValue}}
@type='text'
@width={{@width}}
disabled={{@disabled}}
aria-labelledby={{valueHeaderID}}
{{on 'input' (set-from-event this 'newOptionValue')}}
/>
</B.Td>
<B.Td>
<Hds::Button
data-test-select-text-add-btn
@text={{t 'actions.add'}}
@color='secondary'
type='button'
disabled={{or @disabled (not this.newOptionKey)}}
{{on 'click' this.addOption}}
/>
</B.Td>
</B.Tr>
{{/if}}
</:body>
</Hds::Table>
{{/let}}
@@ -0,0 +1,137 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { set } from '@ember/object';
export default class MappingListComponent extends Component {
// =attributes
/**
* @type {string}
*/
@tracked newOptionKey = '';
/**
* @type {string}
*/
@tracked newOptionValue = '';
/**
* Returns an object of key/value pair that the user enters
* @type {object}
*/
get options() {
return this.args?.options || this.args?.model?.[this.args.name];
}
/**
* Determines if we need to show an empty row to the users to enter more key/value pairs based on removeDuplicates arg,
* by default it is true
* @type {object}
*/
get showNewRow() {
if (this.args.removeDuplicates) {
return (
Object.keys(this.options || {}).length !==
Object.keys(this.args.selectOptions || {}).length
);
} else {
return true;
}
}
/**
* Prevents users from selecting duplicate keys from the select list if there's the arg is set to true
* @type {object}
*/
get selectOptions() {
const previouslySelectedKeys = Object.keys(this.options || {});
if (this.args.removeDuplicates && previouslySelectedKeys.length) {
const newObj = { ...this.args.selectOptions };
for (const key of Object.keys(newObj)) {
if (previouslySelectedKeys.includes(key)) {
delete newObj[key];
}
}
return newObj;
} else {
return this.args.selectOptions;
}
}
// =actions
/**
* Handles when then user makes changes to the select list
* @param oldkey {string}
* @param oldVal {string}
*/
@action
selectChange(oldkey, oldVal, { target: { value: newKey } }) {
const field = this.args.name;
const newObj = { ...this.args.model[field], [newKey]: oldVal };
delete newObj[oldkey];
set(this.args.model, field, newObj);
}
/**
* Handles input changes
* @param key {string}
*/
@action
updateInput(key, { target: { value: newValue } }) {
const field = this.args.name;
this.args.model[field] = {
...this.args.model[field],
[key]: newValue,
};
}
/**
* If a new key value is entered and an addOption method was specified,
* calls addOption with the new key and value. Resets key and value.
* Otherwise use the model argument to create the array and update the model
*/
@action
addOption() {
if (this.args.addOption) {
if (this.newOptionKey) {
this.args.addOption({
key: this.newOptionKey,
value: this.newOptionValue,
});
}
} else {
const field = this.args.name;
this.args.model[field] = {
...this.args.model[field],
[this.newOptionKey]: this.newOptionValue,
};
}
this.newOptionKey = '';
this.newOptionValue = '';
}
/**
* If removeOptionByIndex method was passed, use that.
* Otherwise, use the model to remove an option by key
* @param index {number}
*/
@action
removeOptionByKey(selectedKey) {
if (this.args.removeOptionByKey) {
this.args.removeOptionByKey(selectedKey);
} else {
const field = this.args.name;
const newObj = { ...this.args.model[field] };
delete newObj[selectedKey];
set(this.args.model, field, newObj);
}
}
}