virool-pivot
Version:
A web-based exploratory visualization UI for Druid.io
1,472 lines • 73.7 kB
JavaScript
webpackJsonp([3],{
/***/ 337:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(338);
var React = __webpack_require__(5);
var index_1 = __webpack_require__(194);
var bubble_menu_1 = __webpack_require__(261);
var string_filter_menu_1 = __webpack_require__(340);
var time_filter_menu_1 = __webpack_require__(349);
var number_filter_menu_1 = __webpack_require__(363);
var FilterMenu = (function (_super) {
__extends(FilterMenu, _super);
function FilterMenu() {
_super.call(this);
}
FilterMenu.prototype.render = function () {
var _a = this.props, clicker = _a.clicker, essence = _a.essence, changePosition = _a.changePosition, direction = _a.direction, containerStage = _a.containerStage, openOn = _a.openOn, dimension = _a.dimension, onClose = _a.onClose, inside = _a.inside;
if (!dimension)
return null;
var menuSize = null;
var menuCont = null;
if (dimension.kind === 'time') {
menuSize = index_1.Stage.fromSize(250, 274);
menuCont = React.createElement(time_filter_menu_1.TimeFilterMenu, {clicker: clicker, dimension: dimension, essence: essence, onClose: onClose});
}
else if (dimension.kind === 'number') {
menuSize = index_1.Stage.fromSize(250, 274);
menuCont = React.createElement(number_filter_menu_1.NumberFilterMenu, {clicker: clicker, dimension: dimension, essence: essence, onClose: onClose});
}
else {
menuSize = index_1.Stage.fromSize(250, 410);
menuCont = React.createElement(string_filter_menu_1.StringFilterMenu, {clicker: clicker, dimension: dimension, essence: essence, changePosition: changePosition, onClose: onClose});
}
return React.createElement(bubble_menu_1.BubbleMenu, {className: "filter-menu", direction: direction, containerStage: containerStage, stage: menuSize, openOn: openOn, onClose: onClose, inside: inside}, menuCont);
};
return FilterMenu;
}(React.Component));
exports.FilterMenu = FilterMenu;
/***/ },
/***/ 338:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(339);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./filter-menu.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./filter-menu.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 339:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".filter-menu .button-bar{margin-top:12px}.filter-menu .button-bar button{min-width:70px}.filter-menu .button-bar button:not(:last-child){margin-right:6px}\n", ""]);
// exports
/***/ },
/***/ 340:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(341);
var React = __webpack_require__(5);
var plywood_1 = __webpack_require__(190);
var constants_1 = __webpack_require__(227);
var index_1 = __webpack_require__(194);
var general_1 = __webpack_require__(199);
var dom_1 = __webpack_require__(245);
var clearable_input_1 = __webpack_require__(301);
var checkbox_1 = __webpack_require__(324);
var loader_1 = __webpack_require__(173);
var query_error_1 = __webpack_require__(343);
var highlight_string_1 = __webpack_require__(292);
var button_1 = __webpack_require__(346);
var TOP_N = 100;
var StringFilterMenu = (function (_super) {
__extends(StringFilterMenu, _super);
function StringFilterMenu() {
var _this = this;
_super.call(this);
this.state = {
loading: false,
dataset: null,
error: null,
fetchQueued: false,
searchText: '',
selectedValues: null,
colors: null
};
this.collectTriggerSearch = general_1.collect(constants_1.SEARCH_WAIT, function () {
if (!_this.mounted)
return;
var _a = _this.props, essence = _a.essence, dimension = _a.dimension;
_this.fetchData(essence, dimension);
});
this.globalKeyDownListener = this.globalKeyDownListener.bind(this);
}
StringFilterMenu.prototype.fetchData = function (essence, dimension) {
var _this = this;
var searchText = this.state.searchText;
var dataSource = essence.dataSource;
var nativeCount = dataSource.getMeasure('count');
var measureExpression = nativeCount ? nativeCount.expression : plywood_1.$('main').count();
var filterExpression = essence.getEffectiveFilter(null, dimension).toExpression();
if (searchText) {
filterExpression = filterExpression.and(dimension.expression.contains(plywood_1.r(searchText), 'ignoreCase'));
}
var query = plywood_1.$('main')
.filter(filterExpression)
.split(dimension.expression, dimension.name)
.apply('MEASURE', measureExpression)
.sort(plywood_1.$('MEASURE'), plywood_1.SortAction.DESCENDING)
.limit(TOP_N + 1);
this.setState({
loading: true,
fetchQueued: false
});
dataSource.executor(query, { timezone: essence.timezone })
.then(function (dataset) {
if (!_this.mounted)
return;
_this.setState({
loading: false,
dataset: dataset,
error: null
});
}, function (error) {
if (!_this.mounted)
return;
_this.setState({
loading: false,
dataset: null,
error: error
});
});
};
StringFilterMenu.prototype.componentWillMount = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var filter = essence.filter, colors = essence.colors;
var myColors = (colors && colors.dimension === dimension.name ? colors : null);
var valueSet = filter.getLiteralSet(dimension.expression);
this.setState({
selectedValues: valueSet || (myColors ? myColors.toSet() : null) || plywood_1.Set.EMPTY,
colors: myColors
});
this.fetchData(essence, dimension);
};
StringFilterMenu.prototype.componentWillReceiveProps = function (nextProps) {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var nextEssence = nextProps.essence;
var nextDimension = nextProps.dimension;
if (essence.differentDataSource(nextEssence) ||
essence.differentEffectiveFilter(nextEssence, null, nextDimension) || !dimension.equals(nextDimension)) {
this.fetchData(nextEssence, nextDimension);
}
};
StringFilterMenu.prototype.componentDidMount = function () {
this.mounted = true;
window.addEventListener('keydown', this.globalKeyDownListener);
};
StringFilterMenu.prototype.componentWillUnmount = function () {
this.mounted = false;
window.removeEventListener('keydown', this.globalKeyDownListener);
};
StringFilterMenu.prototype.globalKeyDownListener = function (e) {
if (dom_1.enterKey(e)) {
this.onOkClick();
}
};
StringFilterMenu.prototype.constructFilter = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension, changePosition = _a.changePosition;
var selectedValues = this.state.selectedValues;
var filter = essence.filter;
if (selectedValues.size()) {
var clause = new index_1.FilterClause({
expression: dimension.expression,
selection: plywood_1.r(selectedValues)
});
if (changePosition) {
if (changePosition.isInsert()) {
return filter.insertByIndex(changePosition.insert, clause);
}
else {
return filter.replaceByIndex(changePosition.replace, clause);
}
}
else {
return filter.setClause(clause);
}
}
else {
return filter.remove(dimension.expression);
}
};
StringFilterMenu.prototype.onSearchChange = function (text) {
var _a = this.state, searchText = _a.searchText, dataset = _a.dataset, fetchQueued = _a.fetchQueued, loading = _a.loading;
var newSearchText = text.substr(0, constants_1.MAX_SEARCH_LENGTH);
// If the user is just typing in more and there are already < TOP_N results then there is nothing to do
if (newSearchText.indexOf(searchText) !== -1 && !fetchQueued && !loading && dataset && dataset.data.length < TOP_N) {
this.setState({
searchText: newSearchText
});
return;
}
this.setState({
searchText: newSearchText,
fetchQueued: true
});
this.collectTriggerSearch();
};
StringFilterMenu.prototype.onValueClick = function (value, e) {
var _a = this.state, selectedValues = _a.selectedValues, colors = _a.colors;
if (colors) {
colors = colors.toggle(value);
selectedValues = selectedValues.toggle(value);
}
else {
if (e.altKey || e.ctrlKey || e.metaKey) {
if (selectedValues.contains(value) && selectedValues.size() === 1) {
selectedValues = plywood_1.Set.EMPTY;
}
else {
selectedValues = plywood_1.Set.EMPTY.add(value);
}
}
else {
selectedValues = selectedValues.toggle(value);
}
}
this.setState({
selectedValues: selectedValues,
colors: colors
});
};
StringFilterMenu.prototype.onOkClick = function () {
if (!this.actionEnabled())
return;
var _a = this.props, clicker = _a.clicker, onClose = _a.onClose;
var colors = this.state.colors;
clicker.changeFilter(this.constructFilter(), colors);
onClose();
};
StringFilterMenu.prototype.onCancelClick = function () {
var onClose = this.props.onClose;
onClose();
};
StringFilterMenu.prototype.actionEnabled = function () {
var essence = this.props.essence;
return !essence.filter.equals(this.constructFilter());
};
StringFilterMenu.prototype.renderTable = function () {
var _this = this;
var _a = this.state, loading = _a.loading, dataset = _a.dataset, error = _a.error, fetchQueued = _a.fetchQueued, searchText = _a.searchText, selectedValues = _a.selectedValues;
var dimension = this.props.dimension;
var rows = [];
var hasMore = false;
if (dataset) {
hasMore = dataset.data.length > TOP_N;
var rowData = dataset.data.slice(0, TOP_N);
if (searchText) {
var searchTextLower = searchText.toLowerCase();
rowData = rowData.filter(function (d) {
return String(d[dimension.name]).toLowerCase().indexOf(searchTextLower) !== -1;
});
}
rows = rowData.map(function (d) {
var segmentValue = d[dimension.name];
var segmentValueStr = String(segmentValue);
var selected = selectedValues && selectedValues.contains(segmentValue);
return React.createElement("div", {className: 'row' + (selected ? ' selected' : ''), key: segmentValueStr, title: segmentValueStr, onClick: _this.onValueClick.bind(_this, segmentValue)}, React.createElement("div", {className: "row-wrapper"}, React.createElement(checkbox_1.Checkbox, {selected: selected}), React.createElement(highlight_string_1.HighlightString, {className: "label", text: segmentValueStr, highlightText: searchText})));
});
}
var message = null;
if (!loading && dataset && !fetchQueued && searchText && !rows.length) {
message = React.createElement("div", {className: "message"}, 'No results for "' + searchText + '"');
}
var className = [
'menu-table',
(hasMore ? 'has-more' : 'no-more')
].join(' ');
return React.createElement("div", {className: className}, React.createElement("div", {className: "search-box"}, React.createElement(clearable_input_1.ClearableInput, {placeholder: "Search", focusOnMount: true, value: searchText, onChange: this.onSearchChange.bind(this)})), React.createElement("div", {className: "rows"}, rows, message), error ? React.createElement(query_error_1.QueryError, {error: error}) : null, loading ? React.createElement(loader_1.Loader, null) : null);
};
StringFilterMenu.prototype.render = function () {
var dimension = this.props.dimension;
if (!dimension)
return null;
return React.createElement("div", {className: "string-filter-menu"}, this.renderTable(), React.createElement("div", {className: "button-bar"}, React.createElement(button_1.Button, {type: "primary", title: constants_1.STRINGS.ok, onClick: this.onOkClick.bind(this), disabled: !this.actionEnabled()}), React.createElement(button_1.Button, {type: "secondary", title: constants_1.STRINGS.cancel, onClick: this.onCancelClick.bind(this)})));
};
return StringFilterMenu;
}(React.Component));
exports.StringFilterMenu = StringFilterMenu;
/***/ },
/***/ 341:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(342);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./string-filter-menu.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./string-filter-menu.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 342:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".string-filter-menu .menu-table .search-box .clearable-input{background:#fff;border:1px solid #d1d1d1;border-radius:2px;box-shadow:inset 0 1px 1px 0 rgba(0,0,0,0.1)}.string-filter-menu .menu-table:after{position:absolute;top:0;bottom:0;left:0;right:0;content:'';pointer-events:none;box-shadow:inset 0 -20px 10px -10px #fff;border-radius:2px}.string-filter-menu .menu-table{background:#fff;color:#000}.string-filter-menu .menu-table:after{position:absolute;top:0;bottom:0;left:-14px;right:-14px}.string-filter-menu .menu-table .search-box{height:30px}.string-filter-menu .menu-table .search-box .clearable-input{width:100%;height:30px;padding-left:6px}.string-filter-menu .menu-table .rows{height:280px;margin-top:10px;margin-left:-14px;margin-right:-14px;overflow:auto}.string-filter-menu .menu-table .row{height:24px;cursor:pointer;padding:0 14px}.string-filter-menu .menu-table .row .row-wrapper{white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;height:100%}.string-filter-menu .menu-table .row .row-wrapper .label{display:inline-block;vertical-align:top;padding-top:4px}.string-filter-menu .menu-table .row:hover{background:#e3f4fc}.string-filter-menu .menu-table .row:last-child{margin-bottom:12px}.string-filter-menu .menu-table .message{padding:4px 10px;color:#999;font-style:italic}.string-filter-menu .menu-table .loader,.string-filter-menu .menu-table .query-error{position:absolute;top:0;bottom:0;left:0;right:0}\n", ""]);
// exports
/***/ },
/***/ 349:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(350);
var React = __webpack_require__(5);
var chronoshift_1 = __webpack_require__(181);
var plywood_1 = __webpack_require__(190);
var constants_1 = __webpack_require__(227);
var index_1 = __webpack_require__(194);
var time_1 = __webpack_require__(209);
var dom_1 = __webpack_require__(245);
var button_1 = __webpack_require__(346);
var button_group_1 = __webpack_require__(352);
var date_range_picker_1 = __webpack_require__(355);
var $maxTime = plywood_1.$(index_1.FilterClause.MAX_TIME_REF_NAME);
var latestPresets = [
{ name: '1H', selection: $maxTime.timeRange('PT1H', -1) },
{ name: '6H', selection: $maxTime.timeRange('PT6H', -1) },
{ name: '1D', selection: $maxTime.timeRange('P1D', -1) },
{ name: '7D', selection: $maxTime.timeRange('P1D', -7) },
{ name: '30D', selection: $maxTime.timeRange('P1D', -30) }
];
var $now = plywood_1.$(index_1.FilterClause.NOW_REF_NAME);
var currentPresets = [
{ name: 'D', selection: $now.timeBucket('P1D') },
{ name: 'W', selection: $now.timeBucket('P1W') },
{ name: 'M', selection: $now.timeBucket('P1M') },
{ name: 'Q', selection: $now.timeBucket('P3M') },
{ name: 'Y', selection: $now.timeBucket('P1Y') }
];
var previousPresets = [
{ name: 'D', selection: $now.timeFloor('P1D').timeRange('P1D', -1) },
{ name: 'W', selection: $now.timeFloor('P1W').timeRange('P1W', -1) },
{ name: 'M', selection: $now.timeFloor('P1M').timeRange('P1M', -1) },
{ name: 'Q', selection: $now.timeFloor('P3M').timeRange('P3M', -1) },
{ name: 'Y', selection: $now.timeFloor('P1Y').timeRange('P1Y', -1) }
];
var TimeFilterMenu = (function (_super) {
__extends(TimeFilterMenu, _super);
function TimeFilterMenu() {
_super.call(this);
this.state = {
tab: null,
timeSelection: null,
startTime: null,
endTime: null,
hoverPreset: null
};
this.globalKeyDownListener = this.globalKeyDownListener.bind(this);
}
TimeFilterMenu.prototype.componentWillMount = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var filter = essence.filter;
var timezone = essence.timezone;
var timeSelection = filter.getSelection(dimension.expression);
var selectedTimeRangeSet = essence.getEffectiveFilter().getLiteralSet(dimension.expression);
var selectedTimeRange = (selectedTimeRangeSet && selectedTimeRangeSet.size() === 1) ? selectedTimeRangeSet.elements[0] : null;
this.setState({
timeSelection: timeSelection,
tab: (filter.isEmpty() || filter.isRelative()) ? 'relative' : 'specific',
startTime: selectedTimeRange ? chronoshift_1.day.floor(selectedTimeRange.start, timezone) : null,
endTime: selectedTimeRange ? chronoshift_1.day.ceil(selectedTimeRange.end, timezone) : null
});
};
TimeFilterMenu.prototype.componentDidMount = function () {
window.addEventListener('keydown', this.globalKeyDownListener);
};
TimeFilterMenu.prototype.componentWillUnmount = function () {
window.removeEventListener('keydown', this.globalKeyDownListener);
};
TimeFilterMenu.prototype.globalKeyDownListener = function (e) {
if (dom_1.enterKey(e)) {
this.onOkClick();
}
};
TimeFilterMenu.prototype.constructFilter = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var _b = this.state, tab = _b.tab, startTime = _b.startTime, endTime = _b.endTime;
var filter = essence.filter;
var timezone = essence.timezone;
if (tab !== 'specific')
return null;
if (startTime && !endTime) {
endTime = chronoshift_1.day.shift(startTime, timezone, 1);
}
if (startTime && endTime && startTime < endTime) {
return filter.setSelection(dimension.expression, plywood_1.r(plywood_1.TimeRange.fromJS({ start: startTime, end: endTime })));
}
else {
return null;
}
};
TimeFilterMenu.prototype.onPresetClick = function (preset) {
var _a = this.props, clicker = _a.clicker, onClose = _a.onClose;
clicker.changeTimeSelection(preset.selection);
onClose();
};
TimeFilterMenu.prototype.onPresetMouseEnter = function (preset) {
var hoverPreset = this.state.hoverPreset;
if (hoverPreset === preset)
return;
this.setState({
hoverPreset: preset
});
};
TimeFilterMenu.prototype.onPresetMouseLeave = function (preset) {
var hoverPreset = this.state.hoverPreset;
if (hoverPreset !== preset)
return;
this.setState({
hoverPreset: null
});
};
TimeFilterMenu.prototype.onStartChange = function (start) {
this.setState({
startTime: start
});
};
TimeFilterMenu.prototype.onEndChange = function (end) {
this.setState({
endTime: end
});
};
TimeFilterMenu.prototype.selectTab = function (tab) {
this.setState({ tab: tab });
};
TimeFilterMenu.prototype.onOkClick = function () {
if (!this.actionEnabled())
return;
var _a = this.props, clicker = _a.clicker, onClose = _a.onClose;
var newFilter = this.constructFilter();
if (!newFilter)
return;
clicker.changeFilter(newFilter);
onClose();
};
TimeFilterMenu.prototype.onCancelClick = function () {
var onClose = this.props.onClose;
onClose();
};
TimeFilterMenu.prototype.renderPresets = function () {
var _this = this;
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var _b = this.state, timeSelection = _b.timeSelection, hoverPreset = _b.hoverPreset;
if (!dimension)
return null;
var timezone = essence.timezone;
var presetToButton = function (preset) {
return React.createElement("button", {key: preset.name, className: dom_1.classNames('preset', { hover: preset === hoverPreset, selected: preset.selection.equals(timeSelection) }), onClick: _this.onPresetClick.bind(_this, preset), onMouseEnter: _this.onPresetMouseEnter.bind(_this, preset), onMouseLeave: _this.onPresetMouseLeave.bind(_this, preset)}, preset.name);
};
var previewTimeRange = essence.evaluateSelection(hoverPreset ? hoverPreset.selection : timeSelection);
var previewText = previewTimeRange ? time_1.formatTimeRange(previewTimeRange, timezone, time_1.DisplayYear.IF_DIFF) : constants_1.STRINGS.noFilter;
return React.createElement("div", {className: "cont"}, React.createElement("div", {className: "type"}, constants_1.STRINGS.latest), React.createElement("div", {className: "buttons"}, latestPresets.map(presetToButton)), React.createElement("div", {className: "type"}, constants_1.STRINGS.current), React.createElement("div", {className: "buttons"}, currentPresets.map(presetToButton)), React.createElement("div", {className: "type"}, constants_1.STRINGS.previous), React.createElement("div", {className: "buttons"}, previousPresets.map(presetToButton)), React.createElement("div", {className: "preview"}, previewText));
};
TimeFilterMenu.prototype.actionEnabled = function () {
var essence = this.props.essence;
var tab = this.state.tab;
if (tab !== 'specific')
return false;
var newFilter = this.constructFilter();
return newFilter && !essence.filter.equals(newFilter);
};
TimeFilterMenu.prototype.renderCustom = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var _b = this.state, timeSelection = _b.timeSelection, startTime = _b.startTime, endTime = _b.endTime;
if (!dimension)
return null;
if (!timeSelection)
return null;
return React.createElement("div", null, React.createElement(date_range_picker_1.DateRangePicker, {startTime: startTime, endTime: endTime, maxTime: essence.dataSource.getMaxTimeDate(), timezone: essence.timezone, onStartChange: this.onStartChange.bind(this), onEndChange: this.onEndChange.bind(this)}), React.createElement("div", {className: "button-bar"}, React.createElement(button_1.Button, {type: "primary", onClick: this.onOkClick.bind(this), disabled: !this.actionEnabled(), title: constants_1.STRINGS.ok}), React.createElement(button_1.Button, {type: "secondary", onClick: this.onCancelClick.bind(this), title: constants_1.STRINGS.cancel})));
};
;
TimeFilterMenu.prototype.render = function () {
var _this = this;
var dimension = this.props.dimension;
var tab = this.state.tab;
if (!dimension)
return null;
var tabs = ['relative', 'specific'].map(function (name) {
return {
isSelected: tab === name,
title: (name === 'relative' ? constants_1.STRINGS.relative : constants_1.STRINGS.specific),
key: name,
onClick: _this.selectTab.bind(_this, name)
};
});
return React.createElement("div", {className: "time-filter-menu"}, React.createElement(button_group_1.ButtonGroup, {groupMembers: tabs}), tab === 'relative' ? this.renderPresets() : this.renderCustom());
};
return TimeFilterMenu;
}(React.Component));
exports.TimeFilterMenu = TimeFilterMenu;
/***/ },
/***/ 350:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(351);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./time-filter-menu.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./time-filter-menu.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 351:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".time-filter-menu .cont .buttons button.selected,.time-filter-menu .cont .buttons button{display:inline-block;padding:6px 16px;font-size:13px;min-width:46px;text-align:center;cursor:pointer;border-radius:2px;outline:none;height:30px}.time-filter-menu .cont .buttons button.disabled,.time-filter-menu .cont .buttons button[disabled]{opacity:.60;cursor:default;pointer-events:none}.time-filter-menu .cont .buttons button.selected{background:#1ea3e6;color:#fff}.time-filter-menu .cont .buttons button.selected svg path{fill:#fff}.time-filter-menu .cont .buttons button.selected:hover{background:#1795d3}.time-filter-menu .cont .buttons button.active.selected,.time-filter-menu .cont .buttons button.selected:active{background:#1584bc;color:#e0e0e0}.time-filter-menu .cont .buttons button.active.selected svg path,.time-filter-menu .cont .buttons button.selected:active svg path{fill:#e0e0e0}.time-filter-menu .cont .buttons button{background:rgba(30,163,230,0.22);color:#1ea3e6}.time-filter-menu .cont .buttons button svg path{fill:#1ea3e6}.time-filter-menu .cont .buttons button:hover{background:rgba(30,163,230,0.3)}.time-filter-menu .cont .buttons button.active,.time-filter-menu .cont .buttons button:active{background:rgba(30,163,230,0.38)}.time-filter-menu .cont .preview{white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;height:30px;line-height:28px;background:#f2f2f2;border-radius:2px;color:#909090;text-align:center;padding-left:8px;padding-right:8px}.time-filter-menu .cont .type{text-transform:uppercase;font-size:12px;color:#a6a6a6;margin-bottom:5px}.time-filter-menu .cont{margin-top:18px}.time-filter-menu .cont .buttons{margin-bottom:14px}.time-filter-menu .cont .buttons button{min-width:0;padding:0;width:17.5%;margin-right:3%}.time-filter-menu .cont .buttons button.selected{min-width:0;padding:0}.time-filter-menu .cont .buttons button:last-child{margin-right:0}\n", ""]);
// exports
/***/ },
/***/ 355:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(356);
var React = __webpack_require__(5);
var chronoshift_1 = __webpack_require__(181);
var plywood_1 = __webpack_require__(190);
var time_1 = __webpack_require__(209);
var dom_1 = __webpack_require__(245);
var constants_1 = __webpack_require__(227);
var svg_icon_1 = __webpack_require__(176);
var date_range_input_1 = __webpack_require__(358);
var DateRangePicker = (function (_super) {
__extends(DateRangePicker, _super);
function DateRangePicker() {
_super.call(this);
this.state = {
activeMonthStartDate: null,
hoverTimeRange: null,
selectionSet: false
};
}
DateRangePicker.prototype.componentWillMount = function () {
var _a = this.props, startTime = _a.startTime, endTime = _a.endTime, timezone = _a.timezone;
if (!startTime)
return;
if (!time_1.datesEqual(startTime, chronoshift_1.day.floor(startTime, timezone)))
throw new Error("start time must be round");
if (endTime && !time_1.datesEqual(endTime, chronoshift_1.day.floor(endTime, timezone)))
throw new Error("end time must be round");
var flooredStart = chronoshift_1.month.floor(startTime, timezone);
this.setState({
activeMonthStartDate: flooredStart,
selectionSet: true
});
};
DateRangePicker.prototype.navigateToMonth = function (offset) {
var timezone = this.props.timezone;
var activeMonthStartDate = this.state.activeMonthStartDate;
var newDate = chronoshift_1.month.shift(activeMonthStartDate, timezone, offset);
this.setState({
activeMonthStartDate: newDate
});
};
DateRangePicker.prototype.goToPreviousMonth = function () {
return this.navigateToMonth(-1);
};
DateRangePicker.prototype.goToNextMonth = function () {
return this.navigateToMonth(1);
};
DateRangePicker.prototype.calculateHoverTimeRange = function (mouseEnteredDay) {
var _a = this.props, startTime = _a.startTime, endTime = _a.endTime;
var hoverTimeRange = null;
if (startTime && !endTime) {
var start = startTime;
var end = mouseEnteredDay;
// if mousing over backwards, set end to old start time
if (mouseEnteredDay < startTime) {
start = mouseEnteredDay;
end = startTime;
}
hoverTimeRange = new plywood_1.TimeRange({ start: start, end: end, bounds: '[]' });
}
this.setState({ hoverTimeRange: hoverTimeRange });
};
DateRangePicker.prototype.onCalendarMouseLeave = function () {
this.setState({ hoverTimeRange: null });
};
DateRangePicker.prototype.selectNewRange = function (startDate, endDate) {
var _a = this.props, onStartChange = _a.onStartChange, onEndChange = _a.onEndChange, timezone = _a.timezone;
onStartChange(startDate);
// real end points are exclusive so +1 full day to selection (which is floored) to get the real end point
if (endDate)
endDate = time_1.shiftOneDay(endDate, timezone);
onEndChange(endDate);
};
DateRangePicker.prototype.selectDay = function (selection) {
var startTime = this.props.startTime;
var selectionSet = this.state.selectionSet;
if (!startTime)
return;
if (selectionSet) {
this.setState({ hoverTimeRange: null, selectionSet: false });
this.selectNewRange(selection, null);
}
else {
var isDoubleClickSameDay = time_1.datesEqual(selection, startTime);
var isBackwardSelection = selection < startTime;
if (isDoubleClickSameDay) {
this.selectNewRange(startTime, startTime);
}
else if (isBackwardSelection) {
this.selectNewRange(selection, startTime);
}
else {
this.selectNewRange(startTime, selection);
}
this.setState({ selectionSet: true });
}
};
DateRangePicker.prototype.getIsSelectable = function (date) {
var _a = this.state, hoverTimeRange = _a.hoverTimeRange, selectionSet = _a.selectionSet;
var inHoverTimeRange = false;
if (hoverTimeRange) {
inHoverTimeRange = hoverTimeRange.contains(date);
}
return inHoverTimeRange && !selectionSet;
};
DateRangePicker.prototype.getIsSelectedEdgeEnd = function (isSingleDate, candidate) {
if (isSingleDate)
return false;
var _a = this.props, startTime = _a.startTime, endTime = _a.endTime, timezone = _a.timezone;
var candidateEndPoint = time_1.shiftOneDay(candidate, timezone);
return time_1.wallTimeInclusiveEndEqual(endTime, candidateEndPoint, timezone) && endTime > startTime;
};
DateRangePicker.prototype.renderDays = function (weeks, monthStart, isSingleDate) {
var _this = this;
var _a = this.props, startTime = _a.startTime, endTime = _a.endTime, maxTime = _a.maxTime, timezone = _a.timezone;
var nextMonthStart = chronoshift_1.month.shift(monthStart, timezone, 1);
return weeks.map(function (daysInWeek, row) {
return React.createElement("div", {className: "week", key: row}, " ", daysInWeek.map(function (dayDate, column) {
var isPast = dayDate < monthStart;
var isFuture = dayDate >= nextMonthStart;
var isBeyondMaxRange = dayDate > maxTime;
var isSelectedEdgeStart = time_1.datesEqual(dayDate, startTime);
var isSelectedEdgeEnd = _this.getIsSelectedEdgeEnd(isSingleDate, dayDate);
var className = dom_1.classNames("day", "value", {
past: isPast,
future: isFuture,
"beyond-max-range": isBeyondMaxRange,
"selectable": _this.getIsSelectable(dayDate),
"selected": startTime < dayDate && dayDate < endTime,
"selected-edge": isSelectedEdgeStart || isSelectedEdgeEnd
});
return React.createElement("div", {className: className, key: column, onClick: _this.selectDay.bind(_this, dayDate), onMouseEnter: _this.calculateHoverTimeRange.bind(_this, dayDate)}, time_1.getWallTimeDay(dayDate, timezone));
}));
});
};
;
DateRangePicker.prototype.renderCalendar = function (startDate, isSingleDate) {
var timezone = this.props.timezone;
var weeks = time_1.monthToWeeks(startDate, timezone, constants_1.getLocale());
var firstWeek = weeks[0];
var lastWeek = weeks[weeks.length - 1];
var countPrepend = 7 - firstWeek.length;
var countAppend = 7 - lastWeek.length;
weeks[0] = time_1.prependDays(timezone, firstWeek, countPrepend);
weeks[weeks.length - 1] = time_1.appendDays(timezone, lastWeek, countAppend);
return this.renderDays(weeks, startDate, isSingleDate);
};
DateRangePicker.prototype.renderCalendarNav = function (startDate) {
var timezone = this.props.timezone;
return React.createElement("div", {className: "calendar-nav"}, React.createElement("div", {className: 'caret left', onClick: this.goToPreviousMonth.bind(this)}, React.createElement(svg_icon_1.SvgIcon, {svg: __webpack_require__(361)})), time_1.getWallTimeMonthWithYear(startDate, timezone), React.createElement("div", {className: 'caret right', onClick: this.goToNextMonth.bind(this)}, React.createElement(svg_icon_1.SvgIcon, {svg: __webpack_require__(362)})));
};
DateRangePicker.prototype.render = function () {
var _a = this.props, startTime = _a.startTime, endTime = _a.endTime, timezone = _a.timezone, onStartChange = _a.onStartChange, onEndChange = _a.onEndChange;
var _b = this.state, activeMonthStartDate = _b.activeMonthStartDate, selectionSet = _b.selectionSet;
if (!activeMonthStartDate)
return null;
var isSingleDate = endTime ? time_1.getWallTimeDay(startTime, timezone) === time_1.getEndWallTimeInclusive(endTime, timezone).getDate() : true;
return React.createElement("div", {className: "date-range-picker"}, React.createElement("div", {className: "side-by-side"}, React.createElement(date_range_input_1.DateRangeInput, {type: "start", time: startTime, timezone: timezone, onChange: onStartChange.bind(this)}), React.createElement(date_range_input_1.DateRangeInput, {type: "end", time: endTime, timezone: timezone, onChange: onEndChange.bind(this), hide: !selectionSet})), React.createElement("div", {className: "calendar", onMouseLeave: this.onCalendarMouseLeave.bind(this)}, this.renderCalendarNav(activeMonthStartDate), React.createElement("div", {className: "week"}, constants_1.getLocale().shortDays.map(function (day, i) {
return React.createElement("div", {className: "day label", key: day + i}, React.createElement("span", {className: "space"}), day);
})), this.renderCalendar(activeMonthStartDate, isSingleDate)));
};
return DateRangePicker;
}(React.Component));
exports.DateRangePicker = DateRangePicker;
/***/ },
/***/ 356:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(357);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./date-range-picker.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./date-range-picker.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 357:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".date-range-picker .side-by-side{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.date-range-picker .side-by-side .date-range-input{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0}.date-range-picker .side-by-side :not(:last-child){margin-right:8px}.date-range-picker .calendar{padding-left:4px;padding-right:4px}.date-range-picker .calendar .calendar-nav{margin-top:18px;margin-bottom:12px;text-align:center;line-height:23px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.date-range-picker .calendar .calendar-nav .caret{position:absolute;top:0;padding:3px 3px;cursor:pointer}.date-range-picker .calendar .calendar-nav .caret svg{width:19px}.date-range-picker .calendar .calendar-nav .caret svg path{fill:#777}.date-range-picker .calendar .calendar-nav .caret:hover svg path{fill:#555}.date-range-picker .calendar .calendar-nav .caret.left{left:0}.date-range-picker .calendar .calendar-nav .caret.right{right:0}.date-range-picker .calendar .week{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%}.date-range-picker .calendar .week .day{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;text-align:center;height:26px;line-height:26px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.date-range-picker .calendar .week .day.label{color:#bbb;pointer-events:none}.date-range-picker .calendar .week .day.value.selectable,.date-range-picker .calendar .week .day.value.selected{background:rgba(30,163,230,0.26)}.date-range-picker .calendar .week .day.value.selectable.past:not(.selected-edge),.date-range-picker .calendar .week .day.value.selectable.future:not(.selected-edge),.date-range-picker .calendar .week .day.value.selected.past:not(.selected-edge),.date-range-picker .calendar .week .day.value.selected.future:not(.selected-edge){color:#87acbf}.date-range-picker .calendar .week .day.value:hover:not(.selectable):after{position:absolute;top:0;bottom:0;left:0;right:0;content:'';pointer-events:none;background:rgba(0,0,0,0.06)}.date-range-picker .calendar .week .day.value:hover:not(.selectable).beyond-max-range:after{background:rgba(0,0,0,0.1)}.date-range-picker .calendar .week .day.value.beyond-max-range:after{position:absolute;top:0;bottom:0;left:0;right:0;content:'';pointer-events:none;background:rgba(0,0,0,0.05)}.date-range-picker .calendar .week .day.value.past,.date-range-picker .calendar .week .day.value.future{color:#bbb}.date-range-picker .calendar .week .day.value.selected-edge{background:#1ea3e6;color:#fff}.date-range-picker .calendar .week .day span.space{color:transparent}\n", ""]);
// exports
/***/ },
/***/ 358:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(359);
var React = __webpack_require__(5);
var chronoshift_1 = __webpack_require__(181);
var time_1 = __webpack_require__(209);
var DateRangeInput = (function (_super) {
__extends(DateRangeInput, _super);
function DateRangeInput() {
_super.call(this);
this.state = {
dateString: ''
};
}
// 2015-09-23T17:42:57.636Z
// 2015-09-23 17:42
DateRangeInput.prototype.componentDidMount = function () {
var _a = this.props, time = _a.time, timezone = _a.timezone;
this.updateStateFromTime(time, timezone);
};
DateRangeInput.prototype.componentWillReceiveProps = function (nextProps) {
var time = nextProps.time, timezone = nextProps.timezone;
this.updateStateFromTime(time, timezone);
};
DateRangeInput.prototype.updateStateFromTime = function (time, timezone) {
if (!time)
return;
if (isNaN(time.valueOf())) {
this.setState({
dateString: ''
});
return;
}
var effectiveTime = this.props.type === "end" ? time_1.exclusiveToInclusiveEnd(time) : time;
this.setState({
dateString: time_1.getWallTimeString(effectiveTime, timezone)
});
};
DateRangeInput.prototype.dateChange = function (e) {
var dateString = e.target.value.replace(/[^\d-]/g, '').substr(0, 10);
this.setState({
dateString: dateString
});
if (dateString.length === 10) {
this.changeDate(dateString);
}
};
DateRangeInput.prototype.changeDate = function (possibleDateString) {
var _a = this.props, timezone = _a.timezone, onChange = _a.onChange, type = _a.type;
var possibleDate = new Date(possibleDateString);
// add one if end so it passes the inclusive formatting
var day = type === "end" ? possibleDate.getUTCDate() + 1 : possibleDate.getUTCDate();
if (isNaN(possibleDate.valueOf())) {
onChange(null);
}
else {
// Convert from WallTime to UTC
var possibleDate = chronoshift_1.WallTime.WallTimeToUTC(timezone.toString(), possibleDate.getUTCFullYear(), possibleDate.getUTCMonth(), day, possibleDate.getUTCHours(), possibleDate.getUTCMinutes(), possibleDate.getUTCSeconds(), possibleDate.getUTCMilliseconds());
onChange(possibleDate);
}
};
DateRangeInput.prototype.render = function () {
var hide = this.props.hide;
var dateString = this.state.dateString;
var value = hide ? '' : dateString;
return React.createElement("div", {className: "date-range-input"}, React.createElement("input", {className: "input-field", value: value, onChange: this.dateChange.bind(this)}));
};
return DateRangeInput;
}(React.Component));
exports.DateRangeInput = DateRangeInput;
/***/ },
/***/ 359:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(360);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./date-range-input.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./date-range-input.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 360:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".date-range-input .input-field{border:1px solid #d4d4d4;border-radius:2px;box-shadow:inset 0 1px 1px rgba(0,0,0,0.13);padding-left:6px;padding-right:6px;width:100%;height:30px}.date-range-input .input-field:hover{border-color:#b8b8b8}.date-range-input .input-field:focus{border-color:#1ea3e6}.date-range-input .error.input-field{border-color:#e24c4c}\n", ""]);
// exports
/***/ },
/***/ 361:
/***/ function(module, exports) {
module.exports = "<svg viewBox=\"0 0 19 19\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4,3 L14,9.5 L4,16\" transform=\"matrix(-1 0 0 1 18 0)\" fill=\"#000000\" fill-rule=\"evenodd\"/></svg>"
/***/ },
/***/ 362:
/***/ function(module, exports) {
module.exports = "<svg viewBox=\"0 0 19 19\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5,3 L15,9.5 L5,16\" fill=\"#000000\" fill-rule=\"evenodd\"/></svg>"
/***/ },
/***/ 363:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(364);
var React = __webpack_require__(5);
var plywood_1 = __webpack_require__(190);
var index_1 = __webpack_require__(194);
var constants_1 = __webpack_require__(227);
var dom_1 = __webpack_require__(245);
var button_1 = __webpack_require__(346);
var number_range_picker_1 = __webpack_require__(366);
function numberOrAnyToString(start) {
if (start === number_range_picker_1.ANY_VALUE)
return constants_1.STRINGS.any;
return '' + start;
}
function stringToNumberOrAny(startInput) {
var parse = parseFloat(startInput);
return isNaN(parse) ? number_range_picker_1.ANY_VALUE : parse;
}
var NumberFilterMenu = (function (_super) {
__extends(NumberFilterMenu, _super);
function NumberFilterMenu() {
_super.call(this);
this.state = {
leftOffset: null,
rightBound: null,
start: null,
startInput: "",
end: null,
endInput: ""
};
this.globalKeyDownListener = this.globalKeyDownListener.bind(this);
}
NumberFilterMenu.prototype.componentWillMount = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var valueSet = essence.filter.getLiteralSet(dimension.expression);
var hasRange = valueSet && valueSet.elements.length !== 0;
var start = null;
var end = null;
if (hasRange) {
var range = valueSet.elements[0];
start = range.start;
end = range.end;
}
this.setState({
startInput: numberOrAnyToString(start),
endInput: numberOrAnyToString(end),
start: start,
end: end
});
};
NumberFilterMenu.prototype.componentDidMount = function () {
window.addEventListener('keydown', this.globalKeyDownListener);
};
NumberFilterMenu.prototype.componentWillUnmount = function () {
window.removeEventListener('keydown', this.globalKeyDownListener);
};
NumberFilterMenu.prototype.constructFilter = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var _b = this.state, start = _b.start, end = _b.end;
var filter = essence.filter;
var validFilter = false;
if ((start !== null && end !== null)) {
validFilter = start <= end;
}
else {
validFilter = (!isNaN(start) && !(isNaN(end))) && (start !== null || end !== null);
}
if (validFilter) {
var bounds = start === end ? '[]' : '[)';
var newSet = plywood_1.Set.fromJS({ setType: "NUMBER_RANGE", elements: [plywood_1.NumberRange.fromJS({ start: start, end: end, bounds: bounds })] });
var clause = new index_1.FilterClause({
expression: dimension.expression,
selection: new plywood_1.LiteralExpression({ type: "SET/NUMBER_RANGE", value: newSet })
});
return filter.setClause(clause);
}
else {
return null;
}
};
NumberFilterMenu.prototype.globalKeyDownListener = function (e) {
if (dom_1.enterKey(e)) {
this.onOkClick();
}
};
NumberFilterMenu.prototype.onOkClick = function () {
if (!this.actionEnabled())
return;
var _a = this.props, clicker = _a.clicker, onClose = _a.onClose;
clicker.changeFilter(this.constructFilter());
onClose();
};
NumberFilterMenu.prototype.onCancelClick = function () {
var onClose = this.props.onClose;
onClose();
};
NumberFilterMenu.prototype.onRangeInputStartChange = function (e) {
var startInput = e.target.value;
this.setState({
startInput: startInput,
start: stringToNumberOrAny(startInput)
});
};
NumberFilterMenu.prototype.onRangeInputEndChange = function (e) {
var endInput = e.target.value;
this.setState({
endInput: endInput,
end: stringToNumberOrAny(endInput)
});
};
NumberFilterMenu.prototype.onRangeStartChange = function (newStart) {
this.setState({ startInput: numberOrAnyToString(newStart), start: newStart });
};
NumberFilterMenu.prototype.onRangeEndChange = function (newEnd) {
this.setState({ endInput: numberOrAnyToString(newEnd), end: newEnd });
};
NumberFilterMenu.prototype.actionEnabled = function () {
var essence = this.props.essence;
return !essence.filter.equals(this.constructFilter()) && Boolean(this.constructFilter());
};
NumberFilterMenu.prototype.render = function () {
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var _b = this.state, endInput = _b.endInput, startInput = _b.startInput, end = _b.end, start = _b.start;
return React.createElement("div", {className: "number-filter-menu", ref: "number-filter-menu"}, React.createElement("div", {className: "side-by-side"}, React.createElement("div", {className: "group"}, React.createElement("label", {className: "input-top-label"}, "Min"), React.createElement("input", {value: startInput, onChange: this.onRangeInputStartChange.bind(this)})), React.createElement("div", {className: "group"}, React.createElement("label", {className: "input-top-label"}, "Max"), React.createElement("input", {value: endInput, onChange: this.onRangeInputEndChange.bind(this)}))), React.createElement(number_range_picker_1.NumberRangePicker, {onRangeEndChange: this.onRangeEndChange.bind(this), onRangeStartChange: this.onRangeStartChange.bind(this), start: start, end: end, dimension: dimension, essence: essence}), React.createElement("div", {className: "button-bar"}, React.createElement(button_1.Button, {type: "primary", title: constants_1.STRINGS.ok, onClick: this.onOkClick.bind(this), disabled: !this.actionEnabled()}), React.createElement(button_1.Button, {type: "secondary", title: constants_1.STRINGS.cancel, onClick: this.onCancelClick.bind(this)})));
};
return NumberFilterMenu;
}(React.Component));
exports.NumberFilterMenu = NumberFilterMenu;
/***/ },
/***/ 364:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(365);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./number-filter-menu.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./number-filter-menu.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 365:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".number-filter-menu .side-by-side{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.number-filter-menu .side-by-side>*{margin-right:5px}.number-filter-menu .side-by-side>*:last-child{margin-right:0}.number-filter-menu .input-top-label{text-transform:uppercase;font-size:12px;color:#a6a6a6;margin-bottom:5px}.number-filter-menu .side-by-side{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.number-filter-menu .side-by-side>input{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0}.number-filter-menu .side-by-side :not(:last-child){margin-right:8px}.number-filter-menu input{border:1px solid #d4d4d4;border-radius:2px;box-shadow:inset 0 1px 1px rgba(0,0,0,0.13);padding-left:6px;padding-right:6px;width:100%;height:30px}.number-filter-menu input:hover{border-color:#b8b8b8}.number-filter-menu input:focus{border-color:#1ea3e6}.number-filter-menu input.error{border-color:#e24c4c}.number-filter-menu .group{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.number-filter-menu input{margin-top:6px}.number-filter-menu input.gray{color:#ccc}\n", ""]);
// exports
/***/ },
/***/ 366:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(367);
var React = __webpack_require__(5);
var ReactDOM = __webpack_require__(42);
var plywood_1 = __webpack_require__(190);
var general_1 = __webpack_require__(199);
var dom_1 = __webpack_require__(245);
var loader_1 = __webpack_require__(173);
var query_error_1 = __webpack_require__(343);
var range_handle_1 = __webpack_require__(369);
exports.ANY_VALUE = null;
var NUB_SIZE = 16;
var GRANULARITY_IN_BAR = 300; // this is how many steps we want to represent in the slider bar
function addNubSize(value) {
return value + NUB_SIZE;
}
function subtractNubSize(value) {
return value && value > NUB_SIZE ? value - NUB_SIZE : 0;
}
function getNumberOfDigitsToShow(n) {
var totalDigits = general_1.getNumberOfWholeDigits(n / GRANULARITY_IN_BAR);
return totalDigits > 3 ? Math.min(totalDigits, 4) : 3;
}
// offset the bar a little because a rectangle at the same position as a circle will peek through
function getAdjustedStartHalf(start) {
return start + NUB_SIZE / 2;
}
var NumberRangePicker = (function (_super) {
__extends(NumberRangePicker, _super);
function NumberRangePicker() {
_super.call(this);
this.state = {
min: null,
max: null,
step: null,
loading: false,
error: null
};
}
NumberRangePicker.prototype.fetchData = function (essence, dimension, rightBound) {
var _this = this;
var dataSource = essence.dataSource;
var filterExpression = essence.getEffectiveFilter(null, dimension).toExpression();
var $main = plywood_1.$('main');
var query = plywood_1.ply()
.apply('main', $main.filter(filterExpression))
.apply('Min', $main.min(plywood_1.$(dimension.name)))
.apply('Max', $main.max(plywood_1.$(dimension.name)));
this.setState({
loading: true
});
dataSource.executor(query)
.then(function (dataset) {
if (!_this.mounted)
return;
var min = dataset.data[0]['Min'];
var max = dataset.data[0]['Max'];
var step = max && min && isFinite(max) && isFinite(min) ? (max - min) / rightBound : 1;
_this.setState({
min: min,
max: max,
loading: false,
step: step !== 0 && isFinite(step) ? step : 1
});
}, function (error) {
if (!_this.mounted)
return;
_this.setState({
loading: false,
error: error
});
});
};
NumberRangePicker.prototype.componentDidMount = function () {
this.mounted = true;
var node = ReactDOM.findDOMNode(this.refs['number-range-picker']);
var rect = node.getBoundingClientRect();
var _a = this.props, essence = _a.essence, dimension = _a.dimension;
var leftOffset = rect.left;
var rightBound = rect.width;
this.setState({ leftOffset: leftOffset, rightBound: rightBound });
this.fetchData(essence, dimension, rightBound);
};
NumberRangePicker.prototype.componentWillUnmount = function () {
this.mounted = false;
};
NumberRangePicker.prototype.relativePositionToValue = function (position, type) {
var _a = this.state, step = _a.step, min = _a.min, max = _a.max, rightBound = _a.rightBound;
if (position <= addNubSize(0) && type === 'start')
return exports.ANY_VALUE;
if (position >= rightBound && type === 'end')
return exports.ANY_VALUE;
var range = max - min !== 0 ? max - min : Math.abs(max);
return general_1.toSignificantDigits(position * step, getNumberOfDigitsToShow(range));
};
NumberRangePicker.prototype.valueToRelativePosition = function (value) {
var step = this.state.step;
return value / step;
};
NumberRangePicker.prototype.onBarClick = function (positionStart, positionEnd, e) {
var leftOffset = this.state.leftOffset;
var clickPadding = 5;
var absoluteX = dom_1.getXFromEvent(e);
var relativeX = absoluteX - leftOffset;
if (relativeX < NUB_SIZE / 2)
return this.updateStart(leftOffset);
var startNubPosition = addNubSize(positionStart) + clickPadding;
var endNubPosition = subtractNubSize(positionEnd) + clickPadding;
var isBeforeStart = relativeX < positionStart;
var isAfterEnd = relativeX > positionEnd + NUB_SIZE;
var inBetween = (relativeX < positionEnd) && relativeX > startNubPosition;
if (isBeforeStart) {
this.updateStart(absoluteX - NUB_SIZE);
}
else if (isAfterEnd) {
this.updateEnd(absoluteX);
}
else if (inBetween) {
var distanceFromEnd = endNubPosition - relativeX;
var distanceFromStart = relativeX - startNubPosition;
if (distanceFromEnd < distanceFromStart) {
this.updateEnd(endNubPosition + leftOffset - distanceFromEnd);
}
else {
this.updateStart(startNubPosition + leftOffset + distanceFromStart - NUB_SIZE);
}
return;
}
};
NumberRangePicker.prototype.updateStart = function (absolutePosition) {
var onRangeStartChange = this.props.onRangeStartChange;
var leftOffset = this.state.leftOffset;
var relativePosition = absolutePosition - leftOffset;
var newValue = this.relativePositionToValue(addNubSize(relativePosition), 'start');
onRangeStartChange(newValue);
};
NumberRangePicker.prototype.updateEnd = function (absolutePosition) {
var onRangeEndChange = this.props.onRangeEndChange;
var leftOffset = this.state.leftOffset;
var relativePosition = absolutePosition - leftOffset;
var newValue = this.relativePositionToValue(relativePosition, 'end');
onRangeEndChange(newValue);
};
NumberRangePicker.prototype.render = function () {
var _a = this.props, start = _a.start, end = _a.end;
var _b = this.state, min = _b.min, max = _b.max, loading = _b.loading, error = _b.error, step = _b.step, rightBound = _b.rightBound, leftOffset = _b.leftOffset;
var content = null;
if (rightBound && step && isFinite(max) && isFinite(min)) {
var relativeStart = start === exports.ANY_VALUE ? 0 : subtractNubSize(this.valueToRelativePosition(start));
var relativeEnd = end === exports.ANY_VALUE ? rightBound : this.valueToRelativePosition(end);
var adjustedRightBound = subtractNubSize(rightBound);
var positionEnd = dom_1.clamp(relativeEnd, addNubSize(relativeStart), adjustedRightBound);
var positionStart = start ? dom_1.clamp(relativeStart, 0, subtractNubSize(positionEnd)) : 0;
var rangeBarSelected = { left: getAdjustedStartHalf(positionStart), width: positionEnd - positionStart };
var absoluteRightBound = leftOffset + rightBound;
content = React.createElement("div", {className: "range-slider", onMouseDown: this.onBarClick.bind(this, positionStart, positionEnd)}, React.createElement("div", {className: "range-bar full"}), React.createElement("div", {className: "range-bar selected", style: rangeBarSelected}), React.createElement(range_handle_1.RangeHandle, {positionLeft: positionStart, onChange: this.updateStart.bind(this), isAny: start === exports.ANY_VALUE, isBeyondMin: start !== exports.ANY_VALUE && start < min, leftBound: leftOffset, rightBound: leftOffset + subtractNubSize(positionEnd), offset: leftOffset}), React.createElement(range_handle_1.RangeHandle, {positionLeft: positionEnd, onChange: this.updateEnd.bind(this), isAny: end === exports.ANY_VALUE, isBeyondMax: end !== exports.ANY_VALUE && max < end, leftBound: leftOffset + addNubSize(positionStart), rightBound: absoluteRightBound, offset: leftOffset}));
}
return React.createElement("div", {className: "number-range-picker", ref: "number-range-picker"}, content, loading ? React.createElement(loader_1.Loader, null) : null, error ? React.createElement(query_error_1.QueryError, {error: error}) : null);
};
return NumberRangePicker;
}(React.Component));
exports.NumberRangePicker = NumberRangePicker;
/***/ },
/***/ 367:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(368);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./number-range-picker.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./number-range-picker.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 368:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".number-range-picker{margin:10px 0;height:25px}.number-range-picker .range-bar{position:absolute;top:6px;height:6px}.number-range-picker .range-bar.full{background-color:#dedede;left:8px;right:8px}.number-range-picker .range-bar.selected{background-color:#1ea3e6}.number-range-picker .range-handle{position:absolute}.number-range-picker .loader,.number-range-picker .query-error{position:absolute;top:0;bottom:0;left:0;right:0}\n", ""]);
// exports
/***/ },
/***/ 369:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(370);
var React = __webpack_require__(5);
var dom_1 = __webpack_require__(245);
var RangeHandle = (function (_super) {
__extends(RangeHandle, _super);
function RangeHandle() {
_super.call(this);
this.state = {
anchor: null
};
this.onGlobalMouseUp = this.onGlobalMouseUp.bind(this);
this.onGlobalMouseMove = this.onGlobalMouseMove.bind(this);
}
RangeHandle.prototype.onGlobalMouseMove = function (event) {
var _a = this.props, onChange = _a.onChange, leftBound = _a.leftBound, rightBound = _a.rightBound;
var anchor = this.state.anchor;
var newX = dom_1.getXFromEvent(event) - anchor;
onChange(dom_1.clamp(newX, leftBound, rightBound));
};
RangeHandle.prototype.onMouseDown = function (event) {
var _a = this.props, offset = _a.offset, positionLeft = _a.positionLeft;
var x = dom_1.getXFromEvent(event);
var anchor = x - offset - positionLeft;
this.setState({
anchor: anchor
});
event.preventDefault();
window.addEventListener('mouseup', this.onGlobalMouseUp);
window.addEventListener('mousemove', this.onGlobalMouseMove);
};
RangeHandle.prototype.onGlobalMouseUp = function () {
window.removeEventListener('mouseup', this.onGlobalMouseUp);
window.removeEventListener('mousemove', this.onGlobalMouseMove);
};
RangeHandle.prototype.render = function () {
var _a = this.props, positionLeft = _a.positionLeft, isAny = _a.isAny, isBeyondMin = _a.isBeyondMin, isBeyondMax = _a.isBeyondMax;
var style = { left: positionLeft };
return React.createElement("div", {className: dom_1.classNames("range-handle", { empty: isAny, "beyond min": isBeyondMin, "beyond max": isBeyondMax }), style: style, onMouseDown: this.onMouseDown.bind(this)});
};
return RangeHandle;
}(React.Component));
exports.RangeHandle = RangeHandle;
/***/ },
/***/ 370:
/***/ function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(371);
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(4)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!./../../../../node_modules/css-loader/index.js!./range-handle.css", function() {
var newContent = require("!!./../../../../node_modules/css-loader/index.js!./range-handle.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
/***/ },
/***/ 371:
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, ".range-handle{width:16px;height:16px;background:#1ea3e6;border-radius:50%;border:2px solid #1ea3e6;z-index:2}.range-handle.empty{background:#fff}.range-handle.beyond::before{border-style:solid;border-color:#ededed;border-width:2.5px 2.5px 0 0;content:'';display:inline-block;height:4px;position:relative;top:2.5px;vertical-align:top;width:4px}.range-handle.beyond.min::before{top:3px;left:4px;-webkit-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.range-handle.beyond.max::before{left:2px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}\n", ""]);
// exports
/***/ }
});