想要将故事从一个项目复制到另一个项目 [英] Want to copy Rally stories from one project to another

查看:500
本文介绍了想要将故事从一个项目复制到另一个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从一个Rally项目中复制故事和任务(及其层次结构)到另一个。

I'm trying to copy stories and tasks (and their hierarchies) from one Rally project to another.

我只需要从一个模板项目所以我不需要使用ProjectPicker小部件。简单地利用复制故事和任务的现有应用程序只需要 ,它需要能够从一个项目读取并写入另一个项目(您当前登录的项目将是最简单。)

I only need to copy from one 'template' project so I don't need to make use of the ProjectPicker widget. Simply leveraging the existing app that copies stories and tasks is all that is need but it needs to be able to read from one project and write to another project (the current project you're logged into would be the easiest.)

我修改了应用程序,以便它可以从项目中读取我没有登录 - 好。
复制导致在我正在阅读的项目中复制的故事 - 不是我在Rally中登录的那个 - 任何人都知道如何使这个发生吗?

I modified the app so that it can read from a project I'm not logged into - good. The copy results in a copied story in the project I'm reading from - not the one I'm logged into in Rally - does anyone know how to make this happen?

感谢,

Kevin

推荐答案

您正在使用Story Deep Copy应用程序。
从你的问题,它看起来像你已经修改了一个项目的hangman变量,你从中复制。假设该项目的OID是22222,并且要复制的目标项目的OID是33333.这两个项目都在同一个工作空间OID 11111中。

I assume you are using Story Deep Copy app. From your question it looks like you already modified the hangman variable for a project from which you copy. Let's say the OID of that project is 22222, and the OID of the destination project where you want to copy is 33333. Both projects are in the same workspace, 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>

编辑:上面的代码修改为使用对象下拉列表,从中选择目标项目。因此,不需要硬编码目标项目的引用。

The code above was modified to use an object dropdown from which a destination project is selected. Hence there is no need to hardcode the destination project's reference.

<!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>

这篇关于想要将故事从一个项目复制到另一个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆