diff --git a/superset-frontend/spec/fixtures/mockDashboardInfo.js b/superset-frontend/spec/fixtures/mockDashboardInfo.js
index 4fd599ea3b473..2f747fd07b557 100644
--- a/superset-frontend/spec/fixtures/mockDashboardInfo.js
+++ b/superset-frontend/spec/fixtures/mockDashboardInfo.js
@@ -31,6 +31,19 @@ export default {
},
],
},
+ changed_on_delta_humanized: '7 minutes ago',
+ changed_by: {
+ id: 3,
+ first_name: 'John',
+ last_name: 'Doe',
+ },
+ created_on_delta_humanized: '10 days ago',
+ created_by: {
+ id: 2,
+ first_name: 'Kay',
+ last_name: 'Mon',
+ },
+ owners: [{ first_name: 'John', last_name: 'Doe', id: 1 }],
userId: 'mock_user_id',
dash_edit_perm: true,
dash_save_perm: true,
diff --git a/superset-frontend/src/dashboard/components/Header/Header.test.tsx b/superset-frontend/src/dashboard/components/Header/Header.test.tsx
index 2df5fa8318912..9160be6ad82ce 100644
--- a/superset-frontend/src/dashboard/components/Header/Header.test.tsx
+++ b/superset-frontend/src/dashboard/components/Header/Header.test.tsx
@@ -22,6 +22,7 @@ import userEvent from '@testing-library/user-event';
import fetchMock from 'fetch-mock';
import { getExtensionsRegistry } from '@superset-ui/core';
import setupExtensions from 'src/setup/setupExtensions';
+import getOwnerName from 'src/utils/getOwnerName';
import { HeaderProps } from './types';
import Header from '.';
@@ -44,6 +45,19 @@ const createProps = () => ({
],
},
},
+ changed_on_delta_humanized: '7 minutes ago',
+ changed_by: {
+ id: 3,
+ first_name: 'John',
+ last_name: 'Doe',
+ },
+ created_on_delta_humanized: '10 days ago',
+ created_by: {
+ id: 2,
+ first_name: 'Kay',
+ last_name: 'Mon',
+ },
+ owners: [{ first_name: 'John', last_name: 'Doe', id: 1 }],
},
user: {
createdOn: '2021-04-27T18:12:38.952304',
@@ -187,6 +201,17 @@ test('should publish', () => {
expect(mockedProps.savePublished).toHaveBeenCalledTimes(1);
});
+test('should render metadata', () => {
+ const mockedProps = createProps();
+ setup(mockedProps);
+ expect(
+ screen.getByText(getOwnerName(mockedProps.dashboardInfo.created_by)),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(mockedProps.dashboardInfo.changed_on_delta_humanized),
+ ).toBeInTheDocument();
+});
+
test('should render the "Undo" action as disabled', () => {
setup(editableProps);
expect(screen.getByTestId('undo-action').parentElement).toBeDisabled();
diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx
index f4a864b83540f..bce3e60d6f8f4 100644
--- a/superset-frontend/src/dashboard/components/Header/index.jsx
+++ b/superset-frontend/src/dashboard/components/Header/index.jsx
@@ -46,6 +46,7 @@ import PublishedStatus from 'src/dashboard/components/PublishedStatus';
import UndoRedoKeyListeners from 'src/dashboard/components/UndoRedoKeyListeners';
import PropertiesModal from 'src/dashboard/components/PropertiesModal';
import { chartPropShape } from 'src/dashboard/util/propShapes';
+import getOwnerName from 'src/utils/getOwnerName';
import {
UNDO_LIMIT,
SAVE_TYPE_OVERWRITE,
@@ -55,6 +56,7 @@ import setPeriodicRunner, {
stopPeriodicRender,
} from 'src/dashboard/util/setPeriodicRunner';
import { PageHeaderWithActions } from 'src/components/PageHeaderWithActions';
+import MetadataBar, { MetadataType } from 'src/components/MetadataBar';
import DashboardEmbedModal from '../EmbeddedModal';
import OverwriteConfirm from '../OverwriteConfirm';
@@ -435,6 +437,27 @@ class Header extends React.PureComponent {
this.setState({ showingEmbedModal: false });
};
+ getMetadataItems = () => {
+ const { dashboardInfo } = this.props;
+ return [
+ {
+ type: MetadataType.LastModified,
+ value: dashboardInfo.changed_on_delta_humanized,
+ modifiedBy:
+ getOwnerName(dashboardInfo.changed_by) || t('Not available'),
+ },
+ {
+ type: MetadataType.Owner,
+ createdBy: getOwnerName(dashboardInfo.created_by) || t('Not available'),
+ owners:
+ dashboardInfo.owners.length > 0
+ ? dashboardInfo.owners.map(getOwnerName)
+ : t('None'),
+ createdOn: dashboardInfo.created_on_delta_humanized,
+ },
+ ];
+ };
+
render() {
const {
dashboardTitle,
@@ -535,6 +558,12 @@ class Header extends React.PureComponent {
visible={!editMode}
/>
),
+ !editMode && (
+