|
|
@ -3,9 +3,7 @@ import { |
|
|
|
useEffect, |
|
|
|
useEffect, |
|
|
|
useState, |
|
|
|
useState, |
|
|
|
type MouseEvent, |
|
|
|
type MouseEvent, |
|
|
|
useMemo, |
|
|
|
|
|
|
|
useRef, |
|
|
|
useRef, |
|
|
|
type RefObject, |
|
|
|
|
|
|
|
} from 'react'; |
|
|
|
} from 'react'; |
|
|
|
import { Spinner } from '../ReactIcons/Spinner'; |
|
|
|
import { Spinner } from '../ReactIcons/Spinner'; |
|
|
|
import '../FrameRenderer/FrameRenderer.css'; |
|
|
|
import '../FrameRenderer/FrameRenderer.css'; |
|
|
@ -22,10 +20,8 @@ import { useToast } from '../../hooks/use-toast'; |
|
|
|
import { useAuth } from '../../hooks/use-auth'; |
|
|
|
import { useAuth } from '../../hooks/use-auth'; |
|
|
|
import { pageProgressMessage } from '../../stores/page'; |
|
|
|
import { pageProgressMessage } from '../../stores/page'; |
|
|
|
import type { GetRoadmapResponse } from '../CustomRoadmap/CustomRoadmap'; |
|
|
|
import type { GetRoadmapResponse } from '../CustomRoadmap/CustomRoadmap'; |
|
|
|
import { ReadonlyEditor } from '@roadmapsh/web-draw/src/editor/readonly-editor'; |
|
|
|
import { ReadonlyEditor } from '../../../editor/readonly-editor'; |
|
|
|
import type { Node } from 'reactflow'; |
|
|
|
import type { Node } from 'reactflow'; |
|
|
|
import { calculateDimensions } from '@roadmapsh/web-draw/src/editor/utils/roadmap'; |
|
|
|
|
|
|
|
import { isMobile } from '@roadmapsh/web-draw/src/editor/utils/is-mobile'; |
|
|
|
|
|
|
|
import { useKeydown } from '../../hooks/use-keydown'; |
|
|
|
import { useKeydown } from '../../hooks/use-keydown'; |
|
|
|
import { useOutsideClick } from '../../hooks/use-outside-click'; |
|
|
|
import { useOutsideClick } from '../../hooks/use-outside-click'; |
|
|
|
import { MemberProgressModalHeader } from './MemberProgressModalHeader'; |
|
|
|
import { MemberProgressModalHeader } from './MemberProgressModalHeader'; |
|
|
@ -67,17 +63,6 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
const [isLoading, setIsLoading] = useState(true); |
|
|
|
const [isLoading, setIsLoading] = useState(true); |
|
|
|
const toast = useToast(); |
|
|
|
const toast = useToast(); |
|
|
|
|
|
|
|
|
|
|
|
const initialZoom = useMemo(() => (isMobile() ? 0.35 : 0.7), []); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { measuredHeight } = useMemo( |
|
|
|
|
|
|
|
() => |
|
|
|
|
|
|
|
calculateDimensions({ |
|
|
|
|
|
|
|
nodes: roadmap?.nodes || [], |
|
|
|
|
|
|
|
padding: 100, |
|
|
|
|
|
|
|
}), |
|
|
|
|
|
|
|
[roadmap?.nodes] |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useKeydown('Escape', () => onClose()); |
|
|
|
useKeydown('Escape', () => onClose()); |
|
|
|
useOutsideClick(popupBodyEl, () => onClose()); |
|
|
|
useOutsideClick(popupBodyEl, () => onClose()); |
|
|
|
|
|
|
|
|
|
|
@ -85,12 +70,12 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
teamId: string, |
|
|
|
teamId: string, |
|
|
|
memberId: string, |
|
|
|
memberId: string, |
|
|
|
resourceType: string, |
|
|
|
resourceType: string, |
|
|
|
resourceId: string |
|
|
|
resourceId: string, |
|
|
|
) { |
|
|
|
) { |
|
|
|
const { error, response } = await httpGet<MemberProgressResponse>( |
|
|
|
const { error, response } = await httpGet<MemberProgressResponse>( |
|
|
|
`${ |
|
|
|
`${ |
|
|
|
import.meta.env.PUBLIC_API_URL |
|
|
|
import.meta.env.PUBLIC_API_URL |
|
|
|
}/v1-get-member-resource-progress/${teamId}/${memberId}?resourceType=${resourceType}&resourceId=${resourceId}` |
|
|
|
}/v1-get-member-resource-progress/${teamId}/${memberId}?resourceType=${resourceType}&resourceId=${resourceId}`,
|
|
|
|
); |
|
|
|
); |
|
|
|
if (error || !response) { |
|
|
|
if (error || !response) { |
|
|
|
toast.error(error?.message || 'Failed to get member progress'); |
|
|
|
toast.error(error?.message || 'Failed to get member progress'); |
|
|
@ -104,7 +89,7 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
|
|
|
|
|
|
|
|
async function getRoadmap() { |
|
|
|
async function getRoadmap() { |
|
|
|
const { response, error } = await httpGet<GetRoadmapResponse>( |
|
|
|
const { response, error } = await httpGet<GetRoadmapResponse>( |
|
|
|
`${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${resourceId}` |
|
|
|
`${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${resourceId}`, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (error || !response) { |
|
|
|
if (error || !response) { |
|
|
@ -149,14 +134,14 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
resourceType: resourceType as ResourceType, |
|
|
|
resourceType: resourceType as ResourceType, |
|
|
|
topicId, |
|
|
|
topicId, |
|
|
|
}, |
|
|
|
}, |
|
|
|
newStatus |
|
|
|
newStatus, |
|
|
|
) |
|
|
|
) |
|
|
|
.then(() => { |
|
|
|
.then(() => { |
|
|
|
renderTopicProgress(topicId, newStatus); |
|
|
|
renderTopicProgress(topicId, newStatus); |
|
|
|
getMemberProgress(teamId, member._id, resourceType, resourceId).then( |
|
|
|
getMemberProgress(teamId, member._id, resourceType, resourceId).then( |
|
|
|
(data) => { |
|
|
|
(data) => { |
|
|
|
setMemberProgress(data); |
|
|
|
setMemberProgress(data); |
|
|
|
} |
|
|
|
}, |
|
|
|
); |
|
|
|
); |
|
|
|
}) |
|
|
|
}) |
|
|
|
.catch((err) => { |
|
|
|
.catch((err) => { |
|
|
@ -197,7 +182,7 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
const isCurrentStatusLearning = target?.classList.contains('learning'); |
|
|
|
const isCurrentStatusLearning = target?.classList.contains('learning'); |
|
|
|
updateTopicStatus( |
|
|
|
updateTopicStatus( |
|
|
|
node.id, |
|
|
|
node.id, |
|
|
|
isCurrentStatusLearning ? 'pending' : 'learning' |
|
|
|
isCurrentStatusLearning ? 'pending' : 'learning', |
|
|
|
); |
|
|
|
); |
|
|
|
}, []); |
|
|
|
}, []); |
|
|
|
|
|
|
|
|
|
|
@ -250,13 +235,8 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
{!isLoading && roadmap && ( |
|
|
|
{!isLoading && roadmap && ( |
|
|
|
<div className="px-4 pb-2"> |
|
|
|
<div className="px-4 pb-2"> |
|
|
|
<ReadonlyEditor |
|
|
|
<ReadonlyEditor |
|
|
|
|
|
|
|
variant="modal" |
|
|
|
roadmap={roadmap!} |
|
|
|
roadmap={roadmap!} |
|
|
|
style={{ |
|
|
|
|
|
|
|
height: measuredHeight * initialZoom, |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
zoom={{ |
|
|
|
|
|
|
|
initial: initialZoom, |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
className="min-h-[400px]" |
|
|
|
className="min-h-[400px]" |
|
|
|
onRendered={() => { |
|
|
|
onRendered={() => { |
|
|
|
const { |
|
|
|
const { |
|
|
@ -268,13 +248,13 @@ export function MemberCustomProgressModal(props: ProgressMapProps) { |
|
|
|
|
|
|
|
|
|
|
|
done.forEach((id: string) => renderTopicProgress(id, 'done')); |
|
|
|
done.forEach((id: string) => renderTopicProgress(id, 'done')); |
|
|
|
learning.forEach((id: string) => |
|
|
|
learning.forEach((id: string) => |
|
|
|
renderTopicProgress(id, 'learning') |
|
|
|
renderTopicProgress(id, 'learning'), |
|
|
|
); |
|
|
|
); |
|
|
|
skipped.forEach((id: string) => |
|
|
|
skipped.forEach((id: string) => |
|
|
|
renderTopicProgress(id, 'skipped') |
|
|
|
renderTopicProgress(id, 'skipped'), |
|
|
|
); |
|
|
|
); |
|
|
|
removed.forEach((id: string) => |
|
|
|
removed.forEach((id: string) => |
|
|
|
renderTopicProgress(id, 'removed') |
|
|
|
renderTopicProgress(id, 'removed'), |
|
|
|
); |
|
|
|
); |
|
|
|
}} |
|
|
|
}} |
|
|
|
onTopicRightClick={handleTopicRightClick} |
|
|
|
onTopicRightClick={handleTopicRightClick} |
|
|
|