mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-01 19:18:05 +00:00
metapilot cleanup (#15144)
This commit is contained in:
parent
b3401a32de
commit
e5fad139db
@ -25,7 +25,6 @@ import DomainProvider from './components/Domain/DomainProvider/DomainProvider';
|
||||
import { EntityExportModalProvider } from './components/Entity/EntityExportModalProvider/EntityExportModalProvider.component';
|
||||
import ErrorBoundary from './components/ErrorBoundary/ErrorBoundary';
|
||||
import GlobalSearchProvider from './components/GlobalSearchProvider/GlobalSearchProvider';
|
||||
import MetaPilotProvider from './components/MetaPilot/MetaPilotProvider/MetaPilotProvider';
|
||||
import PermissionProvider from './components/PermissionProvider/PermissionProvider';
|
||||
import TourProvider from './components/TourProvider/TourProvider';
|
||||
import WebAnalyticsProvider from './components/WebAnalytics/WebAnalyticsProvider';
|
||||
@ -51,11 +50,9 @@ const App: FC = () => {
|
||||
<WebSocketProvider>
|
||||
<GlobalSearchProvider>
|
||||
<DomainProvider>
|
||||
<MetaPilotProvider>
|
||||
<EntityExportModalProvider>
|
||||
<AppRouter />
|
||||
</EntityExportModalProvider>
|
||||
</MetaPilotProvider>
|
||||
<EntityExportModalProvider>
|
||||
<AppRouter />
|
||||
</EntityExportModalProvider>
|
||||
</DomainProvider>
|
||||
</GlobalSearchProvider>
|
||||
</WebSocketProvider>
|
||||
|
||||
@ -21,8 +21,6 @@ import SignUpPage from '../../pages/SignUp/SignUpPage';
|
||||
import Appbar from '../AppBar/Appbar';
|
||||
import AuthenticatedAppRouter from '../AppRouter/AuthenticatedAppRouter';
|
||||
import { useAuthContext } from '../Auth/AuthProviders/AuthProvider';
|
||||
import { useMetaPilotContext } from '../MetaPilot/MetaPilotProvider/MetaPilotProvider';
|
||||
import MetaPilotSidebar from '../MetaPilot/MetaPilotSidebar/MetaPilotSidebar';
|
||||
import LeftSidebar from '../MyData/LeftSidebar/LeftSidebar.component';
|
||||
import './app-container.less';
|
||||
|
||||
@ -30,7 +28,6 @@ const AppContainer = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const { Header, Sider, Content } = Layout;
|
||||
const { currentUser } = useAuthContext();
|
||||
const { suggestionsVisible } = useMetaPilotContext();
|
||||
|
||||
const isDirectionRTL = useMemo(() => i18n.dir() === 'rtl', [i18n]);
|
||||
|
||||
@ -56,11 +53,6 @@ const AppContainer = () => {
|
||||
<Content className="main-content">
|
||||
<AuthenticatedAppRouter />
|
||||
</Content>
|
||||
{suggestionsVisible && (
|
||||
<Sider className="right-sidebar-col" width={340}>
|
||||
<MetaPilotSidebar />
|
||||
</Sider>
|
||||
)}
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Space, Typography } from 'antd';
|
||||
import React, { useLayoutEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as SuggestionsIcon } from '../../../assets/svg/ic-suggestions.svg';
|
||||
import { ReactComponent as MetaPilotIcon } from '../../../assets/svg/MetaPilotApplication.svg';
|
||||
import RichTextEditorPreviewer from '../../common/RichTextEditor/RichTextEditorPreviewer';
|
||||
import { useMetaPilotContext } from '../MetaPilotProvider/MetaPilotProvider';
|
||||
import { SuggestionAction } from '../MetaPilotProvider/MetaPilotProvider.interface';
|
||||
import { MetaPilotDescriptionAlertProps } from './MetaPilotDescriptionAlert.interface';
|
||||
|
||||
const MetaPilotDescriptionAlert = ({
|
||||
showHeading = true,
|
||||
suggestion,
|
||||
hasEditAccess = false,
|
||||
}: MetaPilotDescriptionAlertProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { onUpdateActiveSuggestion, acceptRejectSuggestion } =
|
||||
useMetaPilotContext();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const element = document.querySelector('.suggested-description-card');
|
||||
if (element) {
|
||||
element.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!suggestion) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Space
|
||||
className="schema-description d-flex"
|
||||
data-testid="asset-description-container"
|
||||
direction="vertical"
|
||||
size={12}>
|
||||
{showHeading && (
|
||||
<Space size={4}>
|
||||
<Typography.Text className="right-panel-label">
|
||||
{t('label.description')}
|
||||
</Typography.Text>
|
||||
<MetaPilotIcon className="d-flex" height={24} width={24} />
|
||||
</Space>
|
||||
)}
|
||||
<Card className="suggested-description-card">
|
||||
<div className="d-flex m-b-xs justify-between">
|
||||
<div className="d-flex items-center gap-2">
|
||||
<SuggestionsIcon height={20} width={20} />
|
||||
<Typography.Text className="m-b-0 font-medium text-md">
|
||||
{t('label.metapilot-suggested-description')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<CloseOutlined onClick={() => onUpdateActiveSuggestion(undefined)} />
|
||||
</div>
|
||||
<RichTextEditorPreviewer markdown={suggestion.description ?? ''} />
|
||||
{hasEditAccess && (
|
||||
<div className="d-flex justify-end p-t-sm gap-2">
|
||||
<Button
|
||||
ghost
|
||||
icon={<CloseOutlined />}
|
||||
type="primary"
|
||||
onClick={() =>
|
||||
acceptRejectSuggestion(suggestion, SuggestionAction.Reject)
|
||||
}>
|
||||
{t('label.reject')}
|
||||
</Button>
|
||||
<Button
|
||||
icon={<CheckOutlined />}
|
||||
type="primary"
|
||||
onClick={() =>
|
||||
acceptRejectSuggestion(suggestion, SuggestionAction.Accept)
|
||||
}>
|
||||
{t('label.accept')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetaPilotDescriptionAlert;
|
||||
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { Suggestion } from '../../../generated/entity/feed/suggestion';
|
||||
|
||||
export interface MetaPilotDescriptionAlertProps {
|
||||
showHeading?: boolean;
|
||||
suggestion: Suggestion;
|
||||
hasEditAccess?: boolean;
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Space, Typography } from 'antd';
|
||||
import React, { useLayoutEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as QuestionMarkIcon } from '../../../assets/svg/ic-question-mark.svg';
|
||||
import { ReactComponent as SuggestionsIcon } from '../../../assets/svg/ic-suggestions.svg';
|
||||
import RichTextEditorPreviewer from '../../common/RichTextEditor/RichTextEditorPreviewer';
|
||||
import { useMetaPilotContext } from '../MetaPilotProvider/MetaPilotProvider';
|
||||
import { SuggestionAction } from '../MetaPilotProvider/MetaPilotProvider.interface';
|
||||
import './metapilot-popover-content.less';
|
||||
import { MetaPilotPopoverContentProps } from './MetaPilotPopoverContent.interface';
|
||||
|
||||
const MetaPilotPopoverContent = ({
|
||||
suggestion,
|
||||
hasEditAccess = false,
|
||||
}: MetaPilotPopoverContentProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { acceptRejectSuggestion } = useMetaPilotContext();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const element = document.querySelector('.has-suggestion');
|
||||
if (element) {
|
||||
element.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!suggestion) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Space
|
||||
className="schema-description d-flex"
|
||||
data-testid="asset-description-container"
|
||||
direction="vertical"
|
||||
size={12}>
|
||||
<Card className="card-padding-0 card-body-border-none">
|
||||
<div className="p-sm">
|
||||
<SuggestionsIcon
|
||||
className="float-left m-r-xs"
|
||||
height={16}
|
||||
width={16}
|
||||
/>
|
||||
<RichTextEditorPreviewer markdown={suggestion.description ?? ''} />
|
||||
</div>
|
||||
|
||||
<div className="p-xs popover-card-footer">
|
||||
<div className="d-flex items-center text-xs">
|
||||
<QuestionMarkIcon height={20} width={20} />
|
||||
<Typography.Text className="m-l-xs">
|
||||
{t('label.generated-by')}
|
||||
</Typography.Text>
|
||||
<Typography.Text strong className="m-l-xss text-primary">
|
||||
{t('label.metapilot')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
{hasEditAccess && (
|
||||
<div className="d-flex gap-2">
|
||||
<Button
|
||||
ghost
|
||||
icon={<CloseOutlined />}
|
||||
size="small"
|
||||
type="primary"
|
||||
onClick={() =>
|
||||
acceptRejectSuggestion(suggestion, SuggestionAction.Reject)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
icon={<CheckOutlined />}
|
||||
size="small"
|
||||
type="primary"
|
||||
onClick={() =>
|
||||
acceptRejectSuggestion(suggestion, SuggestionAction.Accept)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetaPilotPopoverContent;
|
||||
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { Suggestion } from '../../../generated/entity/feed/suggestion';
|
||||
|
||||
export interface MetaPilotPopoverContentProps {
|
||||
showHeading?: boolean;
|
||||
suggestion: Suggestion;
|
||||
hasEditAccess?: boolean;
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 url('../../../styles/variables.less');
|
||||
|
||||
.popover-card-footer {
|
||||
background-color: @grey-1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.metapilot-popover {
|
||||
width: 350px;
|
||||
.ant-popover-inner-content {
|
||||
padding: 0;
|
||||
}
|
||||
.markdown-parser .toastui-editor-contents {
|
||||
p {
|
||||
color: @text-grey-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { ReactNode } from 'react';
|
||||
import { Suggestion } from '../../../generated/entity/feed/suggestion';
|
||||
|
||||
export interface MetaPilotContextType {
|
||||
suggestionsVisible: boolean;
|
||||
isMetaPilotEnabled: boolean;
|
||||
onToggleSuggestionsVisible: (state: boolean) => void;
|
||||
activeSuggestion?: Suggestion;
|
||||
suggestions: Suggestion[];
|
||||
loading: boolean;
|
||||
entityFqn: string;
|
||||
onUpdateActiveSuggestion: (suggestion?: Suggestion) => void;
|
||||
fetchSuggestions: (entityFqn: string) => void;
|
||||
acceptRejectSuggestion: (
|
||||
suggestion: Suggestion,
|
||||
action: SuggestionAction
|
||||
) => void;
|
||||
onUpdateEntityFqn: (entityFqn: string) => void;
|
||||
resetMetaPilot: () => void;
|
||||
initMetaPilot: (
|
||||
entityFqn: string,
|
||||
refreshEntity?: (suggestion: Suggestion) => void
|
||||
) => void;
|
||||
}
|
||||
|
||||
export interface MetaPilotContextProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export enum SuggestionAction {
|
||||
Accept = 'accept',
|
||||
Reject = 'reject',
|
||||
}
|
||||
@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isEmpty } from 'lodash';
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as MetaPilotIcon } from '../../../assets/svg/MetaPilotApplication.svg';
|
||||
import { Suggestion } from '../../../generated/entity/feed/suggestion';
|
||||
import { Include } from '../../../generated/type/include';
|
||||
import { getApplicationByName } from '../../../rest/applicationAPI';
|
||||
import {
|
||||
getMetaPilotSuggestionsList,
|
||||
updateSuggestionStatus,
|
||||
} from '../../../rest/suggestionsAPI';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import { usePermissionProvider } from '../../PermissionProvider/PermissionProvider';
|
||||
import {
|
||||
MetaPilotContextProps,
|
||||
MetaPilotContextType,
|
||||
SuggestionAction,
|
||||
} from './MetaPilotProvider.interface';
|
||||
|
||||
export const MetaPilotContext = createContext({} as MetaPilotContextType);
|
||||
|
||||
const MetaPilotProvider = ({ children }: MetaPilotContextProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [suggestionsVisible, setSuggestionsVisible] = useState(false);
|
||||
const [isMetaPilotEnabled, setIsMetaPilotEnabled] = useState(false);
|
||||
const [activeSuggestion, setActiveSuggestion] = useState<
|
||||
Suggestion | undefined
|
||||
>();
|
||||
const [entityFqn, setEntityFqn] = useState('');
|
||||
const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const refreshEntity = useRef<(suggestion: Suggestion) => void>();
|
||||
const { permissions } = usePermissionProvider();
|
||||
|
||||
const fetchMetaPilotAppDetails = useCallback(async () => {
|
||||
try {
|
||||
await getApplicationByName('MetaPilotApplication', {
|
||||
fields: 'owner',
|
||||
include: Include.All,
|
||||
});
|
||||
setIsMetaPilotEnabled(true);
|
||||
} catch (error) {
|
||||
setIsMetaPilotEnabled(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchSuggestions = useCallback(async (entityFQN: string) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await getMetaPilotSuggestionsList({
|
||||
entityFQN,
|
||||
});
|
||||
setSuggestions(res.data);
|
||||
} catch (err) {
|
||||
showErrorToast(
|
||||
err as AxiosError,
|
||||
t('server.entity-fetch-error', {
|
||||
entity: t('label.lineage-data-lowercase'),
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const acceptRejectSuggestion = useCallback(
|
||||
async (suggestion: Suggestion, status: SuggestionAction) => {
|
||||
try {
|
||||
await updateSuggestionStatus(suggestion, status);
|
||||
await fetchSuggestions(entityFqn);
|
||||
setActiveSuggestion(undefined);
|
||||
if (status === SuggestionAction.Accept) {
|
||||
refreshEntity.current?.(suggestion);
|
||||
}
|
||||
} catch (err) {
|
||||
showErrorToast(err as AxiosError);
|
||||
}
|
||||
},
|
||||
[entityFqn, refreshEntity]
|
||||
);
|
||||
|
||||
const onToggleSuggestionsVisible = useCallback((state: boolean) => {
|
||||
setSuggestionsVisible(state);
|
||||
}, []);
|
||||
|
||||
const onUpdateActiveSuggestion = useCallback((suggestion?: Suggestion) => {
|
||||
setActiveSuggestion(suggestion);
|
||||
}, []);
|
||||
|
||||
const onUpdateEntityFqn = useCallback((entityFqn: string) => {
|
||||
setEntityFqn(entityFqn);
|
||||
}, []);
|
||||
|
||||
const resetMetaPilot = useCallback(() => {
|
||||
setSuggestionsVisible(false);
|
||||
setActiveSuggestion(undefined);
|
||||
setEntityFqn('');
|
||||
}, []);
|
||||
|
||||
const initMetaPilot = useCallback(
|
||||
(entityFqn: string, refreshEntityFn?: (suggestion: Suggestion) => void) => {
|
||||
setEntityFqn(entityFqn);
|
||||
refreshEntity.current = refreshEntityFn;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isMetaPilotEnabled && !isEmpty(entityFqn)) {
|
||||
fetchSuggestions(entityFqn);
|
||||
}
|
||||
}, [isMetaPilotEnabled, entityFqn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(permissions)) {
|
||||
fetchMetaPilotAppDetails();
|
||||
}
|
||||
}, [permissions]);
|
||||
|
||||
const metaPilotContextObj = useMemo(() => {
|
||||
return {
|
||||
suggestionsVisible,
|
||||
isMetaPilotEnabled,
|
||||
suggestions,
|
||||
activeSuggestion,
|
||||
entityFqn,
|
||||
loading,
|
||||
onToggleSuggestionsVisible,
|
||||
onUpdateEntityFqn,
|
||||
onUpdateActiveSuggestion,
|
||||
fetchSuggestions,
|
||||
acceptRejectSuggestion,
|
||||
initMetaPilot,
|
||||
resetMetaPilot,
|
||||
};
|
||||
}, [
|
||||
suggestionsVisible,
|
||||
isMetaPilotEnabled,
|
||||
suggestions,
|
||||
activeSuggestion,
|
||||
entityFqn,
|
||||
loading,
|
||||
onToggleSuggestionsVisible,
|
||||
onUpdateEntityFqn,
|
||||
onUpdateActiveSuggestion,
|
||||
fetchSuggestions,
|
||||
acceptRejectSuggestion,
|
||||
initMetaPilot,
|
||||
resetMetaPilot,
|
||||
]);
|
||||
|
||||
return (
|
||||
<MetaPilotContext.Provider value={metaPilotContextObj}>
|
||||
{children}
|
||||
{isMetaPilotEnabled && (
|
||||
<div className="floating-button-container">
|
||||
<Button
|
||||
icon={<MetaPilotIcon height={60} width={60} />}
|
||||
shape="circle"
|
||||
style={{ height: '60px', width: '60px' }}
|
||||
type="text"
|
||||
onClick={() => onToggleSuggestionsVisible(true)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</MetaPilotContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useMetaPilotContext = () => useContext(MetaPilotContext);
|
||||
|
||||
export default MetaPilotProvider;
|
||||
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { CloseOutlined } from '@ant-design/icons';
|
||||
import { Card, Drawer, Typography } from 'antd';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as MetaPilotIcon } from '../../../assets/svg/MetaPilotApplication.svg';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from '../../../enums/common.enum';
|
||||
import { Suggestion } from '../../../generated/entity/feed/suggestion';
|
||||
import EntityLink from '../../../utils/EntityLink';
|
||||
import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import RichTextEditorPreviewer from '../../common/RichTextEditor/RichTextEditorPreviewer';
|
||||
import Loader from '../../Loader/Loader';
|
||||
import { useMetaPilotContext } from '../MetaPilotProvider/MetaPilotProvider';
|
||||
import './meta-pilot-sidebar.less';
|
||||
|
||||
const MetaPilotSidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
onUpdateActiveSuggestion,
|
||||
suggestions,
|
||||
loading,
|
||||
suggestionsVisible,
|
||||
onToggleSuggestionsVisible,
|
||||
} = useMetaPilotContext();
|
||||
|
||||
const descriptionsView = useMemo(() => {
|
||||
return suggestions.map((item: Suggestion) => {
|
||||
return (
|
||||
<Card
|
||||
className="suggestion-card m-t-xs border-primary"
|
||||
key={item.id}
|
||||
onClick={() => onUpdateActiveSuggestion(item)}>
|
||||
<RichTextEditorPreviewer
|
||||
enableSeeMoreVariant={false}
|
||||
markdown={item.description ?? ''}
|
||||
/>
|
||||
<Typography.Text className="text-xss text-grey-muted">
|
||||
{EntityLink.getTableColumnName(item.entityLink) ??
|
||||
EntityLink.getEntityFqn(item.entityLink)}
|
||||
</Typography.Text>
|
||||
</Card>
|
||||
);
|
||||
});
|
||||
}, [suggestions]);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
destroyOnClose
|
||||
className="meta-pilot-drawer"
|
||||
closable={false}
|
||||
extra={
|
||||
<CloseOutlined
|
||||
data-testid="entity-panel-close-icon"
|
||||
onClick={() => onToggleSuggestionsVisible(false)}
|
||||
/>
|
||||
}
|
||||
getContainer={false}
|
||||
headerStyle={{ padding: 16 }}
|
||||
mask={false}
|
||||
open={suggestionsVisible}
|
||||
title={
|
||||
<div className="d-flex items-center gap-2">
|
||||
<MetaPilotIcon height={24} width={24} />
|
||||
<Typography.Title className="m-b-0" level={4}>
|
||||
{t('label.metapilot')}
|
||||
</Typography.Title>
|
||||
</div>
|
||||
}
|
||||
width={340}>
|
||||
{loading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<>
|
||||
{suggestions?.length === 0 && (
|
||||
<ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.NO_DATA} />
|
||||
)}
|
||||
{suggestions.length > 0 && (
|
||||
<>
|
||||
<Typography.Text className="text-grey-muted m-m-xs">
|
||||
{t('label.suggested-description-plural')}
|
||||
</Typography.Text>
|
||||
{descriptionsView}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetaPilotSidebar;
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 url('../../../styles/variables.less');
|
||||
|
||||
.meta-pilot-drawer {
|
||||
.ant-drawer-content {
|
||||
background-color: #f6f9fd;
|
||||
}
|
||||
.ant-drawer-body {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
.suggestion-card {
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
p {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-drawer-content-wrapper {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
@ -11,21 +11,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Button, Popover, Space } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Button, Space } from 'antd';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as EditIcon } from '../../assets/svg/edit-new.svg';
|
||||
import RichTextEditorPreviewer from '../../components/common/RichTextEditor/RichTextEditorPreviewer';
|
||||
import { DE_ACTIVE_COLOR } from '../../constants/constants';
|
||||
import { EntityField } from '../../constants/Feeds.constants';
|
||||
import { EntityType } from '../../enums/entity.enum';
|
||||
import EntityTasks from '../../pages/TasksPage/EntityTasks/EntityTasks.component';
|
||||
import EntityLink from '../../utils/EntityLink';
|
||||
import { getEntityFeedLink } from '../../utils/EntityUtils';
|
||||
import MetaPilotPopoverContent from '../MetaPilot/MetaPilotPopoverContent/MetaPilotPopoverContent.component';
|
||||
import { useMetaPilotContext } from '../MetaPilot/MetaPilotProvider/MetaPilotProvider';
|
||||
import { TableDescriptionProps } from './TableDescription.interface';
|
||||
|
||||
const TableDescription = ({
|
||||
@ -39,118 +32,49 @@ const TableDescription = ({
|
||||
onThreadLinkSelect,
|
||||
}: TableDescriptionProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { activeSuggestion, suggestions, onUpdateActiveSuggestion } =
|
||||
useMetaPilotContext();
|
||||
const [showSuggestionPopover, setShowSuggestionPopover] = useState(false);
|
||||
|
||||
const entityLink = useMemo(
|
||||
() =>
|
||||
entityType === EntityType.TABLE
|
||||
? EntityLink.getTableEntityLink(
|
||||
entityFqn,
|
||||
columnData.record?.name ?? ''
|
||||
)
|
||||
: getEntityFeedLink(entityType, columnData.fqn),
|
||||
[entityType, entityFqn]
|
||||
);
|
||||
|
||||
const suggestionForEmptyData = useMemo(() => {
|
||||
if (isEmpty(columnData.field ?? ''.trim())) {
|
||||
return suggestions.find(
|
||||
(suggestion) => suggestion.entityLink === entityLink
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [suggestions, columnData.field, entityLink]);
|
||||
|
||||
const suggestionData = useMemo(() => {
|
||||
if (activeSuggestion?.entityLink === entityLink) {
|
||||
return (
|
||||
<MetaPilotPopoverContent
|
||||
hasEditAccess={hasEditPermission}
|
||||
suggestion={activeSuggestion}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [hasEditPermission, suggestionForEmptyData, activeSuggestion]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeSuggestion?.entityLink === entityLink) {
|
||||
setShowSuggestionPopover(true);
|
||||
} else {
|
||||
setShowSuggestionPopover(false);
|
||||
}
|
||||
}, [activeSuggestion, entityLink]);
|
||||
|
||||
const onPopoverOpenChange = useCallback(
|
||||
(data: boolean) => {
|
||||
setShowSuggestionPopover(data);
|
||||
if (!data) {
|
||||
onUpdateActiveSuggestion();
|
||||
}
|
||||
},
|
||||
[onUpdateActiveSuggestion]
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
align={{ targetOffset: [0, 40] }}
|
||||
content={suggestionData}
|
||||
open={showSuggestionPopover}
|
||||
overlayClassName="metapilot-popover"
|
||||
overlayStyle={{
|
||||
bottom: 'auto',
|
||||
}}
|
||||
placement="bottom"
|
||||
trigger="click"
|
||||
onOpenChange={onPopoverOpenChange}>
|
||||
<Space
|
||||
className={classNames('hover-icon-group', {
|
||||
'has-suggestion': Boolean(suggestionData),
|
||||
})}
|
||||
data-testid="description"
|
||||
direction="vertical"
|
||||
id={`field-description-${index}`}>
|
||||
{columnData.field ? (
|
||||
<RichTextEditorPreviewer markdown={columnData.field} />
|
||||
) : (
|
||||
<span className="text-grey-muted">
|
||||
{t('label.no-entity', {
|
||||
entity: t('label.description'),
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
{!isReadOnly ? (
|
||||
<Space align="baseline" size="middle">
|
||||
{hasEditPermission && (
|
||||
<Button
|
||||
className="cursor-pointer hover-cell-icon"
|
||||
data-testid="edit-button"
|
||||
style={{
|
||||
color: DE_ACTIVE_COLOR,
|
||||
padding: 0,
|
||||
border: 'none',
|
||||
background: 'transparent',
|
||||
}}
|
||||
onClick={onClick}>
|
||||
<EditIcon />
|
||||
</Button>
|
||||
)}
|
||||
<Space
|
||||
className="hover-icon-group"
|
||||
data-testid="description"
|
||||
direction="vertical"
|
||||
id={`field-description-${index}`}>
|
||||
{columnData.field ? (
|
||||
<RichTextEditorPreviewer markdown={columnData.field} />
|
||||
) : (
|
||||
<span className="text-grey-muted">
|
||||
{t('label.no-entity', {
|
||||
entity: t('label.description'),
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
{!isReadOnly ? (
|
||||
<Space align="baseline" size="middle">
|
||||
{hasEditPermission && (
|
||||
<Button
|
||||
className="cursor-pointer hover-cell-icon"
|
||||
data-testid="edit-button"
|
||||
style={{
|
||||
color: DE_ACTIVE_COLOR,
|
||||
padding: 0,
|
||||
border: 'none',
|
||||
background: 'transparent',
|
||||
}}
|
||||
onClick={onClick}>
|
||||
<EditIcon />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<EntityTasks
|
||||
data={columnData}
|
||||
entityFqn={entityFqn}
|
||||
entityTaskType={EntityField.DESCRIPTION}
|
||||
entityType={entityType}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
) : null}
|
||||
</Space>
|
||||
</Popover>
|
||||
<EntityTasks
|
||||
data={columnData}
|
||||
entityFqn={entityFqn}
|
||||
entityTaskType={EntityField.DESCRIPTION}
|
||||
entityType={entityType}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</Space>
|
||||
) : null}
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -74,12 +74,6 @@ jest.mock('../../TableTags/TableTags.component', () =>
|
||||
))
|
||||
);
|
||||
|
||||
jest.mock('../../MetaPilot/MetaPilotProvider/MetaPilotProvider', () => ({
|
||||
useMetaPilotContext: jest.fn().mockReturnValue({
|
||||
suggestions: [],
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
|
||||
jest
|
||||
.fn()
|
||||
|
||||
@ -43,14 +43,6 @@ jest.mock('react-router-dom', () => ({
|
||||
useParams: jest.fn().mockImplementation(() => mockParams),
|
||||
}));
|
||||
|
||||
jest.mock('../MetaPilot/MetaPilotProvider/MetaPilotProvider', () => ({
|
||||
useMetaPilotContext: jest.fn().mockReturnValue({
|
||||
suggestions: [],
|
||||
initMetaPilot: jest.fn(),
|
||||
resetMetaPilot: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../rest/rolesAPIV1', () => ({
|
||||
getRoles: jest.fn().mockImplementation(() => Promise.resolve(mockUserRole)),
|
||||
}));
|
||||
|
||||
@ -12,11 +12,9 @@
|
||||
*/
|
||||
|
||||
import Icon from '@ant-design/icons';
|
||||
import { Card, Popover, Space, Tooltip, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { Card, Space, Tooltip, Typography } from 'antd';
|
||||
import { t } from 'i18next';
|
||||
import { isEmpty } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { ReactComponent as CommentIcon } from '../../../assets/svg/comment.svg';
|
||||
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
|
||||
@ -31,8 +29,6 @@ import {
|
||||
getUpdateDescriptionPath,
|
||||
TASK_ENTITIES,
|
||||
} from '../../../utils/TasksUtils';
|
||||
import MetaPilotPopoverContent from '../../MetaPilot/MetaPilotPopoverContent/MetaPilotPopoverContent.component';
|
||||
import { useMetaPilotContext } from '../../MetaPilot/MetaPilotProvider/MetaPilotProvider';
|
||||
import { ModalWithMarkdownEditor } from '../../Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
|
||||
import RichTextEditorPreviewer from '../RichTextEditor/RichTextEditorPreviewer';
|
||||
const { Text } = Typography;
|
||||
@ -77,9 +73,6 @@ const DescriptionV1 = ({
|
||||
reduceDescription,
|
||||
}: Props) => {
|
||||
const history = useHistory();
|
||||
const { activeSuggestion, suggestions, onUpdateActiveSuggestion } =
|
||||
useMetaPilotContext();
|
||||
const [showSuggestionPopover, setShowSuggestionPopover] = useState(false);
|
||||
const handleRequestDescription = useCallback(() => {
|
||||
history.push(
|
||||
getRequestDescriptionPath(entityType as string, entityFqn as string)
|
||||
@ -92,18 +85,8 @@ const DescriptionV1 = ({
|
||||
);
|
||||
}, [entityType, entityFqn]);
|
||||
|
||||
const { entityLink, entityLinkWithoutField } = useMemo(() => {
|
||||
const entityLink = getEntityFeedLink(
|
||||
entityType,
|
||||
entityFqn,
|
||||
EntityField.DESCRIPTION
|
||||
);
|
||||
const entityLinkWithoutField = getEntityFeedLink(entityType, entityFqn);
|
||||
|
||||
return {
|
||||
entityLink,
|
||||
entityLinkWithoutField,
|
||||
};
|
||||
const entityLink = useMemo(() => {
|
||||
return getEntityFeedLink(entityType, entityFqn, EntityField.DESCRIPTION);
|
||||
}, [entityType, entityFqn]);
|
||||
|
||||
const taskActionButton = useMemo(() => {
|
||||
@ -174,89 +157,38 @@ const DescriptionV1 = ({
|
||||
]
|
||||
);
|
||||
|
||||
const suggestionForEmptyData = useMemo(() => {
|
||||
if (isEmpty(description.trim())) {
|
||||
return suggestions.find(
|
||||
(suggestion) => suggestion.entityLink === entityLinkWithoutField
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [suggestions, description]);
|
||||
|
||||
const suggestionData = useMemo(() => {
|
||||
if (activeSuggestion?.entityLink === entityLinkWithoutField) {
|
||||
return (
|
||||
<MetaPilotPopoverContent
|
||||
hasEditAccess={hasEditAccess}
|
||||
suggestion={activeSuggestion}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [hasEditAccess, suggestionForEmptyData, activeSuggestion]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeSuggestion?.entityLink === entityLinkWithoutField) {
|
||||
setShowSuggestionPopover(true);
|
||||
} else {
|
||||
setShowSuggestionPopover(false);
|
||||
}
|
||||
}, [activeSuggestion, entityLinkWithoutField]);
|
||||
|
||||
const onPopoverOpenChange = useCallback(
|
||||
(data: boolean) => {
|
||||
setShowSuggestionPopover(data);
|
||||
if (!data) {
|
||||
onUpdateActiveSuggestion();
|
||||
}
|
||||
},
|
||||
[onUpdateActiveSuggestion]
|
||||
);
|
||||
|
||||
const content = (
|
||||
<Popover
|
||||
content={suggestionData}
|
||||
open={showSuggestionPopover}
|
||||
overlayClassName="metapilot-popover"
|
||||
placement="bottom"
|
||||
trigger="click"
|
||||
onOpenChange={onPopoverOpenChange}>
|
||||
<Space
|
||||
className={classNames('schema-description d-flex', {
|
||||
'has-suggestion': Boolean(suggestionData),
|
||||
})}
|
||||
data-testid="asset-description-container"
|
||||
direction="vertical"
|
||||
size={16}>
|
||||
<Space size="middle">
|
||||
<Text className="right-panel-label">{t('label.description')}</Text>
|
||||
{showActions && actionButtons}
|
||||
</Space>
|
||||
<div>
|
||||
{description.trim() ? (
|
||||
<RichTextEditorPreviewer
|
||||
className={reduceDescription ? 'max-two-lines' : ''}
|
||||
enableSeeMoreVariant={!removeBlur}
|
||||
markdown={description}
|
||||
/>
|
||||
) : (
|
||||
<span>{t('label.no-description')}</span>
|
||||
)}
|
||||
<ModalWithMarkdownEditor
|
||||
header={t('label.edit-description-for', { entityName })}
|
||||
placeholder={t('label.enter-entity', {
|
||||
entity: t('label.description'),
|
||||
})}
|
||||
value={description}
|
||||
visible={Boolean(isEdit)}
|
||||
onCancel={onCancel}
|
||||
onSave={onDescriptionUpdate}
|
||||
/>
|
||||
</div>
|
||||
<Space
|
||||
className="schema-description d-flex"
|
||||
data-testid="asset-description-container"
|
||||
direction="vertical"
|
||||
size={16}>
|
||||
<Space size="middle">
|
||||
<Text className="right-panel-label">{t('label.description')}</Text>
|
||||
{showActions && actionButtons}
|
||||
</Space>
|
||||
</Popover>
|
||||
<div>
|
||||
{description.trim() ? (
|
||||
<RichTextEditorPreviewer
|
||||
className={reduceDescription ? 'max-two-lines' : ''}
|
||||
enableSeeMoreVariant={!removeBlur}
|
||||
markdown={description}
|
||||
/>
|
||||
) : (
|
||||
<span>{t('label.no-description')}</span>
|
||||
)}
|
||||
<ModalWithMarkdownEditor
|
||||
header={t('label.edit-description-for', { entityName })}
|
||||
placeholder={t('label.enter-entity', {
|
||||
entity: t('label.description'),
|
||||
})}
|
||||
value={description}
|
||||
visible={Boolean(isEdit)}
|
||||
onCancel={onCancel}
|
||||
onSave={onDescriptionUpdate}
|
||||
/>
|
||||
</div>
|
||||
</Space>
|
||||
);
|
||||
|
||||
return wrapInCard ? <Card>{content}</Card> : content;
|
||||
|
||||
@ -30,17 +30,6 @@ jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
'../../components/MetaPilot/MetaPilotProvider/MetaPilotProvider',
|
||||
() => ({
|
||||
useMetaPilotContext: jest.fn().mockReturnValue({
|
||||
suggestions: [],
|
||||
initMetaPilot: jest.fn(),
|
||||
resetMetaPilot: jest.fn(),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
jest.mock('../../rest/tableAPI', () => ({
|
||||
getTableDetailsByFQN: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
|
||||
@ -33,7 +33,6 @@ import EntityRightPanel from '../../components/Entity/EntityRightPanel/EntityRig
|
||||
import Lineage from '../../components/Lineage/Lineage.component';
|
||||
import LineageProvider from '../../components/LineageProvider/LineageProvider';
|
||||
import Loader from '../../components/Loader/Loader';
|
||||
import { useMetaPilotContext } from '../../components/MetaPilot/MetaPilotProvider/MetaPilotProvider';
|
||||
import { EntityName } from '../../components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||
@ -63,7 +62,6 @@ import {
|
||||
import { CreateThread } from '../../generated/api/feed/createThread';
|
||||
import { Tag } from '../../generated/entity/classification/tag';
|
||||
import { JoinedWith, Table } from '../../generated/entity/data/table';
|
||||
import { Suggestion } from '../../generated/entity/feed/suggestion';
|
||||
import { ThreadType } from '../../generated/entity/feed/thread';
|
||||
import { TagLabel } from '../../generated/type/tagLabel';
|
||||
import { useFqn } from '../../hooks/useFqn';
|
||||
@ -86,7 +84,6 @@ import {
|
||||
sortTagsCaseInsensitive,
|
||||
} from '../../utils/CommonUtils';
|
||||
import { defaultFields } from '../../utils/DatasetDetailsUtils';
|
||||
import EntityLink from '../../utils/EntityLink';
|
||||
import { getEntityName } from '../../utils/EntityUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
||||
@ -117,7 +114,6 @@ const TableDetailsPageV1 = () => {
|
||||
ThreadType.Conversation
|
||||
);
|
||||
const [queryCount, setQueryCount] = useState(0);
|
||||
const { resetMetaPilot, initMetaPilot } = useMetaPilotContext();
|
||||
|
||||
const [loading, setLoading] = useState(!isTourOpen);
|
||||
const [tablePermissions, setTablePermissions] = useState<OperationPermission>(
|
||||
@ -281,59 +277,11 @@ const TableDetailsPageV1 = () => {
|
||||
[getEntityPermissionByFqn, setTablePermissions]
|
||||
);
|
||||
|
||||
const updateDescriptionFromMetaPilot = useCallback(
|
||||
(suggestion: Suggestion) => {
|
||||
setTableDetails((prev) => {
|
||||
if (!prev) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeCol = prev?.columns.find((column) => {
|
||||
return (
|
||||
EntityLink.getTableEntityLink(
|
||||
prev.fullyQualifiedName ?? '',
|
||||
column.name ?? ''
|
||||
) === suggestion.entityLink
|
||||
);
|
||||
});
|
||||
|
||||
if (!activeCol) {
|
||||
return {
|
||||
...prev,
|
||||
description: suggestion.description,
|
||||
};
|
||||
} else {
|
||||
const updatedColumns = prev.columns.map((column) => {
|
||||
if (column.fullyQualifiedName === activeCol.fullyQualifiedName) {
|
||||
return {
|
||||
...column,
|
||||
description: suggestion.description,
|
||||
};
|
||||
} else {
|
||||
return column;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...prev,
|
||||
columns: updatedColumns,
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (tableFqn && updateDescriptionFromMetaPilot) {
|
||||
if (tableFqn) {
|
||||
fetchResourcePermission(tableFqn);
|
||||
initMetaPilot(tableFqn, updateDescriptionFromMetaPilot);
|
||||
}
|
||||
|
||||
return () => {
|
||||
resetMetaPilot();
|
||||
};
|
||||
}, [tableFqn, updateDescriptionFromMetaPilot]);
|
||||
}, [tableFqn]);
|
||||
|
||||
const handleFeedCount = useCallback((data: FeedCounts) => {
|
||||
setFeedCount(data);
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { PagingResponse } from 'Models';
|
||||
import { SuggestionAction } from '../components/MetaPilot/MetaPilotProvider/MetaPilotProvider.interface';
|
||||
import { Suggestion } from '../generated/entity/feed/suggestion';
|
||||
import { ListParams } from '../interface/API.interface';
|
||||
import APIClient from './index';
|
||||
|
||||
const BASE_URL = '/suggestions';
|
||||
|
||||
export type ListSuggestionsParams = ListParams & {
|
||||
entityFQN?: string;
|
||||
};
|
||||
|
||||
export const getMetaPilotSuggestionsList = async (
|
||||
params?: ListSuggestionsParams
|
||||
) => {
|
||||
const response = await APIClient.get<PagingResponse<Suggestion[]>>(BASE_URL, {
|
||||
params,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateSuggestionStatus = (
|
||||
data: Suggestion,
|
||||
action: SuggestionAction
|
||||
): Promise<AxiosResponse> => {
|
||||
const url = `${BASE_URL}/${data.id}/${action}`;
|
||||
|
||||
return APIClient.put(url, {});
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user