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

add Guided tour tile #5822

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions frontend/packages/dev-console/src/components/EmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { history, PageHeading, useAccessReview } from '@console/internal/compone
import { useExtensions } from '@console/plugin-sdk';
import { RootState } from '@console/internal/redux';
import { isAddAction, AddAction } from '../extensions/add-actions';
import GuidedTourTile from './GuidedTourTile';

import './EmptyState.scss';
import { ALL_NAMESPACES_KEY } from '@console/shared';

Expand Down Expand Up @@ -71,6 +73,7 @@ const ODCEmptyState: React.FC<Props> = ({
const addActionExtensions = useExtensions<AddAction>(
isAddAction,
).filter(({ properties: { hide } }) => (hide ? hide() : true));

return (
<>
<div className="odc-empty-state__title">
Expand All @@ -83,6 +86,7 @@ const ODCEmptyState: React.FC<Props> = ({
</div>
<div className="odc-empty-state__content">
<Gallery className="co-catalog-tile-view" hasGutter>
<GuidedTourTile />
{addActionExtensions.map((action) => (
<Item key={action.properties.id} namespace={activeNamespace} action={action} />
))}
Expand Down
19 changes: 19 additions & 0 deletions frontend/packages/dev-console/src/components/GuidedTourTile.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import '../../../../public/style/vars';

.odc-guidedtour-tile {
&__card {
height: $co-m-catalog-tile-height;
width: $co-m-catalog-tile-width;
}
&__tour {
margin-bottom: var(--pf-global--spacer--sm);
}
&__arrowbtn {
margin-right: var(--pf-global--spacer--sm);
}
&__footer {
border-top: 1px solid var(--pf-global--BorderColor--100);
padding-top: var(--pf-global--spacer--sm);
padding-bottom: var(--pf-global--spacer--sm);
}
}
83 changes: 83 additions & 0 deletions frontend/packages/dev-console/src/components/GuidedTourTile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import * as React from 'react';
import { Link } from 'react-router-dom';
import {
Card,
CardActions,
CardBody,
CardFooter,
CardHeader,
CardHeaderMain,
Dropdown,
DropdownItem,
GalleryItem,
KebabToggle,
Title,
} from '@patternfly/react-core';
import { ArrowRightIcon } from '@patternfly/react-icons';
import { getGuidedToursWithStatus } from '@console/app/src/components/guided-tours/utils/guided-tour-utils';
import './GuidedTourTile.scss';

export const HIDE_TOUR_TILE_STORAGE_KEY = 'bridge/hide-tour-tile';

const GuidedTourTile: React.FC = () => {
const isTourTileHidden = localStorage.getItem(HIDE_TOUR_TILE_STORAGE_KEY) === 'true';
const [showTile, setShowTile] = React.useState<boolean>(!isTourTileHidden);
const [isOpen, setOpen] = React.useState<boolean>(false);
const tours = getGuidedToursWithStatus();

const onRemove = () => {
localStorage.setItem(HIDE_TOUR_TILE_STORAGE_KEY, 'true');
setShowTile(false);
};

const onToggle = () => setOpen(!isOpen);

const actionDropdownItem = [
<DropdownItem
onClick={() => {
onRemove();
}}
key="action"
component="button"
>
Remove guided tours
</DropdownItem>,
];
const slicedTours = tours.length > 3 ? tours.slice(0, 3) : tours;

return slicedTours.length > 0 && showTile ? (
<GalleryItem>
<Card className="odc-guidedtour-tile__card">
<CardHeader>
<CardHeaderMain>
<Title headingLevel="h1" size="xl">
Guided Tours
</Title>
</CardHeaderMain>
<CardActions>
<Dropdown
toggle={<KebabToggle onToggle={onToggle} />}
isOpen={isOpen}
isPlain
dropdownItems={actionDropdownItem}
position="right"
/>
</CardActions>
</CardHeader>
<CardBody>
{slicedTours.map((tour) => (
<div key={tour.name} className="odc-guidedtour-tile__tour">
<Link to="/#">{tour.name}</Link>
</div>
))}
</CardBody>
<CardFooter className="odc-guidedtour-tile__footer">
<ArrowRightIcon className="odc-guidedtour-tile__arrowbtn" />
<Link to="/tours">See all guided tours</Link>
</CardFooter>
</Card>
</GalleryItem>
) : null;
};

export default GuidedTourTile;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import { Link } from 'react-router-dom';
import { shallow } from 'enzyme';
import GuidedTourTile, { HIDE_TOUR_TILE_STORAGE_KEY } from '../GuidedTourTile';
import { CardActions, Dropdown, CardBody, CardFooter } from '@patternfly/react-core';

describe('GuidedTourTile', () => {
const guidedTourTileWrapper = shallow(<GuidedTourTile />);
it('should show proper CardAction', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be good to have a test for when local storage has removed tile state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

const cardAction = guidedTourTileWrapper.find(CardActions);
expect(cardAction.exists()).toBe(true);
expect(cardAction.find(Dropdown).prop('dropdownItems').length).toEqual(1);
});
it('should show 3 tour links', () => {
const cardBody = guidedTourTileWrapper.find(CardBody);
expect(cardBody.exists()).toBe(true);
expect(cardBody.find(Link).length).toEqual(3);
});
it('should show a footer link to GuidedTourCatalog', () => {
const cardFooter = guidedTourTileWrapper.find(CardFooter);
expect(cardFooter.exists()).toBe(true);
expect(cardFooter.find(Link).exists()).toBe(true);
expect(cardFooter.find(Link).prop('to')).toEqual('/tours');
});
it('should hide GuidedTourTile when locaStorage is set', () => {
localStorage.setItem(HIDE_TOUR_TILE_STORAGE_KEY, 'true');
const emptyWrapper = shallow(<GuidedTourTile />);
expect(emptyWrapper.find(GuidedTourTile).exists()).toBe(false);
});
});