Skip to content

Commit 8874afd

Browse files
authored
Add updated_at column to objects' tables (#1218)
* Add updated_at columnb to objects' tables Signed-off-by: sitbubu <royi.sitbon@logz.io> * Grammer and iso usage Signed-off-by: sitbubu <royi.sitbon@logz.io> * Set updated at field from advanced settings Signed-off-by: sitbubu <royi.sitbon@logz.io> * Use dateFormat instead of dateFormat:scaled Signed-off-by: sitbubu <royi.sitbon@logz.io> * snapshot Signed-off-by: sitbubu <royi.sitbon@logz.io> * Add updated_at to additional comment Signed-off-by: sitbubu <royi.sitbon@logz.io> * Add unit-tests for updated_at as null undefined or unknown Signed-off-by: sitbubu <royi.sitbon@logz.io> * Simplify test file Signed-off-by: sitbubu <royi.sitbon@logz.io> * Simplified header and import from src Signed-off-by: sitbubu <royi.sitbon@logz.io> Signed-off-by: sitbubu <royi.sitbon@logz.io>
1 parent 890a4b6 commit 8874afd

File tree

13 files changed

+305
-14
lines changed

13 files changed

+305
-14
lines changed

src/core/public/saved_objects/saved_objects_client.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ import { SimpleSavedObject } from './simple_saved_object';
3333
import { httpServiceMock } from '../http/http_service.mock';
3434

3535
describe('SavedObjectsClient', () => {
36+
const updatedAt = new Date().toISOString();
3637
const doc = {
3738
id: 'AVwSwFxtcMV38qjDZoQg',
3839
type: 'config',
3940
attributes: { title: 'Example title' },
4041
version: 'foo',
42+
updated_at: updatedAt,
4143
};
4244

4345
const http = httpServiceMock.createStartContract();
@@ -356,7 +358,7 @@ describe('SavedObjectsClient', () => {
356358
Array [
357359
"/api/saved_objects/_bulk_create",
358360
Object {
359-
"body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\",\\"attributes\\":{\\"title\\":\\"Example title\\"},\\"version\\":\\"foo\\"}]",
361+
"body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\",\\"attributes\\":{\\"title\\":\\"Example title\\"},\\"version\\":\\"foo\\",\\"updated_at\\":\\"${updatedAt}\\"}]",
360362
"method": "POST",
361363
"query": Object {
362364
"overwrite": false,
@@ -374,7 +376,7 @@ describe('SavedObjectsClient', () => {
374376
Array [
375377
"/api/saved_objects/_bulk_create",
376378
Object {
377-
"body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\",\\"attributes\\":{\\"title\\":\\"Example title\\"},\\"version\\":\\"foo\\"}]",
379+
"body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\",\\"attributes\\":{\\"title\\":\\"Example title\\"},\\"version\\":\\"foo\\",\\"updated_at\\":\\"${updatedAt}\\"}]",
378380
"method": "POST",
379381
"query": Object {
380382
"overwrite": true,

src/core/public/saved_objects/simple_saved_object.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,11 @@ describe('SimpleSavedObject', () => {
6767
const savedObject = new SimpleSavedObject(client, { version } as SavedObject);
6868
expect(savedObject._version).toEqual(version);
6969
});
70+
71+
it('persists updated_at', () => {
72+
const updatedAt = new Date().toString();
73+
74+
const savedObject = new SimpleSavedObject(client, { updated_at: updatedAt } as SavedObject);
75+
expect(savedObject.updated_at).toEqual(updatedAt);
76+
});
7077
});

src/core/public/saved_objects/simple_saved_object.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,29 @@ export class SimpleSavedObject<T = unknown> {
5151
public migrationVersion: SavedObjectType<T>['migrationVersion'];
5252
public error: SavedObjectType<T>['error'];
5353
public references: SavedObjectType<T>['references'];
54+
public updated_at: SavedObjectType<T>['updated_at'];
5455

5556
constructor(
5657
private client: SavedObjectsClientContract,
57-
{ id, type, version, attributes, error, references, migrationVersion }: SavedObjectType<T>
58+
{
59+
id,
60+
type,
61+
version,
62+
attributes,
63+
error,
64+
references,
65+
migrationVersion,
66+
// eslint-disable-next-line @typescript-eslint/naming-convention
67+
updated_at,
68+
}: SavedObjectType<T>
5869
) {
5970
this.id = id;
6071
this.type = type;
6172
this.attributes = attributes || ({} as T);
6273
this.references = references || [];
6374
this._version = version;
6475
this.migrationVersion = migrationVersion;
76+
this.updated_at = updated_at;
6577
if (error) {
6678
this.error = error;
6779
}

src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.js.snap

Lines changed: 132 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/dashboard/public/application/listing/dashboard_listing.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import React, { Fragment } from 'react';
3232
import PropTypes from 'prop-types';
33+
import moment from 'moment';
3334

3435
import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
3536
import { i18n } from '@osd/i18n';
@@ -161,6 +162,7 @@ export class DashboardListing extends React.Component {
161162
}
162163

163164
getTableColumns() {
165+
const dateFormat = this.props.core.uiSettings.get('dateFormat');
164166
const tableColumns = [
165167
{
166168
field: 'title',
@@ -185,6 +187,19 @@ export class DashboardListing extends React.Component {
185187
dataType: 'string',
186188
sortable: true,
187189
},
190+
{
191+
field: `updated_at`,
192+
name: i18n.translate('dashboard.listing.table.columnUpdatedAtName', {
193+
defaultMessage: 'Last updated',
194+
}),
195+
dataType: 'date',
196+
sortable: true,
197+
description: i18n.translate('dashboard.listing.table.columnUpdatedAtDescription', {
198+
defaultMessage: 'Last update of the saved object',
199+
}),
200+
['data-test-subj']: 'updated-at',
201+
render: (updatedAt) => updatedAt && moment(updatedAt).format(dateFormat),
202+
},
188203
];
189204
return tableColumns;
190205
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { SavedObjectsClientContract } from 'opensearch-dashboards/public';
7+
import { SavedObjectLoader } from './saved_object_loader';
8+
9+
describe('SimpleSavedObjectLoader', () => {
10+
const createLoader = (updatedAt?: any) => {
11+
const id = 'logstash-*';
12+
const type = 'index-pattern';
13+
14+
const savedObject = {
15+
attributes: {},
16+
id,
17+
type,
18+
updated_at: updatedAt as any,
19+
};
20+
21+
client = {
22+
...client,
23+
find: jest.fn(() =>
24+
Promise.resolve({
25+
total: 1,
26+
savedObjects: [savedObject],
27+
})
28+
),
29+
} as any;
30+
31+
return new SavedObjectLoader(savedObject, client);
32+
};
33+
34+
let client: SavedObjectsClientContract;
35+
let loader: SavedObjectLoader;
36+
beforeEach(() => {
37+
client = {
38+
update: jest.fn(),
39+
create: jest.fn(),
40+
delete: jest.fn(),
41+
} as any;
42+
});
43+
44+
afterEach(async () => {
45+
const savedObjects = await loader.findAll();
46+
47+
expect(savedObjects.hits[0].updated_at).toEqual(undefined);
48+
});
49+
50+
it('set updated_at as undefined if undefined', async () => {
51+
loader = createLoader(undefined);
52+
});
53+
54+
it("set updated_at as undefined if doesn't exist", async () => {
55+
loader = createLoader();
56+
});
57+
58+
it('set updated_at as undefined if null', async () => {
59+
loader = createLoader(null);
60+
});
61+
});

0 commit comments

Comments
 (0)