Files
redash/client/app/components/parameters.js
Gabriel Dutra f0576a3623 Support multi-select in parameters (#3952)
* Allow multiple values for enum parameter

* Allow multi-select for Query dropdown parameters

* CR + make sure list values are allowed

* Add prefix, suffix and separator

* Rename multipleValues and cast options as strings

* Replicate serialization logic on frontend

* Add Quote Option Select

* Make sure it's enum or query before join

* Add a couple of tests

* Add help to quote option

* Add min-width and normalize empty array

* Improve behavior when changing parameter settings
- Set parameter value again to pass through checks
- Add setValue check for multi values

* Validate enum values on setValue + CodeClimate

* Ran wording suggestions

* Updates after Apply Changes

* Fix failing Cypress tests

* Make sure enumOptions exists before split

* Improve propTypes for QueyBasedParameterInput

Co-Authored-By: Ran Byron <ranbena@gmail.com>

* CR

* Cypress: Test for multi-select Enum

* Fix multi-selection Cypress spec

* Update Refresh Schedule
2019-08-04 15:47:30 +03:00

99 lines
2.7 KiB
JavaScript

import { extend, filter, forEach, size } from 'lodash';
import template from './parameters.html';
import EditParameterSettingsDialog from './EditParameterSettingsDialog';
function ParametersDirective($location, KeyboardShortcuts) {
return {
restrict: 'E',
transclude: true,
scope: {
parameters: '=',
syncValues: '=?',
editable: '=?',
changed: '&onChange',
onUpdated: '=',
onValuesChange: '=',
applyOnKeyboardShortcut: '<?',
},
template,
link(scope, $element) {
const el = $element.get(0);
const shortcuts = {
'mod+enter': () => scope.onApply(),
'alt+enter': () => scope.onApply(),
};
const onFocus = () => { KeyboardShortcuts.bind(shortcuts); };
const onBlur = () => { KeyboardShortcuts.unbind(shortcuts); };
el.addEventListener('focus', onFocus, true);
el.addEventListener('blur', onBlur, true);
scope.$on('$destroy', () => {
KeyboardShortcuts.unbind(shortcuts);
el.removeEventListener('focus', onFocus);
el.removeEventListener('blur', onBlur);
});
// is this the correct location for this logic?
if (scope.syncValues !== false) {
scope.$watch(
'parameters',
() => {
if (scope.changed) {
scope.changed({});
}
const params = extend({}, $location.search());
scope.parameters.forEach((param) => {
extend(params, param.toUrlParams());
});
Object.keys(params).forEach(key => params[key] == null && delete params[key]);
$location.search(params);
},
true,
);
}
scope.showParameterSettings = (parameter, index) => {
EditParameterSettingsDialog
.showModal({ parameter })
.result.then((updated) => {
scope.parameters[index] = extend(parameter, updated).setValue(updated.value);
scope.onUpdated();
});
};
scope.dirtyParamCount = 0;
scope.$watch(
'parameters',
() => {
scope.dirtyParamCount = size(filter(scope.parameters, 'hasPendingValue'));
},
true,
);
scope.isApplying = false;
scope.applyChanges = () => {
scope.isApplying = true;
forEach(scope.parameters, p => p.applyPendingValue());
scope.isApplying = false;
};
scope.onApply = () => {
if (!scope.dirtyParamCount) {
return false; // so keyboard shortcut doesn't run needlessly
}
scope.$apply(scope.applyChanges);
scope.onValuesChange();
};
},
};
}
export default function init(ngModule) {
ngModule.directive('parameters', ParametersDirective);
}
init.init = true;