| 
8 | 8 |   spacing,  | 
9 | 9 |   openToast,  | 
10 | 10 |   closeToast,  | 
 | 11 | +  Icon,  | 
 | 12 | +  Button,  | 
11 | 13 | } from '@mongodb-js/compass-components';  | 
12 | 14 | import type { ConnectionInfo } from '@mongodb-js/connection-info';  | 
13 | 15 | import { getConnectionTitle } from '@mongodb-js/connection-info';  | 
@@ -38,74 +40,101 @@ export function getConnectingStatusText(connectionInfo: ConnectionInfo) {  | 
38 | 40 | 
 
  | 
39 | 41 | type ConnectionErrorToastBodyProps = {  | 
40 | 42 |   info?: ConnectionInfo | null;  | 
 | 43 | +  error: Error;  | 
41 | 44 |   showReviewButton: boolean;  | 
 | 45 | +  showDebugButton: boolean;  | 
42 | 46 |   onReview: () => void;  | 
 | 47 | +  onDebug: () => void;  | 
43 | 48 | };  | 
44 | 49 | 
 
  | 
 | 50 | +const connectionErrorToastStyles = css({  | 
 | 51 | +  // the gap on the right after the buttons takes up a lot of space form the  | 
 | 52 | +  // description, so we remove it and add a little bit of margin elsewhere  | 
 | 53 | +  gap: 0,  | 
 | 54 | +  '[data-testid="lg-toast-content"] > div, [data-testid="lg-toast-content"] > div > p + p':  | 
 | 55 | +    {  | 
 | 56 | +      // don't cut off the glow of the button  | 
 | 57 | +      overflow: 'visible',  | 
 | 58 | +    },  | 
 | 59 | +});  | 
 | 60 | + | 
45 | 61 | const connectionErrorToastBodyStyles = css({  | 
46 | 62 |   display: 'grid',  | 
47 | 63 |   gridAutoFlow: 'column',  | 
48 | 64 |   gap: spacing[200],  | 
49 | 65 | });  | 
50 | 66 | 
 
  | 
51 |  | -const connectionErrorToastActionMessageStyles = css({});  | 
 | 67 | +const connectionErrorActionsStyles = css({  | 
 | 68 | +  display: 'flex',  | 
 | 69 | +  flexDirection: 'column',  | 
 | 70 | +  textAlign: 'right',  | 
 | 71 | +  // replacing the gap with a margin so the button glow does not get cut off  | 
 | 72 | +  marginRight: spacing[100],  | 
 | 73 | +  gap: spacing[100],  | 
 | 74 | +  justifyContent: 'center',  | 
 | 75 | +});  | 
52 | 76 | 
 
  | 
53 |  | -const connectionErrorTextStyles = css({  | 
54 |  | -  overflow: 'hidden',  | 
55 |  | -  textOverflow: 'ellipsis',  | 
 | 77 | +const connectionErrorStyles = css({  | 
 | 78 | +  display: 'flex',  | 
 | 79 | +  flexDirection: 'column',  | 
 | 80 | +});  | 
 | 81 | + | 
 | 82 | +const connectionErrorTitleStyles = css({  | 
 | 83 | +  fontWeight: 'bold',  | 
 | 84 | +});  | 
 | 85 | + | 
 | 86 | +const debugActionStyles = css({  | 
 | 87 | +  display: 'flex',  | 
 | 88 | +  alignItems: 'center',  | 
 | 89 | +  gap: spacing[100],  | 
 | 90 | +  justifyContent: 'right',  | 
 | 91 | +  textWrap: 'nowrap',  | 
56 | 92 | });  | 
57 | 93 | 
 
  | 
58 | 94 | function ConnectionErrorToastBody({  | 
59 | 95 |   info,  | 
 | 96 | +  error,  | 
60 | 97 |   showReviewButton,  | 
 | 98 | +  showDebugButton,  | 
61 | 99 |   onReview,  | 
 | 100 | +  onDebug,  | 
62 | 101 | }: ConnectionErrorToastBodyProps): React.ReactElement {  | 
63 | 102 |   return (  | 
64 | 103 |     <span className={connectionErrorToastBodyStyles}>  | 
65 |  | -      <span  | 
66 |  | -        data-testid="connection-error-text"  | 
67 |  | -        className={connectionErrorTextStyles}  | 
68 |  | -      >  | 
69 |  | -        There was a problem connecting{' '}  | 
70 |  | -        {info ? `to ${getConnectionTitle(info)}` : ''}  | 
71 |  | -      </span>  | 
72 |  | -      {info && showReviewButton && (  | 
73 |  | -        <Link  | 
74 |  | -          className={connectionErrorToastActionMessageStyles}  | 
75 |  | -          hideExternalIcon={true}  | 
76 |  | -          onClick={onReview}  | 
77 |  | -          data-testid="connection-error-review"  | 
 | 104 | +      <span className={connectionErrorStyles}>  | 
 | 105 | +        <span  | 
 | 106 | +          data-testid="connection-error-title"  | 
 | 107 | +          className={connectionErrorTitleStyles}  | 
78 | 108 |         >  | 
79 |  | -          REVIEW  | 
80 |  | -        </Link>  | 
81 |  | -      )}  | 
82 |  | -    </span>  | 
83 |  | -  );  | 
84 |  | -}  | 
85 |  | - | 
86 |  | -type ConnectionDebugToastBodyProps = {  | 
87 |  | -  onDebug: () => void;  | 
88 |  | -};  | 
89 |  | - | 
90 |  | -function ConnectionDebugToastBody({  | 
91 |  | -  onDebug,  | 
92 |  | -}: ConnectionDebugToastBodyProps): React.ReactElement {  | 
93 |  | -  return (  | 
94 |  | -    <span className={connectionErrorToastBodyStyles}>  | 
95 |  | -      <span  | 
96 |  | -        data-testid="connection-debug-text"  | 
97 |  | -        className={connectionErrorTextStyles}  | 
98 |  | -      >  | 
99 |  | -        Diagnose the issue and explore solutions with the assistant  | 
 | 109 | +          {info ? getConnectionTitle(info) : 'Connection failed'}  | 
 | 110 | +        </span>  | 
 | 111 | +        <span data-testid="connection-error-text">{error.message}</span>  | 
 | 112 | +      </span>  | 
 | 113 | +      <span className={connectionErrorActionsStyles}>  | 
 | 114 | +        {info && showReviewButton && (  | 
 | 115 | +          <span>  | 
 | 116 | +            <Button  | 
 | 117 | +              onClick={onReview}  | 
 | 118 | +              data-testid="connection-error-review"  | 
 | 119 | +              size="small"  | 
 | 120 | +            >  | 
 | 121 | +              Review  | 
 | 122 | +            </Button>  | 
 | 123 | +          </span>  | 
 | 124 | +        )}  | 
 | 125 | +        {info && showDebugButton && (  | 
 | 126 | +          <span className={debugActionStyles}>  | 
 | 127 | +            <Icon glyph="Sparkle" size="small"></Icon>  | 
 | 128 | +            <Link  | 
 | 129 | +              hideExternalIcon={true}  | 
 | 130 | +              onClick={onDebug}  | 
 | 131 | +              data-testid="connection-error-debug"  | 
 | 132 | +            >  | 
 | 133 | +              Debug for me  | 
 | 134 | +            </Link>  | 
 | 135 | +          </span>  | 
 | 136 | +        )}  | 
100 | 137 |       </span>  | 
101 |  | -      <Link  | 
102 |  | -        className={connectionErrorToastActionMessageStyles}  | 
103 |  | -        hideExternalIcon={true}  | 
104 |  | -        onClick={onDebug}  | 
105 |  | -        data-testid="connection-error-debug"  | 
106 |  | -      >  | 
107 |  | -        DEBUG FOR ME  | 
108 |  | -      </Link>  | 
109 | 138 |     </span>  | 
110 | 139 |   );  | 
111 | 140 | }  | 
@@ -150,51 +179,50 @@ const openConnectionSucceededToast = (connectionInfo: ConnectionInfo) => {  | 
150 | 179 |   });  | 
151 | 180 | };  | 
152 | 181 | 
 
  | 
153 |  | -const openConnectionFailedToast = (  | 
 | 182 | +const openConnectionFailedToast = ({  | 
 | 183 | +  connectionInfo,  | 
 | 184 | +  error,  | 
 | 185 | +  showReviewButton,  | 
 | 186 | +  showDebugButton,  | 
 | 187 | +  onReviewClick,  | 
 | 188 | +  onDebugClick,  | 
 | 189 | +}: {  | 
154 | 190 |   // Connection info might be missing if we failed connecting before we  | 
155 | 191 |   // could even resolve connection info. Currently the only case where this  | 
156 | 192 |   // can happen is autoconnect flow  | 
157 |  | -  connectionInfo: ConnectionInfo | null | undefined,  | 
158 |  | -  error: Error,  | 
159 |  | -  showReviewButton: boolean,  | 
160 |  | -  onReviewClick: () => void  | 
161 |  | -) => {  | 
 | 193 | +  connectionInfo: ConnectionInfo | null | undefined;  | 
 | 194 | +  error: Error;  | 
 | 195 | +  showReviewButton: boolean;  | 
 | 196 | +  showDebugButton: boolean;  | 
 | 197 | +  onReviewClick: () => void;  | 
 | 198 | +  onDebugClick: () => void;  | 
 | 199 | +}) => {  | 
162 | 200 |   const failedToastId = connectionInfo?.id ?? 'failed';  | 
163 | 201 | 
 
  | 
164 |  | -  // TODO(COMPASS-9746): close the existing connection toast and make a new one  | 
165 |  | -  // for the failure so that the debug toast will appear below the failure one  | 
166 | 202 |   openToast(`connection-status--${failedToastId}`, {  | 
167 |  | -    title: error.message,  | 
 | 203 | +    // we place the title inside the description to get the layout we need  | 
 | 204 | +    title: '',  | 
168 | 205 |     description: (  | 
169 | 206 |       <ConnectionErrorToastBody  | 
170 | 207 |         info={connectionInfo}  | 
 | 208 | +        error={error}  | 
171 | 209 |         showReviewButton={showReviewButton}  | 
 | 210 | +        showDebugButton={showDebugButton}  | 
172 | 211 |         onReview={() => {  | 
173 |  | -          closeToast(`connection-status--${failedToastId}`);  | 
 | 212 | +          if (!showDebugButton) {  | 
 | 213 | +            // don't close the toast if there are two actionsso that the user  | 
 | 214 | +            // can still use the other one  | 
 | 215 | +            closeToast(`connection-status--${failedToastId}`);  | 
 | 216 | +          }  | 
174 | 217 |           onReviewClick();  | 
175 | 218 |         }}  | 
176 |  | -      />  | 
177 |  | -    ),  | 
178 |  | -    variant: 'warning',  | 
179 |  | -  });  | 
180 |  | -};  | 
181 |  | - | 
182 |  | -const openDebugConnectionErrorToast = (  | 
183 |  | -  connectionInfo: ConnectionInfo,  | 
184 |  | -  error: Error,  | 
185 |  | -  onDebugClick: () => void  | 
186 |  | -) => {  | 
187 |  | -  openToast(`debug-connection-error--${connectionInfo.id}`, {  | 
188 |  | -    title: 'Need help debugging your connection error?',  | 
189 |  | -    description: (  | 
190 |  | -      <ConnectionDebugToastBody  | 
191 | 219 |         onDebug={() => {  | 
192 |  | -          closeToast(`debug-connection-error--${connectionInfo.id}`);  | 
193 | 220 |           onDebugClick();  | 
194 | 221 |         }}  | 
195 | 222 |       />  | 
196 | 223 |     ),  | 
197 |  | -    variant: 'note',  | 
 | 224 | +    variant: 'warning',  | 
 | 225 | +    className: connectionErrorToastStyles,  | 
198 | 226 |   });  | 
199 | 227 | };  | 
200 | 228 | 
 
  | 
@@ -262,7 +290,6 @@ export function getNotificationTriggers() {  | 
262 | 290 |     openConnectionStartedToast,  | 
263 | 291 |     openConnectionSucceededToast,  | 
264 | 292 |     openConnectionFailedToast,  | 
265 |  | -    openDebugConnectionErrorToast,  | 
266 | 293 |     openMaximumConnectionsReachedToast,  | 
267 | 294 |     closeConnectionStatusToast: (connectionId: string) => {  | 
268 | 295 |       return closeToast(`connection-status--${connectionId}`);  | 
 | 
0 commit comments