feat(ui): change sidebar label to tooltip hover and supported multi language (#12996)

* change sidebar label to tooplip hover and supported multi language

* fix alignment and cypress issues

* fix cpress issue
This commit is contained in:
Ashish Gupta 2023-08-29 13:01:06 +05:30 committed by GitHub
parent 3cc15e6d0b
commit 197dd196fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 343 additions and 212 deletions

View File

@ -171,7 +171,7 @@ export const goToAdvanceSearch = () => {
'explorePage'
);
// Navigate to explore page
cy.get('[data-testid="appbar-item-explore"]')
cy.get('[data-testid="app-bar-item-explore"]')
.should('exist')
.and('be.visible')
.click();

View File

@ -376,7 +376,7 @@ export const deleteCreatedService = (
'api/v1/teams/name/Organization?fields=*',
'getSettingsPage'
);
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click({ force: true });
verifyResponseStatusCode('@getSettingsPage', 200);
@ -454,7 +454,7 @@ export const goToAddNewServicePage = (service_type) => {
'getSettingsPage'
);
// Click on settings page
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]').should('be.visible').click();
verifyResponseStatusCode('@getSettingsPage', 200);
// Services page
interceptURL('GET', '/api/v1/services/*', 'getServiceList');
@ -1055,7 +1055,7 @@ export const updateDescriptionForIngestedTables = (
verifyResponseStatusCode('@updateEntity', 200);
// re-run ingestion flow
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]').should('be.visible').click();
// Services page
cy.get('.ant-menu-title-content').contains(type).should('be.visible').click();
@ -1254,7 +1254,7 @@ export const visitServiceDetailsPage = (
export const visitDataModelPage = (dataModelFQN, dataModelName) => {
interceptURL('GET', '/api/v1/teams/name/*', 'getOrganization');
cy.get('[data-testid="appbar-item-settings"]').click();
cy.get('[data-testid="app-bar-item-settings"]').click();
verifyResponseStatusCode('@getOrganization', 200);

View File

@ -19,7 +19,7 @@ export const visitServiceDetailsPage = (service, verifyHeader = true) => {
'api/v1/teams/name/Organization?fields=*',
'getSettingsPage'
);
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]').should('be.visible').click();
verifyResponseStatusCode('@getSettingsPage', 200);
// Services page

View File

@ -62,29 +62,29 @@ export const LEFT_PANEL_DETAILS = {
export const NAVBAR_DETAILS = {
explore: {
testid: '[data-testid="appbar-item-explore"]',
testid: '[data-testid="app-bar-item-explore"]',
url: `${BASE_URL}/explore/tables`,
},
quality: {
testid: '[data-testid="appbar-item-data-quality"]',
testid: '[data-testid="app-bar-item-data-quality"]',
url: `${BASE_URL}/data-quality`,
},
insights: {
testid: '[data-testid="appbar-item-data-insight"]',
testid: '[data-testid="app-bar-item-data-insight"]',
url: `${BASE_URL}/data-insights`,
},
glossary: {
testid: `[data-testid="governance"]`,
subMenu: `[data-testid="appbar-item-glossary"]`,
subMenu: `[data-testid="app-bar-item-glossary"]`,
url: `${BASE_URL}/glossary`,
},
tags: {
testid: `[data-testid="governance"]`,
subMenu: '[data-testid="appbar-item-tags"]',
subMenu: '[data-testid="app-bar-item-tags"]',
url: `${BASE_URL}/tags/`,
},
settings: {
testid: '[data-testid="appbar-item-settings"]',
testid: '[data-testid="app-bar-item-settings"]',
url: `${BASE_URL}/settings/members/teams/Organization`,
},
profile: {
@ -96,7 +96,7 @@ export const NAVBAR_DETAILS = {
export const SETTINGS_LEFT_PANEL = {
settings: {
testid: '[data-testid="appbar-item-settings"]',
testid: '[data-testid="app-bar-item-settings"]',
url: `${BASE_URL}/settings/members/teams/Organization`,
},
teams: {

View File

@ -102,7 +102,7 @@ describe('Postgres Ingestion', () => {
'/api/v1/services/ingestionPipelines/deploy/*',
'deployIngestion'
);
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click({ force: true });
verifyResponseStatusCode('@getSettingsPage', 200);

View File

@ -101,7 +101,7 @@ describe('RedShift Ingestion', () => {
'/api/v1/services/ingestionPipelines/*/pipelineStatus?startTs=*&endTs=*',
'pipelineStatus'
);
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click({ force: true });
verifyResponseStatusCode('@getSettingsPage', 200);
@ -219,7 +219,7 @@ describe('RedShift Ingestion', () => {
.should('be.visible')
.click();
cy.get('[data-testid="appbar-item-tags"]')
cy.get('[data-testid="app-bar-item-tags"]')
.should('exist')
.should('be.visible')
.click({ waitForAnimations: true });

View File

@ -70,7 +70,7 @@ describe('Restore entity functionality should work properly', () => {
});
it('Check Soft Deleted entity table', () => {
cy.get('[data-testid="appbar-item-explore"]').click();
cy.get('[data-testid="app-bar-item-explore"]').click();
verifyResponseStatusCode('@nonDeletedTables', 200);
cy.get('[data-testid="show-deleted"]').should('exist').click();
@ -91,7 +91,7 @@ describe('Restore entity functionality should work properly', () => {
});
it("Check Soft Deleted table in it's Schema", () => {
cy.get('[data-testid="appbar-item-explore"]').click();
cy.get('[data-testid="app-bar-item-explore"]').click();
verifyResponseStatusCode('@nonDeletedTables', 200);
cy.get('[data-testid="show-deleted"]').click();
verifyResponseStatusCode('@showDeletedTables', 200);
@ -133,7 +133,7 @@ describe('Restore entity functionality should work properly', () => {
});
it('Restore Soft Deleted table', () => {
cy.get('[data-testid="appbar-item-explore"]').click();
cy.get('[data-testid="app-bar-item-explore"]').click();
verifyResponseStatusCode('@nonDeletedTables', 200);
cy.get('[data-testid="show-deleted"]').click();
verifyResponseStatusCode('@showDeletedTables', 200);

View File

@ -38,7 +38,9 @@ describe('Add nested teams and test TeamsSelectable', () => {
beforeEach(() => {
cy.login();
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
interceptURL('GET', '/api/v1/teams/name/*', 'getOrganization');
interceptURL('GET', '/api/v1/permissions/team/name/*', 'getPermissions');
// Clicking on teams

View File

@ -163,7 +163,7 @@ describe('Add and Remove Owner', () => {
'testSuiteDetails'
);
interceptURL('GET', '/api/v1/dataQuality/testCases?*', 'testCases');
cy.get('[data-testid="appbar-item-data-quality"]')
cy.get('[data-testid="app-bar-item-data-quality"]')
.should('be.visible')
.click();
verifyResponseStatusCode('@testSuites', 200);
@ -189,7 +189,9 @@ describe('Add and Remove Owner', () => {
'/api/v1/teams/name/Organization?fields=*',
'getOrganization'
);
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
verifyResponseStatusCode('@entityPermission', 200);
verifyResponseStatusCode('@getOrganization', 200);
verifyResponseStatusCode('@teamPermission', 200);
@ -203,8 +205,9 @@ describe('Add and Remove Owner', () => {
interceptURL('GET', '/api/v1/permissions/glossary/*', 'glossaryPermission');
interceptURL('GET', '/api/v1/glossaries?*', 'getGlossaries');
cy.get('[data-testid="governance"]').should('be.visible').click();
cy.get('[data-testid="appbar-item-glossary"]').click({
cy.get('[data-testid="app-bar-item-glossary"]').click({
waitForAnimations: true,
force: true,
});
verifyResponseStatusCode('@getGlossaries', 200);
cy.get('[data-testid="add-glossary"]').click();
@ -238,9 +241,9 @@ describe('Add and Remove Owner', () => {
'getGlossaryTermDetails'
);
cy.get('[data-testid="governance"]').should('be.visible').click();
cy.get('[data-testid="appbar-item-glossary"]')
cy.get('[data-testid="app-bar-item-glossary"]')
.should('be.visible')
.click({ waitForAnimations: true });
.click({ waitForAnimations: true, force: true });
verifyResponseStatusCode('@getGlossaries', 200);
verifyResponseStatusCode('@glossaryPermission', 200);
interceptURL('GET', '/api/v1/glossaryTerms*', 'getGlossaryTerms');
@ -274,9 +277,9 @@ describe('Add and Remove Owner', () => {
interceptURL('GET', '/api/v1/glossaries?*', 'getGlossaries');
cy.get('[data-testid="governance"]').should('be.visible').click();
cy.get('[data-testid="appbar-item-glossary"]')
cy.get('[data-testid="app-bar-item-glossary"]')
.should('be.visible')
.click({ waitForAnimations: true });
.click({ waitForAnimations: true, force: true });
verifyResponseStatusCode('@getGlossaries', 200);
verifyResponseStatusCode('@glossaryPermission', 200);
interceptURL('GET', '/api/v1/glossaryTerms*', 'getGlossaryTerms');

View File

@ -28,7 +28,9 @@ describe('Test Add role and assign it to the user', () => {
cy.login();
interceptURL('GET', '*api/v1/roles*', 'getRoles');
interceptURL('GET', '/api/v1/users?*', 'usersPage');
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
});
it('Create role', () => {

View File

@ -48,7 +48,9 @@ describe('Create a team and add that team as a owner of the entity', () => {
it('Add a group team type and assign it as a owner of the entity', () => {
interceptURL('GET', '/api/v1/teams/name/*', 'getTeams');
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
// Clicking on teams
cy.get('[data-testid="settings-left-panel"]')

View File

@ -33,7 +33,7 @@ describe(`Advanced search quick filters should work properly for assets`, () =>
it(`should show the quick filters for respective assets`, () => {
// Navigate to explore page
cy.get('[data-testid="appbar-item-explore"]').click();
cy.get('[data-testid="app-bar-item-explore"]').click();
QUICK_FILTERS_BY_ASSETS.map((asset) => {
cy.get(`[data-testid="${asset.tab}"]`).scrollIntoView().click();
@ -50,7 +50,7 @@ describe(`Advanced search quick filters should work properly for assets`, () =>
const asset = QUICK_FILTERS_BY_ASSETS[0];
// Navigate to explore page
cy.get('[data-testid="appbar-item-explore"]').click();
cy.get('[data-testid="app-bar-item-explore"]').click();
cy.get(`[data-testid="${asset.tab}"]`).scrollIntoView().click();
asset.filters

View File

@ -17,29 +17,29 @@ describe('Collect end point should work properly', () => {
const PAGES = {
setting: {
name: 'Settings',
mainMenuId: `[data-testid="appbar-item-settings"]`,
mainMenuId: `[data-testid="app-bar-item-settings"]`,
},
explore: {
name: 'Explore',
mainMenuId: `[data-testid="appbar-item-explore"]`,
mainMenuId: `[data-testid="app-bar-item-explore"]`,
},
dataQuality: {
name: 'Quality',
mainMenuId: `[data-testid="appbar-item-data-quality"]`,
mainMenuId: `[data-testid="app-bar-item-data-quality"]`,
},
insight: {
name: 'Insights',
mainMenuId: `[data-testid="appbar-item-data-insight"]`,
mainMenuId: `[data-testid="app-bar-item-data-insight"]`,
},
glossary: {
name: 'Glossary',
mainMenuId: `[data-testid="governance"]`,
subMenu: `[data-testid="appbar-item-glossary"]`,
subMenu: `[data-testid="app-bar-item-glossary"]`,
},
tag: {
name: 'Tags',
mainMenuId: `[data-testid="governance"]`,
subMenu: `[data-testid="appbar-item-tags"]`,
subMenu: `[data-testid="app-bar-item-tags"]`,
},
};
@ -66,7 +66,7 @@ describe('Collect end point should work properly', () => {
if (page.subMenu) {
// adding manual wait to open dropdown in UI
cy.wait(500);
cy.get(page.subMenu).should('be.visible').click();
cy.get(page.subMenu).should('be.visible').click({ force: true });
}
assertCollectEndPoint();
});

View File

@ -21,7 +21,7 @@ describe('Logout User', () => {
it('After login logout the user and invalidate the token', () => {
interceptURL('POST', '/api/v1/users/logout', 'logoutUser');
cy.get('[data-testid="appbar-item-logout"]').click();
cy.get('[data-testid="app-bar-item-logout"]').click();
cy.get('[data-testid="confirm-logout"]').click();

View File

@ -55,7 +55,9 @@ describe.skip('pre-requests for test case', () => {
'api/v1/teams/name/Organization?fields=*',
'getSettingsPage'
);
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
verifyResponseStatusCode('@getSettingsPage', 200);
// Services page
interceptURL('GET', '/api/v1/services/*', 'getServiceList');

View File

@ -61,7 +61,7 @@ describe.skip('Alerts page should work properly', () => {
interceptURL('POST', '/api/v1/events/subscriptions', 'createAlert');
interceptURL('GET', `/api/v1/search/query?q=*`, 'getSearchResult');
cy.login();
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('exist')
.and('be.visible')
.click();

View File

@ -76,7 +76,7 @@ const revokeToken = () => {
describe('Bots Page should work properly', () => {
beforeEach(() => {
cy.login();
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('exist')
.should('be.visible')
.click();

View File

@ -26,7 +26,7 @@ describe('Custom Logo Config', () => {
beforeEach(() => {
cy.login();
cy.get('[data-testid="appbar-item-settings"]').click();
cy.get('[data-testid="app-bar-item-settings"]').click();
interceptURL(
'GET',

View File

@ -25,7 +25,9 @@ describe('Custom Properties should work properly', () => {
cy.login();
interceptURL('GET', '/api/v1/teams/name/*', 'settingsPage');
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
verifyResponseStatusCode('@settingsPage', 200);
cy.get('[data-testid="settings-left-panel"]').should('be.visible');
});
@ -59,7 +61,7 @@ describe('Custom Properties should work properly', () => {
);
// Navigating back to custom properties page
cy.get('[data-testid="appbar-item-settings"]').click();
cy.get('[data-testid="app-bar-item-settings"]').click();
cy.get(`[data-menu-id*="customAttributes.${entity.name}"]`)
.scrollIntoView()
.click();
@ -130,7 +132,7 @@ describe('Custom Properties should work properly', () => {
);
// Navigating back to custom properties page
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
// Selecting the entity
@ -206,7 +208,7 @@ describe('Custom Properties should work properly', () => {
);
// Navigating back to custom properties page
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
cy.get(`[data-menu-id*="customAttributes.${entity.name}"]`)

View File

@ -30,7 +30,7 @@ describe('Data Insight Alert', () => {
beforeEach(() => {
cy.login();
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('exist')
.and('be.visible')
.click();

View File

@ -21,7 +21,7 @@ describe('Data Insight settings page should work properly', () => {
cy.login();
interceptURL('GET', '/api/v1/teams/name/*', 'settingsPage');
cy.get('[data-testid="appbar-item-settings"]').click();
cy.get('[data-testid="app-bar-item-settings"]').click();
verifyResponseStatusCode('@settingsPage', 200);
cy.get('[data-testid="settings-left-panel"]').should('be.visible');

View File

@ -98,7 +98,9 @@ describe('Data Quality and Profiler should work properly', () => {
cy.clickOnLogo();
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
cy.get('[data-menu-id*="databases"]').should('be.visible').click();
cy.intercept('/api/v1/services/ingestionPipelines?*').as('ingestionData');
interceptURL(
@ -443,7 +445,7 @@ describe('Data Quality and Profiler should work properly', () => {
'/api/v1/search/query?q=*&index=test_case_search_index*',
'getTestCase'
);
cy.get('[data-testid="appbar-item-data-quality"]').click();
cy.get('[data-testid="app-bar-item-data-quality"]').click();
cy.get('[data-testid="by-test-suites"]').click();
verifyResponseStatusCode('@testSuite', 200);
cy.get('[data-testid="add-test-suite-btn"]').click();
@ -483,7 +485,7 @@ describe('Data Quality and Profiler should work properly', () => {
'/api/v1/dataQuality/testCases/logicalTestCases',
'putTestCase'
);
cy.get('[data-testid="appbar-item-data-quality"]').click();
cy.get('[data-testid="app-bar-item-data-quality"]').click();
cy.get('[data-testid="by-test-suites"]').click();
verifyResponseStatusCode('@testSuite', 200);
cy.get('[data-testid="test-suite-container"]')
@ -520,7 +522,7 @@ describe('Data Quality and Profiler should work properly', () => {
'/api/v1/dataQuality/testCases/logicalTestCases/*/*',
'removeTestCase'
);
cy.get('[data-testid="appbar-item-data-quality"]').click();
cy.get('[data-testid="app-bar-item-data-quality"]').click();
cy.get('[data-testid="by-test-suites"]').click();
verifyResponseStatusCode('@testSuite', 200);
cy.get('[data-testid="test-suite-container"]')
@ -544,7 +546,7 @@ describe('Data Quality and Profiler should work properly', () => {
'/api/v1/dataQuality/testSuites?fields=*&testSuiteType=logical',
'testSuite'
);
cy.get('[data-testid="appbar-item-data-quality"]').click();
cy.get('[data-testid="app-bar-item-data-quality"]').click();
cy.get('[data-testid="by-test-suites"]').click();
verifyResponseStatusCode('@testSuite', 200);
cy.get('[data-testid="test-suite-container"]')

View File

@ -394,10 +394,10 @@ describe('Glossary page should work properly', () => {
.and('be.visible')
.then(($el) => {
cy.wrap($el)
.find('[data-testid="appbar-item-glossary"]')
.find('[data-testid="app-bar-item-glossary"]')
.should('exist')
.and('be.visible')
.click();
.click({ force: true });
});
});
@ -786,7 +786,7 @@ describe('Glossary page should work properly', () => {
.should('contain', term3);
cy.get('[data-testid="governance"]').click();
cy.get('[data-testid="appbar-item-glossary"]').click();
cy.get('[data-testid="app-bar-item-glossary"]').click({ force: true });
cy.get('.ant-menu-item').contains(NEW_GLOSSARY_1.name).click();
@ -859,7 +859,7 @@ describe('Glossary page should work properly', () => {
.and('not.contain', 'Personal');
cy.get('[data-testid="governance"]').click();
cy.get('[data-testid="appbar-item-glossary"]').click();
cy.get('[data-testid="app-bar-item-glossary"]').click({ force: true });
selectActiveGlossary(NEW_GLOSSARY_1.name);

View File

@ -100,7 +100,9 @@ describe('Policy page should work properly', () => {
cy.login();
cy.intercept('GET', '*api/v1/policies*').as('getPolicies');
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
cy.get('[data-testid="settings-left-panel"]')
.contains('Policies')

View File

@ -61,7 +61,9 @@ describe('Roles page should work properly', () => {
interceptURL('GET', '*api/v1/roles*', 'getRoles');
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
cy.get('[data-testid="settings-left-panel"]')
.contains('Roles')

View File

@ -38,7 +38,9 @@ describe('Services page should work properly', () => {
cy.login();
// redirecting to services page
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
cy.get('[data-testid="settings-left-panel"]')
.contains('Database')

View File

@ -121,7 +121,7 @@ describe('Tags page should work', () => {
// adding manual wait to open dropdown in UI
cy.wait(500);
cy.get('[data-testid="appbar-item-tags"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-tags"]').should('be.visible').click();
verifyResponseStatusCode('@getTags', 200);
});

View File

@ -53,7 +53,9 @@ describe('Teams flow should work properly', () => {
interceptURL('GET', `/api/v1/permissions/team/name/*`, 'permissions');
cy.login();
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
cy.get('[data-testid="app-bar-item-settings"]')
.should('be.visible')
.click();
// Clicking on teams
cy.get('[data-testid="settings-left-panel"]')

View File

@ -34,7 +34,7 @@ describe('Users flow should work properly', () => {
beforeEach(() => {
cy.login();
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('exist')
.should('be.visible')
.click();
@ -82,7 +82,7 @@ describe('Admin flow should work properly', () => {
beforeEach(() => {
cy.login();
cy.get('[data-testid="appbar-item-settings"]')
cy.get('[data-testid="app-bar-item-settings"]')
.should('exist')
.should('be.visible')
.click();

View File

@ -10,22 +10,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Button, Col, Menu, MenuProps, Row, Typography } from 'antd';
import { Button, Col, Menu, MenuProps, Row, Tooltip, Typography } from 'antd';
import Modal from 'antd/lib/modal/Modal';
import { ReactComponent as GovernIcon } from 'assets/svg/bank.svg';
import { ReactComponent as ClassificationIcon } from 'assets/svg/classification.svg';
import { ReactComponent as ExploreIcon } from 'assets/svg/globalsearch.svg';
import { ReactComponent as GlossaryIcon } from 'assets/svg/glossary.svg';
import { ReactComponent as QualityIcon } from 'assets/svg/ic-quality-v1.svg';
import { ReactComponent as SettingsIcon } from 'assets/svg/ic-settings-v1.svg';
import { ReactComponent as InsightsIcon } from 'assets/svg/lampcharge.svg';
import { ReactComponent as LogoutIcon } from 'assets/svg/logout.svg';
import { useAuthContext } from 'components/authentication/auth-provider/AuthProvider';
import { ROUTES } from 'constants/constants';
import {
SETTING_ITEM,
SIDEBAR_GOVERN_LIST,
SIDEBAR_LIST,
} from 'constants/LeftSidebar.constants';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { NavLink } from 'react-router-dom';
import './left-sidebar.less';
import LeftSidebarItem from './LeftSidebarItem.component';
const LeftSidebar = () => {
const { t } = useTranslation();
@ -48,53 +47,45 @@ const LeftSidebar = () => {
key: 'governance',
popupClassName: 'govern-menu',
label: (
<div
className="d-flex flex-col items-center"
data-testid="governance">
<GovernIcon className="m-0" width={30} />
<Tooltip
overlayClassName="left-panel-tooltip"
placement="right"
title={
<Typography.Text className="left-panel-label">
{t('label.govern', { lng: 'en-US' })}
{t('label.govern')}
</Typography.Text>
</div>
}>
<GovernIcon data-testid="governance" width={30} />
</Tooltip>
),
children: [
{
key: 'glossary',
children: SIDEBAR_GOVERN_LIST.map(
({ key, label, icon, redirect_url, dataTestId }) => {
const Icon = icon;
return {
key,
label: (
<NavLink
className="no-underline"
data-testid="appbar-item-glossary"
to={{
pathname: ROUTES.GLOSSARY,
}}>
<span className="left-panel-item p-y-xss">
<GlossaryIcon className="m-0" width={30} />
<Tooltip
overlayClassName="left-panel-tooltip"
placement="right"
title={
<Typography.Text className="left-panel-label">
{t('label.glossary', { lng: 'en-US' })}
{label}
</Typography.Text>
</span>
</NavLink>
),
},
{
key: 'tags',
label: (
}>
<NavLink
className="no-underline"
data-testid="appbar-item-tags"
className="no-underline d-flex justify-center"
data-testid={dataTestId}
to={{
pathname: ROUTES.TAGS,
pathname: redirect_url,
}}>
<div className="left-panel-item p-y-xss">
<ClassificationIcon className="m-0" width={30} />
<Typography.Text className="left-panel-label">
{t('label.classification', { lng: 'en-US' })}
</Typography.Text>
</div>
<Icon className="left-panel-item p-y-sm" width={30} />
</NavLink>
</Tooltip>
),
};
}
),
},
],
},
];
}, []);
@ -103,67 +94,18 @@ const LeftSidebar = () => {
setShowConfirmLogoutModal(true);
};
const hideCofirmationModal = () => {
const hideConfirmationModal = () => {
setShowConfirmLogoutModal(false);
};
return (
<div className="d-flex flex-col justify-between h-full">
<Row className="p-y-sm">
<Col span={24}>
<NavLink
className="no-underline"
data-testid="appbar-item-explore"
to={{
pathname: '/explore/tables',
}}>
<div
className={`left-panel-item ${
location.pathname.startsWith('/explore') ? 'active' : ''
}`}>
<ExploreIcon className="m-0" width={30} />
<Typography.Text className="left-panel-label">
{t('label.explore', { lng: 'en-US' })}
</Typography.Text>
</div>
</NavLink>
</Col>
<Col span={24}>
<NavLink
className="no-underline"
data-testid="appbar-item-data-quality"
to={{
pathname: ROUTES.DATA_QUALITY,
}}>
<div
className={`left-panel-item ${
location.pathname.includes(ROUTES.DATA_QUALITY) ? 'active' : ''
}`}>
<QualityIcon className="m-0" width={30} />
<Typography.Text className="left-panel-label">
{t('label.quality', { lng: 'en-US' })}
</Typography.Text>
</div>
</NavLink>
</Col>
<Col span={24}>
<NavLink
className="no-underline"
data-testid="appbar-item-data-insight"
to={{
pathname: ROUTES.DATA_INSIGHT,
}}>
<div
className={`left-panel-item ${
location.pathname.includes(ROUTES.DATA_INSIGHT) ? 'active' : ''
}`}>
<InsightsIcon className="m-0" width={30} />
<Typography.Text className="left-panel-label">
{t('label.insight-plural', { lng: 'en-US' })}
</Typography.Text>
</div>
</NavLink>
{SIDEBAR_LIST.map((item) => (
<Col key={item.key} span={24}>
<LeftSidebarItem data={item} />
</Col>
))}
<Menu
className="left-panel-item"
items={items}
@ -174,33 +116,24 @@ const LeftSidebar = () => {
</Row>
<Row className="p-y-sm">
<Col span={24}>
<NavLink
className="no-underline"
data-testid="appbar-item-settings"
to={{
pathname: ROUTES.SETTINGS,
}}>
<div
className={`left-panel-item ${
location.pathname.startsWith('/settings') ? 'active' : ''
}`}>
<SettingsIcon className="m-0" width={30} />
<Typography.Text className="left-panel-label">
{t('label.setting-plural', { lng: 'en-US' })}
</Typography.Text>
</div>
</NavLink>
<LeftSidebarItem data={SETTING_ITEM} />
</Col>
<Col span={24}>
<Tooltip
overlayClassName="left-panel-tooltip"
placement="right"
title={
<Typography.Text className="left-panel-label">
{t('label.logout')}
</Typography.Text>
}>
<div
className="left-panel-item cursor-pointer"
data-testid="appbar-item-logout"
className="left-panel-item"
data-testid="app-bar-item-logout"
onClick={handleLogoutClick}>
<LogoutIcon className="m-0" width={30} />
<Typography.Text className="left-panel-label">
{t('label.logout', { lng: 'en-US' })}
</Typography.Text>
</div>
</Tooltip>
</Col>
</Row>
{showConfirmLogoutModal && (
@ -212,14 +145,14 @@ const LeftSidebar = () => {
footer={null}
open={showConfirmLogoutModal}
width={360}
onCancel={hideCofirmationModal}>
onCancel={hideConfirmationModal}>
<Typography.Title level={5}>{t('label.logout')}</Typography.Title>
<Typography.Text className="text-grey-muted">
{t('message.logout-confirmation')}
</Typography.Text>
<div className="d-flex gap-2 w-full m-t-md justify-center">
<Button className="confirm-btn" onClick={hideCofirmationModal}>
<Button className="confirm-btn" onClick={hideConfirmationModal}>
{t('label.cancel')}
</Button>
<Button

View File

@ -23,10 +23,10 @@ describe('LeftSidebar', () => {
</BrowserRouter>
);
const exploreLink = screen.getByTestId('appbar-item-explore');
const qualityLink = screen.getByTestId('appbar-item-data-quality');
const insightLink = screen.getByTestId('appbar-item-data-insight');
const settingsLink = screen.getByTestId('appbar-item-settings');
const exploreLink = screen.getByTestId('app-bar-item-explore');
const qualityLink = screen.getByTestId('app-bar-item-data-quality');
const insightLink = screen.getByTestId('app-bar-item-data-insight');
const settingsLink = screen.getByTestId('app-bar-item-settings');
expect(exploreLink).toBeInTheDocument();
expect(qualityLink).toBeInTheDocument();

View File

@ -0,0 +1,57 @@
/*
* 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 { Tooltip, Typography } from 'antd';
import classNames from 'classnames';
import React from 'react';
import { NavLink } from 'react-router-dom';
interface LeftSidebarItemProps {
data: {
key: string;
label: string;
dataTestId: string;
redirect_url: string;
icon: SvgComponent;
};
}
const LeftSidebarItem = ({
data: { key, label, icon, redirect_url, dataTestId },
}: LeftSidebarItemProps) => {
const Icon = icon;
return (
<Tooltip
overlayClassName="left-panel-tooltip"
placement="right"
title={
<Typography.Text className="left-panel-label">{label}</Typography.Text>
}>
<NavLink
className={classNames(
'no-underline d-flex justify-center left-panel-item',
{
active: location.pathname.startsWith(key),
}
)}
data-testid={dataTestId}
to={{
pathname: redirect_url,
}}>
<Icon width={30} />
</NavLink>
</Tooltip>
);
};
export default LeftSidebarItem;

View File

@ -0,0 +1,31 @@
/*
* 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 { render, screen } from '@testing-library/react';
import { SETTING_ITEM } from 'constants/LeftSidebar.constants';
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import LeftSidebarItem from './LeftSidebarItem.component';
describe('LeftSidebar Items', () => {
it('renders sidebar items data', () => {
render(
<BrowserRouter>
<LeftSidebarItem data={SETTING_ITEM} />
</BrowserRouter>
);
const item = screen.getByTestId('app-bar-item-settings');
expect(item).toBeInTheDocument();
});
});

View File

@ -54,6 +54,13 @@
}
.left-panel-item {
cursor: pointer;
color: @text-grey-muted;
.ant-menu-submenu-vertical {
.ant-menu-submenu-title {
margin: 0;
}
}
svg {
color: @text-grey-muted;
}
@ -71,16 +78,12 @@
svg {
color: @primary-color;
}
.left-panel-label {
color: @text-color;
}
}
.govern-menu {
width: 100px !important;
.ant-menu-item {
height: auto !important;
padding: 8px 0 0 !important;
margin: 0;
}
.ant-menu-item:hover,
@ -95,18 +98,25 @@
}
}
.ant-menu-vertical {
min-width: 100px !important;
min-width: 58px !important;
width: 58px;
margin-top: 3px;
margin-left: 4px;
.ant-menu-item {
margin: 0;
}
.ant-menu-item:not(:last-child) {
margin: 0;
}
}
}
.left-panel-label.ant-typography {
font-size: 12px;
color: @text-grey-muted;
color: @white;
font-weight: 500;
padding-top: 0.5rem;
padding: 0 20px;
line-height: 26px;
text-decoration: none;
}
@ -114,3 +124,10 @@
.confirm-btn {
width: 130px;
}
.left-panel-tooltip {
.ant-tooltip-inner {
padding: 0;
min-height: auto;
}
}

View File

@ -0,0 +1,70 @@
/*
* 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 { ReactComponent as ClassificationIcon } from 'assets/svg/classification.svg';
import { ReactComponent as ExploreIcon } from 'assets/svg/globalsearch.svg';
import { ReactComponent as GlossaryIcon } from 'assets/svg/glossary.svg';
import { ReactComponent as QualityIcon } from 'assets/svg/ic-quality-v1.svg';
import { ReactComponent as SettingsIcon } from 'assets/svg/ic-settings-v1.svg';
import { ReactComponent as InsightsIcon } from 'assets/svg/lampcharge.svg';
import i18next from 'i18next';
import { ROUTES } from './constants';
export const SIDEBAR_LIST = [
{
key: ROUTES.EXPLORE,
label: i18next.t('label.explore'),
redirect_url: '/explore/tables',
icon: ExploreIcon,
dataTestId: 'app-bar-item-explore',
},
{
key: ROUTES.DATA_QUALITY,
label: i18next.t('label.quality'),
redirect_url: ROUTES.DATA_QUALITY,
icon: QualityIcon,
dataTestId: 'app-bar-item-data-quality',
},
{
key: ROUTES.DATA_INSIGHT,
label: i18next.t('label.insight-plural'),
redirect_url: ROUTES.DATA_INSIGHT,
icon: InsightsIcon,
dataTestId: 'app-bar-item-data-insight',
},
];
export const SIDEBAR_GOVERN_LIST = [
{
key: 'glossary',
label: i18next.t('label.glossary'),
redirect_url: ROUTES.GLOSSARY,
icon: GlossaryIcon,
dataTestId: 'app-bar-item-glossary',
},
{
key: 'tags',
label: i18next.t('label.classification'),
redirect_url: ROUTES.TAGS,
icon: ClassificationIcon,
dataTestId: 'app-bar-item-tags',
},
];
export const SETTING_ITEM = {
key: ROUTES.SETTINGS,
label: i18next.t('label.setting-plural'),
redirect_url: ROUTES.SETTINGS,
icon: SettingsIcon,
dataTestId: 'app-bar-item-settings',
};