diff --git a/src/firefly/js/tables/TableConnector.js b/src/firefly/js/tables/TableConnector.js
index b2dd881900..3b7584b05d 100644
--- a/src/firefly/js/tables/TableConnector.js
+++ b/src/firefly/js/tables/TableConnector.js
@@ -87,7 +87,12 @@ export class TableConnector {
const {hlRowIdx, startIdx} = TblUtil.getTblInfoById(this.tbl_id);
if (rowIdx !== hlRowIdx) {
const highlightedRow = startIdx + rowIdx;
- TblCntlr.dispatchTableHighlight(this.tbl_id, highlightedRow);
+ if (this.origTableModel) {
+ const tableModel = {tbl_id: this.tbl_id, highlightedRow};
+ flux.process({type: TblCntlr.TABLE_UPDATE, payload: tableModel});
+ } else {
+ TblCntlr.dispatchTableHighlight(this.tbl_id, highlightedRow);
+ }
}
}
diff --git a/src/firefly/js/tables/TableUtil.js b/src/firefly/js/tables/TableUtil.js
index 7f3616f07c..5a37855bcb 100644
--- a/src/firefly/js/tables/TableUtil.js
+++ b/src/firefly/js/tables/TableUtil.js
@@ -441,7 +441,7 @@ export function getTblInfo(tableModel, aPageSize) {
const currentPage = highlightedRow >= 0 ? Math.floor(highlightedRow / pageSize)+1 : 1;
const hlRowIdx = highlightedRow >= 0 ? highlightedRow % pageSize : 0;
const startIdx = (currentPage-1) * pageSize;
- const endIdx = Math.min(startIdx+pageSize, totalRows) || startIdx ;
+ const endIdx = Math.min(startIdx+pageSize, totalRows) || get(tableModel,'tableData.data.length', startIdx) ;
var totalPages = Math.ceil((totalRows || 0)/pageSize);
return { tableModel, tbl_id, title, totalRows, request, startIdx, endIdx, hlRowIdx, currentPage, pageSize,totalPages, highlightedRow, selectInfo, error};
}
diff --git a/src/firefly/js/tables/ui/TableRenderer.js b/src/firefly/js/tables/ui/TableRenderer.js
index 0fbdd94059..4d6434602f 100644
--- a/src/firefly/js/tables/ui/TableRenderer.js
+++ b/src/firefly/js/tables/ui/TableRenderer.js
@@ -177,12 +177,11 @@ export class TextCell extends React.Component {
// }
//
render() {
- const lineHeight = this.props.height - 6 + 'px'; // 6 is the top/bottom padding.
- const style = Object.assign({lineHeight}, this.props.style || {});
var val = getValue(this.props);
- val = (isString(val) && val.search(html_regex) >= 0) ?
: val;
+ const lineHeight = this.props.height - 6 + 'px'; // 6 is the top/bottom padding.
+ val = (val.search && val.search(html_regex) >= 0) ? : val;
return (
- {val}
+ {val}
);
}
}
diff --git a/src/firefly/js/ui/TextButton.jsx b/src/firefly/js/ui/TextButton.jsx
new file mode 100644
index 0000000000..3983d1f3a4
--- /dev/null
+++ b/src/firefly/js/ui/TextButton.jsx
@@ -0,0 +1,51 @@
+/*
+ * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
+ */
+
+
+import React, {PropTypes} from 'react';
+
+const labelStyle= {
+ display: 'inline-block',
+ lineHeight: '30px',
+ fontSize: '10pt',
+ fontStyle: 'italic',
+ color: 'blue',
+ verticalAlign:'baseline'
+};
+
+/**
+ *
+ * @param text
+ * @param tip
+ * @param onClick
+ * @param style
+ * @return react object
+ */
+export function TextButton({text, tip='$text',style={}, onClick}) {
+ var s= Object.assign({cursor:'pointer', verticalAlign:'bottom'},style);
+ return (
+
+ );
+}
+
+
+//CloseButton.contextTypes= {
+//};
+
+
+TextButton.propTypes= {
+ text : PropTypes.string,
+ style : PropTypes.object,
+ tip : PropTypes.string,
+ onClick : PropTypes.func
+};
+
+
+
diff --git a/src/firefly/js/visualize/ColSelectView.jsx b/src/firefly/js/visualize/ColSelectView.jsx
new file mode 100644
index 0000000000..996b308804
--- /dev/null
+++ b/src/firefly/js/visualize/ColSelectView.jsx
@@ -0,0 +1,139 @@
+/*
+ */
+import React from 'react';
+import DialogRootContainer from '../ui/DialogRootContainer.jsx';
+import {PopupPanel} from '../ui/PopupPanel.jsx';
+import {dispatchTableRemove} from '../tables/TablesCntlr';
+
+import {BasicTable} from '../tables/ui/BasicTable.jsx';
+import {getTblById} from '../tables/TableUtil.js';
+import {dispatchShowDialog} from '../core/ComponentCntlr.js';
+import CompleteButton from '../ui/CompleteButton.jsx';
+import HelpIcon from '../ui/HelpIcon.jsx';
+const popupId = 'XYColSelect';
+const TBL_ID ='selectCol';
+
+const popupPanelResizableStyle = {
+ width: 600,
+ minWidth: 450,
+ height: 450,
+ minHeight: 300,
+ resize: 'both',
+ overflow: 'hidden',
+ position: 'relative'
+};
+
+
+//define the table style only in the table div
+const tableStyle = {boxSizing: 'border-box', paddingLeft:5,paddingRight:5, width: '100%', height: 'calc(100% - 70px)', overflow: 'hidden', flexGrow: 1, display: 'flex', resize:'none'};
+
+//define the complete button
+const closeButtonStyle = {'textAlign': 'center', display: 'inline-block', height:40, marginTop:10, width: '90%'};
+//define the helpButton
+const helpIdStyle = {'textAlign': 'center', display: 'inline-block', height:40, marginRight: 20};
+
+
+export function showColSelectPopup(colValStats,onColSelected,popupTitle,buttonText,currentVal) {
+
+ if (getTblById(TBL_ID)) {
+ dispatchTableRemove(TBL_ID);
+ }
+
+ const colNames = colValStats.map((colVal) => {return colVal.name;});
+ var hlRowNum = getHlRow(currentVal,colNames) || 0;
+
+ // make a local table for plot column selection panel
+ var columns = [
+ {name: 'Name',visibility: 'show', prefWidth: 12},
+ {name: 'Unit',visibility: 'show', prefWidth: 8},
+ {name: 'Type',visibility: 'show', prefWidth: 8},
+ {name: 'Description',visibility: 'show', prefWidth: 60}
+ ];
+ var data = [];
+ for (var i = 0; i < colValStats.length; i++) {
+ data[i] = [
+ colValStats[i].name,
+ colValStats[i].unit,
+ colValStats[i].type,
+ colValStats[i].descr
+ ];
+ }
+ const request = {pageSize:10000};
+ var tableModel = {totalRows: data.length, request, tbl_id:TBL_ID, tableData: {columns, data }, highlightedRow: hlRowNum};
+
+
+ var popup = (
+ {popupForm(tableModel,onColSelected,buttonText,popupId)}
+
+
+ );
+
+ DialogRootContainer.defineDialog(popupId, popup);
+ dispatchShowDialog(popupId);
+}
+
+function popupForm(tableModel, onColSelected,buttonText,popupId) {
+ const tblId = tableModel.tbl_id;
+ return (
+
+ { renderTable(tableModel,popupId)}
+ { renderCloseAndHelpButtons(tblId,onColSelected,buttonText,popupId)}
+
+ );
+
+}
+
+/**
+ * display the data into a tabular format
+ * @param tableModel
+ * @param popupId
+ * @return table section
+ */
+function renderTable(tableModel,popupId) {
+
+ return (
+
+
+
+ );
+
+}
+
+function renderCloseAndHelpButtons(tblId,onColSelected,buttonText,popupId) {
+
+ return(
+
+
+ < CompleteButton
+ text={buttonText}
+ onSuccess={()=>setXYColumns(tblId,onColSelected)}
+ dialogId={popupId}
+ />
+
+ {/* comment out the help button for now
+
+
+
+ */}
+
+);
+}
+
+function setXYColumns(tblId,onColSelected) {
+ const tableModel = getTblById(tblId);
+ var hlRow = tableModel.highlightedRow || 0;
+ const selectedColName = tableModel.tableData.data[hlRow][0];
+ onColSelected(selectedColName);
+
+}
+
+function getHlRow(currentVal,colNames) {
+ for(var i = 0; i < colNames.length; i++) {
+ if (colNames[i] === currentVal) {
+ return i;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/firefly/js/visualize/ColValuesStatistics.js b/src/firefly/js/visualize/ColValuesStatistics.js
index ca66a61814..4b8f6e7401 100644
--- a/src/firefly/js/visualize/ColValuesStatistics.js
+++ b/src/firefly/js/visualize/ColValuesStatistics.js
@@ -1,10 +1,11 @@
export default class ColValuesStatistics{
- constructor(name, descr, unit, min, max, numpoints) {
+ constructor(name, descr, unit, min, max, numpoints,type) {
this.name = name;
this.descr = descr;
this.unit = unit;
this.min = Number(min);
this.max = Number(max);
this.numpoints = Number(numpoints);
+ this.type = type;
}
};
\ No newline at end of file
diff --git a/src/firefly/js/visualize/TableStatsCntlr.js b/src/firefly/js/visualize/TableStatsCntlr.js
index 059f6d88da..9d2f35ab17 100644
--- a/src/firefly/js/visualize/TableStatsCntlr.js
+++ b/src/firefly/js/visualize/TableStatsCntlr.js
@@ -1,6 +1,6 @@
import {flux} from '../Firefly.js';
-import {has, omit} from 'lodash';
+import {get, has, omit} from 'lodash';
import {updateSet, updateMerge} from '../util/WebUtil.js';
import ColValuesStatistics from './ColValuesStatistics.js';
@@ -129,15 +129,23 @@ function fetchTblStats(dispatch, activeTableServerRequest) {
const sreq = Object.assign({}, omit(activeTableServerRequest, ['tbl_id', 'META_INFO']),
{'startIdx': 0, 'pageSize': 1000000});
- const req = TableUtil.makeTblRequest('StatisticsProcessor', null,
- { searchRequest: JSON.stringify(sreq) },
- 'tblstats-'+tbl_id);
+ const req = TableUtil.makeTblRequest('StatisticsProcessor', `Statistics for ${tbl_id}`,
+ { searchRequest: JSON.stringify(sreq) },
+ {'startIdx': 0, 'pageSize': 1000});
TableUtil.doFetchTable(req).then(
(tableModel) => {
if (tableModel.tableData && tableModel.tableData.data) {
+ const columns = get(TableUtil.getTblById(tbl_id), 'tableData.columns', []);
const colStats = tableModel.tableData.data.reduce((colstats, arow) => {
- colstats.push(new ColValuesStatistics(...arow));
+ const r = new ColValuesStatistics(...arow);
+ const col = columns.find((c)=>{return c.name=== r.name;});
+ if (col) {
+ r.unit = col.units && col.units !== 'null' ? col.units : '';
+ r.descr = col.desc ? col.desc: '';
+ r.type = col.type ? col.type : '';
+ }
+ colstats.push(r);
return colstats;
}, []);
dispatch(updateTblStats(
diff --git a/src/firefly/js/visualize/XYPlotOptions.jsx b/src/firefly/js/visualize/XYPlotOptions.jsx
index a9686130de..1ec0672808 100644
--- a/src/firefly/js/visualize/XYPlotOptions.jsx
+++ b/src/firefly/js/visualize/XYPlotOptions.jsx
@@ -17,10 +17,12 @@ import {RadioGroupInputField} from '../ui/RadioGroupInputField.jsx';
import {SuggestBoxInputField} from '../ui/SuggestBoxInputField.jsx';
import {FieldGroupCollapsible} from '../ui/panel/CollapsiblePanel.jsx';
import {plotParamsShape} from './XYPlot.jsx';
+import {showColSelectPopup} from './ColSelectView.jsx';
const DECI_ENABLE_SIZE = 5000;
const helpStyle = {fontStyle: 'italic', color: '#808080', paddingBottom: 10};
+import {TextButton} from '../ui/TextButton.jsx';
/*
* Split content into prior content and the last alphanumeric token in the text
@@ -116,6 +118,23 @@ export function setOptions(groupKey, xyPlotParams) {
dispatchMultiValueChange(groupKey, flds);
}
+export function getColValidator(colValStats) {
+ const colNames = colValStats.map((colVal) => {return colVal.name;});
+ return (val) => {
+ let retval = {valid: true, message: ''};
+ if (!val) {
+ return {valid: false, message: 'Can not be empty. Please provide value or expression'};
+ } else if (colNames.indexOf(val) < 0) {
+ const expr = new Expression(val, colNames);
+ if (!expr.isValid()) {
+ retval = {valid: false, message: `${expr.getError().error}. Unable to parse ${val}.`};
+ }
+ }
+ return retval;
+ };
+}
+
+
var XYPlotOptions = React.createClass({
@@ -126,6 +145,18 @@ var XYPlotOptions = React.createClass({
xyPlotParams: plotParamsShape
},
+ componentDidMount() {
+ // make sure column validator matches current columns
+ const {colValStats, groupKey} = this.props;
+ if (colValStats) {
+ const colValidator = getColValidator(colValStats);
+ const flds = [
+ {fieldKey: 'x.columnOrExpr', validator: colValidator},
+ {fieldKey: 'y.columnOrExpr', validator: colValidator}
+ ];
+ dispatchMultiValueChange(groupKey, flds);
+ }
+ },
shouldComponentUpdate(np) {
return this.props.groupKey !== np.groupKey || this.props.colValStats !== np.colValStats ||
@@ -191,7 +222,6 @@ var XYPlotOptions = React.createClass({
render() {
const { colValStats, groupKey, xyPlotParams, onOptionsSelected}= this.props;
- const colNames = colValStats.map((colVal) => {return colVal.name;});
// the suggestions are indexes in the colValStats array - it makes it easier to render then with labels
const allSuggestions = colValStats.map((colVal,idx)=>{return idx;});
@@ -212,19 +242,27 @@ var XYPlotOptions = React.createClass({
return priorContent+colValStats[idx].name;
};
- const colValidator = (val) => {
- let retval = {valid: true, message: ''};
- if (!val) {
- return {valid: false, message: 'Can not be empty. Please provide value or expression'};
- } else if (colNames.indexOf(val)<0) {
- const expr = new Expression(val,colNames);
- if (!expr.isValid()) {
- retval = {valid: false, message: `${expr.getError().error}. Unable to parse ${val}.`};
- }
- }
- return retval;
- };
-
+ var x = get(xyPlotParams, 'x.columnOrExpr');
+ var y = get(xyPlotParams, 'y.columnOrExpr');
+ const onXColSelected = (colName) => {
+ x = colName;
+ const flds = [
+ {fieldKey: 'x.columnOrExpr', value: colName},
+ {fieldKey: 'x.label', value: ''},
+ {fieldKey: 'x.unit', value: ''}
+ ];
+ dispatchMultiValueChange(groupKey, flds);
+ };
+ const onYColSelected = (colName) => {
+ y = colName;
+ const flds = [
+ {fieldKey: 'y.columnOrExpr', value: colName},
+ {fieldKey: 'y.label', value: ''},
+ {fieldKey: 'y.unit', value: ''}
+ ];
+ dispatchMultiValueChange(groupKey, flds);
+ };
+
return (
@@ -233,21 +271,42 @@ var XYPlotOptions = React.createClass({
For X and Y, enter a column or an expression
ex. log(col); 100*col1/col2; col1-col2
-
+
+
+
+ |
+
+
+
+ |
+
+
+ showColSelectPopup(colValStats, onXColSelected,'Choose X','Set X',x)}
+ onSuccess={this.resultsSuccess}
+ onFail={this.resultsFail}
+ />
+
+ |
+
+
+
+
@@ -291,21 +350,42 @@ var XYPlotOptions = React.createClass({
-
+
+
+
+ |
+
+
+
+ |
+
+
+ showColSelectPopup(colValStats,onYColSelected,'Choose Y','Set Y',y)}
+ onSuccess={this.resultsSuccess}
+ onFail={this.resultsFail}
+ />
+
+ |
+
+
+
+