mirror of
https://github.com/hashicorp/vault.git
synced 2026-04-29 18:19:24 -04:00
Merge 37dd8c0dd3 into 54d6d84268
This commit is contained in:
commit
e9ffeb143e
8 changed files with 1310 additions and 2 deletions
|
|
@ -13,6 +13,7 @@
|
|||
<Icon @name="pencil-tool" /><Icon @name="git-branch" />
|
||||
</div>
|
||||
</div>
|
||||
<Hds::Link::Standalone @text="Showcase" @icon="package" @color="secondary" @route="vault.cluster.showcase" />
|
||||
{{/if}}
|
||||
</AF.ExtraBefore>
|
||||
<AF.Link @href={{changelog-url-for this.version.version}} data-test-footer-version>
|
||||
|
|
|
|||
499
ui/app/controllers/vault/cluster/showcase.js
Normal file
499
ui/app/controllers/vault/cluster/showcase.js
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
// import { tracked } from '@glimmer/tracking';
|
||||
|
||||
export default class ShowcaseController extends Controller {
|
||||
// ###########################################
|
||||
// FORMFIELD
|
||||
// ###########################################
|
||||
|
||||
jsonExample = JSON.stringify(
|
||||
{ type: 'JSON', text: 'Lorem ipsum', value: 1234, object: { a: 'b', c: [9, 8, 7] } },
|
||||
null,
|
||||
2
|
||||
);
|
||||
|
||||
@action
|
||||
dynamicFormFieldModel(editType, variant) {
|
||||
const model = {
|
||||
// emulate model's setter
|
||||
set: () => {},
|
||||
};
|
||||
if (editType === 'boolean') {
|
||||
if (variant === 'checked' || variant === 'disabled') {
|
||||
model.boolean = true;
|
||||
}
|
||||
} else if (editType === 'checkboxList') {
|
||||
model.checkboxList = 'Ipsum';
|
||||
} else if (editType === 'dateTimeLocal') {
|
||||
if (variant === 'with value' || variant === 'with validation errors') {
|
||||
model.dateTimeLocal = new Date();
|
||||
}
|
||||
} else if (editType === 'input') {
|
||||
if (variant === 'with value' || variant === 'with validation errors') {
|
||||
model.input = 'Lorem ipsum dolor sit amet';
|
||||
} else if (variant === 'with character limit') {
|
||||
model.input = '123456789';
|
||||
} else if (variant === 'readonly' || variant === 'disabled') {
|
||||
model.input = 'Lorem ipsum';
|
||||
}
|
||||
} else if (editType === 'json') {
|
||||
model.json = '{}';
|
||||
if (variant === 'with value' || variant === 'with value + restore') {
|
||||
model.json = this.jsonExample;
|
||||
}
|
||||
} else if (editType === 'kv') {
|
||||
if (variant === 'with value' || variant === 'with validation errors') {
|
||||
model.kv = {
|
||||
'my-key': 'This is the value for `my-key`',
|
||||
};
|
||||
} else if (variant === 'with whitespace in key') {
|
||||
model.kv = {
|
||||
'my key with space': 'You need to set `@allowWhiteSpace` to avoid this warning',
|
||||
};
|
||||
}
|
||||
} else if (editType === 'mountAccessor') {
|
||||
if (variant === 'with value') {
|
||||
// TODO! not sure what to use here, it's too connected with the `authMethods` task (see the `mount-accessor-select` controller)
|
||||
model.mountAccessor = '???';
|
||||
}
|
||||
} else if (editType === 'object') {
|
||||
model.object = '{}';
|
||||
if (variant === 'with value' || variant === 'with value + restore') {
|
||||
model.object = { type: 'object', text: 'Hello world', number: 4567, array: ['a', 'b', 'c'] };
|
||||
}
|
||||
} else if (editType === 'optionalText') {
|
||||
if (variant === 'with value' || variant === 'with value + subText + docLink') {
|
||||
model.optionalText = 'Lorem ipsum';
|
||||
}
|
||||
} else if (editType === 'password') {
|
||||
if (variant === 'with value') {
|
||||
model.password = '123abc';
|
||||
}
|
||||
} else if (editType === 'radio') {
|
||||
model.radio = 2;
|
||||
} else if (editType === 'regex') {
|
||||
if (variant === 'with value') {
|
||||
model.regex = '/^lorem .*$/i';
|
||||
}
|
||||
} else if (editType === 'stringArray') {
|
||||
if (variant === 'with value') {
|
||||
model.stringArray = ['Lorem', 'Ipsum'];
|
||||
}
|
||||
} else if (editType === 'searchSelect') {
|
||||
if (variant === 'with value') {
|
||||
model.searchSelect = ['Lorem', 'Ipsum'];
|
||||
}
|
||||
} else if (editType === 'select') {
|
||||
if (variant === 'with value') {
|
||||
model.select = 'Ipsum';
|
||||
}
|
||||
} else if (editType === 'sensitive') {
|
||||
if (variant === 'with value' || variant === 'with copy') {
|
||||
model.sensitive = 'Lorem ipsum dolor';
|
||||
}
|
||||
} else if (editType === 'textarea') {
|
||||
if (variant === 'with value' || variant === 'with validation errors') {
|
||||
model.textarea = 'Lorem\nipsum\ndolor';
|
||||
}
|
||||
} else if (editType === 'toggleButton') {
|
||||
model.toggleButton = false;
|
||||
if (variant === 'checked' || variant === 'checked with opposite value' || variant === 'disabled') {
|
||||
model.toggleButton = true;
|
||||
}
|
||||
} else if (editType === 'ttl') {
|
||||
if (variant === 'with value' || variant === 'with validation errors') {
|
||||
model.ttl = 123;
|
||||
} else if (variant === 'with value 0s') {
|
||||
model.ttl = '0s';
|
||||
} else if (variant === 'with value 1h') {
|
||||
model.ttl = '1h';
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicFormFieldModelValidations(editType, variant) {
|
||||
const modelValidations = {};
|
||||
if (editType === 'boolean') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.boolean = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.boolean = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.boolean = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'checkboxList') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.checkboxList = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.checkboxList = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.checkboxList = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'dateTimeLocal') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.dateTimeLocal = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.dateTimeLocal = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.dateTimeLocal = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'input') {
|
||||
if (variant === 'with validation errors') {
|
||||
modelValidations.input = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'file') {
|
||||
if (variant === 'with validation errors') {
|
||||
// NOTICE! this generates a double error message, it's a bug in the code (error is already output by the `FormField`, see line 374, but is also output by `TextFile` via the argument `@validationError`)
|
||||
modelValidations.file = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'kv') {
|
||||
if (variant === 'with validation errors') {
|
||||
modelValidations.kv = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'radio') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.radio = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.radio = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.radio = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'stringArray') {
|
||||
if (variant === 'with validation errors') {
|
||||
modelValidations.stringArray = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'select') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.select = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.select = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.select = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'textarea') {
|
||||
if (variant === 'with validation errors') {
|
||||
modelValidations.textarea = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'password') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.password = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.password = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.password = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'toggleButton') {
|
||||
if (variant === 'with validation errors and warnings') {
|
||||
modelValidations.toggleButton = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
} else if (variant === 'with validation errors') {
|
||||
modelValidations.toggleButton = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
} else if (variant === 'with validation warnings') {
|
||||
modelValidations.toggleButton = {
|
||||
isValid: true,
|
||||
warnings: [
|
||||
'This is the validation warning message #1',
|
||||
'This is the validation warning message #2',
|
||||
],
|
||||
};
|
||||
}
|
||||
} else if (editType === 'ttl') {
|
||||
if (variant === 'with validation errors') {
|
||||
// NOTICE: there is a bug in the CSS for the class "ttl-picker-form-field-error" because the border color is applied to the `input` child, but such element is hidden so the red border is not visible!
|
||||
modelValidations.ttl = {
|
||||
isValid: false,
|
||||
errors: ['This is the validation error message #1', 'This is the validation error message #2'],
|
||||
};
|
||||
}
|
||||
}
|
||||
return modelValidations;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicFormFieldOptionsModels(editType) {
|
||||
let optionsModels = [];
|
||||
if (editType === 'searchSelect') {
|
||||
// TODO! find which is the right format for this
|
||||
optionsModels = [];
|
||||
}
|
||||
return optionsModels;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicFormFieldOptionsPossibleValues(editType, variant) {
|
||||
let possibleValues = [];
|
||||
if (editType === 'checkboxList') {
|
||||
possibleValues = ['Lorem', 'Ipsum', 'Dolor'];
|
||||
} else if (editType === 'radio') {
|
||||
possibleValues = [
|
||||
{
|
||||
label: 'One',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: 'Two',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: 'Three',
|
||||
value: 3,
|
||||
},
|
||||
];
|
||||
if (variant === 'with item subText') {
|
||||
possibleValues.forEach((i) => (i.subText = `Subtext for ${i.label.toLowerCase()}`));
|
||||
}
|
||||
if (variant === 'with item helpText') {
|
||||
possibleValues.forEach((i) => (i.helpText = `Helptext for ${i.label.toLowerCase()}`));
|
||||
}
|
||||
} else if (editType === 'select') {
|
||||
possibleValues = ['Lorem', 'Ipsum', 'Dolor'];
|
||||
}
|
||||
return possibleValues;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicFormFieldOptionsFieldValue(editType) {
|
||||
let fieldValue;
|
||||
if (editType === 'checkboxList') {
|
||||
fieldValue = 'checkboxList';
|
||||
} else if (editType === 'input') {
|
||||
fieldValue = 'input';
|
||||
} else if (editType === 'optionalText') {
|
||||
fieldValue = 'optionalText';
|
||||
} else if (editType === 'radio') {
|
||||
fieldValue = 'radio';
|
||||
} else if (editType === 'regex') {
|
||||
fieldValue = 'regex';
|
||||
} else if (editType === 'toggleButton') {
|
||||
fieldValue = 'toggleButton';
|
||||
}
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicFormFieldHelperTextEnabledValue(editType, variant) {
|
||||
let helperTextEnabled;
|
||||
if (editType === 'ttl' && variant === 'with custom helper text') {
|
||||
helperTextEnabled = 'Enabled state custom helper text';
|
||||
} else if (
|
||||
editType === 'toggleButton' &&
|
||||
(variant === 'with custom helper text' ||
|
||||
variant === 'checked' ||
|
||||
variant === 'checked with opposite value' ||
|
||||
variant === 'disabled')
|
||||
) {
|
||||
helperTextEnabled = 'Enabled state custom helper text';
|
||||
}
|
||||
return helperTextEnabled;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicFormFieldHelperTextDisabledValue(editType, variant) {
|
||||
let helperTextDisabled;
|
||||
if (editType === 'ttl' && variant === 'with custom helper text') {
|
||||
helperTextDisabled = 'Disabled state custom helper text';
|
||||
} else if (
|
||||
editType === 'toggleButton' &&
|
||||
(variant === 'with custom helper text' ||
|
||||
variant === 'checked' ||
|
||||
variant === 'checked with opposite value' ||
|
||||
variant === 'disabled')
|
||||
) {
|
||||
helperTextDisabled = 'Disabled state custom helper text';
|
||||
}
|
||||
return helperTextDisabled;
|
||||
}
|
||||
|
||||
// ###########################################
|
||||
// READONLY-FORMFIELD
|
||||
// ###########################################
|
||||
|
||||
@action
|
||||
dynamicReadonlyFormFieldValue(attrType, variant) {
|
||||
let value;
|
||||
// if (attrType === 'select') {
|
||||
// } else {
|
||||
// }
|
||||
if (variant === 'with value' || variant === 'with value + helpText + subText') {
|
||||
value = 'Lorem ipsum';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// ###########################################
|
||||
// OBJECT-LIST-INPUT
|
||||
// ###########################################
|
||||
|
||||
@action
|
||||
dynamicObjectListInputObjectKeys(variant) {
|
||||
// any variant needs the definition of the object keys
|
||||
if (variant) {
|
||||
return [
|
||||
{ label: 'Label for input A', key: 'A', placeholder: 'Placeholder for A' },
|
||||
{ label: 'Label for input B', key: 'B', placeholder: 'Placeholder for B' },
|
||||
{ label: 'Label for input C', key: 'C' },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicObjectListInputInputValue(variant) {
|
||||
let inputValue = [];
|
||||
if (variant === 'with single set of values') {
|
||||
inputValue = [{ A: 'First value for A', B: 'First value for B', C: '' }];
|
||||
} else if (variant === 'with multiple sets of values' || variant === 'with validation errors') {
|
||||
inputValue = [
|
||||
{ A: 'First value for A', B: 'First value for B', C: '' },
|
||||
{ A: 'Second value for A', B: 'Second value for B', C: '' },
|
||||
];
|
||||
}
|
||||
return inputValue;
|
||||
}
|
||||
|
||||
@action
|
||||
dynamicObjectListInputValidationErrors(variant) {
|
||||
let validationErrors = [];
|
||||
if (variant === 'with validation errors') {
|
||||
validationErrors = [
|
||||
{ A: { errors: ['Error message for first A'], isValid: false } },
|
||||
{ B: { errors: ['Error message for second B'], isValid: false } },
|
||||
];
|
||||
}
|
||||
return validationErrors;
|
||||
}
|
||||
|
||||
// ###########################################
|
||||
// OTHER
|
||||
// ###########################################
|
||||
|
||||
@action
|
||||
noop() {}
|
||||
}
|
||||
|
|
@ -14,6 +14,13 @@ export default class Router extends EmberRouter {
|
|||
Router.map(function () {
|
||||
this.route('vault', { path: '/' }, function () {
|
||||
this.route('cluster', { path: '/:cluster_name' }, function () {
|
||||
// ----------------------
|
||||
// ----------------------
|
||||
// Form Elements - Showcase
|
||||
// ----------------------
|
||||
this.route('showcase');
|
||||
// ----------------------
|
||||
// ----------------------
|
||||
this.route('dashboard');
|
||||
this.mount('config-ui');
|
||||
this.mount('sync');
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
@use 'ember-power-select';
|
||||
@use 'core';
|
||||
@use 'docs';
|
||||
@use './showcase';
|
||||
|
||||
@mixin font-face($name) {
|
||||
@font-face {
|
||||
|
|
|
|||
95
ui/app/styles/showcase.scss
Normal file
95
ui/app/styles/showcase.scss
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
/* SHOWCASE OF COMPONENTS */
|
||||
|
||||
@use './utils/font_variables';
|
||||
|
||||
.shw-page-wrapper {
|
||||
padding: 24px 48px;
|
||||
|
||||
/* ------------------ */
|
||||
|
||||
/* local styling for showcase text elements [intentionally scrappy but simple to use] */
|
||||
|
||||
h1:not([class]) {
|
||||
font-family: font_variables.$family-sans;
|
||||
font-size: 48px;
|
||||
line-height: 1.2em;
|
||||
font-weight: 900;
|
||||
color: #000;
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
h2:not([class]) {
|
||||
font-family: font_variables.$family-sans;
|
||||
font-size: 32px;
|
||||
line-height: 1.2em;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
h3:not([class]) {
|
||||
font-family: font_variables.$family-sans;
|
||||
font-size: 24px;
|
||||
line-height: 1.2em;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
h4:not([class]) {
|
||||
font-family: font_variables.$family-sans;
|
||||
font-size: 16px;
|
||||
line-height: 1.2em;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
pre:not([class]) {
|
||||
font-family: font_variables.$family-monospace;
|
||||
font-size: 11px;
|
||||
line-height: 1.2em;
|
||||
font-weight: bold;
|
||||
color: #999;
|
||||
margin: 24px 0 4px;
|
||||
}
|
||||
|
||||
blockquote:not([class]) {
|
||||
display: block;
|
||||
font-family: font_variables.$family-monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4em;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
margin: 24px 0 32px;
|
||||
padding-left: 12px;
|
||||
border-left: 2px solid #ccc;
|
||||
}
|
||||
|
||||
hr:not([class]) {
|
||||
border: none;
|
||||
background: none;
|
||||
border-top: 1px solid #bac1cc;
|
||||
margin: 48px 0;
|
||||
}
|
||||
|
||||
hr:not([class])[level='2'] {
|
||||
border: none;
|
||||
background: none;
|
||||
border-top: 1px dotted #bac1cc;
|
||||
margin: 36px 0;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line selector-class-pattern */
|
||||
.isHds {
|
||||
border-left: 3px solid #06be03;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
/* ------------------ */
|
||||
}
|
||||
704
ui/app/templates/vault/cluster/showcase.hbs
Normal file
704
ui/app/templates/vault/cluster/showcase.hbs
Normal file
|
|
@ -0,0 +1,704 @@
|
|||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<div class="shw-page-wrapper">
|
||||
|
||||
<h1>Vault Components Showcase</h1>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Form Components</h2>
|
||||
|
||||
<h3>FormFieldLabel</h3>
|
||||
|
||||
<blockquote>FormFieldLabel components add labels and descriptions to inputs</blockquote>
|
||||
|
||||
<pre>Only Label</pre>
|
||||
<FormFieldLabel @label="This is the label" />
|
||||
|
||||
<pre>Label with HelpText</pre>
|
||||
<FormFieldLabel @label="This is the label" @helpText="This is the help text" />
|
||||
|
||||
<pre>Only SubText</pre>
|
||||
<FormFieldLabel @subText="This is the subtext" />
|
||||
|
||||
<pre>SubText with DocLink</pre>
|
||||
<FormFieldLabel @subText="This is the subtext" @docLink="#" />
|
||||
|
||||
<pre>Label + SubText</pre>
|
||||
<FormFieldLabel @label="This is the label" @subText="This is the subtext" />
|
||||
|
||||
<pre>Label with HelpText + SubText with DocLink</pre>
|
||||
<FormFieldLabel @label="This is the label" @helpText="This is the help text" @subText="This is the subtext" @docLink="#" />
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>FormField</h3>
|
||||
|
||||
<blockquote>FormField components are field elements associated with a particular model.</blockquote>
|
||||
|
||||
{{#let
|
||||
(array
|
||||
(hash
|
||||
editType="boolean"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with helpText + subText + docLink"
|
||||
"checked"
|
||||
"disabled"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
isHds=true
|
||||
editType="checkboxList"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with helpText + subText + docLink"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
editType="dateTimeLocal"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with helpText + subText + docLink"
|
||||
"with value"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
editType="file" variants=(array "base" "with label" "with helpText + subText + docLink" "with validation errors")
|
||||
)
|
||||
(hash
|
||||
editType="input"
|
||||
attrType="string"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with helpText + subText + docLink"
|
||||
"with placeholder"
|
||||
"with value"
|
||||
"with character limit"
|
||||
"with validation errors"
|
||||
"readonly"
|
||||
"disabled"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
editType="json"
|
||||
attrType="string"
|
||||
variants=(array "base" "with label" "with helpText" "with value" "with value + restore")
|
||||
)
|
||||
(hash
|
||||
editType="kv"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with label as section header"
|
||||
"with helpText + subText"
|
||||
"with key/value placeholders"
|
||||
"single row"
|
||||
"with value"
|
||||
"with validation errors"
|
||||
"with whitespace in key"
|
||||
)
|
||||
)
|
||||
(hash editType="mountAccessor" variants=(array "base" "with label" "with helpText" "with value"))
|
||||
(hash editType="object" attrType="object" variants=(array "base" "with label" "with helpText" "with value"))
|
||||
(hash
|
||||
editType="optionalText"
|
||||
variants=(array
|
||||
"base" "with label" "with subText + docLink" "with default subText" "with value" "with value + subText + docLink"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
isHds=true
|
||||
editType="password"
|
||||
attrType="string"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with label as section header"
|
||||
"with helpText + subText + docLink"
|
||||
"with value"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
isHds=true
|
||||
editType="radio"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with helpText + subText + docLink"
|
||||
"with item subText"
|
||||
"with item helpText"
|
||||
"disabled"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash editType="regex" variants=(array "base" "with label" "with helpText + subText + docLink" "with value"))
|
||||
(hash
|
||||
editType="searchSelect"
|
||||
variants=(array "base" "with label" "with label as section header" "with helpText + subText" "with value")
|
||||
)
|
||||
(hash
|
||||
isHds=true
|
||||
editType="select"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with label as section header"
|
||||
"with helpText + subText"
|
||||
"with helpText + subText + docLink"
|
||||
"with no default"
|
||||
"with value"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash editType="stringArray" variants=(array "base" "with label" "with helpText + subText" "with value"))
|
||||
(hash editType="sensitive" variants=(array "base" "with label" "with value" "with copy"))
|
||||
(hash
|
||||
isHds=true
|
||||
editType="textarea"
|
||||
attrType="string"
|
||||
variants=(array "base" "with label" "with helpText + subText + docLink" "with value" "with validation errors")
|
||||
)
|
||||
(hash
|
||||
editType="toggleButton"
|
||||
attrType="boolean"
|
||||
variants=(array
|
||||
"base"
|
||||
"with label"
|
||||
"with custom helper text"
|
||||
"checked"
|
||||
"checked with opposite value"
|
||||
"disabled"
|
||||
"with validation errors"
|
||||
"with validation warnings"
|
||||
"with validation errors and warnings"
|
||||
)
|
||||
)
|
||||
(hash
|
||||
editType="ttl"
|
||||
variants=(array
|
||||
"base"
|
||||
"with helpText"
|
||||
"with custom helper texts"
|
||||
"with value"
|
||||
"with value 0s"
|
||||
"with value 1h"
|
||||
"with validation errors"
|
||||
"with hidden toggle"
|
||||
)
|
||||
)
|
||||
(hash editType="yield" variants=(array "yielded content"))
|
||||
)
|
||||
as |FormFieldTypes|
|
||||
}}
|
||||
{{#each FormFieldTypes as |FormFieldType index|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
{{#let FormFieldType.editType FormFieldType.attrType FormFieldType.variants as |editType attrType variants|}}
|
||||
<h4>{{#if FormFieldType.isHds}}✅{{/if}} Type "{{editType}}"</h4>
|
||||
{{#each variants as |variant|}}
|
||||
{{#let
|
||||
(fn this.dynamicFormFieldOptionsModels editType)
|
||||
(fn this.dynamicFormFieldOptionsPossibleValues editType variant)
|
||||
(fn this.dynamicFormFieldOptionsFieldValue editType)
|
||||
(fn this.dynamicFormFieldHelperTextEnabledValue editType variant)
|
||||
(fn this.dynamicFormFieldHelperTextDisabledValue editType variant)
|
||||
as |dynamicFormFieldOptionsModels dynamicFormFieldOptionsPossibleValues dynamicFormFieldOptionsFieldValue dynamicFormFieldHelperTextEnabledValue dynamicFormFieldHelperTextDisabledValue|
|
||||
}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<FormField
|
||||
class={{if FormFieldType.isHds "isHds"}}
|
||||
data-test-field={{true}}
|
||||
@attr={{(hash
|
||||
name=(if
|
||||
(or
|
||||
(eq editType "input")
|
||||
(eq editType "optionalText")
|
||||
(eq editType "radio")
|
||||
(eq editType "regex")
|
||||
(eq editType "toggleButton")
|
||||
)
|
||||
(concat editType "-" variant)
|
||||
editType
|
||||
)
|
||||
type=attrType
|
||||
options=(hash
|
||||
editType=(if (eq editType "input") undefined editType)
|
||||
label=(unless (eq variant "base") (concat "This is the label of the '" editType "' type of field"))
|
||||
isSectionHeader=(if (eq variant "with label as section header") true)
|
||||
helpText=(if
|
||||
(or
|
||||
(eq variant "with helpText")
|
||||
(eq variant "with helpText + subText")
|
||||
(eq variant "with helpText + subText + docLink")
|
||||
(eq variant "with subText + docLink")
|
||||
(eq variant "with value + subText + docLink")
|
||||
)
|
||||
"This is the help text"
|
||||
)
|
||||
subText=(if
|
||||
(or
|
||||
(eq variant "with subText")
|
||||
(eq variant "with helpText + subText")
|
||||
(eq variant "with helpText + subText + docLink")
|
||||
(eq variant "with subText + docLink")
|
||||
(eq variant "with value + subText + docLink")
|
||||
)
|
||||
"This is the subtext"
|
||||
)
|
||||
defaultSubText=(if
|
||||
(and (eq editType "optionalText") (eq variant "with default subText")) "This is the default subtext"
|
||||
)
|
||||
docLink=(if
|
||||
(or (eq variant "with helpText + subText + docLink") (eq variant "with value + subText + docLink")) "/#"
|
||||
)
|
||||
example=(if (and (eq editType "json") (eq variant "with value + restore")) this.jsonExample)
|
||||
noCopy=(if (and (eq editType "sensitive") (eq variant "with copy")) false true)
|
||||
hideToggle=(if (and (eq editType "ttl") (eq variant "with hidden toggle")) true false)
|
||||
helperTextEnabled=(dynamicFormFieldHelperTextEnabledValue)
|
||||
helperTextDisabled=(dynamicFormFieldHelperTextDisabledValue)
|
||||
readOnly=(if (eq variant "readonly") true false)
|
||||
editDisabled=(if (eq variant "disabled") "Enabled state custom helper text")
|
||||
noDefault=(if (and (eq editType "select") (eq variant "with no default")) true false)
|
||||
placeholder=(if (and (eq editType "input") (eq variant "with placeholder")) "This is the placeholder text")
|
||||
keyPlaceholder=(if (and (eq editType "kv") (eq variant "with key/value placeholders")) "Key placeholder")
|
||||
valuePlaceholder=(if
|
||||
(and (eq editType "kv") (eq variant "with key/value placeholders")) "Value placeholder"
|
||||
)
|
||||
isSingleRow=(if (and (eq editType "kv") (eq variant "single row")) true false)
|
||||
isOppositeValue=(if
|
||||
(and (eq editType "toggleButton") (eq variant "checked with opposite value")) true false
|
||||
)
|
||||
characterLimit=(if (and (eq editType "input") (eq variant "with character limit")) 10)
|
||||
models=(dynamicFormFieldOptionsModels)
|
||||
possibleValues=(dynamicFormFieldOptionsPossibleValues)
|
||||
fieldValue=(dynamicFormFieldOptionsFieldValue)
|
||||
sensitive=(if (eq editType "sensitive") true false)
|
||||
)
|
||||
)}}
|
||||
@disabled={{if (eq variant "disabled") true false}}
|
||||
@mode={{if (eq variant "readonly") "edit"}}
|
||||
@model={{this.dynamicFormFieldModel editType variant}}
|
||||
@modelValidations={{this.dynamicFormFieldModelValidations editType variant}}
|
||||
>
|
||||
{{#if (eq editType "yield")}}
|
||||
<span>This is yielded content</span>
|
||||
{{/if}}
|
||||
</FormField>
|
||||
{{/let}}
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>FormSaveButtons</h3>
|
||||
|
||||
<pre>Save</pre>
|
||||
<FormSaveButtons @saveButtonText="Save" />
|
||||
|
||||
<pre>Save / Loading state (isSaving=true)</pre>
|
||||
<FormSaveButtons @saveButtonText="Save" @isSaving={{true}} />
|
||||
|
||||
<pre>Save + Cancel (onCancel)</pre>
|
||||
<FormSaveButtons @saveButtonText="Save" @cancelButtonText="Cancel" @onCancel={{this.noop}} />
|
||||
|
||||
<pre>Save + Cancel (cancelLinkParams)</pre>
|
||||
<FormSaveButtons @saveButtonText="Save" @cancelButtonText="Cancel" @cancelLinkParams={{array "vault.cluster.storage"}} />
|
||||
|
||||
<pre>Save (isSaving=true / saveButtonText="Loading") + Cancel</pre>
|
||||
<FormSaveButtons @saveButtonText="Save" @isSaving={{true}} @cancelButtonText="Cancel" @onCancel={{this.noop}} />
|
||||
|
||||
<pre>Without top border (includeBox=false)</pre>
|
||||
<FormSaveButtons @saveButtonText="Save" @cancelButtonText="Cancel" @onCancel={{this.noop}} @includeBox={{false}} />
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>ReadonlyFormField</h3>
|
||||
|
||||
{{#let
|
||||
(array
|
||||
(hash
|
||||
attrType="text"
|
||||
variants=(array "base" "with label" "with helpText + subText" "with value" "with value + helpText + subText")
|
||||
)
|
||||
(hash
|
||||
attrType="password"
|
||||
variants=(array "base" "with label" "with helpText + subText" "with value" "with value + helpText + subText")
|
||||
)
|
||||
(hash
|
||||
attrType="date"
|
||||
variants=(array "base" "with label" "with helpText + subText" "with value" "with value + helpText + subText")
|
||||
)
|
||||
(hash
|
||||
attrType="select"
|
||||
variants=(array "base" "with label" "with helpText + subText" "with value" "with value + helpText + subText")
|
||||
)
|
||||
)
|
||||
as |ReadonlyFormFieldTypes|
|
||||
}}
|
||||
{{#each ReadonlyFormFieldTypes as |ReadonlyFormFieldType index|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
{{#let ReadonlyFormFieldType.attrType ReadonlyFormFieldType.variants as |attrType variants|}}
|
||||
<h4>Input type="{{attrType}}"</h4>
|
||||
{{#each variants as |variant|}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<ReadonlyFormField
|
||||
@value={{this.dynamicReadonlyFormFieldValue attrType variant}}
|
||||
@attr={{(hash
|
||||
name=(concat attrType "-" variant)
|
||||
type=attrType
|
||||
options=(hash
|
||||
label=(unless (eq variant "base") (concat "This is the label of the readonly '" attrType "' type of field"))
|
||||
helpText=(if
|
||||
(or
|
||||
(eq variant "with helpText")
|
||||
(eq variant "with helpText + subText")
|
||||
(eq variant "with value + helpText + subText")
|
||||
)
|
||||
"This is the help text"
|
||||
)
|
||||
subText=(if
|
||||
(or
|
||||
(eq variant "with subText")
|
||||
(eq variant "with helpText + subText")
|
||||
(eq variant "with value + helpText + subText")
|
||||
)
|
||||
"This is the subtext"
|
||||
)
|
||||
possibleValues=(if (eq attrType "select") (array "a" "b" "c"))
|
||||
)
|
||||
)}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>FormFieldGroups</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>FormFieldGroupsLoop</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>FormFieldGroupFromModel</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>AutocompleteInput</h3>
|
||||
|
||||
{{#let (array "base" "with label" "with subText" "with placeholder" "with value") as |variants index|}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<AutocompleteInput
|
||||
@label={{unless (eq variant "base") "This is the label of the 'AutocompleteInput' type of input"}}
|
||||
@subText={{if (or (eq variant "with subText") (eq variant "with value + subText")) "Type '$' to see autocomplete"}}
|
||||
@placeholder={{if (eq variant "with placeholder") "This is the placeholder text"}}
|
||||
@value={{if (eq variant "with value") "Lorem"}}
|
||||
@optionsTrigger="$"
|
||||
@options={{(array
|
||||
(hash label="Lorem" value="lorem") (hash label="Ipsum" value="ipsum") (hash label="Dolor" value="dolor")
|
||||
)}}
|
||||
@onChange={{this.noop}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>CommandInput</h3>
|
||||
|
||||
<Console::CommandInput
|
||||
@isFullscreen={{false}}
|
||||
@isRunning={{false}}
|
||||
@value="lorem"
|
||||
@onValueUpdate={{this.noop}}
|
||||
@onFullscreen={{this.noop}}
|
||||
@onExecuteCommand={{this.noop}}
|
||||
@onShiftCommand={{this.noop}}
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>EnableInput</h3>
|
||||
|
||||
<blockquote>EnableInput components render a disabled input with a hardcoded masked value beside an "Edit" button to
|
||||
"enable" the input. Clicking "Edit" hides the disabled input and renders the yielded component. This way any data
|
||||
management is handled by the parent. These are useful for editing inputs of sensitive values not returned by the API. The
|
||||
extra click ensures the user is intentionally editing the field.</blockquote>
|
||||
|
||||
<pre>With generic input / with Input placeholder (@label)</pre>
|
||||
<div {{style width="fit-content"}}>
|
||||
<EnableInput @label="This is the label">
|
||||
<Input @type="text" @value="This input is yielded" />
|
||||
</EnableInput>
|
||||
</div>
|
||||
|
||||
<pre>With generic input / with ReadonlyFormField placeholder (@attr)</pre>
|
||||
<div {{style width="fit-content"}}>
|
||||
<EnableInput
|
||||
@attr={{(hash
|
||||
name="EnableInputWithReadonlyFormField"
|
||||
type="text"
|
||||
options=(hash label="This is the label" helpText="This is the help text" subText="This is the subtext")
|
||||
)}}
|
||||
>
|
||||
<Input @type="text" @value="This input is yielded" />
|
||||
</EnableInput>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>✅ FilterInput</h3>
|
||||
|
||||
<pre>Base</pre>
|
||||
<FilterInput />
|
||||
|
||||
<pre>With value</pre>
|
||||
<FilterInput value="Lorem ipsum" />
|
||||
|
||||
<pre>With icon hidden</pre>
|
||||
<FilterInput value="Lorem ipsum" @hideIcon={{true}} />
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>✅ InputSearch</h3>
|
||||
|
||||
<blockquote>This component renders an input that fires a callback on "keyup" containing the input's value</blockquote>
|
||||
|
||||
<pre>Base</pre>
|
||||
<InputSearch @id="input-search-base" />
|
||||
|
||||
<pre>With label</pre>
|
||||
<InputSearch @id="input-search-with-label" @label="This is the label" />
|
||||
|
||||
<pre>With subText</pre>
|
||||
<InputSearch @id="input-search-with-subtext" @label="This is the label" @subText="This is the subtext" />
|
||||
|
||||
<pre>With placeholder</pre>
|
||||
<InputSearch @id="input-search-with-placeholder" @label="This is the label" @placeholder="This is the placeholder" />
|
||||
|
||||
<pre>With value</pre>
|
||||
<InputSearch @id="input-search-with-value" @label="This is the label" @initialValue="Lorem ipsum" />
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>KvSuggestionInput</h3>
|
||||
|
||||
<blockquote>Input component that fetches secrets at a provided mount path and displays them as suggestions in a dropdown.
|
||||
As the user types the result set will be filtered providing suggestions for the user to select. After the input debounce
|
||||
wait time (500ms), if the value ends in a slash, secrets will be fetched at that path. The new result set will then be
|
||||
displayed in the dropdown as suggestions for the newly inputted path. Selecting a suggestion will append it to the input
|
||||
value. This allows the user to build a full path to a secret for the provided mount. This is useful for helping the user
|
||||
find deeply nested secrets given the path based policy system. If the user does not have list permission they are still
|
||||
able to enter a path to a secret but will not see suggestions. Input is disabled when mount path is not provided</blockquote>
|
||||
|
||||
{{#let (array "base" "with label" "with subText" "no mountpath") as |variants index|}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<KvSuggestionInput
|
||||
@label={{unless (eq variant "base") "This is the label of the 'KvSuggestionInput'"}}
|
||||
@subText={{if (eq variant "with subText") "This is the subtext"}}
|
||||
@value="lorem-ipsum/"
|
||||
@mountPath={{(unless (eq variant "no mountpath") "secret/")}}
|
||||
@onChange={{this.noop}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>MaskedInput</h3>
|
||||
|
||||
<blockquote>MaskedInput components are textarea inputs where the input is hidden. They are used to enter sensitive
|
||||
information like passwords.</blockquote>
|
||||
|
||||
{{#let
|
||||
(array
|
||||
"base"
|
||||
"with label"
|
||||
"with value"
|
||||
"allow download"
|
||||
"allow copy + download"
|
||||
"display only"
|
||||
"display only with value"
|
||||
"display only with empty string as value"
|
||||
)
|
||||
as |variants index|
|
||||
}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<MaskedInput
|
||||
@name={{concat "masked-input-" variant}}
|
||||
@value={{if
|
||||
(or
|
||||
(eq variant "with value")
|
||||
(eq variant "allow download")
|
||||
(eq variant "allow copy + download")
|
||||
(eq variant "display only with value")
|
||||
)
|
||||
"lorem ipsum"
|
||||
(if (eq variant "display only with empty string as value") "")
|
||||
}}
|
||||
@allowCopy={{if (or (eq variant "allow copy") (eq variant "allow copy + download")) true false}}
|
||||
@allowDownload={{if (or (eq variant "allow download") (eq variant "allow copy + download")) true false}}
|
||||
@displayOnly={{if
|
||||
(or
|
||||
(eq variant "display only")
|
||||
(eq variant "display only with value")
|
||||
(eq variant "display only with empty string as value")
|
||||
)
|
||||
true
|
||||
false
|
||||
}}
|
||||
@onChange={{this.noop}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>✅ NavigateInput</h3>
|
||||
|
||||
<blockquote>NavigateInput components are used to filter list data.</blockquote>
|
||||
|
||||
{{#let (array "base" "with placeholder" "with value") as |variants index|}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<NavigateInput
|
||||
@filter={{(if (eq variant "with value") "lorem ipsum")}}
|
||||
@placeholder={{(if (eq variant "with placeholder") "This is the placeholder")}}
|
||||
@filterDidChange={{this.noop}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>ObjectListInput</h3>
|
||||
|
||||
<blockquote>ObjectListInput components are used to render a variable number of text inputs in a single row with an "Add"
|
||||
button at the end of the row. Clicking 'add' generates a new row of empty inputs. Each input field is generated by an
|
||||
object in the @objectKeys array. Labels render above each column.</blockquote>
|
||||
|
||||
{{#let
|
||||
(array "base" "with single set of values" "with multiple sets of values" "with validation errors")
|
||||
as |variants index|
|
||||
}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<ObjectListInput
|
||||
@objectKeys={{this.dynamicObjectListInputObjectKeys variant}}
|
||||
@inputValue={{this.dynamicObjectListInputInputValue variant}}
|
||||
@validationErrors={{this.dynamicObjectListInputValidationErrors variant}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>Select</h3>
|
||||
|
||||
{{#let (array "base" "with label" "with no default" "with selected value" "inline" "full width") as |variants index|}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<Select
|
||||
@label={{unless (eq variant "base") "This is the label of the 'Select'"}}
|
||||
@selectedValue={{if (eq variant "with selected value") 123456}}
|
||||
@labelAttribute="label"
|
||||
@valueAttribute="value"
|
||||
@options={{(array
|
||||
(hash label="Lorem ipsum" value="lorem")
|
||||
(hash label="123456" value=123456)
|
||||
(hash label="Disabled option" value="disabled" isDisabled=true)
|
||||
)}}
|
||||
@isInline={{if (eq variant "inline") true false}}
|
||||
@isFullwidth={{if (eq variant "full width") true false}}
|
||||
@onChange={{this.noop}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>TextFile</h3>
|
||||
|
||||
<blockquote>TextFile components render a file upload input with the option to toggle a "Enter as text" button that changes
|
||||
the input into a textarea</blockquote>
|
||||
|
||||
{{#let
|
||||
(array "base" "base / upload only" "with label" "with helpText + subText + docLink" "with validation errors")
|
||||
as |variants index|
|
||||
}}
|
||||
{{#each variants as |variant|}}
|
||||
{{#unless (eq index 0)}}
|
||||
<hr level="2" />
|
||||
{{/unless}}
|
||||
<pre>{{capitalize variant}}</pre>
|
||||
<TextFile
|
||||
@uploadOnly={{if (eq variant "base / upload only") true false}}
|
||||
@label={{if (not (or (eq variant "base") (eq variant "base / upload only"))) "This is the label of the 'Select'"}}
|
||||
@helpText={{if (eq variant "with helpText + subText + docLink") "This is the helptext"}}
|
||||
@subText={{if (eq variant "with helpText + subText + docLink") "This is the subtext"}}
|
||||
@docLink={{if (eq variant "with helpText + subText + docLink") "/#"}}
|
||||
@validationError={{if (eq variant "with validation errors") "This is the validation error message"}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
|
||||
</div>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
}}
|
||||
|
||||
{{! template-lint-configure simple-unless "warn" }}
|
||||
<div class="field" data-test-field={{@attr.name}}>
|
||||
<div class="field" data-test-field={{@attr.name}} ...attributes>
|
||||
{{#if this.isHdsFormField}}
|
||||
{{! •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }}
|
||||
{{! HDS COMPONENTS - START }}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
{{#let (find-by "key" inputKey @objectKeys) as |field|}}
|
||||
<div class="column">
|
||||
{{#if (eq index 0)}}
|
||||
<h2 data-test-object-list-label={{inputKey}}>{{field.label}}</h2>
|
||||
{{! TODO! remove the class name here, it was added only for testing purposes, to avoid applying styles to it }}
|
||||
<h2 class="todo-remove" data-test-object-list-label={{inputKey}}>{{field.label}}</h2>
|
||||
{{/if}}
|
||||
{{#let (get rowValidations field.key) as |inputError|}}
|
||||
<Input
|
||||
|
|
|
|||
Loading…
Reference in a new issue