Tuesday

Get parameters from url as query params in react with typescript

 Call your react as >> localhost:3000?firstParam=123&secondParam=123&thirdParam=false

IQueryParams.tsx >>
type IQueryParams = {
  firstParam?: string;
  secondParam?: string;
  thirdParam?: boolean;
};

app.tsx>>
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import Body from './router';

interface IProp {
}

class App extends React.PureComponent<IProp> {
  constructor(props: IProp) {
    super(props);
    this.setQueryParams = this.setQueryParams.bind(this);
  }

  componentDidMount() {
    this.setQueryParams();
  }

  setQueryParams() {
    const search = window.location.search;
    const params = new URLSearchParams(search);

    const params = {
      firstParam: params.get('firstParam'),
      secondParam: params.get('secondParam'),
      thirdParam: params.get('thirdParam'),
    };

    console.log(params);
  }

  render() {
    return (
      <Router>
        <div className="app">
          <Body />
        </div>
      </Router>
    );
  }
}

export default App;

Property context does not exist on type NodeRequire

BUG: I'm getting following error while trying to:
           ** Property context does not exist on type NodeRequire
const customIcons = importAll(require.context('./', false, /\.(png|jpe?g|svg)$/));

FIX:
npm install @types/webpack-env 

Monday

React: calling a function from a string using Typescript

Example of calling functions(in actions.ts) by giving string name dynamically with the same input parameters.

actions.ts
export function actionExampleFirst(data: any) {
  console.log('actionExampleFirst has called. parameters: ' + data);
}

export function actionExampleSecond(data: any) {
  console.log('actionExampleSecond has called. parameters: ' + data);
}

callActionsDynamically.tsx
import React from 'react';
import * as actions from './actions';

interface IProp {
}

type ActionType = typeof actions;

class CallActionsDynamically extends React.PureComponent<IProp> {
  constructor(props: IProp) {
    super(props);
    this.dynamicCall = this.dynamicCall.bind(this);
  }

  componentDidMount() {
    this.dynamicCall('actionExampleSecond', 'some parameters 2');
    this.dynamicCall('actionExampleFirst', 'some parameters 1');
  }

  dynamicCall<K extends keyof ActionType>(funcName: K, data: any) {
     actions[funcName](data);
  }

  render() {
    return(
      <></>
    );
  }
}

export default CallActionsDynamically;

You will see in the console:
actionExampleSecond has called. parameters: some parameters 2
actionExampleFirst has called. parameters: some parameters 1

Tuesday

react - fusioncharts example with typescript (linear-scale-gauge)

npm install fusioncharts --save
npm install react-fusioncharts --save



chartWithParameters.tsx
import React from 'react';
import LinearChart from './linearChart';

class ChartWithParameters extends React.PureComponent {
  render() {
    return (
      <LinearChart
        belowAverageValue={"3"}
        averageValue={"7"}
        highValue={"8"}
        existingValue={"5"}
      />
    );
  }
}

export default ChartWithParameters;

linearChart.tsx
import React from 'react';
import ReactFC from 'react-fusioncharts';
import FusionCharts from 'fusioncharts';
import Widgets from 'fusioncharts/fusioncharts.widgets';

ReactFC.fcRoot(FusionCharts, Widgets);

interface IOwnProps {
  belowAverageValue: string;
  averageValue: string;
  highValue: string;
  existingValue: string;
}

type IProp = IOwnProps;

class LinearChart extends React.PureComponent<IProp> {
  render() {
    const linearChartConfigs = {
      type : 'hlineargauge',
      width : '700',
      height : '150',
      dataFormat : 'json',
      dataSource : {
        chart: {
          caption: "Example Flow Chart",
          bgColor: '#f7fcff',
          upperLimit: this.props.highValue,
          chartTopMargin: '20',
          chartBottomMargin: '20',
          valueFontSize: '12',
          gaugeFillMix: '{light-30}',
          showValue: '1',
          majorTMNumber: '11',
          majorTMColor: '#1e5779',
          showBorder: '0',
        },
        colorRange: {
          color: [
            {
              maxValue: this.props.averageValue,
              code: '#FFC533',
              label: "averageValue",
            },
            {
              maxValue: this.props.belowAverageValue,
              code: '#F2726F',
              label: "belowAverageValue",
            },
            {
              maxValue: this.props.highValue,
              code: '#62B58F',
              label: "highValue",
            },
          ],
        },
        pointers: {
          pointer: [
            {
              value: this.props.existingValue,
              showValue: '0',
              radius: '10',
              bgColor: '#6400ff',
              BorderColor: '#6400ff',
            },
          ],
        },
        trendPoints: {
          point: [
            {
              startValue: this.props.existingValue,
              endValue: this.props.highValue,
              thickness: '1',
              markerColor: '#0075c2',
              markerBorderColor: '#666666',
              markerRadius: '5',
              alpha: '30',
              displayValue: ' ',
            },
            {
              startValue: this.props.averageValue,
              thickness: '1',
              useMarker: '1',
              markerColor: '#87dc9',
              markerBorderColor: '#fff',
              markerRadius: '5',
              displayValue: ('average' + '<br/>' + 'count:' + this.props.averageValue + '<br/>'),
            },
            {
              startValue: this.props.belowAverageValue,
              thickness: '1',
              useMarker: '1',
              markerColor: '#f5be416',
              markerBorderColor: '#fff',
              markerRadius: '5',
              displayValue: ('below average' + '<br/>' + 'count:' +this.props.belowAverageValue + '<br/>'),
            },
          ],
        },
      },
    };

    return <ReactFC {...linearChartConfigs} />;
  }
}

export default LinearChart;












references:
https://www.fusioncharts.com/react-charts
https://www.fusioncharts.com/charts/gauges/linear-scale-gauge

React >> tooltip example with typescript (material-ui)

npm install @material-ui/core --save
  
tooltipExample.tsx
**   enterDelay={100}  >> tooltip is displayed in 100ms
**   leaveDelay={200} >> tooltip hides in 200ms
**  "On mobile, the tooltip is displayed when the user longpresses the element. You can disable this feature with the disableTouchListener property." ( references: https://material-ui.com/components/tooltips/ )
import React from 'react';
import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip';
import './tooltipExample.scss';
import ArrowTooltip from '../../commons/arrowTooltip/arowTooltip';

const listItems = ["tooltip 1", "tooltip 2", "tooltip 3", "tooltip 4"];

class TooltipExample extends React.PureComponent {
  render() {
    return (
      <>
        <div className="custom-margin">
          <strong>Tooltip at the left on the icon</strong>
          <Tooltip
            title={listItems.map((item:string, idx: number) => <li key={idx}>{item}</li>)}
            placement="right"
            enterDelay={100}
            leaveDelay={200}
          >
            <span className="info" />
          </Tooltip>
        </div>

        <div className="custom-margin">
          <strong>ArrowTooltip at the left on the icon</strong>
          <ArrowTooltip
            title={listItems.map((item:string, idx: number) => <li key={idx}>{item}</li>)}
            placement="right"
            enterDelay={100}
            leaveDelay={200}
          >
            <span className="info" />
          </ArrowTooltip>
        </div>

        <div className="custom-margin">
          <Tooltip
            title="Tooltip at the bottom on the button"
            placement="bottom-start"
            enterDelay={100}
            leaveDelay={200}
          >
            <Button>Button example</Button>
          </Tooltip>
        </div>

      </>
    );
  }
}

export default TooltipExample;

tooltipExample.scss
(you should also add a file named as info.svg in the project)
.info {
  display: inline-block;
  background: url(./info.svg) no-repeat;
  background-size: 13px 18px;
  width: 15px;
  height: 20px;
  margin-left: 3px;
}

.custom-margin {
  margin-bottom: 25px;
}

arrowTooltip.tsx ( references: https://material-ui.com/components/tooltips/ )
import React from 'react';
import { Theme, makeStyles, createStyles } from '@material-ui/core/styles';
import Tooltip, { TooltipProps } from '@material-ui/core/Tooltip';
import PropTypes from 'prop-types';

function arrowGenerator(color: string) {
  return {
    '&[x-placement*="bottom"] $arrow': {
      top: 0,
      left: 0,
      marginTop: '-0.95em',
      width: '3em',
      height: '1em',
      '&::before': {
        borderWidth: '0 1em 1em 1em',
        borderColor: `transparent transparent ${color} transparent`,
      },
    },
    '&[x-placement*="top"] $arrow': {
      bottom: 0,
      left: 0,
      marginBottom: '-0.95em',
      width: '3em',
      height: '1em',
      '&::before': {
        borderWidth: '1em 1em 0 1em',
        borderColor: `${color} transparent transparent transparent`,
      },
    },
    '&[x-placement*="right"] $arrow': {
      left: 0,
      marginLeft: '-0.95em',
      height: '3em',
      width: '1em',
      '&::before': {
        borderWidth: '1em 1em 1em 0',
        borderColor: `transparent ${color} transparent transparent`,
      },
    },
    '&[x-placement*="left"] $arrow': {
      right: 0,
      marginRight: '-0.95em',
      height: '3em',
      width: '1em',
      '&::before': {
        borderWidth: '1em 0 1em 1em',
        borderColor: `transparent transparent transparent ${color}`,
      },
    },
  };
}

const useStylesArrow = makeStyles((theme: Theme) =>
  createStyles({
    tooltip: {
      position: 'relative',
    },
    arrow: {
      position: 'absolute',
      fontSize: 6,
      width: '3em',
      height: '3em',
      '&::before': {
        content: '""',
        margin: 'auto',
        display: 'block',
        width: 0,
        height: 0,
        borderStyle: 'solid',
      },
    },
    popper: arrowGenerator(theme.palette.grey[700]),
  }),
);

export default function ArrowTooltip(props: TooltipProps) {
  const { arrow, ...classes } = useStylesArrow();
  const [arrowRef, setArrowRef] = React.useState<HTMLSpanElement | null>(null);

  return (
    <Tooltip
      classes={classes}
      PopperProps={{
        popperOptions: {
          modifiers: {
            arrow: {
              enabled: Boolean(arrowRef),
              element: arrowRef,
            },
          },
        },
      }}
      {...props}
      title={
        <React.Fragment>
          {props.title}
          <span className={arrow} ref={setArrowRef} />
        </React.Fragment>
      }
    />
  );
}

ArrowTooltip.propTypes = {
  title: PropTypes.node,
};

screenshots:


 


Wednesday

REST API Naming Conventions

1. Do not use slash(/) at the last character of the URI
http://localhost:8080/user-authorization/users/   /* Don't */
http://localhost:8080/user-authorization/users   /* Do */

2. Use hypens (-), use lowercase letters, do not use underscore (_), do not use file extension
http://localhost:8080/userAuthorization/homeButtons          /* Don't */
http://localhost:8080/user_authorization/home_buttons        /* Don't */
http://localhost:8080/USER-AUTHORIZATION/HOME_BUTTONS        /* Don't */
http://localhost:8080/user-authorization/home-buttons.xml    /* Don't. if you want to show media type, use Content-Type header */

http://localhost:8080/user-authorization/home-buttons        /* Do */

3.If you have a hierarchical relation (like user's buttons, user's sidebar buttons) then divide this relation by using slash.
http://localhost:8080/users-buttons                /* Don't */
http://localhost:8080/users-sidebar-buttons/{id}   /* Don't */

http://localhost:8080/users/{id}/buttons            /* Do */
http://localhost:8080/users/{id}/sidebar-buttons    /* Do */     

4. Example for returning collection or a singular object:
http://localhost:8080/user-authorization/cards         /* Use this if you will return a collection of card */
http://localhost:8080/user-authorization/cards/{id}    /* Use this if only the given card will return  */

5. Do not use crud function names like get, delete, update, create.
HTTP request methods (GET, PUT, POST, DELETE) should indicate the type of the function.
/* Get given user's cards */
HTTP GET http://localhost:8080/users/{id}/cards   

/* Get given user's card for given id */
HTTP GET http://localhost:8080/users/{id}/cards/{id}  

/* create card for given user */
HTTP POST http://localhost:8080/users/{id}/cards

/* Update card for given user */
HTTP PUT http://localhost:8080/users/{id}/cards/{id}  

/* Delete card for given user */
HTTP DELETE http://localhost:8080/users/{id}/cards/{id}  

6. If you need parameters like sorting, filtering, limiting then use query parameters.
http://localhost:8080/users?sort=registration-date

Intellij: 'string template are not supported by current javascript version' error

Intellij gives following error on my react project:
  • string template are not supported by current javascript version
 FIX: 
Go to File >> Settings >> Languages & Frameworks >> Javascript
Change "Javascript language version" to "React JSX" then click to OK and wait for indexing.

Friday

React.js: dynamic sidebar example with typescript

I'm trying to implement a generic sidebar in my react project.
* I used prime react sidebar.
* It can be used multiple times in the page/application
* It loads different prime react buttons for every sidebar.
* For every sidebar its own onclick function is called when buttons has clicked.

Example screenshots:























project structure:




















index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import App from './components/app';
import reducer from './reducer/reducer';

const rootReducer = combineReducers(
  { reducer: reducer}
 );
const store = createStore(rootReducer);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
app.tsx
import React from 'react';
import { connect } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import Home from './home/home';
import { SET_USER } from '../static/reducerActionTypes';

interface IDispatchProps {
    setUser: (user: string) => void;
}

type IProp = IDispatchProps;

class App extends React.PureComponent<IProp> {
    constructor(props: IProp) {
        super(props);
    }

    componentDidMount() {
        const { setUser } = this.props;
        setUser('Eda Merdan Biricik');
    }

    componentWillUnmount() {
        const { setUser } = this.props;
        setUser('');
    }

    render() {
        return (
            <Router>
                <div className="app">
                    <Home />
                </div>
            </Router>
        );
    }
}

const mapDispatchToProps = (dispatch: any) => ({
    setUser: (user: string) => {
        dispatch({
            user,
            type: SET_USER,
        });
    },
});

export default connect(null, mapDispatchToProps)(App);
home.tsx
import React from 'react';
import MyLeftSidebar from "../sidebar/myLeftSidebar";
import MyRightSidebar from "../sidebar/myRightSidebar";

export default () => (
    <>
        <div>
            <MyLeftSidebar />
        </div>
        <div>
             <MyRightSidebar />
        </div>
    </>
);
myLeftSidebar.tsx
import React from 'react';
import { connect } from 'react-redux';
import CommonSidebar from '../../commons/sidebar/commonSidebar';

const sidebarParameters = {
    fetchApiParameter: 'left',
    reducerKey: 'leftSidebarButtons',
    position: 'left',
};

interface IStateProps {
    user: string;
}

type IProp = IStateProps;

class MyLeftSidebar extends React.PureComponent<IProp> {
    constructor(props: IProp) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(params: any) {
        alert('do want you want. my params: ' + params);
    }

    render() {
        const { user } = this.props;

        return (
            <>
                {user !== null &&
                <CommonSidebar
                    handleOnClick={this.handleClick}
                    sidebarParameters={sidebarParameters}
                />
                }
            </>
        );
    }
}

const mapStateToProps = ({ reducer }: any): IStateProps => {
    return {
        user: reducer.get('user', null),
    };
};

export default connect(mapStateToProps, null)(MyLeftSidebar);
myRightSidebar.tsx
import React from 'react';
import { connect } from 'react-redux';
import CommonSidebar from '../../commons/sidebar/commonSidebar';

const sidebarParameters = {
    fetchApiParameter: 'right',
    reducerKey: 'rightSidebarButtons',
    position: 'right',
};

interface IStateProps {
    user: string;
}

type IProp = IStateProps;

class MyRightSidebar extends React.PureComponent<IProp> {
    constructor(props: IProp) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(params: any) {
        alert('do want you want. my params: ' + params);
    }

    render() {
        const { user } = this.props;

        return (
            <>
                {user !== null &&
                <CommonSidebar
                    handleOnClick={this.handleClick}
                    sidebarParameters={sidebarParameters}
                />
                }
            </>
        );
    }
}

const mapStateToProps = ({ reducer }: any): IStateProps => {
    return {
        user: reducer.get('user', null),
    };
};

export default connect(mapStateToProps, null)(MyRightSidebar);
reducerActionTypes.ts
export const SET_SIDEBAR_BUTTONS = 'SET_SIDEBAR_BUTTONS';
export const SET_USER = 'SET_USER';
reducer.ts
import I from 'immutable';
import { SET_SIDEBAR_BUTTONS, SET_USER } from '../static/reducerActionTypes';

interface Action {
    type: string;
    data: any;
    user: string;
}

export default (state: any = I.Map(), action: Action) => {
    switch (action.type) {

        case SET_USER:
            return state.set('user', action.user);

        case SET_SIDEBAR_BUTTONS:
            const { data: { key = '', buttons = I.Map() } = {} } = action;
            return state.set(key, buttons);

        default:
            return state;
    }
};
commonSidebar.tsx
import React from 'react';
import I from 'immutable';
import { connect } from 'react-redux';
import { Sidebar } from 'primereact/sidebar';
import  { CommonSidebarButton } from './commonSidebarButton';
import { getSidebarButtons } from '../../apis/sidebarAPI';
import { SET_SIDEBAR_BUTTONS } from '../../static/reducerActionTypes';
import 'primereact/resources/themes/nova-light/theme.css';
import 'primereact/resources/primereact.min.css';
import './commonSidebar.scss';

interface ISidebarParameters {
    fetchApiParameter: string;
    reducerKey: string;
    position: string;
}

interface IOwnProps {
    handleOnClick: (params: object) => void;
    sidebarParameters: ISidebarParameters;
}

interface IDispatchProps {
    setSidebarButtons: (buttons: any) => void;
}

interface IStateProps {
    sidebarButtons: any;
    user: string;
}

type IProp = IOwnProps & IDispatchProps & IStateProps;

class CommonSidebar extends React.PureComponent<IProp> {
    constructor(props: IProp) {
        super(props);
        this.renderButtons = this.renderButtons.bind(this);
    }

    async componentDidMount() {
        const { setSidebarButtons, sidebarParameters, user } = this.props;
        const buttons = await getSidebarButtons(sidebarParameters.fetchApiParameter, user);
        setSidebarButtons(buttons);
    }

    componentWillUnmount(): void {
        const { setSidebarButtons } = this.props;
        setSidebarButtons(I.Map());
    }

    renderButtons() {
        const { sidebarButtons } = this.props;
        const isSuccess = I.List.isList(sidebarButtons);
        const sortedSidebarButtons = isSuccess && sidebarButtons.sortBy((s: any) => s.get('orderNo'));

        return(
            <div >
                {isSuccess &&
                sortedSidebarButtons.map((button:any, idx: number) => (
                    <CommonSidebarButton
                        button={button}
                        handleOnClick={this.props.handleOnClick}
                        key={idx}
                    />
                ))
                }
            </div>
        );
    }

    render() {
        const { position } = this.props.sidebarParameters;

        return(
            <Sidebar
                className="common-sidebar"
                modal={false}
                visible
                onHide={() => null}
                showCloseIcon={false}
                baseZIndex={1}
                position={position}
            >
                {this.renderButtons()}
            </Sidebar>
        );
    }
}

const mapStateToProps = ({ reducer }: any, ownProps: IOwnProps): IStateProps => {
    return {
        sidebarButtons: reducer.getIn([ownProps.sidebarParameters.reducerKey, 'data'], I.List()),
        user: reducer.get('user', ''),
    };
};

const mapDispatchToProps = (dispatch: any, ownProps: IOwnProps): IDispatchProps => ({
    setSidebarButtons: (data: any) => {
        dispatch({
            data: { buttons: data, key: ownProps.sidebarParameters.reducerKey },
            type: SET_SIDEBAR_BUTTONS,
        });
    },
});

export default connect<IStateProps, IDispatchProps, IOwnProps>(
    mapStateToProps,
    mapDispatchToProps
)(CommonSidebar);
commonSidebarButton.tsx
import React from 'react';
import { Button } from 'primereact/button';
import 'primereact/resources/themes/nova-light/theme.css';
import 'primereact/resources/primereact.min.css';
import 'primeicons/primeicons.css';
import './commonSidebar.scss';

export const CommonSidebarButton = ({ button, handleOnClick }: any) => (
    <Button
        label={button.get('iconLabel')}
        icon={button.get('iconName')}
        onClick={() => handleOnClick(button.get('payload'))}
    />
);
commonSidebar.scss
body {
  div {
    .common-sidebar {
      background: #2c7f33;
      width: 70px;
    }
  }
}

body {
  .p-sidebar {
    border: 0px ;
    padding:0px;
  }

  .p-button {
    background-color: transparent;
    border-color: #2c7f33;
    color: #ffffff;
    font-size: 12px;
    padding: 10px 5px;
    margin-top: 10px;
  }

  .p-button.p-button-icon-only {
    width: 100%;
  }

  .pi {
    font-size: 3.00em;
  }

  .p-button.p-button-text-icon-left .p-button-text {
    padding: 0px;
  }

  .p-button.p-button-icon-only .p-button-text {
    display: none;
  }

  .p-button:enabled:active {
    background-color: #1b9e1c;
    border-color: #ffffff;
  }

  .p-button:enabled:focus {
    box-shadow: 0 0 0 0.1em red;
  }

  .p-button:enabled:hover {
    background-color: #1b9e1c;
    border-color: #ffffff;
  }
}

.p-button-icon-only .p-button-icon-left, .p-button-text-icon-left .p-button-icon-left {
  position: initial;
}

.p-button-text {
  color: #ffffff;
  font-size: 9px;
}

.p-button-icon-only .p-button-icon-left{
  margin-top: 0px;
  margin-left: 0px;
}
sidebarAPI.ts
import axios from 'axios';
import I from 'immutable';

export const getSidebarButtons = async(sidebarType: string, user: string) => {
    try {
        const { data } = await axios.get(
            `http://localhost.../getSidebarButtons?sidebarType=${sidebarType}&user=${user}`);
        return I.fromJS({ data });

    } catch (e) {
        return I.fromJS({
            data: {
                error: 'Error while fetching sidebar buttons',
            },
        });
    }
};
For this dynamic loading a rest api has called. It takes 2 parameter -sidebarType, user- to decide which parameters should return.
An example of  rest api result: (sidebarType is 'left')
[{
"id":"1","orderNo":"2","iconName":"pi pi-bell",
  "iconLabel":"Give Your Icon Label If You Want",
  "payload":{"params":{"componentPath":"/test"}}
},
{
"id":"2","orderNo":"3","iconName":"pi pi-check",
  "payload":{"params":{"componentPath":"/test"}}
},
{
"id":"3","orderNo":"1","iconName":"pi pi-times",
  "iconLabel":"Give Your Icon Label If You Want",
  "payload":{"params":{"componentPath":"/test"}}
}]
for sidebarType = 'right'
[{
"id":"1","orderNo":"2","iconName":"pi pi-bell",
  "iconLabel":"Give Your Icon Label If You Want",
  "payload":{"params":{"componentPath":"/test"}}
}]

Thursday

Fragments in React (No more unnecessary nodes in the DOM)

React.Fragment advantages:
- return elements without any extra div or any other tags
- return a list of child without having a parent node. No more wrapping elements.

Requirements:
- Babel v7.0.0-beta.31 and above
- React v16.2.0 and above

Normally you can not the following, you have to wrap it.
import React, { Component } from 'react';

class FragmentExample extends Component {
  render() {
      return (
          <li>One</li>
          <li>Two</li>
      );
    }
  }
  
export default FragmentExample;

Before react@16, you have to wrap with any tag like <ul> || <span>.
But no need anymore with Fragment.
import React, { Component, Fragment } from 'react';

class FragmentExample extends Component {
  render() {
      return (
        <Fragment>
          <li>One</li>
          <li>Two</li>
        </Fragment>
      );
    }
  }
  
export default FragmentExample;

Short syntax:
class FragmentExample extends Component {
  render() {
      return (
        <>
          <li>One</li>
          <li>Two</li>
        </>
      );
    }
  }
  
export default FragmentExample;

Wednesday

How to use enums as props in react with typescript

myConstants.ts
export enum SIZE_TYPES {
  FULL = 'full',
  SMALL = 'small',
}

myClass.tsx
.
.
import { SIZE_TYPES } from '../static/myConstants';

interface Prop {
  sizeType: SIZE_TYPES;
}

class MyClass extends React.PureComponent<Prop> {
 .
 .
}

myClass2.tsx
.
.
import { SIZE_TYPES } from '../static/myConstants';

class MyClass2 extends React.PureComponent {
  render() {
    return (
        <MyClass sizeType={SIZE_TYPES.FULL}/>
    );
  }
}

Thursday

jquery dialog example

HTML:
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>position demo</title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
  <script src="https://code.jquery.com/jquery-1.9.1.js"></script>
  <script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
</head>

<body>
 <table id="table">
   <tr>
     <td style="padding:0px 0px; border-top:0px 0px; width:100%;">
        <div id="header">Header</div>
     </td>
     <td rowspan="2" style="padding:0px 0px 0px; border-top:0px; width:100%;">
         <div id="sidebar" >
           Sidebar
         </div>
      </td>
  </tr>
   <tr>
      <td style="width: 100%;padding:0px 0px 0px; border-top:0px; width:100%;">
        <div id="content" >
           <button type="button" id="opener1">Open the dialog full</button>
           <button type="button" id="opener2">Open the dialog half</button>
        </div>
      </td>
   </tr>
 </table>

   <div id="dialog" >Dialog</div>
    
</body>
</html>
CSS:
#dialog {   
    background: green;
    font-size: 24pt;
    text-align: center;
}

#header {
  border: solid 1px;
  height: 20px;
  width: 100%;
  margin-top: 20px;
}

#content {
  border: solid 1px;
  margin-top: 0px;
  margin-right: 0px;
  height: 300px;
  width: 100%;
}

#sidebar {
  border: solid 1px;
  margin-top: 20px;
  margin-left: 0px;
  height: 324px;
  width: 55px;
}

.ui-dialog-titlebar-close, .ui-dialog-titlebar {
  display: none;
}

.ui-dialog {
    z-index: 999999 !important ;
    margin-left: 0px;
}

.ui-dialog, .ui-dialog-content {
    box-sizing: content-box;
}
JS:
 function closeDilalogIfClickedOutside(event) {
    if($('#dialog').dialog('isOpen')
        && !($('#dialog')).is(event.target)
        && $('#dialog').has(event.target).length == 0 ) {
            $('#dialog').dialog('close');
    }
}

$(window).on("click", function(event){   
    closeDilalogIfClickedOutside(event);
});

function catchOutsideClickEvent() {
    var i;
    for(i = 0; i < (window.frames).length; i++) {
        try {
            var win = window.frames[i];
            if(win.frameElement.id != 'dialogIframe') {
                $(win).on("click", function(event){   
                    closeDilalogIfClickedOutside(event);
                });         
            }
        } catch(err) {
            console.log("frame: " + i + " y:" + y + " err: " + err);
        };
    };
}
$(document).ready(function () {
  $(function() {
    $("#dialog").dialog({
        autoOpen: false, 
        modal: false,
        hide: {effect:"slide", direction:"right", duration: 700},
        show : {effect:"slide", direction:"right", duration: 700},
        open: function(event, ui) {
            catchOutsideClick();
        }
    });
  });
});

function resizeDialog(sizeType) {
    var relativeDiv, relativeHeight, relativeWidth, relativeMy;

    if(sizeType == 'full') {
        relativeDiv = '#sidebar';
        relativeHeight = $('#sidebar').height();
        relativeWidth = '200';
        relativeMy = 'left top';

    } else {
        relativeDiv = '#content';
        relativeHeight =  $('#content').height();
        relativeWidth = $(window).width() / 2;
        relativeMy = 'right top';
    }

    $("#dialog").dialog({
        width:relativeWidth,
        height:relativeHeight,
        position: {
            my: relativeMy,
            at: relativeMy,
            of: relativeDiv
        }
    });
}

$('#opener1').click(function() {
      resizeDialog("full");
      $("#dialog").dialog("open");
});

$('#opener2').click(function() {
      resizeDialog("half");
      $("#dialog").dialog("open");
});


var resizeId;
$(window).bind('resize', function(event) {
    if($('#dialog').dialog('isOpen') && !$(event.target).hasClass('ui-resizable')){
      clearTimeout(resizeId);
      resizeId = setTimeout(resizeDialog, 250);
    }
});