diff --git a/superset-frontend/src/components/MetadataBar/ContentType.ts b/superset-frontend/src/components/MetadataBar/ContentType.ts
index b4fcb103f..6f88d556a 100644
--- a/superset-frontend/src/components/MetadataBar/ContentType.ts
+++ b/superset-frontend/src/components/MetadataBar/ContentType.ts
@@ -51,7 +51,7 @@ export type LastModified = {
export type Owner = {
type: MetadataType.Owner;
createdBy: string;
- owners?: string[];
+ owners?: string[] | string;
createdOn: string;
onClick?: (type: string) => void;
};
diff --git a/superset-frontend/src/components/MetadataBar/MetadataBar.tsx b/superset-frontend/src/components/MetadataBar/MetadataBar.tsx
index 2a5826480..3503021f8 100644
--- a/superset-frontend/src/components/MetadataBar/MetadataBar.tsx
+++ b/superset-frontend/src/components/MetadataBar/MetadataBar.tsx
@@ -23,27 +23,18 @@ import { styled } from '@superset-ui/core';
import { Tooltip, TooltipPlacement } from 'src/components/Tooltip';
import { ContentType } from './ContentType';
import { config } from './ContentConfig';
-
-export const MIN_NUMBER_ITEMS = 2;
-export const MAX_NUMBER_ITEMS = 6;
-
-const HORIZONTAL_PADDING = 12;
-const VERTICAL_PADDING = 8;
-const ICON_PADDING = 8;
-const SPACE_BETWEEN_ITEMS = 16;
-const ICON_WIDTH = 16;
-const TEXT_MIN_WIDTH = 70;
-const TEXT_MAX_WIDTH = 150;
-const ORDER = {
- dashboards: 0,
- table: 1,
- sql: 2,
- rows: 3,
- tags: 4,
- description: 5,
- owner: 6,
- lastModified: 7,
-};
+import {
+ HORIZONTAL_PADDING,
+ ICON_PADDING,
+ ICON_WIDTH,
+ VERTICAL_PADDING,
+ TEXT_MIN_WIDTH,
+ TEXT_MAX_WIDTH,
+ SPACE_BETWEEN_ITEMS,
+ ORDER,
+ MIN_NUMBER_ITEMS,
+ MAX_NUMBER_ITEMS,
+} from './constants';
const Bar = styled.div<{ count: number }>`
${({ theme, count }) => `
diff --git a/superset-frontend/src/components/MetadataBar/constants.ts b/superset-frontend/src/components/MetadataBar/constants.ts
new file mode 100644
index 000000000..9114c95dd
--- /dev/null
+++ b/superset-frontend/src/components/MetadataBar/constants.ts
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export const MIN_NUMBER_ITEMS = 2;
+export const MAX_NUMBER_ITEMS = 6;
+
+export const HORIZONTAL_PADDING = 12;
+export const VERTICAL_PADDING = 8;
+export const ICON_PADDING = 8;
+export const SPACE_BETWEEN_ITEMS = 16;
+export const ICON_WIDTH = 16;
+export const TEXT_MIN_WIDTH = 70;
+export const TEXT_MAX_WIDTH = 150;
+export const ORDER = {
+ dashboards: 0,
+ table: 1,
+ sql: 2,
+ rows: 3,
+ tags: 4,
+ description: 5,
+ owner: 6,
+ lastModified: 7,
+};
diff --git a/superset-frontend/src/components/MetadataBar/index.tsx b/superset-frontend/src/components/MetadataBar/index.tsx
index a40e4113b..dd72af2b0 100644
--- a/superset-frontend/src/components/MetadataBar/index.tsx
+++ b/superset-frontend/src/components/MetadataBar/index.tsx
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-import MetadataBar, { MIN_NUMBER_ITEMS, MAX_NUMBER_ITEMS } from './MetadataBar';
+import MetadataBar from './MetadataBar';
+import { MIN_NUMBER_ITEMS, MAX_NUMBER_ITEMS } from './constants';
export type { MetadataBarProps } from './MetadataBar';
diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx
index 01d542470..e49b136c0 100644
--- a/superset-frontend/src/dashboard/components/Header/index.jsx
+++ b/superset-frontend/src/dashboard/components/Header/index.jsx
@@ -44,7 +44,6 @@ import ConnectedHeaderActionsDropdown from 'src/dashboard/components/Header/Head
import PublishedStatus from 'src/dashboard/components/PublishedStatus';
import UndoRedoKeyListeners from 'src/dashboard/components/UndoRedoKeyListeners';
import PropertiesModal from 'src/dashboard/components/PropertiesModal';
-import getOwnerName from 'src/utils/getOwnerName';
import {
UNDO_LIMIT,
SAVE_TYPE_OVERWRITE,
@@ -55,7 +54,6 @@ 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';
import {
@@ -88,6 +86,7 @@ import { logEvent } from '../../../logger/actions';
import { dashboardInfoChanged } from '../../actions/dashboardInfo';
import isDashboardLoading from '../../util/isDashboardLoading';
import { useChartIds } from '../../util/charts/useChartIds';
+import { useDashboardMetadataBar } from './useDashboardMetadataBar';
const extensionsRegistry = getExtensionsRegistry();
@@ -472,32 +471,7 @@ const Header = () => {
setShowingEmbedModal(false);
}, []);
- const getMetadataItems = useCallback(
- () => [
- {
- 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,
- },
- ],
- [
- dashboardInfo.changed_by,
- dashboardInfo.changed_on_delta_humanized,
- dashboardInfo.created_by,
- dashboardInfo.created_on_delta_humanized,
- dashboardInfo.owners,
- ],
- );
+ const metadataBar = useDashboardMetadataBar(dashboardInfo);
const userCanEdit =
dashboardInfo.dash_edit_perm && !dashboardInfo.is_managed_externally;
@@ -579,15 +553,13 @@ const Header = () => {
visible={!editMode}
/>
),
- !editMode && !isEmbedded && (
-
- ),
+ !editMode && !isEmbedded && metadataBar,
],
[
boundActionCreators.savePublished,
dashboardInfo.id,
editMode,
- getMetadataItems,
+ metadataBar,
isEmbedded,
isPublished,
userCanEdit,
diff --git a/superset-frontend/src/dashboard/components/Header/useDashboardMetadataBar.tsx b/superset-frontend/src/dashboard/components/Header/useDashboardMetadataBar.tsx
new file mode 100644
index 000000000..3ded29a67
--- /dev/null
+++ b/superset-frontend/src/dashboard/components/Header/useDashboardMetadataBar.tsx
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { useMemo } from 'react';
+import { t } from '@superset-ui/core';
+import { DashboardInfo } from 'src/dashboard/types';
+import MetadataBar, { MetadataType } from 'src/components/MetadataBar';
+import getOwnerName from 'src/utils/getOwnerName';
+
+export const useDashboardMetadataBar = (dashboardInfo: DashboardInfo) => {
+ const items = useMemo(
+ () => [
+ {
+ type: MetadataType.LastModified as const,
+ value: dashboardInfo.changed_on_delta_humanized,
+ modifiedBy:
+ getOwnerName(dashboardInfo.changed_by) || t('Not available'),
+ },
+ {
+ type: MetadataType.Owner as const,
+ 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,
+ },
+ ],
+ [
+ dashboardInfo.changed_by,
+ dashboardInfo.changed_on_delta_humanized,
+ dashboardInfo.created_by,
+ dashboardInfo.created_on_delta_humanized,
+ dashboardInfo.owners,
+ ],
+ );
+
+ return ;
+};
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
index 0e52e4def..f1b328292 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings/FilterBarSettings.test.tsx
@@ -52,6 +52,9 @@ const initialState: { dashboardInfo: DashboardInfo } = {
conf: {},
},
crossFiltersEnabled: true,
+ created_on_delta_humanized: '',
+ changed_on_delta_humanized: '',
+ owners: [],
},
};
diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts
index f1b1c47b5..a643463dd 100644
--- a/superset-frontend/src/dashboard/types.ts
+++ b/superset-frontend/src/dashboard/types.ts
@@ -33,6 +33,7 @@ import Database from 'src/types/Database';
import { UrlParamEntries } from 'src/utils/urlUtils';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';
+import Owner from 'src/types/Owner';
import { ChartState } from '../explore/types';
export type { Dashboard } from 'src/types/Dashboard';
@@ -139,6 +140,11 @@ export type DashboardInfo = {
};
crossFiltersEnabled: boolean;
filterBarOrientation: FilterBarOrientation;
+ created_on_delta_humanized: string;
+ changed_on_delta_humanized: string;
+ changed_by?: Owner;
+ created_by?: Owner;
+ owners: Owner[];
};
export type ChartsState = { [key: string]: Chart };
diff --git a/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx b/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx
index c7df2af40..20a97980d 100644
--- a/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx
+++ b/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { Tooltip } from 'src/components/Tooltip';
-import { css, logging, SupersetClient, t, tn } from '@superset-ui/core';
+import { css, logging, SupersetClient, t } from '@superset-ui/core';
import { chartPropShape } from 'src/dashboard/util/propShapes';
import AlteredSliceTag from 'src/components/AlteredSliceTag';
import Button from 'src/components/Button';
@@ -29,10 +29,10 @@ import Icons from 'src/components/Icons';
import PropertiesModal from 'src/explore/components/PropertiesModal';
import { sliceUpdated } from 'src/explore/actions/exploreActions';
import { PageHeaderWithActions } from 'src/components/PageHeaderWithActions';
-import MetadataBar, { MetadataType } from 'src/components/MetadataBar';
import { setSaveChartModalVisibility } from 'src/explore/actions/saveModalActions';
import { applyColors, resetColors } from 'src/utils/colorScheme';
import { useExploreAdditionalActionsMenu } from '../useExploreAdditionalActionsMenu';
+import { useExploreMetadataBar } from './useExploreMetadataBar';
const propTypes = {
actions: PropTypes.object.isRequired,
@@ -160,48 +160,7 @@ export const ExploreChartHeader = ({
metadata?.dashboards,
);
- const metadataBar = useMemo(() => {
- if (!metadata) {
- return null;
- }
- const items = [];
- items.push({
- type: MetadataType.Dashboards,
- title:
- metadata.dashboards.length > 0
- ? tn(
- 'Added to 1 dashboard',
- 'Added to %s dashboards',
- metadata.dashboards.length,
- metadata.dashboards.length,
- )
- : t('Not added to any dashboard'),
- description:
- metadata.dashboards.length > 0
- ? t(
- 'You can preview the list of dashboards in the chart settings dropdown.',
- )
- : undefined,
- });
- items.push({
- type: MetadataType.LastModified,
- value: metadata.changed_on_humanized,
- modifiedBy: metadata.changed_by || t('Not available'),
- });
- items.push({
- type: MetadataType.Owner,
- createdBy: metadata.created_by || t('Not available'),
- owners: metadata.owners.length > 0 ? metadata.owners : t('None'),
- createdOn: metadata.created_on_humanized,
- });
- if (slice?.description) {
- items.push({
- type: MetadataType.Description,
- value: slice?.description,
- });
- }
- return ;
- }, [metadata, slice?.description]);
+ const metadataBar = useExploreMetadataBar(metadata, slice);
const oldSliceName = slice?.slice_name;
return (
diff --git a/superset-frontend/src/explore/components/ExploreChartHeader/useExploreMetadataBar.tsx b/superset-frontend/src/explore/components/ExploreChartHeader/useExploreMetadataBar.tsx
new file mode 100644
index 000000000..943d91efc
--- /dev/null
+++ b/superset-frontend/src/explore/components/ExploreChartHeader/useExploreMetadataBar.tsx
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { useMemo } from 'react';
+import { t, tn } from '@superset-ui/core';
+import MetadataBar, { MetadataType } from 'src/components/MetadataBar';
+import { ExplorePageInitialData } from 'src/explore/types';
+
+export const useExploreMetadataBar = (
+ metadata: ExplorePageInitialData['metadata'],
+ slice: ExplorePageInitialData['slice'],
+) =>
+ useMemo(() => {
+ if (!metadata) {
+ return null;
+ }
+ const items = [];
+ if (metadata.dashboards) {
+ items.push({
+ type: MetadataType.Dashboards as const,
+ title:
+ metadata.dashboards.length > 0
+ ? tn(
+ 'Added to 1 dashboard',
+ 'Added to %s dashboards',
+ metadata.dashboards.length,
+ metadata.dashboards.length,
+ )
+ : t('Not added to any dashboard'),
+ description:
+ metadata.dashboards.length > 0
+ ? t(
+ 'You can preview the list of dashboards in the chart settings dropdown.',
+ )
+ : undefined,
+ });
+ }
+ items.push({
+ type: MetadataType.LastModified as const,
+ value: metadata.changed_on_humanized,
+ modifiedBy: metadata.changed_by || t('Not available'),
+ });
+ items.push({
+ type: MetadataType.Owner as const,
+ createdBy: metadata.created_by || t('Not available'),
+ owners: metadata.owners.length > 0 ? metadata.owners : t('None'),
+ createdOn: metadata.created_on_humanized,
+ });
+ if (slice?.description) {
+ items.push({
+ type: MetadataType.Description as const,
+ value: slice?.description,
+ });
+ }
+ return ;
+ }, [metadata, slice?.description]);
diff --git a/superset-frontend/src/explore/types.ts b/superset-frontend/src/explore/types.ts
index 8ff0219fe..301c9a686 100644
--- a/superset-frontend/src/explore/types.ts
+++ b/superset-frontend/src/explore/types.ts
@@ -82,6 +82,10 @@ export interface ExplorePageInitialData {
owners: string[];
created_by?: string;
changed_by?: string;
+ dashboards?: {
+ id: number;
+ dashboard_title: string;
+ }[];
};
saveAction?: SaveActionType | null;
}