From c53f9e4896435fe964fc50f82245e5aceff6bee9 Mon Sep 17 00:00:00 2001 From: Ceolter Date: Sun, 24 Jan 2016 12:32:09 +0000 Subject: [PATCH] iteration --- src/AgGridReact.jsx | 85 ++++++++++++++++++-- src/ComponentUtil.js | 154 +++++++++++++++++++++++++++++++++++++ src/RefData.js | 2 +- src/SkillsCellRenderer.jsx | 21 +++++ src/index.js | 5 +- 5 files changed, 259 insertions(+), 8 deletions(-) create mode 100644 src/ComponentUtil.js create mode 100644 src/SkillsCellRenderer.jsx diff --git a/src/AgGridReact.jsx b/src/AgGridReact.jsx index 274e798..8bc715d 100644 --- a/src/AgGridReact.jsx +++ b/src/AgGridReact.jsx @@ -1,16 +1,63 @@ import ReactDOM from 'react-dom'; import React from 'react'; import AgGrid from 'ag-grid'; +import ComponentUtil from './ComponentUtil'; -export class AgGridReact extends React.Component { +export default class AgGridReact extends React.Component { componentDidMount() { var domNode = ReactDOM.findDOMNode(this); - AgGrid(domNode, this.props.gridOptions); + this.gridOptions = ComponentUtil.copyAttributesToGridOptions(this.props.gridOptions, this.props); + AgGrid(domNode, this.gridOptions); + + this.api = this.gridOptions.api; + this.columnApi = this.gridOptions.columnApi; + this.api.addGlobalListener(this.globalEventListener.bind(this)); + } + + // this method is duplicated, taken from gridOptionsWrapper + getCallbackForEvent(eventName) { + if (!eventName || eventName.length < 2) { + return eventName; + } else { + return 'on' + eventName[0].toUpperCase() + eventName.substr(1); + } + } + + // duplicated, taken from gridOptionsWrapper + globalEventListener(eventName, event) { + var callbackMethodName = this.getCallbackForEvent(eventName); + var callbackFromProps = this.props[callbackMethodName]; + if (callbackFromProps) { + callbackFromProps(event); + } + } + + shouldComponentUpdate () { + // we want full control of the dom, as ag-Grid doesn't use React internally, + // so for performance reasons we tell React we don't need render called after + // property changes. + return false; + } + + componentWillReceiveProps(nextProps) { + // keeping consistent with web components, put changing + // values in currentValue and previousValue pairs and + // not include items that have not changed. + var changes = {}; + ComponentUtil.ALL_PROPERTIES.forEach( (propKey)=> { + if (this.props[propKey]!==nextProps[propKey]) { + changes[propKey] = { + previousValue: this.props[propKey], + currentValue: nextProps[propKey] + }; + } + }); + ComponentUtil.processOnChange(changes, this.gridOptions, this.api, this.columnApi); } componentWillUnmount() { - //console.log('componentWillUnmount'); + this.api.destroy(); } render() { @@ -19,7 +66,33 @@ export class AgGridReact extends React.Component { } AgGridReact.propTypes = { - 'style': React.PropTypes.object, - 'className': React.PropTypes.string, - 'gridOptions': React.PropTypes.object + style: React.PropTypes.object, + className: React.PropTypes.string, + gridOptions: React.PropTypes.object + + // we should iterate through all the properties and add them here + //onRowSelected: React.PropTypes.func, + //showToolPanel: React.PropTypes.bool }; + +ComponentUtil.SIMPLE_BOOLEAN_PROPERTIES + .concat(ComponentUtil.WITH_IMPACT_BOOLEAN_PROPERTIES) + .forEach( (propKey)=> { + AgGridReact.propTypes[propKey] = React.PropTypes.bool; + }); + +//ComponentUtil.SIMPLE_PROPERTIES +// .concat(ComponentUtil.WITH_IMPACT_STRING_PROPERTIES) +// .forEach( (propKey)=> { +// AgGridReact.propTypes[propKey] = React.PropTypes.bool; +// }); + + //.concat(ComponentUtil.) + //.concat(ComponentUtil.SIMPLE_NUMBER_PROPERTIES) + //.concat(ComponentUtil.WITH_IMPACT_OTHER_PROPERTIES) + //.concat(ComponentUtil.WITH_IMPACT_NUMBER_PROPERTIES) + //.concat(ComponentUtil.CALLBACKS), + + +var i = new AgGridReact(); +console.log(i); diff --git a/src/ComponentUtil.js b/src/ComponentUtil.js new file mode 100644 index 0000000..b2a1aac --- /dev/null +++ b/src/ComponentUtil.js @@ -0,0 +1,154 @@ +export default class ComponentUtil {} + +ComponentUtil.SIMPLE_PROPERTIES = [ + 'sortingOrder', + 'icons','localeText','localeTextFunc', + 'groupColumnDef','context','rowStyle','rowClass','headerCellRenderer', + 'groupDefaultExpanded','slaveGrids','rowSelection', + 'overlayLoadingTemplate','overlayNoRowsTemplate', + 'headerCellTemplate' + ]; + +ComponentUtil.SIMPLE_NUMBER_PROPERTIES = [ + 'rowHeight','rowBuffer','colWidth' + ]; + +ComponentUtil.SIMPLE_BOOLEAN_PROPERTIES = [ + 'virtualPaging','toolPanelSuppressGroups','toolPanelSuppressValues','rowsAlreadyGrouped', + 'suppressRowClickSelection','suppressCellSelection','suppressHorizontalScroll','debug', + 'enableColResize','enableCellExpressions','enableSorting','enableServerSideSorting', + 'enableFilter','enableServerSideFilter','angularCompileRows','angularCompileFilters', + 'angularCompileHeaders','groupSuppressAutoColumn','groupSelectsChildren','groupHideGroupColumns', + 'groupIncludeFooter','groupUseEntireRow','groupSuppressRow','groupSuppressBlankHeader','forPrint', + 'suppressMenuHide','rowDeselection','unSortIcon','suppressMultiSort','suppressScrollLag', + 'singleClickEdit','suppressLoadingOverlay','suppressNoRowsOverlay','suppressAutoSize', + 'suppressParentsInRowNodes' + ]; + +ComponentUtil.WITH_IMPACT_STRING_PROPERTIES = ['quickFilterText']; +ComponentUtil.WITH_IMPACT_NUMBER_PROPERTIES = ['headerHeight']; +ComponentUtil.WITH_IMPACT_BOOLEAN_PROPERTIES = ['showToolPanel']; +ComponentUtil.WITH_IMPACT_OTHER_PROPERTIES = [ + 'rowData','floatingTopRowData','floatingBottomRowData', + 'columnDefs','datasource']; + +ComponentUtil.CALLBACKS = ['groupRowInnerRenderer', 'groupRowRenderer', 'groupAggFunction', + 'isScrollLag','isExternalFilterPresent','doesExternalFilterPass','getRowClass','getRowStyle', + 'headerCellRenderer','getHeaderCellTemplate']; + +ComponentUtil.ALL_PROPERTIES = ComponentUtil.SIMPLE_PROPERTIES + .concat(ComponentUtil.SIMPLE_NUMBER_PROPERTIES) + .concat(ComponentUtil.SIMPLE_BOOLEAN_PROPERTIES) + .concat(ComponentUtil.WITH_IMPACT_NUMBER_PROPERTIES) + .concat(ComponentUtil.WITH_IMPACT_BOOLEAN_PROPERTIES) + .concat(ComponentUtil.WITH_IMPACT_OTHER_PROPERTIES); + +ComponentUtil.copyAttributesToGridOptions = function(gridOptions, component) { + // create empty grid options if none were passed + if (typeof gridOptions !== 'object') { + gridOptions = {}; + } + // to allow array style lookup in TypeScript, take type away from 'this' and 'gridOptions' + var pGridOptions = gridOptions; + // add in all the simple properties + ComponentUtil.SIMPLE_PROPERTIES.concat(ComponentUtil.WITH_IMPACT_OTHER_PROPERTIES).forEach( (key)=> { + if (typeof (component)[key] !== 'undefined') { + pGridOptions[key] = component[key]; + } + }); + ComponentUtil.SIMPLE_BOOLEAN_PROPERTIES.concat(ComponentUtil.WITH_IMPACT_BOOLEAN_PROPERTIES).forEach( (key)=> { + if (typeof (component)[key] !== 'undefined') { + pGridOptions[key] = ComponentUtil.toBoolean(component[key]); + } + }); + ComponentUtil.SIMPLE_NUMBER_PROPERTIES.concat(ComponentUtil.WITH_IMPACT_NUMBER_PROPERTIES).forEach( (key)=> { + if (typeof (component)[key] !== 'undefined') { + pGridOptions[key] = ComponentUtil.toNumber(component[key]); + } + }); + + return gridOptions; + }; + +ComponentUtil.processOnChange = function(changes, gridOptions, api) { + // to allow array style lookup in TypeScript, take type away from 'this' and 'gridOptions' + var pGridOptions = gridOptions; + + // check if any change for the simple types, and if so, then just copy in the new value + ComponentUtil.SIMPLE_PROPERTIES.forEach( (key)=> { + if (changes[key]) { + pGridOptions[key] = changes[key].currentValue; + } + }); + ComponentUtil.SIMPLE_BOOLEAN_PROPERTIES.forEach( (key)=> { + if (changes[key]) { + pGridOptions[key] = ComponentUtil.toBoolean(changes[key].currentValue); + } + }); + ComponentUtil.SIMPLE_NUMBER_PROPERTIES.forEach( (key)=> { + if (changes[key]) { + pGridOptions[key] = ComponentUtil.toNumber(changes[key].currentValue); + } + }); + + if (changes.showToolPanel) { + api.showToolPanel(changes.showToolPanel.currentValue); + } + + if (changes.quickFilterText) { + api.setQuickFilter(changes.quickFilterText.currentValue); + } + + if (changes.rowData) { + api.setRowData(changes.rowData.currentValue); + } + + if (changes.floatingTopRowData) { + api.setFloatingTopRowData(changes.floatingTopRowData.currentValue); + } + + if (changes.floatingBottomRowData) { + api.setFloatingBottomRowData(changes.floatingBottomRowData.currentValue); + } + + if (changes.columnDefs) { + api.setColumnDefs(changes.columnDefs.currentValue); + } + + if (changes.datasource) { + api.setDatasource(changes.datasource.currentValue); + } + + if (changes.headerHeight) { + api.setHeaderHeight(changes.headerHeight.currentValue); + } + + // need to review this, it is not impacting anything, they should + // call something on the API to update the grid + if (changes.groupAggFunction) { + gridOptions.groupAggFunction = changes.groupAggFunction; + } + }; + +ComponentUtil.toBoolean = function(value) { + if (typeof value === 'boolean') { + return value; + } else if (typeof value === 'string') { + // for boolean, compare to empty String to allow attributes appearing with + // not value to be treated as 'true' + return value.toUpperCase() === 'TRUE' || value==''; + } else { + return false; + } + }; + +ComponentUtil.toNumber = function(value) { + if (typeof value === 'number') { + return value; + } else if (typeof value === 'string') { + return Number(value); + } else { + return undefined; + } + }; + diff --git a/src/RefData.js b/src/RefData.js index 5f53a19..47d8802 100644 --- a/src/RefData.js +++ b/src/RefData.js @@ -1,4 +1,4 @@ -export class RefData {} +export default class RefData {} RefData.FIRST_NAMES = [ "Sophie", "Isabelle", "Emily", "Olivia", "Lily", "Chloe", "Isabella", diff --git a/src/SkillsCellRenderer.jsx b/src/SkillsCellRenderer.jsx new file mode 100644 index 0000000..590f3e2 --- /dev/null +++ b/src/SkillsCellRenderer.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import RefData from './RefData'; + +export default class SkillsCellRenderer extends React.Component { + + render() { + var skills = []; + RefData.IT_SKILLS.forEach( (skill) => { + if (this.props.skills[skill]) { + skills.push(); + } + }); + + return {skills}; + } + +} + +SkillsCellRenderer.propTypes = { + skills: React.PropTypes.object +}; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 0c968d4..1bbecdd 100644 --- a/src/index.js +++ b/src/index.js @@ -2,10 +2,13 @@ import ReactDOM from 'react-dom'; import React from 'react'; -import {MyApp} from './myApp.jsx'; +import MyApp from './MyApp.jsx'; +// is there a better way of doing this? import 'ag-grid-root/ag-grid.css'; import 'ag-grid-root/theme-fresh.css'; +// waiting for dom to load before booting react. we could alternatively +// put the index.js reference at the end fo the index.html, but i prefer this way. document.addEventListener('DOMContentLoaded', ()=> { var container = document.getElementById('myAppContainer'); ReactDOM.render(