Commit 6a95df40 by Torkel Ödegaard

refacoring: more work on metric segment replacement

parent 380e7e7f
<input type="text"
data-provide="typeahead"
class="gf-form-input"
spellcheck="false"
style="display:none"></input>
<a class="gf-form-label"
ng-class="ctrl.cssClass"
tabindex="1"
ng-click="ctrl.open()"
give-focus="ctrl.focus"
ng-bind-html="ctrl.display"></a>
...@@ -15,15 +15,17 @@ function typeaheadMatcher(item) { ...@@ -15,15 +15,17 @@ function typeaheadMatcher(item) {
export class FormDropdownCtrl { export class FormDropdownCtrl {
inputElement: any; inputElement: any;
linkElement: any; linkElement: any;
value: any; model: any;
text: any;
display: any; display: any;
text: any;
options: any; options: any;
cssClass: any; cssClass: any;
allowCustom: any; allowCustom: any;
linkMode: boolean; linkMode: boolean;
cancelBlur: any; cancelBlur: any;
onChange: any; onChange: any;
getOptions: any;
optionCache: any;
constructor(private $scope, $element, private $sce, private templateSrv) { constructor(private $scope, $element, private $sce, private templateSrv) {
this.inputElement = $element.find('input').first(); this.inputElement = $element.find('input').first();
...@@ -31,11 +33,15 @@ export class FormDropdownCtrl { ...@@ -31,11 +33,15 @@ export class FormDropdownCtrl {
this.linkMode = true; this.linkMode = true;
this.cancelBlur = null; this.cancelBlur = null;
if (this.options) { if (!this.getOptions) {
var item = _.find(this.options, {value: this.value}); this.getOptions = () => {
this.updateDisplay(item ? item.text : this.value); return Promise.resolve(this.options);
};
} }
// listen to model changes
$scope.$watch("ctrl.model", this.modelChanged.bind(this));
this.inputElement.attr('data-provide', 'typeahead'); this.inputElement.attr('data-provide', 'typeahead');
this.inputElement.typeahead({ this.inputElement.typeahead({
source: this.typeaheadSource.bind(this), source: this.typeaheadSource.bind(this),
...@@ -64,19 +70,40 @@ export class FormDropdownCtrl { ...@@ -64,19 +70,40 @@ export class FormDropdownCtrl {
this.inputElement.blur(this.inputBlur.bind(this)); this.inputElement.blur(this.inputBlur.bind(this));
} }
modelChanged(newVal) {
if (_.isObject(this.model)) {
this.updateDisplay(this.model.text);
} else {
// if we have text use it
if (this.text) {
this.updateDisplay(this.text);
} else {
// otherwise we need to do initial lookup, usually happens first time
this.getOptions().then(options => {
var item = _.find(options, {value: this.model});
this.updateDisplay(item ? item.text : this.model);
});
}
}
}
typeaheadSource(query, callback) { typeaheadSource(query, callback) {
if (this.options) { this.getOptions({$query: query}).then(options => {
var typeaheadOptions = _.map(this.options, 'text'); this.optionCache = options;
// extract texts
let optionTexts = _.map(options, 'text');
// add current custom value // add custom values
if (this.allowCustom) { if (this.allowCustom) {
if (_.indexOf(typeaheadOptions, this.text) === -1) { if (_.indexOf(optionTexts, this.text) === -1) {
typeaheadOptions.unshift(this.text); options.unshift(this.text);
} }
} }
callback(typeaheadOptions); callback(optionTexts);
} });
} }
typeaheadUpdater(text) { typeaheadUpdater(text) {
...@@ -114,21 +141,29 @@ export class FormDropdownCtrl { ...@@ -114,21 +141,29 @@ export class FormDropdownCtrl {
} }
this.$scope.$apply(() => { this.$scope.$apply(() => {
var option = _.find(this.options, {text: text}); var option = _.find(this.optionCache, {text: text});
if (option) { if (option) {
this.value = option.value; if (_.isObject(this.model)) {
this.updateDisplay(option.text); this.model = option;
} else {
this.model = option.value;
}
this.text = option.text;
} else if (this.allowCustom) { } else if (this.allowCustom) {
this.value = text; if (_.isObject(this.model)) {
this.updateDisplay(text); this.model.text = this.model.value = text;
} else {
this.model = text;
}
this.text = text;
} }
// needs to call this after digest so // needs to call this after digest so
// property is synced with outerscope // property is synced with outerscope
this.$scope.$$postDigest(() => { this.$scope.$$postDigest(() => {
this.$scope.$apply(() => { this.$scope.$apply(() => {
this.onChange(); this.onChange({$option: option});
}); });
}); });
...@@ -157,17 +192,30 @@ export class FormDropdownCtrl { ...@@ -157,17 +192,30 @@ export class FormDropdownCtrl {
} }
} }
const template = `
<input type="text"
data-provide="typeahead"
class="gf-form-input"
spellcheck="false"
style="display:none"></input>
<a class="gf-form-label"
ng-class="ctrl.cssClass"
tabindex="1"
ng-click="ctrl.open()"
give-focus="ctrl.focus"
ng-bind-html="ctrl.display"></a>
`;
export function formDropdownDirective() { export function formDropdownDirective() {
return { return {
restrict: 'E', restrict: 'E',
templateUrl: 'public/app/core/components/form_dropdown/form_dropdown.html', template: template,
controller: FormDropdownCtrl, controller: FormDropdownCtrl,
bindToController: true, bindToController: true,
controllerAs: 'ctrl', controllerAs: 'ctrl',
scope: { scope: {
value: "=", model: "=",
options: "=", options: "=",
getOptions: "&", getOptions: "&",
onChange: "&", onChange: "&",
......
...@@ -35,7 +35,7 @@ function ($, angular, coreModule) { ...@@ -35,7 +35,7 @@ function ($, angular, coreModule) {
options.html = editViewMap[options.editview].html; options.html = editViewMap[options.editview].html;
} }
if (lastEditView === options.editview) { if (lastEditView && lastEditView === options.editview) {
hideEditorPane(false); hideEditorPane(false);
return; return;
} }
......
...@@ -143,6 +143,7 @@ function (_, $, coreModule) { ...@@ -143,6 +143,7 @@ function (_, $, coreModule) {
$input.focus(); $input.focus();
linkMode = false; linkMode = false;
var typeahead = $input.data('typeahead'); var typeahead = $input.data('typeahead');
if (typeahead) { if (typeahead) {
$input.val(''); $input.val('');
...@@ -151,6 +152,7 @@ function (_, $, coreModule) { ...@@ -151,6 +152,7 @@ function (_, $, coreModule) {
}); });
$input.blur($scope.inputBlur); $input.blur($scope.inputBlur);
$compile(elem.contents())($scope); $compile(elem.contents())($scope);
} }
}; };
......
...@@ -5,8 +5,6 @@ import _ from 'lodash'; ...@@ -5,8 +5,6 @@ import _ from 'lodash';
import {DashboardModel} from '../dashboard/model'; import {DashboardModel} from '../dashboard/model';
export class MetricsTabCtrl { export class MetricsTabCtrl {
dsSegment: any;
mixedDsSegment: any;
dsName: string; dsName: string;
panel: any; panel: any;
panelCtrl: any; panelCtrl: any;
...@@ -14,30 +12,26 @@ export class MetricsTabCtrl { ...@@ -14,30 +12,26 @@ export class MetricsTabCtrl {
current: any; current: any;
nextRefId: string; nextRefId: string;
dashboard: DashboardModel; dashboard: DashboardModel;
panelDsValue: any;
addQueryDropdown: any;
/** @ngInject */ /** @ngInject */
constructor($scope, private uiSegmentSrv, datasourceSrv) { constructor($scope, private uiSegmentSrv, private datasourceSrv) {
this.panelCtrl = $scope.ctrl; this.panelCtrl = $scope.ctrl;
$scope.ctrl = this; $scope.ctrl = this;
this.panel = this.panelCtrl.panel; this.panel = this.panelCtrl.panel;
this.dashboard = this.panelCtrl.dashboard; this.dashboard = this.panelCtrl.dashboard;
this.datasources = datasourceSrv.getMetricSources(); this.datasources = datasourceSrv.getMetricSources();
this.panelDsValue = this.panelCtrl.panel.datasource || null;
var dsValue = this.panelCtrl.panel.datasource || null;
for (let ds of this.datasources) { for (let ds of this.datasources) {
if (ds.value === dsValue) { if (ds.value === this.panelDsValue) {
this.current = ds; this.current = ds;
} }
} }
if (!this.current) { this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
this.current = {name: dsValue + ' not found', value: null};
}
this.dsSegment = uiSegmentSrv.newSegment({value: this.current.name, selectMode: true});
this.mixedDsSegment = uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true, fake: true});
// update next ref id // update next ref id
this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel); this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
...@@ -46,33 +40,28 @@ export class MetricsTabCtrl { ...@@ -46,33 +40,28 @@ export class MetricsTabCtrl {
getOptions(includeBuiltin) { getOptions(includeBuiltin) {
return Promise.resolve(this.datasources.filter(value => { return Promise.resolve(this.datasources.filter(value => {
return includeBuiltin || !value.meta.builtIn; return includeBuiltin || !value.meta.builtIn;
}).map(value => { }).map(ds => {
return this.uiSegmentSrv.newSegment(value.name); return {value: ds.value, text: ds.name, datasource: ds};
})); }));
} }
datasourceChanged() { datasourceChanged(option) {
var ds = _.find(this.datasources, {name: this.dsSegment.value}); if (!option) {
if (ds) { return;
this.current = ds;
this.panelCtrl.setDatasource(ds);
}
} }
mixedDatasourceChanged() { this.current = option.datasource;
var target: any = {isNew: true}; this.panelCtrl.setDatasource(option.datasource);
var ds = _.find(this.datasources, {name: this.mixedDsSegment.value}); }
if (ds) { addMixedQuery(option) {
target.datasource = ds.name; if (!option) {
this.panelCtrl.addQuery(target); return;
} }
// metric segments are really bad, requires hacks to update var target: any = {isNew: true};
const segment = this.uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true, fake: true}); this.panelCtrl.addQuery({isNew: true, datasource: option.datasource.name});
this.mixedDsSegment.value = segment.value; this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
this.mixedDsSegment.html = segment.html;
this.mixedDsSegment.text = segment.text;
} }
addQuery() { addQuery() {
......
...@@ -19,7 +19,10 @@ ...@@ -19,7 +19,10 @@
</button> </button>
<div class="dropdown" ng-if="ctrl.current.meta.mixed"> <div class="dropdown" ng-if="ctrl.current.meta.mixed">
<metric-segment segment="ctrl.mixedDsSegment" get-options="ctrl.getOptions(false)" on-change="ctrl.mixedDatasourceChanged()"></metric-segment> <gf-form-dropdown model="ctrl.addQueryDropdown"
get-options="ctrl.getOptions(false)"
on-change="ctrl.addMixedQuery($option)">
</gf-form-dropdown>
</div> </div>
</div> </div>
</div> </div>
...@@ -30,10 +33,12 @@ ...@@ -30,10 +33,12 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form"> <div class="gf-form">
<label class="gf-form-label"> <label class="gf-form-label">Panel Data Source</label>
Panel Data Source <gf-form-dropdown model="ctrl.panelDsValue"
</label> get-options="ctrl.getOptions(true)"
<metric-segment segment="ctrl.dsSegment" get-options="ctrl.getOptions(true)" on-change="ctrl.datasourceChanged()"></metric-segment> on-change="ctrl.datasourceChanged($option)"
css-class="width-10">
</gf-form-dropdown>
</div> </div>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment