mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 10:26:09 +00:00
UI: Add support for deleting a post in table entity (#3405)
* UI: Add support for deleting a post in table entity * Addressing review comment
This commit is contained in:
parent
3dfae301fe
commit
eb436adcb2
@ -74,3 +74,10 @@ export const postFeedById: Function = (
|
||||
): Promise<AxiosResponse> => {
|
||||
return APIClient.post(`/feed/${id}/posts`, data);
|
||||
};
|
||||
|
||||
export const deletePostById: Function = (
|
||||
threadId: string,
|
||||
postId: string
|
||||
): Promise<AxiosResponse> => {
|
||||
return APIClient.delete(`/feed/${threadId}/posts/${postId}`);
|
||||
};
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2021 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 { Post } from 'Models';
|
||||
import { HTMLAttributes } from 'react';
|
||||
|
||||
export interface ConfirmState {
|
||||
state: boolean;
|
||||
threadId: string | undefined;
|
||||
postId: string | undefined;
|
||||
}
|
||||
export interface ActivityFeedCardProp extends HTMLAttributes<HTMLDivElement> {
|
||||
feed: Post;
|
||||
entityLink?: string;
|
||||
repliedUsers?: Array<string>;
|
||||
replies?: number;
|
||||
isEntityFeed?: boolean;
|
||||
threadId?: string;
|
||||
lastReplyTimeStamp?: number;
|
||||
isFooterVisible?: boolean;
|
||||
onThreadSelect?: (id: string) => void;
|
||||
deletePostHandler?: (threadId: string, postId: string) => void;
|
||||
}
|
||||
export interface FeedHeaderProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<ActivityFeedCardProp, 'isEntityFeed'> {
|
||||
createdBy: string;
|
||||
timeStamp: number;
|
||||
entityType: string;
|
||||
entityFQN: string;
|
||||
entityField: string;
|
||||
}
|
||||
export interface FeedBodyProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<ActivityFeedCardProp, 'deletePostHandler'> {
|
||||
message: string;
|
||||
postId: string;
|
||||
threadId: string;
|
||||
onConfirmation: (data: ConfirmState) => void;
|
||||
}
|
||||
export interface FeedFooterProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<
|
||||
ActivityFeedCardProp,
|
||||
| 'replies'
|
||||
| 'repliedUsers'
|
||||
| 'threadId'
|
||||
| 'onThreadSelect'
|
||||
| 'lastReplyTimeStamp'
|
||||
| 'isFooterVisible'
|
||||
> {}
|
@ -14,8 +14,7 @@
|
||||
import { AxiosResponse } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isUndefined, toLower } from 'lodash';
|
||||
import { Post } from 'Models';
|
||||
import React, { FC, Fragment, HTMLAttributes, useState } from 'react';
|
||||
import React, { FC, Fragment, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import AppState from '../../../AppState';
|
||||
import { getUserByName } from '../../../axiosAPIs/userAPI';
|
||||
@ -36,41 +35,14 @@ import Avatar from '../../common/avatar/Avatar';
|
||||
import PopOver from '../../common/popover/PopOver';
|
||||
import RichTextEditorPreviewer from '../../common/rich-text-editor/RichTextEditorPreviewer';
|
||||
import Loader from '../../Loader/Loader';
|
||||
|
||||
interface ActivityFeedCardProp extends HTMLAttributes<HTMLDivElement> {
|
||||
feed: Post;
|
||||
entityLink?: string;
|
||||
repliedUsers?: Array<string>;
|
||||
replies?: number;
|
||||
isEntityFeed?: boolean;
|
||||
threadId?: string;
|
||||
lastReplyTimeStamp?: number;
|
||||
isFooterVisible?: boolean;
|
||||
onThreadSelect?: (id: string) => void;
|
||||
}
|
||||
interface FeedHeaderProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<ActivityFeedCardProp, 'isEntityFeed'> {
|
||||
createdBy: string;
|
||||
timeStamp: number;
|
||||
entityType: string;
|
||||
entityFQN: string;
|
||||
entityField: string;
|
||||
}
|
||||
interface FeedBodyProp extends HTMLAttributes<HTMLDivElement> {
|
||||
message: string;
|
||||
}
|
||||
interface FeedFooterProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<
|
||||
ActivityFeedCardProp,
|
||||
| 'replies'
|
||||
| 'repliedUsers'
|
||||
| 'threadId'
|
||||
| 'onThreadSelect'
|
||||
| 'lastReplyTimeStamp'
|
||||
| 'isFooterVisible'
|
||||
> {}
|
||||
import ConfirmationModal from '../../Modals/ConfirmationModal/ConfirmationModal';
|
||||
import {
|
||||
ActivityFeedCardProp,
|
||||
ConfirmState,
|
||||
FeedBodyProp,
|
||||
FeedFooterProp,
|
||||
FeedHeaderProp,
|
||||
} from './ActivityFeedCard.interface';
|
||||
|
||||
const FeedHeader: FC<FeedHeaderProp> = ({
|
||||
className,
|
||||
@ -230,15 +202,31 @@ const FeedHeader: FC<FeedHeaderProp> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const FeedBody: FC<FeedBodyProp> = ({ message, className }) => {
|
||||
const FeedBody: FC<FeedBodyProp> = ({
|
||||
message,
|
||||
className,
|
||||
threadId,
|
||||
postId,
|
||||
deletePostHandler,
|
||||
onConfirmation,
|
||||
}) => {
|
||||
return (
|
||||
<div className={className}>
|
||||
<RichTextEditorPreviewer
|
||||
className="activity-feed-card-text"
|
||||
enableSeeMoreVariant={false}
|
||||
markdown={getFrontEndFormat(message)}
|
||||
/>
|
||||
</div>
|
||||
<Fragment>
|
||||
<div className={className}>
|
||||
<RichTextEditorPreviewer
|
||||
className="activity-feed-card-text"
|
||||
enableSeeMoreVariant={false}
|
||||
markdown={getFrontEndFormat(message)}
|
||||
/>
|
||||
{threadId && postId && deletePostHandler ? (
|
||||
<span
|
||||
className="tw-opacity-0 hover:tw-opacity-100 tw-cursor-pointer"
|
||||
onClick={() => onConfirmation({ state: true, postId, threadId })}>
|
||||
<SVGIcons alt="delete" icon={Icons.DELETE} width="12px" />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@ -296,11 +284,37 @@ const ActivityFeedCard: FC<ActivityFeedCardProp> = ({
|
||||
lastReplyTimeStamp,
|
||||
onThreadSelect,
|
||||
isFooterVisible = false,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const entityType = getEntityType(entityLink as string);
|
||||
const entityFQN = getEntityFQN(entityLink as string);
|
||||
const entityField = getEntityField(entityLink as string);
|
||||
|
||||
const [confirmationState, setConfirmationState] = useState<ConfirmState>({
|
||||
state: false,
|
||||
threadId: undefined,
|
||||
postId: undefined,
|
||||
});
|
||||
|
||||
const onCancel = () => {
|
||||
setConfirmationState({
|
||||
state: false,
|
||||
threadId: undefined,
|
||||
postId: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const onDelete = () => {
|
||||
if (confirmationState.postId && confirmationState.threadId) {
|
||||
deletePostHandler?.(confirmationState.threadId, confirmationState.postId);
|
||||
}
|
||||
onCancel();
|
||||
};
|
||||
|
||||
const onConfirmation = (data: ConfirmState) => {
|
||||
setConfirmationState(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classNames(className)}>
|
||||
<FeedHeader
|
||||
@ -312,8 +326,12 @@ const ActivityFeedCard: FC<ActivityFeedCardProp> = ({
|
||||
timeStamp={feed.postTs}
|
||||
/>
|
||||
<FeedBody
|
||||
className="tw-mx-7 tw-ml-9 tw-bg-white tw-p-3 tw-border tw-border-main tw-rounded-md tw-break-all"
|
||||
className="tw-mx-7 tw-ml-9 tw-bg-white tw-p-3 tw-border tw-border-main tw-rounded-md tw-break-all tw-flex tw-justify-between "
|
||||
deletePostHandler={deletePostHandler}
|
||||
message={feed.message}
|
||||
postId={feed.id}
|
||||
threadId={threadId as string}
|
||||
onConfirmation={onConfirmation}
|
||||
/>
|
||||
<FeedFooter
|
||||
className="tw-ml-9 tw-mt-3"
|
||||
@ -324,6 +342,18 @@ const ActivityFeedCard: FC<ActivityFeedCardProp> = ({
|
||||
threadId={threadId}
|
||||
onThreadSelect={onThreadSelect}
|
||||
/>
|
||||
{confirmationState.state && (
|
||||
<ConfirmationModal
|
||||
bodyClassName="tw-h-18"
|
||||
bodyText="Are you sure you want to permanently remove this post?"
|
||||
cancelText="Cancel"
|
||||
className="tw-w-auto"
|
||||
confirmText="Delete"
|
||||
header="Delete Post?"
|
||||
onCancel={onCancel}
|
||||
onConfirm={onDelete}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2021 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 { EntityThread } from 'Models';
|
||||
import { HTMLAttributes } from 'react';
|
||||
|
||||
export interface ActivityFeedListProp extends HTMLAttributes<HTMLDivElement> {
|
||||
feedList: EntityThread[];
|
||||
withSidePanel?: boolean;
|
||||
isEntityFeed?: boolean;
|
||||
entityName?: string;
|
||||
postFeedHandler?: (value: string, id: string) => void;
|
||||
deletePostHandler?: (threadId: string, postId: string) => void;
|
||||
}
|
||||
|
||||
export interface FeedListSeparatorProp extends HTMLAttributes<HTMLDivElement> {
|
||||
relativeDay: string;
|
||||
}
|
||||
|
||||
export interface FeedListBodyProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<FeedListSeparatorProp, 'relativeDay'>,
|
||||
Pick<
|
||||
ActivityFeedListProp,
|
||||
'isEntityFeed' | 'withSidePanel' | 'deletePostHandler'
|
||||
> {
|
||||
updatedFeedList: Array<EntityThread & { relativeDay: string }>;
|
||||
selctedThreadId: string;
|
||||
onThreadIdSelect: (value: string) => void;
|
||||
onThreadIdDeselect: () => void;
|
||||
onThreadSelect: (value: string) => void;
|
||||
postFeed: (value: string) => void;
|
||||
onViewMore: () => void;
|
||||
}
|
@ -14,13 +14,7 @@
|
||||
import classNames from 'classnames';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { EntityThread } from 'Models';
|
||||
import React, {
|
||||
FC,
|
||||
Fragment,
|
||||
HTMLAttributes,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { FC, Fragment, useEffect, useState } from 'react';
|
||||
import { withLoader } from '../../../hoc/withLoader';
|
||||
import { getFeedListWithRelativeDays } from '../../../utils/FeedUtils';
|
||||
import ActivityFeedCard, {
|
||||
@ -29,30 +23,11 @@ import ActivityFeedCard, {
|
||||
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
||||
import ActivityFeedPanel from '../ActivityFeedPanel/ActivityFeedPanel';
|
||||
import NoFeedPlaceholder from '../NoFeedPlaceholder/NoFeedPlaceholder';
|
||||
|
||||
interface ActivityFeedListProp extends HTMLAttributes<HTMLDivElement> {
|
||||
feedList: EntityThread[];
|
||||
withSidePanel?: boolean;
|
||||
isEntityFeed?: boolean;
|
||||
entityName?: string;
|
||||
postFeedHandler?: (value: string, id: string) => void;
|
||||
}
|
||||
interface FeedListSeparatorProp extends HTMLAttributes<HTMLDivElement> {
|
||||
relativeDay: string;
|
||||
}
|
||||
|
||||
interface FeedListBodyProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<FeedListSeparatorProp, 'relativeDay'>,
|
||||
Pick<ActivityFeedListProp, 'isEntityFeed' | 'withSidePanel'> {
|
||||
updatedFeedList: Array<EntityThread & { relativeDay: string }>;
|
||||
selctedThreadId: string;
|
||||
onThreadIdSelect: (value: string) => void;
|
||||
onThreadIdDeselect: () => void;
|
||||
onThreadSelect: (value: string) => void;
|
||||
postFeed: (value: string) => void;
|
||||
onViewMore: () => void;
|
||||
}
|
||||
import {
|
||||
ActivityFeedListProp,
|
||||
FeedListBodyProp,
|
||||
FeedListSeparatorProp,
|
||||
} from './ActivityFeedList.interface';
|
||||
|
||||
export const FeedListSeparator: FC<FeedListSeparatorProp> = ({
|
||||
className,
|
||||
@ -81,6 +56,7 @@ const FeedListBody: FC<FeedListBodyProp> = ({
|
||||
postFeed,
|
||||
onViewMore,
|
||||
selctedThreadId,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
return (
|
||||
<Fragment>
|
||||
@ -91,6 +67,7 @@ const FeedListBody: FC<FeedListBodyProp> = ({
|
||||
message: feed.message,
|
||||
postTs: feed.threadTs,
|
||||
from: feed.createdBy,
|
||||
id: feed.id,
|
||||
};
|
||||
const postLength = feed.posts.length;
|
||||
const replies = feed.postsCount - 1;
|
||||
@ -128,8 +105,10 @@ const FeedListBody: FC<FeedListBodyProp> = ({
|
||||
) : null}
|
||||
<ActivityFeedCard
|
||||
className="tw-mb-6 tw-ml-9"
|
||||
deletePostHandler={deletePostHandler}
|
||||
feed={lastPost}
|
||||
isEntityFeed={isEntityFeed}
|
||||
threadId={feed.id}
|
||||
/>
|
||||
<p
|
||||
className="link-text tw-text-xs tw-underline tw-ml-9 tw-pl-9 tw--mt-4 tw-mb-6"
|
||||
@ -170,6 +149,7 @@ const ActivityFeedList: FC<ActivityFeedListProp> = ({
|
||||
isEntityFeed = false,
|
||||
postFeedHandler,
|
||||
entityName,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const { updatedFeedList, relativeDays } =
|
||||
getFeedListWithRelativeDays(feedList);
|
||||
@ -234,6 +214,7 @@ const ActivityFeedList: FC<ActivityFeedListProp> = ({
|
||||
relativeDay={d}
|
||||
/>
|
||||
<FeedListBody
|
||||
deletePostHandler={deletePostHandler}
|
||||
isEntityFeed={isEntityFeed}
|
||||
postFeed={postFeed}
|
||||
relativeDay={d}
|
||||
@ -251,6 +232,7 @@ const ActivityFeedList: FC<ActivityFeedListProp> = ({
|
||||
{withSidePanel && selectedThread && isPanelOpen ? (
|
||||
<Fragment>
|
||||
<ActivityFeedPanel
|
||||
deletePostHandler={deletePostHandler}
|
||||
open={!isUndefined(selectedThread) && isPanelOpen}
|
||||
postFeed={postFeed}
|
||||
selectedThread={selectedThread}
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2021 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 { EntityThread } from 'Models';
|
||||
import { HTMLAttributes } from 'react';
|
||||
|
||||
export interface ActivityFeedPanelProp extends HTMLAttributes<HTMLDivElement> {
|
||||
selectedThread: EntityThread;
|
||||
open?: boolean;
|
||||
onCancel: () => void;
|
||||
postFeed: (value: string) => void;
|
||||
deletePostHandler?: (threadId: string, postId: string) => void;
|
||||
}
|
||||
|
||||
export interface FeedPanelHeaderProp
|
||||
extends HTMLAttributes<HTMLHeadingElement>,
|
||||
Pick<ActivityFeedPanelProp, 'onCancel'> {
|
||||
entityField: string;
|
||||
noun?: string;
|
||||
onShowNewConversation?: (v: boolean) => void;
|
||||
}
|
||||
export interface FeedPanelOverlayProp
|
||||
extends HTMLAttributes<HTMLButtonElement>,
|
||||
Pick<ActivityFeedPanelProp, 'onCancel'> {}
|
||||
export interface FeedPanelBodyProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<ActivityFeedPanelProp, 'deletePostHandler'> {
|
||||
threadData: EntityThread;
|
||||
isLoading: boolean;
|
||||
}
|
@ -15,13 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { EntityThread, Post } from 'Models';
|
||||
import React, {
|
||||
FC,
|
||||
Fragment,
|
||||
HTMLAttributes,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { FC, Fragment, useEffect, useState } from 'react';
|
||||
import { getFeedById } from '../../../axiosAPIs/feedsAPI';
|
||||
import { getEntityField, getReplyText } from '../../../utils/FeedUtils';
|
||||
import { Button } from '../../buttons/Button/Button';
|
||||
@ -29,28 +23,12 @@ import PopOver from '../../common/popover/PopOver';
|
||||
import Loader from '../../Loader/Loader';
|
||||
import ActivityFeedCard from '../ActivityFeedCard/ActivityFeedCard';
|
||||
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
||||
|
||||
interface ActivityFeedPanelProp extends HTMLAttributes<HTMLDivElement> {
|
||||
selectedThread: EntityThread;
|
||||
open?: boolean;
|
||||
onCancel: () => void;
|
||||
postFeed: (value: string) => void;
|
||||
}
|
||||
|
||||
interface FeedPanelHeaderProp
|
||||
extends HTMLAttributes<HTMLHeadingElement>,
|
||||
Pick<ActivityFeedPanelProp, 'onCancel'> {
|
||||
entityField: string;
|
||||
noun?: string;
|
||||
onShowNewConversation?: (v: boolean) => void;
|
||||
}
|
||||
interface FeedPanelOverlayProp
|
||||
extends HTMLAttributes<HTMLButtonElement>,
|
||||
Pick<ActivityFeedPanelProp, 'onCancel'> {}
|
||||
interface FeedPanelBodyProp extends HTMLAttributes<HTMLDivElement> {
|
||||
threadData: EntityThread;
|
||||
isLoading: boolean;
|
||||
}
|
||||
import {
|
||||
ActivityFeedPanelProp,
|
||||
FeedPanelBodyProp,
|
||||
FeedPanelHeaderProp,
|
||||
FeedPanelOverlayProp,
|
||||
} from './ActivityFeedPanel.interface';
|
||||
|
||||
export const FeedPanelHeader: FC<FeedPanelHeaderProp> = ({
|
||||
onCancel,
|
||||
@ -118,12 +96,14 @@ const FeedPanelBody: FC<FeedPanelBodyProp> = ({
|
||||
threadData,
|
||||
className,
|
||||
isLoading,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const repliesLength = threadData?.posts?.length ?? 0;
|
||||
const mainThread = {
|
||||
message: threadData.message,
|
||||
from: threadData.createdBy,
|
||||
postTs: threadData.threadTs,
|
||||
id: threadData.id,
|
||||
};
|
||||
|
||||
return (
|
||||
@ -151,8 +131,10 @@ const FeedPanelBody: FC<FeedPanelBodyProp> = ({
|
||||
<ActivityFeedCard
|
||||
isEntityFeed
|
||||
className="tw-mb-3"
|
||||
deletePostHandler={deletePostHandler}
|
||||
feed={reply}
|
||||
key={key}
|
||||
threadId={threadData.id}
|
||||
/>
|
||||
))}
|
||||
</Fragment>
|
||||
@ -169,6 +151,7 @@ const ActivityFeedPanel: FC<ActivityFeedPanelProp> = ({
|
||||
onCancel,
|
||||
className,
|
||||
postFeed,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const [threadData, setThreadData] = useState<EntityThread>(selectedThread);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
@ -204,6 +187,7 @@ const ActivityFeedPanel: FC<ActivityFeedPanelProp> = ({
|
||||
|
||||
<FeedPanelBody
|
||||
className="tw-p-4 tw-pl-8 tw-mb-3"
|
||||
deletePostHandler={deletePostHandler}
|
||||
isLoading={isLoading}
|
||||
threadData={threadData as EntityThread}
|
||||
/>
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2021 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 { EntityThread } from 'Models';
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { CreateThread } from '../../../generated/api/feed/createThread';
|
||||
|
||||
export interface ActivityThreadPanelProp
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
threadLink: string;
|
||||
open?: boolean;
|
||||
postFeedHandler: (value: string, id: string) => void;
|
||||
onCancel: () => void;
|
||||
createThread: (data: CreateThread) => void;
|
||||
deletePostHandler?: (threadId: string, postId: string) => void;
|
||||
}
|
||||
|
||||
export interface ActivityThreadListProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<ActivityThreadPanelProp, 'deletePostHandler'> {
|
||||
threads: EntityThread[];
|
||||
selectedThreadId: string;
|
||||
postFeed: (value: string) => void;
|
||||
onThreadIdSelect: (value: string) => void;
|
||||
onThreadSelect: (value: string) => void;
|
||||
}
|
||||
export interface ActivityThreadProp
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
Pick<ActivityThreadPanelProp, 'deletePostHandler'> {
|
||||
selectedThread: EntityThread;
|
||||
postFeed: (value: string) => void;
|
||||
}
|
@ -15,16 +15,9 @@ import { AxiosResponse } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { EntityThread, Post } from 'Models';
|
||||
import React, {
|
||||
FC,
|
||||
Fragment,
|
||||
HTMLAttributes,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { FC, Fragment, useEffect, useState } from 'react';
|
||||
import AppState from '../../../AppState';
|
||||
import { getAllFeeds, getFeedById } from '../../../axiosAPIs/feedsAPI';
|
||||
import { CreateThread } from '../../../generated/api/feed/createThread';
|
||||
import {
|
||||
getEntityField,
|
||||
getFeedListWithRelativeDays,
|
||||
@ -39,26 +32,11 @@ import {
|
||||
FeedPanelHeader,
|
||||
FeedPanelOverlay,
|
||||
} from '../ActivityFeedPanel/ActivityFeedPanel';
|
||||
|
||||
interface ActivityThreadPanelProp extends HTMLAttributes<HTMLDivElement> {
|
||||
threadLink: string;
|
||||
open?: boolean;
|
||||
postFeedHandler: (value: string, id: string) => void;
|
||||
onCancel: () => void;
|
||||
createThread: (data: CreateThread) => void;
|
||||
}
|
||||
|
||||
interface ActivityThreadListProp extends HTMLAttributes<HTMLDivElement> {
|
||||
threads: EntityThread[];
|
||||
selectedThreadId: string;
|
||||
postFeed: (value: string) => void;
|
||||
onThreadIdSelect: (value: string) => void;
|
||||
onThreadSelect: (value: string) => void;
|
||||
}
|
||||
interface ActivityThreadProp extends HTMLAttributes<HTMLDivElement> {
|
||||
selectedThread: EntityThread;
|
||||
postFeed: (value: string) => void;
|
||||
}
|
||||
import {
|
||||
ActivityThreadListProp,
|
||||
ActivityThreadPanelProp,
|
||||
ActivityThreadProp,
|
||||
} from './ActivityThreadPanel.interface';
|
||||
|
||||
const ActivityThreadList: FC<ActivityThreadListProp> = ({
|
||||
className,
|
||||
@ -67,6 +45,7 @@ const ActivityThreadList: FC<ActivityThreadListProp> = ({
|
||||
postFeed,
|
||||
onThreadIdSelect,
|
||||
onThreadSelect,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const { updatedFeedList: updatedThreads, relativeDays } =
|
||||
getFeedListWithRelativeDays(threads);
|
||||
@ -87,6 +66,7 @@ const ActivityThreadList: FC<ActivityThreadListProp> = ({
|
||||
message: thread.message,
|
||||
postTs: thread.threadTs,
|
||||
from: thread.createdBy,
|
||||
id: thread.id,
|
||||
};
|
||||
const postLength = thread.posts.length;
|
||||
const replies = thread.postsCount - 1;
|
||||
@ -123,7 +103,9 @@ const ActivityThreadList: FC<ActivityThreadListProp> = ({
|
||||
<ActivityFeedCard
|
||||
isEntityFeed
|
||||
className="tw-mb-6 tw-ml-9"
|
||||
deletePostHandler={deletePostHandler}
|
||||
feed={lastPost}
|
||||
threadId={thread.id}
|
||||
/>
|
||||
<p
|
||||
className="link-text tw-text-xs tw-underline tw-ml-9 tw-pl-9 tw--mt-4 tw-mb-6"
|
||||
@ -161,6 +143,7 @@ const ActivityThread: FC<ActivityThreadProp> = ({
|
||||
className,
|
||||
selectedThread,
|
||||
postFeed,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const [threadData, setThreadData] = useState<EntityThread>(selectedThread);
|
||||
const repliesLength = threadData?.posts?.length ?? 0;
|
||||
@ -168,6 +151,7 @@ const ActivityThread: FC<ActivityThreadProp> = ({
|
||||
message: threadData.message,
|
||||
from: threadData.createdBy,
|
||||
postTs: threadData.threadTs,
|
||||
id: threadData.id,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -198,8 +182,10 @@ const ActivityThread: FC<ActivityThreadProp> = ({
|
||||
<ActivityFeedCard
|
||||
isEntityFeed
|
||||
className="tw-mb-3"
|
||||
deletePostHandler={deletePostHandler}
|
||||
feed={reply}
|
||||
key={key}
|
||||
threadId={threadData.id}
|
||||
/>
|
||||
))}
|
||||
</Fragment>
|
||||
@ -221,6 +207,7 @@ const ActivityThreadPanel: FC<ActivityThreadPanelProp> = ({
|
||||
open,
|
||||
postFeedHandler,
|
||||
createThread,
|
||||
deletePostHandler,
|
||||
}) => {
|
||||
const [threads, setThreads] = useState<EntityThread[]>([]);
|
||||
const [selectedThread, setSelectedThread] = useState<EntityThread>();
|
||||
@ -276,6 +263,13 @@ const ActivityThreadPanel: FC<ActivityThreadPanelProp> = ({
|
||||
}, 500);
|
||||
};
|
||||
|
||||
const onPostDelete = (threadId: string, postId: string) => {
|
||||
deletePostHandler?.(threadId, postId);
|
||||
setTimeout(() => {
|
||||
getThreads();
|
||||
}, 500);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const escapeKeyHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
@ -332,6 +326,7 @@ const ActivityThreadPanel: FC<ActivityThreadPanelProp> = ({
|
||||
</p>
|
||||
<ActivityThread
|
||||
className="tw-pb-6 tw-pl-5"
|
||||
deletePostHandler={onPostDelete}
|
||||
postFeed={postFeed}
|
||||
selectedThread={selectedThread}
|
||||
/>
|
||||
@ -353,6 +348,7 @@ const ActivityThreadPanel: FC<ActivityThreadPanelProp> = ({
|
||||
) : null}
|
||||
<ActivityThreadList
|
||||
className="tw-py-6 tw-pl-5"
|
||||
deletePostHandler={onPostDelete}
|
||||
postFeed={postFeed}
|
||||
selectedThreadId={selectedThreadId}
|
||||
threads={threads}
|
||||
|
@ -118,6 +118,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
qualityTestFormHandler,
|
||||
handleSelectedColumn,
|
||||
selectedColumn,
|
||||
deletePostHandler,
|
||||
}: DatasetDetailsProps) => {
|
||||
const { isAuthDisabled } = useAuthContext();
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
@ -565,6 +566,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
{threadLink ? (
|
||||
<ActivityThreadPanel
|
||||
createThread={createThread}
|
||||
deletePostHandler={deletePostHandler}
|
||||
open={Boolean(threadLink)}
|
||||
postFeedHandler={postFeedHandler}
|
||||
threadLink={threadLink}
|
||||
@ -595,6 +597,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
isLoading={isentityThreadLoading}
|
||||
|
@ -108,4 +108,5 @@ export interface DatasetDetailsProps {
|
||||
columnName: string,
|
||||
testType: ColumnTestType
|
||||
) => void;
|
||||
deletePostHandler: (threadId: string, postId: string) => void;
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ const DatasetDetailsProps = {
|
||||
handleRemoveColumnTest: jest.fn(),
|
||||
handleTestModeChange: jest.fn(),
|
||||
qualityTestFormHandler: jest.fn(),
|
||||
deletePostHandler: jest.fn(),
|
||||
};
|
||||
jest.mock('../ManageTab/ManageTab.component', () => {
|
||||
return jest.fn().mockReturnValue(<p>ManageTab</p>);
|
||||
|
@ -17,6 +17,7 @@ import React, { ReactNode } from 'react';
|
||||
import { Button } from '../../buttons/Button/Button';
|
||||
import Loader from '../../Loader/Loader';
|
||||
type Props = {
|
||||
className?: string;
|
||||
loadingState?: LoadingState;
|
||||
cancelText: string | ReactNode;
|
||||
confirmText: string | ReactNode;
|
||||
@ -43,9 +44,12 @@ const ConfirmationModal = ({
|
||||
onConfirm,
|
||||
onCancel,
|
||||
bodyText,
|
||||
className,
|
||||
}: Props) => {
|
||||
return (
|
||||
<dialog className="tw-modal" data-testid="confirmation-modal">
|
||||
<dialog
|
||||
className={classNames('tw-modal', className)}
|
||||
data-testid="confirmation-modal">
|
||||
<div className="tw-modal-backdrop" />
|
||||
<div className="tw-modal-container tw-w-120">
|
||||
<div className={classNames('tw-modal-header', headerClassName)}>
|
||||
|
@ -568,6 +568,7 @@ declare module 'Models' {
|
||||
message: string;
|
||||
postTs: number;
|
||||
from: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface EntityFieldThreadCount {
|
||||
|
@ -27,6 +27,7 @@ import React, { FunctionComponent, useEffect, useState } from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import AppState from '../../AppState';
|
||||
import {
|
||||
deletePostById,
|
||||
getAllFeeds,
|
||||
getFeedCount,
|
||||
postFeedById,
|
||||
@ -753,6 +754,30 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const deletePostHandler = (threadId: string, postId: string) => {
|
||||
deletePostById(threadId, postId)
|
||||
.then((res: AxiosResponse) => {
|
||||
if (res.data) {
|
||||
const { id } = res.data;
|
||||
setEntityThread((pre) => {
|
||||
return pre.map((thread) => {
|
||||
const posts = thread.posts.filter((post) => post.id !== id);
|
||||
|
||||
return { ...thread, posts: posts };
|
||||
});
|
||||
});
|
||||
getEntityFeedCount();
|
||||
showToast({
|
||||
variant: 'success',
|
||||
body: 'Post got deleted successfully',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showToast({ variant: 'error', body: 'Error while deleting post' });
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTableDetail();
|
||||
setActiveTab(getCurrentDatasetTab(tab));
|
||||
@ -786,6 +811,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
createThread={createThread}
|
||||
dataModel={tableDetails.dataModel}
|
||||
datasetFQN={tableFQN}
|
||||
deletePostHandler={deletePostHandler}
|
||||
deleted={deleted}
|
||||
description={description}
|
||||
descriptionUpdateHandler={descriptionUpdateHandler}
|
||||
|
@ -179,6 +179,7 @@ const TourPage = () => {
|
||||
columnsUpdateHandler={handleCountChange}
|
||||
createThread={handleCountChange}
|
||||
datasetFQN={mockDatasetData.datasetFQN}
|
||||
deletePostHandler={handleCountChange}
|
||||
description={mockDatasetData.description}
|
||||
descriptionUpdateHandler={handleCountChange}
|
||||
entityFieldThreadCount={[]}
|
||||
|
Loading…
x
Reference in New Issue
Block a user