Refactor Readonly editor

feat/readonly-editor
Arik Chakma 1 year ago
parent aa2bb3484b
commit 7aba00b372
  1. 2
      .gitignore
  2. 28
      src/components/CustomRoadmap/FlowRoadmapRenderer.tsx
  3. 42
      src/components/TeamProgress/MemberCustomProgressModal.tsx
  4. 34
      src/components/UserProgress/UserCustomProgressModal.tsx

2
.gitignore vendored

@ -28,3 +28,5 @@ pnpm-debug.log*
/playwright/.cache/ /playwright/.cache/
tests-examples tests-examples
*.csv *.csv
/editor/*

@ -1,4 +1,4 @@
import { ReadonlyEditor } from '@roadmapsh/web-draw/src/editor/readonly-editor'; import { ReadonlyEditor } from '../../../editor/readonly-editor';
import type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal'; import type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';
import { import {
renderResourceProgress, renderResourceProgress,
@ -11,12 +11,6 @@ import { pageProgressMessage } from '../../stores/page';
import { useToast } from '../../hooks/use-toast'; import { useToast } from '../../hooks/use-toast';
import type { Node } from 'reactflow'; import type { Node } from 'reactflow';
import { useCallback, type MouseEvent, useMemo, useState, useRef } from 'react'; import { useCallback, type MouseEvent, useMemo, useState, useRef } from 'react';
import {
INITIAL_DESKTOP_ZOOM,
INITIAL_MOBILE_ZOOM,
calculateDimensions,
} from '@roadmapsh/web-draw/src/editor/utils/roadmap';
import { isMobile } from '@roadmapsh/web-draw/src/editor/utils/is-mobile';
import { EmptyRoadmap } from './EmptyRoadmap'; import { EmptyRoadmap } from './EmptyRoadmap';
import { cn } from '../../lib/classname'; import { cn } from '../../lib/classname';
@ -31,20 +25,7 @@ export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) {
const [hideRenderer, setHideRenderer] = useState(false); const [hideRenderer, setHideRenderer] = useState(false);
const editorWrapperRef = useRef<HTMLDivElement>(null); const editorWrapperRef = useRef<HTMLDivElement>(null);
const initialZoom = useMemo(
() => (isMobile() ? INITIAL_MOBILE_ZOOM : INITIAL_DESKTOP_ZOOM),
[],
);
const toast = useToast(); const toast = useToast();
const { measuredHeight } = useMemo(
() =>
calculateDimensions({
nodes: roadmap?.nodes,
padding: 100,
}),
[roadmap?.nodes],
);
async function updateTopicStatus( async function updateTopicStatus(
topicId: string, topicId: string,
@ -150,15 +131,10 @@ export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) {
<ReadonlyEditor <ReadonlyEditor
ref={editorWrapperRef} ref={editorWrapperRef}
roadmap={roadmap} roadmap={roadmap}
style={{
height: measuredHeight * initialZoom,
}}
className={cn( className={cn(
roadmap?.nodes?.length === 0 roadmap?.nodes?.length === 0
? 'grow' ? 'grow'
: isMobile() : 'min-h-0 max-md:min-h-[1000px]',
? 'min-h-0'
: 'min-h-[1000px]',
)} )}
onRendered={() => { onRendered={() => {
renderResourceProgress('roadmap', roadmapId).then(() => { renderResourceProgress('roadmap', roadmapId).then(() => {

@ -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}

@ -8,9 +8,7 @@ import CloseIcon from '../../icons/close.svg';
import { deleteUrlParam, getUrlParams } from '../../lib/browser'; import { deleteUrlParam, getUrlParams } from '../../lib/browser';
import { useAuth } from '../../hooks/use-auth'; import { useAuth } from '../../hooks/use-auth';
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 { isMobile } from '@roadmapsh/web-draw/src/editor/utils/is-mobile';
import { calculateDimensions } from '@roadmapsh/web-draw/src/editor/utils/roadmap';
import { ProgressLoadingError } from './ProgressLoadingError'; import { ProgressLoadingError } from './ProgressLoadingError';
import { UserProgressModalHeader } from './UserProgressModalHeader'; import { UserProgressModalHeader } from './UserProgressModalHeader';
@ -61,26 +59,15 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(''); const [error, setError] = useState('');
const initialZoom = useMemo(() => (isMobile() ? 0.35 : 0.7), []);
const { measuredHeight } = useMemo(
() =>
calculateDimensions({
nodes: roadmap?.nodes || [],
padding: 100,
}),
[roadmap?.nodes]
);
async function getUserProgress( async function getUserProgress(
userId: string, userId: string,
resourceType: string, resourceType: string,
resourceId: string resourceId: string,
): Promise<UserProgressResponse | undefined> { ): Promise<UserProgressResponse | undefined> {
const { error, response } = await httpGet<UserProgressResponse>( const { error, response } = await httpGet<UserProgressResponse>(
`${ `${
import.meta.env.PUBLIC_API_URL import.meta.env.PUBLIC_API_URL
}/v1-get-user-progress/${userId}?resourceType=${resourceType}&resourceId=${resourceId}` }/v1-get-user-progress/${userId}?resourceType=${resourceType}&resourceId=${resourceId}`,
); );
if (error || !response) { if (error || !response) {
@ -92,7 +79,7 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
async function getRoadmapSVG(): Promise<GetRoadmapResponse> { async function getRoadmapSVG(): Promise<GetRoadmapResponse> {
const { error, response: roadmapData } = await httpGet<GetRoadmapResponse>( const { error, response: roadmapData } = 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 || !roadmapData) { if (error || !roadmapData) {
throw error || new Error('Something went wrong. Please try again!'); throw error || new Error('Something went wrong. Please try again!');
@ -177,13 +164,8 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
<div ref={resourceSvgEl} className="px-4 pb-2"> <div ref={resourceSvgEl} 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={(wrapperRef: RefObject<HTMLDivElement>) => { onRendered={(wrapperRef: RefObject<HTMLDivElement>) => {
const { const {
@ -196,7 +178,7 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
topicSelectorAll(topicId, wrapperRef?.current!).forEach( topicSelectorAll(topicId, wrapperRef?.current!).forEach(
(el) => { (el) => {
el.classList.add('done'); el.classList.add('done');
} },
); );
}); });
@ -204,7 +186,7 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
topicSelectorAll(topicId, wrapperRef?.current!).forEach( topicSelectorAll(topicId, wrapperRef?.current!).forEach(
(el) => { (el) => {
el.classList.add('learning'); el.classList.add('learning');
} },
); );
}); });
@ -212,7 +194,7 @@ export function UserCustomProgressModal(props: ProgressMapProps) {
topicSelectorAll(topicId, wrapperRef?.current!).forEach( topicSelectorAll(topicId, wrapperRef?.current!).forEach(
(el) => { (el) => {
el.classList.add('skipped'); el.classList.add('skipped');
} },
); );
}); });
}} }}

Loading…
Cancel
Save