Updated code to make build and deploy simpler
This commit is contained in:
Родитель
4dc20cc0c7
Коммит
6fefc16252
|
@ -1,5 +1,4 @@
|
|||
node_modules
|
||||
typings
|
||||
dist
|
||||
*.vsix
|
||||
*.log
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"public": false,
|
||||
"baseUri": "https://localhost:8080"
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"public": true,
|
||||
"files": [
|
||||
{
|
||||
"path": "src",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "libs",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "marketplace",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "img",
|
||||
"addressable": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -16,8 +16,8 @@
|
|||
.settings-control {
|
||||
margin-top: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.combo {
|
||||
width: 400px;
|
||||
}
|
||||
.settings-control .combo {
|
||||
width: 400px;
|
||||
}
|
До Ширина: | Высота: | Размер: 421 B После Ширина: | Высота: | Размер: 421 B |
До Ширина: | Высота: | Размер: 4.3 KiB После Ширина: | Высота: | Размер: 4.3 KiB |
|
@ -1,28 +0,0 @@
|
|||
var webpackConfig = require('./webpack.config');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['mocha', 'chai', 'sinon'],
|
||||
files: [
|
||||
'src/**/*.tests.ts'
|
||||
],
|
||||
exclude: [
|
||||
],
|
||||
preprocessors: {
|
||||
'src/**/*.tests.ts': ['webpack']
|
||||
},
|
||||
webpack: {
|
||||
module: webpackConfig.module,
|
||||
resolve: webpackConfig.resolve
|
||||
},
|
||||
reporters: ['mocha'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['PhantomJS'],
|
||||
singleRun: false,
|
||||
concurrency: Infinity
|
||||
})
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
49
package.json
49
package.json
|
@ -1,46 +1,15 @@
|
|||
{
|
||||
"description": "",
|
||||
"main": "webpack.config.js",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist *.vsix",
|
||||
"dev": "webpack-dev-server --hot --progress --colors --content-base ./src --https",
|
||||
"package:dev": "node ./scripts/packageDev",
|
||||
"publish:dev": "npm run package:dev && node ./scripts/publishDev",
|
||||
"build:release": "npm run clean && mkdir dist && webpack --progress --colors --output-path ./dist -p",
|
||||
"publish:release": "npm run build:release && node ./scripts/publishRelease",
|
||||
"dev:test": "karma start",
|
||||
"test": "karma start --single-run",
|
||||
"postinstall": "typings install"
|
||||
},
|
||||
"author": "Christopher Schleiden",
|
||||
"license": "MIT",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"chai": "^4.1.2",
|
||||
"copy-webpack-plugin": "^4.5.0",
|
||||
"css-loader": "^0.28.10",
|
||||
"cwd": "^0.10.0",
|
||||
"karma": "^1.7.1",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"karma-sinon": "^1.0.5",
|
||||
"karma-webpack": "^2.0.13",
|
||||
"mocha": "^4.1.0",
|
||||
"node-sass": "^4.7.2",
|
||||
"phantomjs-prebuilt": "^2.1.16",
|
||||
"rimraf": "^2.6.2",
|
||||
"sass-loader": "^6.0.7",
|
||||
"sinon": "^4.4.2",
|
||||
"style-loader": "^0.19.1",
|
||||
"tfx-cli": "^0.4.16",
|
||||
"ts-loader": "^3.5.0",
|
||||
"typescript": "^2.7.2",
|
||||
"typings": "^2.1.1",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-dev-server": "^2.11.2"
|
||||
"tfx-cli": "^0.6.3",
|
||||
"typescript": "^3.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "tsc -p .",
|
||||
"package": "tfx extension create"
|
||||
},
|
||||
"dependencies": {
|
||||
"vss-web-extension-sdk": "^2.117.0"
|
||||
"vss-web-extension-sdk": "^5.141.0"
|
||||
}
|
||||
}
|
||||
|
|
73
readme.md
73
readme.md
|
@ -5,16 +5,16 @@ WSJF enables a **calculated field** for computing and storing WSJF on your work
|
|||
|
||||
The [Scaled Agile Framework](http://www.scaledagileframework.com) defines [WSJF (Weighted Shortest Job First)](http://www.scaledagileframework.com/wsjf/) as a calculation of cost of delay vs. job size which can help teams prioritize their portfolio backlogs with the items contributing the highest ROI.
|
||||
|
||||
![WSJF = (Business Value + Time Criticality)/Job Size](http://www.scaledagileframework.com/wp-content/uploads/2014/07/Figure-2.-A-formula-for-calculating-WSJF.png)
|
||||
![WSJF = (Business Value + Time Criticality - Risk Reduction | Opportunity Enablement Value)/Job Size](http://www.scaledagileframework.com/wp-content/uploads/2014/07/Figure-2.-A-formula-for-calculating-WSJF.png)
|
||||
|
||||
Three values are used to calculate WSJF:
|
||||
Four values are used to calculate WSJF:
|
||||
* **Business Value**
|
||||
* **Risk Reduction | Opportunity Enablement Value**
|
||||
* **Time Criticality**
|
||||
* **Job Size**
|
||||
|
||||
# Setup
|
||||
1. The first thing you need is to create the field that will store the WSJF values. [Create a custom decimal field](https://www.visualstudio.com/en-us/docs/work/process/customize-process-field#add-a-custom-field) through the process hub and add it to the work items you want to display WSJF data on.
|
||||
1. The first thing you need is to create the fields that will store the RR-OE and WSJF values. [Create a custom decimal field](https://www.visualstudio.com/en-us/docs/work/process/customize-process-field#add-a-custom-field) through the process hub and add it to the work items you want to display WSJF data on.
|
||||
![WSJF displaying on the work item form](marketplace/CreateField.png)
|
||||
|
||||
*NOTE: If you're using TFS onprem, you need to use witadmin to [Create a custom decimal field](https://www.visualstudio.com/en-us/docs/work/customize/add-modify-field#to-add-a-custom-field)*
|
||||
|
@ -37,65 +37,20 @@ Three values are used to calculate WSJF:
|
|||
![Mapping fields for calculation](marketplace/Settings.gif)
|
||||
|
||||
## Support
|
||||
Because this extension requires the new work item form, it is only supported on VSTS and the next version of TFS (Dev15-RC1).
|
||||
|
||||
# Using the sample
|
||||
|
||||
This is an example for using relatively modern web dev technologies to build a VSTS (https://www.visualstudio.com) extension. In contrast to my other seed project and example (https://github.com/cschleiden/vsts-extension-ts-seed-simple and https://github.com/cschleiden/vsts-extension-tags-mru) which focused on simplicity, this sample aims to be more complete. It supports:
|
||||
|
||||
- Code written in Typescript/Styling defined using SASS
|
||||
- Publishing a dev version of an extension and a production one, without changing the manifest
|
||||
- Webpack for watching and building files during development, and for building optimized bundles for production
|
||||
- Unit tests of the core logic using mocha/chai
|
||||
- React for rendering a complex UI with user interation
|
||||
|
||||
## Building ##
|
||||
|
||||
This extension uses *webpack* for bundling, *webpack-dev-server* for watching files and serving bundles during development, *mocha*, *chai* for writing unit tests, and *karma* as a test runner.
|
||||
|
||||
Two bundles are defined for webpack, one for the main dialog, one for the extension context menu registration.
|
||||
|
||||
All actions can be triggered using npm scripts (`npm run <target>`), no additional task runner required.
|
||||
|
||||
### General setup ###
|
||||
|
||||
You need
|
||||
|
||||
* node/npm
|
||||
1. Download the .zip file from the [Master Branch](https://github.com/Microsoft/vsts-wsjf-extension/archive/master.zip)
|
||||
2. Extract to a local folder on your machine
|
||||
3. Open up a command prompt (or powershell) and change directory to your root folder *(ie. C:\ ... \vsts-wsjf-extension-master)*
|
||||
4. Run the command in command prompt: `npm update && npm install`
|
||||
|
||||
|
||||
*Note: Be sure to install npm in your root directory*
|
||||
|
||||
### Development (Local Instance of TFS) ###
|
||||
*These are solutions for running on a local instance of TFS **only**. If you build from these and push to a live server, they will not work*
|
||||
* Run `npm run publish:dev` to publish the current extension manifest to the marketplace as a private extension with a suffix of `-dev` added to the extension id. This package will use a baseUri of `https://localhost:8080`.
|
||||
* Run `npm run dev` to start a webpack development server that watches all source files. Tests live next to product code and use a `.tests.ts` suffix instead of only `.ts`.
|
||||
* To run a single test pass execute `npm run test`, to keep watching tests and build/execute as you develop execute `npm run dev:test`.
|
||||
|
||||
### Production (Live TFS Server) ###
|
||||
|
||||
*Pushing to a live TFS Server instance*
|
||||
|
||||
1. Run `npm run publish:release` to compile all modules into bundles, package them into a .vsix, and publish as a *public* extension to the VSTS marketplace.
|
||||
Because this extension requires the new work item form, it is only supported on Azure DevOps and the next version of TFS 2018 and above.
|
||||
|
||||
*NOTE: You may get an error on the publish part, however your .vsix file should be in your root to manually upload to your TFS Server if you have not setup a marketplace*
|
||||
### Adding RROE and WSJF Score Values (For TFS) ###
|
||||
|
||||
### Adding RROE and WSJF Score Values (For Non-VSTS) ###
|
||||
|
||||
1. Export your WorkItem.XML file *(ie. Epic.XML)* using either [Visual Studio Powertools](https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.ProductivityPowerPack2017) or [WITAdmin](https://docs.microsoft.com/en-us/vsts/work/customize/reference/witadmin/witadmin-import-export-manage-wits?view=tfs-2018)
|
||||
1. Export your WorkItem.XML file *(ie. Epic.XML)* using [WITAdmin](https://docs.microsoft.com/en-us/Azure DevOps/work/customize/reference/witadmin/witadmin-import-export-manage-wits?view=tfs-2018)
|
||||
2. At the bottom of your "Fields" section add the following (Name and reference names may vary):
|
||||
|
||||
``` xml
|
||||
<FIELD name="WSJF Risk-Reduction Opportunity-Enablement" refname="WSFJ.RROEValue" type="Integer" reportable="dimension">
|
||||
<HELPTEXT> WSJF Risk-Reduction </HELPTEXT>
|
||||
<FIELD name="WSJF Risk-Reduction Opportunity-Enablement" refname="WSJF.RROEValue" type="Integer" reportable="dimension">
|
||||
<HELPTEXT>WSJF Risk-Reduction</HELPTEXT>
|
||||
</FIELD>
|
||||
|
||||
<FIELD name="WSJF Score" refname="WSJF.Score" type="Double" reportable="dimension">
|
||||
<HELPTEXT> WSJF Score </HELPTEXT>
|
||||
<HELPTEXT>WSJF Score</HELPTEXT>
|
||||
</FIELD>
|
||||
```
|
||||
3. Under your
|
||||
|
@ -104,17 +59,13 @@ You need
|
|||
```xml
|
||||
<Section>
|
||||
<Group Label="WSJF">
|
||||
<Control Label="User-Business Value" Type="FieldControl" FieldName="Microsoft.VSTS.Common.BusinessValue" EmptyText="[Numbered Value]" />
|
||||
<Control Label="Urgency/Time Criticality" Type="FieldControl" FieldName="Microsoft.VSTS.Common.TimeCriticality" EmptyText="[Numbered Value]" />
|
||||
<Control Label="User-Business Value" Type="FieldControl" FieldName="Microsoft.Azure DevOps.Common.BusinessValue" EmptyText="[Numbered Value]" />
|
||||
<Control Label="Urgency/Time Criticality" Type="FieldControl" FieldName="Microsoft.Azure DevOps.Common.TimeCriticality" EmptyText="[Numbered Value]" />
|
||||
<Control Label="Risk Reduction/Opportunity Enablement" Type="FieldControl" FieldName="WSJF.RROEValue" EmptyText="[Numbered Value]" />
|
||||
<Control Label="Size" Type="FieldControl" FieldName="Microsoft.VSTS.Scheduling.Effort" EmptyText="[Numbered Value]" />
|
||||
<Control Label="Size" Type="FieldControl" FieldName="Microsoft.Azure DevOps.Scheduling.Effort" EmptyText="[Numbered Value]" />
|
||||
<Control Label="WSJF Score" Type="FieldControl" FieldName="WSJF.Value" EmptyText="[Numbered Value]" />
|
||||
</Group>
|
||||
</Section>
|
||||
```
|
||||
4. After this is done, open up your WSJF tab and adjust your settings:
|
||||
![Mapping fields for calculation](marketplace/Settings.png)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
var exec = require("child_process").exec;
|
||||
|
||||
// Load existing publisher
|
||||
var manifest = require("../vss-extension.json");
|
||||
var extensionId = manifest.id;
|
||||
|
||||
// Package extension
|
||||
var command = `tfx extension create --overrides-file configs/dev.json --manifest-globs vss-extension.json --extension-id ${extensionId}-dev --no-prompt`;
|
||||
exec(command, function() {
|
||||
console.log("Package created");
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
var exec = require("child_process").exec;
|
||||
|
||||
var manifest = require("../vss-extension.json");
|
||||
var extensionId = manifest.id;
|
||||
var extensionPublisher = manifest.publisher;
|
||||
var extensionVersion = manifest.version;
|
||||
|
||||
// Package extension
|
||||
var command = `tfx extension publish --vsix ${extensionPublisher}.${extensionId}-dev-${extensionVersion}.vsix --no-prompt`;
|
||||
exec(command, function() {
|
||||
console.log("Package published.");
|
||||
});
|
|
@ -1,52 +0,0 @@
|
|||
//"use strict";
|
||||
|
||||
var exec = require("child_process").exec;
|
||||
//var cwd = require('cwd');
|
||||
//var path = require('path');
|
||||
|
||||
// Package extension
|
||||
var command = `tfx extension create --overrides-file release.json --manifest-globs vss-extension-release.json --no-prompt --json`;
|
||||
//var pkg = File.join(cwd, '');
|
||||
//var test = `system("cd")`;
|
||||
|
||||
//exec(test, stdout => {
|
||||
// console.log(`${stdout}`);
|
||||
//});
|
||||
|
||||
//var outputPath = "";
|
||||
|
||||
//exec('cd', (err, stdout, stderr) => {
|
||||
// if (err) {
|
||||
// // node couldn't execute the command
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // the *entire* stdout and stderr (buffered)
|
||||
// console.log(`stdout: ${stdout}`);
|
||||
// console.log(`stderr: ${stderr}`);
|
||||
// outputPath = `${stdout}/dist`
|
||||
//});
|
||||
|
||||
exec(command, {
|
||||
"cwd": "./dist"
|
||||
// outputPath
|
||||
}, (error, stdout) => {
|
||||
if (error) {
|
||||
console.error(`Could not create package: '${error}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
let output = JSON.parse(stdout);
|
||||
|
||||
console.log(`Package created ${output.path}`);
|
||||
|
||||
var command = `tfx extension publish --vsix ${output.path} --no-prompt`;
|
||||
exec(command, (error, stdout) => {
|
||||
if (error) {
|
||||
console.error(`Could not create package: '${error}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Package published.");
|
||||
});
|
||||
});
|
20
src/wsjf.tsx
20
src/wsjf.tsx
|
@ -1,8 +1,10 @@
|
|||
import Q = require("q");
|
||||
import WIT_Client = require("TFS/WorkItemTracking/RestClient");
|
||||
import Contracts = require("TFS/WorkItemTracking/Contracts");
|
||||
import {IWorkItemFormService, WorkItemFormService} from "TFS/WorkItemTracking/Services";
|
||||
import { StoredFieldReferences } from "wsjfModels";
|
||||
|
||||
import TFS_Wit_Contracts = require("TFS/WorkItemTracking/Contracts");
|
||||
import TFS_Wit_Client = require("TFS/WorkItemTracking/RestClient");
|
||||
import TFS_Wit_Services = require("TFS/WorkItemTracking/Services");
|
||||
|
||||
import { StoredFieldReferences } from "./wsjfModels";
|
||||
|
||||
function GetStoredFields(): IPromise<any> {
|
||||
var deferred = Q.defer();
|
||||
|
@ -22,12 +24,12 @@ function GetStoredFields(): IPromise<any> {
|
|||
|
||||
function getWorkItemFormService()
|
||||
{
|
||||
return WorkItemFormService.getService();
|
||||
return TFS_Wit_Services.WorkItemFormService.getService();
|
||||
}
|
||||
|
||||
function updateWSJFOnForm(storedFields:StoredFieldReferences) {
|
||||
getWorkItemFormService().then((service) => {
|
||||
service.getFields().then((fields: Contracts.WorkItemField[]) => {
|
||||
service.getFields().then((fields: TFS_Wit_Contracts.WorkItemField[]) => {
|
||||
var matchingBusinessValueFields = fields.filter(field => field.referenceName === storedFields.bvField);
|
||||
var matchingTimeCriticalityFields = fields.filter(field => field.referenceName === storedFields.tcField);
|
||||
var matchingRROEValueFields = fields.filter(field => field.referenceName === storedFields.rvField);
|
||||
|
@ -69,8 +71,8 @@ function updateWSJFOnGrid(workItemId, storedFields:StoredFieldReferences):IPromi
|
|||
|
||||
var deferred = Q.defer();
|
||||
|
||||
var client = WIT_Client.getClient();
|
||||
client.getWorkItem(workItemId, wsjfFields).then((workItem: Contracts.WorkItem) => {
|
||||
var client = TFS_Wit_Client.getClient();
|
||||
client.getWorkItem(workItemId, wsjfFields).then((workItem: TFS_Wit_Contracts.WorkItem) => {
|
||||
if (storedFields.wsjfField !== undefined && storedFields.rvField !== undefined) {
|
||||
var businessValue = +workItem.fields[storedFields.bvField];
|
||||
var timeCriticality = +workItem.fields[storedFields.tcField];
|
||||
|
@ -91,7 +93,7 @@ function updateWSJFOnGrid(workItemId, storedFields:StoredFieldReferences):IPromi
|
|||
|
||||
// Only update the work item if the WSJF has changed
|
||||
if (wsjf != workItem.fields[storedFields.wsjfField]) {
|
||||
client.updateWorkItem(document, workItemId).then((updatedWorkItem:Contracts.WorkItem) => {
|
||||
client.updateWorkItem(document, workItemId).then((updatedWorkItem:TFS_Wit_Contracts.WorkItem) => {
|
||||
deferred.resolve(updatedWorkItem);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import "./wsjfSettings.scss";
|
||||
|
||||
import Q = require("q");
|
||||
import Controls = require("VSS/Controls");
|
||||
import {Combo, IComboOptions} from "VSS/Controls/Combos";
|
||||
|
@ -7,7 +5,8 @@ import Menus = require("VSS/Controls/Menus");
|
|||
import WIT_Client = require("TFS/WorkItemTracking/RestClient");
|
||||
import Contracts = require("TFS/WorkItemTracking/Contracts");
|
||||
import Utils_string = require("VSS/Utils/String");
|
||||
import { StoredFieldReferences } from "wsjfModels";
|
||||
|
||||
import { StoredFieldReferences } from "./wsjfModels";
|
||||
|
||||
export class Settings {
|
||||
private _changeMade = false;
|
||||
|
@ -90,7 +89,7 @@ export class Settings {
|
|||
header = $("<div />").addClass("description-text bowtie").appendTo(hubContent);
|
||||
header.html(Utils_string.format(descriptionText));
|
||||
|
||||
$("<img src='http://www.scaledagileframework.com/wp-content/uploads/2014/07/Figure-2.-A-formula-for-calculating-WSJF.png' />").addClass("description-image").appendTo(hubContent);
|
||||
$("<img src='https://www.scaledagileframework.com/wp-content/uploads/2014/07/Figure-2.-A-formula-for-calculating-WSJF.png' />").addClass("description-image").appendTo(hubContent);
|
||||
|
||||
descriptionText = "You must add a custom decimal field from the {0} to each work item type you wish to compute WSJF.";
|
||||
header = $("<div />").addClass("description-text bowtie").appendTo(hubContent);
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "amd",
|
||||
"sourceMap": false
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": false,
|
||||
"jsx": "react",
|
||||
"outDir": "dist",
|
||||
"types": [
|
||||
"vss-web-extension-sdk"
|
||||
]
|
||||
},
|
||||
"filesGlob": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"typings/index.d.ts"
|
||||
"include": [
|
||||
"src/**/*.tsx"
|
||||
]
|
||||
}
|
13
typings.json
13
typings.json
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"globalDependencies": {
|
||||
"jquery": "registry:dt/jquery#1.10.0+20160316155526",
|
||||
"knockout": "registry:dt/knockout#0.0.0+20160409112158",
|
||||
"mocha": "registry:env/mocha#2.2.5+20160321223601",
|
||||
"q": "registry:dt/q#0.0.0+20160323171452",
|
||||
"tfs": "npm:vss-web-extension-sdk/typings/tfs.d.ts",
|
||||
"vss": "npm:vss-web-extension-sdk/typings/vss.d.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"chai": "registry:npm/chai#3.5.0+20160415060238"
|
||||
}
|
||||
}
|
|
@ -1,47 +1,23 @@
|
|||
{
|
||||
"public": false,
|
||||
"manifestVersion": 1,
|
||||
"version": "1.0.0",
|
||||
"name": "WSJF (Weighted Shortest Job First)",
|
||||
"scopes": [ "vso.work", "vso.work_write" ],
|
||||
"description": "Auto calculates WSJF (weighted shortest job first) per work item and stores it in a work item field.",
|
||||
"publisher": "MS-Agile-SAFe",
|
||||
"id": "WSJF-extension",
|
||||
"icons": {
|
||||
"default": "marketplace/logo.png"
|
||||
},
|
||||
"publisher": "MS-Agile-SAFe",
|
||||
"version": "1.2.0",
|
||||
"name": "WSJF (Weighted Shortest Job First)",
|
||||
"description": "Auto calculates WSJF (weighted shortest job first) per work item and stores it in a work item field.",
|
||||
"categories": [ "Azure Boards" ],
|
||||
"tags": [
|
||||
"WSJF",
|
||||
"SAFe"
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"id": "Microsoft.VisualStudio.Services"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Work Items", "WSJF", "SAFe", "Agile", "Backlog", "Stack rank"
|
||||
],
|
||||
"content": {
|
||||
"details": {
|
||||
"path": "marketplace/details.md"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"learn": {
|
||||
"uri": "https://github.com/Microsoft/vsts-wsjf-extension"
|
||||
},
|
||||
"support": {
|
||||
"uri": "mailto:jmarks@microsoft.com"
|
||||
}
|
||||
},
|
||||
"branding": {
|
||||
"color": "rgb(220, 235, 252)",
|
||||
"theme": "light"
|
||||
},
|
||||
"categories": [
|
||||
"Plan and track"
|
||||
],
|
||||
"demands" : [
|
||||
"api-version/3.0"
|
||||
],
|
||||
"contributions": [
|
||||
{
|
||||
{
|
||||
"id": "wsjf-work-item-form-observer",
|
||||
"type": "ms.vss-work-web.work-item-notifications",
|
||||
"description": "Update the 'WSJF' field when other fields on the form change.",
|
||||
|
@ -49,7 +25,7 @@
|
|||
"ms.vss-work-web.work-item-form"
|
||||
],
|
||||
"properties": {
|
||||
"uri": "src/wsjf.html"
|
||||
"uri": "wsjf.html"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -61,7 +37,7 @@
|
|||
],
|
||||
"properties": {
|
||||
"name": "WSJF",
|
||||
"uri": "src/wsjfSettings.html"
|
||||
"uri": "wsjfSettings.html"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -73,12 +49,67 @@
|
|||
],
|
||||
"properties": {
|
||||
"text": "Recalculate WSJF values",
|
||||
"title": "Update the WSJF value for the selected work items",
|
||||
"icon": "img/icon-refresh.png",
|
||||
"title": "Update the WSJF value for the selected work items",
|
||||
"icon": "images/icon-refresh.png",
|
||||
"groupId": "SAFe",
|
||||
"uri": "src/wsjf.html"
|
||||
"uri": "wsjf.html"
|
||||
}
|
||||
}
|
||||
],
|
||||
"files": []
|
||||
"files": [
|
||||
{
|
||||
"path": "css",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "images",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "dist",
|
||||
"addressable": true,
|
||||
"packagePath": "scripts"
|
||||
},
|
||||
{
|
||||
"path": "wsjf.html",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "wsjfSettings.html",
|
||||
"addressable": true
|
||||
},
|
||||
{
|
||||
"path": "node_modules/vss-web-extension-sdk/lib",
|
||||
"addressable": true,
|
||||
"packagePath": "lib"
|
||||
}
|
||||
],
|
||||
"scopes": [
|
||||
"vso.work",
|
||||
"vso.work_write"
|
||||
],
|
||||
"icons": {
|
||||
"default": "images/logo.png"
|
||||
},
|
||||
"content": {
|
||||
"details": {
|
||||
"path": "marketplace/details.md"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"support": {
|
||||
"uri": "mailto:jmarks@microsoft.com"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"uri": "https://github.com/Microsoft/vsts-wsjf-extension"
|
||||
},
|
||||
"branding": {
|
||||
"color": "rgb(220, 235, 252)",
|
||||
"theme": "light"
|
||||
},
|
||||
"demands": [
|
||||
"api-version/3.0"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
var path = require("path");
|
||||
var webpack = require("webpack");
|
||||
var CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
target: "web",
|
||||
entry: {
|
||||
wsjf: "./src/wsjf.tsx",
|
||||
wsjfSettings: "./src/wsjfSettings.tsx"
|
||||
},
|
||||
output: {
|
||||
filename: "src/[name].js",
|
||||
libraryTarget: "amd"
|
||||
},
|
||||
externals: [
|
||||
/^VSS\/.*/, /^TFS\/.*/, /^q$/
|
||||
],
|
||||
resolve: {
|
||||
extensions: [
|
||||
".webpack.js",
|
||||
".web.js",
|
||||
".ts",
|
||||
".tsx",
|
||||
".js"]
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: "ts-loader"
|
||||
},
|
||||
{
|
||||
test: /\.s?css$/,
|
||||
loaders: ["style-loader", "css-loader", "sass-loader"]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
{ from: "./node_modules/vss-web-extension-sdk/lib/VSS.SDK.min.js", to: "libs/VSS.SDK.min.js" },
|
||||
{ from: "./src/*.html", to: "./" },
|
||||
{ from: "./marketplace", to: "marketplace" },
|
||||
{ from: "./img", to: "img" },
|
||||
{ from: "./vss-extension.json", to: "vss-extension-release.json" },
|
||||
{ from: "./configs/release.json", to: "release.json" }
|
||||
])
|
||||
]
|
||||
}
|
|
@ -3,19 +3,18 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script src="../libs/VSS.SDK.min.js"></script>
|
||||
<script src="lib/VSS.SDK.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
// Initialize framework
|
||||
VSS.init({
|
||||
explicitNotifyLoaded: true,
|
||||
usePlatformScripts: true,
|
||||
configureModuleLoader: true
|
||||
usePlatformScripts: true
|
||||
});
|
||||
|
||||
// Load main entry point for extension
|
||||
VSS.require(["src/wsjf"], function () {
|
||||
VSS.require(["scripts/wsjf"], function () {
|
||||
// Loading succeeded
|
||||
VSS.notifyLoadSucceeded();
|
||||
});
|
|
@ -3,19 +3,20 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script src="../libs/VSS.SDK.min.js"></script>
|
||||
<script src="lib/VSS.SDK.min.js"></script>
|
||||
|
||||
<link href="css/wsjfSettings.css" rel="stylesheet"></link>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
// Initialize framework
|
||||
VSS.init({
|
||||
explicitNotifyLoaded: true,
|
||||
usePlatformScripts: true,
|
||||
configureModuleLoader: true
|
||||
usePlatformScripts: true
|
||||
});
|
||||
|
||||
|
||||
// Load main entry point for extension
|
||||
VSS.require(["src/wsjfSettings"], function (s) {
|
||||
VSS.require(["scripts/wsjfSettings"], function (s) {
|
||||
var settings = new s.Settings();
|
||||
settings.initialize();
|
||||
});
|
||||
|
@ -25,6 +26,6 @@
|
|||
<div class="hub-title">Settings</div>
|
||||
|
||||
<div class="hub-content" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче