Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Date time local transform #24694

Merged
10 changes: 5 additions & 5 deletions ui/app/models/config-ui/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
import Model, { attr } from '@ember-data/model';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
import { isAfter, addDays, startOfDay } from 'date-fns';
import { isAfter, addDays, startOfDay, parseISO } from 'date-fns';
import { withModelValidations } from 'vault/decorators/model-validations';
import { withFormFields } from 'vault/decorators/model-form-fields';

Expand Down Expand Up @@ -72,14 +72,14 @@ export default class MessageModel extends Model {
editType: 'textarea',
})
message;
@attr('date', {
@attr('dateTimeLocal', {
editType: 'dateTimeLocal',
label: 'Message starts',
subText: 'Defaults to 12:00 a.m. the following day (local timezone).',
defaultValue: addDays(startOfDay(new Date() || this.startTime), 1).toISOString(),
defaultValue: addDays(startOfDay(new Date()), 1).toISOString(),
})
startTime;
@attr('date', { editType: 'yield', label: 'Message expires' }) endTime;
@attr('dateTimeLocal', { editType: 'yield', label: 'Message expires' }) endTime;

// the api returns link as an object with title and href as keys, but we separate the link key/values into
// different attributes to easily show link title and href fields on the create form. In our serializer,
Expand All @@ -89,7 +89,7 @@ export default class MessageModel extends Model {

// date helpers
get isStartTimeAfterToday() {
return isAfter(this.startTime, new Date());
return isAfter(parseISO(this.startTime), new Date());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use parseISO since date-fns doesn't accept strings as arguments.
Screenshot 2024-01-08 at 11 16 05 AM

}

// capabilities
Expand Down
24 changes: 1 addition & 23 deletions ui/app/serializers/config-ui/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,6 @@ export default class MessageSerializer extends ApplicationSerializer {
end_time: { serialize: false },
};

getISODateFormat(snapshotDateTime, jsonDateTime) {
if (typeof snapshotDateTime === 'object') {
return jsonDateTime;
}

// if the snapshot date is in local date time format ("yyyy-MM-dd'T'HH:mm"), we want to ensure
// it gets converted to an ISOString
if (typeof snapshotDateTime === 'string' && !snapshotDateTime.includes('Z')) {
return new Date(snapshotDateTime).toISOString();
}

return snapshotDateTime;
}
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
if (requestType === 'queryRecord') {
const transformed = {
Expand All @@ -41,22 +28,13 @@ export default class MessageSerializer extends ApplicationSerializer {
return super.normalizeResponse(store, primaryModelClass, payload, id, requestType);
}

serialize(snapshot) {
serialize() {
const json = super.serialize(...arguments);
json.message = encodeString(json.message);
json.link = {
title: json?.link_title || '',
href: json?.link_href || '',
};
// When editing a message with pre-populated dates, this returns a date object. In this case, we would want to use
// the json date from the serializer. When selecting a date from the datetime-local input date picker, the dates gets
// set as a date time local string in the model - we would want to convert this local string to an ISOString. Lastly,
// if this date is not an object and isn’t a local date string, then return the snapshot date, which is set by default
// values defined on the model.
json.start_time = this.getISODateFormat(snapshot.record.startTime, json.start_time);
json.end_time = snapshot.record.endTime
? this.getISODateFormat(snapshot.record.endTime, json.end_time)
: null;
delete json?.link_title;
delete json?.link_href;
return json;
Expand Down
2 changes: 2 additions & 0 deletions ui/app/services/custom-messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ export default class CustomMessageService extends Service {
}

get bannerMessages() {
if (!this.messages || !this.messages.length) return [];
return this.messages?.filter((message) => message?.type === 'banner');
}

get modalMessages() {
if (!this.messages || !this.messages.length) return [];
return this.messages?.filter((message) => message?.type === 'modal');
}

Expand Down
34 changes: 34 additions & 0 deletions ui/app/transforms/date-time-local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/

import Transform from '@ember-data/serializer/transform';
import { datetimeLocalStringFormat } from 'core/utils/date-formatters';
import { format } from 'date-fns';

export default class DateTimeLocalTransform extends Transform {
getISODateFormat(deserializedDate) {
if (!deserializedDate) return null;

// if the date is a date object or in local date time format ("yyyy-MM-dd'T'HH:mm"), we want to ensure
// it gets converted to an ISOString
if (
typeof deserializedDate === 'object' ||
(typeof deserializedDate === 'string' && !deserializedDate.includes('Z'))
) {
return new Date(deserializedDate).toISOString();
}

return deserializedDate;
}

deserialize(serialized) {
if (!serialized) return null;
return format(new Date(serialized), datetimeLocalStringFormat);
}

serialize(deserialized) {
return this.getISODateFormat(deserialized);
}
}
30 changes: 30 additions & 0 deletions ui/tests/unit/transforms/date-time-local-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/

import { module, test } from 'qunit';

import { setupTest } from 'vault/tests/helpers';

module('Unit | Transform | date time local', function (hooks) {
setupTest(hooks);

hooks.beforeEach(function () {
this.transform = this.owner.lookup('transform:date-time-local');
});

test('it serializes correctly for the API', function (assert) {
assert.ok(this.transform);
let serialized = this.transform.serialize('2024-01-31T00:00');
assert.strictEqual(
serialized,
new Date('2024-01-31T00:00').toISOString(),
'should serialize a string that is not in ISO format'
);
serialized = this.transform.serialize(new Date('2024-03-30T17:11:00Z'));
assert.strictEqual(serialized, '2024-03-30T17:11:00.000Z', 'should serialize a date object');
serialized = this.transform.serialize('2024-03-30T17:11:00.000Z');
assert.strictEqual(serialized, '2024-03-30T17:11:00.000Z', 'should always show an ISO string');
});
});
Loading