Skip to content

Commit 990dd29

Browse files
committed
- removes BasicTable
- client-side filtering - added more jsdoc for table related code - fix filter input field auto-correct issue.
1 parent 55592c9 commit 990dd29

File tree

13 files changed

+361
-274
lines changed

13 files changed

+361
-274
lines changed

src/firefly/html/firefly.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<script type="text/javascript" src="firefly_loader.js"></script>
2727
</head>
2828

29-
<body style="margin: 0px;">
29+
<body style="margin: 0; background-color: rgb(200,200,200)">
3030
<!-- attached loaction for firefly app -->
3131
<div id='app'/>
3232

src/firefly/js/charts/ui/ColSelectView.jsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import DialogRootContainer from '../../ui/DialogRootContainer.jsx';
55
import {PopupPanel} from '../../ui/PopupPanel.jsx';
66
import {dispatchTableRemove} from '../../tables/TablesCntlr';
77

8-
import {BasicTable} from '../../tables/ui/BasicTable.jsx';
9-
import {getTblById} from '../../tables/TableUtil.js';
8+
import {TablePanel} from '../../tables/ui/TablePanel.jsx';
9+
import {getTblById, calcColumnWidths} from '../../tables/TableUtil.js';
1010
import {dispatchShowDialog, dispatchHideDialog, isDialogVisible} from '../../core/ComponentCntlr.js';
1111
import CompleteButton from '../../ui/CompleteButton.jsx';
1212
//import HelpIcon from '../../ui/HelpIcon.jsx';
@@ -25,7 +25,7 @@ const popupPanelResizableStyle = {
2525

2626

2727
//define the table style only in the table div
28-
const tableStyle = {boxSizing: 'border-box', paddingLeft:5,paddingRight:5, width: '100%', height: 'calc(100% - 70px)', overflow: 'hidden', flexGrow: 1, display: 'flex', resize:'none'};
28+
const tableStyle = {boxSizing: 'border-box', width: '100%', height: 'calc(100% - 40px)', overflow: 'hidden', resize:'none'};
2929

3030
//define the complete button
3131
const closeButtonStyle = {'textAlign': 'center', display: 'inline-block', height:40, marginTop:10, width: '90%'};
@@ -45,10 +45,10 @@ export function showColSelectPopup(colValStats,onColSelected,popupTitle,buttonTe
4545

4646
// make a local table for plot column selection panel
4747
var columns = [
48-
{name: 'Name',visibility: 'show', prefWidth: 12},
49-
{name: 'Unit',visibility: 'show', prefWidth: 8},
50-
{name: 'Type',visibility: 'show', prefWidth: 8},
51-
{name: 'Description',visibility: 'show', prefWidth: 60}
48+
{name: 'Name'},
49+
{name: 'Unit'},
50+
{name: 'Type'},
51+
{name: 'Description'}
5252
];
5353
var data = [];
5454
for (var i = 0; i < colValStats.length; i++) {
@@ -59,6 +59,14 @@ export function showColSelectPopup(colValStats,onColSelected,popupTitle,buttonTe
5959
colValStats[i].descr
6060
];
6161
}
62+
63+
const widths = calcColumnWidths(columns, data);
64+
columns[0].prefWidth = Math.min(widths[0], 30); // adjust width of column for optimum display.
65+
columns[1].prefWidth = Math.min(widths[1], 15);
66+
columns[2].prefWidth = Math.min(widths[2], 15);
67+
columns[3].prefWidth = Math.min(widths[3], 100);
68+
69+
6270
const request = {pageSize:10000};
6371
var tableModel = {totalRows: data.length, request, tbl_id:TBL_ID, tableData: {columns, data }, highlightedRow: hlRowNum};
6472

@@ -100,9 +108,12 @@ function renderTable(tableModel,popupId) {
100108

101109
return (
102110
<div style={tableStyle}>
103-
<BasicTable
111+
<TablePanel
104112
key={popupId}
105113
tableModel={tableModel}
114+
showToolbar={false}
115+
selectable={false}
116+
border={false}
106117
/>
107118
</div>
108119
);

src/firefly/js/tables/FilterInfo.js

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
/**
2-
* Created by loi on 1/15/16.
3-
*/
4-
5-
61
/*
72
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
83
*/
9-
const op_regex = new RegExp('(!=|>=|<=|<|>|=|like|in)', 'i');
10-
const cond_regex = new RegExp('^' + op_regex.source + '\\s+(.+)', 'i');
11-
const filter_regex = new RegExp('(\\S+)\\s+' + op_regex.source + '\\s+(.+)', 'i');
4+
5+
import {getColumnIdx, getColumn} from './TableUtil.js';
6+
const cond_regex = new RegExp('(!=|>=|<=|<|>|=|like|in)\\s*(.+)');
7+
const cond_only_regex = new RegExp('^' + cond_regex.source, 'i');
8+
const filter_regex = new RegExp('(\\S+)\\s*' + cond_regex.source, 'i');
129

1310
export const FILTER_CONDITION_TTIPS =
1411
`Valid values are one of (=, >, <, !=, >=, <=, LIKE) followed by a value separated by a space.
@@ -47,8 +44,8 @@ export class FilterInfo {
4744
var filterInfo = new FilterInfo();
4845
if (filterString) {
4946
filterString && filterString.split(';').forEach( (v) => {
50-
const parts = v.trim().match(filter_regex);
51-
if (parts.length > 3) filterInfo.addFilter(parts[1], `${parts[2]} ${parts[3]}`);
47+
const [, cname, op, val] = v.trim().match(filter_regex) || [];
48+
if (cname) filterInfo.addFilter(cname, `${op} ${val}`);
5249
});
5350
}
5451
return filterInfo;
@@ -63,8 +60,8 @@ export class FilterInfo {
6360
static autoCorrect(conditions) {
6461
if (conditions) {
6562
const parts = conditions.split(';').map( (v) => {
66-
const opVal = v.replace(/\(|\)| /g, '').split(op_regex);
67-
var [op, val] = opVal.length > 1 ? [ opVal[1], opVal[2] ] : [ 'like', opVal[0] ]; // defualt to 'like' if no operators found
63+
var [, op, val] = v.trim().replace(/[()]/g, '').match(cond_only_regex) || [];
64+
[op, val] = op ? [op, val] : [ 'like', v.trim() ]; // defualt to 'like' if no operators found
6865
val = op.toLowerCase() === 'in' ? `(${val})` : val; // add parentheses when 'in' is used.
6966
return `${op} ${val}`;
7067
});
@@ -83,9 +80,9 @@ export class FilterInfo {
8380
static autoCorrectFilter(filterInfo) {
8481
if (filterInfo) {
8582
const filters = filterInfo.split(';').map( (v) => {
86-
const parts = v.split(op_regex).map( (s) => s.trim());
87-
if (parts.length != 3) return v;
88-
return `${parts[0]} ${FilterInfo.autoCorrect(parts[1]+parts[2])}`;
83+
const [, cname, op, val] = v.trim().match(filter_regex) || [];
84+
if (!cname) return v;
85+
return `${cname} ${FilterInfo.autoCorrect(op + ' ' + val)}`;
8986
});
9087
return filters.join(';');
9188
} else {
@@ -100,7 +97,7 @@ export class FilterInfo {
10097
*/
10198
static isConditionValid(conditions) {
10299
return !conditions || conditions.split(';').reduce( (rval, v) => {
103-
return rval && cond_regex.test(v.trim());
100+
return rval && cond_only_regex.test(v.trim());
104101
}, true);
105102
}
106103

@@ -117,19 +114,19 @@ export class FilterInfo {
117114

118115
/**
119116
* validate the filterInfo string
120-
* @param conditions
121-
* @param columns array of column definitions
117+
* @param {string} filterInfo
118+
* @param {TableColumn[]} columns array of column definitions
122119
* @returns {[boolean, string]} isValid plus an error message if isValid is false.
123120
*/
124121
static isValid(filterInfo, columns = []) {
125122
const rval = [true, ''];
126123
const allowCols = columns.concat({name:'ROWID'});
127124
if (filterInfo && filterInfo.trim().length > 0) {
128125
return filterInfo.split(';').reduce( ([isValid, msg], v) => {
129-
const parts = v.split(op_regex).map( (s) => s.trim());
130-
if (parts.length !== 3) {
126+
const [, cname] = v.trim().match(filter_regex) || [];
127+
if (!cname) {
131128
msg += `\n"${v}" is not a valid filter.`;
132-
} else if (!allowCols.some( (col) => col.name === parts[0])) {
129+
} else if (!allowCols.some( (c) => c.name === cname)) {
133130
msg +=`\n"${v}" column not found.\n`;
134131
}
135132
return [!msg, msg];
@@ -141,8 +138,8 @@ export class FilterInfo {
141138

142139
/**
143140
* validator for free-form filters field
144-
* @param filterInfo string serialized filter list
145-
* @param columns array of column definitions
141+
* @param {TableColumn[]} columns array of column definitions
142+
* @param {string} filterInfo
146143
* @returns {{valid: boolean, value: (string|*), message: string}}
147144
*/
148145
static validator(columns, filterInfo) {
@@ -151,6 +148,49 @@ export class FilterInfo {
151148
return {valid, value: filterInfo, message};
152149
}
153150

151+
/**
152+
* returns a comparator function that takes a row(string[]) as parameter.
153+
* This comparator will returns true if the given row passes the given filterStr.
154+
* @param {string} filterStr
155+
* @param {TableModel} tableModel
156+
* @returns {function(): boolean}
157+
*/
158+
static createComparator(filterStr, tableModel) {
159+
var [ , cname, op, val] =filterStr.match(filter_regex) || [];
160+
if (!cname) return () => false; // bad filter.. returns nothing.
161+
162+
op = op.toLowerCase();
163+
val = val.toLowerCase();
164+
const cidx = getColumnIdx(tableModel, cname);
165+
const col = getColumn(tableModel, cname);
166+
val = op === 'in' ? val.replace(/[()]/g, '').split(',').map((s) => s.trim()) : val;
167+
return (row) => {
168+
var compareTo = row[cidx].toLowerCase();
169+
if (!['in','like'].includes(op) && col.type.match(/^[dfil]/)) { // int, float, double, long .. or their short form.
170+
val = Number(val);
171+
compareTo = Number(compareTo);
172+
}
173+
switch (op) {
174+
case '!=' :
175+
return compareTo !== val;
176+
case '>=' :
177+
return compareTo >= val;
178+
case '<=' :
179+
return compareTo <= val;
180+
case '>' :
181+
return compareTo > val;
182+
case '=' :
183+
return compareTo === val;
184+
case 'like' :
185+
return compareTo.includes(val);
186+
case 'in' :
187+
return val.includes(compareTo);
188+
default :
189+
return false;
190+
}
191+
};
192+
}
193+
154194
serialize() {
155195
return Object.keys(this).reduce( (rval, key) => {
156196
this[key].split(';').forEach((v) => {
@@ -174,8 +214,8 @@ export class FilterInfo {
174214
Reflect.deleteProperty(this, colName);
175215
if (conditions) {
176216
conditions.split(';').forEach( (v) => {
177-
const parts = v.trim().match(cond_regex);
178-
if (parts.length > 2) this.addFilter(colName, `${parts[1]} ${parts[2]}`);
217+
const [, op, val] = v.trim().match(cond_only_regex) || [];
218+
if (op) this.addFilter(colName, `${op} ${val}`);
179219
});
180220
}
181221
}

src/firefly/js/tables/TableConnector.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class TableConnector {
2222
var {tableModel, request} = TblUtil.getTblInfoById(this.tbl_id);
2323
if (this.origTableModel) {
2424
tableModel = TblUtil.sortTable(this.origTableModel, sortInfoString);
25-
flux.process({type: TblCntlr.TABLE_REPLACE, payload: tableModel});
25+
TblCntlr.dispatchTableReplace(tableModel);
2626
} else {
2727
request = Object.assign({}, request, {sortInfo: sortInfoString});
2828
TblCntlr.dispatchTableSort(request);
@@ -32,7 +32,8 @@ export class TableConnector {
3232
onFilter(filterIntoString) {
3333
var {tableModel, request} = TblUtil.getTblInfoById(this.tbl_id);
3434
if (this.origTableModel) {
35-
// not implemented yet
35+
tableModel = filterIntoString ? TblUtil.filterTable(this.origTableModel, filterIntoString) : this.origTableModel;
36+
TblCntlr.dispatchTableReplace(tableModel);
3637
} else {
3738
request = Object.assign({}, request, {filters: filterIntoString});
3839
TblCntlr.dispatchTableFilter(request);

0 commit comments

Comments
 (0)