Change tooltip for token_bound_certs and glimmerize string-list component (#15852)

* wip

* wip

* glimmerization done?

* fix tests

* tooltip and test

* changelog

* clean up

* cleanup

* cleanup
This commit is contained in:
Angel Garbarino
2022-06-07 12:15:25 -07:00
committed by GitHub
parent 06c56355b5
commit fc20910ee7
7 changed files with 169 additions and 171 deletions

View File

@@ -196,12 +196,13 @@
</Toggle>
{{else if (eq @attr.options.editType "stringArray")}}
<StringList
@data-test-input={{@attr.name}}
data-test-input={{@attr.name}}
@label={{this.labelString}}
@warning={{@attr.options.warning}}
@helpText={{@attr.options.helpText}}
@inputValue={{get @model this.valuePath}}
@onChange={{this.setAndBroadcast}}
@attrName={{@attr.name}}
/>
{{else if (eq @attr.options.sensitive true)}}
{{! Masked Input }}

View File

@@ -0,0 +1,56 @@
<div
class="field string-list form-section"
data-test-component="string-list"
{{did-insert this.autoSize}}
{{did-update this.autoSizeUpdate}}
data-test-input
...attributes
>
{{#if @label}}
<label class="title is-label" data-test-string-list-label="true">
{{@label}}
{{#if this.helpText}}
<InfoTooltip>{{this.helpText}}</InfoTooltip>
{{/if}}
</label>
{{/if}}
{{#if @warning}}
<AlertBanner @type="warning" @message={{@warning}} />
{{/if}}
{{#each this.inputList as |data index|}}
<div class="field is-grouped" data-test-string-list-row={{index}}>
<div class="control is-expanded">
<Textarea
data-test-string-list-input={{index}}
class="input"
@value={{data.value}}
name={{concat this.elementId "-" index}}
id={{concat this.elementId "-" index}}
{{on "keyup" (action "inputChanged" index)}}
{{on "change" (action "inputChanged" index)}}
/>
</div>
<div class="control">
{{#if (eq (inc index) this.inputList.length)}}
<button
type="button"
class="button is-outlined is-primary"
data-test-string-list-button="add"
{{on "click" this.addInput}}
>
Add
</button>
{{else}}
<button
type="button"
class="button is-expanded is-icon"
data-test-string-list-button="delete"
{{on "click" (fn this.removeInput index)}}
>
<Icon @name="trash" />
</button>
{{/if}}
</div>
</div>
{{/each}}
</div>

View File

@@ -1,75 +1,32 @@
import ArrayProxy from '@ember/array/proxy';
import Component from '@ember/component';
import { set, computed } from '@ember/object';
import Component from '@glimmer/component';
import autosize from 'autosize';
import layout from '../templates/components/string-list';
import { action } from '@ember/object';
import { set } from '@ember/object';
export default Component.extend({
layout,
'data-test-component': 'string-list',
attributeBindings: ['data-test-component', 'data-test-input'],
classNames: ['field', 'string-list', 'form-section'],
/**
* @module StringList
*
* @example
* ```js
* <StringList @label={label} @onChange={{this.setAndBroadcast}} @inputValue={{this.valuePath}}/>
* ```
* @param {string} label - Text displayed in the header above all the inputs.
* @param {function} onChange - Function called when any of the inputs change.
* @param {string} inputValue - A string or an array of strings.
* @param {string} warning - Text displayed as a warning.
* @param {string} helpText - Text displayed as a tooltip.
* @param {string} type=array - Optional type for inputValue.
* @param {string} attrName - We use this to check the type so we can modify the tooltip content.
*/
/*
* @public
* @param String
*
* Optional - Text displayed in the header above all of the inputs
*
*/
label: null,
export default class StringList extends Component {
constructor() {
super(...arguments);
/*
* @public
* @param Function
*
* Function called when any of the inputs change
* accepts a single param `value` that is the
* result of calling `toVal()`.
*
*/
onChange: () => {},
/*
* @public
* @param String | Array
* A comma-separated string or an array of strings.
* Defaults to an empty array.
*
*/
inputValue: computed(function () {
return [];
}),
/*
*
* @public
* @param String - ['array'|'string]
*
* Optional type for `inputValue` - defaults to `'array'`
* Needs to match type of `inputValue` because it is set by the component on init.
*
*/
type: 'array',
/*
*
* @private
* @param Ember.ArrayProxy
*
* mutable array that contains objects in the form of
* {
* value: 'somestring',
* }
*
* used to track the state of values bound to the various inputs
*
*/
/* eslint-disable ember/no-side-effects */
inputList: computed('content', function () {
return ArrayProxy.create({
content: [],
this.inputList = ArrayProxy.create({
// trim the `value` when accessing objects
content: [],
objectAtContent: function (idx) {
const obj = this.content.objectAt(idx);
if (obj && obj.value) {
@@ -78,32 +35,28 @@ export default Component.extend({
return obj;
},
});
}),
init() {
this._super(...arguments);
this.type = this.args.type || 'array';
this.setType();
this.toList();
this.send('addInput');
},
didInsertElement() {
this._super(...arguments);
autosize(this.element.querySelector('textarea'));
},
didUpdate() {
this._super(...arguments);
autosize.update(this.element.querySelector('textarea'));
},
this.addInput();
}
setType() {
const list = this.inputList;
if (!list) {
return;
}
this.set('type', typeof list);
},
this.type = typeof list;
}
toList() {
let input = this.args.inputValue || [];
const inputList = this.inputList;
if (typeof input === 'string') {
input = input.split(',');
}
inputList.addObjects(input.map((value) => ({ value })));
}
toVal() {
const inputs = this.inputList.filter((x) => x.value).mapBy('value');
@@ -111,37 +64,47 @@ export default Component.extend({
return inputs.join(',');
}
return inputs;
},
}
toList() {
let input = this.inputValue || [];
const inputList = this.inputList;
if (typeof input === 'string') {
input = input.split(',');
get helpText() {
if (this.args.attrName === 'tokenBoundCidrs') {
return 'Specifies the blocks of IP addresses which are allowed to use the generated token. One entry per row.';
} else {
return this.args.helpText;
}
inputList.addObjects(input.map((value) => ({ value })));
},
}
actions: {
inputChanged(idx, event) {
const inputObj = this.inputList.objectAt(idx);
const onChange = this.onChange;
set(inputObj, 'value', event.target.value);
onChange(this.toVal());
},
@action
autoSize(element) {
autosize(element.querySelector('textarea'));
}
addInput() {
const inputList = this.inputList;
if (inputList.get('lastObject.value') !== '') {
inputList.pushObject({ value: '' });
}
},
@action
autoSizeUpdate(element) {
autosize.update(element.querySelector('textarea'));
}
removeInput(idx) {
const onChange = this.onChange;
const inputs = this.inputList;
inputs.removeObject(inputs.objectAt(idx));
onChange(this.toVal());
},
},
});
@action
inputChanged(idx, event) {
const inputObj = this.inputList.objectAt(idx);
const onChange = this.args.onChange;
set(inputObj, 'value', event.target.value);
onChange(this.toVal());
}
@action
addInput() {
const inputList = this.inputList;
if (inputList.get('lastObject.value') !== '') {
inputList.pushObject({ value: '' });
}
}
@action
removeInput(idx) {
const onChange = this.args.onChange;
const inputs = this.inputList;
inputs.removeObject(inputs.objectAt(idx));
onChange(this.toVal());
}
}