mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-24 14:08:45 +00:00
* Fix #8846 : Replace Reviewer and deploy ingestion with antd modal in the UI * Fix : Failing cypress tests * Address comments * Addressing comments * fixed failing cypress * fixing glossary test Co-authored-by: Shailesh Parmar <shailesh.parmar.webdev@gmail.com>
This commit is contained in:
parent
7241c3a975
commit
0306bc6d69
@ -82,6 +82,7 @@ it('Update table description and verify description after re-run', () => {
|
||||
|
||||
it('Add Usage ingestion', () => {
|
||||
interceptURL('GET', 'api/v1/teams/name/Organization?fields=*', 'getSettingsPage');
|
||||
interceptURL("POST", "/api/v1/services/ingestionPipelines/deploy/*", "deployIngestion");
|
||||
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click({ force: true });
|
||||
verifyResponseStatusCode('@getSettingsPage', 200);
|
||||
// Services page
|
||||
@ -118,16 +119,15 @@ it('Add Usage ingestion', () => {
|
||||
|
||||
scheduleIngestion();
|
||||
|
||||
// wait for ingestion to run
|
||||
cy.clock();
|
||||
cy.wait(10000);
|
||||
|
||||
cy.get('[data-testid="view-service-button"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.wait("@deployIngestion").then(() => {
|
||||
cy.get('[data-testid="view-service-button"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
handleIngestionRetry('database', true, 0, 'usage');
|
||||
handleIngestionRetry('database', true, 0, 'usage');
|
||||
});
|
||||
});
|
||||
|
||||
it('Verify if usage is ingested properly',() => {
|
||||
|
||||
@ -104,7 +104,7 @@ describe('Data Quality and Profiler should work properly', () => {
|
||||
.scrollIntoView()
|
||||
.contains('Profiler Ingestion')
|
||||
.click();
|
||||
cy.get('[data-testid="profileSample"]').should('be.visible').type(10);
|
||||
cy.get('[data-testid="profileSample"]').should('be.visible').and('not.be.disabled').type(10);
|
||||
cy.get('[data-testid="next-button"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
@ -112,10 +112,6 @@ describe('Data Quality and Profiler should work properly', () => {
|
||||
|
||||
scheduleIngestion();
|
||||
|
||||
// wait for ingestion to run
|
||||
cy.clock();
|
||||
cy.wait(10000);
|
||||
|
||||
cy.wait("@deployIngestion").then(() => {
|
||||
cy.get('[data-testid="view-service-button"]')
|
||||
.scrollIntoView()
|
||||
|
||||
@ -24,8 +24,9 @@ import {
|
||||
} from '../../constants/constants';
|
||||
|
||||
const createGlossaryTerm = (term) => {
|
||||
cy.get('[data-testid="header"]')
|
||||
.should('be.visible')
|
||||
cy.get('[data-testid="breadcrumb-link"]')
|
||||
.should('exist')
|
||||
.and('be.visible')
|
||||
.contains(NEW_GLOSSARY.name)
|
||||
.should('exist');
|
||||
cy.get('[data-testid="add-new-tag-button"]').should('be.visible').click();
|
||||
@ -62,12 +63,12 @@ const createGlossaryTerm = (term) => {
|
||||
.click();
|
||||
verifyResponseStatusCode('@createGlossaryTerms', 201);
|
||||
|
||||
cy.get('#left-panelV1').contains(term.name).should('be.visible');
|
||||
cy.get('[data-testid="glossary-left-panel"]').contains(term.name).should('be.visible');
|
||||
};
|
||||
|
||||
const deleteGlossary = ({ name }) => {
|
||||
verifyResponseStatusCode('@getGlossaryTerms', 200);
|
||||
cy.get('#left-panelV1').contains(name).should('be.visible').click();
|
||||
cy.get('[data-testid="glossary-left-panel"]').contains(name).should('be.visible').click();
|
||||
cy.wait(500);
|
||||
cy.get('[data-testid="inactive-link"]').contains(name).should('be.visible');
|
||||
|
||||
@ -90,11 +91,11 @@ const deleteGlossary = ({ name }) => {
|
||||
|
||||
toastNotification('Glossary term deleted successfully!')
|
||||
cy.get('.tw-modal-container').should('not.exist');
|
||||
cy.get('#left-panelV1').should('be.visible').should('not.contain', name)
|
||||
cy.get('[data-testid="glossary-left-panel"]').should('be.visible').should('not.contain', name)
|
||||
};
|
||||
|
||||
const goToAssetsTab = (term) => {
|
||||
cy.get('#left-panelV1').should('be.visible').contains(term).click();
|
||||
cy.get('[data-testid="glossary-left-panel"]').should('be.visible').contains(term).click();
|
||||
cy.wait(500);
|
||||
cy.get('[data-testid="inactive-link"]').contains(term).should('be.visible');
|
||||
cy.get('[data-testid="Assets"]').should('be.visible').click();
|
||||
@ -112,7 +113,8 @@ describe('Glossary page should work properly', () => {
|
||||
.click({ animationDistanceThreshold: 10 });
|
||||
//Clicking on Glossary
|
||||
cy.get('[data-testid="appbar-item-glossary"]')
|
||||
.should('be.visible')
|
||||
.should('exist')
|
||||
.and('be.visible')
|
||||
.click();
|
||||
|
||||
// Todo: need to remove below uncaught exception once tree-view error resolves
|
||||
@ -124,6 +126,8 @@ describe('Glossary page should work properly', () => {
|
||||
});
|
||||
|
||||
it('Create new glossary flow should work properly', () => {
|
||||
interceptURL('POST', '/api/v1/glossaries', 'createGlossary');
|
||||
|
||||
// check for no data placeholder
|
||||
cy.get('[data-testid="add-new-glossary"]').should('be.visible').as('addNewGlossary');
|
||||
|
||||
@ -148,10 +152,12 @@ describe('Glossary page should work properly', () => {
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('.tw-modal-container').should('be.visible');
|
||||
cy.get('[data-testid="confirmation-modal"]').should('exist').within(() => {
|
||||
cy.get('[role="dialog"]').should('be.visible');
|
||||
});
|
||||
|
||||
//Change this once issue related to suggestion API is fixed.
|
||||
cy.get('.tw-grid > [data-testid="user-card-container"]')
|
||||
cy.get('[data-testid="user-card-container"]')
|
||||
.first()
|
||||
.should('be.visible')
|
||||
.as('reviewer');
|
||||
@ -161,8 +167,8 @@ describe('Glossary page should work properly', () => {
|
||||
.should('be.visible')
|
||||
.check();
|
||||
|
||||
cy.get('[data-testid="saveButton"]').should('be.visible').click();
|
||||
cy.get('.tw-modal-container').should('not.exist');
|
||||
cy.get('[data-testid="save-button"]').should('exist').and('be.visible').click();
|
||||
cy.get('[data-testid="delete-confirmation-modal"]').should('not.exist');
|
||||
cy.get('[data-testid="reviewers-container"]')
|
||||
.children()
|
||||
.should('have.length', 1);
|
||||
@ -172,12 +178,15 @@ describe('Glossary page should work properly', () => {
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="inactive-link"]')
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.then((text) => {
|
||||
expect(text).to.equal(NEW_GLOSSARY.name);
|
||||
});
|
||||
cy.wait("@createGlossary").then(() => {
|
||||
cy.url().should('include', '/glossary/')
|
||||
cy.get('[data-testid="breadcrumb-link"]')
|
||||
.should('exist')
|
||||
.and('be.visible')
|
||||
.within(() => {
|
||||
cy.contains(NEW_GLOSSARY.name);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('Verify added glossary details', () => {
|
||||
@ -205,10 +214,12 @@ describe('Glossary page should work properly', () => {
|
||||
const newDescription = 'Updated description';
|
||||
// updating tags
|
||||
cy.get('[data-testid="tag-container"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
.should('exist')
|
||||
.and('be.visible')
|
||||
.within(() => {
|
||||
cy.get('[data-testid="add-tag"]').should('exist').and('be.visible').click()
|
||||
});
|
||||
|
||||
cy.get('[class*="-control"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
@ -221,7 +232,7 @@ describe('Glossary page should work properly', () => {
|
||||
.scrollIntoView()
|
||||
.contains('PersonalData.Personal')
|
||||
.should('be.visible');
|
||||
|
||||
|
||||
// updating description
|
||||
cy.get('[data-testid="edit-description"]').should('be.visible').click();
|
||||
cy.get('.tw-modal-container').should('be.visible');
|
||||
@ -250,7 +261,7 @@ describe('Glossary page should work properly', () => {
|
||||
const uSynonyms = ['pick up', 'take', 'obtain'];
|
||||
const newRef = { name: 'take', url: 'https://take.com' };
|
||||
const newDescription = 'Updated description';
|
||||
cy.get('#left-panelV1').should('be.visible').contains(term).click();
|
||||
cy.get('[data-testid="glossary-left-panel"]').should('be.visible').contains(term).click();
|
||||
verifyResponseStatusCode('@permissionApi', 200);
|
||||
verifyResponseStatusCode('@glossaryAPI', 200);
|
||||
|
||||
@ -423,7 +434,7 @@ describe('Glossary page should work properly', () => {
|
||||
|
||||
cy.get('[data-testid="governance"]')
|
||||
.should('exist')
|
||||
.should('be.visible')
|
||||
.and('be.visible')
|
||||
.click();
|
||||
cy.get('[data-testid="appbar-item-glossary"]')
|
||||
.should('exist')
|
||||
@ -513,7 +524,7 @@ describe('Glossary page should work properly', () => {
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('.tw-modal-container').should('be.visible');
|
||||
cy.get('[data-testid="delete-confirmation-modal"]').should('be.visible');
|
||||
cy.get('[data-testid="modal-header"]').should('be.visible').should('contain', `Delete ${NEW_GLOSSARY.name}`);
|
||||
cy.get('[data-testid="confirmation-text-input"]')
|
||||
.should('be.visible')
|
||||
|
||||
@ -248,16 +248,14 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
|
||||
{showDeployModal && (
|
||||
<DeployIngestionLoaderModal
|
||||
action={ingestionAction}
|
||||
ingestionName={ingestionData?.name || ''}
|
||||
isDeployed={isIngestionDeployed}
|
||||
isIngestionCreated={isIngestionCreated}
|
||||
progress={ingestionProgress}
|
||||
/>
|
||||
)}
|
||||
<DeployIngestionLoaderModal
|
||||
action={ingestionAction}
|
||||
ingestionName={ingestionData?.name || ''}
|
||||
isDeployed={isIngestionDeployed}
|
||||
isIngestionCreated={isIngestionCreated}
|
||||
progress={ingestionProgress}
|
||||
visible={showDeployModal}
|
||||
/>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Space } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { t } from 'i18next';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { EditorContentRef, EntityTags } from 'Models';
|
||||
import React, { useRef, useState } from 'react';
|
||||
@ -58,7 +59,7 @@ const AddGlossary = ({
|
||||
|
||||
const [name, setName] = useState('');
|
||||
const [description] = useState<string>('');
|
||||
const [showRevieweModal, setShowRevieweModal] = useState(false);
|
||||
const [showReviewerModal, setShowReviewerModal] = useState(false);
|
||||
const [tags, setTags] = useState<EntityTags[]>([]);
|
||||
const [reviewer, setReviewer] = useState<Array<EntityReference>>([]);
|
||||
|
||||
@ -67,7 +68,7 @@ const AddGlossary = ({
|
||||
};
|
||||
|
||||
const onReviewerModalCancel = () => {
|
||||
setShowRevieweModal(false);
|
||||
setShowReviewerModal(false);
|
||||
};
|
||||
|
||||
const handleReviewerSave = (reviewer: Array<EntityReference>) => {
|
||||
@ -255,7 +256,7 @@ const AddGlossary = ({
|
||||
size="x-small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => setShowRevieweModal(true)}>
|
||||
onClick={() => setShowReviewerModal(true)}>
|
||||
<FontAwesomeIcon icon="plus" />
|
||||
</Button>
|
||||
</div>
|
||||
@ -289,15 +290,13 @@ const AddGlossary = ({
|
||||
{getSaveButton()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showRevieweModal && (
|
||||
<ReviewerModal
|
||||
header="Add Reviewer"
|
||||
reviewer={reviewer}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
)}
|
||||
<ReviewerModal
|
||||
header={t('label.add-reviewer')}
|
||||
reviewer={reviewer}
|
||||
visible={showReviewerModal}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Space } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { t } from 'i18next';
|
||||
import { cloneDeep, isEmpty, isUndefined } from 'lodash';
|
||||
import { EditorContentRef, EntityTags } from 'Models';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
@ -72,7 +73,7 @@ const AddGlossaryTerm = ({
|
||||
|
||||
const [name, setName] = useState('');
|
||||
const [description] = useState<string>('');
|
||||
const [showRevieweModal, setShowRevieweModal] = useState(false);
|
||||
const [showReviewerModal, setShowReviewerModal] = useState(false);
|
||||
const [showRelatedTermsModal, setShowRelatedTermsModal] = useState(false);
|
||||
const [reviewer, setReviewer] = useState<Array<EntityReference>>([]);
|
||||
const [tags, setTags] = useState<EntityTags[]>([]);
|
||||
@ -100,7 +101,7 @@ const AddGlossaryTerm = ({
|
||||
};
|
||||
|
||||
const onReviewerModalCancel = () => {
|
||||
setShowRevieweModal(false);
|
||||
setShowReviewerModal(false);
|
||||
};
|
||||
|
||||
const handleReviewerSave = (reviewer: Array<EntityReference>) => {
|
||||
@ -478,7 +479,7 @@ const AddGlossaryTerm = ({
|
||||
size="x-small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => setShowRevieweModal(true)}>
|
||||
onClick={() => setShowReviewerModal(true)}>
|
||||
<FontAwesomeIcon icon="plus" />
|
||||
</Button>
|
||||
</div>
|
||||
@ -513,23 +514,21 @@ const AddGlossaryTerm = ({
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
{showRelatedTermsModal && (
|
||||
<RelatedTermsModal
|
||||
header="Add Related Terms"
|
||||
relatedTerms={relatedTerms}
|
||||
onCancel={onRelatedTermsModalCancel}
|
||||
onSave={handleRelatedTermsSave}
|
||||
/>
|
||||
)}
|
||||
<RelatedTermsModal
|
||||
header={t('label.add-related-terms')}
|
||||
relatedTerms={relatedTerms}
|
||||
visible={showRelatedTermsModal}
|
||||
onCancel={onRelatedTermsModalCancel}
|
||||
onSave={handleRelatedTermsSave}
|
||||
/>
|
||||
|
||||
{showRevieweModal && (
|
||||
<ReviewerModal
|
||||
header="Add Reviewers"
|
||||
reviewer={reviewer}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
)}
|
||||
<ReviewerModal
|
||||
header={t('label.add-reviewers')}
|
||||
reviewer={reviewer}
|
||||
visible={showReviewerModal}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
|
||||
@ -832,15 +832,14 @@ const AddIngestion = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
{showDeployModal && (
|
||||
<DeployIngestionLoaderModal
|
||||
action={ingestionAction}
|
||||
ingestionName={ingestionName}
|
||||
isDeployed={isIngestionDeployed}
|
||||
isIngestionCreated={isIngestionCreated}
|
||||
progress={ingestionProgress}
|
||||
/>
|
||||
)}
|
||||
<DeployIngestionLoaderModal
|
||||
action={ingestionAction}
|
||||
ingestionName={ingestionName}
|
||||
isDeployed={isIngestionDeployed}
|
||||
isIngestionCreated={isIngestionCreated}
|
||||
progress={ingestionProgress}
|
||||
visible={showDeployModal}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -15,6 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Button as ButtonAntd, Card as AntdCard, Tooltip } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { t } from 'i18next';
|
||||
import { cloneDeep, debounce, includes, isEqual } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
@ -523,14 +524,13 @@ const GlossaryDetails = ({ permissions, glossary, updateGlossary }: props) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showRevieweModal && (
|
||||
<ReviewerModal
|
||||
header="Add Reviewer"
|
||||
reviewer={reviewer}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
)}
|
||||
<ReviewerModal
|
||||
header={t('label.add-reviewer')}
|
||||
reviewer={reviewer}
|
||||
visible={showRevieweModal}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -15,6 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Button, Card, Col, Divider, Row, Tooltip, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { t } from 'i18next';
|
||||
import { cloneDeep, includes, isEqual } from 'lodash';
|
||||
import { AssetsDataType, EntityTags } from 'Models';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@ -429,14 +430,13 @@ const GlossaryTermsV1 = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{showRevieweModal && (
|
||||
<ReviewerModal
|
||||
header="Add Reviewer"
|
||||
reviewer={reviewer}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
)}
|
||||
<ReviewerModal
|
||||
header={t('label.add-reviewer')}
|
||||
reviewer={reviewer}
|
||||
visible={showRevieweModal}
|
||||
onCancel={onReviewerModalCancel}
|
||||
onSave={handleReviewerSave}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type DeployIngestionLoaderModalProps = {
|
||||
className?: string;
|
||||
ingestionName: string;
|
||||
action: string;
|
||||
progress: number;
|
||||
isIngestionCreated: boolean;
|
||||
isDeployed: boolean;
|
||||
visible: boolean;
|
||||
};
|
||||
@ -15,6 +15,7 @@ import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import DeployIngestionLoaderModal from './DeployIngestionLoaderModal';
|
||||
import { DeployIngestionLoaderModalProps } from './DeployIngestionLoaderModal.interface';
|
||||
|
||||
const deployIngestionLoaderModalProps = {
|
||||
ingestionName: 'test_metadata',
|
||||
@ -22,7 +23,8 @@ const deployIngestionLoaderModalProps = {
|
||||
progress: 0,
|
||||
isIngestionCreated: false,
|
||||
isDeployed: false,
|
||||
};
|
||||
visible: true,
|
||||
} as DeployIngestionLoaderModalProps;
|
||||
|
||||
describe('Test DeployIngestionLoaderModal component', () => {
|
||||
it('Component should render properly', async () => {
|
||||
|
||||
@ -11,18 +11,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Typography } from 'antd';
|
||||
import Modal from 'antd/lib/modal/Modal';
|
||||
import classNames from 'classnames';
|
||||
import React, { Fragment } from 'react';
|
||||
import { LITE_GRAY_COLOR, PRIMERY_COLOR } from '../../../constants/constants';
|
||||
import SVGIcons, { Icons } from '../../../utils/SvgUtils';
|
||||
type Props = {
|
||||
className?: string;
|
||||
ingestionName: string;
|
||||
action: string;
|
||||
progress: number;
|
||||
isIngestionCreated: boolean;
|
||||
isDeployed: boolean;
|
||||
};
|
||||
import { DeployIngestionLoaderModalProps } from './DeployIngestionLoaderModal.interface';
|
||||
|
||||
const DeployIngestionLoaderModal = ({
|
||||
className,
|
||||
ingestionName,
|
||||
@ -30,67 +26,63 @@ const DeployIngestionLoaderModal = ({
|
||||
progress,
|
||||
isIngestionCreated,
|
||||
isDeployed,
|
||||
}: Props) => {
|
||||
visible,
|
||||
}: DeployIngestionLoaderModalProps) => {
|
||||
const isActive = (value: boolean) => {
|
||||
return value ? PRIMERY_COLOR : LITE_GRAY_COLOR;
|
||||
};
|
||||
|
||||
return (
|
||||
<dialog
|
||||
className={classNames('tw-modal', className)}
|
||||
data-testid="deploy-modal">
|
||||
<div className="tw-modal-backdrop" />
|
||||
<div className="tw-modal-container tw-w-120">
|
||||
<div className="tw-modal-body tw-h-40" data-testid="body-text">
|
||||
<div
|
||||
className={classNames('ingestion-content tw-relative', className)}>
|
||||
<Fragment>
|
||||
<span
|
||||
className={classNames('ingestion-deploy-line')}
|
||||
style={{
|
||||
background: `linear-gradient(to right, ${PRIMERY_COLOR} ${progress}%, ${LITE_GRAY_COLOR} ${progress}%)`,
|
||||
}}
|
||||
/>
|
||||
<Modal
|
||||
centered
|
||||
destroyOnClose
|
||||
className={classNames('h-40', className)}
|
||||
closable={false}
|
||||
data-testid="deploy-modal"
|
||||
footer={null}
|
||||
visible={visible}>
|
||||
<div className="p-y-lg flex flex-col" data-testid="body-text">
|
||||
<div className={classNames('ingestion-content relative', className)}>
|
||||
<Fragment>
|
||||
<Typography.Text
|
||||
className={classNames('ingestion-deploy-line')}
|
||||
style={{
|
||||
background: `linear-gradient(to right, ${PRIMERY_COLOR} ${progress}%, ${LITE_GRAY_COLOR} ${progress}%)`,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
className="ingestion-wrapper tw-absolute"
|
||||
style={{ left: '16%' }}>
|
||||
<span
|
||||
className={classNames(
|
||||
'ingestion-deploy-rounder tw-self-center'
|
||||
)}
|
||||
style={{
|
||||
background: isActive(isIngestionCreated),
|
||||
}}>
|
||||
<span className="tw-flex-center tw-h-full">
|
||||
<SVGIcons alt="" icon={Icons.CREATE_INGESTION} />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="ingestion-wrapper tw-absolute"
|
||||
style={{ left: '72%' }}>
|
||||
<span
|
||||
className={classNames(
|
||||
'ingestion-deploy-rounder tw-self-center'
|
||||
)}
|
||||
style={{
|
||||
background: isActive(isDeployed),
|
||||
}}>
|
||||
<span className="tw-flex-center tw-h-full">
|
||||
<SVGIcons alt="" icon={Icons.DEPLOY_INGESTION} />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</Fragment>
|
||||
</div>
|
||||
<p className="tw-text-center tw-mt-24">
|
||||
{action}
|
||||
<span className="tw-font-semibold tw-ml-1">“{ingestionName}”</span>
|
||||
</p>
|
||||
<div className="ingestion-wrappe absolute" style={{ left: '16%' }}>
|
||||
<Typography.Text
|
||||
className={classNames('ingestion-deploy-rounder self-center')}
|
||||
style={{
|
||||
background: isActive(isIngestionCreated),
|
||||
}}>
|
||||
<Typography.Text className="flex-center h-full">
|
||||
<SVGIcons alt="" icon={Icons.CREATE_INGESTION} />
|
||||
</Typography.Text>
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<div className="ingestion-wrapper absolute" style={{ left: '72%' }}>
|
||||
<Typography.Text
|
||||
className={classNames('ingestion-deploy-rounder self-center')}
|
||||
style={{
|
||||
background: isActive(isDeployed),
|
||||
}}>
|
||||
<Typography.Text className="flex-center h-full">
|
||||
<SVGIcons alt="" icon={Icons.DEPLOY_INGESTION} />
|
||||
</Typography.Text>
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Fragment>
|
||||
</div>
|
||||
<Typography.Text className="text-center mt-24">
|
||||
{action}
|
||||
<Typography.Text className="font-semibold m-l-xss">
|
||||
“{ingestionName}”
|
||||
</Typography.Text>
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</dialog>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 { GlossaryTerm } from '../../../generated/entity/data/glossaryTerm';
|
||||
|
||||
export type RelatedTermsModalProp = {
|
||||
glossaryTermFQN?: string;
|
||||
relatedTerms?: Array<GlossaryTerm>;
|
||||
onCancel: () => void;
|
||||
onSave: (terms: Array<GlossaryTerm>) => void;
|
||||
header: string;
|
||||
visible: boolean;
|
||||
};
|
||||
@ -11,8 +11,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isUndefined } from 'lodash';
|
||||
|
||||
import { Button, Col, Modal, Row, Typography } from 'antd';
|
||||
import { t } from 'i18next';
|
||||
import { isUndefined, uniqueId } from 'lodash';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { searchData } from '../../../axiosAPIs/miscAPI';
|
||||
import { PAGE_SIZE } from '../../../constants/constants';
|
||||
@ -20,17 +21,9 @@ import { SearchIndex } from '../../../enums/search.enum';
|
||||
import { GlossaryTerm } from '../../../generated/entity/data/glossaryTerm';
|
||||
import CheckboxUserCard from '../../../pages/teams/CheckboxUserCard';
|
||||
import { formatSearchGlossaryTermResponse } from '../../../utils/APIUtils';
|
||||
import { Button } from '../../buttons/Button/Button';
|
||||
import Searchbar from '../../common/searchbar/Searchbar';
|
||||
import Loader from '../../Loader/Loader';
|
||||
|
||||
type RelatedTermsModalProp = {
|
||||
glossaryTermFQN?: string;
|
||||
relatedTerms?: Array<GlossaryTerm>;
|
||||
onCancel: () => void;
|
||||
onSave: (terms: Array<GlossaryTerm>) => void;
|
||||
header: string;
|
||||
};
|
||||
import { RelatedTermsModalProp } from './RelatedTermsModal.interface';
|
||||
|
||||
const RelatedTermsModal = ({
|
||||
glossaryTermFQN = '',
|
||||
@ -38,6 +31,7 @@ const RelatedTermsModal = ({
|
||||
onCancel,
|
||||
onSave,
|
||||
header,
|
||||
visible,
|
||||
}: RelatedTermsModalProp) => {
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@ -98,24 +92,6 @@ const RelatedTermsModal = ({
|
||||
}
|
||||
};
|
||||
|
||||
const getUserCards = () => {
|
||||
return options.map((d) => (
|
||||
<CheckboxUserCard
|
||||
isActionVisible
|
||||
isCheckBoxes
|
||||
item={{
|
||||
name: '',
|
||||
displayName: d.displayName || d.name,
|
||||
id: d.id,
|
||||
type: 'tag',
|
||||
isChecked: isIncludeInOptions(d.id),
|
||||
}}
|
||||
key={d.id}
|
||||
onSelect={selectionHandler}
|
||||
/>
|
||||
));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isUndefined(relatedTerms) && relatedTerms.length) {
|
||||
setOptions(relatedTerms);
|
||||
@ -124,57 +100,77 @@ const RelatedTermsModal = ({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<dialog className="tw-modal" data-testid="modal-container">
|
||||
<div className="tw-modal-backdrop" onClick={() => onCancel()} />
|
||||
<div className="tw-modal-container tw-overflow-y-auto tw-max-w-3xl tw-max-h-screen">
|
||||
<div className="tw-modal-header">
|
||||
<p className="tw-modal-title tw-text-grey-body" data-testid="header">
|
||||
{header}
|
||||
</p>
|
||||
</div>
|
||||
<div className="tw-modal-body">
|
||||
<Searchbar
|
||||
placeholder="Search for a term..."
|
||||
searchValue={searchText}
|
||||
typingInterval={500}
|
||||
onSearch={handleSearchAction}
|
||||
/>
|
||||
<div className="tw-min-h-256">
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : options.length > 0 ? (
|
||||
<div className="tw-grid tw-grid-cols-3 tw-gap-4">
|
||||
{getUserCards()}
|
||||
</div>
|
||||
) : (
|
||||
<p className="tw-text-center tw-mt-10 tw-text-grey-muted tw-text-base">
|
||||
{searchText
|
||||
? `No terms found for "${searchText}"`
|
||||
: 'No terms found'}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-modal-footer" data-testid="cta-container">
|
||||
<Modal
|
||||
centered
|
||||
destroyOnClose
|
||||
closable={false}
|
||||
data-testid="confirmation-modal"
|
||||
footer={
|
||||
<div data-testid="cta-container">
|
||||
<Button
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="link"
|
||||
data-testid="cancelButton"
|
||||
key="remove-edge-btn"
|
||||
type="text"
|
||||
onClick={onCancel}>
|
||||
Cancel
|
||||
{t('label.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="saveButton"
|
||||
size="regular"
|
||||
theme="primary"
|
||||
type="submit"
|
||||
variant="contained"
|
||||
key="save-btn"
|
||||
type="primary"
|
||||
onClick={() => onSave(selectedOption)}>
|
||||
Save
|
||||
{t('label.save')}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title={
|
||||
<Typography.Text strong data-testid="header">
|
||||
{header}
|
||||
</Typography.Text>
|
||||
}
|
||||
visible={visible}
|
||||
width={800}>
|
||||
<div className="h-full">
|
||||
<Searchbar
|
||||
placeholder={`${t('label.search-for-user')}...`}
|
||||
searchValue={searchText}
|
||||
typingInterval={500}
|
||||
onSearch={handleSearchAction}
|
||||
/>
|
||||
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : options.length > 0 ? (
|
||||
<Row gutter={[16, 16]}>
|
||||
{options.map((d) => (
|
||||
<Col key={uniqueId()} span={8}>
|
||||
<CheckboxUserCard
|
||||
isActionVisible
|
||||
isCheckBoxes
|
||||
item={{
|
||||
name: '',
|
||||
displayName: d.displayName || d.name,
|
||||
id: d.id,
|
||||
type: 'tag',
|
||||
isChecked: isIncludeInOptions(d.id),
|
||||
}}
|
||||
key={d.id}
|
||||
onSelect={selectionHandler}
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
) : (
|
||||
<Typography.Text className="flex justify-center mt-10 text-grey-muted text-base">
|
||||
{searchText
|
||||
? t('label.no-terms-found-for-searchText', {
|
||||
searchText,
|
||||
})
|
||||
: t('label.no-terms-found')}
|
||||
</Typography.Text>
|
||||
)}
|
||||
</div>
|
||||
</dialog>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -11,15 +11,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Button } from 'antd';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { Button, Col, Row, Typography } from 'antd';
|
||||
import Modal from 'antd/lib/modal/Modal';
|
||||
import { isUndefined, uniqueId } from 'lodash';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getSuggestedUsers, searchData } from '../../../axiosAPIs/miscAPI';
|
||||
import { WILD_CARD_CHAR } from '../../../constants/char.constants';
|
||||
import { SearchIndex } from '../../../enums/search.enum';
|
||||
import { User } from '../../../generated/entity/teams/user';
|
||||
import { EntityReference } from '../../../generated/type/entityReference';
|
||||
import { SearchResponse } from '../../../interface/search.interface';
|
||||
import CheckboxUserCard from '../../../pages/teams/CheckboxUserCard';
|
||||
import { formatUsersResponse } from '../../../utils/APIUtils';
|
||||
@ -29,19 +29,14 @@ import {
|
||||
getEntityReferenceFromUser,
|
||||
getUserFromEntityReference,
|
||||
} from '../../Users/Users.util';
|
||||
|
||||
type ReviewerModalProp = {
|
||||
reviewer?: Array<EntityReference>;
|
||||
onCancel: () => void;
|
||||
onSave: (reviewer: Array<EntityReference>) => void;
|
||||
header: string;
|
||||
};
|
||||
import { ReviewerModalProp } from './ReviewerModal.interface';
|
||||
|
||||
const ReviewerModal = ({
|
||||
reviewer,
|
||||
onCancel,
|
||||
onSave,
|
||||
header,
|
||||
visible,
|
||||
}: ReviewerModalProp) => {
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@ -116,26 +111,6 @@ const ReviewerModal = ({
|
||||
}
|
||||
};
|
||||
|
||||
const getUserCards = () => {
|
||||
return options.map((d) => (
|
||||
<CheckboxUserCard
|
||||
isActionVisible
|
||||
isCheckBoxes
|
||||
isIconVisible
|
||||
item={{
|
||||
name: d.name,
|
||||
displayName: d.displayName || d.name,
|
||||
email: d.email,
|
||||
id: d.id,
|
||||
isChecked: isIncludeInOptions(d.id),
|
||||
type: 'user',
|
||||
}}
|
||||
key={d.id}
|
||||
onSelect={selectionHandler}
|
||||
/>
|
||||
));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isUndefined(reviewer) && reviewer.length) {
|
||||
setOptions(reviewer.map(getUserFromEntityReference));
|
||||
@ -144,39 +119,23 @@ const ReviewerModal = ({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<dialog className="tw-modal" data-testid="modal-container">
|
||||
<div className="tw-modal-backdrop" onClick={() => onCancel()} />
|
||||
<div className="tw-modal-container tw-overflow-y-auto tw-max-w-3xl tw-max-h-screen">
|
||||
<div className="tw-modal-header">
|
||||
<p className="tw-modal-title tw-text-grey-body" data-testid="header">
|
||||
{header}
|
||||
</p>
|
||||
</div>
|
||||
<div className="tw-modal-body">
|
||||
<Searchbar
|
||||
placeholder="Search for user..."
|
||||
searchValue={searchText}
|
||||
typingInterval={500}
|
||||
onSearch={handleSearchAction}
|
||||
/>
|
||||
<div className="tw-min-h-256">
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : options.length > 0 ? (
|
||||
<div className="tw-grid tw-grid-cols-3 tw-gap-4">
|
||||
{getUserCards()}
|
||||
</div>
|
||||
) : (
|
||||
<p className="tw-text-center tw-mt-10 tw-text-grey-muted tw-text-base">
|
||||
No user available
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-modal-footer" data-testid="cta-container">
|
||||
<Button onClick={onCancel}>{t('label.cancel')}</Button>
|
||||
<Modal
|
||||
centered
|
||||
destroyOnClose
|
||||
closable={false}
|
||||
data-testid="confirmation-modal"
|
||||
footer={
|
||||
<div data-testid="cta-container">
|
||||
<Button
|
||||
data-testid="saveButton"
|
||||
data-testid="cancel"
|
||||
key="remove-edge-btn"
|
||||
type="text"
|
||||
onClick={onCancel}>
|
||||
{t('label.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="save-button"
|
||||
key="save-btn"
|
||||
type="primary"
|
||||
onClick={() =>
|
||||
onSave(selectedOption.map(getEntityReferenceFromUser))
|
||||
@ -184,8 +143,52 @@ const ReviewerModal = ({
|
||||
{t('label.save')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
}
|
||||
title={
|
||||
<Typography.Text strong data-testid="header">
|
||||
{header}
|
||||
</Typography.Text>
|
||||
}
|
||||
visible={visible}
|
||||
width={800}>
|
||||
<>
|
||||
<Searchbar
|
||||
placeholder={`${t('label.search-for-user')}...`}
|
||||
searchValue={searchText}
|
||||
typingInterval={500}
|
||||
onSearch={handleSearchAction}
|
||||
/>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : options.length > 0 ? (
|
||||
<Row gutter={[16, 16]}>
|
||||
{options.map((d) => (
|
||||
<Col key={uniqueId()} span={8}>
|
||||
<CheckboxUserCard
|
||||
isActionVisible
|
||||
isCheckBoxes
|
||||
isIconVisible
|
||||
item={{
|
||||
name: d.name,
|
||||
displayName: d.displayName || d.name,
|
||||
email: d.email,
|
||||
id: d.id,
|
||||
isChecked: isIncludeInOptions(d.id),
|
||||
type: 'user',
|
||||
}}
|
||||
key={d.id}
|
||||
onSelect={selectionHandler}
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
) : (
|
||||
<Typography.Text className="flex justify-center mt-10 text-grey-muted text-base">
|
||||
{t('label.no-user-available')}
|
||||
</Typography.Text>
|
||||
)}
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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 { EntityReference } from '../../../generated/type/entityReference';
|
||||
|
||||
export type ReviewerModalProp = {
|
||||
reviewer?: Array<EntityReference>;
|
||||
onCancel: () => void;
|
||||
onSave: (reviewer: Array<EntityReference>) => void;
|
||||
header: string;
|
||||
visible: boolean;
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user