import React, { useState, useEffect, useCallback, useMemo, } from 'react'; import type { IRevisionOnConflict } from '@growi/core'; import { MergeViewer, CodeMirrorEditorDiff, GlobalCodeMirrorEditorKey, useCodeMirrorEditorIsolated, } from '@growi/editor'; import { UserPicture } from '@growi/ui/dist/components'; import { format } from 'date-fns'; import { useTranslation } from 'next-i18next'; import { Modal, ModalHeader, ModalBody, ModalFooter, } from 'reactstrap'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { useCurrentPathname, useCurrentUser } from '~/stores/context'; import { useConflictDiffModal } from '~/stores/modal'; import { useCurrentPagePath, useSWRxCurrentPage, useCurrentPageId } from '~/stores/page'; import { useRemoteRevisionBody, useRemoteRevisionId, useRemoteRevisionLastUpdatedAt, useRemoteRevisionLastUpdateUser, useSetRemoteLatestPageData, } from '~/stores/remote-latest-page'; import styles from './ConflictDiffModal.module.scss'; type ConflictDiffModalCoreProps = { isOpen?: boolean; onClose?: (() => void); // optionsToSave: OptionsToSave | undefined; request: IRevisionOnConflictWithStringDate, latest: IRevisionOnConflictWithStringDate, // afterResolvedHandler: () => void, }; type IRevisionOnConflictWithStringDate = Omit & { createdAt: string } const ConflictDiffModalCore = (props: ConflictDiffModalCoreProps): JSX.Element => { const { onClose, request, latest, } = props; const [resolvedRevision, setResolvedRevision] = useState(''); const [isRevisionselected, setIsRevisionSelected] = useState(false); const [revisionSelectedToggler, setRevisionSelectedToggler] = useState(false); const [isModalExpanded, setIsModalExpanded] = useState(false); const { t } = useTranslation(); const { data: conflictDiffModalStatus, close: closeConflictDiffModal } = useConflictDiffModal(); const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.DIFF); // const [codeMirrorRef, setCodeMirrorRef] = useState(null); // const { data: remoteRevisionId } = useRemoteRevisionId(); // const { setRemoteLatestPageData } = useSetRemoteLatestPageData(); // const { data: pageId } = useCurrentPageId(); // const { data: currentPagePath } = useCurrentPagePath(); // const { data: currentPathname } = useCurrentPathname(); const revisionSelectHandler = useCallback((selectedRevision: string) => { setResolvedRevision(selectedRevision); // Enable selecting the same revision after editing by including revisionSelectedToggler in the dependency array of useEffect setRevisionSelectedToggler(prev => !prev); if (!isRevisionselected) { setIsRevisionSelected(true); } }, [isRevisionselected]); const closeModal = useCallback(() => { onClose?.(); closeConflictDiffModal(); }, [closeConflictDiffModal, onClose]); const headerButtons = useMemo(() => (
), [closeModal, isModalExpanded]); useEffect(() => { codeMirrorEditor?.initDoc(resolvedRevision); }, [codeMirrorEditor, resolvedRevision, revisionSelectedToggler]); return ( error{t('modal_resolve_conflict.resolve_conflict')}

{t('modal_resolve_conflict.resolve_conflict_message')}

{t('modal_resolve_conflict.requested_revision')}

updated by {request.user.username}

{request.createdAt}

{t('modal_resolve_conflict.latest_revision')}

updated by {latest.user.username}

{latest.createdAt}

{t('modal_resolve_conflict.selected_editable_revision')}

); }; type ConflictDiffModalProps = { isOpen?: boolean; onClose?: (() => void); markdownOnEdit: string; // optionsToSave: OptionsToSave | undefined; // afterResolvedHandler: () => void, }; export const ConflictDiffModal = (props: ConflictDiffModalProps): JSX.Element => { const { isOpen, onClose, markdownOnEdit, } = props; const { data: currentUser } = useCurrentUser(); // state for current page const { data: currentPage } = useSWRxCurrentPage(); // state for latest page const { data: remoteRevisionId } = useRemoteRevisionId(); const { data: remoteRevisionBody } = useRemoteRevisionBody(); const { data: remoteRevisionLastUpdateUser } = useRemoteRevisionLastUpdateUser(); const { data: remoteRevisionLastUpdatedAt } = useRemoteRevisionLastUpdatedAt(); const currentTime: Date = new Date(); const isRemotePageDataInappropriate = remoteRevisionId == null || remoteRevisionBody == null || remoteRevisionLastUpdateUser == null; if (!isOpen || currentUser == null || currentPage == null) { return <>; } const request: IRevisionOnConflictWithStringDate = { revisionId: '', revisionBody: markdownOnEdit, createdAt: format(currentTime, 'yyyy/MM/dd HH:mm:ss'), user: currentUser, }; const latest: IRevisionOnConflictWithStringDate = { revisionId: '', revisionBody: markdownOnEdit, createdAt: format(currentTime, 'yyyy/MM/dd HH:mm:ss'), user: currentUser, }; // const latest: IRevisionOnConflictWithStringDate = { // revisionId: remoteRevisionId, // revisionBody: remoteRevisionBody, // createdAt: format(new Date(remoteRevisionLastUpdatedAt || currentTime.toString()), 'yyyy/MM/dd HH:mm:ss'), // user: remoteRevisionLastUpdateUser, // }; const propsForCore = { isOpen, onClose, request, latest, }; return ; };