Skip to content

Commit 9ae12db

Browse files
committed
wip
1 parent 6bfc571 commit 9ae12db

File tree

4 files changed

+139
-224
lines changed

4 files changed

+139
-224
lines changed

packages/compass-components/src/hooks/use-confirmation.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,28 @@ export const ConfirmationModalArea: React.FC = ({ children }) => {
100100
});
101101
const callbackRef = useRef<ConfirmationCallback>();
102102

103+
const listenerRef =
104+
useRef<(event: CustomEvent<ShowConfirmationEventDetail>) => void>();
105+
103106
const contextValue = React.useMemo(
104-
() => ({ showConfirmation, isMounted: true }),
107+
() => ({
108+
showConfirmation: (props: ConfirmationProperties) => {
109+
return new Promise((resolve, reject) => {
110+
const event = new CustomEvent<ShowConfirmationEventDetail>(
111+
'show-confirmation',
112+
{
113+
detail: {
114+
props: { ...props, confirmationId: ++confirmationId },
115+
resolve,
116+
reject,
117+
},
118+
}
119+
);
120+
listenerRef.current?.(event);
121+
});
122+
},
123+
isMounted: true,
124+
}),
105125
[]
106126
);
107127

@@ -127,6 +147,7 @@ export const ConfirmationModalArea: React.FC = ({ children }) => {
127147
};
128148
props.signal?.addEventListener('abort', onAbort);
129149
};
150+
listenerRef.current = listener;
130151
globalConfirmation.addEventListener('show-confirmation', listener);
131152
return () => {
132153
globalConfirmation.removeEventListener('show-confirmation', listener);
Lines changed: 30 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,33 @@
1-
import React, { useContext, useEffect, useState } from 'react';
2-
import {
3-
ErrorDetailsModal,
4-
type ErrorDetailsModalProps,
5-
} from '../components/modals/error-details-modal';
6-
7-
type ErrorDetailsOptions = Omit<ErrorDetailsModalProps, 'onClose'>;
8-
9-
interface ErrorDetailsModalContextData {
10-
showErrorDetails: (props: ErrorDetailsOptions) => void;
11-
isMounted: boolean;
12-
}
13-
14-
let errorDetailsId = 0;
15-
16-
interface ErrorDetailsEventMap {
17-
'show-error-details': CustomEvent<ErrorDetailsOptions>;
18-
}
19-
20-
interface GlobalErrorDetails extends EventTarget {
21-
addEventListener<K extends keyof ErrorDetailsEventMap>(
22-
type: K,
23-
listener: (this: GlobalErrorDetails, ev: ErrorDetailsEventMap[K]) => void
24-
): void;
25-
addEventListener(
26-
type: string,
27-
listener: EventListenerOrEventListenerObject
28-
): void;
29-
removeEventListener<K extends keyof ErrorDetailsEventMap>(
30-
type: K,
31-
listener: (this: GlobalErrorDetails, ev: ErrorDetailsEventMap[K]) => void
32-
): void;
33-
removeEventListener(
34-
type: string,
35-
listener: EventListenerOrEventListenerObject
36-
): void;
37-
}
38-
39-
type ShowErrorDetailsEventDetail = ErrorDetailsOptions & {
40-
errorDetailsId: number;
41-
};
42-
43-
class GlobalErrorDetails extends EventTarget {
44-
showErrorDetails(props: ErrorDetailsOptions) {
45-
this.dispatchEvent(
46-
new CustomEvent<ShowErrorDetailsEventDetail>('show-error-details', {
47-
detail: {
48-
...props,
49-
errorDetailsId: ++errorDetailsId,
50-
},
51-
})
52-
);
53-
}
54-
}
55-
const globalErrorDetails = new GlobalErrorDetails();
56-
57-
export const showErrorDetails =
58-
globalErrorDetails.showErrorDetails.bind(globalErrorDetails);
59-
60-
const ErrorDetailsModalContext =
61-
React.createContext<ErrorDetailsModalContextData>({
62-
isMounted: false,
63-
showErrorDetails,
64-
});
65-
66-
type ErrorDetailsModalAreaProps = Partial<ShowErrorDetailsEventDetail> & {
67-
open: boolean;
68-
};
69-
70-
export const ErrorDetailsModalArea: React.FC = ({ children }) => {
71-
const hasParentContext = useContext(ErrorDetailsModalContext).isMounted;
72-
73-
const [errorDetailsProps, setErrorDetailsProps] =
74-
useState<ErrorDetailsModalAreaProps>({
75-
open: false,
76-
errorDetailsId: -1,
1+
import { useConfirmationModal } from './use-confirmation';
2+
import { Code } from '../components/leafygreen';
3+
import React from 'react';
4+
5+
export function useErrorDetailsModal() {
6+
const { showConfirmation } = useConfirmationModal();
7+
8+
const showErrorDetails = ({
9+
details,
10+
closeAction,
11+
}: {
12+
details: Record<string, unknown>;
13+
closeAction: 'back' | 'close';
14+
}) =>
15+
showConfirmation({
16+
title: 'Error details',
17+
description: (
18+
<Code
19+
language="json"
20+
data-testid="error-details-json"
21+
id="error-details-json"
22+
>
23+
{JSON.stringify(details, undefined, 2)}
24+
</Code>
25+
),
26+
hideCancelButton: true,
27+
buttonText: closeAction.replace(/\b\w/g, (c) => c.toUpperCase()),
28+
// modalProps
29+
// buttonProps
7730
});
7831

79-
const contextValue = React.useMemo(
80-
() => ({
81-
showErrorDetails: (options: ErrorDetailsOptions) =>
82-
setErrorDetailsProps({ open: true, ...options }),
83-
isMounted: true,
84-
}),
85-
[setErrorDetailsProps]
86-
);
87-
88-
// Event listener to use confirmation modal outside of react
89-
useEffect(() => {
90-
const listener = ({ detail }: CustomEvent<ErrorDetailsOptions>) => {
91-
setErrorDetailsProps({ open: true, ...detail });
92-
};
93-
globalErrorDetails.addEventListener('show-error-details', listener);
94-
return () => {
95-
globalErrorDetails.removeEventListener('show-error-details', listener);
96-
};
97-
}, []);
98-
99-
const handleClose = () => {
100-
setErrorDetailsProps((state: ErrorDetailsModalAreaProps) => ({
101-
...state,
102-
open: false,
103-
}));
104-
};
105-
106-
if (hasParentContext) {
107-
return <>{children}</>;
108-
}
109-
110-
return (
111-
<ErrorDetailsModalContext.Provider value={contextValue}>
112-
{children}
113-
<ErrorDetailsModal
114-
// To make sure that confirmation modal internal state is reset for
115-
// every confirmation request triggered with showConfirmation method we
116-
// pass `errorDetailsId` as a component key to force React to remount it
117-
// when request starts
118-
key={errorDetailsId}
119-
data-testid="import-error-details-modal"
120-
open={errorDetailsProps.open}
121-
title={errorDetailsProps.title}
122-
closeAction={errorDetailsProps.closeAction || 'close'}
123-
onClose={handleClose}
124-
details={errorDetailsProps.details}
125-
/>
126-
</ErrorDetailsModalContext.Provider>
127-
);
128-
};
129-
130-
export const useErrorDetailsModal = () => {
131-
const { isMounted, showErrorDetails } = useContext(ErrorDetailsModalContext);
132-
if (!isMounted) {
133-
throw new Error(
134-
'useErrorDetailsModal must be used within a ErrorDetailsModalArea'
135-
);
136-
}
13732
return { showErrorDetails };
138-
};
33+
}

packages/compass-crud/src/components/document-list.tsx

Lines changed: 84 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -519,92 +519,90 @@ const DocumentList: React.FunctionComponent<DocumentListProps> = (props) => {
519519

520520
return (
521521
<div className={documentsContainerStyles} data-testid="compass-crud">
522-
<ErrorDetailsModalArea>
523-
<WorkspaceContainer
524-
scrollableContainerRef={scrollRef}
525-
initialTopInView={currentViewInitialScrollTop === 0}
526-
toolbar={
527-
<CrudToolbar
528-
activeDocumentView={view}
529-
error={error}
530-
count={count}
531-
isFetching={isFetching}
532-
loadingCount={loadingCount}
533-
start={start}
534-
end={end}
535-
page={page}
536-
getPage={getPage}
537-
insertDataHandler={onOpenInsert}
538-
onApplyClicked={onApplyClicked}
539-
onResetClicked={onResetClicked}
540-
onUpdateButtonClicked={onUpdateButtonClicked}
541-
onDeleteButtonClicked={onDeleteButtonClicked}
542-
onExpandAllClicked={onExpandAllClicked}
543-
onCollapseAllClicked={onCollapseAllClicked}
544-
openExportFileDialog={openExportFileDialog}
545-
outdated={outdated}
546-
readonly={!isEditable}
547-
viewSwitchHandler={handleViewChanged}
548-
isWritable={isWritable}
549-
instanceDescription={instanceDescription}
550-
refreshDocuments={refreshDocuments}
551-
resultId={resultId}
552-
querySkip={query.skip}
553-
queryLimit={query.limit}
554-
insights={getToolbarSignal(
555-
JSON.stringify(query.filter ?? {}),
556-
Boolean(isCollectionScan),
557-
isSearchIndexesSupported,
558-
store.openCreateIndexModal.bind(store),
559-
store.openCreateSearchIndexModal.bind(store)
560-
)}
561-
docsPerPage={docsPerPage}
562-
updateMaxDocumentsPerPage={handleMaxDocsPerPageChanged}
563-
/>
564-
}
565-
>
566-
{renderContent}
567-
</WorkspaceContainer>
568-
569-
{isEditable && (
570-
<>
571-
<InsertDocumentDialog
572-
closeInsertDocumentDialog={closeInsertDocumentDialog}
573-
insertDocument={insertDocument}
574-
insertMany={insertMany}
575-
updateJsonDoc={updateJsonDoc}
576-
toggleInsertDocument={toggleInsertDocument}
577-
toggleInsertDocumentView={toggleInsertDocumentView}
578-
jsonView
579-
version={version}
580-
ns={ns}
581-
updateComment={updateComment}
582-
{...insert}
583-
/>
584-
<BulkUpdateModal
585-
ns={ns}
586-
filter={query.filter ?? {}}
587-
count={count}
588-
enablePreview={isUpdatePreviewSupported}
589-
{...bulkUpdate}
590-
closeBulkUpdateModal={closeBulkUpdateModal}
591-
updateBulkUpdatePreview={updateBulkUpdatePreview}
592-
runBulkUpdate={runBulkUpdate}
593-
saveUpdateQuery={onSaveUpdateQuery}
594-
/>
595-
<BulkDeleteModal
596-
open={store.state.bulkDelete.status === 'open'}
597-
namespace={store.state.ns}
598-
documentCount={store.state.bulkDelete.affected}
599-
filter={query.filter ?? {}}
600-
onCancel={onCancelBulkDeleteDialog}
601-
onConfirmDeletion={onConfirmBulkDeleteDialog}
602-
sampleDocuments={store.state.bulkDelete.previews}
603-
onExportToLanguage={onExportToLanguageDeleteQuery}
604-
/>
605-
</>
606-
)}
607-
</ErrorDetailsModalArea>
522+
<WorkspaceContainer
523+
scrollableContainerRef={scrollRef}
524+
initialTopInView={currentViewInitialScrollTop === 0}
525+
toolbar={
526+
<CrudToolbar
527+
activeDocumentView={view}
528+
error={error}
529+
count={count}
530+
isFetching={isFetching}
531+
loadingCount={loadingCount}
532+
start={start}
533+
end={end}
534+
page={page}
535+
getPage={getPage}
536+
insertDataHandler={onOpenInsert}
537+
onApplyClicked={onApplyClicked}
538+
onResetClicked={onResetClicked}
539+
onUpdateButtonClicked={onUpdateButtonClicked}
540+
onDeleteButtonClicked={onDeleteButtonClicked}
541+
onExpandAllClicked={onExpandAllClicked}
542+
onCollapseAllClicked={onCollapseAllClicked}
543+
openExportFileDialog={openExportFileDialog}
544+
outdated={outdated}
545+
readonly={!isEditable}
546+
viewSwitchHandler={handleViewChanged}
547+
isWritable={isWritable}
548+
instanceDescription={instanceDescription}
549+
refreshDocuments={refreshDocuments}
550+
resultId={resultId}
551+
querySkip={query.skip}
552+
queryLimit={query.limit}
553+
insights={getToolbarSignal(
554+
JSON.stringify(query.filter ?? {}),
555+
Boolean(isCollectionScan),
556+
isSearchIndexesSupported,
557+
store.openCreateIndexModal.bind(store),
558+
store.openCreateSearchIndexModal.bind(store)
559+
)}
560+
docsPerPage={docsPerPage}
561+
updateMaxDocumentsPerPage={handleMaxDocsPerPageChanged}
562+
/>
563+
}
564+
>
565+
{renderContent}
566+
</WorkspaceContainer>
567+
568+
{isEditable && (
569+
<>
570+
<InsertDocumentDialog
571+
closeInsertDocumentDialog={closeInsertDocumentDialog}
572+
insertDocument={insertDocument}
573+
insertMany={insertMany}
574+
updateJsonDoc={updateJsonDoc}
575+
toggleInsertDocument={toggleInsertDocument}
576+
toggleInsertDocumentView={toggleInsertDocumentView}
577+
jsonView
578+
version={version}
579+
ns={ns}
580+
updateComment={updateComment}
581+
{...insert}
582+
/>
583+
<BulkUpdateModal
584+
ns={ns}
585+
filter={query.filter ?? {}}
586+
count={count}
587+
enablePreview={isUpdatePreviewSupported}
588+
{...bulkUpdate}
589+
closeBulkUpdateModal={closeBulkUpdateModal}
590+
updateBulkUpdatePreview={updateBulkUpdatePreview}
591+
runBulkUpdate={runBulkUpdate}
592+
saveUpdateQuery={onSaveUpdateQuery}
593+
/>
594+
<BulkDeleteModal
595+
open={store.state.bulkDelete.status === 'open'}
596+
namespace={store.state.ns}
597+
documentCount={store.state.bulkDelete.affected}
598+
filter={query.filter ?? {}}
599+
onCancel={onCancelBulkDeleteDialog}
600+
onConfirmDeletion={onConfirmBulkDeleteDialog}
601+
sampleDocuments={store.state.bulkDelete.previews}
602+
onExportToLanguage={onExportToLanguageDeleteQuery}
603+
/>
604+
</>
605+
)}
608606
</div>
609607
);
610608
};

0 commit comments

Comments
 (0)