Skip to content

Commit f6402c1

Browse files
authored
feat: error details on update COMPASS-8865 (#6778)
1 parent b574c1e commit f6402c1

23 files changed

+290
-365
lines changed

packages/compass-components/src/components/document-list/document-edit-actions-footer.tsx

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { css } from '@leafygreen-ui/emotion';
66
import { palette } from '@leafygreen-ui/palette';
77
import { spacing } from '@leafygreen-ui/tokens';
88
import { useDarkMode } from '../../hooks/use-theme';
9+
import { showErrorDetails } from '../../hooks/use-error-details';
910

1011
type Status =
1112
| 'Initial'
@@ -81,13 +82,30 @@ function useHadronDocumentStatus(
8182
? 'Deleting'
8283
: 'Initial';
8384
});
84-
const [errorMessage, setErrorMessage] = useState<string | null>(null);
85+
const [error, setError] = useState<{
86+
message: string;
87+
details?: Record<string, unknown>;
88+
} | null>(null);
8589
const invalidElementsRef = useRef(new Set());
8690

87-
const updateStatus = useCallback((newStatus: Status, errorMessage = null) => {
88-
setStatus(newStatus);
89-
setErrorMessage(errorMessage);
90-
}, []);
91+
const updateStatus = useCallback(
92+
(
93+
newStatus: Status,
94+
error: Error | null = null,
95+
errorDetails?: Record<string, unknown>
96+
) => {
97+
setStatus(newStatus);
98+
setError(
99+
error
100+
? {
101+
message: error?.message,
102+
details: errorDetails,
103+
}
104+
: null
105+
);
106+
},
107+
[]
108+
);
91109

92110
useEffect(() => {
93111
if (status !== 'Initial') {
@@ -128,17 +146,23 @@ function useHadronDocumentStatus(
128146
const onUpdateSuccess = () => {
129147
updateStatus('UpdateSuccess');
130148
};
131-
const onUpdateError = (err: string) => {
132-
updateStatus('UpdateError', err);
149+
const onUpdateError = (
150+
err: Error,
151+
errorDetails?: Record<string, unknown>
152+
) => {
153+
updateStatus('UpdateError', err, errorDetails);
133154
};
134155
const onRemoveStart = () => {
135156
updateStatus('DeleteStart');
136157
};
137158
const onRemoveSuccess = () => {
138159
updateStatus('DeleteSuccess');
139160
};
140-
const onRemoveError = (err: string) => {
141-
updateStatus('DeleteError', err);
161+
const onRemoveError = (
162+
err: Error,
163+
errorDetails?: Record<string, unknown>
164+
) => {
165+
updateStatus('DeleteError', err, errorDetails);
142166
};
143167

144168
doc.on(Element.Events.Added, onUpdate);
@@ -183,30 +207,30 @@ function useHadronDocumentStatus(
183207
}
184208
}, [status, updateStatus]);
185209

186-
return { status, updateStatus, errorMessage };
210+
return { status, updateStatus, error };
187211
}
188212

189213
const container = css({
190214
display: 'flex',
191-
paddingTop: spacing[2],
192-
paddingRight: spacing[2],
193-
paddingBottom: spacing[2],
194-
paddingLeft: spacing[3],
215+
paddingTop: spacing[200],
216+
paddingRight: spacing[200],
217+
paddingBottom: spacing[200],
218+
paddingLeft: spacing[400],
195219
alignItems: 'center',
196-
gap: spacing[2],
220+
gap: spacing[200],
197221
borderBottomLeftRadius: 'inherit',
198222
borderBottomRightRadius: 'inherit',
199223
});
200224

201225
const message = css({
202-
overflow: 'hidden',
203-
textOverflow: 'ellipsis',
226+
overflow: 'scroll',
204227
});
205228

206229
const buttonGroup = css({
207230
display: 'flex',
208231
marginLeft: 'auto',
209-
gap: spacing[2],
232+
gap: spacing[200],
233+
flexShrink: 0,
210234
});
211235

212236
const button = css({
@@ -275,7 +299,7 @@ const EditActionsFooter: React.FunctionComponent<{
275299
const {
276300
status: _status,
277301
updateStatus,
278-
errorMessage,
302+
error,
279303
} = useHadronDocumentStatus(doc, editing, deleting);
280304

281305
const darkMode = useDarkMode();
@@ -303,10 +327,25 @@ const EditActionsFooter: React.FunctionComponent<{
303327
data-status={status}
304328
>
305329
<div className={message} data-testid="document-footer-message">
306-
{errorMessage ?? statusMessage}
330+
{error?.message ?? statusMessage}
307331
</div>
308332
{!isSuccess(status) && (
309333
<div className={buttonGroup}>
334+
{error?.details && (
335+
<Button
336+
className={button}
337+
size="xsmall"
338+
onClick={() =>
339+
showErrorDetails({
340+
details: error.details!,
341+
closeAction: 'close',
342+
})
343+
}
344+
data-testid="edit-actions-footer-error-details-button"
345+
>
346+
VIEW ERROR DETAILS
347+
</Button>
348+
)}
310349
<Button
311350
type="button"
312351
size="xsmall"

packages/compass-components/src/components/modals/error-details-modal.tsx

Lines changed: 0 additions & 69 deletions
This file was deleted.

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useContext, useEffect, useRef, useState } from 'react';
22
import { Variant as ConfirmationModalVariant } from '@leafygreen-ui/confirmation-modal';
33
import ConfirmationModal from '../components/modals/confirmation-modal';
44
import { css } from '@leafygreen-ui/emotion';
5+
import type { ButtonProps } from '@leafygreen-ui/button';
56

67
export { ConfirmationModalVariant };
78

@@ -11,6 +12,7 @@ type ConfirmationProperties = Partial<
1112
Pick<ConfirmationModalProps, 'title' | 'variant' | 'requiredInputText'>
1213
> & {
1314
buttonText?: React.ReactNode;
15+
confirmButtonProps?: Omit<ButtonProps, 'onClick'>;
1416
hideConfirmButton?: boolean;
1517
hideCancelButton?: boolean;
1618
description?: React.ReactNode;
@@ -100,8 +102,28 @@ export const ConfirmationModalArea: React.FC = ({ children }) => {
100102
});
101103
const callbackRef = useRef<ConfirmationCallback>();
102104

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

@@ -127,6 +149,7 @@ export const ConfirmationModalArea: React.FC = ({ children }) => {
127149
};
128150
props.signal?.addEventListener('abort', onAbort);
129151
};
152+
listenerRef.current = listener;
130153
globalConfirmation.addEventListener('show-confirmation', listener);
131154
return () => {
132155
globalConfirmation.removeEventListener('show-confirmation', listener);
@@ -170,6 +193,7 @@ export const ConfirmationModalArea: React.FC = ({ children }) => {
170193
: undefined,
171194
children: confirmationProps.buttonText ?? 'Confirm',
172195
onClick: handleConfirm,
196+
...confirmationProps.confirmButtonProps,
173197
}}
174198
cancelButtonProps={{
175199
className: confirmationProps.hideCancelButton
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {
2+
type showConfirmation as originalShowConfirmation,
3+
showConfirmation,
4+
} from './use-confirmation';
5+
import { Code } from '../components/leafygreen';
6+
import React from 'react';
7+
import { ButtonVariant } from '..';
8+
9+
const getShowErrorDetails = (
10+
showConfirmation: typeof originalShowConfirmation
11+
) => {
12+
return ({
13+
details,
14+
closeAction,
15+
}: {
16+
details: Record<string, unknown>;
17+
closeAction: 'back' | 'close';
18+
}) =>
19+
void showConfirmation({
20+
title: 'Error details',
21+
description: (
22+
<Code
23+
language="json"
24+
data-testid="error-details-json"
25+
id="error-details-json"
26+
>
27+
{JSON.stringify(details, undefined, 2)}
28+
</Code>
29+
),
30+
hideCancelButton: true,
31+
buttonText: closeAction.replace(/\b\w/g, (c) => c.toUpperCase()),
32+
confirmButtonProps: {
33+
variant: ButtonVariant.Default,
34+
},
35+
});
36+
};
37+
38+
export const showErrorDetails = getShowErrorDetails(showConfirmation);

packages/compass-components/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ export { ModalBody } from './components/modals/modal-body';
9292
export { ModalHeader } from './components/modals/modal-header';
9393
export { FormModal } from './components/modals/form-modal';
9494
export { InfoModal } from './components/modals/info-modal';
95-
export { ErrorDetailsModal } from './components/modals/error-details-modal';
9695

9796
export type {
9897
FileInputBackend,
@@ -183,6 +182,7 @@ export {
183182
ConfirmationModalArea,
184183
showConfirmation,
185184
} from './hooks/use-confirmation';
185+
export { showErrorDetails } from './hooks/use-error-details';
186186
export {
187187
useHotkeys,
188188
formatHotkey,

packages/compass-crud/src/actions/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ const configureActions = () => {
1919
'toggleInsertDocumentView',
2020
'toggleInsertDocument',
2121
'openInsertDocumentDialog',
22-
'openErrorDetailsDialog',
23-
'closeErrorDetailsDialog',
2422
'openBulkUpdateModal',
2523
'updateBulkUpdatePreview',
2624
'runBulkUpdate',

packages/compass-crud/src/components/document-json-view.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export type DocumentJsonViewProps = {
3333
| 'removeDocument'
3434
| 'replaceDocument'
3535
| 'updateDocument'
36-
| 'openErrorDetailsDialog'
3736
| 'openInsertDocumentDialog'
3837
>;
3938

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ describe('<DocumentListView />', function () {
2121
replaceDocument={sinon.spy()}
2222
updateDocument={sinon.spy()}
2323
openInsertDocumentDialog={sinon.spy()}
24-
openErrorDetailsDialog={sinon.spy()}
2524
/>
2625
);
2726

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ class DocumentListView extends React.Component<DocumentListViewProps> {
9797
replaceDocument: PropTypes.func,
9898
updateDocument: PropTypes.func,
9999
openInsertDocumentDialog: PropTypes.func,
100-
openErrorDetailsDialog: PropTypes.func,
101100
copyToClipboard: PropTypes.func,
102101
className: PropTypes.string,
103102
};

0 commit comments

Comments
 (0)