Skip to content

Commit

Permalink
Backport of Clients config updates for census reporting into release/…
Browse files Browse the repository at this point in the history
…1.11.x (#21208)

* Clients config updates for census reporting (#20125)

* updates clients config view for census reporting

* adds changelog entry

* fixes issue with modal staying open and error not showing on clients config save failure

* adds min retention months to clients config model and form validation

* removes model-form-field decorator from clients config model
  • Loading branch information
zofskeez committed Jun 14, 2023
1 parent 0ce30bc commit 455b8b6
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 199 deletions.
3 changes: 3 additions & 0 deletions changelog/20125.txt
@@ -0,0 +1,3 @@
```release-note:improvement
ui: updates clients configuration edit form state based on census reporting configuration
```
28 changes: 14 additions & 14 deletions ui/app/components/clients/config.js
Expand Up @@ -18,9 +18,11 @@ import { task } from 'ember-concurrency';

export default class ConfigComponent extends Component {
@service router;

@tracked mode = 'show';
@tracked modalOpen = false;
error = null;
@tracked validations;
@tracked error = null;

get infoRows() {
return [
Expand All @@ -38,38 +40,36 @@ export default class ConfigComponent extends Component {
}

get modalTitle() {
let content = 'Turn usage tracking off?';
if (this.args.model && this.args.model.enabled === 'On') {
content = 'Turn usage tracking on?';
}
return content;
return `Turn usage tracking ${this.args.model.enabled.toLowerCase()}?`;
}

@(task(function* () {
try {
yield this.args.model.save();
this.router.transitionTo('vault.cluster.clients.config');
} catch (err) {
this.error = err.message;
return;
this.modalOpen = false;
}
this.router.transitionTo('vault.cluster.clients.config');
}).drop())
save;

@action
updateBooleanValue(attr, value) {
let valueToSet = value === true ? attr.options.trueValue : attr.options.falseValue;
this.args.model[attr.name] = valueToSet;
toggleEnabled(event) {
this.args.model.enabled = event.target.checked ? 'On' : 'Off';
}

@action
onSaveChanges(evt) {
evt.preventDefault();
const { isValid, state } = this.args.model.validate();
const changed = this.args.model.changedAttributes();
if (!changed.enabled) {
if (!isValid) {
this.validations = state;
} else if (changed.enabled) {
this.modalOpen = true;
} else {
this.save.perform();
return;
}
this.modalOpen = true;
}
}
4 changes: 3 additions & 1 deletion ui/app/decorators/model-validations.js
Expand Up @@ -103,9 +103,11 @@ export function withModelValidations(validations) {
: validator(get(this, key), options); // dot notation may be used to define key for nested property

if (!passedValidation) {
// message can also be a function
const validationMessage = typeof message === 'function' ? message(this) : message;
// consider setting a prop like validationErrors directly on the model
// for now return an errors object
state[key].errors.push(message);
state[key].errors.push(validationMessage);
if (isValid) {
isValid = false;
}
Expand Down
70 changes: 45 additions & 25 deletions ui/app/models/clients/config.js
@@ -1,30 +1,50 @@
import Model, { attr } from '@ember-data/model';
import { computed } from '@ember/object';
import attachCapabilities from 'vault/lib/attach-capabilities';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
import { expandAttributeMeta } from 'vault/utils/field-to-attrs';
import { apiPath } from 'vault/macros/lazy-capabilities';
import { withModelValidations } from 'vault/decorators/model-validations';

const M = Model.extend({
queriesAvailable: attr('boolean'),
retentionMonths: attr('number', {
const validations = {
retentionMonths: [
{
validator: (model) => parseInt(model.retentionMonths) >= model.minimumRetentionMonths,
message: (model) =>
`Retention period must be greater than or equal to ${model.minimumRetentionMonths}.`,
},
],
};

@withModelValidations(validations)
export default class ClientsConfigModel extends Model {
@attr('boolean') queriesAvailable; // true only if historical data exists, will be false if there is only current month data

@attr('number', {
label: 'Retention period',
subText: 'The number of months of activity logs to maintain for client tracking.',
}),
enabled: attr('string', {
editType: 'boolean',
trueValue: 'On',
falseValue: 'Off',
label: 'Enable usage data collection',
helpText:
'Enable or disable client tracking. Keep in mind that disabling tracking will delete the data for the current month.',
}),

configAttrs: computed(function () {
let keys = ['enabled', 'retentionMonths'];
return expandAttributeMeta(this, keys);
}),
});

export default attachCapabilities(M, {
configPath: apiPath`sys/internal/counters/config`,
});
})
retentionMonths;

@attr('number') minimumRetentionMonths;

@attr('string') enabled;

@attr('boolean') reportingEnabled;

@attr('date') billingStartTimestamp;

@lazyCapabilities(apiPath`sys/internal/counters/config`) configPath;

get canRead() {
return this.configPath.get('canRead') !== false;
}
get canEdit() {
return this.configPath.get('canUpdate') !== false;
}

_formFields = null;
get formFields() {
if (!this._formFields) {
this._formFields = expandAttributeMeta(this, ['enabled', 'retentionMonths']);
}
return this._formFields;
}
}
109 changes: 35 additions & 74 deletions ui/app/templates/components/clients/config.hbs
@@ -1,80 +1,38 @@
{{#if (eq @mode "edit")}}
<form onsubmit={{action "onSaveChanges"}} data-test-pricing-metrics-config-form>
<form onsubmit={{action "onSaveChanges"}} data-test-clients-config-form>
<div class="box is-sideless is-fullwidth is-marginless">
<MessageError @model={{@model}} @errorMessage={{this.error}} />
{{#each @model.configAttrs as |attr|}}
{{#if (and (eq attr.type "string") (eq attr.options.editType "boolean"))}}
{{#each @model.formFields as |attr|}}
{{#if (eq attr.name "enabled")}}
<label class="is-label">Usage data collection</label>
{{#if attr.options.helpText}}
<p class="sub-text">
{{attr.options.helpText}}
{{#if attr.options.docLink}}
<a href={{attr.options.docLink}} target="_blank" rel="noopener noreferrer">
See our documentation
</a>
for help.
{{/if}}
</p>
{{/if}}
<p class="sub-text">
Enable or disable client tracking. Keep in mind that disabling tracking will delete the data for the current
month.
</p>
<div class="control is-flex has-bottom-margin-l">
<input
data-test-field
data-test-input="enabled"
type="checkbox"
id={{attr.name}}
name={{attr.name}}
id="enabled"
name="enabled"
class="switch is-rounded is-success is-small"
checked={{eq (get @model attr.name) attr.options.trueValue}}
onchange={{action (action "updateBooleanValue" attr) value="target.checked"}}
disabled={{@model.reportingEnabled}}
checked={{eq @model.enabled "On"}}
{{on "change" this.toggleEnabled}}
/>
<label for={{attr.name}}>
{{#if (eq @model.enabled "Off")}}
Data collection is off
{{else}}
Data collection is on
{{/if}}
<label for="enabled">
Data collection is
{{lowercase @model.enabled}}
</label>
</div>
{{else if (eq attr.type "number")}}
<div class="has-top-margin-s">
<label for={{attr.name}} class="is-label">
{{attr.options.label}}
</label>
{{#if attr.options.subText}}
<p class="sub-text">
{{attr.options.subText}}
{{#if attr.options.docLink}}
<a href={{attr.options.docLink}} target="_blank" rel="noopener noreferrer">
See our documentation
</a>
for help.
{{/if}}
</p>
{{/if}}
<div class="control">
<input
data-test-field
id={{attr.name}}
disabled={{eq @model.enabled "Off"}}
autocomplete="off"
spellcheck="false"
onchange={{action (mut (get @model attr.name)) value="target.value"}}
value={{or (get @model attr.name) attr.options.defaultValue}}
class="input"
maxLength={{attr.options.characterLimit}}
/>
</div>
</div>
{{else}}
<FormField @attr={{attr}} @model={{@model}} @modelValidations={{this.validations}} />
{{/if}}
{{/each}}
</div>
<div class="field is-grouped-split box is-fullwidth is-bottomless">
<div class="control">
<button
type="submit"
disabled={{this.buttonDisabled}}
class="button is-primary"
data-test-edit-metrics-config-save={{true}}
>
<button type="submit" disabled={{this.buttonDisabled}} class="button is-primary" data-test-clients-config-save>
Save
</button>
<LinkTo @route="vault.cluster.clients.config" class="button">
Expand All @@ -83,6 +41,7 @@
</div>
</div>
</form>

<Modal
@title={{this.modalTitle}}
@onClose={{action (mut this.modalOpen) false}}
Expand All @@ -92,38 +51,40 @@
>
<section class="modal-card-body">
{{#if (eq @model.enabled "On")}}
<p class="has-bottom-margin-s">
<p class="has-bottom-margin-s" data-test-clients-config-modal="on">
Vault will start tracking data starting from today’s date,
{{date-format (now) "d MMMM yyyy"}}. You will not be able to see or query usage until the end of the month.
{{date-format (now) "MMMM d, yyyy"}}. If you’ve previously enabled usage tracking, that historical data will still
be available to you.
</p>
<p>If you’ve previously enabled usage tracking, that historical data will still be available to you.</p>
{{else}}
<p class="has-bottom-margin-s">
<p class="has-bottom-margin-s" data-test-clients-config-modal="off">
Turning usage tracking off means that all data for the current month will be deleted. You will still be able to
query previous months.
</p>
<p>Are you sure?</p>
{{/if}}
</section>
<footer class="modal-card-foot modal-card-foot-outlined">
<button
type="button"
class="button is-primary"
data-test-clients-config-modal="continue"
{{on "click" (perform this.save)}}
>
Continue
</button>
<button
type="button"
class="button is-secondary"
onclick={{action (mut this.modalOpen) false}}
data-test-metrics-config-cancel
{{on "click" (fn (mut this.modalOpen) false)}}
data-test-clients-config-modal="cancel"
>
Cancel
</button>
<button type="button" class="button is-primary" onclick={{perform this.save}}>
Continue
</button>
</footer>
</Modal>
{{else}}
<div
class="tabs-container box is-bottomless is-marginless is-fullwidth is-paddingless"
data-test-pricing-metrics-config-table
>
<div class="tabs-container box is-bottomless is-marginless is-fullwidth is-paddingless" data-test-clients-config-table>
{{#each this.infoRows as |item|}}
<InfoTableRow @label={{item.label}} @helperText={{item.helperText}} @value={{get @model item.valueKey}} />
{{/each}}
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/components/clients/current.hbs
Expand Up @@ -7,7 +7,7 @@
@title="Tracking is disabled"
@message="Tracking is disabled and data is not being collected. To turn it on edit the configuration."
>
{{#if @model.config.configPath.canUpdate}}
{{#if @model.config.canEdit}}
<LinkTo @route="vault.cluster.clients.config">
Go to configuration
</LinkTo>
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/components/clients/history.hbs
Expand Up @@ -40,7 +40,7 @@
@title="Data tracking is disabled"
@message="Tracking is disabled, and no data is being collected. To turn it on, edit the configuration."
>
{{#if @model.config.configPath.canUpdate}}
{{#if @model.config.canEdit}}
<p>
<LinkTo @route="vault.cluster.clients.config">
Go to configuration
Expand Down
7 changes: 5 additions & 2 deletions ui/app/templates/vault/cluster/clients.hbs
Expand Up @@ -15,8 +15,11 @@
<LinkTo @route="vault.cluster.clients.history" data-test-history>
History
</LinkTo>
{{#if (or @model.config.configPath.canRead @model.configPath.canRead)}}
<LinkTo @route="vault.cluster.clients.config">
{{#if (or @model.config.canRead @model.canRead)}}
<LinkTo
@route="vault.cluster.clients.config"
@current-when="vault.cluster.clients.config vault.cluster.clients.edit"
>
Configuration
</LinkTo>
{{/if}}
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/vault/cluster/clients/config.hbs
@@ -1,6 +1,6 @@
<Toolbar>
<ToolbarActions>
{{#if @model.configPath.canUpdate}}
{{#if @model.canEdit}}
<LinkTo @route="vault.cluster.clients.edit" class="toolbar-link">
Edit configuration
</LinkTo>
Expand Down

0 comments on commit 455b8b6

Please sign in to comment.