fix: Collab feedback fixes (#7298)
* hide the widget names * blocking multiselect in comment mode * wrapped the name * the latest comment will be on top * isolated a condition for selection canvas * added unresolve tooltip * added resolved thread tooltip * updated sorted comment cards when user gets the update/insert/delete events
This commit is contained in:
parent
594e0ef2e1
commit
3c0b33763e
|
|
@ -10,6 +10,8 @@ import {
|
||||||
getCommentThreadsFetched,
|
getCommentThreadsFetched,
|
||||||
getSortedAndFilteredAppCommentThreadIds,
|
getSortedAndFilteredAppCommentThreadIds,
|
||||||
shouldShowResolved as shouldShowResolvedSelector,
|
shouldShowResolved as shouldShowResolvedSelector,
|
||||||
|
getLastUpdatedCommentThreadId,
|
||||||
|
getUnreadCommentsCount,
|
||||||
} from "selectors/commentsSelectors";
|
} from "selectors/commentsSelectors";
|
||||||
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
||||||
|
|
||||||
|
|
@ -38,6 +40,8 @@ export const useSortedCommentThreadIds = (commentThreadIds: string[]) => {
|
||||||
|
|
||||||
const currentUser = useSelector(getCurrentUser);
|
const currentUser = useSelector(getCurrentUser);
|
||||||
const currentUsername = currentUser?.username;
|
const currentUsername = currentUser?.username;
|
||||||
|
const unreadCommentsCount = useSelector(getUnreadCommentsCount);
|
||||||
|
const lastUpdatedCommentThreadId = useSelector(getLastUpdatedCommentThreadId);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|
@ -54,6 +58,8 @@ export const useSortedCommentThreadIds = (commentThreadIds: string[]) => {
|
||||||
shouldShowResolved,
|
shouldShowResolved,
|
||||||
appCommentsFilter,
|
appCommentsFilter,
|
||||||
currentUsername,
|
currentUsername,
|
||||||
|
lastUpdatedCommentThreadId,
|
||||||
|
unreadCommentsCount,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,13 @@ const UserName = styled.span`
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1; /* number of lines to show */
|
-webkit-line-clamp: 1; /* number of lines to show */
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
word-break: break-word;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const HeaderSection = styled.div`
|
const HeaderSection = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
& ${Profile} {
|
& ${Profile} {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@ import styled, { withTheme } from "styled-components";
|
||||||
import Icon, { IconSize } from "components/ads/Icon";
|
import Icon, { IconSize } from "components/ads/Icon";
|
||||||
import { Theme } from "constants/DefaultTheme";
|
import { Theme } from "constants/DefaultTheme";
|
||||||
import Tooltip from "components/ads/Tooltip";
|
import Tooltip from "components/ads/Tooltip";
|
||||||
import { createMessage, RESOLVE_THREAD } from "constants/messages";
|
import {
|
||||||
|
createMessage,
|
||||||
|
RESOLVE_THREAD,
|
||||||
|
RESOLVED_THREAD,
|
||||||
|
} from "constants/messages";
|
||||||
import { Colors } from "constants/Colors";
|
import { Colors } from "constants/Colors";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
|
|
@ -64,7 +68,10 @@ const ResolveCommentButton = withTheme(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container onClick={_handleClick}>
|
<Container onClick={_handleClick}>
|
||||||
<Tooltip content={createMessage(RESOLVE_THREAD)} hoverOpenDelay={1000}>
|
<Tooltip
|
||||||
|
content={createMessage(resolved ? RESOLVED_THREAD : RESOLVE_THREAD)}
|
||||||
|
hoverOpenDelay={1000}
|
||||||
|
>
|
||||||
<StyledResolveIcon
|
<StyledResolveIcon
|
||||||
fillColor={fillColor}
|
fillColor={fillColor}
|
||||||
keepColors
|
keepColors
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ const WidgetTypes = WidgetFactory.widgetTypes;
|
||||||
import { snipingModeSelector } from "selectors/editorSelectors";
|
import { snipingModeSelector } from "selectors/editorSelectors";
|
||||||
import { bindDataToWidget } from "../../../actions/propertyPaneActions";
|
import { bindDataToWidget } from "../../../actions/propertyPaneActions";
|
||||||
import { hideErrors } from "selectors/debuggerSelectors";
|
import { hideErrors } from "selectors/debuggerSelectors";
|
||||||
|
import { commentModeSelector } from "../../../selectors/commentsSelectors";
|
||||||
|
|
||||||
const PositionStyle = styled.div<{ topRow: number; isSnipingMode: boolean }>`
|
const PositionStyle = styled.div<{ topRow: number; isSnipingMode: boolean }>`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -57,6 +58,7 @@ type WidgetNameComponentProps = {
|
||||||
export function WidgetNameComponent(props: WidgetNameComponentProps) {
|
export function WidgetNameComponent(props: WidgetNameComponentProps) {
|
||||||
const showPropertyPane = useShowPropertyPane();
|
const showPropertyPane = useShowPropertyPane();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const isCommentMode = useSelector(commentModeSelector);
|
||||||
const isSnipingMode = useSelector(snipingModeSelector);
|
const isSnipingMode = useSelector(snipingModeSelector);
|
||||||
const showTableFilterPane = useShowTableFilterPane();
|
const showTableFilterPane = useShowTableFilterPane();
|
||||||
// Dispatch hook handy to set a widget as focused/selected
|
// Dispatch hook handy to set a widget as focused/selected
|
||||||
|
|
@ -132,6 +134,7 @@ export function WidgetNameComponent(props: WidgetNameComponentProps) {
|
||||||
selectedWidgets.includes(props.widgetId);
|
selectedWidgets.includes(props.widgetId);
|
||||||
const shouldShowWidgetName = () => {
|
const shouldShowWidgetName = () => {
|
||||||
return (
|
return (
|
||||||
|
!isCommentMode &&
|
||||||
!isMultiSelectedWidget &&
|
!isMultiSelectedWidget &&
|
||||||
(isSnipingMode
|
(isSnipingMode
|
||||||
? focusedWidget === props.widgetId
|
? focusedWidget === props.widgetId
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,7 @@ export const DOWNLOAD_FILE_NAME_ERROR = () => "File name was not provided";
|
||||||
export const MORE_OPTIONS = () => "More Options";
|
export const MORE_OPTIONS = () => "More Options";
|
||||||
export const ADD_REACTION = () => "Add Reaction";
|
export const ADD_REACTION = () => "Add Reaction";
|
||||||
export const RESOLVE_THREAD = () => "Resolve Thread";
|
export const RESOLVE_THREAD = () => "Resolve Thread";
|
||||||
|
export const RESOLVED_THREAD = () => "Resolved Thread";
|
||||||
export const EMOJI = () => "Emoji";
|
export const EMOJI = () => "Emoji";
|
||||||
|
|
||||||
// Sniping mode messages
|
// Sniping mode messages
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import { useWidgetSelection } from "utils/hooks/useWidgetSelection";
|
||||||
import WidgetFactory from "utils/WidgetFactory";
|
import WidgetFactory from "utils/WidgetFactory";
|
||||||
import { AppState } from "reducers";
|
import { AppState } from "reducers";
|
||||||
import { useWidgetDragResize } from "utils/hooks/dragResizeHooks";
|
import { useWidgetDragResize } from "utils/hooks/dragResizeHooks";
|
||||||
|
import { commentModeSelector } from "selectors/commentsSelectors";
|
||||||
|
|
||||||
const WidgetTypes = WidgetFactory.widgetTypes;
|
const WidgetTypes = WidgetFactory.widgetTypes;
|
||||||
const StyledSelectionBox = styled.div`
|
const StyledSelectionBox = styled.div`
|
||||||
|
|
@ -171,6 +172,7 @@ function WidgetsMultiSelectBox(props: {
|
||||||
snapRowSpace: number;
|
snapRowSpace: number;
|
||||||
}): any {
|
}): any {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const isCommentMode = useSelector(commentModeSelector);
|
||||||
const canvasWidgets = useSelector(getCanvasWidgets);
|
const canvasWidgets = useSelector(getCanvasWidgets);
|
||||||
const selectedWidgetIDs = useSelector(getSelectedWidgets);
|
const selectedWidgetIDs = useSelector(getSelectedWidgets);
|
||||||
const selectedWidgets = selectedWidgetIDs.map(
|
const selectedWidgets = selectedWidgetIDs.map(
|
||||||
|
|
@ -188,7 +190,7 @@ function WidgetsMultiSelectBox(props: {
|
||||||
* 3. multiple widgets are selected
|
* 3. multiple widgets are selected
|
||||||
*/
|
*/
|
||||||
const shouldRender = useMemo(() => {
|
const shouldRender = useMemo(() => {
|
||||||
if (isDragging) {
|
if (isDragging || isCommentMode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const parentIDs = selectedWidgets
|
const parentIDs = selectedWidgets
|
||||||
|
|
@ -203,7 +205,7 @@ function WidgetsMultiSelectBox(props: {
|
||||||
hasCommonParent &&
|
hasCommonParent &&
|
||||||
get(selectedWidgets, "0.parentId") === props.widgetId
|
get(selectedWidgets, "0.parentId") === props.widgetId
|
||||||
);
|
);
|
||||||
}, [selectedWidgets, isDragging]);
|
}, [selectedWidgets, isDragging, isCommentMode]);
|
||||||
const draggableRef = useRef<HTMLDivElement>(null);
|
const draggableRef = useRef<HTMLDivElement>(null);
|
||||||
const { setDraggingState } = useWidgetDragResize();
|
const { setDraggingState } = useWidgetDragResize();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import { useCanvasDragToScroll } from "utils/hooks/useCanvasDragToScroll";
|
||||||
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
||||||
import { XYCord } from "utils/hooks/useCanvasDragging";
|
import { XYCord } from "utils/hooks/useCanvasDragging";
|
||||||
import { theme } from "constants/DefaultTheme";
|
import { theme } from "constants/DefaultTheme";
|
||||||
|
import { commentModeSelector } from "../../selectors/commentsSelectors";
|
||||||
|
|
||||||
const StyledSelectionCanvas = styled.canvas`
|
const StyledSelectionCanvas = styled.canvas`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -56,6 +57,7 @@ export function CanvasSelectionArena({
|
||||||
snapRowSpace: number;
|
snapRowSpace: number;
|
||||||
}) {
|
}) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const isCommentMode = useSelector(commentModeSelector);
|
||||||
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||||
const parentWidget = useSelector((state: AppState) =>
|
const parentWidget = useSelector((state: AppState) =>
|
||||||
getWidget(state, parentId || ""),
|
getWidget(state, parentId || ""),
|
||||||
|
|
@ -439,7 +441,10 @@ export function CanvasSelectionArena({
|
||||||
snapRowSpace,
|
snapRowSpace,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return appMode === APP_MODE.EDIT && !(isDragging || isResizing) ? (
|
const shouldShow =
|
||||||
|
appMode === APP_MODE.EDIT && !(isDragging || isResizing || isCommentMode);
|
||||||
|
|
||||||
|
return shouldShow ? (
|
||||||
<StyledSelectionCanvas
|
<StyledSelectionCanvas
|
||||||
data-testid={`canvas-${widgetId}`}
|
data-testid={`canvas-${widgetId}`}
|
||||||
id={`canvas-${widgetId}`}
|
id={`canvas-${widgetId}`}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ const initialState: CommentsReduxState = {
|
||||||
draftComments: {},
|
draftComments: {},
|
||||||
unpublishedThreadDraftComment: null,
|
unpublishedThreadDraftComment: null,
|
||||||
commentThreadsFetched: false,
|
commentThreadsFetched: false,
|
||||||
|
lastUpdatedCommentThreadId: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const handleUpdateCommentThreadEvent = (
|
||||||
applicationId,
|
applicationId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return { ...updatedState };
|
return { ...updatedState, lastUpdatedCommentThreadId: commentThreadId };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handleUpdateCommentThreadEvent;
|
export default handleUpdateCommentThreadEvent;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ const handleNewCommentThreadEvent = (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
lastUpdatedCommentThreadId: thread.id,
|
||||||
showUnreadIndicator,
|
showUnreadIndicator,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ const handleUpdateCommentThreadEvent = (
|
||||||
|
|
||||||
const showUnreadIndicator = !state.isCommentMode;
|
const showUnreadIndicator = !state.isCommentMode;
|
||||||
|
|
||||||
return { ...state, showUnreadIndicator };
|
return { ...state, showUnreadIndicator, lastUpdatedCommentThreadId: id };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handleUpdateCommentThreadEvent;
|
export default handleUpdateCommentThreadEvent;
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,5 @@ export interface CommentsReduxState {
|
||||||
unpublishedThreadDraftComment: EditorState | null;
|
unpublishedThreadDraftComment: EditorState | null;
|
||||||
draftComments: Record<string, EditorState>;
|
draftComments: Record<string, EditorState>;
|
||||||
commentThreadsFetched: boolean;
|
commentThreadsFetched: boolean;
|
||||||
|
lastUpdatedCommentThreadId: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,18 +99,20 @@ export const getSortedAndFilteredAppCommentThreadIds = (
|
||||||
if (!commentThreadsMap[a] || !commentThreadsMap[b]) return -1;
|
if (!commentThreadsMap[a] || !commentThreadsMap[b]) return -1;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
isViewed: isAViewed,
|
||||||
pinnedState: isAPinned,
|
pinnedState: isAPinned,
|
||||||
updationTime: updationTimeA,
|
updationTime: updationTimeA,
|
||||||
} = commentThreadsMap[a];
|
} = commentThreadsMap[a];
|
||||||
const {
|
const {
|
||||||
|
isViewed: isBViewed,
|
||||||
pinnedState: isBPinned,
|
pinnedState: isBPinned,
|
||||||
updationTime: updationTimeB,
|
updationTime: updationTimeB,
|
||||||
} = commentThreadsMap[b];
|
} = commentThreadsMap[b];
|
||||||
|
|
||||||
const sortIdx = getSortIndexBool(
|
let sortIdx = getSortIndexBool(!!isAPinned?.active, !!isBPinned?.active);
|
||||||
!!isAPinned?.active,
|
if (sortIdx !== 0) return sortIdx;
|
||||||
!!isBPinned?.active,
|
|
||||||
);
|
sortIdx = getSortIndexBool(!!isBViewed, !!isAViewed);
|
||||||
if (sortIdx !== 0) return sortIdx;
|
if (sortIdx !== 0) return sortIdx;
|
||||||
|
|
||||||
const result = getSortIndexTime(updationTimeA, updationTimeB);
|
const result = getSortIndexTime(updationTimeA, updationTimeB);
|
||||||
|
|
@ -145,6 +147,11 @@ export const getSortedAndFilteredAppCommentThreadIds = (
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
export const getUnreadCommentsCount = (state: AppState) =>
|
||||||
|
state.ui.comments.unreadCommentThreadsCount;
|
||||||
|
|
||||||
|
export const getLastUpdatedCommentThreadId = (state: AppState) =>
|
||||||
|
state.ui.comments.lastUpdatedCommentThreadId;
|
||||||
|
|
||||||
export const shouldShowResolved = (state: AppState) =>
|
export const shouldShowResolved = (state: AppState) =>
|
||||||
state.ui.comments.shouldShowResolvedAppCommentThreads;
|
state.ui.comments.shouldShowResolvedAppCommentThreads;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user