aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/editor/ConnectionStatusNotification.tsx
blob: e402e2960b13d8ec4328a989ab3759a8b420ba65 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import Button from '@mui/material/Button';
import { observer } from 'mobx-react-lite';
import { type SnackbarKey, useSnackbar } from 'notistack';
import React, { useEffect } from 'react';

import { ContrastThemeProvider } from '../theme/ThemeProvider';

import type EditorStore from './EditorStore';

const CONNECTING_DEBOUNCE_TIMEOUT = 250;

export default observer(function ConnectionStatusNotification({
  editorStore,
}: {
  editorStore: EditorStore;
}): null {
  const { opened, opening, connectionErrors } = editorStore;
  const { enqueueSnackbar, closeSnackbar } = useSnackbar();

  useEffect(() => {
    if (opening) {
      let key: SnackbarKey | undefined;
      let timeout: number | undefined = setTimeout(() => {
        timeout = undefined;
        key = enqueueSnackbar('Connecting to Refinery', {
          persist: true,
          action: (
            <Button onClick={() => editorStore.disconnect()} color="inherit">
              Cancel
            </Button>
          ),
        });
      }, CONNECTING_DEBOUNCE_TIMEOUT);
      return () => {
        if (timeout !== undefined) {
          clearTimeout(timeout);
        }
        if (key !== undefined) {
          closeSnackbar(key);
        }
      };
    }

    if (connectionErrors.length >= 1) {
      const key = enqueueSnackbar(
        <div>
          Connection error: <b>{connectionErrors[0]}</b>
          {connectionErrors.length >= 2 && (
            <>
              {' '}
              and <b>{connectionErrors.length - 1}</b> more{' '}
              {connectionErrors.length >= 3 ? 'errors' : 'error'}
            </>
          )}
        </div>,
        {
          persist: !opened,
          variant: 'error',
          action: opened ? (
            <ContrastThemeProvider>
              <Button onClick={() => editorStore.disconnect()} color="inherit">
                Disconnect
              </Button>
            </ContrastThemeProvider>
          ) : (
            <ContrastThemeProvider>
              <Button onClick={() => editorStore.connect()} color="inherit">
                Reconnect
              </Button>
              <Button onClick={() => editorStore.disconnect()} color="inherit">
                Cancel
              </Button>
            </ContrastThemeProvider>
          ),
        },
      );
      return () => closeSnackbar(key);
    }

    if (!opened) {
      const key = enqueueSnackbar(
        <div>
          <b>Not connected to Refinery:</b> Some editing features might be
          degraded
        </div>,
        {
          action: (
            <ContrastThemeProvider>
              <Button onClick={() => editorStore.connect()}>Reconnect</Button>
            </ContrastThemeProvider>
          ),
        },
      );
      return () => closeSnackbar(key);
    }

    return () => {};
  }, [
    editorStore,
    opened,
    opening,
    connectionErrors,
    closeSnackbar,
    enqueueSnackbar,
  ]);

  return null;
});