This commit is contained in:
Родитель
03dfb6e3a9
Коммит
feb1757441
|
@ -1,6 +1,6 @@
|
|||
import Q = require("q");
|
||||
import * as WitService from "TFS/WorkItemTracking/Services";
|
||||
import * as VSSUtilsCore from "VSS/Utils/Core";
|
||||
import Q = require("q");
|
||||
|
||||
export class BaseMultiValueControl {
|
||||
/**
|
||||
|
@ -31,22 +31,22 @@ export class BaseMultiValueControl {
|
|||
*/
|
||||
private _windowWidth: number;
|
||||
private _minWindowWidthDelta: number = 10; // Minum change in window width to react to
|
||||
private _windowResizeThrottleDelegate: Function;
|
||||
private _windowResizeThrottleDelegate: () => void;
|
||||
|
||||
constructor() {
|
||||
let initialConfig = VSS.getConfiguration();
|
||||
const initialConfig = VSS.getConfiguration();
|
||||
this._showFieldBorder = !!initialConfig.fieldBorder;
|
||||
|
||||
this.containerElement = $(".container");
|
||||
if (this._showFieldBorder) {
|
||||
this.containerElement.addClass("fieldBorder")
|
||||
this.containerElement.addClass("fieldBorder");
|
||||
}
|
||||
|
||||
this._errorPane = $("<div>").addClass("errorPane").appendTo(this.containerElement);
|
||||
|
||||
var inputs: IDictionaryStringTo<string> = initialConfig.witInputs;
|
||||
const inputs: IDictionaryStringTo<string> = initialConfig.witInputs;
|
||||
|
||||
this.fieldName = inputs["FieldName"];
|
||||
this.fieldName = inputs.FieldName;
|
||||
if (!this.fieldName) {
|
||||
this.showError("FieldName input has not been specified");
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ export class BaseMultiValueControl {
|
|||
this._getCurrentFieldValue().then(
|
||||
(value: string) => {
|
||||
this.setValue(value);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ export class BaseMultiValueControl {
|
|||
}
|
||||
|
||||
public clear(): void {
|
||||
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,9 +104,9 @@ export class BaseMultiValueControl {
|
|||
() => {
|
||||
this._flushing = false;
|
||||
this.showError("Error storing the field value");
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ export class BaseMultiValueControl {
|
|||
}
|
||||
|
||||
protected setValue(value: string): void {
|
||||
|
||||
// noop
|
||||
}
|
||||
|
||||
protected showError(error: string): void {
|
||||
|
@ -129,7 +129,7 @@ export class BaseMultiValueControl {
|
|||
}
|
||||
|
||||
private _getCurrentFieldValue(): IPromise<string> {
|
||||
var defer = Q.defer<string>();
|
||||
const defer = Q.defer<string>();
|
||||
WitService.WorkItemFormService.getService().then(
|
||||
(service) => {
|
||||
service.getFieldValues([this.fieldName]).then(
|
||||
|
@ -137,19 +137,19 @@ export class BaseMultiValueControl {
|
|||
defer.resolve(values[this.fieldName] as string);
|
||||
},
|
||||
() => {
|
||||
this.showError("Error loading values for field: " + this.fieldName)
|
||||
}
|
||||
)
|
||||
}
|
||||
this.showError("Error loading values for field: " + this.fieldName);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
protected resize() {
|
||||
this._bodyElement = <HTMLBodyElement>document.getElementsByTagName("body").item(0);
|
||||
this._bodyElement = document.getElementsByTagName("body").item(0) as HTMLBodyElement;
|
||||
|
||||
// Cast as any until declarations are updated
|
||||
VSS.resize(null, this._bodyElement.offsetHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import Q = require("q");
|
||||
import * as WitService from "TFS/WorkItemTracking/Services";
|
||||
import * as Utils_Array from "VSS/Utils/Array";
|
||||
import * as Utils_String from "VSS/Utils/String";
|
||||
import Q = require("q");
|
||||
import * as VSSUtilsCore from "VSS/Utils/Core";
|
||||
import * as Utils_String from "VSS/Utils/String";
|
||||
import {BaseMultiValueControl} from "./BaseMultiValueControl";
|
||||
|
||||
export class MultiValueCombo extends BaseMultiValueControl {
|
||||
/*
|
||||
/*
|
||||
* UI elements for the control.
|
||||
*/
|
||||
private _selectedValuesWrapper: JQuery;
|
||||
|
@ -22,7 +22,7 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
private _chevronDownClass = "bowtie-chevron-down-light";
|
||||
private _chevronUpClass = "bowtie-chevron-up-light";
|
||||
|
||||
private _toggleThrottleDelegate: Function;
|
||||
private _toggleThrottleDelegate: () => void;
|
||||
/**
|
||||
* Initialize a new instance of MultiValueControl
|
||||
*/
|
||||
|
@ -37,12 +37,13 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
|
||||
this._getSuggestedValues().then(
|
||||
(values: string[]) => {
|
||||
this._suggestedValues = values.filter((s:string):boolean => {
|
||||
return s.trim()!==''});
|
||||
|
||||
this._suggestedValues = values.filter((s: string): boolean => {
|
||||
return s.trim() !== "";
|
||||
});
|
||||
|
||||
this._populateCheckBoxes();
|
||||
super.initialize();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
this._toggleThrottleDelegate = VSSUtilsCore.throttledDelegate(this, 100, () => {
|
||||
|
@ -70,9 +71,9 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
});
|
||||
|
||||
$(window).keydown((eventObject) => {
|
||||
if(eventObject.keyCode == 38 /* Up */) {
|
||||
let focusedCheckBox = $("input:focus", this._checkboxValuesContainer);
|
||||
if(focusedCheckBox.length <= 0) {
|
||||
if (eventObject.keyCode === 38 /* Up */) {
|
||||
const focusedCheckBox = $("input:focus", this._checkboxValuesContainer);
|
||||
if (focusedCheckBox.length <= 0) {
|
||||
// None selected, choose last
|
||||
$("input:last", this._checkboxValuesContainer).focus();
|
||||
} else {
|
||||
|
@ -81,10 +82,9 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(eventObject.keyCode == 40 /* Down */) {
|
||||
let focusedCheckBox = $("input:focus", this._checkboxValuesContainer);
|
||||
if(focusedCheckBox.length <= 0) {
|
||||
} else if (eventObject.keyCode === 40 /* Down */) {
|
||||
const focusedCheckBox = $("input:focus", this._checkboxValuesContainer);
|
||||
if (focusedCheckBox.length <= 0) {
|
||||
// None selected, choose first
|
||||
$("input:first", this._checkboxValuesContainer).focus();
|
||||
} else {
|
||||
|
@ -93,24 +93,23 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
var checkboxes: JQuery = $("input", this._checkboxValuesContainer);
|
||||
var labels: JQuery = $(".checkboxLabel", this._checkboxValuesContainer);
|
||||
const checkboxes: JQuery = $("input", this._checkboxValuesContainer);
|
||||
const labels: JQuery = $(".checkboxLabel", this._checkboxValuesContainer);
|
||||
checkboxes.prop("checked", false);
|
||||
checkboxes.removeClass("selectedCheckbox");
|
||||
this._selectedValuesContainer.empty();
|
||||
}
|
||||
|
||||
protected getValue(): string {
|
||||
var selectedCheckboxes: JQuery = $("input.valueOption:checked", this._checkboxValuesContainer);
|
||||
var selectedValues: string[] = [];
|
||||
const selectedCheckboxes: JQuery = $("input.valueOption:checked", this._checkboxValuesContainer);
|
||||
let selectedValues: string[] = [];
|
||||
|
||||
selectedCheckboxes.each((i: number, elem: HTMLElement) => {
|
||||
selectedValues.push($(elem).attr("value"));
|
||||
|
@ -122,15 +121,15 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
|
||||
protected setValue(value: string): void {
|
||||
this.clear();
|
||||
var selectedValues = value ? value.split(";") : [];
|
||||
const selectedValues = value ? value.split(";") : [];
|
||||
|
||||
this._showValues(selectedValues);
|
||||
|
||||
$.each(selectedValues, (i, value) => {
|
||||
if (value) {
|
||||
$.each(selectedValues, (i, selectedValue) => {
|
||||
if (selectedValue) {
|
||||
// mark the checkbox as checked
|
||||
var checkbox = this._valueToCheckboxMap[value];
|
||||
var label = this._valueToLabelMap[value];
|
||||
const checkbox = this._valueToCheckboxMap[selectedValue];
|
||||
const label = this._valueToLabelMap[selectedValue];
|
||||
if (checkbox) {
|
||||
checkbox.prop("checked", true);
|
||||
checkbox.addClass("selectedCheckbox");
|
||||
|
@ -142,8 +141,7 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
private _toggleCheckBoxContainer() {
|
||||
if (this._checkboxValuesContainer.is(":visible")) {
|
||||
this._hideCheckBoxContainer();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._showCheckBoxContainer();
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +153,6 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
this.resize();
|
||||
}
|
||||
|
||||
|
||||
private _hideCheckBoxContainer() {
|
||||
this._chevron.removeClass(this._chevronUpClass).addClass(this._chevronDownClass);
|
||||
this.containerElement.removeClass("expanded").addClass("collapsed");
|
||||
|
@ -163,20 +160,17 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
this.resize();
|
||||
}
|
||||
|
||||
|
||||
private _showValues(values: string[]) {
|
||||
if (values.length <= 0) {
|
||||
this._selectedValuesContainer.append("<div class='noSelection'>No selection made</div>");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$.each(values, (i, value) => {
|
||||
var control;
|
||||
let control;
|
||||
// only show first N selections and the rest as more.
|
||||
if (i < this._maxSelectedToShow) {
|
||||
control = this._createSelectedValueControl(value);
|
||||
}
|
||||
else {
|
||||
control = this._createSelectedValueControl(values.length - i + " more")
|
||||
} else {
|
||||
control = this._createSelectedValueControl(values.length - i + " more");
|
||||
control.attr("title", values.slice(i).join(";"));
|
||||
return false;
|
||||
}
|
||||
|
@ -189,14 +183,14 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
}
|
||||
|
||||
private _refreshValues() {
|
||||
var rawValue = this.getValue();
|
||||
var values = rawValue ? rawValue.split(";") : [];
|
||||
const rawValue = this.getValue();
|
||||
const values = rawValue ? rawValue.split(";") : [];
|
||||
this._selectedValuesContainer.empty();
|
||||
this._showValues(values);
|
||||
}
|
||||
|
||||
private _createSelectedValueControl(value: string): JQuery {
|
||||
var control = $("<div />");
|
||||
const control = $("<div />");
|
||||
if (value) {
|
||||
control.text(value);
|
||||
control.attr("title", value);
|
||||
|
@ -214,10 +208,9 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
private _populateCheckBoxes(): void {
|
||||
if (!this._suggestedValues || this._suggestedValues.length === 0) {
|
||||
this.showError("No values to select.");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Add the select all method
|
||||
let selectAllBox = this._createSelectAllControl();
|
||||
const selectAllBox = this._createSelectAllControl();
|
||||
|
||||
$.each(this._suggestedValues, (i, value) => {
|
||||
this._createCheckBoxControl(value, selectAllBox);
|
||||
|
@ -226,32 +219,31 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
}
|
||||
|
||||
private _updateSelectAllControlState() {
|
||||
let selectAllBox = $("input.selectAllOption", this._checkboxValuesContainer);
|
||||
let allBoxes = $("input.valueOption", this._checkboxValuesContainer);
|
||||
let checkedBoxes = $("input.valueOption:checked", this._checkboxValuesContainer);
|
||||
if(allBoxes.length > checkedBoxes.length) {
|
||||
const selectAllBox = $("input.selectAllOption", this._checkboxValuesContainer);
|
||||
const allBoxes = $("input.valueOption", this._checkboxValuesContainer);
|
||||
const checkedBoxes = $("input.valueOption:checked", this._checkboxValuesContainer);
|
||||
if (allBoxes.length > checkedBoxes.length) {
|
||||
selectAllBox.prop("checked", false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
selectAllBox.prop("checked", true);
|
||||
}
|
||||
}
|
||||
|
||||
private _createSelectAllControl() {
|
||||
|
||||
let value = "Select All";
|
||||
let label = this._createValueLabel(value);
|
||||
let checkbox = this._createCheckBox(value, label, () => {
|
||||
const value = "Select All";
|
||||
const label = this._createValueLabel(value);
|
||||
const checkbox = this._createCheckBox(value, label, () => {
|
||||
|
||||
let checkBoxes = $("input.valueOption", this._checkboxValuesContainer);
|
||||
if(checkbox.prop("checked")) {
|
||||
const checkBoxes = $("input.valueOption", this._checkboxValuesContainer);
|
||||
if (checkbox.prop("checked")) {
|
||||
checkBoxes.prop("checked", true);
|
||||
} else {
|
||||
checkBoxes.prop("checked", false);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
var container = $("<div />").addClass("checkboxContainer selectAllControlContainer");
|
||||
const container = $("<div />").addClass("checkboxContainer selectAllControlContainer");
|
||||
checkbox.addClass("selectAllOption");
|
||||
this._valueToCheckboxMap[value] = checkbox;
|
||||
|
||||
|
@ -267,9 +259,9 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
|
||||
private _createCheckBoxControl(value: string, selectAllBox: JQuery) {
|
||||
|
||||
let label = this._createValueLabel(value);
|
||||
let checkbox = this._createCheckBox(value, label);
|
||||
let container = $("<div />").addClass("checkboxContainer");
|
||||
const label = this._createValueLabel(value);
|
||||
const checkbox = this._createCheckBox(value, label);
|
||||
const container = $("<div />").addClass("checkboxContainer");
|
||||
checkbox.addClass("valueOption");
|
||||
this._valueToCheckboxMap[value] = checkbox;
|
||||
|
||||
|
@ -282,7 +274,7 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
}
|
||||
|
||||
private _createValueLabel(value: string) {
|
||||
let label = $("<label />");
|
||||
const label = $("<label />");
|
||||
label.attr("for", "checkbox" + value);
|
||||
label.text(value);
|
||||
label.attr("title", value);
|
||||
|
@ -290,8 +282,8 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
return label;
|
||||
}
|
||||
|
||||
private _createCheckBox(value:string, label: JQuery, action?: Function) {
|
||||
let checkbox = $("<input />");
|
||||
private _createCheckBox(value: string, label: JQuery, action?: () => void) {
|
||||
const checkbox = $("<input />");
|
||||
checkbox.attr("type", "checkbox");
|
||||
checkbox.attr("name", value);
|
||||
checkbox.attr("value", value);
|
||||
|
@ -300,7 +292,7 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
|
||||
checkbox.change((e) => {
|
||||
|
||||
if(action){
|
||||
if (action) {
|
||||
action.call(this);
|
||||
}
|
||||
|
||||
|
@ -311,17 +303,15 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
return checkbox;
|
||||
}
|
||||
|
||||
|
||||
private _getSuggestedValues(): IPromise<string[]> {
|
||||
var defer = Q.defer<any>();
|
||||
var inputs: IDictionaryStringTo<string> = VSS.getConfiguration().witInputs;
|
||||
const defer = Q.defer<any>();
|
||||
const inputs: IDictionaryStringTo<string> = VSS.getConfiguration().witInputs;
|
||||
|
||||
var valuesString: string = inputs["Values"];
|
||||
const valuesString: string = inputs.Values;
|
||||
if (valuesString) {
|
||||
defer.resolve(valuesString.split(";"));
|
||||
}
|
||||
// if the values input were not specified as an input, get the suggested values for the field.
|
||||
else {
|
||||
} else {
|
||||
// if the values input were not specified as an input, get the suggested values for the field.
|
||||
WitService.WorkItemFormService.getService().then(
|
||||
(service: any) => {
|
||||
service.getAllowedFieldValues(this.fieldName).then(
|
||||
|
@ -329,13 +319,13 @@ export class MultiValueCombo extends BaseMultiValueControl {
|
|||
defer.resolve(values);
|
||||
},
|
||||
() => {
|
||||
this.showError("Could not load values for field " + this.fieldName)
|
||||
}
|
||||
)
|
||||
}
|
||||
this.showError("Could not load values for field " + this.fieldName);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
src/app.ts
19
src/app.ts
|
@ -1,10 +1,10 @@
|
|||
import {MultiValueCombo} from "./MultiValueCombo";
|
||||
import {BaseMultiValueControl} from "./BaseMultiValueControl";
|
||||
import * as WitExtensionContracts from "TFS/WorkItemTracking/ExtensionContracts";
|
||||
import * as WitExtensionContracts from "TFS/WorkItemTracking/ExtensionContracts";
|
||||
import { WorkItemFormService } from "TFS/WorkItemTracking/Services";
|
||||
import {BaseMultiValueControl} from "./BaseMultiValueControl";
|
||||
import {MultiValueCombo} from "./MultiValueCombo";
|
||||
|
||||
// save on ctr + s
|
||||
$(window).bind("keydown", function (event: JQueryEventObject) {
|
||||
$(window).bind("keydown", (event: JQueryEventObject) => {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
if (String.fromCharCode(event.which) === "S") {
|
||||
event.preventDefault();
|
||||
|
@ -13,10 +13,10 @@ $(window).bind("keydown", function (event: JQueryEventObject) {
|
|||
}
|
||||
});
|
||||
|
||||
var control: BaseMultiValueControl;
|
||||
let control: BaseMultiValueControl;
|
||||
|
||||
var provider = () => {
|
||||
var ensureControl = () => {
|
||||
const provider = (): Partial<WitExtensionContracts.IWorkItemNotificationListener> => {
|
||||
const ensureControl = () => {
|
||||
if (!control) {
|
||||
control = new MultiValueCombo();
|
||||
control.initialize();
|
||||
|
@ -38,9 +38,8 @@ var provider = () => {
|
|||
if (control && args.changedFields[control.fieldName] !== undefined && args.changedFields[control.fieldName] !== null) {
|
||||
control.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
VSS.register(VSS.getContribution().id, provider);
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": [
|
||||
"tslint:recommended"
|
||||
],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"member-ordering": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"variable-name": false,
|
||||
"max-line-length": [true, 180]
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
Загрузка…
Ссылка в новой задаче