<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>ondrejstastny</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/ondrejstastny/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/feed.xml</link>
    <description />
    <lastBuildDate>Wed, 17 Apr 2019 04:00:54 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 6: Modifying Build Template To Automate Extension Minification and Packaging</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-6-modifying-build-template-to-automate-extension-minification-and-packaging</link>
      <pubDate>Tue, 27 Nov 2012 03:12:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/27/tfs-2012-web-access-customizations-part-6-modifying-build-template-to-automate-extension-minification-and-packaging/</guid>
      <description><![CDATA[Manually minifying files and creating extension packages can be very tedious work. In this post, I...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;"><span style="font-family: Calibri;">Manually minifying files and creating extension packages can be very tedious work. In this post, I will show you how to automate this process.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">In order to make it work, we will rely on a few conventions. In our project, each extension will have its own folder. Name of that folder will be used to produce a package of the same name. In this folder, there must be the manifest file, source files and all the resources. All .debug.js files will be automatically minified. The folder should not contain manually minified files (.min.js files) as those will be overwritten.</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">First step is to modify TFS build template in order to enable batch script execution. Within this script, source files are minified and extension packages are automatically created.</span></span></p>
<p>&nbsp;</p>
<pre class="scroll"><code class="cplusplus">echo off<br /> <br />FOR /R "%SourcesDirectory%" %%G in (.) DO (<br /> Pushd %%G<br /> IF EXIST manifest.xml (<br /> rem minify files<br /> FOR %%F in ("*.debug.js") DO (<br /> FOR %%H in (%%~nF) DO ( ajaxminifier "%%F" -out "%%~nH.min.js" -clobber )<br /> )<br /> <br /> rem create zip package<br /> 7za a -tzip "%BinariesDirectory%\%%~nxG.zip" *<br /> ) <br />Popd )</code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;"></span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Note, in the script we use 2 external tools:</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>Ajaxminifier</strong>, Microsoft tool available from <span style="text-decoration: underline;"><a href="https://ajaxmin.codeplex.com/"><span style="color: #0000ff;">https://ajaxmin.codeplex.com/</span></a></span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>7za</strong>, 7zip console available from <span style="text-decoration: underline;"><a href="https://www.7-zip.org/"><span style="color: #0000ff;">https://www.7-zip.org/</span></a></span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Both these tools as well as the script have to be deployed on the target build machine where the Build Agent will run the job. For convenience, we deployed all to System32 folder for easy access, but you should be cautious when doing that. </span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">We insert new <strong>InvokeProcess</strong> action to <strong>RunOnAgent</strong> and add 2 new arguments <strong>BatchFile</strong> and <strong>BatchFileArguments</strong>. That we use to configure properties of InvokeProcess.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/2783.build1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/2783.build1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/2783.build1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/2783.build1.png" alt="" border="0" /></a></span></p>
<p><span style="font-family: Calibri; font-size: small;"><span style="font-size: small;"><span style="font-family: Calibri;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/8228.build2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/8228.build2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/8228.build2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/8228.build2.png" alt="" border="0" /></a></span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Then we create new build definition that includes the configuration for our batch script. Note, the script path is local to the build machine.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/4745.build3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/4745.build3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/4745.build3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/4745.build3.png" alt="" border="0" /></a></span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Having all that successfully setup, we can now query new build in TFS. It will create the extension package for each control in our solution and put it to the output directory. </span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Next time, we will look at the implementation details for TFS Web Access progress indicator that you would use to signalize a long(er) running operations in your extensions.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"></span></span></p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 5: Using Fiddler to Speed Up Development</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-5-using-fiddler-to-speed-up-development</link>
      <pubDate>Tue, 27 Nov 2012 03:11:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/27/tfs-2012-web-access-customizations-part-5-using-fiddler-to-speed-up-development/</guid>
      <description><![CDATA[The whole process of making a change, creating a package, deploying it to TFS, re-enabling and...]]></description>
      <content:encoded><![CDATA[<p>The whole process of making a change, creating a package, deploying it to TFS, re-enabling and testing it is very tedious. In order to speed up the development effort, Fiddler can be used.</p>
<p>Fiddler is a Web Debugging Proxy which logs all HTTP(S) traffic between your computer and the Internet. Fiddler allows you to inspect traffic, set breakpoints, and "fiddle" with incoming or outgoing data. Fiddler includes a powerful event-based scripting subsystem, and can be extended using any .NET language.</p>
<p>Fiddler is freeware and can debug traffic from virtually any application that supports a proxy, including Internet Explorer, Google Chrome, Apple Safari, Mozilla Firefox, Opera, and many others. You can download Fiddler from <a href="https://www.fiddler2.com/">https://www.fiddler2.com</a>.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/8468.screen8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/8468.screen8.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/8468.screen8.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/8468.screen8.png" alt="" border="0" /></a>&nbsp;&nbsp;</p>
<p>For our purpose, we need to enable Automatic responses and setup 2 AutoResponder rules as seen on the screenshot above.</p>
<p>The URI should be specific to a target TFS that we are using for testing. We use regex here to support scenarios when we indeed do deploy new version of our plugin through the standard process. At that point, part of the URI for the extension changes (number right after the &hellip;/_plugins/ part of the URI) and we do not need to update our rule.</p>
<p>First rule responds with HTTP header modification that disables caching of our .js resource. Otherwise, the code would not be requested from the server unless the web browser cache was cleared.</p>
<p>Second rule bypasses the request and supplies our own development copy of the source file from hard drive.</p>
<p>This way, whenever we do any modification to the source our changes will be immediately propagated to the client browser for testing.</p>
<p>&nbsp;</p>
<p>Next time, I will show you how to modify Build template to automate extension source file minification and package creation.</p>]]></content:encoded>
    </item>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 4: Sample Extensions</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-4-sample-extensions</link>
      <pubDate>Tue, 27 Nov 2012 03:10:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/27/tfs-2012-web-access-customizations-part-4-sample-extensions/</guid>
      <description><![CDATA[In this post I will show you sample code for several Web Access controls. This should help you grasp...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;"><span style="font-family: Calibri;">In this post I will show you sample code for several Web Access controls. This should help you grasp all the concepts fairly quickly and get started developing your own extensions. </span></span></p>
<p><span style="font-family: Calibri; font-size: small;">Here is the screenshot of what we are trying to achieve today:</span></p>
<p><span style="font-family: Calibri; font-size: small;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/4540.screen9.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/4540.screen9.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/4540.screen9.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/4540.screen9.png" alt="" border="0" /></a>&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">First extension that we are going to look at is a progress bar that reflects state of a bug. It will be empty for a new bug, half full for a complete bug and full when the bug gets closed. You could also modify it to reflect your work item&rsquo;s states <span style="font-size: small;"><span style="font-family: Calibri;">more appropriately. For the progressbar, I am using the jQuery UI and the default theme that comes with TFS.</span></span></span></span></p>
<pre class="scroll"><code class="js">TFS.module("TFS.WA.ProgressBar",<br /> [<br /> "TFS.WorkItemTracking.Controls",<br /> "TFS.WorkItemTracking",<br /> "TFS.Core"<br /> ],<br /> function () {<br /> var WITOM = TFS.WorkItemTracking,<br /> WITCONTROLS = TFS.WorkItemTracking.Controls,<br /> delegate = TFS.Core.delegate,<br /> moduleBaseUrl = TFS.getModuleBase("TFS.WA.ProgressBar");<br /> <br /> // Constructor for ProgressBar<br /> function ProgressBar(container, options, workItemType) {<br /> this.baseConstructor.call(this, container, options, workItemType);<br /> }<br /> <br /> // ProgressBar inherits from WorkItemControl<br /> ProgressBar.inherit(WITCONTROLS.WorkItemControl, {<br /> _control: null,<br /> <br /> // Initialize the control UI without data (in "blank" state).<br /> _init: function () {<br /> this._base();<br /> <br /> //add css style<br /> //$("&lt;link /&gt;").attr("href", moduleBaseUrl + "style.css")<br /> //.attr("type", "text/css").attr("rel", "stylesheet").appendTo($("head").first());<br /> <br /> this._control = $("&lt;div id='progressbar'&gt;&lt;/div&gt;").appendTo(this._container);<br /> },<br /> <br /> // Update the control data<br /> invalidate: function (flushing) { <br /> var a = this._workItem.getField('System.State');//same as this._getField() because this control is associated with System.State field<br /> <br /> switch(a.getDisplayText())<br /> {<br /> case "Active":<br /> $(this._control).progressbar({ value: 0 });<br /> break;<br /> case "Resolved":<br /> $(this._control).progressbar({ value: 50 });<br /> break;<br /> case "Closed":<br /> $(this._control).progressbar({ value: 100 });<br /> break;<br /> }<br /> },<br /> <br /> // Clear the control data<br /> clear: function () {<br /> <br /> }<br /> <br /> });<br /> <br /> // Register this module as a work item custom control called "ProgressBar"<br /> WITCONTROLS.registerWorkItemControl("TFS.WA.ProgressBar", ProgressBar);<br /> <br /> return {<br /> ProgressBar: ProgressBar<br /> };<br /> });</code></pre>
<p><span style="font-family: Calibri; font-size: small;">Before deploying this extension, you will need to update your work item (most likely Bug)&nbsp;definition (please refer to <a title="https://blogs.msdn.com/b/ondrejstastny/archive/2012/11/27/tfs-2012-web-access-customizations-part-3-extension-deployment.aspx" href="https://blogs.msdn.com/controlpanel/blogs/posteditor.aspx/Part 3">Part 3</a>) to include the control in the WebAccess form layout:</span></p>
<pre class="scroll"><code class="html">&lt;Control FieldName="System.State" Type="ProgressBar" Label="State:" LabelPosition="Left" /&gt;<br /> </code></pre>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">The other sample is much more complex. While the scenario to use this extension is purely artificial, it shows well some more advanced techniques such as work item querying or progress indicator usage. Btw,&nbsp;I will dedicate&nbsp;one separate post entirely to&nbsp;TFS&nbsp;Progress Indicator, so don't worry if you do not fully&nbsp;understand &nbsp;how it works. The control itself is a combo box that lists all bugs in the project. It remembers what bug is selected for each work item and displays who the bug is assigned to.</span></span></p>
<pre class="scroll"><code class="js">TFS.module("TFS.WA.BugList",<br /> [<br /> "TFS.WorkItemTracking.Controls",<br /> "TFS.WorkItemTracking",<br /> "TFS.Core"<br /> ],<br /> function () {<br /> <br /> // module content<br /> <br /> var WITOM = TFS.WorkItemTracking,<br /> WITCONTROLS = TFS.WorkItemTracking.Controls,<br /> delegate = TFS.Core.delegate,<br /> moduleBaseUrl = TFS.getModuleBase("TFS.WA.BugList");<br /> <br /> // Constructor for URIs<br /> function BugList(container, options, workItemType) {<br /> this.baseConstructor.call(this, container, options, workItemType);<br /> }<br /> <br /> // BugList inherits from WorkItemControl<br /> BugList.inherit(WITCONTROLS.WorkItemControl, {<br /> _control: null,<br /> _loaded: false,<br /> <br /> // Initialize the control UI without data (in "blank" state).<br /> _init: function () {<br /> this._base();<br /> <br /> //add css style<br /> $("&lt;link /&gt;").attr("href", moduleBaseUrl + "TFS.WA.BugList.styles.css")<br /> .attr("type", "text/css").attr("rel", "stylesheet").appendTo($("head").first());<br /> <br /> this._control = $("&lt;div&gt;&lt;select id='BugListList'/&gt;&lt;span id='BugListRefreshButton' class='icon icon-refresh-2' /&gt;&lt;br /&gt;&lt;label class='workitemcontrol-label'&gt;Assigned To:&lt;/label&gt;&lt;input readonly='readonly' type='text' id='BugListAssignedTo'&gt;&lt;/div&gt;")<br /> .appendTo(this._container);<br /> $(this._control).children("#BugListList").bind("change", delegate(this, this._changed));<br /> $(this._control).children("#BugListRefreshButton").bind("click", delegate(this, this._updateList));<br /> },<br /> <br /> // Update the control data<br /> invalidate: function (flushing) {<br /> if (!this._loaded)<br /> this._updateList(delegate(this, this._updateListSelection));<br /> else<br /> this._updateListSelection();<br /> },<br /> <br /> // Clear the control data<br /> clear: function () {<br /> <br /> },<br /> <br /> _updateListSelection: function() {<br /> var list = $(this._control).children("#BugListList");<br /> <br /> $(list).val(this._getField().getValue());<br /> <br /> this._updateAssignedTo();<br /> },<br /> <br /> _changed: function () {<br /> var list = $(this._control).children("#BugListList");<br /> var val = list.val();<br /> <br /> if (this._getField().getValue() == val)<br /> return; //no need to update the underlying field<br /> <br /> //store new value in the underlying field<br /> this._getField().setValue(val);<br /> },<br /> <br /> _updateAssignedTo: function () {<br /> var progressId = TFS.globalProgressIndicator.actionStarted("TFS.WA.BugList_updateAssignedTo", true);<br /> <br /> var list = $(this._control).children("#BugListList");<br /> var field = $(this._control).children("#BugListAssignedTo");<br /> var val = list.val();<br /> <br /> //clear <br /> $(field).val('');<br /> <br /> //call query and fill the field<br /> var query = "Select [Assigned To] From WorkItems Where [Id] = '" + val + "'";<br /> this._runQuery(query, function (res) {<br /> if (res.payload.rows.length == 1) {<br /> $(field).val(res.payload.rows[0][1]);<br /> }<br /> <br /> TFS.globalProgressIndicator.actionCompleted(progressId);<br /> });<br /> <br /> },<br /> <br /> _updateList: function (callback) {<br /> var progressId = TFS.globalProgressIndicator.actionStarted("TFS.WA.BugList_updateList", true);<br /> <br /> var list = $(this._control).children("#BugListList");<br /> <br /> //clear options<br /> $(list).text('');<br /> <br /> var that = this;<br /> <br /> //call query and fill the list with options<br /> var query = "Select [State], [Title] From WorkItems Where [Work Item Type] = 'Bug' Order By [State] Asc, [Changed Date] Desc";<br /> this._runQuery(query, function (res) {<br /> $.each(res.payload.rows, function (i, v) {<br /> $(list).append($('&lt;option /&gt;').attr('value', v[0]).text(v[2] + " [" + v[1] + "]"));<br /> });<br /> <br /> this._loaded = true;<br /> <br /> if ($.isFunction(callback)) callback.call();<br /> <br /> TFS.globalProgressIndicator.actionCompleted(progressId);<br /> });<br /> },<br /> <br /> _runQuery: function (query, callback) {<br /> this._workItem.store.beginQuery(this._workItem.project, query, callback, null, null);<br /> }<br /> <br /> });<br /> <br /> <br /> // Register this module as a work item custom control called "BugList"<br /> WITCONTROLS.registerWorkItemControl("TFS.WA.BugList", BugList);<br /> <br /> return {<br /> BugList: BugList<br /> };<br /> });</code></pre>
<p><span style="font-family: Calibri; font-size: small;">Again, before deploying this extension add following to the work item definition:</span></p>
<ol>
<li><span style="font-family: Calibri; font-size: small;">Add new field to hold the selection:</span></li>
</ol>
<pre class="scroll"><code class="html">&lt;FIELD name="SelectedBug" refname="TFS.WA.SelectedBug" type="Integer"&gt;<br /> &lt;HELPTEXT&gt;Bug individually picked from the list of all project bugs&lt;/HELPTEXT&gt;<br /> &lt;/FIELD&gt;</code></pre>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.&nbsp;&nbsp; Add the control itself:</span></p>
<pre class="scroll"><code class="html">&lt;Control FieldName="TFS.WA.SelectedBug" Type="TFS.WA.BugList" Label="Project Bugs:" LabelPosition="Left" /&gt;<br /> </code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">I hope these samples were useful to you and you. In the next post, I will show you how to use Fiddler to speed up your development by surpassing the need to re-deploy the extension every time you make even the slightest modification to the source code.</span></span></p>]]></content:encoded>
    </item>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 3: Extension Packaging &amp; Deployment</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-3-extension-packaging-deployment</link>
      <pubDate>Tue, 27 Nov 2012 03:08:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/27/tfs-2012-web-access-customizations-part-3-extension-packaging-deployment/</guid>
      <description><![CDATA[Our fourth (yay zero based numbering!) will explain the fundamentals of TFS Web Access Extension...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;"><span style="font-family: Calibri;">Our fourth (yay zero based numbering!) will explain the fundamentals of TFS Web Access Extension package and how to deploy it to the server. After reading this article, you should be able create an extension on your own. However, in the upcoming articles we will discuss sample implementation of a few extensions and look at ways to speed up the development process.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">&nbsp;</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Extension contains JavaScript source files and a manifest file at least. It can also contain CSS, images or other resources. When deploying the final extension package (which is an ordinary ZIP file with the aforementioned content) it must contain two version of each JavaScript file. The <strong>.debug.js</strong> version with full source code and comments and <strong>.min.js</strong> minified file that is reduced in size and does not contain whitespace or comments. A way to automate JS file minification will be shown in a later article.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">The manifest file, which is a plain old XML, contains metadata for the extension. This metadata (description, vendor and extension website) is displayed primarily in the Control Panel of the Team Foundation Server. It also contains a list of all modules within that particular extension. </span></span></p>
<p>&nbsp;</p>
<pre class="scroll"><code class="html">&lt;WebAccess version="11.0"&gt;<br /> &lt;plugin name="description" vendor="Microsoft" moreinfo="url" version="1.0.0" &gt;<br /> &lt;modules&gt;<br /> &lt;module namespace="Microsoft.Siemens.BugList&ldquo; kind="TFS.WorkItem.CustomControl"/&gt; <br /> &lt;/modules&gt;<br /> &lt;/plugin&gt;<br />&lt;/WebAccess&gt;</code></pre>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Before you can deploy your extension, you must modify the Work Item definition file. The definition file tells TFS what work item types are available and how should each item be presented. A work item type defines the rules, fields, states, and transitions for an item of work that will be tracked for a team project, such as a bug, requirement, or risk. This definition is shared by both Web Access and Visual Studio (and &ldquo;other clients&rdquo; to be more precise). However, there is a way to differentiate what gets displayed where. You can have some layout and controls specific to web access and some to Visual Studio. This actually comes in handy considering the fact that you have to provide 2 different implementations (one .NET, one JavaScript) in order to be able to cater to both.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">To retrieve current work item definition file, you use following command:</span></span></p>
<p><strong><span style="font-size: small;"><span style="font-family: Calibri;">&nbsp;witadmin exportwitd /n:Bug /f:c:\bug.xml /collection:https://tfsinstance:8080/tfs/collectionname /p:project</span></span></strong></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">The XML file gets saved to a local disk where you can do any modifications deemed necessary.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">You can either:</span></span></p>
<ol start="1">
<li><span style="font-size: small;"><span style="font-family: Calibri;">Add proprietary fields to fields collection to store additional data for work each work item</span></span></li>
</ol>
<pre class="scroll"><code class="html">&lt;FIELD name="SelectedBug" <br /> refname="TFS.WA.SelectedBug" <br /> type="Integer" /&gt;<br /> </code></pre>
<ol start="2">
<li><span style="font-size: small;"><span style="font-family: Calibri;">Add control and associate a field (system or custom) with a control </span></span></li>
</ol>
<pre class="scroll"><code class="html">&lt;Control <br /> Name="TFS.WA.Control" <br /> FieldName="TFS.WA.SelectedBug" <br /> Type="TFS.WA.BugList" <br /> Label="Project Bugs:" <br /> LabelPosition="Left" /&gt;</code></pre>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Control&rsquo;s optional attribute <strong>Name</strong> uniquely identifies a control. It is mandatory if more than one control on the form is associated with the same work item field. </span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>FieldName</strong> references field in the TFS data store that holds the value for each work item.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>Type</strong> is our registered extension.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">For the full reference, see the MSDN article <span style="text-decoration: underline;"><a href="https://msdn.microsoft.com/en-us/library/ms243932.aspx"><span style="color: #0000ff;">https://msdn.microsoft.com/en-us/library/ms243932.aspx</span></a></span>.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">To create different configuration for Web Access and other clients, you split up the layout definition into two groups in a following way:</span></span></p>
<pre class="scroll"><code class="html">&lt;FORM&gt;<br /> &lt;Layout Target="Web"&gt;<br /> &lt;Group&gt;<br /> &hellip;<br /> &lt;/Group&gt;<br /> &lt;/Layout&gt;<br /> &lt;Layout Target="WinForms"&gt;<br /> &lt;Group&gt;<br /> &hellip;<br /> &lt;/Group&gt;<br /> &lt;/Layout&gt;<br />&lt;/FORM&gt;</code></pre>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Only downside to that is you have to maintain definition for shared controls in both layouts. Also note that control&rsquo;s name attribute has to be unique across the whole work item definition, not only one layout.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">When our work item type definition is ready, we can deploy it back to TFS with the following command:</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>witadmin importwitd /f:"c:\bug.xml" /collection:https://tfsinstance:8080/tfs/collectioname /p:projectname</strong></span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Next step is to deploy the packaged extension itself.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/5611.screen7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/5611.screen7.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/5611.screen7.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/5611.screen7.png" alt="" border="0" /></a></span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">We can go to TFS control panel and click the Administration button.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">On the Extensions tab, we see all currently deployed extensions, have a chance to enable/disable them or deploy new extensions.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Every time we deploy new version of the extension, it is enough to upload and enable it. It is not necessary to uninstall previous version.</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">In this post you learned how to modify the work item definition file, create extension package and deploy it to the TFS server. By now, you should be able to start developing Web Access extensions on your own. If you stick with me for couple more posts, you will also see some sample code and learn how to improve your development process.</span></span></p>]]></content:encoded>
    </item>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 2: Extension template</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-2-extension-template</link>
      <pubDate>Tue, 27 Nov 2012 03:07:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/27/tfs-2012-web-access-customizations-part-2-extension-template/</guid>
      <description><![CDATA[In this part of our on-going series about TFS 2012 Web Access customizations we are going look at...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;"><span style="font-family: Calibri;">In this part of our on-going series about TFS 2012 Web Access customizations we are going look at the actual blueprint for the Work Item control. In the next article you will learn about packaging the extension, providing all the necessary metadata and deploying it to TFS server.&nbsp;&nbsp;</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">After reading this article, you should understand how to compose a new Web Access control and what is the minimal code necessary for it.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Below is the source code divided into sections with comments below each of the sections and then we include the full source code at the end of the article again for convenience.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<pre class="scroll"><code class="js">TFS.module("TFS.WA.BugList",<br /> <br /> [<br /> <br /> "TFS.WorkItemTracking.Controls",<br /> <br /> "TFS.WorkItemTracking",<br /> <br /> "TFS.Core"<br /> <br /> ],<br /> <br /> function () {<br /> </code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">TFS is a global variable belonging to Web Access framework which provides a utility method to define your module.&nbsp; <br /></span></span><span style="font-size: small;"><span style="font-family: Calibri;">The first parameter of the module is a string which specifies a namespace for the module. Please note that this namespace should match the filename you specified for your .js file (the part before flavor). <br /></span></span><span style="font-size: small;"><span style="font-family: Calibri;">The second parameter is an array of strings which specifies the dependencies of your module. The list in the above line is a typical list for the custom control development. Web Access module loader makes sure that the dependent modules are first loaded before your module gets executed. <br /></span></span><span style="font-size: small;"><span style="font-family: Calibri;">The last parameter is a function which gets executed when the module is loaded and the actual module implementation lives in here. Optionally you can expose anything you want from your module by return an object.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<pre class="scroll"><code class="js">// module content<br /> var WITOM = TFS.WorkItemTracking,<br /> WITCONTROLS = TFS.WorkItemTracking.Controls,<br /> delegate = TFS.Core.delegate,<br /> moduleBaseUrl = TFS.getModuleBase("TFS.WA.BugList");</code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">For convenience, we define few shortcuts and get the module base URI to use for including CSS files and/or other resources in our module.</span></span></p>
<p>&nbsp;</p>
<pre class="scroll"><code class="js">// Constructor for URIs<br /> function BugList(container, options, workItemType) {<br /> this.baseConstructor.call(this, container, options, workItemType);<br /> }</code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Next up is a constructor for our module. The parameters come from XML definition of the work item in TFS. Notice the explicit call to base class constructor.</span></span></p>
<p>&nbsp;</p>
<pre class="scroll"><code class="js">// BugList inherits from WorkItemControl BugList.inherit(WITCONTROLS.WorkItemControl, {<br /> _control: null,<br /> _loaded: false,</code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">We inherit our extension class from WorkItemControl.</span></span></p>
<p>&nbsp;</p>
<pre class="scroll"><code class="js">// Initialize the control UI without data (in "blank" state).<br />_init: function () {<br /> this._base();<br /> <br /> //add css style<br /> $("&lt;link /&gt;").attr("href", moduleBaseUrl + "TFS.WA.BugList.styles.css")<br /> .attr("type", "text/css")<br /> .attr("rel","stylesheet")<br /> .appendTo($("head").first());<br /> <br /> this._control = $("&lt;div /&gt;").appendTo(this._container);<br />},</code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>Init</strong> function represents component initialization, generally consisting of HTML construction. Here we also add CSS link to the DOM. Important thing to remember is that the initialization is <strong>shared</strong> across multiple items and is not invoked every time a work item is accessed but rather the first time the control is displayed on the UI. The implication of that is that at this point the control is not associated with any work item. Binding mechanism is used for associating controls with specific items (see next slide).</span></span></p>
<p>&nbsp;</p>
<pre class="scroll"><code class="js">// Update the control data<br />invalidate: function (flushing) {<br /> //...<br />}, </code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>Invalidate</strong> method is called every time the value in the underlying data store has changed (what field is associated with the control is driven by the XML work item type definition). The change occurs when we the value is saved, reverted or refreshed. If flushing is true then the value is being written to the work item field.</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<pre class="scroll"><code class="cplusplus">// Clear the control data<br /> clear: function () {},<br /> });<br /> // Register this module as a work item custom control called "BugList"<br /> WITCONTROLS.registerWorkItemControl("TFS.WA.BugList", BugList); <br /> return {<br /> BugList: BugList<br /> };<br /> });</code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Framework calls <strong>clear</strong> method when the control needs to reset its state to "blank".<br /></span></span><span style="font-size: small;"><span style="font-family: Calibri;">At the end we register our extension with the TFS.</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>bind(workItem)<br /></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;">This method is called when the control is being bound to a new work item.</span></span><span style="font-size: small;"><span style="font-family: Calibri;">&nbsp;</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>unbind(workItem)<br /></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;">This method is called when the control is no longer bound to the specified work item</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>getControlValue()<br /></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;">This method is called to get the value of the control to write to the corresponding Work Item Tracking field.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>cleanup()<br /></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;">This method is called to allow the control to release reference to work item, detach from events, set members to null to free memory which is called after unbind.</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>_container<br /></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;">This property is a jQuery object (DIV) which contains the control and sub elements are placed.</span></span><span style="font-size: small;"><span style="font-family: Calibri;">&nbsp;</span></span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;"><strong>_getField()<br /></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;">This method gets the work item form field that corresponds to this control. _getField().getValue() and _getField().setValue(value) are used to read and modify the underlying work item fields. This method returns null if no field is associated with the control in the work item type definition.</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">Here is the above code again in one part:</span></span></p>
<pre class="scroll"><code class="js">TFS.module("TFS.WA.BugList",<br />[<br /> "TFS.WorkItemTracking.Controls",<br /> "TFS.WorkItemTracking",<br /> "TFS.Core"<br />],<br />function () {<br /> // module content<br /> var WITOM = TFS.WorkItemTracking,<br /> WITCONTROLS = TFS.WorkItemTracking.Controls,<br /> delegate = TFS.Core.delegate,<br /> moduleBaseUrl = TFS.getModuleBase("TFS.WA.BugList");<br /></code><code class="js"> // Constructor for URIs<br /> function BugList(container, options, workItemType) {<br /> this.baseConstructor.call(this, container, options, workItemType);<br /> }<br /> // BugList inherits from WorkItemControl <br /> BugList.inherit(WITCONTROLS.WorkItemControl, {<br /> _control: null,<br /> _loaded: false,<br /> // Initialize the control UI without data (in "blank" state).<br /> _init: function () {<br /> this._base();<br /> <br /> //add css style<br /> $("&lt;link /&gt;").attr("href", moduleBaseUrl + "TFS.WA.BugList.styles.css")<br /> .attr("type", "text/css")<br /> .attr("rel","stylesheet")<br /> .appendTo($("head").first());<br /> <br /> this._control = $("&lt;div /&gt;").appendTo(this._container);<br /> },<br /> // Update the control data<br /> invalidate: function (flushing) {<br /> //...<br /> },<br /> // Clear the control data<br /> clear: function () {},<br /> //...<br /> });<br /> <br /> // Register this module as a work item custom control called "BugList"<br /> WITCONTROLS.registerWorkItemControl("TFS.WA.BugList", BugList); <br /> return {<br /> BugList: BugList<br />};<br />});<br /> </code></pre>
<p><span style="font-size: small;"><span style="font-family: Calibri;">In the next article we will take our code and create extension package that can be deployed on the TFS server.</span></span></p>]]></content:encoded>
    </item>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 1: OOP Principles in JavaScript</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-1-oop-principles-in-javascript</link>
      <pubDate>Mon, 26 Nov 2012 21:00:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/26/tfs-2012-web-access-customizations-part-1-oop-principles-in-javascript/</guid>
      <description><![CDATA[This is a second part in a series of posts that will get you jump started on developing custom...]]></description>
      <content:encoded><![CDATA[<p>This is a second part in a series of posts that will get you jump started on developing custom controls for Team Foundation Server 2012 Web Access. We will start with rather general topic, but nonetheless important for TFS Web Access. <span>After reading this article, you should be able to use JavaScript effectively and follow principles of Object Oriented Programming (OOP) the same way it is used in TFS Web Access API.</span></p>
<p>&nbsp;</p>
<p>The TFS client library is designed with&nbsp;OOP principles in mind. For JavaScript that means using following techniques:</p>
<p><strong>Data Abstraction</strong></p>
<p>Abstract data types are descriptions and representations of a real-world construct along with associated behaviour. Languages such as C# provide the <strong>class</strong> keyword to identify abstract data types. In JavaScript functions are used as object descriptors and all functions are actually JavaScript objects. Thus in JavaScript, classes are function definitions.</p>
<p>In TFS, objects consist of constructor definition and methods and properties declared using the <strong><a href="https://www.w3schools.com/jsref/jsref_prototype_math.asp"><span style="color: #0000ff;">prototype</span></a></strong> keyword.</p>
<pre class="scroll"><code class="csharp">function MyClass() {<br /> this.text = "Hello World";<br />}<br />var inst = new MyClass();</code></pre>
<p>&nbsp;</p>
<p><strong>Inheritance</strong></p>
<p>JavaScript supports inheritance through the use of object prototypes. A prototype is a template of properties that is shared by all instances of the object type. Thus instances of object types &ldquo;inherit&rdquo; the values of its prototype property. In JavaScript, all object types have a prototype property that can be both extended and inherited.</p>
<p>TFS contains function <strong>inherit </strong>that helps properly setup inheritance and construct call chain (base constructor has to be called explicitly with <strong>this.baseConstructor.call</strong>).</p>
<pre class="scroll"><code class="csharp">function Parent() { };<br /> <br />Parent.prototype.getName= function() {<br /> return "Parent";<br />}<br /> <br /> <br />function Child() {<br /> Parent.call(this);<br />};<br /> <br />Child.prototype = new Parent();<br />Child.prototype.constructor = Child;<br />Child.prototype.getName= function() { return "Child"; }<br /> </code></pre>
<p>&nbsp;</p>
<p><strong>Encapsulation</strong></p>
<p>Encapsulation represents the principle of hiding implementation details by restricting access to accessors (getters) and mutators(setters).</p>
<p>For TFS specifically, the following principle applies: All methods and variables <strong>are </strong>publicly available, but private access is marked with _ (underscore) prefix.</p>
<pre class="scroll"><code class="csharp">function MyClass()<br />{<br /> var _name = "ondrej"; //private member<br /> this.Age = calcAge(); //public member<br /> this.getName = function() { //public method<br /> return m_name;<br /> }<br /> <br /> function calcAge() { //private method<br /> return 10 + 10;<br /> }<br />}<br /> </code></pre>
<p>&nbsp;</p>
<p><strong>Polymorphism</strong></p>
<p>Polymorphism defines disparate behaviours and actions by objects to the same function invocation.</p>
<p>This is used in TFS extension development extensively when, for example overriding default _<strong>init </strong>method.</p>
<pre class="scroll"><code class="csharp">//note: we are using objects from previous samples<br />var p = new Parent();<br />var c = new Child();<br /> <br /> <br />p.getName(); //returns "Parent"<br />c.getName(); //returns "Child"</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Next time, we will look at the skeleton, or template if you will, of the TFS 2012 Web Access custom control.</p>]]></content:encoded>
    </item>
    <item>
      <title>TFS 2012 Web Access Customizations, Part 0: What is TFS Web Access?</title>
      <link>https://docs.microsoft.com/archive/blogs/ondrejstastny/tfs-2012-web-access-customizations-part-0-what-is-tfs-web-access</link>
      <pubDate>Sun, 25 Nov 2012 08:25:00 GMT</pubDate>
      <dc:creator><![CDATA[OndrejStastny]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ondrejstastny/2012/11/25/tfs-2012-web-access-customizations-part-0-what-is-tfs-web-access/</guid>
      <description><![CDATA[This is a first part in a series of posts that will get you jump started on developing custom...]]></description>
      <content:encoded><![CDATA[<p><span>This is a first part in a series of posts that will get you jump started on developing custom controls for Team Foundation Server 2012 Web Access. There is very little information or documentation on the subject, even internally in Microsoft. That is why I am hoping you will find this series helpful.</span></p>
<p><span>To start at the beginning, we will briefly discuss what TFS 2012 Web Access is and what it can do for you. This is&nbsp;by&nbsp;no means&nbsp;a comprehensive description but rather a simple introduction. You can read up more about it <a href="https://msdn.microsoft.com/en-gb/library/vstudio/ee523998.aspx"><span style="color: #0000ff;">here</span></a>.</span></p>
<p><span>After reading this article, you should be able to describe the features and capabilities of Web Access and understand the benefits for your organization.</span></p>
<p><span>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/0066.screen1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/0066.screen1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/0066.screen1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/0066.screen1.png" alt="" border="0" /></a></span></p>
<p>&nbsp;</p>
<p><span>When using TFS Web Access, you can plan, track and manage work items in Team Foundation Server without a need for a dedicated client application (Visual Studio, Test Professional&hellip;).</span></p>
<p><span>&nbsp;&nbsp;</span></p>
<p><span>Information presented to you in Web Access are mainly driven by two things. Permissions, which we will discuss later, and Process Templates, which dictate how work items look, what states they go through etc. In TFS, you have several process templates out-of the box. And of course you have the ability to create your own. In this article I only show the Scrum template. </span></p>
<p><span>First activity within your process should be creating product backlog items by using the team's product backlog page.</span></p>
<p><span>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/2664.screen2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/2664.screen2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/2664.screen2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/2664.screen2.png" alt="" border="0" /></a></span></p>
<p><span>&nbsp;</span></p>
<p><span>Next up, you ought to configure your team and team&rsquo;s capacity and schedule.</span></p>
<p><span>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/6355.screen3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/6355.screen3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/6355.screen3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/6355.screen3.png" alt="" border="0" /></a></span></p>
<p><span>&nbsp;</span></p>
<p><span>Using task board, you can drag items to different columns to conveniently change the status, update hours worked and add new tasks. The Task board is made to look as close as the physical board it represents and I find it very nice that you have the ability to work with the work items (tasks) same way you would had the board been physically available in your office.</span></p>
<p><span>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/0636.screen4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/0636.screen4.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/0636.screen4.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/0636.screen4.png" alt="" border="0" /></a></span></p>
<p><span>In TFS Web Access you also have a full access to work item queries. You can use existing queries you define in Visual Studio as well as create new ad hoc queries. </span></p>
<p><span>Then, you have full access to queried items and again, you can edit it or create new from within the Web Access.</span></p>
<p><span>This is where we focus the most in this series since this is where our custom controls will be displayed.</span></p>
<p><span>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/0247.screen5.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/0247.screen5.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/0247.screen5.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/0247.screen5.png" alt="" border="0" /></a></span></p>
<p><span>&nbsp;</span></p>
<p><span>From Web Access, you can also access TFS reports on Report Server, same way you would from Visual Studio.</span></p>
<p><span>&nbsp;</span></p>
<p><span>Other nice feature of Web Access is the ability to ask your stakeholders to evaluate the application and provide feedback.</span></p>
<p><span>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/5008.screen6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/5008.screen6.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/5008.screen6.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/5008.screen6.png" alt="" border="0" /></a></span></p>
<p><span>Important part of Web Access is also a Control Panel which is used to administer teams, permissions and extensions. It also provides work areas management and alerts configuration.</span></p>
<p><span>Work areas are used to split up large teams into smaller groups that have defined areas of operation. You could have one team focusing on the UI, other on the backend etc. This comes in handy come reporting time when you are given much clearer view on individual teams and the work they have done.</span></p>
<p><span>&nbsp;&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/6763.Picture7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/6763.Picture7.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/56/88/6763.Picture7.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-56-88/6763.Picture7.png" alt="" border="0" /></a></span></p>
<p><span>&nbsp;</span></p>
<p>&nbsp;</p>
<p><span>Your users will see certain features in Team Web Access by default. As a member of the&nbsp;<strong>Team Foundation Administrators</strong>&nbsp;group, you can change this default level of features for some or for all of your users, but you must have the appropriate level of licensing for those users.</span></p>
<ul>
<li><span><strong>Limited</strong>: This level of access restricts the user so that they can only view work items that they create in Team Web Access (also known as Work Item Only View). No other features, such as team pages, are available to users in this group. <strong>No client access license (CAL) is required </strong>for this level of Team Web Access.</span></li>
<li><span><strong>Standard</strong>: This is the default level of access in Team Web Access for your users. Members of this group can view all Team Web Access features except for: sprint planning and backlog views any of the features for requesting feedback from users and managing that feedback. <strong>A Team Foundation Server (TFS) CAL is required </strong>for all users with this level.</span></li>
<li><span><strong>Full</strong>: This level is reserved for users who are licensed to use all features available in Team Web Access, including the sprint planning and backlog management tools and the Request and Manage Feedback tools. To use these features, <strong>your user must be licensed</strong> for one of the following MSDN subscriptions: Visual Studio Test Professional with MSDN, Visual Studio Premium with MSDN, or Visual Studio Ultimate with MSDN. These MSDN subscriptions each include a TFS CAL for the subscriber.</span></li>
</ul>
<p>&nbsp;</p>
<p><span>Hope this overview was helpful to you. Next time, we will start getting into the development with reviewing some principles of Object Oriented Programming (OOP) and the way they are applied in JavaScript and TFS specifically.</span></p>]]></content:encoded>
    </item>
  </channel>
</rss>