Qlik Community

Qlik Design Blog

All about product and Qlik solutions: scripting, data modeling, visual design, extensions, best practices, etc.

Employee
Employee

I cannot count the times that I had a custom webpage with visualizations from the Qlik Sense engine open, to find out that my charts where not responding due to the websocket connection being lost.

I cannot count the times that I had a custom webpage with visualizations from the Qlik Sense engine open, to find out that my charts where not responding due to the websocket connection being lost.

With Enigma.js and React.js you can create your own custom popup that notifies the end user and force to refresh the page.

So in your Enigma connection, once you have your session opened and right after

 

 

 

const session = enigma.create({ schema, url, responseInterceptors });
const global = await session.open();

 

 

 

 

add the following

 

 

 

  session.on('closed', () => ConnectionLostModal());

 

 

 

 

This will  call your custom component ConnectionLostModal.jsx below. It will inject a div into the DOM and then render and open the material-ui modal. 

 

 

 

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import Button from '@material-ui/core/Button';
import ErrorModal from '../components/QdtModal';

export default () => {
  const element = document.createElement('div');
  const header = 'Connection lost';
  const body = 'Your connection to the Qlik Sense server is lost due to inactivity, refresh to continue working.';
  const refresh = () => window.location.reload();
  const footer = <Button variant="contained" onClick={refresh}>Refresh</Button>;
  ReactDOM.unmountComponentAtNode(element);
  ReactDOM.render(
    <ErrorModal
      open
      header={header}
      body={body}
      footer={footer}
    />,
    element,
  );
};

 

 

 

 

Here is the modal QdtModal.jsx

 

 

 

import React from 'react';
import Modal from '@material-ui/core/Modal';
import PropTypes from 'prop-types';
import useStyles from './QdtModalStyles';

/* className={classes.paper} */
const QdtModal = ({
  open, header, body, footer, handleClose,
}) => {
  const classes = useStyles();

  return (
    <div>
      <Modal
        open={open}
        onClose={handleClose}
        aria-labelledby="QdtModal"
        aria-describedby="QdtModal"
      >
        <div className={classes.paper}>
          {header && (
          <div className={classes.header}>
            { header }
          </div>
          ) }
          { body && (
          <div className={classes.body}>
            { body }
          </div>
          ) }
          { footer && (
          <div className={classes.footer}>
            { footer }
          </div>
          ) }
        </div>
      </Modal>
    </div>
  );
};

QdtModal.propTypes = {
  open: PropTypes.bool.isRequired,
  handleClose: PropTypes.func,
  header: PropTypes.string,
  body: PropTypes.string,
  footer: PropTypes.string,
};
QdtModal.defaultProps = {
  handleClose: null,
  header: null,
  body: null,
  footer: null,
};

export default QdtModal;

 

 

 

 

And the css QdtModalStyles.js

 

 

 

import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles((theme) => ({
  paper: {
    position: 'absolute',
    width: '90%',
    maxWidth: 500,
    backgroundColor: theme.palette.background.paper,
    border: `1px solid ${theme.palette.grey[300]}`,
    boxShadow: theme.shadows[5],
    padding: 0,
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)',
  },
  header: {
    padding: 15,
    fontSize: '1.1em',
    fontWeight: 900,
    backgroundColor: theme.palette.grey[100],
  },
  body: {
    padding: 15,
  },
  footer: {
    padding: 15,
    borderTop: `1px solid ${theme.palette.grey[300]}`,
    backgroundColor: theme.palette.grey[100],
    textAlign: 'right',
  },
}));

export default useStyles;

 

 

 

 

The end result should be similar to this

Screen Shot 2020-04-16 at 6.32.40 AM.png

 

That's it!

/Yianni