ManageIQ/manageiq-ui-classic

View on GitHub
app/javascript/components/dashboard-widgets/widget-wrapper/helper.jsx

Summary

Maintainability
F
4 days
Test Coverage
/* eslint-disable no-alert */
import React from 'react';
import ReactDOM from 'react-dom';
import { OverflowMenuItem, Loading } from 'carbon-components-react';
import classNames from 'classnames';
import WidgetChart from '../widget-chart';
import WidgetError from '../widget-error';
import WidgetFooter from '../widget-footer';
import WidgetMenu from '../widget-menu';
import WidgetReport from '../widget-report';
import WidgetZoom from '../widget-zoom';
import { http } from '../../../http_api';

const widgetUrl = (widgetId, widgetType) => {
  const widgetTypeUrl = {
    menu: '/dashboard/widget_menu_data/',
    report: '/dashboard/widget_report_data/',
    chart: '/dashboard/widget_chart_data/',
  };

  if (widgetTypeUrl[widgetType]) {
    return [widgetTypeUrl[widgetType], widgetId].join('/');
  }
  return null;
};

const model = (isLoading, widgetId, widgetModel, widgetType) => {
  let widget;
  if (isLoading) {
    widget = (
      <div className="loadingSpinner">
        <Loading className="export-spinner" withOverlay={false} small />
      </div>
    );
  } else if (widgetType === 'menu' && isLoading === false) {
    widget = (
      <WidgetMenu
        key={widgetId}
        widgetModel={widgetModel}
      />
    );
  } else if (widgetType === 'report' && isLoading === false) {
    widget = (
      <WidgetReport
        key={widgetId}
        widgetModel={widgetModel}
      />
    );
  } else if (widgetType === 'chart' && isLoading === false) {
    let data = widgetModel;
    let id;
    let title;

    // Parse data from widgetModel that returns a react element with all the required data in the script section
    if (data) {
      const start = data.search('. {') + 2;
      const end = data.search('</script>') - 8;
      data = data.substring(start, end);
      data = JSON.parse(data);
      id = data.id;
      title = data.title;
    }
    widget = (
      <WidgetChart
        key={`${widgetId}-${isLoading}`}
        widgetModel={widgetModel}
        data={data}
        id={id}
        title={title}
      />
    );
  }
  return widget;
};

const footer = (widgetModel, lastRun, nextRun) => {
  if (widgetModel) {
    return (
      <WidgetFooter lastRun={lastRun} nextRun={nextRun} />
    );
  }
  return null;
};

const menuItemOnClick = (menuItems, widgetId, dataMethod, href, buttonTitle, widgetType, widgetTitle, setState, widgetModel, lastRun, nextRun) => {
  let index = 0;
  // Handles Minimize button and changes it to Maximize after click
  if (buttonTitle === __('Minimize')) {
    document.getElementById(`dd_w${widgetId}_box`).style.display = 'none';
    menuItems.forEach((button) => {
      if (button.props.title === __('Minimize')) {
        const newButton = (
          <OverflowMenuItem
            key={button.props.id}
            id={button.props.id}
            itemText={(
              <div>
                <i className={classNames('fa-fw', 'icon', 'fa fa-caret-square-o-down fa-fw')} />
                {__('Maximize')}
              </div>
            )}
            requireTitle
            title={__('Maximize')}
            onClick={() => menuItemOnClick(menuItems, widgetId, '', '', __('Maximize'), widgetType, widgetTitle, setState)}
          />
        );
        if (index > -1) {
          menuItems[index] = newButton;
        }
      }
      index += 1;
    });
    index = 0;
    return;
  }
  // Handles Maximize button and changes it to minimize after click
  if (buttonTitle === __('Maximize')) {
    document.getElementById(`dd_w${widgetId}_box`).style.display = 'block';
    menuItems.forEach((button) => {
      if (button.props.title === __('Maximize')) {
        const newButton = (
          <OverflowMenuItem
            key={button.props.id}
            id={button.props.id}
            itemText={(
              <div>
                <i className={classNames('fa-fw', 'icon', 'fa fa-caret-square-o-up fa-fw')} />
                {__('Minimize')}
              </div>
            )}
            requireTitle
            title={__('Minimize')}
            onClick={() => menuItemOnClick(menuItems, widgetId, '', '', __('Minimize'), widgetType, widgetTitle, setState)}
          />
        );
        if (index > -1) {
          menuItems[index] = newButton;
        }
      }
      index += 1;
    });
    index = 0;
    return;
  }
  // Handles refresh button
  if (buttonTitle === __('Refresh this Widget')) {
    http.get(widgetUrl(widgetId, widgetType))
      .then((response) => {
        setState({
          widgetModel: response.content,
          isLoading: false,
        });
      });
    miqSparkleOff();
    add_flash(sprintf(__('Widget "%s" was refreshed'), widgetTitle), 'success');
    return;
  }
  // Handles zoom button
  if (buttonTitle === __('Zoom in on this chart')) {
    const oldDiv = document.getElementById('lightbox_div');
    const widget = model(false, widgetId, widgetModel, widgetType);
    const newDiv = document.createElement('div');
    ReactDOM.render(<WidgetZoom widgetTitle={widgetTitle} widget={widget} footer={footer(widgetModel, lastRun, nextRun)} />, newDiv);
    oldDiv.parentNode.replaceChild(newDiv, oldDiv);
    $('#lightbox-panel').fadeIn(300);
    return;
  }
  // Handles remove button
  if (dataMethod === 'post') {
    setState((state) => ({
      ...state,
      showConfirm: true,
      href,
    }));
  } else {
    // Handles print or export to PDF button
    if (buttonTitle === __('Print the full report (all rows) or export it as a PDF file')) {
      window.open(href, '_blank', 'noopener,noreferrer');
      return;
    }
    // Handles full screen button
    let confirmText;
    if (buttonTitle === __(`Open the chart and full report in a new window`)) {
      confirmText = __('This will show the chart and the entire report (all rows) in your browser. Do you want to proceed?');
    } else if (buttonTitle === __(`Open the full report in a new window`)) {
      confirmText = __('This will show the entire report (all rows) in your browser. Do you want to proceed?');
    }
    if (window.confirm(confirmText)) {
      window.open(href, '_blank', 'noopener,noreferrer');
    }
  }
};

export const getOverflowButtons = (widgetButtons, widgetId, widgetType, widgetTitle, setState, widgetModel, lastRun, nextRun) => {
  const menuItems = [];
  const parsedButtons = JSON.parse(widgetButtons);
  parsedButtons.forEach((button) => {
    menuItems.push(<OverflowMenuItem
      key={button.id}
      id={button.id}
      itemText={(
        <div>
          <i className={classNames('fa-fw', 'icon', button.fonticon)} />
          {button.name}
        </div>
      )}
      requireTitle
      title={button.title}
      onClick={() => menuItemOnClick(
        menuItems,
        widgetId,
        button.dataMethod,
        button.href,
        button.title,
        widgetType,
        widgetTitle,
        setState,
        widgetModel,
        lastRun,
        nextRun
      )}
    />);
  });
  return menuItems;
};

export const getWidget = (widgetId, isLoading, widgetModel, widgetType, lastRun, nextRun, error) => {
  if (error) {
    return (
      <WidgetError widgetId={widgetId} />
    );
  }
  if (widgetType === 'menu') {
    return (
      <div id={`dd_w${widgetId}_box`}>
        {model(isLoading, widgetId, widgetModel, widgetType)}
      </div>
    );
  }
  return (
    <div id={`dd_w${widgetId}_box`}>
      {model(isLoading, widgetId, widgetModel, widgetType)}
      {footer(widgetModel, lastRun, nextRun)}
    </div>
  );
};