Skip to content
This repository has been archived by the owner on Jun 21, 2020. It is now read-only.

Commit

Permalink
Henry/fancy countdown (#42)
Browse files Browse the repository at this point in the history
* Add a new Widget: Fancy countdown
  • Loading branch information
henrybeen committed Aug 6, 2018
1 parent 7d07fc0 commit d46ba57
Show file tree
Hide file tree
Showing 14 changed files with 867 additions and 45 deletions.
9 changes: 7 additions & 2 deletions CountdownWidget/CountdownWidget/CountdownWidget.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<Use64BitIISExpress />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -45,6 +46,8 @@
<Content Include="static\countdown.html" />
<Content Include="static\countdownconfiguration.html" />
<Content Include="static\css\app.css" />
<Content Include="static\fancy-countdownconfiguration.html" />
<Content Include="static\fancy-countdown.html" />
<Content Include="static\img\Configure-Extension.png" />
<Content Include="static\img\logo.png" />
<Content Include="static\img\Preview-Full.png" />
Expand All @@ -56,12 +59,14 @@
<Content Include="tests\moment.js" />
<Content Include="webpack.config.js" />
<Content Include="whitesource.config.json" />
<TypeScriptCompile Include="src\configuration.ts" />
<TypeScriptCompile Include="src\countdownConfiguration.ts" />
<TypeScriptCompile Include="src\countdownCalculator.ts" />
<TypeScriptCompile Include="src\CountdownResult.ts" />
<TypeScriptCompile Include="src\countdownWidget.ts" />
<TypeScriptCompile Include="src\fancyCountdown.ts" />
<TypeScriptCompile Include="src\fancyCountdownConfiguration.ts" />
<TypeScriptCompile Include="src\isettings.d.ts" />
<TypeScriptCompile Include="src\main.ts" />
<TypeScriptCompile Include="src\countdown.ts" />
<TypeScriptCompile Include="src\telemetryClientSettings.ts" />
<TypeScriptCompile Include="tests\CountdownCalculatorSpec.ts" />
<Content Include="Overview.md" />
Expand Down
36 changes: 0 additions & 36 deletions CountdownWidget/CountdownWidget/CountdownWidget.csproj.user

This file was deleted.

1 change: 1 addition & 0 deletions CountdownWidget/CountdownWidget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"requirejs": "^2.2.0",
"spectrum-colorpicker": "^1.8.0",
"telemetryclient-team-services-extension": "*",
"timecircles": "^1.5.3",
"ts-promise": "^2.0.0",
"vss-web-extension-sdk": "^5.134.0"
}
Expand Down
294 changes: 294 additions & 0 deletions CountdownWidget/CountdownWidget/src/countdownConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
// ---------------------------------------------------------------------
// <copyright file="configuration.ts">
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
// </copyright>
// <summary>
// This is part of the Countdown widget
// from the ALM Rangers. This file contains the
// widget configuration code.
// </summary>
// ---------------------------------------------------------------------

// tslint:disable-next-line
/// <reference path="isettings.d.ts" />

import moment = require("moment-timezone");
import Q = require("q");
import spectrum = require("spectrum-colorpicker");
import TFS_Core_Contracts = require("TFS/Core/Contracts");
import Work_Contracts = require("TFS/Work/Contracts");
import Work_Client = require("TFS/Work/RestClient");
import Controls = require("VSS/Controls");
import Combos = require("VSS/Controls/Combos");
import Service = require("VSS/Service");
import DateUtils = require("VSS/Utils/Date");
import WebApi_Constants = require("VSS/WebApi/Constants");

// import TelemetryClient = require("scripts/TelemetryClient");

export class Configuration {
private static $dateTimeCombo: Combos.Combo = null;

private widgetConfigurationContext = null;
private $countdownDateInput = $("#countdown-date-input");
private $datetimepicker = $("#datetimepicker") as any;
private $timeZoneSelect = $("#countdown-timezone-select");
private $backgroundColor = $("#background-color-input");
private $foregroundColor = $("#foreground-color-input");
private $backgroundColorHoursEnabled = $("#background-color-hours-enabled");
private $backgroundColorHoursThreshold = $("#background-color-hours-threshold");
private $backgroundColorHoursColor = $("#background-color-hours-color-input");
private $skipNonWorkingDays = $("#skipNonWorkingDays");
private $roundNumber = $("#roundNumber");
private currentIterationEnd = null;
constructor(public WidgetHelpers, public isSprintWidget: boolean) { }

public load(widgetSettings, widgetConfigurationContext) {
this.widgetConfigurationContext = widgetConfigurationContext;

this.getCurrentIteration()
.then((currentIterationEnd) => {
this.currentIterationEnd = currentIterationEnd;
const settings: ISettings = JSON.parse(widgetSettings.customSettings.data);

this.showTimezones(settings);
this.showColorPickers(settings);
this.showDateTimePicker(settings, currentIterationEnd);
this.showWorkingDays(settings);
this.showRoundNumber(settings);
this.showBackgroundColorHours(settings);

VSS.resize();
this.$timeZoneSelect
.add(this.$backgroundColor)
.add(this.$foregroundColor)
.add(this.$backgroundColorHoursColor)
.add(this.$backgroundColorHoursEnabled)
.add(this.$backgroundColorHoursThreshold)
.add(this.$skipNonWorkingDays)
.add(this.$roundNumber)
.change(() => {
this.widgetConfigurationContext.notify(this.WidgetHelpers.WidgetEvent.ConfigurationChange,
this.WidgetHelpers.WidgetEvent.Args(this.getCustomSettings()));
});
});

return this.WidgetHelpers.WidgetStatusHelper.Success();
}

public onSave() {
const isValid = true;
if (isValid) {
// TelemetryClient.TelemetryClient.getClient().trackEvent("Updated configuration");
return this.WidgetHelpers.WidgetConfigurationSave.Valid(this.getCustomSettings());
} else {
return this.WidgetHelpers.WidgetConfigurationSave.Invalid();
}

}

private showDateTimePicker(settings, currentIterationEnd) {
if (!this.isSprintWidget) {
let countDownDate = moment();
if (settings && settings.countDownDate) {
countDownDate = moment(settings.countDownDate, "MM-DD-YYYY HH:mm");
} else {
countDownDate = moment().add(1, "days");
}

const dateTimeOptions: Combos.IDateTimeComboOptions = {
change: () => {
this.widgetConfigurationContext.notify(this.WidgetHelpers.WidgetEvent.ConfigurationChange,
this.WidgetHelpers.WidgetEvent.Args(this.getCustomSettings()));
},
dateTimeFormat: "F",
type: "date-time",
value: DateUtils.format(countDownDate.toDate(), "F"),
};
Configuration.$dateTimeCombo = Controls.create(Combos.Combo, this.$datetimepicker, dateTimeOptions);
} else {
this.$datetimepicker.hide();
$(".countdown-config-label").hide();
}
}

private showColorPickers(settings) {
const palette = [
["black", "white", "tan", "turquoise", "pink"],
["red", "yellow", "green", "blue", "violet"],
];

const colorSettings = {
color: "",
hideAfterPaletteSelect: false,
palette,
showPalette: true,
showPaletteOnly: false,
};

colorSettings.color = (settings && settings.backgroundColor) ?
settings.backgroundColor
: "green";

(this.$backgroundColor as any).spectrum(colorSettings);

colorSettings.color = (settings && settings.foregroundColor) ?
settings.foregroundColor
: "white";

(this.$foregroundColor as any).spectrum(colorSettings);

colorSettings.color = (settings && settings.backgroundColorHoursColor)
? settings.backgroundColorHoursColor
: "red";

(this.$backgroundColorHoursColor as any).spectrum(colorSettings);
}

private showTimezones(settings) {
if (!this.isSprintWidget) {
const timezones = moment.tz.names();
for (const timezone of timezones) {
const opt = document.createElement("option");
opt.innerHTML = timezone;
opt.value = timezone;
this.$timeZoneSelect[0].appendChild(opt);
}

if (settings && settings.timezone) {
this.$timeZoneSelect.val(settings.timezone);
} else {
this.$timeZoneSelect.val((moment as any).tz.guess());
}
} else {
this.$timeZoneSelect.hide();
$(".countdown-config-label").hide();
}
}

private showWorkingDays(settings) {
if (settings) {
this.$skipNonWorkingDays.prop("checked", settings.skipNonWorkingDays);
} else {
this.$skipNonWorkingDays.prop("checked", false);
}
}

private showRoundNumber(settings) {
if (settings) {
this.$roundNumber.prop("checked", settings.roundNumber);
} else {
this.$roundNumber.prop("checked", false);
}
}

private showBackgroundColorHours(settings) {
this.$backgroundColorHoursEnabled.change(() => this.onBackgroundColorHoursChanged());

if (settings && settings.backgroundColorHoursEnabled) {
this.$backgroundColorHoursEnabled.prop("checked", true);
}

this.$backgroundColorHoursThreshold.val(settings.backgroundColorHoursThreshold);

this.onBackgroundColorHoursChanged();
}

private onBackgroundColorHoursChanged() {
if (this.$backgroundColorHoursEnabled.is(":checked")) {
$("#changeColorHoursInputsWrapper").show();
} else {
$("#changeColorHoursInputsWrapper").hide();
}

VSS.resize();
}

private getCustomSettings() {
let formattedDate = "";
if (this.isSprintWidget) {
if (this.currentIterationEnd) {
formattedDate = moment(this.currentIterationEnd).format("MM-DD-YYYY HH:mm");
}
} else {
const selectedDate = Configuration.$dateTimeCombo.getValue();
if (selectedDate) {
formattedDate = moment(selectedDate).format("MM-DD-YYYY HH:mm");
}
}

const foregroundColor = (this.$foregroundColor as any).spectrum("get").toRgbString();
const backgroundColor = (this.$backgroundColor as any).spectrum("get").toRgbString();
const backgroundColorHours = (this.$backgroundColorHoursColor as any).spectrum("get").toRgbString();
const skipNonWorkingDays = this.$skipNonWorkingDays.prop("checked");
const roundNumber = this.$roundNumber.prop("checked");

const result = {
data: JSON.stringify({
backgroundColor,
backgroundColorHoursColor: backgroundColorHours,
backgroundColorHoursEnabled: this.$backgroundColorHoursEnabled.is(":checked"),
backgroundColorHoursThreshold: this.$backgroundColorHoursThreshold.val(),
countDownDate: formattedDate,
foregroundColor,
roundNumber,
skipNonWorkingDays,
timezone: this.$timeZoneSelect.val(),
} as ISettings),
};
return result;
}

private getCurrentIteration(): IPromise<Date> {
const deferred = Q.defer<Date>();
const webContext = VSS.getWebContext();
const teamContext: TFS_Core_Contracts.TeamContext = {
project: "",
projectId: webContext.project.id,
team: "",
teamId: webContext.team.id,
};

const workClient: Work_Client.WorkHttpClient = Service.VssConnection
.getConnection()
.getHttpClient(Work_Client.WorkHttpClient, WebApi_Constants.ServiceInstanceTypes.TFS);

workClient.getTeamIterations(teamContext).then((iterations) => {
if (iterations.length > 0) {
workClient.getTeamIterations(teamContext, "current").then((teamIterations) => {
if (teamIterations.length > 0) {
deferred.resolve(teamIterations[0].attributes.finishDate);
} else {
deferred.resolve(null);
}
});
} else {
deferred.resolve(null);
}
});

return deferred.promise;
}
}

VSS.require(["TFS/Dashboards/WidgetHelpers"], (WidgetHelpers) => {
VSS.register("SprintEndCountdownWidget-Configuration", () => {
const configuration = new Configuration(WidgetHelpers, true);
return configuration;
});

VSS.notifyLoadSucceeded();
});

VSS.require(["TFS/Dashboards/WidgetHelpers"], (WidgetHelpers) => {
VSS.register("CountdownWidget-Configuration", () => {
const configuration = new Configuration(WidgetHelpers, false);
return configuration;
});

VSS.notifyLoadSucceeded();
});
Loading

0 comments on commit d46ba57

Please sign in to comment.