Fixes/08 03 2022 (#3273)

* Fixes: Misc issue fixes

* Fixed issues for adding Glossary terms as tags

* Fixed UI unit tests
This commit is contained in:
darth-coder00 2022-03-08 21:51:48 +05:30 committed by GitHub
parent 876ac24e44
commit bf079a019e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 491 additions and 200 deletions

View File

@ -162,25 +162,16 @@ const AddGlossary = ({
const fetchRightPanel = () => {
return (
<>
<h6 className="tw-heading tw-text-base">Configure Your Glossary</h6>
<h6 className="tw-heading tw-text-base">Configure Glossary</h6>
<div className="tw-mb-5">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
A Glossary is a controlled vocabulary used to define the concepts and
terminology in an organization. Glossaries can be specific to a
certain domain (for e.g., Business Glossary, Technical Glossary). In
the glossary, the standard terms and concepts can be defined along
with the synonyms, and related terms. Control can be established over
how and who can add the terms in the glossary.
</div>
{/* {getDocButton('Read Webhook Doc', '', 'webhook-doc')} */}
{/* {getDocButton('Read Glossary Doc', '', 'glossary-doc')} */}
</>
);
};

View File

@ -249,25 +249,16 @@ const AddGlossaryTerm = ({
const fetchRightPanel = () => {
return (
<>
<h6 className="tw-heading tw-text-base">Configure Your Glossary</h6>
<h6 className="tw-heading tw-text-base">Configure Glossary Term</h6>
<div className="tw-mb-5">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
Every term in the glossary has a unique definition. Along with
defining the standard term for a concept, the synonyms as well as
related terms (for e.g., parent and child terms) can be specified.
References can be added to the assets related to the terms. New terms
can be added or updated to the Glossary. The glossary terms can be
reviewed by certain users, who can accept or reject the terms.
</div>
{/* {getDocButton('Read Webhook Doc', '', 'webhook-doc')} */}
{/* {getDocButton('Read Glossary Term Doc', '', 'glossary-term-doc')} */}
</>
);
};

View File

@ -15,6 +15,7 @@ import { AxiosError, AxiosResponse } from 'axios';
import { LoadingState } from 'Models';
import React, { useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
addGlossaryTerm,
getGlossariesByName,
@ -35,7 +36,8 @@ const AddGlossaryTermPage = () => {
useParams<{ [key: string]: string }>();
const showToast = useToastContext();
const history = useHistory();
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [status, setStatus] = useState<LoadingState>('initial');
const [isLoading, setIsLoading] = useState(true);
const [glossaryData, setGlossaryData] = useState<Glossary>();

View File

@ -439,23 +439,17 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
const fetchRightPanel = () => {
return (
<>
<h6 className="tw-heading tw-text-base">Configure Your Webhook</h6>
<h6 className="tw-heading tw-text-base">Configure Webhooks</h6>
<div className="tw-mb-5">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
OpenMetadata can be configured to automatically send out event
notifications to registered webhooks. Enter the webhook name, and an
Endpoint URL to receive the HTTP call back on. Use Event Filters to
only receive notifications based on events of interest, like when an
entity is created, updated, or deleted; and for the entities your
application is interested in. Add a description to help people
understand the purpose of the webhook and to keep track of the use
case. Use advanced configuration to set up a shared secret key to
verify the webhook events using HMAC signature.
</div>
{getDocButton('Read Webhook Doc', '', 'webhook-doc')}
</>

View File

@ -16,13 +16,13 @@ import { compare } from 'fast-json-patch';
import { EntityTags } from 'Models';
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { getTeamDetailsPath } from '../../constants/constants';
import { EntityType } from '../../enums/entity.enum';
import { Dashboard } from '../../generated/entity/data/dashboard';
import { Operation } from '../../generated/entity/policies/accessControl/rule';
import { EntityReference, User } from '../../generated/entity/teams/user';
import { LabelType, State, TagLabel } from '../../generated/type/tagLabel';
import { useAuth } from '../../hooks/authHooks';
import {
getCurrentUserId,
getHtmlForNonAdminAction,
@ -92,7 +92,7 @@ const DashboardDetails = ({
createThread,
dashboardFQN,
}: DashboardDetailsProps) => {
const { isAuthDisabled } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [isEdit, setIsEdit] = useState(false);
const [followersCount, setFollowersCount] = useState(0);
const [isFollowing, setIsFollowing] = useState(false);
@ -245,22 +245,9 @@ const DashboardDetails = ({
}
};
const onTagUpdate = (selectedTags?: Array<string>) => {
const onTagUpdate = (selectedTags?: Array<EntityTags>) => {
if (selectedTags) {
const prevTags =
dashboardDetails?.tags?.filter((tag) =>
selectedTags.includes(tag?.tagFQN as string)
) || [];
const newTags = selectedTags
.filter((tag) => {
return !prevTags?.map((prevTag) => prevTag.tagFQN).includes(tag);
})
.map((tag) => ({
labelType: LabelType.Manual,
state: State.Confirmed,
tagFQN: tag,
}));
const updatedTags = [...prevTags, ...newTags];
const updatedTags = [...(tier ? [tier] : []), ...selectedTags];
const updatedDashboard = { ...dashboardDetails, tags: updatedTags };
tagUpdateHandler(updatedDashboard);
}
@ -304,7 +291,10 @@ const DashboardDetails = ({
}
};
const handleChartTagSelection = (selectedTags?: Array<EntityTags>) => {
const handleChartTagSelection = (
selectedTags?: Array<EntityTags>,
allTags?: Array<string>
) => {
if (selectedTags && editChartTags) {
const prevTags = editChartTags.chart.tags?.filter((tag) =>
selectedTags.some((selectedTag) => selectedTag.tagFQN === tag.tagFQN)
@ -319,6 +309,7 @@ const DashboardDetails = ({
.map((tag) => ({
labelType: 'Manual',
state: 'Confirmed',
source: (allTags || []).includes(tag.tagFQN) ? 'Tag' : 'Glossary',
tagFQN: tag.tagFQN,
}));
@ -554,7 +545,7 @@ const DashboardDetails = ({
handleChartTagSelection();
}}
onSelectionChange={(tags) => {
handleChartTagSelection(tags);
handleChartTagSelection(tags, tagList);
}}>
{chart.tags?.length ? (
<button

View File

@ -20,6 +20,18 @@ import { EntityLineage } from '../../generated/type/entityLineage';
import { TagLabel } from '../../generated/type/tagLabel';
import DashboardDetails from './DashboardDetails.component';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockUserTeam = [
{
description: 'description',

View File

@ -15,6 +15,7 @@ import classNames from 'classnames';
import { isEqual, isNil, isUndefined } from 'lodash';
import { ColumnJoins, EntityTags, ExtraInfo } from 'Models';
import React, { useEffect, useState } from 'react';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { getTeamDetailsPath, ROUTES } from '../../constants/constants';
import { CSMode } from '../../enums/codemirror.enum';
import { EntityType } from '../../enums/entity.enum';
@ -26,7 +27,6 @@ import {
} from '../../generated/entity/data/table';
import { User } from '../../generated/entity/teams/user';
import { LabelType, State } from '../../generated/type/tagLabel';
import { useAuth } from '../../hooks/authHooks';
import {
getCurrentUserId,
getPartialNameFromFQN,
@ -118,7 +118,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
qualityTestFormHandler,
selectedColumn,
}: DatasetDetailsProps) => {
const { isAuthDisabled } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [isEdit, setIsEdit] = useState(false);
const [followersCount, setFollowersCount] = useState(0);
const [isFollowing, setIsFollowing] = useState(false);

View File

@ -27,6 +27,18 @@ import { DatasetTestModeType } from '../../interface/dataQuality.interface';
import DatasetDetails from './DatasetDetails.component';
import { DatasetOwner } from './DatasetDetails.interface';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockUserTeam = [
{
description: 'description',

View File

@ -36,6 +36,7 @@ import ReactFlow, {
ReactFlowProvider,
removeElements,
} from 'react-flow-renderer';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { getTableDetails } from '../../axiosAPIs/tableAPI';
import { Column } from '../../generated/entity/data/table';
import { Operation } from '../../generated/entity/policies/accessControl/rule';
@ -91,7 +92,8 @@ const Entitylineage: FunctionComponent<EntityLineageProp> = ({
entityLineageHandler,
}: EntityLineageProp) => {
const showToast = useToastContext();
const { userPermissions, isAuthDisabled, isAdminUser } = useAuth();
const { userPermissions, isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const reactFlowWrapper = useRef<HTMLDivElement>(null);
const [lineageData, setLineageData] = useState<EntityLineage>(entityLineage);
const [reactFlowInstance, setReactFlowInstance] = useState<OnLoadParams>();

View File

@ -203,6 +203,7 @@ const EntityTable = ({
.map((tag) => ({
labelType: LabelType.Manual,
state: State.Confirmed,
source: allTags.includes(tag) ? 'Tag' : 'Glossary',
tagFQN: tag,
}));
const updatedTags = [...(prevTags as TagLabel[]), ...newTags];

View File

@ -24,6 +24,18 @@ jest.mock('react-router-dom', () => ({
.mockImplementation(() => ({ search: '', pathname: '/explore' })),
}));
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../../utils/FilterUtils', () => ({
getFilterString: jest.fn().mockImplementation(() => 'user.address'),
getFilterCount: jest.fn().mockImplementation(() => 10),

View File

@ -2,6 +2,7 @@ import classNames from 'classnames';
import { isNil } from 'lodash';
import React, { FunctionComponent } from 'react';
import { useHistory } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { ROUTES, TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
import { useAuth } from '../../hooks/authHooks';
import { Button } from '../buttons/Button/Button';
@ -16,7 +17,8 @@ const Glossary: FunctionComponent<GlossaryProps> = ({
paging,
onPageChange,
}: GlossaryProps) => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const onAddGlossary = () => {

View File

@ -17,6 +17,7 @@ import { GlossaryTermAssets, LoadingState } from 'Models';
import RcTree from 'rc-tree';
import { DataNode, EventDataNode } from 'rc-tree/lib/interface';
import React, { useEffect, useRef, useState } from 'react';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
import { Glossary } from '../../generated/entity/data/glossary';
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
@ -96,7 +97,8 @@ const GlossaryV1 = ({
onAssetPaginate,
}: // handlePathChange,
Props) => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const treeRef = useRef<RcTree<DataNode>>(null);
const [treeData, setTreeData] = useState<DataNode[]>([]);
const [breadcrumb, setBreadcrumb] = useState<

View File

@ -15,6 +15,7 @@ import classNames from 'classnames';
import cronstrue from 'cronstrue';
import { capitalize, isNil, lowerCase } from 'lodash';
import React, { Fragment, useCallback, useState } from 'react';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
import {
AirflowPipeline,
@ -48,7 +49,8 @@ const Ingestion: React.FC<Props> = ({
paging,
pagingHandler,
}: Props) => {
const { isAdminUser, isAuthDisabled } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const showToast = useToastContext();
const [searchText, setSearchText] = useState('');
const [currTriggerId, setCurrTriggerId] = useState({ id: '', state: '' });

View File

@ -24,6 +24,18 @@ import { AirflowPipeline } from '../../generated/operations/pipelines/airflowPip
import Ingestion from './Ingestion.component';
import { mockIngestionWorkFlow } from './Ingestion.mock';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockPaging = {
after: 'after',
before: 'befor',

View File

@ -18,6 +18,7 @@ import { observer } from 'mobx-react';
import { TableDetail } from 'Models';
import React, { FunctionComponent, useEffect, useState } from 'react';
import appState from '../../AppState';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { getCategory } from '../../axiosAPIs/tagAPI';
import { Operation } from '../../generated/entity/policies/accessControl/rule';
import { useAuth } from '../../hooks/authHooks';
@ -48,7 +49,8 @@ const ManageTab: FunctionComponent<Props> = ({
onSave,
hasEditAccess,
}: Props) => {
const { userPermissions, isAuthDisabled } = useAuth();
const { userPermissions } = useAuth();
const { isAuthDisabled } = useAuthContext();
const getOwnerList = () => {
const user = !isEmpty(appState.userDetails)
? appState.userDetails

View File

@ -21,6 +21,18 @@ import {
import React from 'react';
import ManageTab from './ManageTab.component';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockTierData = {
children: [
{

View File

@ -16,6 +16,18 @@ import React from 'react';
import { MemoryRouter } from 'react-router';
import MyAssetStats from './MyAssetStats.component';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
describe('Test MyDataHeader Component', () => {
it('Component should render', () => {
const { container } = render(

View File

@ -27,6 +27,18 @@ import { User } from '../../generated/entity/teams/user';
import { formatDataResponse } from '../../utils/APIUtils';
import MyDataPage from './MyData.component';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockData = {
data: {
took: 50,

View File

@ -17,13 +17,13 @@ import { isNil } from 'lodash';
import { EntityFieldThreads, EntityTags } from 'Models';
import React, { Fragment, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { getTeamDetailsPath } from '../../constants/constants';
import { EntityType } from '../../enums/entity.enum';
import { Pipeline, Task } from '../../generated/entity/data/pipeline';
import { Operation } from '../../generated/entity/policies/accessControl/rule';
import { EntityReference, User } from '../../generated/entity/teams/user';
import { LabelType, State } from '../../generated/type/tagLabel';
import { useAuth } from '../../hooks/authHooks';
import {
getCurrentUserId,
getHtmlForNonAdminAction,
@ -93,7 +93,7 @@ const PipelineDetails = ({
createThread,
pipelineFQN,
}: PipeLineDetailsProp) => {
const { isAuthDisabled } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [isEdit, setIsEdit] = useState(false);
const [followersCount, setFollowersCount] = useState(0);
const [isFollowing, setIsFollowing] = useState(false);
@ -247,22 +247,9 @@ const PipelineDetails = ({
}
};
const onTagUpdate = (selectedTags?: Array<string>) => {
const onTagUpdate = (selectedTags?: Array<EntityTags>) => {
if (selectedTags) {
const prevTags =
pipelineDetails?.tags?.filter((tag) =>
selectedTags.includes(tag?.tagFQN as string)
) || [];
const newTags = selectedTags
.filter((tag) => {
return !prevTags?.map((prevTag) => prevTag.tagFQN).includes(tag);
})
.map((tag) => ({
labelType: LabelType.Manual,
state: State.Confirmed,
tagFQN: tag,
}));
const updatedTags = [...prevTags, ...newTags];
const updatedTags = [...(tier ? [tier] : []), ...selectedTags];
const updatedPipeline = { ...pipelineDetails, tags: updatedTags };
tagUpdateHandler(updatedPipeline);
}

View File

@ -14,6 +14,7 @@
import classNames from 'classnames';
import React, { FC, Fragment } from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
import { excludedMetrics } from '../../constants/profiler.constant';
import { Table, TableProfile } from '../../generated/entity/data/table';
@ -68,7 +69,8 @@ const TableProfiler: FC<Props> = ({
columns,
qualityTestFormHandler,
}) => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const modifiedData = tableProfiles?.map((tableProfile: TableProfile) => ({
rows: tableProfile.rowCount,
profileDate: tableProfile.profileDate,

View File

@ -13,12 +13,12 @@
import { EntityTags } from 'Models';
import React, { useEffect, useState } from 'react';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { getTeamDetailsPath } from '../../constants/constants';
import { EntityType } from '../../enums/entity.enum';
import { Topic } from '../../generated/entity/data/topic';
import { EntityReference, User } from '../../generated/entity/teams/user';
import { LabelType, State } from '../../generated/type/tagLabel';
import { useAuth } from '../../hooks/authHooks';
import { getCurrentUserId, getUserTeams } from '../../utils/CommonUtils';
import { getEntityFeedLink } from '../../utils/EntityUtils';
import { getDefaultValue } from '../../utils/FeedElementUtils';
@ -71,7 +71,7 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
createThread,
topicFQN,
}: TopicDetailsProps) => {
const { isAuthDisabled } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [isEdit, setIsEdit] = useState(false);
const [followersCount, setFollowersCount] = useState(0);
const [isFollowing, setIsFollowing] = useState(false);
@ -274,22 +274,9 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
);
};
const onTagUpdate = (selectedTags?: Array<string>) => {
const onTagUpdate = (selectedTags?: Array<EntityTags>) => {
if (selectedTags) {
const prevTags =
topicDetails?.tags?.filter((tag) =>
selectedTags.includes(tag?.tagFQN as string)
) || [];
const newTags = selectedTags
.filter((tag) => {
return !prevTags?.map((prevTag) => prevTag.tagFQN).includes(tag);
})
.map((tag) => ({
labelType: LabelType.Manual,
state: State.Confirmed,
tagFQN: tag,
}));
const updatedTags = [...prevTags, ...newTags];
const updatedTags = [...(tier ? [tier] : []), ...selectedTags];
const updatedTopic = { ...topicDetails, tags: updatedTags };
tagUpdateHandler(updatedTopic);
}

View File

@ -12,12 +12,14 @@
*/
import { Paging } from 'Models';
import { Webhook } from '../../generated/entity/events/webhook';
import { Status, Webhook } from '../../generated/entity/events/webhook';
export interface WebhooksProps {
data: Array<Webhook>;
paging: Paging;
selectedStatus: Status[];
onAddWebhook: () => void;
onClickWebhook: (name: string) => void;
onPageChange: (type: string) => void;
onStatusFilter: (status: Status[]) => void;
}

View File

@ -12,10 +12,10 @@
*/
import classNames from 'classnames';
import { isNil, startCase } from 'lodash';
import React, { FunctionComponent } from 'react';
import { cloneDeep, isNil, startCase } from 'lodash';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
import { Status } from '../../generated/entity/events/webhook';
import { Status, Webhook } from '../../generated/entity/events/webhook';
import { useAuth } from '../../hooks/authHooks';
import { getDocButton } from '../../utils/CommonUtils';
import { Button } from '../buttons/Button/Button';
@ -52,11 +52,34 @@ const statuses = [
const Webhooks: FunctionComponent<WebhooksProps> = ({
data = [],
paging,
selectedStatus = [],
onAddWebhook,
onClickWebhook,
onPageChange,
onStatusFilter,
}: WebhooksProps) => {
const { isAuthDisabled, isAdminUser } = useAuth();
const [filteredData, setFilteredData] = useState<Array<Webhook>>(data);
const getFilteredWebhooks = () => {
return selectedStatus.length
? data.filter(
(item) => item.status && selectedStatus.includes(item.status)
)
: data;
};
const handleStatusSelection = (status: Status) => {
const arrStatus = cloneDeep(selectedStatus);
if (arrStatus.includes(status)) {
const index = arrStatus.indexOf(status);
arrStatus.splice(index, 1);
} else {
arrStatus.push(status);
}
onStatusFilter(arrStatus);
};
const fetchLeftPanel = () => {
return (
@ -78,9 +101,13 @@ const Webhooks: FunctionComponent<WebhooksProps> = ({
key={index}>
<div className="tw-flex">
<input
checked={selectedStatus.includes(statusType.value)}
className="tw-mr-1 custom-checkbox"
data-testid="checkbox"
type="checkbox"
onChange={() => {
handleStatusSelection(statusType.value);
}}
/>
<div
className="tw-flex tw-items-center filters-title tw-truncate custom-checkbox-label"
@ -99,53 +126,20 @@ const Webhooks: FunctionComponent<WebhooksProps> = ({
return (
<>
<div className="tw-mb-5 tw-mt-11">
Webhook allow external services to be notified when certain events
happen. When the special event happen, well send a POST request to
each of the URLs you provide. Learn more in our Webhooks Guide .
The webhook allows external services to be notified of the metadata
change events happening in your organization through APIs. Register
callback URLs with webhook integration to receive metadata event
notifications. You can add, list, update, and delete webhooks.
</div>
{getDocButton('Webhooks Guide', '', 'webhook-doc')}
</>
);
};
return data.length ? (
<PageLayout leftPanel={fetchLeftPanel()} rightPanel={fetchRightPanel()}>
<div className="">
<div className="tw-flex tw-justify-end tw-items-center">
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
<Button
className={classNames('tw-h-8 tw-rounded tw-mb-3', {
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
})}
data-testid="add-webhook-button"
size="small"
theme="primary"
variant="contained"
onClick={onAddWebhook}>
Add Webhook
</Button>
</NonAdminAction>
</div>
{data.map((webhook, index) => (
<div className="tw-mb-3" key={index}>
<WebhookDataCard
description={webhook.description}
endpoint={webhook.endpoint}
name={webhook.name}
status={webhook.status}
onClick={onClickWebhook}
/>
</div>
))}
{Boolean(!isNil(paging.after) || !isNil(paging.before)) && (
<NextPrevious paging={paging} pagingHandler={onPageChange} />
)}
</div>
</PageLayout>
) : (
<PageLayout>
const fetchErrorPlaceHolder = (message: string) => {
return (
<ErrorPlaceHolder>
<p className="tw-text-center">No webhooks found</p>
<p className="tw-text-center">{message}</p>
<p className="tw-text-center">
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
<Button
@ -157,12 +151,62 @@ const Webhooks: FunctionComponent<WebhooksProps> = ({
theme="primary"
variant="contained"
onClick={onAddWebhook}>
Add New Webhook
Add Webhook
</Button>
</NonAdminAction>
</p>
</ErrorPlaceHolder>
);
};
useEffect(() => {
setFilteredData(getFilteredWebhooks());
}, [data, selectedStatus]);
return data.length ? (
<PageLayout leftPanel={fetchLeftPanel()} rightPanel={fetchRightPanel()}>
<div>
{filteredData.length ? (
<>
<div className="tw-flex tw-justify-end tw-items-center">
<NonAdminAction
position="bottom"
title={TITLE_FOR_NON_ADMIN_ACTION}>
<Button
className={classNames('tw-h-8 tw-rounded tw-mb-3', {
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
})}
data-testid="add-webhook-button"
size="small"
theme="primary"
variant="contained"
onClick={onAddWebhook}>
Add Webhook
</Button>
</NonAdminAction>
</div>
{filteredData.map((webhook, index) => (
<div className="tw-mb-3" key={index}>
<WebhookDataCard
description={webhook.description}
endpoint={webhook.endpoint}
name={webhook.name}
status={webhook.status}
onClick={onClickWebhook}
/>
</div>
))}
{Boolean(!isNil(paging.after) || !isNil(paging.before)) && (
<NextPrevious paging={paging} pagingHandler={onPageChange} />
)}
</>
) : (
fetchErrorPlaceHolder('No webhooks found for applied filters')
)}
</div>
</PageLayout>
) : (
<PageLayout>{fetchErrorPlaceHolder('No webhooks found')}</PageLayout>
);
};

View File

@ -18,7 +18,7 @@ import React, { Fragment, useEffect, useState } from 'react';
import { FOLLOWERS_VIEW_CAP, LIST_SIZE } from '../../../constants/constants';
import { Operation } from '../../../generated/entity/policies/accessControl/rule';
import { User } from '../../../generated/entity/teams/user';
import { TagLabel } from '../../../generated/type/tagLabel';
import { LabelType, State, TagLabel } from '../../../generated/type/tagLabel';
import { getHtmlForNonAdminAction } from '../../../utils/CommonUtils';
import { getEntityFeedLink, getInfoElements } from '../../../utils/EntityUtils';
import SVGIcons, { Icons } from '../../../utils/SvgUtils';
@ -53,7 +53,7 @@ type Props = {
entityFieldThreads?: EntityFieldThreads[];
onThreadLinkSelect?: (value: string) => void;
followHandler?: () => void;
tagsHandler?: (selectedTags?: Array<string>) => void;
tagsHandler?: (selectedTags?: Array<EntityTags>) => void;
versionHandler?: () => void;
};
@ -85,13 +85,34 @@ const EntityPageInfo = ({
const [entityFollowers, setEntityFollowers] =
useState<Array<User>>(followersList);
const [isViewMore, setIsViewMore] = useState<boolean>(false);
const handleTagSelection = (selectedTags?: Array<EntityTags>) => {
tagsHandler?.(selectedTags?.map((tag) => tag.tagFQN));
setIsEditable(false);
};
const [tagList, setTagList] = useState<Array<string>>([]);
const [isTagLoading, setIsTagLoading] = useState<boolean>(false);
const handleTagSelection = (selectedTags?: Array<EntityTags>) => {
if (selectedTags) {
const prevTags =
tags?.filter((tag) =>
selectedTags
.map((selTag) => selTag.tagFQN)
.includes(tag?.tagFQN as string)
) || [];
const newTags = selectedTags
.filter((tag) => {
return !prevTags
?.map((prevTag) => prevTag.tagFQN)
.includes(tag.tagFQN);
})
.map((tag) => ({
labelType: LabelType.Manual,
state: State.Confirmed,
source: tagList.includes(tag.tagFQN) ? 'Tag' : 'Glossary',
tagFQN: tag.tagFQN,
}));
tagsHandler?.([...prevTags, ...newTags]);
}
setIsEditable(false);
};
const getSelectedTags = () => {
return tier?.tagFQN
? [

View File

@ -15,7 +15,7 @@ import { uniqueId } from 'lodash';
import { observer } from 'mobx-react';
import React from 'react';
import AppState from '../../../AppState';
import { useAuth } from '../../../hooks/authHooks';
import { useAuthContext } from '../../../auth-provider/AuthProvider';
type Props = {
type: 'error' | 'noData';
@ -54,7 +54,7 @@ const stepsData = [
];
const ErrorPlaceHolderES = ({ type, errorMessage, query = '' }: Props) => {
const { isAuthDisabled } = useAuth();
const { isAuthDisabled } = useAuthContext();
const getUserDisplayName = () => {
return isAuthDisabled
? AppState.users?.length > 0

View File

@ -27,6 +27,18 @@ jest.mock('../../../hooks/authHooks', () => ({
useAuth: jest.fn(() => mockAuth),
}));
jest.mock('../../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../popover/PopOver', () => {
return jest
.fn()

View File

@ -13,6 +13,7 @@
import { UserPermissions } from 'Models';
import React from 'react';
import { useAuthContext } from '../../../auth-provider/AuthProvider';
import { Operation } from '../../../generated/entity/policies/accessControl/rule';
import { useAuth } from '../../../hooks/authHooks';
import PopOver from '../popover/PopOver';
@ -38,7 +39,8 @@ const NonAdminAction = ({
trigger = 'mouseenter',
permission,
}: Props) => {
const { isAuthDisabled, isAdminUser, userPermissions } = useAuth();
const { isAdminUser, userPermissions } = useAuth();
const { isAuthDisabled } = useAuthContext();
const handleCapturedEvent = (
e: React.KeyboardEvent | React.MouseEvent

View File

@ -40,6 +40,7 @@ const WebhookDataCardBody: FunctionComponent<Props> = ({
<span className="tw-ml-1">{startCase(status)}</span>
</span>
<span className="tw-mx-1.5 tw-inline-block tw-text-gray-400">|</span>
<span className="tw-text-grey-muted">Url:&nbsp;</span>
<span>{endpoint}</span>
</div>
<div className="description-text" data-testid="description-text">

View File

@ -14,12 +14,14 @@
import classNames from 'classnames';
import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { useAuth } from '../../hooks/authHooks';
import SVGIcons from '../../utils/SvgUtils';
import { DropDownListItem, DropDownListProp } from './types';
const AnchorDropDownList = ({ dropDownList, setIsOpen }: DropDownListProp) => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
return (
<>

View File

@ -12,6 +12,7 @@
*/
import React, { Fragment } from 'react';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { useAuth } from '../../hooks/authHooks';
import { DropDownListItem, DropDownListProp } from './types';
@ -22,7 +23,8 @@ const CheckBoxDropDownList = ({
selectedItems,
disabledItems,
}: DropDownListProp) => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
return (
<>

View File

@ -21,6 +21,18 @@ import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import DropDown from './DropDown';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockDropDown = [
{ name: 'Test1', to: '/test1', disabled: false },
{ name: 'Test2', to: '/test2', disabled: false },

View File

@ -83,7 +83,7 @@ const DropDownList: FunctionComponent<DropDownListProp> = ({
key={index}
role="menuitem"
onClick={(e) => !item.disabled && onSelect?.(e, item.value)}>
<p className="tw-truncate tw-w-52" title={item.name as string}>
<p className="tw-truncate tw-w-80" title={item.name as string}>
{item.name}
</p>
</div>

View File

@ -24,6 +24,18 @@ import {
} from '../../generated/entity/data/table';
import SchemaTable from './SchemaTable';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../common/rich-text-editor/RichTextEditorPreviewer', () => {
return jest.fn().mockReturnValue(<p>RichTextEditorPreviewer</p>);
});

View File

@ -135,7 +135,7 @@ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
})
.map((glossary) => {
return {
name: glossary.name,
name: glossary.fqdn,
value: glossary.fqdn,
};
});

View File

@ -2,6 +2,7 @@ import { AxiosError } from 'axios';
import { LoadingState } from 'Models';
import React, { FunctionComponent, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { addGlossaries } from '../../axiosAPIs/glossaryAPI';
import AddGlossary from '../../components/AddGlossary/AddGlossary.component';
import PageContainerV1 from '../../components/containers/PageContainerV1';
@ -12,7 +13,8 @@ import useToastContext from '../../hooks/useToastContext';
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
const AddGlossaryPage: FunctionComponent = () => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const showToast = useToastContext();
const [tagList, setTagList] = useState<Array<string>>([]);

View File

@ -15,6 +15,7 @@ import { AxiosError } from 'axios';
import { LoadingState } from 'Models';
import React, { FunctionComponent, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { addWebhook } from '../../axiosAPIs/webhookAPI';
import AddWebhook from '../../components/AddWebhook/AddWebhook';
import PageContainerV1 from '../../components/containers/PageContainerV1';
@ -25,7 +26,8 @@ import { useAuth } from '../../hooks/authHooks';
import useToastContext from '../../hooks/useToastContext';
const AddWebhookPage: FunctionComponent = () => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const showToast = useToastContext();
const [status, setStatus] = useState<LoadingState>('initial');
@ -51,7 +53,7 @@ const AddWebhookPage: FunctionComponent = () => {
.catch((err: AxiosError) => {
showToast({
variant: 'error',
body: err.message || 'Something went wrong!',
body: err.response?.data?.message || 'Something went wrong!',
});
setStatus('initial');
});

View File

@ -11,6 +11,18 @@ jest.mock('../../components/containers/PageContainerV1', () => {
));
});
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../../components/AddWebhook/AddWebhook', () => {
return jest.fn().mockImplementation(() => <div>AddWebhookComponent</div>);
});

View File

@ -159,7 +159,7 @@ const DashboardDetailsPage = () => {
const saveUpdatedDashboardData = (
updatedData: Dashboard
): Promise<AxiosResponse> => {
const jsonPatch = compare(DashboardDetails, updatedData);
const jsonPatch = compare(dashboardDetails, updatedData);
return patchDashboardDetails(
dashboardId,

View File

@ -15,6 +15,7 @@ import { AxiosError } from 'axios';
import { LoadingState } from 'Models';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
deleteWebhook,
getWebhookByName,
@ -32,7 +33,8 @@ import useToastContext from '../../hooks/useToastContext';
const EditWebhookPage: FunctionComponent = () => {
const { webhookName } = useParams<{ [key: string]: string }>();
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const showToast = useToastContext();
const [isLoading, setIsLoading] = useState<boolean>(true);
@ -49,7 +51,7 @@ const EditWebhookPage: FunctionComponent = () => {
.catch((err: AxiosError) => {
showToast({
variant: 'error',
body: err.message || 'Something went wrong!',
body: err.response?.data?.message || 'Something went wrong!',
});
})
.finally(() => setIsLoading(false));
@ -77,7 +79,7 @@ const EditWebhookPage: FunctionComponent = () => {
.catch((err: AxiosError) => {
showToast({
variant: 'error',
body: err.message || 'Something went wrong!',
body: err.response?.data?.message || 'Something went wrong!',
});
setStatus('initial');
});
@ -93,7 +95,7 @@ const EditWebhookPage: FunctionComponent = () => {
.catch((err: AxiosError) => {
showToast({
variant: 'error',
body: err.message || 'Something went wrong!',
body: err.response?.data?.message || 'Something went wrong!',
});
setDeleteStatus('initial');
});

View File

@ -23,6 +23,7 @@ import {
} from 'Models';
import React, { useCallback, useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
deleteGlossary,
deleteGlossaryTerm,
@ -37,7 +38,6 @@ import { getSuggestions, searchData } from '../../axiosAPIs/miscAPI';
import PageContainerV1 from '../../components/containers/PageContainerV1';
import GlossaryV1 from '../../components/Glossary/GlossaryV1.component';
import Loader from '../../components/Loader/Loader';
import { WILD_CARD_CHAR } from '../../constants/char.constants';
import {
getAddGlossaryTermsPath,
PAGE_SIZE,
@ -63,7 +63,8 @@ const GlossaryPageV1 = () => {
// const { glossaryName, glossaryTermsFQN } =
// useParams<{ [key: string]: string }>();
const { isAdminUser, isAuthDisabled } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const showToast = useToastContext();
const [isLoading, setIsLoading] = useState<boolean>(true);
@ -394,12 +395,13 @@ const GlossaryPageV1 = () => {
};
const fetchGlossaryTermAssets = (data: GlossaryTerm, forceReset = false) => {
if (data?.fullyQualifiedName) {
if (data?.fullyQualifiedName || data?.name) {
const tagName = data?.fullyQualifiedName || data?.name; // Incase fqn is not fetched yet.
searchData(
WILD_CARD_CHAR,
'',
forceReset ? 1 : assetData.currPage,
PAGE_SIZE,
`(tags:${data.fullyQualifiedName})`,
`(tags:${tagName})`,
'',
'',
myDataSearchIndex

View File

@ -17,6 +17,7 @@ import { isEmpty } from 'lodash';
import { Key } from 'rc-tree/lib/interface';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
getGlossariesByName,
getGlossaryTermByFQN,
@ -36,7 +37,8 @@ import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
const GlossaryTermPage: FunctionComponent = () => {
const showToast = useToastContext();
const { isAdminUser, isAuthDisabled } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const { glossaryName, glossaryTermsFQN } =
useParams<{ [key: string]: string }>();
const [isLoading, setIsLoading] = useState(true);

View File

@ -6,6 +6,18 @@ jest.mock('../../components/GlossaryTerms/GlossaryTerms.component', () => {
return jest.fn().mockReturnValue(<div>GlossaryTerms.component</div>);
});
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../../axiosAPIs/glossaryAPI', () => ({
getGlossariesByName: jest.fn().mockImplementation(() => Promise.resolve()),
getGlossaryTermsById: jest.fn().mockImplementation(() => Promise.resolve()),

View File

@ -19,6 +19,7 @@ import { observer } from 'mobx-react';
import { FormErrorData } from 'Models';
import React, { Fragment, useEffect, useState } from 'react';
import AppState from '../../AppState';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
createRole,
getPolicy,
@ -66,7 +67,8 @@ const getActiveTabClass = (tab: number, currentTab: number) => {
const RolesPage = () => {
const showToast = useToastContext();
const [roles, setRoles] = useState<Array<Role>>([]);
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [currentRole, setCurrentRole] = useState<Role>();
const [currentPolicy, setCurrentPolicy] = useState<Policy>();
const [error, setError] = useState<string>('');

View File

@ -32,6 +32,18 @@ jest.mock('../../axiosAPIs/rolesAPI', () => ({
updateRole: jest.fn(),
}));
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock(
'../../components/containers/PageLayout',
() =>

View File

@ -24,7 +24,7 @@ import {
pagingObject,
ROUTES,
} from '../../constants/constants';
import { Webhook } from '../../generated/entity/events/webhook';
import { Status, Webhook } from '../../generated/entity/events/webhook';
import useToastContext from '../../hooks/useToastContext';
const WebhooksPage: FunctionComponent = () => {
@ -33,6 +33,7 @@ const WebhooksPage: FunctionComponent = () => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [paging, setPaging] = useState<Paging>(pagingObject);
const [data, setData] = useState<Array<Webhook>>([]);
const [selectedStatus, setSelectedStatus] = useState<Status[]>([]);
const fetchData = (paging?: string) => {
setIsLoading(true);
@ -64,6 +65,10 @@ const WebhooksPage: FunctionComponent = () => {
fetchData(pagingString);
};
const handleStatusFilter = (status: Status[]) => {
setSelectedStatus(status);
};
const handleAddWebhook = () => {
history.push(ROUTES.ADD_WEBHOOK);
};
@ -82,9 +87,11 @@ const WebhooksPage: FunctionComponent = () => {
<Webhooks
data={data}
paging={paging}
selectedStatus={selectedStatus}
onAddWebhook={handleAddWebhook}
onClickWebhook={handleClickWebhook}
onPageChange={handlePageChange}
onStatusFilter={handleStatusFilter}
/>
) : (
<Loader />

View File

@ -79,6 +79,18 @@ const mockTableData = {
paging: { after: 'ZMbpLOqQQsREk_7DmEOr', total: 12 },
};
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock(
'../../components/common/rich-text-editor/RichTextEditorPreviewer',
() => {

View File

@ -23,6 +23,18 @@ import { MemoryRouter } from 'react-router-dom';
import { act } from 'react-test-renderer';
import ServicePage from './index';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockData = {
description: '',
href: 'link',

View File

@ -25,6 +25,7 @@ import {
import React, { Fragment, FunctionComponent, useEffect, useState } from 'react';
import { Link, useHistory, useParams } from 'react-router-dom';
import AppState from '../../AppState';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
addAirflowPipeline,
deleteAirflowPipelineById,
@ -113,7 +114,8 @@ const ServicePage: FunctionComponent = () => {
const { serviceFQN, serviceType, serviceCategory, tab } =
useParams() as Record<string, string>;
const history = useHistory();
const { isAdminUser, isAuthDisabled } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [serviceName, setServiceName] = useState(
serviceCategory || getServiceCategoryFromType(serviceType)
);

View File

@ -136,6 +136,18 @@ const mockPipelineService = {
},
};
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../../axiosAPIs/serviceAPI', () => ({
deleteService: jest.fn(),
getServiceDetails: jest

View File

@ -17,6 +17,7 @@ import { isNil } from 'lodash';
import { Paging, ServiceCollection, ServiceData, ServiceTypes } from 'Models';
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import { addAirflowPipeline } from '../../axiosAPIs/airflowPipelineAPI';
import {
deleteService,
@ -94,7 +95,8 @@ export type ApiData = {
const ServicesPage = () => {
const showToast = useToastContext();
const { isAdminUser, isAuthDisabled } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [isModalOpen, setIsModalOpen] = useState(false);
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);
const [deleteSelection, setDeleteSelection] = useState({

View File

@ -21,6 +21,18 @@ import {
import React, { ReactNode } from 'react';
import TagsPage from '.';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockTagsCategory = [
{
categoryType: 'Classification',

View File

@ -17,6 +17,7 @@ import { isUndefined, toLower } from 'lodash';
import { EntityTags, FormErrorData } from 'Models';
import React, { useCallback, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
createTag,
createTagCategory,
@ -56,7 +57,8 @@ import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
import Form from './Form';
// import { Tag, TagsCategory } from './tagsTypes';
const TagsPage = () => {
const { isAuthDisabled, isAdminUser } = useAuth();
const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [categories, setCategoreis] = useState<Array<TagCategory>>([]);
const [currentCategory, setCurrentCategory] = useState<TagCategory>();
const [isEditCategory, setIsEditCategory] = useState<boolean>(false);

View File

@ -24,6 +24,18 @@ const mockItem = {
const mockRemove = jest.fn();
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
jest.mock('../../components/common/avatar/Avatar', () => {
return jest.fn().mockReturnValue(<p data-testid="avatar">Avatar</p>);
});

View File

@ -15,6 +15,7 @@ import classNames from 'classnames';
import { capitalize } from 'lodash';
import React from 'react';
import { Link } from 'react-router-dom';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import Avatar from '../../components/common/avatar/Avatar';
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
import { SearchIndex } from '../../enums/search.enum';
@ -49,7 +50,8 @@ const UserCard = ({
onSelect,
onRemove,
}: Props) => {
const { isAuthDisabled, isAdminUser, userPermissions } = useAuth();
const { isAdminUser, userPermissions } = useAuth();
const { isAuthDisabled } = useAuthContext();
const getArrForPartialName = (
type: string
): Array<'service' | 'database' | 'table' | 'column'> => {

View File

@ -20,6 +20,18 @@ import {
import React, { ReactNode } from 'react';
import TeamsPage from './index';
jest.mock('../../auth-provider/AuthProvider', () => {
return {
useAuthContext: jest.fn(() => ({
isAuthDisabled: false,
isAuthenticated: true,
isProtectedRoute: jest.fn().mockReturnValue(true),
isTourRoute: jest.fn().mockReturnValue(false),
onLogoutHandler: jest.fn(),
})),
};
});
const mockTeamsData = [
{
description: '',

View File

@ -20,6 +20,7 @@ import { FormErrorData } from 'Models';
import React, { useEffect, useState } from 'react';
import { Link, useHistory, useParams } from 'react-router-dom';
import AppState from '../../AppState';
import { useAuthContext } from '../../auth-provider/AuthProvider';
import {
createTeam,
getTeamByName,
@ -57,7 +58,8 @@ import UserCard from './UserCard';
const TeamsPage = () => {
const { team } = useParams() as Record<string, string>;
const history = useHistory();
const { isAuthDisabled, isAdminUser, userPermissions } = useAuth();
const { isAdminUser, userPermissions } = useAuth();
const { isAuthDisabled } = useAuthContext();
const [teams, setTeams] = useState<Array<Team>>([]);
const [currentTeam, setCurrentTeam] = useState<Team>();
const [error, setError] = useState<string>('');

View File

@ -389,12 +389,16 @@ export const getSvgArrow = (isActive: boolean) => {
};
export const isValidUrl = (href: string) => {
const regex = new RegExp(
// eslint-disable-next-line no-useless-escape
/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g
);
if (!href) {
return false;
}
try {
const url = new URL(href);
return href.match(regex);
return Boolean(url.href);
} catch {
return false;
}
};
export const getFields = (defaultFields: string, tabSpecificField: string) => {

View File

@ -118,13 +118,13 @@ module.exports = {
'status-queued': statusQueued,
// Ingestion statuses end
// Webhook statuses begin
notStarted: ideal,
started: success,
disabled: ideal,
active: success,
failed: error,
awaitingRetry: success,
retryLimitReached: warning,
'notStarted-lite': idealBG,
'started-lite': successBG,
'disabled-lite': idealBG,
'active-lite': successBG,
'failed-lite': errorBG,
'awaitingRetry-lite': successBG,
'retryLimitReached-lite': warningBG,