76f1971126
* setup routing, move queries in ConfigurationIndex to parent resource route * finish building out form, add model attrs build ttls * add types * update model attribute values, fix default ttl states * remove defaults and use openApi, group with booleans * add model to application route" * add save functionality * add error banner * add transition after save * use defaults from open api * fix empty state language * pass engine data * change model attrs to ttl objects * update types * add invalid form alert to error block * move data manipulation to serialize * fix serializer, add comments * add test for serializer * edit configuration details view * update details test * change to updateRecord so POST request is made * config/urls use POST instead of PUT * add edit tests, update details * add model hooks back to routes * rearrange to remove dif * remove createRecord for urls * update comment * wip sample ttl transform * Revert "wip sample ttl transform" This reverts commit 59fc179b5cd2994c4258e553e56667e29b3d6b72. * revert changes, move model updates back to component * simplify model fetches * address comments; * update pki/urls test * update adapter test
173 lines
5.5 KiB
JavaScript
173 lines
5.5 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*/
|
|
|
|
/**
|
|
* @module TtlPicker
|
|
* TtlPicker components are used to enable and select duration values such as TTL.
|
|
* This component renders a toggle by default, and passes all relevant attributes
|
|
* to TtlForm. Please see that component for additional arguments
|
|
* - allows TTL to be enabled or disabled
|
|
* - recalculates the time when the unit is changed by the user (eg 60s -> 1m)
|
|
*
|
|
* @example
|
|
* ```js
|
|
* <TtlPicker @onChange={{this.handleChange}} @initialEnabled={{@model.myAttribute}} @initialValue={{@model.myAttribute}}/>
|
|
* ```
|
|
* @param onChange {Function} - This function will be passed a TTL object, which includes enabled{bool}, seconds{number}, timeString{string}, goSafeTimeString{string}.
|
|
* @param initialEnabled=false {Boolean} - Set this value if you want the toggle on when component is mounted
|
|
* @param label="Time to live (TTL)" {String} - Label is the main label that lives next to the toggle. Yielded values will replace the label
|
|
* @param labelDisabled=Label to display when TTL is toggled off
|
|
* @param helperTextEnabled="" {String} - This helper text is shown under the label when the toggle is switched on
|
|
* @param helperTextDisabled="" {String} - This helper text is shown under the label when the toggle is switched off
|
|
* @param initialValue=null {string} - InitialValue is the duration value which will be shown when the component is loaded. If it can't be parsed, will default to 0.
|
|
* @param changeOnInit=false {boolean} - if true, calls the onChange hook when component is initialized
|
|
* @param hideToggle=false {Boolean} - set this value if you'd like to hide the toggle and just leverage the input field
|
|
*/
|
|
|
|
import Component from '@glimmer/component';
|
|
import { typeOf } from '@ember/utils';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { action } from '@ember/object';
|
|
import Duration from '@icholy/duration';
|
|
import { guidFor } from '@ember/object/internals';
|
|
import Ember from 'ember';
|
|
import { restartableTask, timeout } from 'ember-concurrency';
|
|
import {
|
|
convertFromSeconds,
|
|
convertToSeconds,
|
|
goSafeConvertFromSeconds,
|
|
largestUnitFromSeconds,
|
|
} from 'core/utils/duration-utils';
|
|
export default class TtlPickerComponent extends Component {
|
|
@tracked enableTTL = false;
|
|
@tracked recalculateSeconds = false;
|
|
@tracked time = ''; // if defaultValue is NOT set, then do not display a defaultValue.
|
|
@tracked unit = 's';
|
|
@tracked recalculateSeconds = false;
|
|
@tracked errorMessage = '';
|
|
|
|
/* Used internally */
|
|
recalculationTimeout = 5000;
|
|
elementId = 'ttl-' + guidFor(this);
|
|
|
|
get label() {
|
|
if (this.args.label && this.args.labelDisabled) {
|
|
return this.enableTTL ? this.args.label : this.args.labelDisabled;
|
|
}
|
|
return this.args.label || 'Time to live (TTL)';
|
|
}
|
|
get helperText() {
|
|
return this.enableTTL || this.args.hideToggle
|
|
? this.args.helperTextEnabled
|
|
: this.args.helperTextDisabled;
|
|
}
|
|
|
|
constructor() {
|
|
super(...arguments);
|
|
const enable = this.args.initialEnabled;
|
|
|
|
let setEnable = !!this.args.hideToggle;
|
|
if (!!enable || typeOf(enable) === 'boolean') {
|
|
// This allows non-boolean values passed in to be evaluated for truthiness
|
|
setEnable = !!enable;
|
|
}
|
|
|
|
this.enableTTL = setEnable;
|
|
this.initializeTtl();
|
|
}
|
|
|
|
initializeTtl() {
|
|
const initialValue = this.args.initialValue;
|
|
let seconds = 0;
|
|
if (typeof initialValue === 'number') {
|
|
// if the passed value is a number, assume unit is seconds
|
|
seconds = initialValue;
|
|
} else {
|
|
try {
|
|
seconds = Duration.parse(initialValue).seconds();
|
|
} catch (e) {
|
|
// if parsing fails leave it empty
|
|
return;
|
|
}
|
|
}
|
|
const unit = largestUnitFromSeconds(seconds);
|
|
this.time = convertFromSeconds(seconds, unit);
|
|
this.unit = unit;
|
|
|
|
if (this.args.changeOnInit) {
|
|
this.handleChange();
|
|
}
|
|
}
|
|
|
|
get seconds() {
|
|
return convertToSeconds(this.time, this.unit);
|
|
}
|
|
get unitOptions() {
|
|
return [
|
|
{ label: 'seconds', value: 's' },
|
|
{ label: 'minutes', value: 'm' },
|
|
{ label: 'hours', value: 'h' },
|
|
{ label: 'days', value: 'd' },
|
|
];
|
|
}
|
|
|
|
keepSecondsRecalculate(newUnit) {
|
|
const newTime = convertFromSeconds(this.seconds, newUnit);
|
|
if (Number.isInteger(newTime)) {
|
|
// Only recalculate if time is whole number
|
|
this.time = newTime;
|
|
}
|
|
this.unit = newUnit;
|
|
}
|
|
|
|
handleChange() {
|
|
const { time, unit, seconds, enableTTL } = this;
|
|
const ttl = {
|
|
enabled: this.args.hideToggle || enableTTL,
|
|
seconds,
|
|
timeString: time + unit,
|
|
goSafeTimeString: goSafeConvertFromSeconds(seconds, unit),
|
|
};
|
|
this.args.onChange(ttl);
|
|
}
|
|
|
|
@action
|
|
toggleEnabled() {
|
|
this.enableTTL = !this.enableTTL;
|
|
this.handleChange();
|
|
}
|
|
|
|
@restartableTask
|
|
*updateTime(newTime) {
|
|
this.errorMessage = '';
|
|
const parsedTime = parseInt(newTime, 10);
|
|
if (!newTime) {
|
|
this.errorMessage = 'This field is required';
|
|
return;
|
|
} else if (Number.isNaN(parsedTime)) {
|
|
this.errorMessage = 'Value must be a number';
|
|
return;
|
|
}
|
|
this.time = parsedTime;
|
|
this.handleChange();
|
|
if (Ember.testing) {
|
|
return;
|
|
}
|
|
this.recalculateSeconds = true;
|
|
yield timeout(this.recalculationTimeout);
|
|
this.recalculateSeconds = false;
|
|
}
|
|
|
|
@action
|
|
updateUnit(newUnit) {
|
|
if (this.recalculateSeconds) {
|
|
this.unit = newUnit;
|
|
} else {
|
|
this.keepSecondsRecalculate(newUnit);
|
|
}
|
|
this.handleChange();
|
|
}
|
|
}
|