fix(ui): tour page (#12122)

Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
This commit is contained in:
Sachin Chaurasiya 2023-06-24 10:33:26 +05:30 committed by GitHub
parent 9c2d21d496
commit 9f148031f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 289 additions and 252 deletions

View File

@ -18,6 +18,7 @@ import ErrorBoundary from 'components/ErrorBoundary/ErrorBoundary';
import GlobalSearchProvider from 'components/GlobalSearchProvider/GlobalSearchProvider';
import PermissionProvider from 'components/PermissionProvider/PermissionProvider';
import AppRouter from 'components/router/AppRouter';
import TourProvider from 'components/TourProvider/TourProvider';
import WebSocketProvider from 'components/web-scoket/web-scoket.provider';
import WebAnalyticsProvider from 'components/WebAnalytics/WebAnalyticsProvider';
import { TOAST_OPTIONS } from 'constants/Toasts.constants';
@ -38,19 +39,21 @@ const App: FunctionComponent = () => {
<ErrorBoundary>
<ApplicationConfigProvider>
<AuthProvider childComponentType={AppRouter}>
<HelmetProvider>
<WebAnalyticsProvider>
<PermissionProvider>
<WebSocketProvider>
<GlobalSearchProvider>
<EntityExportModalProvider>
<AppRouter />
</EntityExportModalProvider>
</GlobalSearchProvider>
</WebSocketProvider>
</PermissionProvider>
</WebAnalyticsProvider>
</HelmetProvider>
<TourProvider>
<HelmetProvider>
<WebAnalyticsProvider>
<PermissionProvider>
<WebSocketProvider>
<GlobalSearchProvider>
<EntityExportModalProvider>
<AppRouter />
</EntityExportModalProvider>
</GlobalSearchProvider>
</WebSocketProvider>
</PermissionProvider>
</WebAnalyticsProvider>
</HelmetProvider>
</TourProvider>
</AuthProvider>
</ApplicationConfigProvider>
</ErrorBoundary>

View File

@ -12,13 +12,11 @@
*/
import { EntityUnion } from 'components/Explore/explore.interface';
import { EntityTabs } from 'enums/entity.enum';
import { isEmpty, isNil, isUndefined } from 'lodash';
import { action, makeAutoObservable } from 'mobx';
import { ClientAuth, NewUser } from 'Models';
import { reactLocalStorage } from 'reactjs-localstorage';
import { LOCALSTORAGE_USER_PROFILES } from './constants/constants';
import { CurrentTourPageType } from './enums/tour.enum';
import { ResourcePermission } from './generated/entity/policies/accessControl/resourcePermission';
import {
EntityReference as UserTeams,
@ -55,10 +53,6 @@ class AppState {
inPageSearchText = '';
explorePageTab = 'tables';
isTourOpen = false;
currentTourPage: CurrentTourPageType = CurrentTourPageType.MY_DATA_PAGE;
activeTabforTourDatasetPage = EntityTabs.SCHEMA;
constructor() {
makeAutoObservable(this, {
updateUserDetails: action,
@ -100,12 +94,6 @@ class AppState {
this.users = data;
this.nonSecureUserDetails = data[0];
}
updateActiveTabForTourDatasetPage(data: EntityTabs) {
this.activeTabforTourDatasetPage = data;
}
updateCurrentTourPage(data: CurrentTourPageType) {
this.currentTourPage = data;
}
updateUserTeam(data: Array<UserTeams>) {
this.userTeams = data;
}

View File

@ -14,12 +14,14 @@
import { Space, Typography } from 'antd';
import { AxiosError } from 'axios';
import { useGlobalSearchProvider } from 'components/GlobalSearchProvider/GlobalSearchProvider';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { tabsInfo } from 'constants/explore.constants';
import {
urlGitbookDocs,
urlGithubRepo,
urlJoinSlack,
} from 'constants/URL.constants';
import { CurrentTourPageType } from 'enums/tour.enum';
import { isEmpty, isString, max } from 'lodash';
import { observer } from 'mobx-react';
import Qs from 'qs';
@ -43,6 +45,7 @@ import {
ROUTES,
TERM_ADMIN,
TERM_USER,
TOUR_SEARCH_TERM,
} from '../../constants/constants';
import {
addToRecentSearched,
@ -58,6 +61,8 @@ const Appbar: React.FC = (): JSX.Element => {
const location = useLocation();
const history = useHistory();
const { t } = useTranslation();
const { isTourOpen, updateTourPage, updateTourSearch, tourSearchValue } =
useTourProvider();
const {
isAuthDisabled,
@ -91,7 +96,11 @@ const Appbar: React.FC = (): JSX.Element => {
const handleSearchChange = (value: string) => {
setSearchValue(value);
value ? setIsOpen(true) : setIsOpen(false);
if (isTourOpen) {
updateTourSearch(value);
} else {
value ? setIsOpen(true) : setIsOpen(false);
}
};
const supportLink = [
@ -327,24 +336,31 @@ const Appbar: React.FC = (): JSX.Element => {
];
const searchHandler = (value: string) => {
setIsOpen(false);
addToRecentSearched(value);
if (!isTourOpen) {
setIsOpen(false);
addToRecentSearched(value);
const defaultTab: string =
searchCriteria !== '' ? tabsInfo[searchCriteria].path : '';
const defaultTab: string =
searchCriteria !== '' ? tabsInfo[searchCriteria].path : '';
history.push(
getExplorePath({
tab: defaultTab,
search: value,
isPersistFilters: false,
})
);
history.push(
getExplorePath({
tab: defaultTab,
search: value,
isPersistFilters: false,
})
);
}
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
const target = e.target as HTMLInputElement;
if (e.key === 'Enter') {
if (isTourOpen && searchValue === TOUR_SEARCH_TERM) {
updateTourPage(CurrentTourPageType.EXPLORE_PAGE);
updateTourSearch('');
}
searchHandler(target.value);
}
};
@ -376,6 +392,11 @@ const Appbar: React.FC = (): JSX.Element => {
useEffect(() => {
setSearchValue(searchQuery);
}, [searchQuery]);
useEffect(() => {
if (isTourOpen) {
setSearchValue(tourSearchValue);
}
}, [tourSearchValue, isTourOpen]);
useEffect(() => {
if (isAuthDisabled) {

View File

@ -505,6 +505,7 @@ export const DataAssetsHeader = ({
</Button>
<Button
className="w-16 p-0"
data-testid="entity-follow-button"
icon={
<Icon component={isFollowing ? StarFilledIcon : StarIcon} />
}

View File

@ -12,8 +12,8 @@
*/
import { Modal, Space } from 'antd';
import AppState from 'AppState';
import { AxiosError } from 'axios';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { mockDatasetData } from 'constants/mockTourData.constants';
import {
debounce,
@ -153,6 +153,7 @@ const EntityLineageComponent: FunctionComponent<EntityLineageProp> = ({
isFullScreen = false,
}: EntityLineageProp) => {
const { t } = useTranslation();
const { isTourOpen } = useTourProvider();
const reactFlowWrapper = useRef<HTMLDivElement>(null);
const [reactFlowInstance, setReactFlowInstance] =
useState<ReactFlowInstance>();
@ -222,7 +223,7 @@ const EntityLineageComponent: FunctionComponent<EntityLineageProp> = ({
const fetchLineageData = useCallback(
async (config: LineageConfig) => {
if (AppState.isTourOpen) {
if (isTourOpen) {
setPaginationData({});
setEntityLineage(mockDatasetData.entityLineage);
setUpdatedLineageData(mockDatasetData.entityLineage);

View File

@ -10,11 +10,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Checkbox, Col, Row, Typography } from 'antd';
import { Button, Checkbox, Col, Row, Typography } from 'antd';
import classNames from 'classnames';
import TitleBreadcrumb from 'components/common/title-breadcrumb/title-breadcrumb.component';
import { EntityHeader } from 'components/Entity/EntityHeader/EntityHeader.component';
import TableDataCardBody from 'components/TableDataCardBody/TableDataCardBody';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
import { EntityType } from 'enums/entity.enum';
import { OwnerType } from 'enums/user.enum';
@ -57,7 +58,7 @@ const ExploreSearchCard: React.FC<ExploreSearchCardProps> = forwardRef<
) => {
const { t } = useTranslation();
const { tab } = useParams<{ tab: string }>();
const { isTourOpen } = useTourProvider();
const otherDetails = useMemo(() => {
const tierValue = isString(source.tier)
? source.tier
@ -148,24 +149,34 @@ const ExploreSearchCard: React.FC<ExploreSearchCardProps> = forwardRef<
</div>
</Col>
<Col span={24}>
<Link
className="no-underline"
data-testid="entity-link"
target={openEntityInNewPage ? '_blank' : '_self'}
to={
source.fullyQualifiedName && source.entityType
? getEntityLinkFromType(
getEncodedFqn(source.fullyQualifiedName),
source.entityType as EntityType
)
: ''
}>
<Typography.Text
className="text-lg font-medium text-link-color"
data-testid="entity-header-display-name">
{stringToHTML(getEntityName(source))}
</Typography.Text>
</Link>
{isTourOpen ? (
<Button data-testid={source.fullyQualifiedName} type="link">
<Typography.Text
className="text-lg font-medium text-link-color"
data-testid="entity-header-display-name">
{stringToHTML(getEntityName(source))}
</Typography.Text>
</Button>
) : (
<Link
className="no-underline"
data-testid="entity-link"
target={openEntityInNewPage ? '_blank' : '_self'}
to={
source.fullyQualifiedName && source.entityType
? getEntityLinkFromType(
getEncodedFqn(source.fullyQualifiedName),
source.entityType as EntityType
)
: ''
}>
<Typography.Text
className="text-lg font-medium text-link-color"
data-testid="entity-header-display-name">
{stringToHTML(getEntityName(source))}
</Typography.Text>
</Link>
)}
</Col>
</Row>
)}

View File

@ -13,12 +13,11 @@
import { Space, Table as AntdTable, Typography } from 'antd';
import { AxiosError } from 'axios';
import { ROUTES } from 'constants/constants';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { mockDatasetData } from 'constants/mockTourData.constants';
import { t } from 'i18next';
import { isEmpty, lowerCase } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom';
import React, { useEffect, useState } from 'react';
import { getSampleDataByTableId } from 'rest/tableAPI';
import { WORKFLOWS_PROFILER_DOCS } from '../../constants/docs.constants';
import { Table } from '../../generated/entity/data/table';
@ -34,17 +33,12 @@ import {
SampleDataType,
} from './sample.interface';
import './SampleDataTable.style.less';
const SampleDataTable = ({ isTableDeleted, tableId }: SampleDataProps) => {
const location = useLocation();
const { isTourOpen } = useTourProvider();
const [sampleData, setSampleData] = useState<SampleData>();
const [isLoading, setIsLoading] = useState(true);
const isTourActive = useMemo(
() => location.pathname.includes(ROUTES.TOUR),
[location.pathname]
);
const getSampleDataWithType = (table: Table) => {
const { sampleData, columns } = table;
const updatedColumns = sampleData?.columns?.map((column) => {
@ -96,12 +90,12 @@ const SampleDataTable = ({ isTableDeleted, tableId }: SampleDataProps) => {
useEffect(() => {
setIsLoading(true);
if (!isTableDeleted && tableId && !isTourActive) {
if (!isTableDeleted && tableId && !isTourOpen) {
fetchSampleData();
} else {
setIsLoading(false);
}
if (isTourActive) {
if (isTourOpen) {
setSampleData(
getSampleDataWithType({
columns: mockDatasetData.tableDetails.columns,

View File

@ -32,6 +32,7 @@ import { SummaryCard } from 'components/common/SummaryCard/SummaryCard.component
import { SummaryCardProps } from 'components/common/SummaryCard/SummaryCard.interface';
import DatePickerMenu from 'components/DatePickerMenu/DatePickerMenu.component';
import { DateRangeObject } from 'components/ProfilerDashboard/component/TestSummary';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { mockDatasetData } from 'constants/mockTourData.constants';
import { Column } from 'generated/entity/data/container';
import {
@ -55,7 +56,7 @@ import { ReactComponent as DataQualityIcon } from '../../assets/svg/data-quality
import { ReactComponent as SettingIcon } from '../../assets/svg/ic-settings-primery.svg';
import { ReactComponent as NoDataIcon } from '../../assets/svg/no-data-icon.svg';
import { ReactComponent as TableProfileIcon } from '../../assets/svg/table-profile.svg';
import { API_RES_MAX_SIZE, ROUTES } from '../../constants/constants';
import { API_RES_MAX_SIZE } from '../../constants/constants';
import { PAGE_HEADERS } from '../../constants/PageHeaders.constant';
import {
allowedServiceForOperationGraph,
@ -93,20 +94,21 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
const { t } = useTranslation();
const history = useHistory();
const location = useLocation();
const { isTourOpen } = useTourProvider();
const { activeTab = TableProfilerTab.TABLE_PROFILE, activeColumnFqn } =
useMemo(() => {
const param = location.search;
const searchData = Qs.parse(
param.startsWith('?') ? param.substring(1) : param
);
const {
activeTab = isTourOpen
? TableProfilerTab.COLUMN_PROFILE
: TableProfilerTab.TABLE_PROFILE,
activeColumnFqn,
} = useMemo(() => {
const param = location.search;
const searchData = Qs.parse(
param.startsWith('?') ? param.substring(1) : param
);
return searchData as { activeTab: string; activeColumnFqn: string };
}, [location.search]);
const isTourPage = useMemo(
() => location.pathname.includes(ROUTES.TOUR),
[location.pathname]
);
return searchData as { activeTab: string; activeColumnFqn: string };
}, [location.search, isTourOpen]);
const { datasetFQN } = useParams<{ datasetFQN: string }>();
const [table, setTable] = useState<Table>();
@ -299,12 +301,12 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
useEffect(() => {
if (isUndefined(activeTab)) {
updateActiveTab(
isTourPage
isTourOpen
? TableProfilerTab.COLUMN_PROFILE
: TableProfilerTab.TABLE_PROFILE
);
}
}, []);
}, [isTourOpen]);
const handleResultUpdate = (testCase: TestCase) => {
setTableTests((prev) => {
@ -432,19 +434,19 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
}, [activeColumnFqn, columnTests]);
useEffect(() => {
if (!isUndefined(table) && viewTest && !isTourPage) {
if (!isUndefined(table) && viewTest && !isTourOpen) {
fetchAllTests();
}
}, [table, viewTest]);
}, [table, viewTest, isTourOpen]);
useEffect(() => {
if (!isTableDeleted && datasetFQN && !isTourPage) {
if (!isTableDeleted && datasetFQN && !isTourOpen) {
fetchLatestProfilerData();
}
if (isTourPage) {
if (isTourOpen) {
setTable(mockDatasetData.tableDetails as unknown as Table);
}
}, [datasetFQN]);
}, [datasetFQN, isTourOpen]);
return (
<Row

View File

@ -0,0 +1,91 @@
/*
* Copyright 2023 Collate.
* Licensed 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 { ROUTES } from 'constants/constants';
import { EntityTabs } from 'enums/entity.enum';
import { CurrentTourPageType } from 'enums/tour.enum';
import React, {
createContext,
FC,
ReactNode,
useContext,
useMemo,
useState,
} from 'react';
import { useLocation } from 'react-router-dom';
interface Props {
children: ReactNode;
}
export interface TourProviderContextProps {
isTourOpen: boolean;
isTourPage: boolean;
currentTourPage: CurrentTourPageType;
activeTabForTourDatasetPage: EntityTabs;
tourSearchValue: string;
updateIsTourOpen: (value: boolean) => void;
updateTourPage: (value: CurrentTourPageType) => void;
updateActiveTab: (value: EntityTabs) => void;
updateTourSearch: (value: string) => void;
}
export const TourContext = createContext({} as TourProviderContextProps);
const TourProvider: FC<Props> = ({ children }) => {
const location = useLocation();
const [isTourOpen, setIsTourOpen] = useState<boolean>(false);
const [currentTourPage, setCurrentTourPage] = useState<CurrentTourPageType>(
CurrentTourPageType.MY_DATA_PAGE
);
const [activeTabForTourDatasetPage, setActiveTabForTourDatasetPage] =
useState<EntityTabs>(EntityTabs.SCHEMA);
const [searchValue, setSearchValue] = useState('');
const isTourPage = useMemo(
() => location.pathname.includes(ROUTES.TOUR),
[location.pathname]
);
const handleIsTourOpen = (value: boolean) => {
setIsTourOpen(value);
};
const handleTourPageChange = (value: CurrentTourPageType) =>
setCurrentTourPage(value);
const handleActiveTabChange = (value: EntityTabs) =>
setActiveTabForTourDatasetPage(value);
const handleUpdateTourSearch = (value: string) => setSearchValue(value);
return (
<TourContext.Provider
value={{
isTourOpen,
isTourPage,
currentTourPage,
tourSearchValue: searchValue,
activeTabForTourDatasetPage,
updateActiveTab: handleActiveTabChange,
updateIsTourOpen: handleIsTourOpen,
updateTourPage: handleTourPageChange,
updateTourSearch: handleUpdateTourSearch,
}}>
{children}
</TourContext.Provider>
);
};
export const useTourProvider = () => useContext(TourContext);
export default TourProvider;

View File

@ -14,6 +14,8 @@ import { Tabs } from 'antd';
import AppState from 'AppState';
import ActivityFeedListV1 from 'components/ActivityFeed/ActivityFeedList/ActivityFeedListV1.component';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { mockFeedData } from 'constants/mockTourData.constants';
import { FeedFilter } from 'enums/mydata.enum';
import { ThreadType } from 'generated/entity/feed/thread';
import React, { useEffect, useMemo, useState } from 'react';
@ -25,6 +27,7 @@ import './feeds-widget.less';
const FeedsWidget = () => {
const { t } = useTranslation();
const { isTourOpen } = useTourProvider();
const [activeTab, setActiveTab] = useState('all');
const { loading, entityThread, getFeedData } = useActivityFeedProvider();
const [taskCount, setTaskCount] = useState(0);
@ -86,9 +89,9 @@ const FeedsWidget = () => {
key: 'all',
children: (
<ActivityFeedListV1
feedList={entityThread}
feedList={isTourOpen ? mockFeedData : entityThread}
hidePopover={false}
isLoading={loading}
isLoading={loading && !isTourOpen}
showThread={false}
/>
),

View File

@ -54,7 +54,7 @@ export const OwnerLabel = ({
}, [owner]);
return (
<Space size={8}>
<Space data-testid="owner-label" size={8}>
{profilePicture}
{displayName ? (

View File

@ -12,15 +12,15 @@
*/
import ReactTutorial, { TourSteps } from '@deuex-solutions/react-tour';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { PRIMERY_COLOR } from 'constants/constants';
import { observer } from 'mobx-react';
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useTour } from '../../hooks/useTour';
import TourEndModal from '../Modals/TourEndModal/TourEndModal';
const Tour = ({ steps }: { steps: TourSteps[] }) => {
const { isTourOpen, handleIsTourOpen } = useTour();
const { isTourOpen, updateIsTourOpen } = useTourProvider();
const [showTourEndModal, setShowTourEndModal] = useState(false);
const history = useHistory();
@ -58,7 +58,7 @@ const Tour = ({ steps }: { steps: TourSteps[] }) => {
playTour={isTourOpen}
stepWaitTimer={300}
steps={steps}
onRequestClose={() => handleIsTourOpen(false)}
onRequestClose={() => updateIsTourOpen(false)}
onRequestSkip={handleModalSubmit}
/>
) : null}

View File

@ -427,62 +427,6 @@ export const mockDatasetData = {
'Bosnia and Herzegovina',
'399.279.7217x2246',
],
[
'2fde1390-9bcd-486e-86e6-b4bb427faa75',
'8b8e2b20-020d-4be3-a11d-1408b0f394d6',
'Edward',
'Tim',
'86241 Marsh Fork',
'14727 Benjamin Place Suite 747',
'Adams, Parker and Gomez',
'Sanchezville',
'66293 Watson Unions',
'50865',
'Saint Vincent and the Grenadines',
'(631)242-5727',
],
[
'376096fe-2c8f-4e56-9ee2-7bd1dd2f9a88',
'1a065321-c6cf-486c-91b1-57f8caab4727',
'Joseph',
'Brianna',
'297 Selena Underpass',
'41353 Mcdonald Squares Apt. 397',
'Wright Inc',
'New Melanie',
'6230 Scott Roads Apt. 163',
'42639',
'Belgium',
'001-360-399-2694x145',
],
[
'afdbca76-af4e-4783-867e-e2b92161c40e',
'adc24930-9dab-400b-9f46-620c1be9c841',
'Beth',
'Justin',
'06732 Owens Ville Apt. 643',
'02881 Tyler Square',
'Baker-Coleman',
'South Jonathan',
'771 Smith Lodge Apt. 619',
'12995',
'Ecuador',
'+1-060-277-3810x438',
],
[
'b3d878b8-8e37-4922-a53a-f4b2295d8bb9',
'647a2505-86da-4bdf-b5f3-d67ac8ec7980',
'Tiffany',
'Justin',
'60489 Barbara Course Suite 095',
'9328 Ashley Drives',
'Schmidt Ltd',
'New William',
'6354 Johnson Glen',
'37229',
'Antarctica (the territory South of 60 deg S)',
'(544)876-8904x194',
],
],
},
entityLineage: {

View File

@ -1,32 +0,0 @@
/*
* Copyright 2022 Collate.
* Licensed 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 { useEffect, useState } from 'react';
import AppState from '../AppState';
export const useTour = () => {
const [isTourOpen, setIsTourOpen] = useState<boolean>();
useEffect(() => {
setIsTourOpen(AppState.isTourOpen);
}, [AppState.isTourOpen]);
const handleIsTourOpen = (value: boolean) => {
AppState.isTourOpen = value;
};
return {
isTourOpen,
handleIsTourOpen,
};
};

View File

@ -38,9 +38,11 @@ import TableProfilerV1 from 'components/TableProfiler/TableProfilerV1';
import TableQueries from 'components/TableQueries/TableQueries';
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
import TagsContainerV1 from 'components/Tag/TagsContainerV1/TagsContainerV1';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
import { getTableTabPath, getVersionPath, ROUTES } from 'constants/constants';
import { EntityField } from 'constants/Feeds.constants';
import { mockDatasetData } from 'constants/mockTourData.constants';
import { EntityTabs, EntityType, FqnPart } from 'enums/entity.enum';
import { compare } from 'fast-json-patch';
import { CreateThread } from 'generated/api/feed/createThread';
@ -80,6 +82,8 @@ import { FrequentlyJoinedTables } from './FrequentlyJoinedTables/FrequentlyJoine
import './table-details-page-v1.less';
const TableDetailsPageV1 = () => {
const { isTourOpen, activeTabForTourDatasetPage, isTourPage } =
useTourProvider();
const [tableDetails, setTableDetails] = useState<Table>();
const { datasetFQN, tab: activeTab = EntityTabs.SCHEMA } =
useParams<{ datasetFQN: string; tab: string }>();
@ -100,7 +104,7 @@ const TableDetailsPageV1 = () => {
);
const [queryCount, setQueryCount] = useState(0);
const [loading, setLoading] = useState(true);
const [loading, setLoading] = useState(!isTourOpen);
const fetchTableDetails = async () => {
setLoading(true);
@ -141,7 +145,6 @@ const TableDetailsPageV1 = () => {
DEFAULT_ENTITY_PERMISSION
);
const isTourPage = location.pathname.includes(ROUTES.TOUR);
const { postFeed, deleteFeed, updateFeed } = useActivityFeedProvider();
const {
tier,
@ -242,7 +245,7 @@ const TableDetailsPageV1 = () => {
const handleTabChange = (activeKey: string) => {
if (activeKey !== activeTab) {
if (!isTourPage) {
if (!isTourOpen) {
history.push(getTableTabPath(datasetFQN, activeKey));
}
}
@ -378,7 +381,7 @@ const TableDetailsPageV1 = () => {
const schemaTab = useMemo(
() => (
<Row gutter={[0, 16]} wrap={false}>
<Row gutter={[0, 16]} id="schemaDetails" wrap={false}>
<Col className="p-t-sm m-l-lg" flex="auto">
<div className="d-flex flex-col gap-4">
<DescriptionV1
@ -754,9 +757,13 @@ const TableDetailsPageV1 = () => {
}, [version]);
useEffect(() => {
fetchTableDetails();
getEntityFeedCount();
}, [datasetFQN]);
if (isTourOpen || isTourPage) {
setTableDetails(mockDatasetData.tableDetails as unknown as Table);
} else {
fetchTableDetails();
getEntityFeedCount();
}
}, [datasetFQN, isTourOpen, isTourPage]);
useEffect(() => {
if (tableDetails) {
@ -798,7 +805,7 @@ const TableDetailsPageV1 = () => {
title="Table details">
<Row gutter={[0, 12]}>
{/* Entity Heading */}
<Col className="p-x-lg" span={24}>
<Col className="p-x-lg" data-testid="entity-page-header" span={24}>
<DataAssetsHeader
dataAsset={tableDetails}
entityType={EntityType.TABLE}
@ -815,7 +822,11 @@ const TableDetailsPageV1 = () => {
{/* Entity Tabs */}
<Col span={24}>
<Tabs
activeKey={activeTab ?? EntityTabs.SCHEMA}
activeKey={
isTourOpen
? activeTabForTourDatasetPage
: activeTab ?? EntityTabs.SCHEMA
}
className="table-details-page-tabs"
data-testid="tabs"
items={tabs}

View File

@ -23,6 +23,8 @@ import {
} from 'components/Explore/explore.interface';
import ExploreV1 from 'components/ExploreV1/ExploreV1.component';
import { withAdvanceSearch } from 'components/router/withAdvanceSearch';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { mockSearchData } from 'constants/mockTourData.constants';
import { SORT_ORDER } from 'enums/common.enum';
import { get, isEmpty, isNil, isString, isUndefined } from 'lodash';
import Qs from 'qs';
@ -63,6 +65,7 @@ import {
const ExplorePageV1: FunctionComponent = () => {
const location = useLocation();
const history = useHistory();
const { isTourOpen } = useTourProvider();
const { tab } = useParams<UrlParams>();
@ -438,10 +441,14 @@ const ExplorePageV1: FunctionComponent = () => {
<ExploreV1
aggregations={updatedAggregations}
facetFilters={facetFilters}
loading={isLoading}
loading={isLoading && !isTourOpen}
quickFilters={advancesSearchQuickFilters}
searchIndex={searchIndex}
searchResults={searchResults}
searchResults={
isTourOpen
? (mockSearchData as unknown as SearchResponse<ExploreSearchIndex>)
: searchResults
}
showDeleted={showDeleted}
sortOrder={sortOrder}
sortValue={sortValue}

View File

@ -12,39 +12,33 @@
*/
import Tour from 'components/tour/Tour';
import { EntityTabs } from 'enums/entity.enum';
import { useTourProvider } from 'components/TourProvider/TourProvider';
import { observer } from 'mobx-react';
import ExplorePageV1Component from 'pages/explore/ExplorePageV1.component';
import MyDataPageV1 from 'pages/MyDataPage/MyDataPageV1.component';
import TableDetailsPageV1 from 'pages/TableDetailsPageV1/TableDetailsPageV1';
import React, { useEffect, useState } from 'react';
import AppState from '../../AppState';
import React, { useEffect } from 'react';
import { TOUR_SEARCH_TERM } from '../../constants/constants';
import { CurrentTourPageType } from '../../enums/tour.enum';
import { useTour } from '../../hooks/useTour';
import { getSteps } from '../../utils/TourUtils';
import { getTourSteps } from '../../utils/TourUtils';
const TourPage = () => {
const { handleIsTourOpen } = useTour();
const [currentPage, setCurrentPage] = useState<CurrentTourPageType>(
AppState.currentTourPage
);
const [, setSearchValue] = useState('');
const {
updateIsTourOpen,
currentTourPage,
updateActiveTab,
updateTourPage,
updateTourSearch,
} = useTourProvider();
const clearSearchTerm = () => {
setSearchValue('');
updateTourSearch('');
};
useEffect(() => {
handleIsTourOpen(true);
AppState.currentTourPage = CurrentTourPageType.MY_DATA_PAGE;
AppState.activeTabforTourDatasetPage = EntityTabs.SCHEMA;
updateIsTourOpen(true);
}, []);
useEffect(() => {
setCurrentPage(AppState.currentTourPage);
}, [AppState.currentTourPage]);
const getCurrentPage = (page: CurrentTourPageType) => {
switch (page) {
case CurrentTourPageType.MY_DATA_PAGE:
@ -63,8 +57,15 @@ const TourPage = () => {
return (
<>
<Tour steps={getSteps(TOUR_SEARCH_TERM, clearSearchTerm)} />
{getCurrentPage(currentPage)}
<Tour
steps={getTourSteps({
searchTerm: TOUR_SEARCH_TERM,
clearSearchTerm,
updateActiveTab,
updateTourPage,
})}
/>
{getCurrentPage(currentTourPage)}
</>
);
};

View File

@ -14,29 +14,20 @@
import { EntityTabs } from 'enums/entity.enum';
import i18next from 'i18next';
import React from 'react';
import AppState from '../AppState';
import { CurrentTourPageType } from '../enums/tour.enum';
import { Transi18next } from './CommonUtils';
export const getSteps = (value: string, clearSearchTerm: () => void) => {
const { updateActiveTabForTourDatasetPage, updateCurrentTourPage } = AppState;
interface ArgObject {
searchTerm: string;
updateTourPage: (value: CurrentTourPageType) => void;
updateActiveTab: (value: EntityTabs) => void;
clearSearchTerm: () => void;
}
export const getTourSteps = (args: ArgObject) => {
const { searchTerm, clearSearchTerm, updateActiveTab, updateTourPage } = args;
return [
{
content: () => (
<p>
<Transi18next
i18nKey="message.tour-step-discover-all-assets-at-one-place"
renderElement={<strong />}
values={{
text: i18next.t('label.open-metadata'),
}}
/>
</p>
),
stepInteraction: false,
selector: '#assetStatsCount',
},
{
content: () => (
<p>
@ -76,23 +67,23 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
i18nKey="message.tour-step-type-search-term"
renderElement={<strong />}
values={{
text: value,
text: searchTerm,
enterText: i18next.t('label.enter'),
}}
/>
</p>
),
actionType: 'enter',
userTypeText: value,
userTypeText: searchTerm,
selector: '#searchBox',
beforeNext: () => {
clearSearchTerm();
updateCurrentTourPage(CurrentTourPageType.EXPLORE_PAGE);
updateTourPage(CurrentTourPageType.EXPLORE_PAGE);
},
},
{
beforePrev: () => {
updateCurrentTourPage(CurrentTourPageType.MY_DATA_PAGE);
updateTourPage(CurrentTourPageType.MY_DATA_PAGE);
},
content: () => (
<p>
@ -118,14 +109,14 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
</p>
),
actionType: 'click',
selector: '[data-testid="sample_data-dim_address"]',
selector: '[data-testid="sample_data.ecommerce_db.shopify.dim_address"]',
beforeNext: () => {
updateCurrentTourPage(CurrentTourPageType.DATASET_PAGE);
updateTourPage(CurrentTourPageType.DATASET_PAGE);
},
},
{
beforePrev: () => {
updateCurrentTourPage(CurrentTourPageType.EXPLORE_PAGE);
updateTourPage(CurrentTourPageType.EXPLORE_PAGE);
},
content: () => (
<p>
@ -139,7 +130,7 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
</p>
),
stepInteraction: false,
selector: '[data-testid="entity-page-info"]',
selector: '[data-testid="entity-page-header"]',
},
{
content: () => (
@ -154,7 +145,7 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
</p>
),
stepInteraction: false,
selector: '[data-testid="owner-link"]',
selector: '[data-testid="owner-label"]',
},
{
content: () => (
@ -188,7 +179,7 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
},
{
beforePrev: () => {
updateActiveTabForTourDatasetPage(EntityTabs.SCHEMA);
updateActiveTab(EntityTabs.SCHEMA);
},
actionType: 'click',
content: () => (
@ -204,7 +195,7 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
),
selector: `[data-testid="${EntityTabs.SAMPLE_DATA}"]`,
beforeNext: () => {
updateActiveTabForTourDatasetPage(EntityTabs.SAMPLE_DATA);
updateActiveTab(EntityTabs.SAMPLE_DATA);
},
},
{
@ -219,14 +210,14 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
/>
</p>
),
selector: '#tab-details',
selector: '[data-testid="sample-data-table"]',
},
{
beforePrev: () => {
updateActiveTabForTourDatasetPage(EntityTabs.SAMPLE_DATA);
updateActiveTab(EntityTabs.SAMPLE_DATA);
},
beforeNext: () => {
updateActiveTabForTourDatasetPage(EntityTabs.PROFILER);
updateActiveTab(EntityTabs.PROFILER);
},
actionType: 'click',
content: () => (
@ -257,14 +248,14 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
</p>
),
stepInteraction: false,
selector: '#tab-details',
selector: '#profilerDetails',
},
{
beforePrev: () => {
updateActiveTabForTourDatasetPage(EntityTabs.PROFILER);
updateActiveTab(EntityTabs.PROFILER);
},
beforeNext: () => {
updateActiveTabForTourDatasetPage(EntityTabs.LINEAGE);
updateActiveTab(EntityTabs.LINEAGE);
},
actionType: 'click',
content: () => (
@ -293,7 +284,7 @@ export const getSteps = (value: string, clearSearchTerm: () => void) => {
</p>
),
stepInteraction: false,
selector: '#tab-details',
selector: '#lineageDetails',
},
];
};