Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 161825a
Showing
23 changed files
with
5,585 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
scripts/*.js | ||
*.vsix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"files.exclude": { | ||
"**/*.js": { | ||
"when": "$(basename).ts" | ||
}, | ||
"**/*.vsix": true, | ||
"*.gitignore": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// A task runner configuration. | ||
{ | ||
"version": "0.1.0", | ||
"command": "grunt", | ||
"isShellCommand": true, | ||
"tasks": [ | ||
{ | ||
"taskName": "build", | ||
"isBuildCommand": true, | ||
"problemMatcher": "$msCompile" | ||
}, | ||
{ | ||
"taskName": "publish", | ||
"isBuildCommand": false, | ||
"problemMatcher": "$msCompile" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## vsts-workitem-recentlyviewed ## | ||
|
||
Adds a group to the work item form showing who recently viewed the work item |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="utf-8" /> | ||
<script src="scripts/VSS.SDK.min.js"></script> | ||
<script src="scripts/moment.min.js"></script> | ||
<link rel="stylesheet" type="text/css" href="styles/RecentlyViewed.css"> | ||
</head> | ||
|
||
<body> | ||
<script type="text/javascript"> | ||
// Initialize framework | ||
VSS.init({ | ||
explicitNotifyLoaded: true, | ||
usePlatformScripts: true, | ||
configureModuleLoader: true | ||
}); | ||
|
||
// Load main entry point for extension | ||
VSS.require(["scripts/RecentlyViewed"], function (RecentlyViewed) { | ||
// Loading succeeded | ||
var recentlyViewedGroupView = new RecentlyViewed.RecentlyViewedGroupView(); | ||
recentlyViewedGroupView.initialize(); | ||
|
||
VSS.notifyLoadSucceeded(); | ||
}); | ||
</script> | ||
|
||
<div class="rv-full"></div> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
module.exports = function (grunt) { | ||
grunt.initConfig({ | ||
ts: { | ||
build: { | ||
src: ["scripts/**/*.ts"], | ||
tsconfig: true | ||
}, | ||
options: { | ||
fast: 'never' | ||
} | ||
}, | ||
exec: { | ||
package: { | ||
command: "tfx extension create --manifest-globs vss-extension.json", | ||
stdout: true, | ||
stderr: true | ||
}, | ||
publish: { | ||
command: "tfx extension publish --service-url https://marketplace.visualstudio.com --manifest-globs vss-extension.json", | ||
stdout: true, | ||
stderr: true | ||
} | ||
}, | ||
copy: { | ||
scripts: { | ||
files: [{ | ||
expand: true, | ||
flatten: true, | ||
src: ["node_modules/vss-web-extension-sdk/lib/VSS.SDK.min.js", "node_modules/moment/min/moment.min.js"], | ||
dest: "scripts", | ||
filter: "isFile" | ||
}] | ||
} | ||
}, | ||
|
||
clean: ["scripts/**/*.js", "*.vsix"] | ||
}); | ||
|
||
grunt.loadNpmTasks("grunt-ts"); | ||
grunt.loadNpmTasks("grunt-exec"); | ||
grunt.loadNpmTasks("grunt-contrib-copy"); | ||
grunt.loadNpmTasks('grunt-contrib-clean'); | ||
|
||
grunt.registerTask("build", ["ts:build", "copy:scripts"]); | ||
grunt.registerTask("package", ["build", "exec:package"]); | ||
grunt.registerTask("publish", ["default", "exec:publish"]); | ||
|
||
grunt.registerTask("default", ["package"]); | ||
}; |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"devDependencies": { | ||
"grunt": "~0.4.5", | ||
"grunt-cli": "^0.1.13", | ||
"grunt-contrib-clean": "^1.0.0", | ||
"grunt-contrib-copy": "~0.8.2", | ||
"grunt-exec": "~0.4.6", | ||
"tfx-cli": "^0.3.13", | ||
"tsd": "~0.6.5", | ||
"vss-web-extension-sdk": "^1.95.2", | ||
"moment": "*" | ||
}, | ||
"name": "vsts-workitem-recentlyviewed", | ||
"private": true, | ||
"version": "0.0.0", | ||
"dependencies": { | ||
"grunt-ts": "^5.3.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
## vsts-extension-workitem-activities ## | ||
|
||
VSTS Extension adds 'Activities' hub under Work group hub providing access to recent activites for work items | ||
|
||
This extension was boostrapped from https://cschleiden.wordpress.com/2016/02/24/extending-vsts-setup/. | ||
|
||
### Structure ### | ||
|
||
``` | ||
/scripts - Typescript code for extension | ||
/img - Image assets for extension and description | ||
/typings - Typescript typings | ||
details.md - Description to be shown in marketplace | ||
index.html - Main entry point | ||
vss-extension.json - Extension manifest | ||
``` | ||
|
||
### Usage ### | ||
|
||
1. Clone the repository | ||
1. `npm install` to install required dependencies | ||
2. `grunt` to build and package the application | ||
|
||
#### Grunt #### | ||
|
||
Three basic `grunt` tasks are defined: | ||
|
||
* `build` - Compiles TS files in `scripts` folder | ||
* `package` - Builds the vsix package | ||
* `publish` - Publishes the extension to the marketplace using `tfx-cli` | ||
|
||
Note: To avoid `tfx` prompting for your token when publishing, login in beforehand using `tfx login` and the service uri of ` https://app.market.visualstudio.com`. | ||
|
||
#### Including framework modules #### | ||
|
||
The VSTS framework is setup to initalize the requirejs AMD loader, so just use `import Foo = require("foo")` to include framework modules. | ||
|
||
#### VS Code #### | ||
|
||
The included `.vscode` config allows you to open and build the project using [VS Code](https://code.visualstudio.com/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="utf-8" /> | ||
<script src="scripts/VSS.SDK.min.js"></script> | ||
<script src="scripts/moment.min.js"></script> | ||
<link rel="stylesheet" type="text/css" href="styles/RecentlyViewed.css"> | ||
</head> | ||
|
||
<body> | ||
<script type="text/javascript"> | ||
// Initialize framework | ||
VSS.init({ | ||
explicitNotifyLoaded: true, | ||
usePlatformScripts: true, | ||
configureModuleLoader: true | ||
}); | ||
|
||
// Load main entry point for extension | ||
VSS.require(["scripts/RecentlyViewed"], function (RecentlyViewed) { | ||
// Loading succeeded | ||
var recentlyViewedGroupView = new RecentlyViewed.RecentlyViewedGroupView(); | ||
recentlyViewedGroupView.initialize(); | ||
|
||
VSS.notifyLoadSucceeded(); | ||
}); | ||
</script> | ||
|
||
<div class="rv-group"></div> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/// <reference path='../typings/moment/moment.d.ts' /> | ||
|
||
import Q = require("q"); | ||
import VSS_Service = require("VSS/Service"); | ||
import * as Utils_Core from "VSS/Utils/Core"; | ||
import {Control} from "VSS/Controls"; | ||
import {StatusIndicator} from "VSS/Controls/StatusIndicator"; | ||
import {CollapsiblePanel} from "VSS/Controls/Panels"; | ||
import * as WitClient from "TFS/WorkItemTracking/RestClient"; | ||
import {WorkItemUpdate} from "TFS/WorkItemTracking/Contracts"; | ||
import {WorkItemFormNavigationService} from "TFS/WorkItemTracking/Services"; | ||
import { WorkItemVisit, IdentityReference, Constants} from "scripts/Models"; | ||
import {manager} from "scripts/observer" | ||
|
||
|
||
export interface IRecentlyViewedListOptions { | ||
maxCount: number; | ||
} | ||
|
||
export class RecentlyViewedList extends Control<IRecentlyViewedListOptions> { | ||
private _visitsContainer: JQuery; | ||
private _currentWorkItemId: number; | ||
|
||
public initialize(): void { | ||
super.initialize(); | ||
|
||
// Initialize elements | ||
this._visitsContainer = $("<div/>").addClass("rv-container").appendTo(this.getElement()); | ||
} | ||
|
||
public initializeOptions(options: IRecentlyViewedListOptions) { | ||
this._options = options; | ||
} | ||
|
||
/* | ||
* Renders views | ||
* | ||
*/ | ||
public render(workItemId: number, visits: WorkItemVisit[]): void { | ||
|
||
// If we already rendered this work item no-op | ||
if(workItemId === this._currentWorkItemId) { | ||
return; | ||
} | ||
|
||
this._currentWorkItemId = workItemId; | ||
this._visitsContainer.empty(); | ||
|
||
if (visits && visits.length > 0) { | ||
|
||
|
||
// Pre-process the list to ensure that in the list views | ||
// we show an optimize version given the count limit | ||
// This entails trying to show unique values over repeated views | ||
|
||
let map = {}; | ||
let uniqueVisits = visits.reverse().filter((visit) =>{ | ||
if(map[visit.user.uniqueName] === undefined) { | ||
map[visit.user.uniqueName] = 0; | ||
return true; | ||
} else { | ||
map[visit.user.uniqueName] += 1; | ||
return false; | ||
} | ||
|
||
}); | ||
|
||
uniqueVisits = uniqueVisits.slice(0,this._options.maxCount); | ||
|
||
// Render filtered activities | ||
uniqueVisits.forEach((visit: WorkItemVisit) => { | ||
this._visitsContainer.append(this._createVisitRow(visit)); | ||
}); | ||
} | ||
} | ||
|
||
private _createVisitRow(visit: WorkItemVisit): JQuery { | ||
var $result = $("<div />").addClass("rv-visit"); | ||
|
||
// Image/Person | ||
var identityImageUrl = `${VSS.getWebContext().host.uri}/_api/_common/IdentityImage?id=`; | ||
identityImageUrl = `${identityImageUrl}&identifier=${visit.user.uniqueName}&identifierType=0`; | ||
var $visitedImageElement = $("<div/>").addClass("visited-image"); | ||
var $imageElement = $("<img/>").attr("src", identityImageUrl).appendTo($visitedImageElement); | ||
$result.append($visitedImageElement); | ||
|
||
|
||
var $userNameElement = $("<div class='visited-name' />").append(visit.user.name); | ||
$userNameElement.attr("title", visit.user.uniqueName); | ||
$imageElement.attr("title", visit.user.name); | ||
$result.append($userNameElement); | ||
|
||
|
||
|
||
|
||
// Visited date | ||
var dateMoment = moment(visit.date.toLocaleString()); | ||
var dateStringFromNow = dateMoment.fromNow(); | ||
var dateElem = $("<div />").addClass("visited-date").text(`${dateStringFromNow}`); | ||
dateElem.attr("title", dateMoment.format()); | ||
dateElem.appendTo($result); | ||
|
||
return $result; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
export class WorkItemVisit { | ||
public workItemId: number; | ||
public revision: number; | ||
public date: string; | ||
public user: UserContext; | ||
} | ||
|
||
export class IdentityReference { | ||
id: string; | ||
displayName: string; | ||
uniqueName: string; | ||
isIdentity: boolean; | ||
} | ||
|
||
export class Constants { | ||
public static StorageKey: string = "WorkItemVisits"; | ||
public static UtcRegex = /\d+-\d+-\d+T\d+:\d+:\d+\.\d+Z/; | ||
|
||
public static ExtensionPublisher = "mmanela"; | ||
public static ExtensionName = "vsts-workitem-recentlyviewed"; | ||
|
||
public static MaxVisitsToStore = 1000; | ||
|
||
public static GroupViewVisitCount = 4; | ||
} | ||
|
||
|
||
export function getStorageKey(workItemId: number){ | ||
return `TEMP2-${Constants.StorageKey}-${workItemId}`; | ||
} |
Oops, something went wrong.