2013-07-22 2 views
3

하나의 랠리 프로젝트에서 다른 프로젝트로 스토리 및 작업 (및 해당 계층 구조)을 복사하려고합니다.복사 할 곳 하나의 프로젝트에서 다른 프로젝트로 랠리 이야기

ProjectPicker 위젯을 사용할 필요가 없으므로 하나의 '템플릿'프로젝트에서만 복사하면됩니다. 스토리와 작업을 복사하는 기존 앱을 활용하면됩니다. 이지만은 하나의 프로젝트에서 읽고 다른 프로젝트에 쓸 수 있어야합니다. (로그인 한 현재 프로젝트가 가장 쉽습니다.)

내가 로그인하지 않은 프로젝트에서 읽을 수 있도록 앱을 수정했습니다. - 좋습니다. 복사하면 내가 읽는 프로젝트의 복사 된 스토리가 생성됩니다 - 집회에 로그인 한 사람이 아닙니다 - 누군가 어떻게 이런 일이 발생하는지 알고 있습니까?

감사합니다,

케빈

답변

2

나는 당신이 이야기 깊은 복사 응용 프로그램을 사용하는 가정합니다. 질문에 복사 한 프로젝트의 행맨 변수가 이미 수정 된 것 같습니다. 이제, 두 프로젝트가 동일한 작업 공간에있는 OID 11111

var dataSource = new rally.sdk.data.RallyDataSource('11111', '22222', 
        '__PROJECT_SCOPING_UP__', '__PROJECT_SCOPING_DOWN__'); 

내가 this._copyStory에 한 줄을 추가 한 프로젝트의 OID는 22222이며, 복사 할 대상 프로젝트의 OID가 33333.입니다 가정 해 봅시다 :

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

EDIT :

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); 
     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> 
+0

호환되지 않는 프로젝트의 필터 기능에 Iteration 및 Release를 추가해야했지만, 그렇지 않은 경우이 기능이 뛰어납니다! 고맙습니다! –

관련 문제