mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 12:39:01 +00:00
parent
93f0efdab1
commit
0d71d15b04
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { AxiosResponse } from 'axios';
|
|
||||||
import axiosClient from '.';
|
|
||||||
import { EventFilter, Filters } from '../generated/settings/settings';
|
|
||||||
|
|
||||||
const BASE_URL = '/settings';
|
|
||||||
|
|
||||||
export interface ActivityFeedSettings {
|
|
||||||
config_type: string;
|
|
||||||
config_value: EventFilter[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getActivityFeedEventFilters = async () => {
|
|
||||||
const response = await axiosClient.get<ActivityFeedSettings>(
|
|
||||||
`${BASE_URL}/activityFeedFilterSetting`
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data.config_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createOrUpdateActivityFeedEventFilter = async (
|
|
||||||
entityType: string,
|
|
||||||
payload: Filters[]
|
|
||||||
) => {
|
|
||||||
const configOptions = {
|
|
||||||
headers: { 'Content-type': 'application/json' },
|
|
||||||
};
|
|
||||||
const url = `${BASE_URL}/filter/${entityType}/add`;
|
|
||||||
|
|
||||||
const response = await axiosClient.put<
|
|
||||||
Filters[],
|
|
||||||
AxiosResponse<ActivityFeedSettings>
|
|
||||||
>(url, payload, configOptions);
|
|
||||||
|
|
||||||
return response.data.config_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateFilters = async (data: ActivityFeedSettings) => {
|
|
||||||
const url = `${BASE_URL}`;
|
|
||||||
|
|
||||||
const response = await axiosClient.put<
|
|
||||||
ActivityFeedSettings,
|
|
||||||
AxiosResponse<ActivityFeedSettings>
|
|
||||||
>(url, data);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const resetAllFilters = async () => {
|
|
||||||
const url = `${BASE_URL}/resetFilters`;
|
|
||||||
|
|
||||||
const response = await axiosClient.post<
|
|
||||||
null,
|
|
||||||
AxiosResponse<ActivityFeedSettings>
|
|
||||||
>(url);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getInitialFilters = async () => {
|
|
||||||
const url = `${BASE_URL}/bootstrappedFilters`;
|
|
||||||
|
|
||||||
const response = await axiosClient.get<EventFilter[]>(url);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
};
|
|
@ -17,7 +17,7 @@ import { MemoryRouter } from 'react-router-dom';
|
|||||||
import DashboardVersion from './DashboardVersion.component';
|
import DashboardVersion from './DashboardVersion.component';
|
||||||
import { DashboardVersionProp } from './DashboardVersion.interface';
|
import { DashboardVersionProp } from './DashboardVersion.interface';
|
||||||
import {
|
import {
|
||||||
dashboardVersionProp,
|
dashboardVersionProps,
|
||||||
mockNoChartData,
|
mockNoChartData,
|
||||||
mockTagChangeVersion,
|
mockTagChangeVersion,
|
||||||
} from './dashboardVersion.mock';
|
} from './dashboardVersion.mock';
|
||||||
@ -70,7 +70,7 @@ JSON.parse = jest.fn().mockReturnValue([]);
|
|||||||
describe('Test DashboardVersion page', () => {
|
describe('Test DashboardVersion page', () => {
|
||||||
it('Checks if the page has all the proper components rendered', async () => {
|
it('Checks if the page has all the proper components rendered', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<DashboardVersion {...dashboardVersionProp} />,
|
<DashboardVersion {...dashboardVersionProps} />,
|
||||||
{
|
{
|
||||||
wrapper: MemoryRouter,
|
wrapper: MemoryRouter,
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ describe('Test DashboardVersion page', () => {
|
|||||||
it('Checks if the page has all the proper components rendered, if change version is related to tags', async () => {
|
it('Checks if the page has all the proper components rendered, if change version is related to tags', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<DashboardVersion
|
<DashboardVersion
|
||||||
{...dashboardVersionProp}
|
{...dashboardVersionProps}
|
||||||
currentVersionData={
|
currentVersionData={
|
||||||
mockTagChangeVersion as DashboardVersionProp['currentVersionData']
|
mockTagChangeVersion as DashboardVersionProp['currentVersionData']
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ describe('Test DashboardVersion page', () => {
|
|||||||
it('Checks if the page has all the proper components rendered, if the dashboard deleted is undefined', async () => {
|
it('Checks if the page has all the proper components rendered, if the dashboard deleted is undefined', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<DashboardVersion
|
<DashboardVersion
|
||||||
{...dashboardVersionProp}
|
{...dashboardVersionProps}
|
||||||
currentVersionData={mockNoChartData}
|
currentVersionData={mockNoChartData}
|
||||||
deleted={undefined}
|
deleted={undefined}
|
||||||
/>,
|
/>,
|
||||||
@ -189,7 +189,7 @@ describe('Test DashboardVersion page', () => {
|
|||||||
|
|
||||||
it('If version is loading it should show loading component', async () => {
|
it('If version is loading it should show loading component', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<DashboardVersion {...dashboardVersionProp} isVersionLoading />,
|
<DashboardVersion {...dashboardVersionProps} isVersionLoading />,
|
||||||
{
|
{
|
||||||
wrapper: MemoryRouter,
|
wrapper: MemoryRouter,
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import { VersionData } from '../../pages/EntityVersionPage/EntityVersionPage.component';
|
import { VersionData } from '../../pages/EntityVersionPage/EntityVersionPage.component';
|
||||||
import { DashboardVersionProp } from './DashboardVersion.interface';
|
import { DashboardVersionProp } from './DashboardVersion.interface';
|
||||||
|
|
||||||
export const dashboardVersionProp = {
|
export const dashboardVersionProps = {
|
||||||
version: '0.3',
|
version: '0.3',
|
||||||
currentVersionData: {
|
currentVersionData: {
|
||||||
id: '4ee70a0c-6ec9-4c93-a91c-4a57d65bebc8',
|
id: '4ee70a0c-6ec9-4c93-a91c-4a57d65bebc8',
|
||||||
|
@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 {
|
|
||||||
faChevronLeft,
|
|
||||||
faChevronRight,
|
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import { ScrollHandle } from 'Models';
|
|
||||||
import React, {
|
|
||||||
HTMLAttributes,
|
|
||||||
useEffect,
|
|
||||||
useLayoutEffect,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import { Pipeline, PipelineStatus } from '../../generated/entity/data/pipeline';
|
|
||||||
import { getDateOrTimeFromSeconds } from '../../utils/TimeUtils';
|
|
||||||
|
|
||||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
||||||
executions: Pipeline['pipelineStatus'];
|
|
||||||
selectedExecution: PipelineStatus;
|
|
||||||
onSelectExecution: (e: PipelineStatus) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ExecutionStrip = ({
|
|
||||||
executions,
|
|
||||||
selectedExecution,
|
|
||||||
onSelectExecution,
|
|
||||||
}: Props) => {
|
|
||||||
const tableRef = useRef<HTMLDivElement>(null);
|
|
||||||
const [scrollOffset, setScrollOffSet] = useState<number>(0);
|
|
||||||
const [containerWidth, setContainerWidth] = useState<number>(0);
|
|
||||||
const [scrollHandle, setScrollHandle] = useState<ScrollHandle>({
|
|
||||||
left: true,
|
|
||||||
right: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const scrollHandler = (scrlOffset: number) => {
|
|
||||||
if (tableRef.current) {
|
|
||||||
tableRef.current.scrollLeft += scrlOffset;
|
|
||||||
setScrollOffSet(tableRef.current.scrollLeft);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getExecutionTooltip = (execution: PipelineStatus) => {
|
|
||||||
const executionDate = execution.timestamp as number;
|
|
||||||
const momentDate = getDateOrTimeFromSeconds(executionDate);
|
|
||||||
const momentTime = getDateOrTimeFromSeconds(executionDate, 'hh:mm a');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span>{momentDate}</span>
|
|
||||||
<br />
|
|
||||||
<span>{momentTime}</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
setContainerWidth(
|
|
||||||
(tableRef.current?.scrollWidth ?? 0) -
|
|
||||||
(tableRef.current?.clientWidth ?? 0)
|
|
||||||
);
|
|
||||||
if (tableRef.current) {
|
|
||||||
scrollHandler(tableRef.current?.scrollWidth);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const rFlag = scrollOffset !== containerWidth;
|
|
||||||
const lFlag = scrollOffset > 0;
|
|
||||||
setScrollHandle((pre) => ({ ...pre, right: rFlag, left: lFlag }));
|
|
||||||
}, [scrollOffset, containerWidth]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="tw-relative execution-timeline-wrapper"
|
|
||||||
onScrollCapture={() => {
|
|
||||||
setScrollOffSet(tableRef.current?.scrollLeft ?? 0);
|
|
||||||
}}>
|
|
||||||
{scrollHandle.left ? (
|
|
||||||
<button
|
|
||||||
className="tw-border tw-border-main tw-fixed tw-left-7 tw-bottom-14 tw-rounded-full tw-shadow-md tw-z-50 tw-bg-body-main tw-w-8 tw-h-8"
|
|
||||||
onClick={() => scrollHandler(-100)}>
|
|
||||||
<FontAwesomeIcon
|
|
||||||
className="tw-text-grey-muted"
|
|
||||||
icon={faChevronLeft}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
{scrollHandle.right ? (
|
|
||||||
<button
|
|
||||||
className="tw-border tw-border-main tw-fixed tw-right-7 tw-bottom-14 tw-rounded-full tw-shadow-md tw-z-50 tw-bg-body-main tw-w-8 tw-h-8"
|
|
||||||
onClick={() => scrollHandler(100)}>
|
|
||||||
<FontAwesomeIcon
|
|
||||||
className="tw-text-grey-muted"
|
|
||||||
icon={faChevronRight}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
<div
|
|
||||||
className="tw-w-full tw-overflow-x-auto tw-pt-20 tw-pb-3"
|
|
||||||
ref={tableRef}>
|
|
||||||
<div className="tw-flex" id="executionTimeline">
|
|
||||||
<div className="data-box-wrapper tw-mr-5">
|
|
||||||
<div className="tw-relative">
|
|
||||||
<div className="exec-date-time">
|
|
||||||
{getExecutionTooltip(executions || {})}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={classNames('data-box', executions?.executionStatus, {
|
|
||||||
selected: _.isEqual(executions, selectedExecution),
|
|
||||||
})}
|
|
||||||
onClick={() => onSelectExecution(executions || {})}>
|
|
||||||
<FontAwesomeIcon
|
|
||||||
className="tw-w-3.5 tw-h-3.5"
|
|
||||||
color={
|
|
||||||
_.isEqual(executions, selectedExecution)
|
|
||||||
? '#FFFFFF'
|
|
||||||
: 'transparent'
|
|
||||||
}
|
|
||||||
icon="check"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ExecutionStrip;
|
|
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import React, { FunctionComponent, useEffect, useState } from 'react';
|
|
||||||
import { TermReference } from '../../generated/entity/data/glossaryTerm';
|
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
|
||||||
import { Button } from '../buttons/Button/Button';
|
|
||||||
import { Field } from '../Field/Field';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
referenceList: TermReference[];
|
|
||||||
onReferenceFieldChange: (newRefList: TermReference[]) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GlossaryReferences: FunctionComponent<Props> = ({
|
|
||||||
referenceList,
|
|
||||||
onReferenceFieldChange,
|
|
||||||
}: Props) => {
|
|
||||||
const [references, setReferences] = useState<TermReference[]>(
|
|
||||||
referenceList || []
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleReferenceFieldsChange = (
|
|
||||||
i: number,
|
|
||||||
field: keyof TermReference,
|
|
||||||
value: string
|
|
||||||
) => {
|
|
||||||
const newFormValues = [...references];
|
|
||||||
newFormValues[i][field] = value;
|
|
||||||
onReferenceFieldChange(newFormValues);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addReferenceFields = () => {
|
|
||||||
onReferenceFieldChange([...references, { name: '', endpoint: '' }]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeReferenceFields = (i: number) => {
|
|
||||||
const newFormValues = [...references];
|
|
||||||
newFormValues.splice(i, 1);
|
|
||||||
onReferenceFieldChange(newFormValues);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setReferences(referenceList);
|
|
||||||
}, [referenceList]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div data-testid="references">
|
|
||||||
<div className="tw-flex tw-items-center">
|
|
||||||
<p className="w-form-label tw-m-0 tw-mr-3">References</p>
|
|
||||||
<Button
|
|
||||||
className="tw-h-5 tw-px-2"
|
|
||||||
size="x-small"
|
|
||||||
theme="primary"
|
|
||||||
variant="contained"
|
|
||||||
onClick={addReferenceFields}>
|
|
||||||
<FontAwesomeIcon icon="plus" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{references.map((value, i) => (
|
|
||||||
<div className="tw-flex tw-items-center" key={i}>
|
|
||||||
<div className="tw-grid tw-grid-cols-2 tw-gap-x-2 tw-w-11/12">
|
|
||||||
<Field>
|
|
||||||
<input
|
|
||||||
className="tw-form-inputs tw-form-inputs-padding"
|
|
||||||
id={`name-${i}`}
|
|
||||||
name="name"
|
|
||||||
placeholder="Name"
|
|
||||||
type="text"
|
|
||||||
value={value.name}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleReferenceFieldsChange(i, 'name', e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
<Field>
|
|
||||||
<input
|
|
||||||
className="tw-form-inputs tw-form-inputs-padding"
|
|
||||||
id={`url-${i}`}
|
|
||||||
name="endpoint"
|
|
||||||
placeholder="Endpoint"
|
|
||||||
type="text"
|
|
||||||
value={value.endpoint}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleReferenceFieldsChange(i, 'endpoint', e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
className="focus:tw-outline-none tw-mt-3 tw-w-1/12"
|
|
||||||
onClick={(e) => {
|
|
||||||
removeReferenceFields(i);
|
|
||||||
e.preventDefault();
|
|
||||||
}}>
|
|
||||||
<SVGIcons
|
|
||||||
alt="delete"
|
|
||||||
icon={Icons.DELETE}
|
|
||||||
title="Delete"
|
|
||||||
width="16px"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GlossaryReferences;
|
|
File diff suppressed because it is too large
Load Diff
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.slack-chat > div > div > div {
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slack-chat .chatIcon {
|
|
||||||
color: white;
|
|
||||||
position: absolute;
|
|
||||||
text-align: center;
|
|
||||||
left: 50%;
|
|
||||||
top: 53%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.slack-chat .bubble {
|
|
||||||
z-index: 10;
|
|
||||||
background-color: #7147e8;
|
|
||||||
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3);
|
|
||||||
height: 60px;
|
|
||||||
position: fixed;
|
|
||||||
right: 20px;
|
|
||||||
bottom: 20px;
|
|
||||||
width: 60px;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
scale: 0.75;
|
|
||||||
transition: scale 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slack-chat .bubble:hover {
|
|
||||||
scale: 1;
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { faMessage } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import { SlackChatConfig } from 'Models';
|
|
||||||
import React, { FC } from 'react';
|
|
||||||
import './SlackChat.css';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
slackConfig: SlackChatConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SlackChat: FC<Props> = ({ slackConfig }) => {
|
|
||||||
const url = slackConfig.slackUrl;
|
|
||||||
|
|
||||||
return url && url.length > 0 ? (
|
|
||||||
<div className="slack-chat">
|
|
||||||
<a href={url} rel="noreferrer" target="_blank">
|
|
||||||
<div className="bubble">
|
|
||||||
<div className="chatIcon">
|
|
||||||
<FontAwesomeIcon icon={faMessage} size="2x" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SlackChat;
|
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 const mockTeams = [
|
|
||||||
{
|
|
||||||
id: '8754b53f-15cd-4d9a-af52-bdb3a2abff61',
|
|
||||||
name: 'Cloud_Infra',
|
|
||||||
fullyQualifiedName: 'Cloud_Infra',
|
|
||||||
displayName: 'Cloud_Infra',
|
|
||||||
description: 'This is Cloud_Infra description.',
|
|
||||||
version: 0.3,
|
|
||||||
updatedAt: 1653388025589,
|
|
||||||
updatedBy: 'anonymous',
|
|
||||||
href: 'http://localhost:8585/api/v1/teams/8754b53f-15cd-4d9a-af52-bdb3a2abff61',
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '8754b53f-15cd-4d9a-af52-bdb3a2abffss',
|
|
||||||
name: 'Customer_Support',
|
|
||||||
fullyQualifiedName: 'Customer_Support',
|
|
||||||
displayName: 'Customer_Support',
|
|
||||||
description: 'This is Customer_Support description.',
|
|
||||||
version: 0.3,
|
|
||||||
updatedAt: 1653388025589,
|
|
||||||
updatedBy: 'anonymous',
|
|
||||||
href: 'test',
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const MOCK_USER = [
|
|
||||||
{
|
|
||||||
id: '011bdb24-90a7-4a97-ba66-24002adb2b12',
|
|
||||||
type: 'user',
|
|
||||||
name: 'aaron_johnson0',
|
|
||||||
fullyQualifiedName: 'aaron_johnson0',
|
|
||||||
displayName: 'Aaron Johnson',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/users/011bdb24-90a7-4a97-ba66-24002adb2b12',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2a31e452-2061-4517-af35-0ace16161cde',
|
|
||||||
type: 'user',
|
|
||||||
name: 'aaron_singh2',
|
|
||||||
fullyQualifiedName: 'aaron_singh2',
|
|
||||||
displayName: 'Aaron Singh',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/users/2a31e452-2061-4517-af35-0ace16161cde',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const MOCK_CURRENT_TEAM_1 = {
|
|
||||||
id: '0ccba9c2-bb41-4e8d-9add-7af8bdd8d6b8',
|
|
||||||
name: 'Cloud_Infra',
|
|
||||||
fullyQualifiedName: 'Cloud_Infra',
|
|
||||||
displayName: 'Cloud_Infra',
|
|
||||||
description: 'This is Cloud_Infra description.',
|
|
||||||
version: 0.3,
|
|
||||||
updatedAt: 1653410822537,
|
|
||||||
updatedBy: 'anonymous',
|
|
||||||
href: 'http://localhost:8585/api/v1/teams/0ccba9c2-bb41-4e8d-9add-7af8bdd8d6b8',
|
|
||||||
isJoinable: true,
|
|
||||||
changeDescription: {
|
|
||||||
fieldsAdded: [
|
|
||||||
{
|
|
||||||
name: 'owner',
|
|
||||||
newValue:
|
|
||||||
'{"id":"9fcf9550-1571-4f79-8016-ba81a8c4a2f4","type":"user","name":"aaron_johnson0","fullyQualifiedName":"aaron_johnson0","displayName":"Aaron Johnson","deleted":false}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
fieldsUpdated: [],
|
|
||||||
fieldsDeleted: [],
|
|
||||||
previousVersion: 0.2,
|
|
||||||
},
|
|
||||||
deleted: false,
|
|
||||||
defaultRoles: [
|
|
||||||
{
|
|
||||||
id: 'fb41f804-e266-4a8e-8f3a-022c72c70033',
|
|
||||||
type: 'role',
|
|
||||||
name: 'DataConsumer',
|
|
||||||
fullyQualifiedName: 'DataConsumer',
|
|
||||||
description:
|
|
||||||
'Users with Data Consumer role use different data assets for their day to day work.',
|
|
||||||
displayName: 'Data Consumer',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/roles/fb41f804-e266-4a8e-8f3a-022c72c70033',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { Button, Col, Row, Space, Switch, Tooltip } from 'antd';
|
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
|
||||||
import {
|
|
||||||
NO_PERMISSION_FOR_ACTION,
|
|
||||||
NO_PERMISSION_TO_VIEW,
|
|
||||||
} from '../../constants/HelperTextUtil';
|
|
||||||
import { Team } from '../../generated/entity/teams/team';
|
|
||||||
import jsonData from '../../jsons/en';
|
|
||||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
|
||||||
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
|
||||||
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
|
||||||
import {
|
|
||||||
OperationPermission,
|
|
||||||
ResourceEntity,
|
|
||||||
} from '../PermissionProvider/PermissionProvider.interface';
|
|
||||||
import TeamHierarchy from './TeamHierarchy';
|
|
||||||
import './teams.less';
|
|
||||||
|
|
||||||
interface TeamsProps {
|
|
||||||
showDeletedTeam: boolean;
|
|
||||||
onShowDeletedTeamChange: (checked: boolean) => void;
|
|
||||||
data: Team[];
|
|
||||||
onAddTeamClick: (value: boolean) => void;
|
|
||||||
onTeamExpand: (
|
|
||||||
loading?: boolean,
|
|
||||||
parentTeam?: string,
|
|
||||||
updateChildNode?: boolean
|
|
||||||
) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Teams: FC<TeamsProps> = ({
|
|
||||||
data,
|
|
||||||
showDeletedTeam,
|
|
||||||
onShowDeletedTeamChange,
|
|
||||||
onAddTeamClick,
|
|
||||||
onTeamExpand,
|
|
||||||
}) => {
|
|
||||||
const { getResourcePermission } = usePermissionProvider();
|
|
||||||
const [resourcePermissions, setResourcePermissions] =
|
|
||||||
useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
|
|
||||||
|
|
||||||
const filteredData = useMemo(
|
|
||||||
() =>
|
|
||||||
data.filter(
|
|
||||||
(d) =>
|
|
||||||
(showDeletedTeam && d.deleted) || (!showDeletedTeam && !d.deleted)
|
|
||||||
),
|
|
||||||
[data, showDeletedTeam]
|
|
||||||
);
|
|
||||||
|
|
||||||
const fetchPermissions = async () => {
|
|
||||||
try {
|
|
||||||
const perms = await getResourcePermission(ResourceEntity.TEAM);
|
|
||||||
setResourcePermissions(perms);
|
|
||||||
} catch (error) {
|
|
||||||
showErrorToast(
|
|
||||||
error as AxiosError,
|
|
||||||
jsonData['api-error-messages']['fetch-user-permission-error']
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchPermissions();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return resourcePermissions.ViewAll || resourcePermissions.ViewBasic ? (
|
|
||||||
<Row className="team-list-container" gutter={[16, 16]}>
|
|
||||||
<Col span={24}>
|
|
||||||
<Space align="center" className="tw-w-full tw-justify-end" size={16}>
|
|
||||||
<Space align="end" size={5}>
|
|
||||||
<Switch
|
|
||||||
checked={showDeletedTeam}
|
|
||||||
size="small"
|
|
||||||
onClick={onShowDeletedTeamChange}
|
|
||||||
/>
|
|
||||||
<span>Deleted Teams</span>
|
|
||||||
</Space>
|
|
||||||
<Tooltip
|
|
||||||
placement="bottom"
|
|
||||||
title={
|
|
||||||
resourcePermissions.Create ? 'Add Team' : NO_PERMISSION_FOR_ACTION
|
|
||||||
}>
|
|
||||||
<Button
|
|
||||||
disabled={!resourcePermissions.Create}
|
|
||||||
type="primary"
|
|
||||||
onClick={() => onAddTeamClick(true)}>
|
|
||||||
Add Team
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Space>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<TeamHierarchy data={filteredData} onTeamExpand={onTeamExpand} />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
) : (
|
|
||||||
<Row align="middle" className="tw-h-full">
|
|
||||||
<Col span={24}>
|
|
||||||
<ErrorPlaceHolder>
|
|
||||||
<p>{NO_PERMISSION_TO_VIEW}</p>
|
|
||||||
</ErrorPlaceHolder>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Teams;
|
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { Card } from 'antd';
|
|
||||||
import { lowerCase } from 'lodash';
|
|
||||||
import React, { HTMLAttributes } from 'react';
|
|
||||||
interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
|
||||||
id: string;
|
|
||||||
heading?: string;
|
|
||||||
classes?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CardV1 = ({ children, id, heading, classes, style }: CardProps) => {
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
className={`${classes} tw-h-full`}
|
|
||||||
data-testid={`${lowerCase(id)}-summary-container`}
|
|
||||||
size="small"
|
|
||||||
style={style}>
|
|
||||||
{heading ? <h6 className="tw-heading tw-text-base">{heading}</h6> : ''}
|
|
||||||
<div>{children}</div>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CardV1;
|
|
@ -20,7 +20,7 @@ import {
|
|||||||
diffWordsWithSpace,
|
diffWordsWithSpace,
|
||||||
} from 'diff';
|
} from 'diff';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { isUndefined, uniqueId } from 'lodash';
|
import { isUndefined, toString, uniqueId } from 'lodash';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import ReactDOMServer from 'react-dom/server';
|
import ReactDOMServer from 'react-dom/server';
|
||||||
import { EntityField } from '../constants/Feeds.constants';
|
import { EntityField } from '../constants/Feeds.constants';
|
||||||
@ -82,39 +82,39 @@ export const getDescriptionDiff = (
|
|||||||
newDescription: string | undefined,
|
newDescription: string | undefined,
|
||||||
latestDescription: string | undefined
|
latestDescription: string | undefined
|
||||||
) => {
|
) => {
|
||||||
if (!isUndefined(newDescription) || !isUndefined(oldDescription)) {
|
if (isUndefined(newDescription) || isUndefined(oldDescription)) {
|
||||||
const diffArr = diffWords(oldDescription ?? '', newDescription ?? '');
|
|
||||||
|
|
||||||
const result = diffArr.map((diff) => {
|
|
||||||
if (diff.added) {
|
|
||||||
return ReactDOMServer.renderToString(
|
|
||||||
<ins className="diff-added" data-testid="diff-added" key={uniqueId()}>
|
|
||||||
{diff.value}
|
|
||||||
</ins>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (diff.removed) {
|
|
||||||
return ReactDOMServer.renderToString(
|
|
||||||
<del
|
|
||||||
data-testid="diff-removed"
|
|
||||||
key={uniqueId()}
|
|
||||||
style={{ color: 'grey', textDecoration: 'line-through' }}>
|
|
||||||
{diff.value}
|
|
||||||
</del>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReactDOMServer.renderToString(
|
|
||||||
<span data-testid="diff-normal" key={uniqueId()}>
|
|
||||||
{diff.value}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return result.join('');
|
|
||||||
} else {
|
|
||||||
return latestDescription || '';
|
return latestDescription || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const diffArr = diffWords(toString(oldDescription), toString(newDescription));
|
||||||
|
|
||||||
|
const result = diffArr.map((diff) => {
|
||||||
|
if (diff.added) {
|
||||||
|
return ReactDOMServer.renderToString(
|
||||||
|
<ins className="diff-added" data-testid="diff-added" key={uniqueId()}>
|
||||||
|
{diff.value}
|
||||||
|
</ins>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (diff.removed) {
|
||||||
|
return ReactDOMServer.renderToString(
|
||||||
|
<del
|
||||||
|
data-testid="diff-removed"
|
||||||
|
key={uniqueId()}
|
||||||
|
style={{ color: 'grey', textDecoration: 'line-through' }}>
|
||||||
|
{diff.value}
|
||||||
|
</del>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReactDOMServer.renderToString(
|
||||||
|
<span data-testid="diff-normal" key={uniqueId()}>
|
||||||
|
{diff.value}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTagsDiff = (
|
export const getTagsDiff = (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user