Skip to content

Commit

Permalink
chore: Brian ui fixes + fix service order (#3238)
Browse files Browse the repository at this point in the history
* UI feedback (#3218)

* UI enhancements per Jan

* Fix font sizes

* UI tweaks

* Design feedback UI

* change token

* remove token

* remove added code

---------

Co-authored-by: Brian Lee <[email protected]>

* fix conflicts

Signed-off-by: at670475 <[email protected]>

* remove unused component

Signed-off-by: at670475 <[email protected]>

* change

Signed-off-by: at670475 <[email protected]>

* fix

Signed-off-by: at670475 <[email protected]>

* sort tiles

Signed-off-by: at670475 <[email protected]>

* revert

Signed-off-by: at670475 <[email protected]>

* add tests

Signed-off-by: at670475 <[email protected]>

* hide scrollbar

Signed-off-by: at670475 <[email protected]>

* fix sonar

Signed-off-by: at670475 <[email protected]>

* add action and reducers to be able to scroll after clicking on content icons

Signed-off-by: at670475 <[email protected]>

* add tests

Signed-off-by: at670475 <[email protected]>

* fix eslint

Signed-off-by: at670475 <[email protected]>

* fix sonarcloud

Signed-off-by: at670475 <[email protected]>

* set timeout to scrolling to avoid weird behaviour and address pr comments

Signed-off-by: at670475 <[email protected]>

* fix test

Signed-off-by: at670475 <[email protected]>

---------

Signed-off-by: at670475 <[email protected]>
Co-authored-by: briandavid85 <[email protected]>
Co-authored-by: Brian Lee <[email protected]>
  • Loading branch information
3 people authored Dec 21, 2023
1 parent e2f51b1 commit eff57b1
Show file tree
Hide file tree
Showing 22 changed files with 370 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright Contributors to the Zowe Project.
*/

import { CLEAR_SERVICE, SELECT_SERVICE } from '../constants/selected-service-constants';
import { CLEAR_SERVICE, SELECT_SERVICE, STORE_CONTENT_ANCHOR } from '../constants/selected-service-constants';

export function selectService(selectedService = {}, selectedTile = '') {
return {
Expand All @@ -25,3 +25,10 @@ export function clearService() {
selectedTile: '',
};
}

export function storeContentAnchor(id) {
return {
type: STORE_CONTENT_ANCHOR,
payload: id,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
* Copyright Contributors to the Zowe Project.
*/

import { CLEAR_SERVICE, SELECT_SERVICE } from '../constants/selected-service-constants';
import { selectService, clearService } from './selected-service-actions';
import { CLEAR_SERVICE, SELECT_SERVICE, STORE_CONTENT_ANCHOR } from '../constants/selected-service-constants';
import { selectService, clearService, storeContentAnchor } from './selected-service-actions';

describe('>>> Selected Service actions tests', () => {
it('should return selected service', () => {
Expand All @@ -31,4 +31,12 @@ describe('>>> Selected Service actions tests', () => {
};
expect(clearService()).toEqual(expectedAction);
});

it('should return store content anchor', () => {
const expectedAction = {
type: STORE_CONTENT_ANCHOR,
payload: '#id',
};
expect(storeContentAnchor('#id')).toEqual(expectedAction);
});
});
14 changes: 14 additions & 0 deletions api-catalog-ui/frontend/src/components/App/_app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,20 @@ body {
span {
font-size: var( --fontSmall );
}
.icon-img {
rect, path {
transition: fill .25s ease;
}
}

&:hover .icon-img {
rect {
fill: var( --criticalShade10 );
}
path {
fill: var( --surface05 );
}
}
}
}//end button-cta

Expand Down
77 changes: 64 additions & 13 deletions api-catalog-ui/frontend/src/components/Dashboard/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { Typography, IconButton, Snackbar } from '@material-ui/core';
import { Alert } from '@mui/material';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Footer from '../Footer/Footer';
import SearchCriteria from '../Search/SearchCriteria';
import Shield from '../ErrorBoundary/Shield/Shield';
Expand All @@ -22,6 +23,7 @@ import DialogDropdown from '../Wizard/DialogDropdown';
import { enablerData } from '../Wizard/configs/wizard_onboarding_methods';
import ConfirmDialogContainer from '../Wizard/ConfirmDialogContainer';
import { customUIStyle, isAPIPortal } from '../../utils/utilFunctions';
import { sortServices } from '../../selectors/selectors';

const loadFeedbackButton = () => {
if (isAPIPortal()) {
Expand Down Expand Up @@ -71,6 +73,34 @@ export default class Dashboard extends Component {
closeAlert();
};

/**
* This method is used only in the portal in combination with CSS, to scroll the tiles.
* @param event
*/
dashboardTileScroll = (event) => {
if (isAPIPortal()) {
const gridHeader = document.querySelectorAll('.dashboard-grid-header')[0];
const getHeaderHeight = gridHeader?.offsetHeight;
const getFilterHeight = document.querySelectorAll('.filtering-container')[0]?.offsetHeight;

if (
gridHeader &&
getHeaderHeight &&
event.target &&
event.target.classList &&
event.target.scrollTop > getFilterHeight
) {
event.target.classList.add('fixed-header');
event.target.style.paddingTop = `${
getHeaderHeight + parseFloat(gridHeader.style.marginBottom) + parseFloat(gridHeader.style.marginTop)
}px`;
} else if (event.target?.classList) {
event.target.classList.remove('fixed-header');
event.target.style.paddingTop = 0;
}
}
};

render() {
const {
tiles,
Expand All @@ -83,6 +113,7 @@ export default class Dashboard extends Component {
clearError,
authentication,
storeCurrentTileId,
storeContentAnchor,
} = this.props;
const hasSearchCriteria =
typeof searchCriteria !== 'undefined' &&
Expand All @@ -100,6 +131,11 @@ export default class Dashboard extends Component {
if (hasTiles && 'customStyleConfig' in tiles[0] && tiles[0].customStyleConfig) {
customUIStyle(tiles[0].customStyleConfig);
}
let allServices;
if (hasTiles) {
allServices = sortServices(tiles);
}

return (
<div className="main-content dashboard-content">
{isAPIPortal() && <FeedbackButton />}
Expand Down Expand Up @@ -147,7 +183,12 @@ export default class Dashboard extends Component {
<ErrorDialog refreshedStaticApisError={refreshedStaticApisError} clearError={clearError} />
{!fetchTilesError && (
<div className="apis">
<div id="grid-container">
<div
id="grid-container"
onScroll={(e) => {
this.dashboardTileScroll(e);
}}
>
<div className="filtering-container">
{apiPortalEnabled && (
<div>
Expand All @@ -169,25 +210,28 @@ export default class Dashboard extends Component {
<div className="empty" />
<h4 className="description-header">Swagger</h4>
<h4 className="description-header">Use Cases</h4>
<h4 className="description-header">Tutorials</h4>
<h4 className="description-header">Videos</h4>
<h4 className="description-header">Getting Started</h4>
</div>
)}
<hr id="separator2" />

<div className="tile-container">
{isLoading && <div className="loadingDiv" />}

{hasTiles &&
tiles.map((tile) =>
tile.services.map((service) => (
<Tile
storeCurrentTileId={storeCurrentTileId}
service={service}
key={service}
tile={tile}
history={history}
/>
))
allServices.map((service) =>
tiles
.filter((tile) => tile.services.includes(service))
.map((tile) => (
<Tile
storeCurrentTileId={storeCurrentTileId}
storeContentAnchor={storeContentAnchor}
service={service}
key={service}
tile={tile}
history={history}
/>
))
)}
{!hasTiles && hasSearchCriteria && (
<Typography id="search_no_results" variant="subtitle2" className="no-content">
Expand All @@ -203,3 +247,10 @@ export default class Dashboard extends Component {
);
}
}

Dashboard.propTypes = {
tiles: PropTypes.shape({
filter: PropTypes.func.isRequired,
}).isRequired,
storeContentAnchor: PropTypes.func.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,98 @@ describe('>>> Dashboard component tests', () => {
expect(getByText('Feedback Button')).toBeInTheDocument();
});
});

it('should add fixed-header class and update padding when scrolled below filter height', () => {
process.env.REACT_APP_API_PORTAL = true;
const wrapper = shallow(
<Dashboard
tiles={null}
fetchTilesStart={jest.fn()}
fetchTilesStop={jest.fn()}
clearService={jest.fn()}
clear={jest.fn()}
assertAuthorization={jest.fn()}
authentication={jest.fn()}
/>
);
const instance = wrapper.instance();
const eventMock = {
target: {
scrollTop: 40,
classList: {
add: jest.fn(),
remove: jest.fn(),
},
style: {
paddingTop: '0px',
},
},
};
const getHeaderMock = {
offsetHeight: 50,
style: {
marginBottom: '10px',
marginTop: '5px',
},
};
const getFilterHeightMock = { offsetHeight: 30 };

jest.spyOn(document, 'querySelectorAll')
.mockReturnValueOnce([getHeaderMock])
.mockReturnValueOnce([getFilterHeightMock]);

instance.dashboardTileScroll(eventMock);

expect(eventMock.target.classList.add).toHaveBeenCalledWith('fixed-header');
expect(eventMock.target.classList.add).toHaveBeenCalledTimes(1);
expect(eventMock.target.style.paddingTop).toBe('65px');
});

it('should handle cases where elements are not found', () => {
process.env.REACT_APP_API_PORTAL = true;
const wrapper = shallow(
<Dashboard
tiles={null}
fetchTilesStart={jest.fn()}
fetchTilesStop={jest.fn()}
clearService={jest.fn()}
clear={jest.fn()}
assertAuthorization={jest.fn()}
authentication={jest.fn()}
/>
);
const instance = wrapper.instance();

const eventMock = {
target: {
scrollTop: 40,
classList: {
add: jest.fn(),
remove: jest.fn(),
},
style: {
paddingTop: '0px',
},
},
};

const getHeaderMock = {
style: {
marginBottom: '10px',
marginTop: '5px',
},
};
const getFilterHeightMock = { offsetHeight: 30 };

jest.spyOn(document, 'querySelectorAll')
.mockReturnValueOnce([getHeaderMock])
.mockReturnValueOnce([getFilterHeightMock]);

instance.dashboardTileScroll(eventMock);

expect(eventMock.target.classList.add).toHaveBeenCalledTimes(0);
expect(eventMock.target.classList.remove).toHaveBeenCalledWith('fixed-header');
expect(eventMock.target.classList.remove).toHaveBeenCalledTimes(1);
expect(eventMock.target.style.paddingTop).toBe(0);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
fetchTilesStop,
storeCurrentTileId,
} from '../../actions/catalog-tile-actions';
import { clearService } from '../../actions/selected-service-actions';
import { clearService, storeContentAnchor } from '../../actions/selected-service-actions';
import { filterText, clear } from '../../actions/filter-actions';
import { createLoadingSelector, getFilteredServices } from '../../selectors/selectors';
import { clearError, refreshedStaticApi } from '../../actions/refresh-static-apis-actions';
Expand Down Expand Up @@ -51,6 +51,7 @@ const mapDispatchToProps = {
selectEnabler,
closeAlert: () => userActions.closeAlert(),
storeCurrentTileId: (id) => storeCurrentTileId(id),
storeContentAnchor: (id) => storeContentAnchor(id),
};

export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
Loading

0 comments on commit eff57b1

Please sign in to comment.