text:
<file_sep>import {throttle} from '../helpers/throttle';

export const persist = ({key, blacklist = [], whitelist = []}: { key: string, blacklist?: string[], whitelist?: string[] }) => {
  return next => (reducer, initialState) => {
    if (!window.localStorage) {
      return next(reducer, initialState);
    }
    let persistedState = JSON.parse(localStorage.getItem(key));
    let finalInitialState = persistedState ? {...initialState, ...persistedState} : initialState;

    const store = next(reducer, finalInitialState);
    const exclude = (obj, keys) => {
      if (!keys.length) return obj;
      let target = {};
      for (let i in obj) {
        if (keys.indexOf(i) >= 0) continue;
        if (!Object.prototype.hasOwnProperty.call(obj, i))
          continue;
        target[i] = obj[i];
      }
      return target;
    };
    const saveStore = (state) => {
      const target = exclude(state, blacklist);
      blacklist.forEach(path => {
        let route = path.split('.');
        if (route.length == 2) {
          target[route[0]] = exclude(target[route[0]], [route[1]])
        }
      });
      const data = {};
      whitelist.forEach(path => {
        data[path] = target[path];
      });
      localStorage.setItem(key, JSON.stringify(data));
    };

    store.subscribe(throttle(() => {
      const state = store.getState();
      saveStore(state);
    }, 1000));
    return store
  }
};
<file_sep>import * as React            from 'react';
import {RouteComponentProps} from 'react-router-dom';
import {dropWhile, slice}    from 'lodash';

import {
  EuiBasicTable,
  EuiTable,
  EuiTableHeaderCell,
  EuiTableHeader,
  EuiTableHeaderCellCheckbox,
  EuiCheckbox,
  EuiTableBody,
  EuiIcon,
  EuiTableRowCell,
  EuiTableRow,
  EuiToolTip,
}                                from "@elastic/eui";
import {EuiDescriptionList}      from "@elastic/eui";
import {EuiButtonIcon}           from "@elastic/eui";
import {EuiButton}               from "@elastic/eui";
import {EuiTitle}                from "@elastic/eui";
import {EuiForm}                 from '@elastic/eui';
import {EuiModal}                from '@elastic/eui';
import {EuiOverlayMask}          from '@elastic/eui';
import {EuiModalHeader}          from '@elastic/eui';
import {EuiModalHeaderTitle}     from '@elastic/eui';
import {EuiModalBody}            from '@elastic/eui';
import {EuiModalFooter}          from '@elastic/eui';
import {EuiTableRowCellCheckbox} from '@elastic/eui';
import {SortDirection}           from '@elastic/eui';
import {EuiButtonEmpty}          from '@elastic/eui';
import {EuiSpacer}               from '@elastic/eui';
import {RIGHT_ALIGNMENT}         from '@elastic/eui/lib/services';
import {EuiKeyboardAccessible} from '@elastic/eui/lib/services';
import {LEFT_ALIGNMENT}        from '@elastic/eui/lib/services';
import {formatAuto}            from '@elastic/eui/lib/services';
import {formatText}            from '@elastic/eui/lib/services';
import {formatNumber}          from '@elastic/eui/lib/services';
import {formatBoolean}         from '@elastic/eui/lib/services';
import {formatDate}            from '@elastic/eui/lib/services';
import {CollapsedItemActions}  from "./CollapsedItemActions";
import {DefaultItemAction}     from "./DefaultItemAction";
import {ExpandedItemActions}   from "./ExpandedItemActions";
import {LoadingTableBody}      from "./LoadingTableBody";

const dataTypesProfiles = {
  auto: {
    align: LEFT_ALIGNMENT,
    render: value => formatAuto(value)
  },
  string: {
    align: LEFT_ALIGNMENT,
    render: value => formatText(value)
  },
  number: {
    align: RIGHT_ALIGNMENT,
    render: value => formatNumber(value),
  },
  boolean: {
    align: LEFT_ALIGNMENT,
    render: value => formatBoolean(value),
  },
  date: {
    align: LEFT_ALIGNMENT,
    render: value => formatDate(value),
  }
};

export class Table extends React.Component<TableProps, TableState> {

  static buildCriteria(props) {
    const criteria: any = {};
    if (props.pagination) {
      criteria.page = {
        index: props.pagination.pageIndex,
        size: props.pagination.pageSize
      };
    }
    if (props.sorting) {
      criteria.sort = props.sorting.sort;
    }
    return criteria;
  }

  static getItemId(item, itemId) {
    if (itemId) {
      if (typeof itemId == 'function') {
        return itemId(item);
      }
      return item[itemId];
    }
  }

  static getRowProps(item, rowProps) {
    if (rowProps) {
      if (typeof rowProps == 'function') {
        return rowProps(item);
      }
      return rowProps;
    }
    return {};
  }

  static getCellProps(item, column, cellProps) {
    if (cellProps) {
      if (typeof cellProps == 'function') {
      }
      return cellProps;
    }

    return {};
  }

  state = {
    selection:[]
  };

  getRendererForDataType(dataType = 'auto') {
    const profile = dataTypesProfiles[dataType];
    if (!profile) {
      throw new Error(`Unknown dataType [${dataType}].`);
    }
    return profile.render;
  }

  getAlignForDataType(dataType = 'auto') {
    const profile = dataTypesProfiles[dataType];
    if (!profile) {
      throw new Error(`Unknown dataType [${dataType}].`);
    }
    return profile.align;
  }

  resolveColumnSortDirection = (column) => {
    const {sorting} = this.props;
    if (!sorting || !sorting.sort || !column.sortable) {
      return;
    }
    if (sorting.sort.field === column.field) {
      return sorting.sort.direction;
    }
  }

  resolveColumnOnSort = (column) => {
    const {sorting} = this.props;
    if (!sorting || !column.sortable) {
      return;
    }
    if (!this.props.onChange) {
      throw new Error(`BasicTable is configured to be sortable on column [${column.field}] but
          [onChange] is not configured. This callback must be implemented to handle the sort requests`);
    }
    return () => this.onColumnSortChange(column);
  }

  changeSelection(selection) {
    if (!this.props.selection) {
      return;
    }
    this.setState({selection});
    if (this.props.selection.onSelectionChange) {
      this.props.selection.onSelectionChange(selection);
    }
  }

  clearSelection() {
    this.changeSelection([]);
  }

  onColumnSortChange(column) {
    this.clearSelection();
    const currentCriteria = Table.buildCriteria(this.props);
    let direction = 'asc';
    if (currentCriteria && currentCriteria.sort && currentCriteria.sort.field === column.field) {
      direction = SortDirection.reverse(currentCriteria.sort.direction);
    }
    const criteria = {
      ...currentCriteria,
      // resetting the page if the criteria has one
      page: !currentCriteria.page ? undefined : {
        index: 0,
        size: currentCriteria.page.size
      },
      sort: {
        field: column.field,
        direction
      }
    };
    this.props.onChange(criteria);
  }

  renderTableHead() {

    const {items, columns, selection} = this.props;

    const headers = [];

    if (selection) {
      const selectableItems = items.filter(item => (
        !selection.selectable || selection.selectable(item)
      ));

      const checked = this.state.selection &&
        selectableItems.length > 0 &&
        this.state.selection.length === selectableItems.length;

      const disabled = selectableItems.length === 0;

      const onChange = (event) => {
        if (event.target.checked) {
          this.changeSelection(selectableItems);
        } else {
          this.changeSelection([]);
        }
      };

      headers.push(
        <EuiTableHeaderCellCheckbox key="_selection_column_h" width="24px">
          <EuiCheckbox
            id="_selection_column-checkbox"
            type="inList"
            checked={checked}
            disabled={disabled}
            onChange={onChange}
            data-test-subj="checkboxSelectAll"
            aria-label="Select all rows"
          />
        </EuiTableHeaderCellCheckbox>
      );
    }

    columns.forEach((column, index) => {
      const {
        actions,
        width,
        name,
        field,
        align,
        dataType,
        sortable,
        isMobileHeader,
        hideForMobile,
      } = column;

      const columnAlign = align || this.getAlignForDataType(dataType);

      // actions column
      if (actions) {
        headers.push(
          <EuiTableHeaderCell
            key={`_actions_h_${index}`}
            align="right"
            width={width}
          >
            {name}
          </EuiTableHeaderCell>
        );
        return;
      }
      // computed column
      if (!field) {
        headers.push(
          <EuiTableHeaderCell
            key={`_computed_column_h_${index}`}
            align={columnAlign}
            width={width}
          >
            {name}
          </EuiTableHeaderCell>
        );
        return;
      }

      // field data column
      const sorting: any = {};
      if (this.props.sorting && sortable) {
        const sortDirection = this.resolveColumnSortDirection(column);
        sorting.isSorted = !!sortDirection;
        sorting.isSortAscending = sortDirection ? SortDirection.isAsc(sortDirection) : undefined;
        sorting.onSort = this.resolveColumnOnSort(column);
      }
      headers.push(
        <EuiTableHeaderCell
          key={`_data_h_${field}_${index}`}
          align={columnAlign}
          width={width}
          isMobileHeader={isMobileHeader}
          hideForMobile={hideForMobile}
          data-test-subj={`tableHeaderCell_${field}_${index}`}
          {...sorting}
        >
          {name}
        </EuiTableHeaderCell>
      );
    });

    return <EuiTableHeader>{headers}</EuiTableHeader>;
  }

  renderErrorBody(error) {
    const colSpan = this.props.columns.length + (this.props.selection ? 1 : 0);
    return (
      <EuiTableBody>
        <EuiTableRow>
          <EuiTableRowCell align="center" colSpan={colSpan} isMobileFullWidth={true}>
            <EuiIcon type="minusInCircle" color="danger"/> {error}
          </EuiTableRowCell>
        </EuiTableRow>
      </EuiTableBody>
    );
  }

  renderEmptyBody() {
    const {columns, selection, noItemsMessage} = this.props;
    const colSpan = columns.length + (selection ? 1 : 0);
    return (
      <EuiTableBody>
        <EuiTableRow>
          <EuiTableRowCell align="center" colSpan={colSpan} isMobileFullWidth={true}>
            {noItemsMessage}
          </EuiTableRowCell>
        </EuiTableRow>
      </EuiTableBody>
    );
  }

  renderItemSelectionCell(itemId, item, selected) {
    const {selection} = this.props;
    const key = `_selection_column_${itemId}`;
    const checked = selected;
    const disabled = selection.selectable && !selection.selectable(item);
    const title = selection.selectableMessage && selection.selectableMessage(!disabled, item);
    const onChange = (event) => {
      if (event.target.checked) {
        this.changeSelection([...this.state.selection, item]);
      } else {
        const {itemId: itemIdCallback} = this.props;
        this.changeSelection(this.state.selection.reduce((selection, selectedItem) => {
          if (Table.getItemId(selectedItem, itemIdCallback) !== itemId) {
            selection.push(selectedItem);
          }
          return selection;
        }, []));
      }
    };
    return (
      <EuiTableRowCellCheckbox key={key}>
        <EuiCheckbox
          id={`${key}-checkbox`}
          type="inList"
          disabled={disabled}
          checked={checked}
          onChange={onChange}
          title={title}
          aria-label="Select this row"
          data-test-subj={`checkboxSelectRow-${itemId}`}
        />
      </EuiTableRowCellCheckbox>
    );
  }

  renderItemActionsCell(itemId, item, column, columnIndex) {
    const actionEnabled = (action) =>
      this.state.selection.length === 0 && (!action.enabled || action.enabled(item));

    let actualActions = column.actions;
    if (column.actions.length > 2) {

      // if any of the actions `isPrimary`, add them inline as well, but only the first 2
      actualActions = slice(dropWhile(column.actions, function (o) {
        return !o.isPrimary;
      }), 0, 2);

      // if we have more than 1 action, we don't show them all in the cell, instead we
      // put them all in a popover tool. This effectively means we can only have a maximum
      // of one tool per row (it's either and normal action, or it's a popover that shows multiple actions)
      //
      // here we create a single custom action that triggers the popover with all the configured actions

      actualActions.push(
        {
          name: 'All actions',
          render: (item) => {
            return (
              <CollapsedItemActions

                actions={column.actions}
                itemId={itemId}
                item={item}
                actionEnabled={actionEnabled}
              />
            );
          }
        }
      );
    }

    const tools = (
      <ExpandedItemActions
        actions={actualActions}
        itemId={itemId}
        item={item}
        actionEnabled={actionEnabled}
      />
    );
    const key = `record_actions_${itemId}_${columnIndex}`;
    return (
      <EuiTableRowCell
        showOnHover={true}
        key={key}
        align="right"
        textOnly={false}
        hasActions={true}
      >
        {tools}
      </EuiTableRowCell>
    );
  }

  renderItemFieldDataCell(itemId, item, column, columnIndex) {
    const {field, render, dataType} = column;

    const key = `_data_column_${field}_${itemId}_${columnIndex}`;
    const contentRenderer = render || this.getRendererForDataType(dataType);
    const value = item[field];
    const content = contentRenderer(value, item);

    return this.renderItemCell(item, column, key, content);
  }

  renderItemComputedCell(itemId, item, column, columnIndex) {
    const {render, dataType} = column;

    const key = `_computed_column_${itemId}_${columnIndex}`;
    const contentRenderer = render || this.getRendererForDataType(dataType);
    const content = contentRenderer(item);

    return this.renderItemCell(item, column, key, content);
  }

  renderItemCell(item, column, key, content) {
    const {
      align,
      render,
      dataType,
      isExpander,
      textOnly,
      name,
      field, // eslint-disable-line no-unused-vars
      description, // eslint-disable-line no-unused-vars
      sortable, // eslint-disable-line no-unused-vars
      footer, // eslint-disable-line no-unused-vars
      ...rest
    } = column;
    const columnAlign = align || this.getAlignForDataType(dataType);
    const {cellProps: cellPropsCallback} = this.props;
    const cellProps = Table.getCellProps(item, column, cellPropsCallback);

    return (
      <EuiTableRowCell
        key={key}
        align={columnAlign}
        header={name}
        isExpander={isExpander}
        textOnly={textOnly || !render}
        {...cellProps}
        {...rest}
      >
        {content}
      </EuiTableRowCell>
    );
  }

  renderItemRow(item, rowIndex) {
    const {columns, selection, isSelectable, hasActions, itemIdToExpandedRowMap = {}, isExpandable} = this.props;

    const cells = [];

    const {itemId: itemIdCallback} = this.props;
    const itemId = Table.getItemId(item, itemIdCallback) || rowIndex;
    const selected = !selection ? false : this.state.selection && !!this.state.selection.find(selectedItem => (
      Table.getItemId(selectedItem, itemIdCallback) === itemId
    ));

    let calculatedHasSelection;
    if (selection) {
      cells.push(this.renderItemSelectionCell(itemId, item, selected));
      calculatedHasSelection = true;
    }

    let calculatedHasActions;
    columns.forEach((column, columnIndex) => {
      if (column.actions) {
        cells.push(this.renderItemActionsCell(itemId, item, column, columnIndex));
        calculatedHasActions = true;
      } else if (column.field) {
        cells.push(this.renderItemFieldDataCell(itemId, item, column, columnIndex));
      } else {
        cells.push(this.renderItemComputedCell(itemId, item, column, columnIndex));
      }
    });

    // Occupy full width of table, taking checkbox & mobile only columns into account.
    let expandedRowColSpan = selection ? columns.length + 1 : columns.length;

    const mobileOnlyCols = columns.reduce((num, column) => {
      return column.isMobileHeader ? num + 1 : num + 0;
    }, 0);

    expandedRowColSpan = expandedRowColSpan - mobileOnlyCols;

    // We'll use the ID to associate the expanded row with the original.
    const hasExpandedRow = itemIdToExpandedRowMap.hasOwnProperty(itemId);
    const expandedRowId = hasExpandedRow ? `row_${itemId}_expansion` : undefined;
    const expandedRow = hasExpandedRow ? (
      <EuiTableRow id={expandedRowId} isExpandedRow={true} isSelectable={isSelectable}>
        <EuiTableRowCell colSpan={expandedRowColSpan}>
          {itemIdToExpandedRowMap[itemId]}
        </EuiTableRowCell>
      </EuiTableRow>
    ) : undefined;

    const {rowProps: rowPropsCallback} = this.props;
    const rowProps = Table.getRowProps(item, rowPropsCallback);
    const row = (
      <EuiTableRow
        aria-owns={expandedRowId}
        isSelectable={isSelectable == null ? calculatedHasSelection : isSelectable}
        isSelected={selected}
        hasActions={hasActions == null ? calculatedHasActions : hasActions}
        isExpandable={isExpandable}
        {...rowProps}
      >
        {cells}
      </EuiTableRow>
    );

    return (
      <React.Fragment key={`row_${itemId}`}>
        {rowProps.onClick
          ? <EuiKeyboardAccessible>{row}</EuiKeyboardAccessible>
          : row
        }
        {expandedRow}
      </React.Fragment>
    );
  }

  renderTableBody() {
    if (this.props.error) {
      return this.renderErrorBody(this.props.error);
    }
    const {items} = this.props;
    if (items.length === 0) {
      return this.renderEmptyBody();
    }

    const rows = items.map((item, index) => {
      // if there's pagination the item's index must be adjusted to the where it is in the whole dataset
      const tableItemIndex = this.props.pagination ?
        this.props.pagination.pageIndex * this.props.pagination.pageSize + index
        : index;
      return this.renderItemRow(item, tableItemIndex);
    });
    if (this.props.loading) {
      return <LoadingTableBody>{rows}</LoadingTableBody>;
    }
    return <EuiTableBody>{rows}</EuiTableBody>;
  }

  render() {
    return (<EuiTable>
      {this.renderTableHead()}
      {this.renderTableBody()}
    </EuiTable>)
  }
}

export interface TableProps {
  items?: any;
  columns?: any;
  pagination?: any;
  sorting?: any;
  onChange?: any
  selection?: any
  loading?: any
  isSelectable?: any
  isExpandable?: any
  error?: any
  hasActions?: any
  itemIdToExpandedRowMap?: any
  noItemsMessage?: string,
  itemId?: string | ((item) => string)
  rowProps?: any | ((item) => string)
  cellProps?: any | ((item) => string)

}

export interface TableState {
  selection: any
}
    <file_sep>import * as React from 'react';

export class Job extends React.Component<JobProps, JobState> {

  render() {
    return (
Job
)
  }
}

export interface JobProps {
}

export interface JobState {
}
    <file_sep>import {Actions}      from "../actions"
import {AppState}     from "../store/state";
import {initialState} from "../store/state";

export function app(state: AppState = initialState.app, action: Actions): AppState {
  switch (action.type) {
    case Actions.updateSchemas.type: {
      return {...state, ...action.payload}
    }
    case Actions.deleteSchemaData.type: {
      let schemas = state.schemas;
      delete schemas[action.payload.className];
      return {...state, ...{schemas}}
    }
    case Actions.initialized.type: {
      return {...state, ...action.payload}
    }
  }
  return state;
}<file_sep>import * as React   from 'react';
import {NavBar}     from "../../components/NavBar";
import {NavBarItem} from "../../components/NavBarItem";

export class JobNavBar extends React.Component<JobNavBarProps, JobNavBarState> {

  render() {
    return (<NavBar>
      <NavBarItem to={`/job/all`}>Job new</NavBarItem>
      <NavBarItem to={`/job/status`}>Job last</NavBarItem>
    </NavBar>)
  }
}

export interface JobNavBarProps {
}

export interface JobNavBarState {
}
    <file_sep>import * as React            from 'react';
import {EuiTitle}            from "@elastic/eui";
import {EuiForm}             from '@elastic/eui';
import {EuiModal}            from '@elastic/eui';
import {EuiOverlayMask}      from '@elastic/eui';
import {EuiModalHeader}      from '@elastic/eui';
import {EuiModalHeaderTitle} from '@elastic/eui';
import {EuiModalBody}        from '@elastic/eui';
import {EuiModalFooter}      from '@elastic/eui';
import {EuiButtonEmpty}      from '@elastic/eui';
import {EuiButton}           from '@elastic/eui';

export class ConfirmationModal extends React.Component<ConfirmationModalProps, ConfirmationModalState> {

  render() {
    return (
      <EuiOverlayMask>
        <EuiModal
          onClose={this.props.onClose}
        >
          <EuiModalHeader>
            <EuiModalHeaderTitle>
              {this.props.title}
            </EuiModalHeaderTitle>
          </EuiModalHeader>
          <EuiModalBody>
            {this.props.body}
          </EuiModalBody>
          <EuiModalFooter>
            <EuiButtonEmpty onClick={() => {
              this.props.onCancel ? this.props.onCancel() : this.props.onClose()
            }}>Cancel
            </EuiButtonEmpty>
            <EuiButton color="danger" fill onClick={this.props.onConfirm}>{this.props.ctaText}</EuiButton>
          </EuiModalFooter>
        </EuiModal>
      </EuiOverlayMask>
    )
  }
}

export interface ConfirmationModalProps {
  title: string,
  body: string,
  ctaText: string,
  onClose: () => void
  onConfirm: () => void
  onCancel?: () => void
}

export interface ConfirmationModalState {
}
    <file_sep>import {combineReducers} from 'redux';

//
// export default combineReducers({
//   byId,
//   ids,
// });

import {Actions}       from "../../actions"
import {union}         from "../../helpers/array";
import {EntitiesState} from "../../store/state";
import {initialState}  from "../../store/state";

function ids(state: any = [], ids: any): any {
  return union([...state, ...ids]);
}

function byIds(state: any = {}, byId: any): any {
  return {...state, ...byId};
}

function browse(browse: any = {}, payload): any {
  return {...browse, ...payload}
}

export function entities(state: EntitiesState = initialState.entities, action: Actions): EntitiesState {
  switch (action.type) {
    case Actions.errorMessageEntity.type:
    case Actions.updatePagination.type:
    case Actions.updateTableIds.type:
    case Actions.updateExpandedRowMop.type:
    case Actions.updateSortField.type:
    case Actions.updateModal.type:
    case Actions.updateItemModalForm.type:
    case Actions.fetchingEntity.type: {
      let {className, ...payload} = action.payload;
      let entity = state[className] || {byId: {}, ids: [], browse: {}};
      entity.browse = browse(entity.browse, payload);
      return {
        ...state, [className]: {...entity}
      }
    }
    case Actions.updateEntity.type: {
      let {className} = action.payload;
      let entity = state[className] || {byId: {}, ids: [], browse: {}};
      entity.byId = byIds(entity.byId, action.payload.byId);
      entity.ids = ids(entity.ids, action.payload.ids);
      return {
        ...state, [className]: {...entity}
      }
    }
    case Actions.updateEntityItemData.type: {
      let {className, byId} = action.payload;
      let entity = state[className] || {byId: {}, ids: [], browse: {}};
      entity.byId = byIds(entity.byId, byId);
      entity.ids = ids(entity.ids, Object.keys(byId));
      return {
        ...state, [className]: {...entity}
      }
    }
    case Actions.deleteEntityItemData.type: {
      let {className, objectId} = action.payload;
      let entity = state[className] || {byId: {}, ids: [], browse: {}};
      delete entity.byId[objectId];
      entity.byId = {...entity.byId};
      entity.browse.tableIds = entity.browse.tableIds.filter((id) => (id != objectId));
      entity.ids = entity.ids.filter((id) => id != objectId);
      return {
        ...state, [className]: {...entity}
      }
    }
  }
  return state;
}<file_sep>import reducers          from '../reducers';
import {createStore}     from 'redux';
import {applyMiddleware} from 'redux';

import {compose}    from 'redux';
import thunk        from "../middlewares/thunk";
import {persist}    from "./persist";
import {StoreState} from './state';
import {Actions}    from "../actions";

const composeEnhancers =
  typeof window === 'object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
      name: 'parse-dashboard', actionsBlacklist: ['REDUX_STORAGE_SAVE']
    }) : compose;

export const store = createStore<StoreState, Actions, any, any>(
  reducers,
  composeEnhancers(
    applyMiddleware(thunk),
    persist({key: 'elastic-dashboard', whitelist: ['session']})
  )
);
<file_sep>import * as React            from 'react';
import {Form}                from "redux-form";
import {SubmissionError}     from "redux-form";
import {InjectedFormProps}   from "redux-form";
import {EuiForm}             from '@elastic/eui';
import {EuiButton}           from '@elastic/eui';
import {EuiModal}            from '@elastic/eui';
import {EuiOverlayMask}      from '@elastic/eui';
import {EuiModalHeader}      from '@elastic/eui';
import {EuiModalHeaderTitle} from '@elastic/eui';
import {EuiModalBody}        from '@elastic/eui';
import {EuiModalFooter}      from '@elastic/eui';
import {EuiButtonEmpty}      from '@elastic/eui';
import {EuiFlexItem}         from '@elastic/eui';
import {Field}               from 'redux-form';
import {ReduxForm}           from "../../decorators/ReduxForm";
import {WithRouter}          from "../../decorators/WithRouter";
import {getEntityNames}      from "../../selectors/app";
import {StoreState}          from "../../store/state";
import {createSchema}        from "../../actions/AppActions";
import {fetchSchemas}        from "../../actions/AppActions";
import {Input}               from "../../components/form/Input";
import {NavBar}              from "../../components/NavBar";
import {NavBarItem}          from "../../components/NavBarItem";
import {Connected}           from "../../decorators/Connected";

@Connected
@ReduxForm({form: 'add-schema'})
@WithRouter
export class BrowserNavBar extends React.Component<BrowserNavBarProps, BrowserNavBarState> {

  state = {
    isModalVisible: false,
  };

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      return {
        entities: getEntityNames(state),
      }
    })
  }

  @Connected
  get actions() {
    return Connected.actions({fetchSchemas, createSchema})
  }

  closeModal = () => {
    this.setState({isModalVisible: false});
  };

  showModal = () => {
    this.setState({isModalVisible: true});
  };

  onFormSubmit = async ({name}) => {
    try {
      await this.actions.createSchema(name)
      await this.actions.fetchSchemas();
      this.closeModal();
    } catch (e) {
      throw new SubmissionError({name: e.message})
    }
    console.log("On form submit", name)
  };

  renderModal = () => {
    return (this.state.isModalVisible && <EuiOverlayMask>
        <EuiModal
          onClose={this.closeModal}
        >
          <Form onSubmit={this.props.handleSubmit(this.onFormSubmit)}>
            <EuiModalHeader>
              <EuiModalHeaderTitle>
                Add a new class
              </EuiModalHeaderTitle>
            </EuiModalHeader>

            <EuiModalBody>
              <EuiForm>
                <Field name="name" label="Name" component={Input}/>
              </EuiForm>
            </EuiModalBody>

            <EuiModalFooter>
              <EuiButtonEmpty onClick={this.closeModal}>Cancel
              </EuiButtonEmpty>
              <EuiButton isLoading={this.props.submitting} type="submit" fill>Add</EuiButton>
            </EuiModalFooter>
          </Form>
        </EuiModal>
      </EuiOverlayMask>
    );
  };

  render() {
    const {entities} = this.model;

    return (
      <NavBar>
        {entities.map((entityName, index) => (
          <NavBarItem key={index} to={`/browser/${entityName}`}>{entityName}</NavBarItem>)
        )}
        <EuiButton fill={true} onClick={this.actions.fetchSchemas}>Refresh</EuiButton>
        <EuiButton onClick={this.showModal} fill={true}>Add class</EuiButton>
        {this.renderModal()}
      </NavBar>
    )
  }
}

export interface BrowserNavBarProps extends InjectedFormProps {
}

export interface BrowserNavBarState {
}
    <file_sep>import * as React               from 'react';
import {EuiForm}                from '@elastic/eui';
import {EuiButtonEmpty}         from '@elastic/eui';
import {EuiButton}              from '@elastic/eui';
import {RouteComponentProps}    from 'react-router';
import {Field, SubmissionError} from 'redux-form';
import {InjectedFormProps}      from 'redux-form';
import {Form}                   from 'redux-form';
import {Actions}                from "../../../actions";
import {updateEntityItem}       from "../../../actions/EntityActions";
import {deleteEntityItem}       from "../../../actions/EntityActions";
import {Connected}              from "../../../decorators/Connected";
import {ReduxForm}              from "../../../decorators/ReduxForm";
import {WithRouter}             from "../../../decorators/WithRouter";
import {getSchemas}             from "../../../selectors/app";
import {StoreState}             from "../../../store/state";
import {Input}                  from "../../../components/form/Input";

@WithRouter
@Connected
@ReduxForm({form: 'add-row'})
export class AddRowForm extends React.Component<AddRowFormProps, AddRowFormState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      const className = props.match.params.entity;
      const entities: any = state.entities[className] || {};
      const browse = entities.browse || {};
      const itemModalForm = (browse.itemModalForm) || {};
      const mode = itemModalForm.mode;
      return {
        initialValues: (state.entities[className] && state.entities[className].byId
          && state.entities[className].browse
          && state.entities[className].browse.itemModalForm
          && state.entities[className].browse.itemModalForm.objectId
          && state.entities[className].byId[state.entities[className].browse.itemModalForm.objectId]
        ),
        objectId: itemModalForm.objectId,
        tableIds: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.tableIds,
        pageSize: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.pageSize,
        schema: getSchemas(state)[className],
        mode,
      }
    })
  }

  @Connected
  get actions() {
    const updateItemModalForm = Actions.updateItemModalForm;
    const updateTableIds = Actions.updateTableIds;
    return Connected.actions({updateItemModalForm, updateEntityItem, deleteEntityItem, updateTableIds})
  }

  onClose = () => {
    this.actions.updateItemModalForm(this.props.match.params.entity, null)
  };

  onSubmit = async (values) => {
    try {
      const item: any = await this.actions.updateEntityItem(this.props.match.params.entity, values);
      console.log("ITEM ", item)
      this.actions.updateItemModalForm(this.props.match.params.entity, null);
      if (this.model.mode == 'ADD') {
        if (this.model.tableIds.length < this.model.pageSize) {
          this.model.tableIds.push(item.objectId);
          this.actions.updateTableIds(this.props.match.params.entity, this.model.tableIds)
        }
      }
    } catch (e) {
      console.log(e);
      throw new SubmissionError(e.message)
    }
  };

  get editableFields() {
    let nonEditableFields = ['objectId', 'updatedAt', 'createdAt', 'ACL']
    return Object.keys(this.model.schema.fields).filter((fieldName) => (nonEditableFields.indexOf(fieldName) == -1))
  }

  render() {
    return (<Form onSubmit={this.props.handleSubmit(this.onSubmit)}>
      <EuiForm>
        {this.editableFields.map((fieldName, index) => {
          return <Field key={index} name={fieldName} label={fieldName} component={Input}/>
        })}
        <EuiButtonEmpty onClick={this.onClose}>Cancel</EuiButtonEmpty>
        <EuiButton isLoading={this.props.submitting} type="submit" fill>Add</EuiButton>
      </EuiForm>
    </Form>)
  }
}

export interface AddRowFormProps extends Partial<InjectedFormProps>, Partial<RouteComponentProps<{ entity: string }>> {
}

export interface AddRowFormState {
}
    <file_sep>import * as React from 'react';
import {EuiTableBody} from '@elastic/eui';

export class LoadingTableBody extends React.Component<LoadingTableBodyProps, LoadingTableBodyState> {
  tbody: any;
  cleanups: Array<any>;

  constructor(props) {
    super(props);
    this.cleanups = [];
  }

  componentDidMount() {
    const listener = (event) => {
      event.stopPropagation();
      event.preventDefault();
    };
    [
      'mousedown',
      'mouseup',
      'mouseover',
      'mouseout',
      'mouseenter',
      'mouseleave',
      'click',
      'dblclick',
      'keydown',
      'keyup',
      'keypress'
    ].forEach((event) => {
      this.tbody.addEventListener(event, listener, true);
      this.cleanups.push(() => this.tbody.removeEventListener(event, listener));
    });
  }

  componentWillUnmount() {
    this.cleanups.forEach(cleanup => cleanup());
  }

  render() {
    return (
      <EuiTableBody
        bodyRef={(tbody) => {
          this.tbody = tbody;
        }}
      >
        {this.props.children}
      </EuiTableBody>
    );
  }
}

export interface LoadingTableBodyProps {
}

export interface LoadingTableBodyState {
}
    <file_sep>import * as React from 'react';

export class JobStatus extends React.Component<JobStatusProps, JobStatusState> {

  render() {
    return (
JobStatus
)
  }
}

export interface JobStatusProps {
}

export interface JobStatusState {
}
    <file_sep>import {Application}  from "../store/state";
import {Applications} from "../store/state";
import {Actions}      from "./index";

export function changeSelectedApplicationId(selectedApplicationId: string) {
  return {selectedApplicationId}
}

export function updateApplications(applications: Applications) {
  return {applications}
}

export function updateSessionUser(user: any) {
  return {user}
}

export const authorize = (username: string, password: string) => {
  return async (dispatch: any, getState: any) => {
    Parse.initialize(
      'KQEi9xr2OZZ5RFmfQTCUaJB0JoZUxbE5H6mgwGng',
      '<KEY>'
    );
    Parse.serverURL = 'https://parseapi.back4app.com/';
    let user = await Parse.User.logIn(username, password);
    dispatch(Actions.updateSessionUser(user));
    return true;
  }
};

export const fetchApplications = () => {
  return async (dispatch: any, getState: any) => {
    let applications: Array<any> = await new Parse.Query("App").find();
    //todo make some Parse service will handle all this weird stuff
    await Parse.User.logOut();

    let fistAppId: string = applications[0].id;
    let normApp: Applications = applications.reduce((normalized, {id, attributes}) => {
      normalized[id] = {...{id}, ...attributes};
      return normalized;
    }, {});
    dispatch(Actions.updateApplications(normApp));
    dispatch(changeSelectedApplication(normApp[fistAppId]))
    return true;
  }
};

export const changeSelectedApplication = (application: Application) => {
  return async (dispatch: any, getState: any) => {
    try {
      dispatch(Actions.showLoader());
      Parse.initialize(application.applicationId, application.masterKey);
      Parse.serverURL = application.serverURL;
      Parse.masterKey = application.masterKey;
      dispatch(Actions.changeSelectedApplicationId(application.id));
      dispatch(Actions.hideLoader());
    } catch (e) {
      dispatch(Actions.hideLoader());
    }
  }
};

// _ApplicationId: "APPLICATION_ID"
// _ClientVersion: "js2.1.0"
// _InstallationId: "de54ff6e-ebd7-013e-89c4-6bbd24d72fd4"
// _JavaScriptKey: "MASTER_KEY"
// _method: "GET"

/*
applicationId: "APPLICATION_ID"
createdAt: "2018-10-31T14:41:19.306Z"
iconType: "logoKibana"
masterKey: "MASTER_KEY"
name: "Test"
objectId: "6Wg8zFaayu"
*/<file_sep>import * as React  from 'react';
import classnames  from 'classnames';
import {IconType} from '@elastic/eui';
import {EuiIcon}   from '@elastic/eui';
import {NavLink}   from 'react-router-dom';

export class AppBarItem extends React.Component<AppBarItemProps, AppBarItemState> {
  render() {
    return <NavLink to={this.props.to} className={classnames('duiAppBarItem')}
                    activeClassName={'duiAppBarItem--active'}>
      <EuiIcon type={this.props.iconType} size={"xl"}/>
    </NavLink>
  }
}

export interface AppBarItemProps {
  to: string
  iconType: IconType
}

export interface AppBarItemState {
}
    <file_sep>import {Schemas} from "../store/state";
import {Actions} from "./index";

declare namespace Parse {
  class Schema extends Object {
    static all(): Promise<Array<any>>;

    delete(): Promise<any>;

    save(): Promise<any>;

    update(): Promise<any>;

    get(): Promise<Schema>;

    deleteField(fieldName: string): any
  }
}

export function initialized() {
  return {initialized: true}
}

export function updateSchemas(schemas: Schemas) {
  return {schemas}
}

export function deleteSchemaData(className) {
  return {className}
}

export const fetchSchemas = () => {
  return async (dispatch: any, getState: any) => {
    let result = await Parse.Schema.all();
    let schemas: Schemas = result.reduce((normalized, schema) => {
      normalized[schema.className] = schema;
      return normalized;
    }, {});
    dispatch(Actions.updateSchemas(schemas));
    return true;
  }
}

export const createSchema = (name: string) => {
  return async (dispatch: any, getState: any) => {
    await new Parse.Schema(name).save();
  }
};
export const deleteSchema = (name: string) => {
  return async (dispatch: any, getState: any) => {
    await new Parse.Schema(name).delete();
    dispatch(Actions.deleteSchemaData(name));
  }
};
export const addField = (className: string, fieldName: string, type: any, targetClass?: string) => {
  return async (dispatch: any, getState: any) => {
    const schema = await new Parse.Schema(className);
    schema[`add${type}`](fieldName, targetClass);
    await schema.update();
  }
};
export const deleteField = (className: string, fieldName: string) => {
  return async (dispatch: any, getState: any) => {
    const schema = await new Parse.Schema(className);
    schema.deleteField(fieldName);
    await schema.update();
  }
};<file_sep>import * as React          from 'react';
import {EuiSelect}         from '@elastic/eui';
import {EuiFormRow}        from '@elastic/eui';
import {WrappedFieldProps} from 'redux-form';

export class Select extends React.Component<SelectProps, SelectState> {

  render() {
    const {
      input,
      options,
      label,
      meta: {touched, error, valid},
      ...rest
    } = this.props;

    return (
      <EuiFormRow label={label} fullWidth={true} error={error} isInvalid={!valid}>
        <EuiSelect options={options} {...input}/>
      </EuiFormRow>
    )
  }
}

export interface SelectProps extends WrappedFieldProps {
  label: string
  options: any
}

export interface SelectState {
}
    <file_sep>import {RouteComponentProps} from "react-router-dom";
import {withRouter}          from "react-router-dom";

export function WithRouter(component: React.ComponentType<any>): any {
    return withRouter(component);
}
<file_sep>import * as React          from 'react';
import {EuiFieldText}      from '@elastic/eui';
import {EuiFieldPassword}  from '@elastic/eui';
import {EuiFormRow}        from '@elastic/eui';
import {WrappedFieldProps} from 'redux-form';

export class Input extends React.Component<InputProps, InputState> {

  static defaultProps = {
    type: "text"
  }

  render() {
    const {
      input,
      label,
      type,
      meta: {touched, error, valid},
      ...rest
    } = this.props;
    return (
      <EuiFormRow label={label} fullWidth={true} error={error} isInvalid={!valid}>
        {
          type != 'password' ?
            <EuiFieldText type={type} {...input} {...rest} isInvalid={!valid}/>
            : <EuiFieldPassword  {...input} />
        }
      </EuiFormRow>
    )
  }
}

export interface InputProps extends WrappedFieldProps {
  label: string
  type?: "text" | "password"
}

export interface InputState {
}
    <file_sep>import {createSelector} from 'reselect'
import {StoreState}     from "../store/state";

const getSession = (state: StoreState) => state.session;

export const getSelectedApplicationId = createSelector([getSession], (session) => {
  return session.selectedApplicationId
});
export const getApplications = createSelector([getSession], (session) => {
  return session.applications
});

export const getSelectedApplication = createSelector([getSelectedApplicationId, getApplications], (id, application) => {
  return application[id]
});
export const getUser = createSelector([getSession], (session) => {
  return session.user
});<file_sep>import {Actions}       from "../actions"
import {union}         from "../helpers/array";
import {EntitiesState} from "../store/state";
import {initialState}  from "../store/state";

export function entities(state: EntitiesState = initialState.entities, action: Actions): EntitiesState {
  switch (action.type) {
    case Actions.errorMessageEntity.type: {
      let {message,className} = action.payload;
      let entity = state[className] || {byId:{},ids:[],browse:{}};
      entity.browse = {...entity.browse, message};
      return {
        ...state, [className]: {...entity}
      }
    }
    case Actions.fetchingEntity.type: {
      let {fetching,className} = action.payload;
      let entity = state[className] || {byId:{},ids:[],browse:{}};
      entity.browse = {...entity.browse, fetching};
      return {
        ...state, [className]: {...entity}
      }
    }
    case Actions.updateEntity.type: {
      let {className, byId, ids} = action.payload;
      let entity = state[className] || {byId:{},ids:[],browse:{}};
      entity.byId = {...entity.byId, ...byId};
      entity.ids = union([...entity.ids, ...ids]);
      return {
        ...state, [className]: {...entity}
      }
    }
  }
  return state;
}<file_sep>import {EuiTableRowCellProps}                from "@elastic/eui";
import * as React                            from 'react';
import {EuiBasicTable, EuiButton, EuiHealth} from '@elastic/eui';
import {EuiDescriptionList}                  from '@elastic/eui';
import {EuiButtonIcon}                       from '@elastic/eui';
import {formatDate}                          from '@elastic/eui';

const userTests: any = [
  {
    "id": "5bd709d3fec9138f1a6d4c5a",
    "firstName": "Elsie",
    "lastName": "Fischer",
    "github": "johndoe",
    "dateOfBirth": 1540819411539,
    "nationality": "NL",
    "online": true
  },
  {
    "id": "5bd709d38c27909b29f10f73",
    "firstName": "Helga",
    "lastName": "Wilkerson",
    "github": "johndoe",
    "dateOfBirth": 1540819411539,
    "nationality": "NL",
    "online": true
  },
  {
    "id": "5bd709d38ebcee1dcd78739a",
    "firstName": "Jones",
    "lastName": "Velasquez",
    "github": "johndoe",
    "dateOfBirth": 1540819411539,
    "nationality": "NL",
    "online": true
  },
  {
    "id": "5bd709d32a185780d1b66c2a",
    "firstName": "Shawn",
    "lastName": "Byers",
    "github": "johndoe",
    "dateOfBirth": 1540819411539,
    "nationality": "NL",
    "online": true
  },
  {
    "id": "5bd709d3979e86a200d3c4dd",
    "firstName": "Castaneda",
    "lastName": "Raymond",
    "github": "johndoe",
    "dateOfBirth": 1540819411539,
    "nationality": "NL",
    "online": true
  },
  {
    "id": "5bd709d3b358b10129f4db35",
    "firstName": "Benson",
    "lastName": "Franklin",
    "github": "johndoe",
    "dateOfBirth": 1540819411539,
    "nationality": "NL",
    "online": true
  }
];
const countries = [{
  code: 'NL',
  name: 'Netherlands',
  flag: '🇳🇱'
}]

export const createDataStore = () => {
  const users = userTests

  return {
    users,
    countries,
    findUsers: (pageIndex, pageSize, sortField, sortDirection) => {
      let items;

      if (sortField) {
        items = users.slice(0);
      } else {
        items = users;
      }

      let pageOfItems;

      if (!pageIndex && !pageSize) {
        pageOfItems = items;
      } else {
        const startIndex = pageIndex * pageSize;
        pageOfItems = items.slice(startIndex, Math.min(startIndex + pageSize, items.length));
      }

      return {
        pageOfItems,
        totalItemCount: items.length
      };
    },

    deleteUsers: (...ids) => {
      ids.forEach(id => {
        const index = users.findIndex(user => user.id === id);
        if (index >= 0) {
          users.splice(index, 1);
        }
      });
    },

    cloneUser: (id: any) => {
      const index = users.findIndex(user => user.id === id);
      if (index >= 0) {
        const user = users[index];
        users.splice(index, 0, {...user, id: users.length});
      }
    },

    getCountry: (code) => countries.find(country => country.code === code)
  };
};
const store = createDataStore();

export class Session extends React.Component<SessionProps, any> {
  state = {
    pageIndex: 0,
    pageSize: 5,
    sortField: 'firstName',
    sortDirection: 'asc',
    selectedItems: [],
    itemIdToExpandedRowMap: {},
  };

  onTableChange = ({page = {}, sort = {}}: any) => {
    const {
      index: pageIndex,
      size: pageSize,
    } = page;

    const {
      field: sortField,
      direction: sortDirection,
    } = sort;

    this.setState({
      pageIndex,
      pageSize,
      sortField,
      sortDirection,
    });
  };

  onSelectionChange = (selectedItems) => {
    this.setState({selectedItems});
  };

  onClickDelete = () => {
    const {selectedItems} = this.state;
    store.deleteUsers(...selectedItems.map(user => user.id));

    this.setState({
      selectedItems: []
    });
  };

  renderDeleteButton() {
    const {selectedItems} = this.state;

    if (selectedItems.length === 0) {
      return;
    }

    return (
      <EuiButton
        color="danger"
        iconType="trash"
        onClick={this.onClickDelete}
      >
        Delete {selectedItems.length} Users
      </EuiButton>
    );
  }

  toggleDetails = (item) => {
    const itemIdToExpandedRowMap = {...this.state.itemIdToExpandedRowMap};
    if (itemIdToExpandedRowMap[item.id]) {
      delete itemIdToExpandedRowMap[item.id];
    } else {
      const {nationality, online} = item;
      const country = store.getCountry(nationality);
      const color = online ? 'success' : 'danger';
      const label = online ? 'Online' : 'Offline';
      const listItems = [
        {
          title: 'Nationality',
          description: `${country.flag} ${country.name}`,
        }, {
          title: 'Online',
          description: <EuiHealth color={color}>{label}</EuiHealth>,
        }
      ];
      itemIdToExpandedRowMap[item.id] = (
        <EuiDescriptionList listItems={listItems}/>
      );
    }
    this.setState({itemIdToExpandedRowMap});
  };

  render() {
    const {
      pageIndex,
      pageSize,
      sortField,
      sortDirection,
      itemIdToExpandedRowMap,
    } = this.state;

    const {
      pageOfItems,
      totalItemCount,
    } = store.findUsers(pageIndex, pageSize, sortField, sortDirection);

    const deleteButton = this.renderDeleteButton();

    const columns = [{
      field: 'firstName',
      name: '<NAME>',
      sortable: true,
      truncateText: true,
      hideForMobile: true,
    }, {
      field: 'lastName',
      name: '<NAME>',
      truncateText: true,
      hideForMobile: true,
    }, {
      field: 'fullName',
      name: '<NAME>',
      sortable: true,
      isMobileHeader: true,
      render: (name, item) => (
        {item.firstName} {item.lastName}
      )
    }, {
      field: 'dateOfBirth',
      name: '<NAME>',
      dataType: 'date',
      render: (date) => formatDate(date, 'dobLong'),
      sortable: true
    }, {
      name: 'Actions',
      actions: [{
        name: 'Clone',
        description: 'Clone this person',
        type: 'icon',
        icon: 'copy',
        onClick: () => ''
      }]
    }, {
      width: '40px',
      isExpander: true,
      render: (item) => (
        <EuiButtonIcon
          onClick={() => this.toggleDetails(item)}
          aria-label={itemIdToExpandedRowMap[item.id] ? 'Collapse' : 'Expand'}
          iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'}
        />
      )
    }];

    const pagination = {
      pageIndex: pageIndex,
      pageSize: pageSize,
      totalItemCount: totalItemCount,
      pageSizeOptions: [3, 5, 8]
    };

    const sorting = {
      sort: {
        field: sortField,
        direction: sortDirection,
      },
    };

    const selection = {
      selectable: (user) => user.online,
      selectableMessage: (selectable) => !selectable ? 'User is currently offline' : undefined,
      onSelectionChange: this.onSelectionChange
    };

    return (
      <React.Fragment>
        {deleteButton}
        <EuiBasicTable
          items={pageOfItems}
          itemId="id"
          itemIdToExpandedRowMap={this.state.itemIdToExpandedRowMap}
          isExpandable={true}
          hasActions={true}
          columns={columns}
          pagination={pagination}
          sorting={sorting}
          isSelectable={true}
          selection={selection}
          onChange={this.onTableChange}
        />
      </React.Fragment>
    );
  }

}

export interface SessionProps {
}

    <file_sep>import * as React          from 'react';
import {CustomItemAction}  from "./CustomItemAction";
import {DefaultItemAction} from "./DefaultItemAction";
import classNames          from 'classnames';

export class ExpandedItemActions extends React.Component<ExpandedItemActionsProps, ExpandedItemActionsState> {

  render() {
    const {
      actions,
      itemId,
      item,
      actionEnabled,
      className,
    } = this.props
    const moreThanThree = actions.length > 2;

    return actions.reduce((tools, action, index) => {

      const available = action.available ? action.available(item) : true;
      if (!available) {
        return tools;
      }

      const enabled = actionEnabled(action);

      const key = `item_action_${itemId}_${index}`;

      const classes = classNames(className, {
        'expandedItemActions__completelyHide': moreThanThree && index < 2,
      });

      if (action.render) {
        tools.push(
          <CustomItemAction
            key={key}
            className={classes}
            index={index}
            action={action}
            enabled={enabled}
            itemId={itemId}
            item={item}
          />
        );
      } else {
        tools.push(
          <DefaultItemAction
            key={key}
            className={classes}
            index={index}
            action={action}
            enabled={enabled}
            itemId={itemId}
            item={item}
          />
        );
      }
      return tools;
    }, []);
  }
}

export interface ExpandedItemActionsProps {
  actions?: Array<any>,
  itemId?: any,
  item?: any,
  actionEnabled?: any,
  className?: any,
}

export interface ExpandedItemActionsState {
}
    <file_sep>import * as React            from 'react';
import {RouteComponentProps} from 'react-router-dom';
import {EuiBasicTable}       from '@elastic/eui';
import {EuiTable}            from '@elastic/eui';
import {EuiTableHeaderCell}  from '@elastic/eui';
import {EuiCodeBlock}        from '@elastic/eui';
import {EuiFlexGroup}        from '@elastic/eui';
import {EuiFieldSearch}      from '@elastic/eui';
import {EuiFlexItem}         from '@elastic/eui';
import {EuiDescriptionList}  from "@elastic/eui";
import {EuiButtonIcon}       from "@elastic/eui";
import {EuiButton}           from "@elastic/eui";
import {EuiTitle}            from "@elastic/eui";
import {EuiForm}             from '@elastic/eui';
import {EuiModal}            from '@elastic/eui';
import {EuiOverlayMask}      from '@elastic/eui';
import {EuiModalHeader}      from '@elastic/eui';
import {EuiModalHeaderTitle} from '@elastic/eui';
import {EuiModalBody}        from '@elastic/eui';
import {EuiModalFooter}      from '@elastic/eui';
import {EuiButtonEmpty}      from '@elastic/eui';
import {EuiSpacer}           from '@elastic/eui';
import {Actions}             from "../../actions";
import {fetchSchemas}        from "../../actions/AppActions";
import {deleteSchema}        from "../../actions/AppActions";
import {fetchTableData}      from "../../actions/EntityActions";
import {Connected}           from "../../decorators/Connected";
import {WithRouter}          from "../../decorators/WithRouter";
import {getSchemas}          from "../../selectors/app";
import {StoreState}          from "../../store/state";
import {InjectedFormProps}   from "redux-form";
import {RIGHT_ALIGNMENT}     from '@elastic/eui/lib/services';
import {LEFT_ALIGNMENT}      from '@elastic/eui/lib/services';
import {EntityItemModal}     from "./EntityItemModal";
import {EntityModal}         from "./EntityModal";

@WithRouter
@Connected
export class BrowserEntity extends React.Component<BrowserEntityProps, BrowserEntityState> {

  state = {};

  static defaultProps = {
    pageIndex: 0,
    pageSize: 5,
    tableIds: [],
    totalItemCount: 0
  }

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      return {
        entity: state.entities[props.match.params.entity],
        pageIndex: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.pageIndex,
        totalItemCount: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.totalItemCount,
        pageSize: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.pageSize,
        tableIds: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.tableIds,
        schemas: getSchemas(state),
        sort: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.sort || {
          field: "createdAt",
          direction: "asc"
        },
        expandedRowMop: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.expandedRowMop || {},
        showItemModal: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.itemModalForm && state.entities[props.match.params.entity].browse.itemModalForm.mode,
        showEntityModal: state.entities[props.match.params.entity] && state.entities[props.match.params.entity].browse.modal,
      }
    })
  }

  @Connected
  get actions() {
    const updateSortField = Actions.updateSortField;
    const updateExpandedRowMop = Actions.updateExpandedRowMop;
    const updateItemModalForm = Actions.updateItemModalForm;
    const updateModal = Actions.updateModal;
    return Connected.actions({
      deleteSchema,
      fetchSchemas,
      updateSortField,
      fetchTableData,
      updateModal,
      updateExpandedRowMop,
      updateItemModalForm
    })
  }

  componentWillReceiveProps(nextProp) {
    if (this.props.match.params.entity != nextProp.match.params.entity ||
      this.model.schemas != nextProp.schemas
    ) {
      this.actions.fetchTableData(nextProp.match.params.entity, this.model.pageIndex, this.model.pageSize, this.model.sort.field, this.model.sort.direction);
    }
  }

  async componentDidMount() {
    await this.actions.fetchTableData(this.props.match.params.entity, this.model.pageIndex, this.model.pageSize, this.model.sort.field, this.model.sort.direction);
  }

  get items() {
    const {byId = {}} = this.model.entity || {};
    return this.model.tableIds.map((id) => {
      return byId[id]
    })
  }

  get columns() {
    const {fields} = this.model.schemas[this.props.match.params.entity];
    let itemColumns: any = Object.keys(fields).map((name) => {
      return {
        field: name,
        name: name,
        sortable: true,
        truncateText: false,
      }
    });
    let tableActions = this.tableActions;
    itemColumns.push({
      name: 'Actions',
      actions: tableActions
    });
    itemColumns.push({
      align: RIGHT_ALIGNMENT,
      width: '40px',
      isExpander: true,
      render: (item) => {
        return <EuiButtonIcon
          onClick={() => this.toggleDetails(item)}
          aria-label={this.model.expandedRowMop[item.objectId] ? 'Collapse' : 'Expand'}
          iconType={this.model.expandedRowMop[item.objectId] ? 'arrowUp' : 'arrowDown'}
        />
      }
    });
    return itemColumns
  }

  onTableChange = async ({page, sort}) => {
    const {index, size} = page;
    const {field, direction} = sort;
    this.actions.updateExpandedRowMop(this.props.match.params.entity, {});
    await this.actions.fetchTableData(this.props.match.params.entity, index, size, field, direction);
  };

  toggleDetails = (item) => {
    const {expandedRowMop} = this.model;

    if (expandedRowMop[item.objectId]) {
      delete expandedRowMop[item.objectId];
    } else {
      expandedRowMop[item.objectId] = true
    }
    this.actions.updateExpandedRowMop(this.props.match.params.entity, expandedRowMop)
  };

  cloneItem = () => {
    console.log("Clone Item")
  };

  deleteItem = (item) => {
    this.actions.updateItemModalForm(this.props.match.params.entity, {objectId: item.objectId, mode: 'DELETE'})
  };

  editItem = (item) => {
    this.actions.updateItemModalForm(this.props.match.params.entity, {objectId: item.objectId, mode: 'EDIT'})
  };

  createItem = (item) => {
    this.actions.updateItemModalForm(this.props.match.params.entity, {objectId: item.objectId, mode: 'ADD'})
  };

  addColumn = (item) => {
    this.actions.updateModal(this.props.match.params.entity, "COLUMN_ADD")
  };

  removeColumn = (item) => {
    this.actions.updateModal(this.props.match.params.entity, "COLUMN_DELETE")
  };

  removeClass = (item) => {
    this.actions.updateModal(this.props.match.params.entity, "CLASS_DELETE")
  };

  get pagination() {
    const {pageIndex, pageSize, totalItemCount} = this.props;
    return {
      pageIndex: pageIndex,
      pageSize,
      totalItemCount,
      hidePerPageOptions: true
    };
  }

  get tableActions() {
    return [{
      name: 'Clone',
      description: 'Clone this row',
      icon: 'copy',
      onClick: this.cloneItem
    }, {
      name: 'Delete',
      description: 'Delete this row',
      icon: 'trash',
      color: 'danger',
      type: 'icon',
      isPrimary: true,
      onClick: this.deleteItem,
    }, {
      name: 'Edit',
      description: 'Edit this row',
      icon: 'pencil',
      type: 'icon',
      isPrimary: true,
      onClick: this.editItem,
    }];
  }

  get sorting() {
    const sort = this.model.sort;
    return {sort}
  }

  get itemIdToExpandedRowMap() {
    const {byId = {}} = this.model.entity || {};
    return Object.keys(this.model.expandedRowMop).reduce((accumulator, objectId) => {
      const component = (
        <EuiCodeBlock language="js" fontSize="l" paddingSize="s" color="dark">
          {JSON.stringify(byId[objectId], null, "\t")}
        </EuiCodeBlock>
      );
      accumulator[objectId] = component;
      return accumulator
    }, {})
  }

  render() {
    const {entity = {browse: {fetching: true}}} = this.model || {};
    return (

      <EuiSpacer size="l"/>
      <EuiFlexGroup gutterSize="l">
        <EuiFlexItem>
          <EuiFieldSearch fullWidth placeholder="Search..."/>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <EuiButton onClick={this.addColumn}>Add column</EuiButton>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <EuiButton onClick={this.createItem}>Add row</EuiButton>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <EuiButton onClick={this.removeColumn}>Remove Column</EuiButton>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <EuiButton onClick={this.removeClass}>Remove Class</EuiButton>
        </EuiFlexItem>
      </EuiFlexGroup>
      <EuiSpacer size="m"/>
      <EuiBasicTable
        loading={entity.browse.fetching}
        error={entity.browse.message}
        itemIdToExpandedRowMap={this.itemIdToExpandedRowMap}
        isExpandable={true}
        items={this.items}
        sorting={this.sorting}
        itemId={'objectId'}
        columns={this.columns}
        onChange={this.onTableChange}
        pagination={this.pagination}
      />
      {this.model.showItemModal && <EntityItemModal/>}
      {this.model.showEntityModal && <EntityModal/>}

)
  }
}

export interface BrowserEntityProps extends InjectedFormProps, Partial<RouteComponentProps<{ entity: string, appId: string }>> {
  pageIndex: any,
  totalItemCount: any
  pageSize: any
}

export interface BrowserEntityState {

}
    <file_sep>import * as React from 'react';

export class JobAll extends React.Component<JobAllProps, JobAllState> {

  render() {
    return (
JobAll
)
  }
}

export interface JobAllProps {
}

export interface JobAllState {
}
    <file_sep>import * as React                  from 'react';
import {changeSelectedApplication} from "../actions/SessionActions";
import {WithRouter}                from "../decorators/WithRouter";
import {getSelectedApplication}    from "../selectors/session";
import {getSelectedApplicationId}  from "../selectors/session";
import {getApplications}           from "../selectors/session";
import {Application}               from "../store/state";
import {StoreState}                from "../store/state";
import {AppBarItem}                from "./AppBarItem";
import {RouteComponentProps}       from 'react-router';
import {ApplicationSelector}       from "./ApplicationSelector";
import {Connected}                 from '../decorators/Connected';

@WithRouter
@Connected
export class AppBar extends React.Component<AppBarProps, AppBarState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      return {
        applications: getApplications(state),
        selectedApp: getSelectedApplication(state),
        selectedAppId: getSelectedApplicationId(state)
      }
    })
  }

  @Connected
  get actions() {
    return Connected.actions({changeSelectedApplication})
  }

  onApplicationChange = (application: Application) => {
    this.actions.changeSelectedApplication(application);
    this.props.history.push(`/config`);
  };

  render() {
    return

      <ApplicationSelector
        applications={this.model.applications}
        selectedApplication={this.model.selectedApp}
        onApplicationChange={this.onApplicationChange}
      />
      <AppBarItem to={`/browser`} iconType={'addDataApp'}/>
      <AppBarItem to={`/job`} iconType={'dashboardApp'}/>
      <AppBarItem to={`/config`} iconType={'devToolsApp'}/>

  }
}

export interface AppBarProps extends Partial<RouteComponentProps<any>> {
}

export interface AppBarState {
}
    <file_sep>import * as React from 'react';
import {EuiPopover, EuiToolTip, EuiButtonIcon, EuiContextMenuItem, EuiContextMenuPanel} from '@elastic/eui';

export class CollapsedItemActions extends React.Component<CollapsedItemActionsProps, CollapsedItemActionsState> {

  popoverDiv:any
  state = {popoverOpen: false};

  togglePopover = () => {
    this.setState(prevState => ({popoverOpen: !prevState.popoverOpen}));
  };

  closePopover = () => {
    this.setState({popoverOpen: false});
  };

  onPopoverBlur = () => {
    // you must be asking... WTF? I know... but this timeout is
    // required to make sure we process the onBlur events after the initial
    // event cycle. Reference:
    // https://medium.com/@jessebeach/dealing-with-focus-and-blur-in-a-composite-widget-in-react-90d3c3b49a9b
    window.requestAnimationFrame(() => {
      if (!this.popoverDiv.contains(document.activeElement)) {
        this.props.onBlur();
      }
    });
  };

  registerPopoverDiv = (popoverDiv) => {
    if (!this.popoverDiv) {
      this.popoverDiv = popoverDiv;
      this.popoverDiv.addEventListener('focusout', this.onPopoverBlur);
    }
  };

  componentWillUnmount() {
    if (this.popoverDiv) {
      this.popoverDiv.removeEventListener('focusout', this.onPopoverBlur);
    }
  }

  onClickItem = (onClickAction) => {
    this.closePopover();
    onClickAction();
  }

  render() {

    const {actions, itemId, item, actionEnabled, onFocus, className} = this.props;

    const isOpen = this.state.popoverOpen;

    let allDisabled = true;
    const controls = actions.reduce((controls, action, index) => {
      const key = `action_${itemId}_${index}`;
      const available = action.available ? action.available(item) : true;
      if (!available) {
        return controls;
      }
      const enabled = actionEnabled(action);
      allDisabled = allDisabled && !enabled;
      if (action.render) {
        const actionControl = action.render(item, enabled);
        const actionControlOnClick = actionControl && actionControl.props && actionControl.props.onClick;
        controls.push(
          <EuiContextMenuItem key={key} onClick={actionControlOnClick ? actionControlOnClick.bind(null, item) : () => {
          }}>
            {actionControl}
          </EuiContextMenuItem>
        );
      } else {
        controls.push(
          <EuiContextMenuItem
            key={key}
            disabled={!enabled}
            icon={action.icon}
            onClick={this.onClickItem.bind(null, action.onClick.bind(null, item))}
          >
            {action.name}
          </EuiContextMenuItem>
        );
      }
      return controls;
    }, []);

    const popoverButton = (
      <EuiButtonIcon
        className={className}
        aria-label="All actions"
        iconType="boxesHorizontal"
        color="text"
        isDisabled={allDisabled}
        onClick={this.togglePopover.bind(this)}
        onFocus={onFocus}
      />
    );

    const withTooltip = !allDisabled && (
      <EuiToolTip content="All actions" delay="long">
        {popoverButton}
      </EuiToolTip>
    );

    return (
      <EuiPopover
        className={className}
        popoverRef={this.registerPopoverDiv}
        id={`${itemId}-actions`}
        isOpen={isOpen}
        button={withTooltip || popoverButton}
        closePopover={this.closePopover}
        panelPaddingSize="none"
        anchorPosition="leftCenter"
      >
        <EuiContextMenuPanel items={controls}/>
      </EuiPopover>
    );
  }
}

export interface CollapsedItemActionsProps {
  actions?:any,
  itemId?:any,
  item?:any,
  actionEnabled?:any,
  onFocus?:any,
  className?:any
  onBlur?:any
}

export interface CollapsedItemActionsState {
  popoverOpen: boolean
}
    <file_sep>import {Actions}      from "../actions"
import {initialState} from "../store/state";
import {BrowseState}  from "../store/state";

export function browse(state: BrowseState = initialState.browse, action: Actions): BrowseState {
  switch (action.type) {
    case Actions.updateMessage.type: {
      return {...state, ...action.payload}
    }
    case Actions.showLoader.type: {
      return {...state, ...action.payload}
    }
    case Actions.hideLoader.type: {
      return {...state, ...action.payload}
    }
  }
  return state;
}<file_sep>import * as React               from 'react';
import {EuiEmptyPrompt}         from '@elastic/eui';
import {EuiButton}              from '@elastic/eui';
import {EuiButtonEmpty}         from '@elastic/eui';
import {RouteComponentProps}    from 'react-router';
import {getSelectedApplication} from "../../selectors/session";
import {StoreState}             from "../../store/state";
import {Connected}              from "../../decorators/Connected";
import {WithRouter}             from "../../decorators/WithRouter";

@WithRouter
@Connected
export class Config extends React.Component<ConfigProps, ConfigState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      return {selectedApp: getSelectedApplication(state)}
    })
  }

  render() {
    const {selectedApp} = this.model;
    console.log("Selected app", selectedApp)
    return (
      <EuiEmptyPrompt
        title={
Application name/id :{selectedApp.name}
}
        actions={[
          <EuiButton color="primary" fill>Harvest spice</EuiButton>,
          <EuiButtonEmpty color="danger">Sabotage all spice fields</EuiButtonEmpty>,
        ]}
      />
    )
  }
}

export interface ConfigProps extends Partial<RouteComponentProps<{ appId: string }>> {
}

export interface ConfigState {
}
    <file_sep>import * as React           from 'react';
import {EuiButton}         from '@elastic/eui';
import {StoreState}         from '../store/state';
import {Actions}            from "../actions";
import {Connected}          from "../decorators/Connected";

@Connected
export class Products extends React.Component<ProductsProps, any> {

    @Connected
    get model() {
        return Connected.state((state: StoreState) => {
            return { message: state.browse.message }
        })
    }

    @Connected
    get actions() {
        const updateMessage = Actions.updateMessage;
        const extra = Actions.extra;
        return Connected.actions({ extra, updateMessage })
    }

    count: number = 0;
    onClick = (e: any) => {
        this.actions.extra(`Message Count is ${this.count}`);
        this.count++;
    };

    render() {
        console.log("On PROD props", this.props);
        return (

                {this.model.message}
                <EuiButton
                    type="submit"
                    color="primary"
                    onClick={this.onClick}
                >
                    Update
                </EuiButton>

        );
    }
}

export interface ProductsProps{

}

export default Products;
<file_sep>import {combineReducers} from 'redux';
import {app}             from "./app";
import {browse}          from './browse';
import {session}         from './session';
import {entities}        from './entities/index';
import {reducer as form} from 'redux-form'

export default combineReducers({
  browse,
  app,
  entities,
  session,
  form
});<file_sep>import {Actions} from "./index";

export function updateMessage(message: string) {
  return {message: message}
}

export function showLoader() {
  return {loading: true}
}

export function hideLoader() {
  return {loading: false}
}

export function doSomething(message: string) {

  return {message: message, someExtraOption: {items: [{firstName: "Jogn"}], total: 1}}
}

export function extra(message: string) {
  console.log("extra upper");
  return (dispatch: any, getState: any) => {
    console.log("extra inner");
    dispatch(Actions.updateMessage(message));
  }
}<file_sep>import {Action}                      from 'redux';
import {hideLoader}                  from "./BrowseActions";
import {showLoader}                  from "./BrowseActions";
import {doSomething}                 from './BrowseActions';
import {updateMessage}               from './BrowseActions';
import {extra}                       from './BrowseActions';
import {updateSchemas}               from "./AppActions";
import {deleteSchemaData}               from "./AppActions";
import {initialized}                 from "./AppActions";
import {updatePagination}            from "./EntityActions";
import {updateTableIds}              from "./EntityActions";
import {updateSortField}             from "./EntityActions";
import {updateExpandedRowMop}        from "./EntityActions";
import {updateEntity}                from "./EntityActions";
import {updateModal}                 from "./EntityActions";
import {fetchingEntity}              from "./EntityActions";
import {deleteEntityItemData}        from "./EntityActions";
import {updateItemModalForm}         from "./EntityActions";
import {updateEntityItemData}        from "./EntityActions";
import {removeFromTableIds}          from "./EntityActions";
import {errorMessageEntity}          from "./EntityActions";
import {updateApplications}          from "./SessionActions";
import {changeSelectedApplicationId} from "./SessionActions";
import {updateSessionUser}           from "./SessionActions";

export const Actions = createActions({
  updateMessage,
  extra,
  showLoader,
  changeSelectedApplicationId,
  updateApplications,
  hideLoader,
  //app
  updateSchemas,
  initialized,
  deleteSchemaData,
  updateSessionUser,
  // ENTITY
  updateEntity,
  updatePagination,
  updateTableIds,
  updateSortField,
  updateExpandedRowMop,
  deleteEntityItemData,
  removeFromTableIds,
  updateItemModalForm,
  updateModal,
  updateEntityItemData,
  fetchingEntity,
  errorMessageEntity,
  //
  doSomething
});
export type Actions = ActionUnion<typeof Actions>;

export interface PayloadAction<T, P> extends Action<T> {
  type: T;
  payload: P;
}

function createActions<T extends { [key: string]: (...args: U) => V }, U extends any[], V>(actions: T): {
  [K in keyof T]: { type: K, is(value: any): value is PayloadAction<K, ReturnType<T[K]>> } & ((...args: ArgType<T[K]>) => PayloadAction<K, ReturnType<T[K]>>)
} {
  return Object.keys(actions).reduce((result, type) => {
    result[type] = Object.assign((...args: U) => {
      let actionResult = actions[type](...args);
      if (typeof actionResult === 'function') {
        return actionResult;
      } else {
        return {
          type: type,
          payload: actionResult
        }
      }

    }, {
      type: type,
      is(action: Action) {
        return action.type === this.type;
      }
    });
    return result;
  }, {} as any);
}

export type ArgType<T> = T extends (...args: infer A) => any ? A : never;
export type ActionUnion any
}> = ReturnType;

<file_sep>import {StoreState}     from "../store/state";
export const getBrowse = (state: StoreState) => state.browse;
<file_sep>import * as React from 'react';
import {EuiButtonIcon, EuiButtonEmpty, EuiToolTip} from '@elastic/eui';

const defaults = {
  color: 'primary'
};
export class DefaultItemAction extends React.Component<DefaultItemActionProps, DefaultItemActionState> {

  render() {
    const { action, enabled, item, className } = this.props;
    if (!action.onClick) {
      throw new Error(`Cannot render item action [${action.name}]. Missing required 'onClick' callback. If you want
      to provide a custom action control, make sure to define the 'render' callback`);
    }
    const onClick = () => action.onClick(item);
    const color = this.resolveActionColor();
    const icon = this.resolveActionIcon();

    let button;
    if (action.type === 'icon') {
      if (!icon) {
        throw new Error(`Cannot render item action [${action.name}]. It is configured to render as an icon but no
        icon is provided. Make sure to set the 'icon' property of the action`);
      }
      button = (
        <EuiButtonIcon
          className={className}
          aria-label={action.name}
          isDisabled={!enabled}
          color={color}
          iconType={icon}
          onClick={onClick}
        />
      );
    } else {
      button = (
        <EuiButtonEmpty
          className={className}
          size="s"
          isDisabled={!enabled}
          color={color}
          iconType={icon}
          onClick={onClick}
          flush="right"
        >
          {action.name}
        </EuiButtonEmpty>
      );
    }

    return (enabled && action.description) ? (
      <EuiToolTip content={action.description} delay="long">
        {button}
      </EuiToolTip>
    ) : button;
  }

  resolveActionIcon() {
    const {action, item} = this.props;
    if (action.icon) {
      return typeof action.icon  =='string'? action.icon : action.icon(item);
    }
  }

  resolveActionColor() {
    const {action, item} = this.props;
    if (action.color) {
      return typeof action.color  =='string' ?  action.color : action.color(item);
    }
    return defaults.color;
  }
}

export interface DefaultItemActionProps {
  action?:any,
  index?:any,
  itemId?:any
enabled?:any,
  item?:any,
  className?:any
}

export interface DefaultItemActionState {
}
    <file_sep>import {Actions}      from "../actions"
import {SessionState} from '../store/state';
import {initialState} from '../store/state';

export function session(state: SessionState = initialState.session, action: Actions): SessionState {
  switch (action.type) {
    case Actions.updateSessionUser.type: {
      return {...state, ...action.payload}
      }
    case Actions.changeSelectedApplicationId.type: {
      return {...state, ...action.payload}
      }
    case Actions.updateApplications.type: {
      return {...state, ...action.payload}
      }
  }
  return state;
}<file_sep>import {reduxForm}         from "redux-form";
import {InjectedFormProps} from "redux-form";
import {ConfigProps}       from "redux-form";

export function ReduxForm<P extends InjectedFormProps<any>>(config?: ConfigProps<FormData, P> | object): any {
  let options = (config || {}) as ConfigProps<FormData, P>;

  return (target) => {
    const name = options.form || target.name;
    const Class = reduxForm({
      form: name,
      ...options
    })(target);
    Class['class'] = name;
    return Class
  };
}
<file_sep>import * as React from 'react';
import Products   from "../pages/Products";
import {Session}  from "../pages/Session";
import {EuiIcon} from '@elastic/eui';

const PagePlaceholder = ({ match }: any) => {
    return
PagePlaceholder. Match {JSON.stringify(match)}

}
export const navigation: any = [
    {
        name: 'browser',
        icon:<EuiIcon type="spacesApp" size='xxl'/>,
        items: [
            {
                name: 'product',
                component: Products,
            },
            {
                name: 'role',
                component: PagePlaceholder,
            },
            {
                name: 'session',
                component: Session,
            },
            {
                name: 'user',
                component: PagePlaceholder,
            }
        ],
    },
    {
        name: 'jobs',
        icon:<EuiIcon type="createMultiMetricJob" size='xxl'/>,
        items: [
            {
                name: 'all',
                component: PagePlaceholder,
            },
            {
                name: 'scheduled',
                component: PagePlaceholder,
            },
            {
                name: 'status',
                component: PagePlaceholder,
            },
        ]
    },
    {
        name: 'logs',
        icon:<EuiIcon type="monitoringApp" size='xxl'/>,
        items: [
            {
                name: 'info',
                component: PagePlaceholder,
            },
            {
                name: 'error',
                component: PagePlaceholder,
            }
        ]
    },
    {
        name: 'push',
        icon:<EuiIcon type="createMultiMetricJob" size='xxl'/>,

        items: [
            {
                name: 'new',
                component: PagePlaceholder,
            },
            {
                name: 'audiences',
                component: PagePlaceholder,
            }
        ]
    },
    {
        name: 'webhooks',
        icon:<EuiIcon type="infraApp" size='xxl'/>,

        component: (PagePlaceholder),
    },
    {
        name: 'config',
        icon:<EuiIcon type="managementApp" size='xxl'/>,

        component: PagePlaceholder,
    }
];
<file_sep>import * as React from 'react';

export class Browser extends React.Component<BrowserProps, BrowserState> {

  render() {
    return (
Browser
)
  }
}

export interface BrowserProps {
}

export interface BrowserState {
}
    <file_sep>export const slugify = (str: string) => {
    const parts = str
        .toLowerCase()
        .replace(/[-]+/g, ' ')
        .replace(/[^\w^\s]+/g, '')
        .replace(/ +/g, ' ').split(' ');
    return parts.join('-');
};
export const ucfirst = (string: string) => {
    return string.charAt(0).toUpperCase() + string.slice(1);
}<file_sep>import {Actions} from "./index";

export const updateEntity = (className: string, {byId, ids}) => {
  return {className, byId, ids}
};
export const updateEntityItemData = (className: string, {objectId, ...data}) => {
  let byId = {[objectId]: {...data, objectId}};
  return {className, byId}
};
export const deleteEntityItemData = (className: string, objectId) => {
  return {className, objectId}
};
export const fetchingEntity = (className: string, fetching: boolean) => {
  return {fetching, className}
};
export const errorMessageEntity = (className: string, message: string) => {
  return {message, className}
};
export const updatePagination = (className: string, payload) => {
  return {className, ...payload}
};

export const updateTableIds = (className: string, tableIds: Array<any>) => {
  return {className, tableIds}
};

export const removeFromTableIds = (className: string, objectId) => {
  return {className, objectId}
};

export const updateSortField = (className: string, sort) => {
  return {className, sort}
};

export const updateItemModalForm = (className: string, itemModalForm) => {
  return {className, itemModalForm}
};
export const updateModal = (className: string, modal) => {
  return {className, modal}
};

export const updateExpandedRowMop = (className: string, expandedRowMop) => {
  return {className, expandedRowMop}
};

export const fetchEntity = (className: string, pageIndex?: number, pageSize?: number, sortField?: string, sortDirection?: 'asc' | 'desc') => {
  return async (dispatch: any) => {
    let query = new Parse.Query(className);
    if (pageIndex) {
      query.skip(pageIndex * pageSize);
    }
    if (pageSize) {
      query.limit(pageSize);
    }
    if (sortField) {
      sortDirection === 'asc' ? query.ascending(sortField) : query.descending(sortField);
    }
    let result = await query.find();
    let byId = result.reduce((normalized, {id: objectId, attributes}) => {
      normalized[objectId] = {...{objectId}, ...attributes};
      return normalized;
    }, {});
    let ids = Object.keys(byId);
    dispatch(Actions.updateEntity(className, {byId, ids}));
    return {byId, ids}
  }
};

export const fetchTableData = (className: string, pageIndex?: number, pageSize?: number, sortField?: string, sortDirection?: 'asc' | 'desc') => {
  return async (dispatch: any) => {
    try {
      dispatch(Actions.fetchingEntity(className, true));
      const {ids} = await dispatch(fetchEntity(className, pageIndex, pageSize, sortField, sortDirection));
      let totalItemCount = await new Parse.Query(className).count();
      dispatch(Actions.updateTableIds(className, ids));
      dispatch(Actions.updatePagination(className, {pageIndex, pageSize, totalItemCount}));
      dispatch(Actions.updateSortField(className, {field: sortField, direction: sortDirection}));
      return true
    } catch (e) {
      dispatch(Actions.errorMessageEntity(className, e.message));
    } finally {
      dispatch(Actions.fetchingEntity(className, false));
    }
  }
};

export const updateEntityItem = (className: string, payload) => {
  return async (dispatch: any) => {
    let item;
    if (payload.objectId) {
      let query = new Parse.Query(className);
      item = await query.get(payload.objectId)
    }
    const Clazz = Parse.Object.extend(className);
    item = new Clazz();
    await item.save(payload);
    dispatch(Actions.updateEntityItemData(className, item.toJSON()));
    return item.toJSON();
  }
};
export const deleteEntityItem = (className: string, objectId: string) => {
  return async (dispatch: any) => {
    let item;
    let query = new Parse.Query(className);
    item = await query.get(objectId);
    await item.destroy();
    dispatch(Actions.deleteEntityItemData(className, objectId));
    return item
  }
};<file_sep>import * as React from 'react';

export class CustomItemAction extends React.Component<CustomItemActionProps, CustomItemActionState> {
  mounted: boolean;

  constructor(props) {
    super(props);
    this.state = {hasFocus: false};

    // while generally considered an anti-pattern, here we require
    // to do that as the onFocus/onBlur events of the action controls
    // may trigger while this component is unmounted. An alternative
    // (at least the workarounds suggested by react is to unregister
    // the onFocus/onBlur listeners from the action controls... this
    // unfortunately will lead to unecessarily complex code... so we'll
    // stick to this approach for now)
    this.mounted = false;
  }

  componentDidMount() {
    this.mounted = true;
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  onFocus = () => {
    if (this.mounted) {
      this.setState({hasFocus: true});
    }
  };

  onBlur = () => {
    if (this.mounted) {
      this.setState({hasFocus: false});
    }
  };

  hasFocus = () => {
    return this.state.hasFocus;
  };

  render() {
    const {action, enabled, item, className} = this.props;
    const tool = action.render(item, enabled);
    const clonedTool = React.cloneElement(tool, {onFocus: this.onFocus, onBlur: this.onBlur});
    const style = this.hasFocus() ? {opacity: 1} : null;
    return (

        {clonedTool}

    );
  }
}

export interface CustomItemActionProps {
  action?: any
  enabled?: any
  index?: any
  itemId?: any
  item?: any
  className?: any
}

export interface CustomItemActionState {
  hasFocus: boolean
}
    <file_sep>import {createSelector} from 'reselect'
import {StoreState}     from "../store/state";

const getApp = (state: StoreState) => state.app;
export const getSchemas = createSelector([getApp],(app)=>{
  return app.schemas

})
export const getEntityNames = createSelector([getSchemas], (schemas) => {
  return Object.keys(schemas)
});
<file_sep>const userTests:any= [
    {
        "id": "5bd709d3fec9138f1a6d4c5a",
        "firstName": "Elsie",
        "lastName": "Fischer",
        "github": "johndoe",
        "dateOfBirth": 1540819411539,
        "nationality": "NL",
        "online": true
    },
    {
        "id": "5bd709d38c27909b29f10f73",
        "firstName": "Helga",
        "lastName": "Wilkerson",
        "github": "johndoe",
        "dateOfBirth": 1540819411539,
        "nationality": "NL",
        "online": true
    },
    {
        "id": "5bd709d38ebcee1dcd78739a",
        "firstName": "Jones",
        "lastName": "Velasquez",
        "github": "johndoe",
        "dateOfBirth": 1540819411539,
        "nationality": "NL",
        "online": true
    },
    {
        "id": "5bd709d32a185780d1b66c2a",
        "firstName": "Shawn",
        "lastName": "Byers",
        "github": "johndoe",
        "dateOfBirth": 1540819411539,
        "nationality": "NL",
        "online": true
    },
    {
        "id": "5bd709d3979e86a200d3c4dd",
        "firstName": "Castaneda",
        "lastName": "Raymond",
        "github": "johndoe",
        "dateOfBirth": 1540819411539,
        "nationality": "NL",
        "online": true
    },
    {
        "id": "5bd709d3b358b10129f4db35",
        "firstName": "Benson",
        "lastName": "Franklin",
        "github": "johndoe",
        "dateOfBirth": 1540819411539,
        "nationality": "NL",
        "online": true
    }
];
const countries = [{
    code: 'NL',
    name: 'Netherlands',
    flag: '🇳🇱'
}]

export const createDataStore = () => {
    const users =userTests

    return {
        users,
        countries,
        findUsers: (pageIndex, pageSize, sortField, sortDirection) => {
            let items;

            if (sortField) {
                items = users.slice(0);
            } else {
                items = users;
            }

            let pageOfItems;

            if (!pageIndex && !pageSize) {
                pageOfItems = items;
            } else {
                const startIndex = pageIndex * pageSize;
                pageOfItems = items.slice(startIndex, Math.min(startIndex + pageSize, items.length));
            }

            return {
                pageOfItems,
                totalItemCount: items.length
            };
        },

        deleteUsers: (...ids) => {
            ids.forEach(id => {
                const index = users.findIndex(user => user.id === id);
                if (index >= 0) {
                    users.splice(index, 1);
                }
            });
        },

        cloneUser: (id:any) => {
            const index = users.findIndex(user => user.id === id);
            if (index >= 0) {
                const user = users[index];
                users.splice(index, 0, { ...user, id: users.length });
            }
        },

        // getCountry: (code) => countries.find(country => country.code === code)
    };
};
export const UserService = createDataStore();
<file_sep>import * as React               from 'react';
import {EuiForm}                from '@elastic/eui';
import {EuiButtonEmpty}         from '@elastic/eui';
import {EuiButton}              from '@elastic/eui';
import {Field, SubmissionError} from 'redux-form';
import {InjectedFormProps}      from 'redux-form';
import {Form}                   from 'redux-form';
import {formValueSelector}      from "redux-form";
import {RouteComponentProps}    from 'react-router';
import {Actions}                from "../../../actions";
import {deleteSchema}           from "../../../actions/AppActions";
import {addField}               from "../../../actions/AppActions";
import {fetchSchemas}           from "../../../actions/AppActions";
import {Connected}              from "../../../decorators/Connected";
import {ReduxForm}              from "../../../decorators/ReduxForm";
import {WithRouter}             from "../../../decorators/WithRouter";
import {getSchemas}             from "../../../selectors/app";
import {getEntityNames}         from "../../../selectors/app";
import {StoreState}             from "../../../store/state";
import {Input}                  from "../../../components/form/Input";
import {Select}                 from "../../../components/form/Select";

@WithRouter
@Connected
@ReduxForm({form: 'add-column'})
export class AddColumnForm extends React.Component<AddColumnFormProps, AddColumnFormState> {

  @Connected
  get model() {
    const selector = formValueSelector('add-column');
    return Connected.state((state: StoreState, props) => {
      return {
        selectedType: selector(state, 'type'),
        initialValues: {type: "String"},
        entityNames: getEntityNames(state),
        fields: getSchemas(state)[props.match.params.entity]
      }
    })
  }

  @Connected
  get actions() {
    const updateModal = Actions.updateModal;
    return Connected.actions({fetchSchemas, addField, deleteSchema, updateModal})
  }

  onCancel = () => {
    this.actions.updateModal(this.props.match.params.entity, null)
  };

  onSubmit = async ({target, name, type}) => {
    try {
      await this.actions.addField(this.props.match.params.entity, name, type, target);
      await this.actions.fetchSchemas();
      this.actions.updateModal(this.props.match.params.entity, null)
      return true
    } catch (e) {
      throw new SubmissionError({name: e.message})
    }

  };

  render() {
    return (<Form onSubmit={this.props.handleSubmit(this.onSubmit)}>
      <EuiForm>
        <Field name="name" label="Name" component={Input}/>
        <Field name="type" label="Type" options={[
          {value: "String", text: "String"},
          {value: "Number", text: "Number"},
          {value: "Date", text: "Date"},
          {value: "File", text: "File"},
          {value: "GeoPoint", text: "GeoPoint"},
          {value: "Polygon", text: "Polygon"},
          {value: "Array", text: "Array"},
          {value: "Object", text: "Object"},
          {value: "Boolean", text: "Boolean"},
          {value: "Pointer", text: "Pointer"},
          {value: "Relation", text: "Relation"}
        ]} component={Select}/>
        {['Pointer', 'Relation'].indexOf(this.model.selectedType) != -1
        && <Field name="target" label="Target Class" options={
          this.model.entityNames.map((className) => ({value: className, text: className}))}
                  component={Select}/>}
        <EuiButtonEmpty onClick={this.onCancel}>Cancel</EuiButtonEmpty>
        <EuiButton isLoading={this.props.submitting} type="submit" fill>Add</EuiButton>
      </EuiForm>
    </Form>)
  }
}

export interface AddColumnFormProps extends Partial<InjectedFormProps>, Partial<RouteComponentProps<{ entity: string }>> {
}

export interface AddColumnFormState {
}
    <file_sep>import * as React from 'react';

declare module '@elastic/eui' {
  export const EuiCard: any;
  export const EuiInMemoryTable: any;
  export const EuiBasicTable: any;
  export const SortDirection: any;
  export const EuiTableFooterCell: any;
  export const formatDate: any;

  export interface EuiTableRowProps {
    isSelected?: boolean;
    isExpandedRow?: boolean
    isSelectable?: boolean
  }

  export interface EuiTableBodyProps {
    [k: string]: any
  }

  export interface EuiTableRowCellProps {
    truncateText?: boolean;
    showOnHover?: any
    hasActions?: boolean
    align?: HorizontalAlignment;
    textOnly?: boolean;
    colSpan?: any
    isMobileFullWidth?: boolean
  }

  export interface EuiPopoverProps {
    popoverRef?: any
    id: string;
    closePopover: NoArgCallback<void>;
    button: React.ReactNode;
    withTitle?: boolean;
    isOpen?: boolean;
    ownFocus?: boolean;
    hasArrow?: boolean;
    anchorPosition?: PopoverAnchorPosition;
    panelClassName?: string;
    panelPaddingSize?: PanelPaddingSize;
  }

  export interface EuiToolTipProps {
    children: React.ReactElement<any>;
    delay: any
    className?: string;
    content: React.ReactNode;
    title?: React.ReactNode;
    id?: string;
    position?: ToolTipPositions;
  }
}<file_sep>import * as React            from 'react';
import {RouteComponentProps} from 'react-router';
import {EuiButton}           from '@elastic/eui';
import {EuiFlexItem}         from '@elastic/eui';

export class NavBar extends React.Component<NavBarProps, NavBarState> {

  render() {

    return (

        {this.props.children}

    )
  }
}

export interface NavBarProps extends Partial<RouteComponentProps<any>> {
}

export interface NavBarState {
}
    <file_sep>import * as React                 from 'react';
import {EuiForm}                  from '@elastic/eui';
import {EuiConfirmModal}          from '@elastic/eui';
import {EuiOverlayMask}           from '@elastic/eui';
import {EuiModal}                 from '@elastic/eui';
import {EuiModalHeader}           from '@elastic/eui';
import {EuiButtonEmpty}           from '@elastic/eui';
import {EuiButton}                from '@elastic/eui';
import {EUI_MODAL_CONFIRM_BUTTON} from '@elastic/eui';
import {RouteComponentProps}      from 'react-router';
import {EuiModalHeaderTitle}      from '@elastic/eui';
import {EuiModalBody}             from '@elastic/eui';
import {AddColumnForm}            from "./forms/AddColumnForm";
import {RemoveColumnForm}         from "./forms/RemoveColumnForm";
import {Actions}                  from "../../actions";
import {deleteSchema}             from "../../actions/AppActions";
import {addField}                 from "../../actions/AppActions";
import {deleteField}              from "../../actions/AppActions";
import {fetchSchemas}             from "../../actions/AppActions";
import {Connected}                from "../../decorators/Connected";
import {WithRouter}               from "../../decorators/WithRouter";
import {StoreState}               from "../../store/state";

@WithRouter
@Connected
export class EntityModal extends React.Component<EntityModalProps, EntityModalState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      const className = props.match.params.entity;
      const entities: any = state.entities[className] || {};
      const browse = entities.browse || {};
      const mode = browse.modal;
      return {
        mode
      }
    })
  }

  @Connected
  get actions() {
    const updateModal = Actions.updateModal;
    return Connected.actions({fetchSchemas, addField, deleteField, deleteSchema, updateModal})
  }

  onClose = () => {
    this.actions.updateModal(this.props.match.params.entity, null)

  };
  onClassDelete = async () => {
    try {
      await this.actions.deleteSchema(this.props.match.params.entity);
      this.props.history.push(`/browser/`);
      this.actions.updateModal(this.props.match.params.entity, null);
    } catch (e) {
      alert(e)
    }

  };
  onColumnDelete = () => {

  };

  render() {

    return (<React.Fragment>
      {this.model.mode == 'CLASS_DELETE' &&
      <EuiOverlayMask>
        <EuiConfirmModal
          title="Delete Class ?"
          onCancel={this.onClose}
          onConfirm={this.onClassDelete}
          cancelButtonText="No, don't do it"
          confirmButtonText="Yes, do it"
          defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON}
        >

You’re about to do something.

Are you sure you want to do this?

        </EuiConfirmModal>
      </EuiOverlayMask>
      }
      {
        this.model.mode == 'COLUMN_DELETE' &&
        <EuiOverlayMask>
          <EuiModal
            onClose={this.onClose}
            maxWidth={false}
          >
            <EuiModalHeader>
              <EuiModalHeaderTitle>
                Remove a column
              </EuiModalHeaderTitle>
            </EuiModalHeader>
            <EuiModalBody>
              <RemoveColumnForm/>
            </EuiModalBody>
          </EuiModal>
        </EuiOverlayMask>
      }{
      this.model.mode == 'COLUMN_ADD' &&
      <EuiOverlayMask>
        <EuiModal
          onClose={this.onClose}
          maxWidth={false}
        >
          <EuiModalHeader>
            <EuiModalHeaderTitle>
              Add a new column
            </EuiModalHeaderTitle>
          </EuiModalHeader>
          <EuiModalBody>
            <AddColumnForm/>
          </EuiModalBody>
        </EuiModal>
      </EuiOverlayMask>
    }
    </React.Fragment>)
  }
}

export interface EntityModalProps extends Partial<RouteComponentProps<{ entity: string }>> {
}

export interface EntityModalState {
}
    <file_sep>import * as React               from 'react';
import {EuiButton}              from '@elastic/eui';
import {EuiFieldPassword}       from '@elastic/eui';
import {EuiFlexItem}            from '@elastic/eui';
import {EuiForm}                from '@elastic/eui';
import {EuiFormRow}             from '@elastic/eui';
import {EuiFieldText}           from '@elastic/eui';
import {EuiPageHeader}          from '@elastic/eui';
import {EuiPageHeaderSection}   from '@elastic/eui';
import {EuiTitle}               from '@elastic/eui';
import {EuiPageContentBody}     from '@elastic/eui';
import {EuiPageContent}         from '@elastic/eui';
import {EuiPageSideBar}         from '@elastic/eui';
import {EuiPageBody}            from '@elastic/eui';
import {EuiLoadingSpinner}      from '@elastic/eui';
import {EuiPage}                from '@elastic/eui';
import {EuiPanel}               from '@elastic/eui';
import {EuiFlexGroup}           from '@elastic/eui';
import {EuiIcon}                from '@elastic/eui';
import {EuiLink}                from '@elastic/eui';
import {IconType}               from '@elastic/eui';
import {Switch}                 from 'react-router-dom';
import {Route}                  from 'react-router-dom';
import {Actions}                from "../actions";
import {fetchSchemas}           from "../actions/AppActions";
import {AppBar}                 from "../components/AppBar";
import {Connected}              from "../decorators/Connected";
import {getSelectedApplication} from "../selectors/session";
import {StoreState}             from "../store/state";
import {Browser}                from "./browser/Browser";
import {BrowserEntity}          from "./browser/BrowserEntity";
import {BrowserNavBar}          from "./browser/BrowserNavBar";
import {Config}                 from "./config/Config";
import {Job}                    from "./job/Job";
import {JobAll}                 from "./job/JobAll";
import {JobNavBar}              from "./job/JobNavBar";
import {JobStatus}              from "./job/JobStatus";

@Connected
export class App extends React.Component<LoginProps, LoginState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      return {
        loading: state.browse.loading,
        initialized: state.app.initialized,
        selectedApp: getSelectedApplication(state)
      }
    })
  }

  @Connected
  get actions() {
    const showLoader = Actions.showLoader;
    const hideLoader = Actions.hideLoader;
    const initialized = Actions.initialized;
    return Connected.actions({fetchSchemas, showLoader, hideLoader, initialized})
  }

  async componentDidMount() {
    const {selectedApp} = this.model;
    Parse.initialize(selectedApp.applicationId, selectedApp.masterKey);
    Parse.serverURL = selectedApp.serverURL;
    Parse.masterKey = selectedApp.masterKey;
    await this.actions.fetchSchemas();
    this.actions.initialized();
  }

  render() {
    const {initialized} = this.model;
    return (initialized && <EuiPage style={{minHeight: "100vh"}}>
        <EuiPageSideBar>
          <AppBar/>
          <Switch>
            <Route path={"/browser"} component={BrowserNavBar}/>
            <Route path={"/job"} component={JobNavBar}/>
          </Switch>
        </EuiPageSideBar>
        <EuiPageBody>
          <EuiFlexItem>
            <Switch>
              <Route path={"/browser"}>
                <Switch>
                  <Route path={"/browser/:entity"} component={BrowserEntity}/>
                  <Route path={"/browser/"} component={Browser}/>
                </Switch>
              </Route>
              <Route path={"/job"}>
                <Switch>
                  <Route path={"/job/all"} component={JobAll}/>
                  <Route path={"/job/status"} component={JobStatus}/>
                  <Route path={"/job/"} component={Job}/>
                </Switch>
              </Route>
              <Route path={"/config"} component={Config}/>
              <Route path={"/"} component={() => (
Index page ?
)}/>
            </Switch>
          </EuiFlexItem>
        </EuiPageBody>
      </EuiPage>
    )
  }
}

export interface LoginProps {
  history?: any;
  match?: any;
  location?: any;
}

export interface LoginState {
}
<file_sep>import * as React            from 'react';
import {EuiForm}             from '@elastic/eui';
import {EuiButtonEmpty}      from '@elastic/eui';
import {EuiButton}           from '@elastic/eui';
import {Field}               from 'redux-form';
import {SubmissionError}     from 'redux-form';
import {InjectedFormProps}   from 'redux-form';
import {Form}                from 'redux-form';
import {Actions}             from "../../../actions";
import {deleteSchema}        from "../../../actions/AppActions";
import {addField}            from "../../../actions/AppActions";
import {deleteField}         from "../../../actions/AppActions";
import {fetchSchemas}        from "../../../actions/AppActions";
import {Connected}           from "../../../decorators/Connected";
import {ReduxForm}           from "../../../decorators/ReduxForm";
import {WithRouter}          from "../../../decorators/WithRouter";
import {getSchemas}          from "../../../selectors/app";
import {StoreState}          from "../../../store/state";
import {Select}              from "../../../components/form/Select";
import {RouteComponentProps} from 'react-router';

@WithRouter
@ReduxForm({form: 'remove-column'})
@Connected
export class RemoveColumnForm extends React.Component<RemoveColumnFormProps, RemoveColumnFormState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      return {
        fields: getSchemas(state)[props.match.params.entity].fields
      }
    })
  }

  @Connected
  get actions() {
    const updateModal = Actions.updateModal;
    return Connected.actions({fetchSchemas, addField, deleteField, deleteSchema, updateModal})
  }

  onCancel = () => {

    this.actions.updateModal(this.props.match.params.entity, null)
  };

  onSubmit = async ({column}) => {
    try {
      await this.actions.deleteField(this.props.match.params.entity, column);
      await this.actions.fetchSchemas();
      this.actions.updateModal(this.props.match.params.entity, null)
      return true
    } catch (e) {
      throw new SubmissionError({column: e.message})
    }

  };

  render() {
    return (<Form onSubmit={this.props.handleSubmit(this.onSubmit)}>
      <EuiForm>
        <Field name="column" label="Column" options={
          Object.keys(this.model.fields).map((className) => ({value: className, text: className}))}
               component={Select}/>
        <EuiButtonEmpty onClick={this.onCancel}>Cancel</EuiButtonEmpty>
        <EuiButton isLoading={this.props.submitting} type="submit" fill>Remove</EuiButton>
      </EuiForm>
    </Form>)
  }
}

export interface RemoveColumnFormProps extends Partial<InjectedFormProps>, Partial<RouteComponentProps<{ entity: string }>> {
}

export interface RemoveColumnFormState {
}
    <file_sep>import * as React            from 'react';
import {EuiButton}           from '@elastic/eui';
import {EuiLoadingSpinner}   from '@elastic/eui';
import {EuiFieldPassword}    from '@elastic/eui';
import {EuiFlexItem}         from '@elastic/eui';
import {EuiForm}             from '@elastic/eui';
import {EuiFormRow}          from '@elastic/eui';
import {EuiFieldText}        from '@elastic/eui';
import {EuiPageContentBody}  from '@elastic/eui';
import {EuiPageContent}      from '@elastic/eui';
import {EuiPageBody}         from '@elastic/eui';
import {EuiPage}             from '@elastic/eui';
import {fetchSchemas}        from "../actions/AppActions";
import {fetchApplications}   from "../actions/SessionActions";
import {authorize}           from "../actions/SessionActions";
import {Input}               from "../components/form/Input";
import {Connected}           from "../decorators/Connected";
import {ReduxForm}           from "../decorators/ReduxForm";
import {getBrowse}           from "../selectors/browse";
import {StoreState}          from "../store/state";
import {RouteComponentProps} from 'react-router-dom';
import {Form}                from 'redux-form';
import {InjectedFormProps}   from 'redux-form';
import {Field}               from 'redux-form';
import {SubmissionError}     from 'redux-form'

@ReduxForm({form: 'login'})
@Connected
export class Login extends React.Component<LoginProps, LoginState> {
  state = {
    username: '',
    password: '',
  };

  @Connected
  get model() {
    return Connected.state((state: StoreState) => {
      return {loading: getBrowse(state).loading}
    })
  }

  @Connected
  get actions() {
    return Connected.actions({
      authorize, fetchApplications, fetchSchemas
    })
  }

  onFormSubmit = async ({username, password}) => {
    try {
      await this.actions.authorize(username, password)
    } catch (e) {
      throw new SubmissionError({
        username: 'User does not exist',
        _error: 'Login failed!'
      })
    }
    try {
      await this.actions.fetchApplications();
      await this.actions.fetchSchemas();
      this.props.history.push(`/config`)
    } catch (e) {
      throw new SubmissionError({
        username: e.message,
      })
    }

  };

  render() {
    return <EuiPage style={{height: "100vh"}}>
      <EuiPageBody>
        <EuiPageContent verticalPosition="center" horizontalPosition="center">
          <EuiPageContentBody>
            <EuiFlexItem style={{minWidth: 300}}>
              {this.model.loading && "LOADINF"}
              <Form onSubmit={this.props.handleSubmit(this.onFormSubmit)}>
                <EuiForm>
                  <Field name="username" label="Username" component={Input}/>
                  <Field name="<PASSWORD>" label="<PASSWORD>" type={'<PASSWORD>'} component={Input}/>
                  <EuiFlexItem>
                    <EuiButton isLoading={this.props.submitting} type="submit" size="s" fill>Login</EuiButton>
                  </EuiFlexItem>
                </EuiForm>
              </Form>
            </EuiFlexItem>
          </EuiPageContentBody>
        </EuiPageContent>
      </EuiPageBody>
    </EuiPage>
  }
}

export interface LoginProps extends InjectedFormProps, RouteComponentProps<any> {

}

export interface LoginState {
}
    <file_sep>import * as React            from 'react';
import {Route}               from 'react-router-dom';
import {Redirect}            from 'react-router-dom';
import {RouteComponentProps} from 'react-router-dom';
import {Connected}           from "../decorators/Connected";
import {getUser}             from "../selectors/session";
import {StoreState}          from "../store/state";

@Connected
export class AuthRoute extends React.PureComponent<any, any> {

  @Connected
  get model() {
    return Connected.state((state: StoreState) => {
      return {sessionUser: getUser(state)}
    })
  }

  renderRoute = (renderProps: RouteComponentProps<any>) => {
    const {component: Component} = this.props;
    if (!this.model.sessionUser) {
      return <Redirect
        to={{
          pathname: `/login`,
          state: {
            from: location.pathname || '/'
          }
        }}
      />
    }
    return (
      <Component {...renderProps} />
    );
  };

  render() {
    const {
      component,
      redirectPath,
      ...rest
    } = this.props
    return <Route {...rest} render={this.renderRoute}/>;
  }
}<file_sep>export const union = (array: Array<any>) => {
  let result = [];
  for (let i = 0; i < array.length; i++) {
    let value = array[i];
    result.indexOf(value) == -1 && result.push(value)
  }
  return result;
};<file_sep>import * as React from 'react';
import {NavLink}  from 'react-router-dom';

export class NavBarItem extends React.Component<NavBarItemProps, NavBarItemState> {

  render() {
    const {to,children, ...other} = this.props;
    return <NavLink {...other} to={to} className="duiNavBarItem"
                    activeClassName={'duiNavBarItem--active'}>
      {children}
    </NavLink>
  }
}

export interface NavBarItemProps {
  to: string
}

export interface NavBarItemState {
}
    <file_sep>/// <reference types="parse" />
import './types';
import * as React      from 'react';
import {render}        from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {Switch}        from 'react-router-dom';
import {Route}         from 'react-router-dom';
import {Redirect}      from 'react-router-dom';
import {Provider}      from 'react-redux';
import {Login}         from "./pages/Login";
import {AuthRoute}     from "./routes/AuthRoute";
import {store}         from './store';
import './index.scss'
import {App}           from './pages/App';

declare global {
  interface Window {
    __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: any
  }
}

export async function main() {
  render(
    <Provider store={store}>
      <BrowserRouter>
        <Switch>
          <Route path='/login' component={Login}/>;
          <AuthRoute path='/' component={App}/>;
          <Redirect to='/config'/>
        </Switch>
      </BrowserRouter>
    </Provider>,
    document.getElementById('root')
  );
}

main().catch(console.error);
<file_sep>import {IconType} from "@elastic/eui";

export type Normalized<T> = {
  [id: string]: T
}

export interface Application {
  id: string
  name: string,
  masterKey: string
  serverURL: string
  applicationId: string
  iconType: IconType
}

export type Applications = Normalized<Application>

export interface Schema {
  className: string
  fields: {
    [name: string]: { type: "String" | "Date" | "ACL" | "Boolean" | "Object" }
  }
  classLevelPermissions: {
    find: any;
    get: any;
    create: any;
    update: any;
    delete: any;
    addField: any;
  }
  indexes: any
}

export type Schemas = Normalized<Schema>

export interface SessionState {
  user?: any
  applications?: Applications,
  selectedApplicationId?: string
}

export interface BrowseState {
  message: string
  loading: boolean
}

export interface EntitiesState {
  [className: string]: Entity,
}

export interface Entity {
  byId?: any
  ids?: Array<any>,
  browse?: {
    pageIndex?: number,
    tableIds?: Array<string>
    sort?: {
      field: string,
      direction: "asc" | 'desc',
    }
    totalItemCount?: number,
    expandedRowMop?: any,
    itemModalForm?: { objectId?: string, mode?: 'EDIT' | 'CREATE' | 'DELETE' }
    modal?: 'CLASS_DELETE' | 'COLUMN_ADD' | 'COLUMN_DELETE'
    pageSize?: number,
    fetching?: boolean,
    message?: string,
    [k: string]: any
  }

  [k: string]: any
}

export interface AppState {
  initialized: boolean
  schemas: Schemas
}

export interface StoreState {
  session: SessionState
  browse: BrowseState,
  app: AppState,
  entities: EntitiesState
}

const initialState: StoreState = {
  session: {
    user: null,
    applications: {},
    selectedApplicationId: null,
  },
  app: {
    initialized: false,
    schemas: {},
  },
  browse: {
    loading: false,
    message: 'INITIAL MESSAGE',
  },
  entities: {}

};
export {initialState}<file_sep>import * as React                from 'react';
import {Applications}            from "../store/state";
import {Application}             from "../store/state";
import {EuiFlyout}               from '@elastic/eui';
import {EuiFlyoutHeader}         from '@elastic/eui';
import {EuiTitle}                from '@elastic/eui';
import {EuiIcon}                 from '@elastic/eui';
import {EuiFlyoutBody}           from '@elastic/eui';
import {EuiFlexItem}             from '@elastic/eui';
import {EuiCard}                 from '@elastic/eui';
import {EuiKeyPadMenuItemButton} from '@elastic/eui';
import {IconType}                from '@elastic/eui';

const iconMapping = {
  1: "logoBeats",
  2: "logoCloud",
  3: "logoKibana",
  4: "logoXpack"
};

export class ApplicationSelector extends React.Component<ApplicationSelectorProps, ApplicationSelectorState> {
  state = {
    isFlyoutVisible: false
  };

  closeFlyout = () => {
    this.setState({isFlyoutVisible: false})
  };

  onSelectorClick = () => {
    this.setState({
      isFlyoutVisible: !this.state.isFlyoutVisible,
    });
  };

  onAppSelect = (app: Application) => {
    this.closeFlyout();
    this.props.onApplicationChange(app)
  };

  render() {
    const {applications, selectedApplication} = this.props;
    const flyout = (
      <EuiFlyout className='left' ownFocus onClose={this.closeFlyout} size="s" aria-labelledby="flyoutSmallTitle">
        <EuiFlyoutHeader hasBorder>
          <EuiTitle size="s">

              Applications

          </EuiTitle>
        </EuiFlyoutHeader>
        <EuiFlyoutBody>
          {Object.keys(applications).map((id, index) => (
            id != selectedApplication.id && <EuiFlexItem key={index}>
              <EuiCard
                icon={<EuiIcon size="xxl" type={applications[id].iconType}/>}
                title={applications[id].name}
                description={''}
                onClick={() => this.onAppSelect(applications[id])}
              />
            </EuiFlexItem>
          ))}
        </EuiFlyoutBody>
      </EuiFlyout>);

    return (

        <EuiIcon onClick={this.onSelectorClick} type={selectedApplication.iconType} size={"xl"}/>
        {this.state.isFlyoutVisible && flyout}

    )
  }
}

export interface ApplicationSelectorProps {
  selectedApplication: Application,
  applications: Applications
  onApplicationChange: (a: Application) => void
}

export interface ApplicationSelectorState {
  isFlyoutVisible: boolean
}
<file_sep>import {createSelector} from 'reselect'
import {StoreState}     from "../store/state";

const getEntities = (state: StoreState) => state.entities;

<file_sep>import * as React                 from 'react';
import {SubmissionError}          from 'redux-form';
import {InjectedFormProps}        from 'redux-form';
import {EuiForm}                  from '@elastic/eui';
import {EuiConfirmModal}          from '@elastic/eui';
import {EuiOverlayMask}           from '@elastic/eui';
import {EuiModal}                 from '@elastic/eui';
import {EuiModalHeader}           from '@elastic/eui';
import {EuiButtonEmpty}           from '@elastic/eui';
import {EuiButton}                from '@elastic/eui';
import {EUI_MODAL_CONFIRM_BUTTON} from '@elastic/eui';
import {EuiModalHeaderTitle}      from '@elastic/eui';
import {EuiModalBody}             from '@elastic/eui';
import {RouteComponentProps}      from 'react-router-dom';
import {Connected}                from "../../decorators/Connected";
import {ReduxForm}                from "../../decorators/ReduxForm";
import {WithRouter}               from "../../decorators/WithRouter";
import {StoreState}               from "../../store/state";
import {Actions}                  from "../../actions";
import {deleteEntityItem}         from "../../actions/EntityActions";
import {updateEntityItem}         from "../../actions/EntityActions";

import {AddRowForm} from "./forms/AddRowForm";

@WithRouter
@Connected
@ReduxForm({form: 'entities-form'})
export class EntityItemModal extends React.Component<EntityItemModalProps, EntityItemModalState> {

  @Connected
  get model() {
    return Connected.state((state: StoreState, props) => {
      const className = props.match.params.entity;
      const entities: any = state.entities[className] || {};
      const browse = entities.browse || {};
      const itemModalForm = (browse.itemModalForm) || {};
      const mode = itemModalForm.mode;
      return {
        objectId: itemModalForm.objectId,
        mode,
      }
    })
  }

  @Connected
  get actions() {
    const updateItemModalForm = Actions.updateItemModalForm;
    return Connected.actions({updateItemModalForm, updateEntityItem, deleteEntityItem})
  }

  onClose = () => {
    this.actions.updateItemModalForm(this.props.match.params.entity, null)
  };

  onRowDelete = async () => {
    try {
      await this.actions.deleteEntityItem(this.props.match.params.entity, this.model.objectId);
      this.actions.updateItemModalForm(this.props.match.params.entity, null)
    } catch (e) {
      console.log(e);
      throw new SubmissionError(e.message)
    }

  };

  render() {
    const mode = this.model.mode;
    return (mode == 'DELETE' ?
        <EuiOverlayMask>
          <EuiConfirmModal
            title="Delete item ?"
            onCancel={this.onClose}
            onConfirm={this.onRowDelete}
            cancelButtonText="No, don't do it"
            confirmButtonText="Yes, do it"
            defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON}
          >

You’re about to do something.

Are you sure you want to do this?

          </EuiConfirmModal>
        </EuiOverlayMask>
        :
        <EuiOverlayMask>
          <EuiModal
            onClose={this.onClose}
            maxWidth={false}
          >
            <EuiModalHeader>
              <EuiModalHeaderTitle>
                {mode == 'EDIT' ? `Edit item ${this.model.objectId}` : `Add a new item`}
              </EuiModalHeaderTitle>
            </EuiModalHeader>
            <EuiModalBody>
              <AddRowForm/>
            </EuiModalBody>
          </EuiModal>
        </EuiOverlayMask>
    )
  }
}

export interface EntityItemModalProps extends Partial<InjectedFormProps>, Partial<RouteComponentProps<{ entity: string }>> {

}

export interface EntityItemModalState {
}

languages: TypeScript TSX

repo_language: TypeScript

repo_name: grishgrigoryan/elastic-dashboard