我假设您正在使用 Story Deep Copy 应用程序。从您的问题来看,您似乎已经为从中复制的项目修改了 hangman 变量。假设该项目的 OID 是 22222,而您要复制的目标项目的 OID 是 33333。这两个项目都在同一个工作区中,OID 为 11111。
var dataSource = new rally.sdk.data.RallyDataSource('11111', '22222',
'__PROJECT_SCOPING_UP__', '__PROJECT_SCOPING_DOWN__');
我在中添加了一行this._copyStory
:
foundObject.Project._ref = "https://rally1.rallydev.com/slm/webservice/1.29/project/33333.js";
这是整个代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">
<head>
<title>Deep Copy Story</title>
<meta name="Name" content="App: Story Deep Copy"/>
<meta name="Version" content="2012.01.14"/>
<meta name="Vendor" content="Rally Software"/>
<script type="text/javascript" src="/apps/1.29/sdk.js?apiVersion=1.29"></script>
<script type="text/javascript">
rally.StoryDeepCopy = function (rallyDataSource, config) {
var storyBuffer = [];
var firstStory = null;
var finishedCallback;
var that = this;
function getTypeFromRef(ref) {
if (rally.sdk.util.Ref.isRef(ref)) {
var list = ref.split("/");
list.pop();
return list.pop();
}
else {
throw "Function getTypeFromRef expected a Rally Reference.";
}
}
//dojo.connect(obj, event, context, method, dontFix);
this._fireEvent = function(eventName, eventArgs) {
if (config && config.eventListeners[eventName] && dojo.isFunction(config.eventListeners[eventName])) {
config.eventListeners[eventName](that, eventArgs);
}
};
// removes private and read only fields to keep from pushing them up.
this.filterObject = function (object) {
delete object.Discussion;
delete object.Rank;
delete object.LastUpdateDate;
delete object.Attachments;
delete object.AcceptedDate;
delete object.Blocker;
delete object.Defects;
delete object.TaskActualTotal;
delete object.TaskEstimateTotal;
delete object.TaskRemainingTotal;
delete object.TaskEstimateTotal;
delete object.RevisionHistory;
delete object.Subscription;
delete object.FormattedID;
delete object.CreationDate;
delete object.Changesets;
delete object.ObjectID;
for (var j in object) {
if (j.substring(0, 1) == '_') {
delete object[j];
}
}
return object;
};
this._addObject = function(object, typeName, callback) {
var item = dojo.clone(object);
item = this.filterObject(item);
function errorFunctionWrapper(error) {
if (dojo.isArray(error.Errors)) {
var errorMessage = error.Errors.pop();
if (errorMessage.indexOf("Not authorized to create:") >= 0) {
errorMessage = "Unable to create an object. This can happen due to a child or task being in a project you do not have write permissions to.";
}
rally.sdk.ui.AppHeader.showMessage("error", errorMessage, 10000);
}
else if(dojo.isObject(error)&&error.message){
rally.sdk.ui.AppHeader.showMessage("error", error.message, 10000);
error = [error.message];
}
if (dojo.isFunction(config.onError)) {
config.onError(error);
}
}
rallyDataSource.create(typeName, item, callback, errorFunctionWrapper);
};
this._copyAllFromBuffer = function() {
if (storyBuffer.length > 0) {
var story = storyBuffer.pop();
that._copyStory(story.ref, story.parent, that._copyAllFromBuffer);
}
else {
if (finishedCallback) {
finishedCallback(firstStory);
}
}
};
this._addStoriesToBuffer = function(storyArray, parentRef) {
dojo.forEach(storyArray, function (story) {
storyBuffer.push({
ref: story._ref,
parent: parentRef
});
});
};
this._copyStory = function(ref, parentRef, callback) {
rallyDataSource.getRallyObject(ref, function (foundObject) {
var type = getTypeFromRef(ref);
that._fireEvent("storyPreAdd", {story:foundObject});
console.log(foundObject.Name);
console.log(foundObject.Project._ref);
foundObject.Project._ref = "https://rally1.rallydev.com/slm/webservice/1.29/project/33333.js";
if (parentRef) {
foundObject.Parent = parentRef;
}
else {
foundObject.Name = "(Copy of) " + foundObject.Name;
}
that._addObject(foundObject, type, function (storyRef) {
if (!firstStory) {
firstStory = storyRef;
}
that._fireEvent("storyPostAdd", {});
that._addStoriesToBuffer(foundObject.Children, storyRef);
that._copyTasksToStory(foundObject.Tasks, storyRef, callback);
}, null);
});
};
this._copyTasksToStory = function(tasks, storyRef, callback) {
//Copy the array
var localTasks = tasks.slice(0);
if (localTasks.length > 0) {
var task = localTasks.pop();
that._copyTask(task._ref, storyRef, function () {
that._copyTasksToStory(localTasks, storyRef, callback);
});
}
else {
callback();
}
};
this._copyTask = function(ref, storyRef, callback) {
rallyDataSource.getRallyObject(ref, function (foundObject) {
var type = getTypeFromRef(ref);
foundObject.WorkProduct = storyRef;
that._fireEvent("taskPreAdd", {task:foundObject});
that._addObject(foundObject, type, function (ref, warnings) {
if (callback) {
that._fireEvent("taskPostAdd", [ref]);
callback();
}
}, null);
});
};
this.copyStory = function (ref, callback) {
that._copyStory(ref, undefined, that._copyAllFromBuffer);
finishedCallback = callback;
};
};
</script>
<script type="text/javascript">
rally.addOnLoad(function() {
var selectedValue = null;
var tasksAdded = 0;
var storiesAdded = 0;
var searchStories;
var goButton, chooseButton;
var chooser;
var waiter;
var dataSource = new rally.sdk.data.RallyDataSource('111111', '2222222',
'__PROJECT_SCOPING_UP__', '__PROJECT_SCOPING_DOWN__');
function taskPostAdd(object, args) {
tasksAdded = tasksAdded + 1;
displayTasksAdded(tasksAdded);
}
function taskPreAdd(object, args) {
dojo.byId("currentInfo").innerHTML = "Adding Task " + args.task.FormattedID + " - " + args.task.Name;
}
function storyPreAdd(object, args) {
dojo.byId("currentInfo").innerHTML = "Adding User Story " + args.story.FormattedID + " - " + args.story.Name;
}
function storyPostAdd(object, args) {
storiesAdded = storiesAdded + 1;
displayStoriesAdded(storiesAdded);
}
function displayStoriesAdded(count) {
dojo.byId("storyResult").innerHTML = "Stories added: " + count;
}
function displayTasksAdded(count) {
dojo.byId("taskResult").innerHTML = "Tasks added: " + tasksAdded;
}
function storyCopied(story) {
dojo.byId("currentInfo").innerHTML = "Copy complete: ";
var link = new rally.sdk.ui.basic.Link({
item: story,
text: story._refObjectName
});
link.display('currentInfo');
goButton.setEnabled(true);
chooseButton.setEnabled(true);
if(waiter) {
waiter.hide();
waiter = null;
}
}
function buttonPressed() {
if (selectedValue) {
var config = {
eventListeners:{
storyPreAdd:storyPreAdd,
storyPostAdd:storyPostAdd ,
taskPreAdd:taskPreAdd,
taskPostAdd: taskPostAdd
}
};
tasksAdded = 0;
displayTasksAdded(tasksAdded);
storiesAdded = 0;
displayStoriesAdded(storiesAdded);
dojo.byId("currentInfo").innerHTML = "";
var copy = new rally.StoryDeepCopy(dataSource, config);
goButton.setEnabled(false);
chooseButton.setEnabled(false);
waiter = new rally.sdk.ui.basic.Wait({});
waiter.display('wait');
copy.copyStory(rally.sdk.util.Ref.getRelativeRef(selectedValue), storyCopied);
}
}
function onChooserClose(chooser, args) {
if (args.selectedItem) {
selectedValue = args.selectedItem;
goButton.setEnabled(true);
dojo.byId('storyBox').innerHTML = args.selectedItem.FormattedID + ' - ' +
args.selectedItem.Name;
}
}
function showChooser() {
var chooserConfig = {
fetch:"FormattedID,Name,Description,Project",
title: 'Story Chooser'
};
chooser = new rally.sdk.ui.Chooser(chooserConfig, dataSource);
chooser.addEventListener('onClose', onChooserClose);
chooser.display();
}
rally.addOnLoad(function () {
goButton = new rally.sdk.ui.basic.Button({
text: "Copy",
enabled: false
});
goButton.addEventListener('onClick', buttonPressed);
goButton.display('goButton');
chooseButton = new rally.sdk.ui.basic.Button({
text: "Choose"
});
chooseButton.addEventListener('onClick', showChooser);
chooseButton.display('chooseButton');
showChooser();
rally.sdk.ui.AppHeader.setHelpTopic("252");
});
});
</script>
</head>
<body>
<div id="container">
<div style="float:left">
<span id="chooseButton"></span>
<span id="storyBox" style="line-height:18px;vertical-align:middle">[No story selected]</span>
<span id="goButton"></span>
</div>
<div id="wait" style="float:left; height: 16px; width: 24px;"></div>
<div style="margin-left:5px;padding-top:10px;clear:both">
<div id="currentInfo" style="height:16px"></div>
<div id="storyResult" style="margin-top:10px"></div>
<div id="taskResult"></div>
</div>
</div>
</body>
</html>
编辑:上面的代码已修改为使用从中选择目标项目的对象下拉列表。因此,无需对目标项目的引用进行硬编码。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">
<head>
<title>Deep Copy Story</title>
<meta name="Name" content="App: Story Deep Copy"/>
<meta name="Version" content="2012.01.14"/>
<meta name="Vendor" content="Rally Software"/>
<script type="text/javascript" src="/apps/1.29/sdk.js?apiVersion=1.29"></script>
<script type="text/javascript">
rally.StoryDeepCopy = function (rallyDataSource, config) {
var storyBuffer = [];
var firstStory = null;
var finishedCallback;
var that = this;
function getTypeFromRef(ref) {
if (rally.sdk.util.Ref.isRef(ref)) {
var list = ref.split("/");
list.pop();
return list.pop();
}
else {
throw "Function getTypeFromRef expected a Rally Reference.";
}
}
//dojo.connect(obj, event, context, method, dontFix);
this._fireEvent = function(eventName, eventArgs) {
if (config && config.eventListeners[eventName] && dojo.isFunction(config.eventListeners[eventName])) {
config.eventListeners[eventName](that, eventArgs);
}
};
// removes private and read only fields to keep from pushing them up.
this.filterObject = function (object) {
delete object.Discussion;
delete object.Rank;
delete object.LastUpdateDate;
delete object.Attachments;
delete object.AcceptedDate;
delete object.Blocker;
delete object.Defects;
delete object.TaskActualTotal;
delete object.TaskEstimateTotal;
delete object.TaskRemainingTotal;
delete object.TaskEstimateTotal;
delete object.RevisionHistory;
delete object.Subscription;
delete object.FormattedID;
delete object.CreationDate;
delete object.Changesets;
delete object.ObjectID;
for (var j in object) {
if (j.substring(0, 1) == '_') {
delete object[j];
}
}
return object;
};
this._addObject = function(object, typeName, callback) {
var item = dojo.clone(object);
console.log(item);
item = this.filterObject(item);
function errorFunctionWrapper(error) {
if (dojo.isArray(error.Errors)) {
var errorMessage = error.Errors.pop();
if (errorMessage.indexOf("Not authorized to create:") >= 0) {
errorMessage = "Unable to create an object. This can happen due to a child or task being in a project you do not have write permissions to.";
}
rally.sdk.ui.AppHeader.showMessage("error", errorMessage, 10000);
}
else if(dojo.isObject(error)&&error.message){
rally.sdk.ui.AppHeader.showMessage("error", error.message, 10000);
error = [error.message];
}
if (dojo.isFunction(config.onError)) {
config.onError(error);
}
}
rallyDataSource.create(typeName, item, callback, errorFunctionWrapper);
};
this._copyAllFromBuffer = function() {
if (storyBuffer.length > 0) {
var story = storyBuffer.pop();
that._copyStory(story.ref, story.parent, that._copyAllFromBuffer);
}
else {
if (finishedCallback) {
finishedCallback(firstStory);
}
}
};
this._addStoriesToBuffer = function(storyArray, parentRef) {
dojo.forEach(storyArray, function (story) {
storyBuffer.push({
ref: story._ref,
parent: parentRef
});
});
};
this._copyStory = function(ref, parentRef, callback) {
rallyDataSource.getRallyObject(ref, function (foundObject) {
var type = getTypeFromRef(ref);
that._fireEvent("storyPreAdd", {story:foundObject});
foundObject.Project._ref = destinationProject;
if (parentRef) {
foundObject.Parent = parentRef;
}
else {
foundObject.Name = "(Copy of) " + foundObject.Name;
}
that._addObject(foundObject, type, function (storyRef) {
if (!firstStory) {
firstStory = storyRef;
}
that._fireEvent("storyPostAdd", {});
that._addStoriesToBuffer(foundObject.Children, storyRef);
that._copyTasksToStory(foundObject.Tasks, storyRef, callback);
}, null);
});
};
this._copyTasksToStory = function(tasks, storyRef, callback) {
//Copy the array
var localTasks = tasks.slice(0);
if (localTasks.length > 0) {
var task = localTasks.pop();
that._copyTask(task._ref, storyRef, function () {
that._copyTasksToStory(localTasks, storyRef, callback);
});
}
else {
callback();
}
};
this._copyTask = function(ref, storyRef, callback) {
rallyDataSource.getRallyObject(ref, function (foundObject) {
var type = getTypeFromRef(ref);
foundObject.WorkProduct = storyRef;
that._fireEvent("taskPreAdd", {task:foundObject});
that._addObject(foundObject, type, function (ref, warnings) {
if (callback) {
that._fireEvent("taskPostAdd", [ref]);
callback();
}
}, null);
});
};
this.copyStory = function (ref, callback) {
that._copyStory(ref, undefined, that._copyAllFromBuffer);
finishedCallback = callback;
};
};
</script>
<script type="text/javascript">
var destinationProject;
function dropdownChanged(dropdown, eventArgs) {
destinationProject = eventArgs.value
console.log(destinationProject);
}
rally.addOnLoad(function() {
var selectedValue = null;
var tasksAdded = 0;
var storiesAdded = 0;
var searchStories;
var goButton, chooseButton;
var chooser;
var waiter;
var dataSource = new rally.sdk.data.RallyDataSource('1111', '2222',
'__PROJECT_SCOPING_UP__', '__PROJECT_SCOPING_DOWN__');
var config = {
type : "project",
attribute: "Name",
query : '(State = "Open")'
};
var objectDropdown = new rally.sdk.ui.ObjectDropdown(config, dataSource);
objectDropdown.display("aDiv", dropdownChanged);
function taskPostAdd(object, args) {
tasksAdded = tasksAdded + 1;
displayTasksAdded(tasksAdded);
}
function taskPreAdd(object, args) {
dojo.byId("currentInfo").innerHTML = "Adding Task " + args.task.FormattedID + " - " + args.task.Name;
}
function storyPreAdd(object, args) {
dojo.byId("currentInfo").innerHTML = "Adding User Story " + args.story.FormattedID + " - " + args.story.Name;
}
function storyPostAdd(object, args) {
storiesAdded = storiesAdded + 1;
displayStoriesAdded(storiesAdded);
}
function displayStoriesAdded(count) {
dojo.byId("storyResult").innerHTML = "Stories added: " + count;
}
function displayTasksAdded(count) {
dojo.byId("taskResult").innerHTML = "Tasks added: " + tasksAdded;
}
function storyCopied(story) {
dojo.byId("currentInfo").innerHTML = "Copy complete: ";
var link = new rally.sdk.ui.basic.Link({
item: story,
text: story._refObjectName
});
link.display('currentInfo');
goButton.setEnabled(true);
chooseButton.setEnabled(true);
if(waiter) {
waiter.hide();
waiter = null;
}
}
function buttonPressed() {
if (selectedValue) {
var config = {
eventListeners:{
storyPreAdd:storyPreAdd,
storyPostAdd:storyPostAdd ,
taskPreAdd:taskPreAdd,
taskPostAdd: taskPostAdd
}
};
tasksAdded = 0;
displayTasksAdded(tasksAdded);
storiesAdded = 0;
displayStoriesAdded(storiesAdded);
dojo.byId("currentInfo").innerHTML = "";
var copy = new rally.StoryDeepCopy(dataSource, config);
goButton.setEnabled(false);
chooseButton.setEnabled(false);
waiter = new rally.sdk.ui.basic.Wait({});
waiter.display('wait');
copy.copyStory(rally.sdk.util.Ref.getRelativeRef(selectedValue), storyCopied);
}
}
function onChooserClose(chooser, args) {
if (args.selectedItem) {
selectedValue = args.selectedItem;
goButton.setEnabled(true);
dojo.byId('storyBox').innerHTML = args.selectedItem.FormattedID + ' - ' +
args.selectedItem.Name;
}
}
function showChooser() {
var chooserConfig = {
fetch:"FormattedID,Name,Description,Project",
title: 'Story Chooser'
};
chooser = new rally.sdk.ui.Chooser(chooserConfig, dataSource);
chooser.addEventListener('onClose', onChooserClose);
chooser.display();
}
rally.addOnLoad(function () {
goButton = new rally.sdk.ui.basic.Button({
text: "Copy",
enabled: false
});
goButton.addEventListener('onClick', buttonPressed);
goButton.display('goButton');
chooseButton = new rally.sdk.ui.basic.Button({
text: "Choose"
});
chooseButton.addEventListener('onClick', showChooser);
chooseButton.display('chooseButton');
showChooser();
rally.sdk.ui.AppHeader.setHelpTopic("252");
});
});
</script>
</head>
<body>
<div id="container">
<div id="aDiv"></div>
<div style="float:left">
<span id="chooseButton"></span>
<span id="storyBox" style="line-height:18px;vertical-align:middle">[No story selected]</span>
<span id="goButton"></span>
</div>
<div id="wait" style="float:left; height: 16px; width: 24px;"></div>
<div style="margin-left:5px;padding-top:10px;clear:both">
<div id="currentInfo" style="height:16px"></div>
<div id="storyResult" style="margin-top:10px"></div>
<div id="taskResult"></div>
</div>
</div>
</body>
</html>