vault/ui/app/forms/custom-message.ts
Jordan Reimer e18b0485f5
[UI] Ember Data Migration - Config UI Engine (#30238)
* WIP updating config-ui engine to use api service and form class

* updates form-field component to support false values for radio types

* updates api-error-message util to log out error in dev env

* fixes issues in custom messages create and edit workflows

* fixes issues in api service

* updates capabilities handling

* updates to custom messages form

* removes store from custom messages tests

* removes store as dependency from config-ui engine

* removes commented out code in messages route

* updates orderedKeys to displayFields in messages page component

* removes unneccesary method var from message create-and-edit component

* removes comment about model in message details page
2025-04-28 16:09:11 -06:00

126 lines
3.9 KiB
TypeScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Form from './form';
import FormField from 'vault/utils/forms/field';
import { isBefore, isAfter } from 'date-fns';
import { encodeString } from 'core/utils/b64';
import type { CreateCustomMessageRequest } from '@hashicorp/vault-client-typescript';
import { Validations } from 'vault/vault/app-types';
type CustomMessageFormData = Partial<CreateCustomMessageRequest>;
export default class CustomMessageForm extends Form {
declare data: CustomMessageFormData;
formFields = [
new FormField('authenticated', undefined, {
label: 'Where should we display this message?',
editType: 'radio',
possibleValues: [
{
label: 'After the user logs in',
subText: 'Display to users after they have successfully logged in to Vault.',
value: true,
id: 'authenticated',
},
{
label: 'On the login page',
subText: 'Display to users on the login page before they have authenticated.',
value: false,
id: 'unauthenticated',
},
],
}),
new FormField('type', 'string', {
label: 'Type',
editType: 'radio',
possibleValues: [
{
label: 'Alert message',
subText:
'A banner that appears on the top of every page to display brief but high-signal messages like an update or system alert.',
value: 'banner',
},
{
label: 'Modal',
subText:
'A pop-up window used to bring immediate attention for important notifications or actions.',
value: 'modal',
},
],
}),
new FormField('title', 'string'),
new FormField('message', 'string', { editType: 'textarea' }),
new FormField('link', 'string', {
editType: 'kv',
keyPlaceholder: 'Display text (e.g. Learn more)',
valuePlaceholder: 'Link URL (e.g. https://www.hashicorp.com/)',
label: 'Link (optional)',
isSingleRow: true,
allowWhiteSpace: true,
}),
new FormField('startTime', 'dateTimeLocal', {
editType: 'dateTimeLocal',
label: 'Message starts',
subText: 'Defaults to 12:00 a.m. the following day (local timezone).',
}),
new FormField('endTime', 'dateTimeLocal', {
editType: 'yield',
label: 'Message expires',
}),
];
validations: Validations = {
title: [{ type: 'presence', message: 'Title is required.' }],
message: [{ type: 'presence', message: 'Message is required.' }],
link: [
{
validator({ link }: CustomMessageFormData) {
if (!link) return true;
const [title] = Object.keys(link);
const [href] = Object.values(link);
return title || href ? !!(title && href) : true;
},
message: 'Link title and url are required.',
},
],
startTime: [
{
validator({ startTime, endTime }: CustomMessageFormData) {
if (!startTime || !endTime) return true;
return isBefore(new Date(startTime), new Date(endTime));
},
message: 'Start time is after end time.',
},
],
endTime: [
{
validator({ startTime, endTime }: CustomMessageFormData) {
if (!startTime || !endTime) return true;
return isAfter(new Date(endTime), new Date(startTime));
},
message: 'End time is before start time.',
},
],
};
toJSON() {
// overriding to do some date serialization
// form sets dates as strings but client expects Date objects
const startTime = this.data.startTime ? new Date(this.data.startTime as unknown as string) : undefined;
const endTime = this.data.endTime ? new Date(this.data.endTime as unknown as string) : undefined;
// encode message to base64
const message = this.data.message ? encodeString(this.data.message) : undefined;
return super.toJSON({ ...this.data, startTime, endTime, message });
}
}