Jazz Forum Welcome to the Jazz Community Forum Connect and collaborate with IBM Engineering experts and users

How to add Links to a Workitem in RTC 5.x (JS/Dojo)

Hy there fellas,

Does someone know how to add a "parentLink" to an existing Workitem.
The Idea is to clone a WI and then add the parent link to the cloned WI.

Maybe I can relate the WI on creation with the Link?

I use this class to get the Item:
com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory
           var params = {
               includeHistory: false,
               newWorkItem: true,
               projectAreaItemId: pid,
               typeId: "com.ibm.team.apt.workItemType.story"
           }
          
           var newProxy = WorkItemProxyFactory.getWorkItemProxy(params);

//Create new Item:
newProxy.initialize(projectArea, type, newWorkitem, includeHistory) //Maybe it's possible to add links here?

//Before I add some attributes like name, description etc
//My Idea here was, to extract the Links, and add it in the same way to the new Item.
workItemToSave.storedObject.linkTypes = parentLink; //itemToSave is "newProxy"

//Store, save it on the DB
newProxy.storeWorkItem();


0 votes


Accepted answer

Permanent link
Hy Ralph,
I don't really like blogging.
But I'll describe it here.

First you should read this Post about how the whole Workitem-System works.
https://jazz.net/wiki/bin/view/Main/WorkItemWebItemProxyDesign
Long story short:
With store and fetch you interact direct with the REST-Client (Store on DB)
Store = Save it on DB
Fetch = Get it from DB
Everything in this "workItemproxy" is kinda like a runtime copy of the actual WI.

Now I gonna try to clarify how to interact with those Workitems.
First, get the workItemProxy class.
dojo.require("com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory");

I instantiate it for easier use:
var WorkItemProxyFactory = com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory;

Now we gonna create a new WIProxy:
var params = {createIfNeeded: true};
var newProxy = WorkItemProxyFactory.getWorkItemProxy(params);

//If you want an WIProxy of an existing WI:
var params = { id: "itemId of the wished WI",
                        createIfNeeded: true,
                       doNotCache: true,
                       doNotGetFromCache:true};
var workingCopyProxy = WorkItemProxyFactory.getWorkItemProxy(params);

//Initialize the WI
//After the initialization, you'll see an unsaved WI in the MenuBar "Work Items".
var params = {projectAreaItemId: "The ItemId of your project",
                       type: "com.ibm.team.apt.workItemType.story", //Story, epic, whatever you need
                       newWorkItem: true,
                       includeHistory: false};
newProxy.initialize(params);

//Get the Links from the workingCopy
var linkTypeArray = workingCopyProxy.object.linkTypes //Here are all Links to this actual WI stored.
//Otherwise you could use:
var linkTypeArray = workingCopyProxy.getLinkTypesToWorkItem(workingCopyProxy);

//If you search specific LinkTypes, use the endpointId
//I.E. linkTypeArray[x].endpointId == 'parent' //To get the parentLink

//Now HOW TO ADD THE WISHED LINKS
                   var param = {
                           addLinkType: linkTypeArray, //It has to be an Array
                           addLinkedProjectAreaItemId: null, //I don't know what this shold do.
                           addLinkedItemId: newProxy.object.itemId, // It's the ItemId of itself
                           addLinkIsSource: linkTypeArray[0].isSource, //Mostly this is "false"
                   }
                   newProxy.addLinkTarget(param);

//At this point ONLY your runtime copy is actualized! You have to store now your WI to save it on the DB
                   newProxy.storeWorkItem({
                       self: this,
                       operationMsg: "Saving",
                       applyDelta: true,
                       onSuccess: function(param) {
                            //Do what you need
                       }
                   });

Et Voilà the Item is created and saved with the wished links.
Ralph Schoon selected this answer as the correct answer

0 votes

Comments

One last comment Jonas.

To make it easier for the forum users to understand the context, please clarify next time that you are not talking about attribute customization, but that you create a web UI extension.

Ok, sory for that!
I'll do it better next time

Hello,

I just followed the above code but it seems to be existing work item is not Fetched.

dojo.provide("net.jazz.example.workitem.web.ui.LinkedDefectEditorToolbar"); //$NON-NLS-1$

dojo.require("com.ibm.team.workitem.web.ui2.internal.action.AbstractAction"); //$NON-NLS-1$

dojo.require("com.ibm.team.workitem.web.client.util"); //$NON-NLS-1$

dojo.require("com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory");


(function() {

    //I instantiate it for easier use:
    var WorkItemProxyFactory = com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory;

    dojo.declare("net.jazz.example.workitem.web.ui.LinkedDefectEditorToolbar", [com.ibm.team.workitem.web.ui2.internal.action.AbstractAction,com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory],
     {
        constructor: function(){
           
            // Calculate current Project Area and Work Item Type

            this._existingid = new String(this.workingCopy.getItemId());
            this._projectAreaItemId = new String(this.workingCopy.getValue({ path: "attributes.projectArea.id"}));
           
            console.log(this._existingid);
            console.log(this._projectAreaItemId);
       

        },
       
        run: function(parms) {

            //I instantiate it for easier use:
            var WorkItemProxyFactory = com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory;

            //Now we gonna create a new WIProxy:
            var params = {createIfNeeded: true};
            var newProxy = WorkItemProxyFactory.getWorkItemProxy(params);

            //If you want an WIProxy of an existing WI:
            var exparams = { id: this._existingid,
                                   createIfNeeded: true,
                                   doNotCache: true,
                                   doNotGetFromCache:true};
            var workingCopyProxy = WorkItemProxyFactory.getWorkItemProxy(exparams);

            //Initialize the WI
            //After the initialization, you'll see an unsaved WI in the MenuBar "Work Items".
            var newparams = {projectAreaItemId:this._projectAreaItemId,
                                   type: "com.ibm.team.apt.workItemType.story", //Story, epic, whatever you need
                                   newWorkItem: true,
                                   includeHistory: false};
            console.log("projectArea:"+projectAreaItemId);
            newProxy.initialize(newparams);

            //Get the Links from the workingCopy
            //var linkTypeArray = workingCopyProxy.object.linkTypes //Here are all Links to this actual WI stored.
            //Otherwise you could use:
            var linkTypeArray = workingCopyProxy.getLinkTypesToWorkItem(workingCopyProxy);
            console.log("linktype:"+linkTypeArray);

            //If you search specific LinkTypes, use the endpointId
            //I.E. linkTypeArray[x].endpointId == 'parent' //To get the parentLink

            //Now HOW TO ADD THE WISHED LINKS
                               var linkparam = {
                                       addLinkType: linkTypeArray, //It has to be an Array
                                       addLinkedProjectAreaItemId: null, //I don't know what this shold do.
                                       addLinkedItemId: newProxy.object.itemId, // It's the ItemId of itself
                                       addLinkIsSource: linkTypeArray[0].isSource, //Mostly this is "false"
                               }
                               newProxy.addLinkTarget(linkparam);

            //At this point ONLY your runtime copy is actualized! You have to store now your WI to save it on the DB
                               newProxy.storeWorkItem({
                                   self: this,
                                   operationMsg: "Saving",
                                   applyDelta: true,
                                   onSuccess: function(param) {
                                        //Do what you need
                                   }
                               });
   
        }   

    });

})();

Not sure what went wrong!!


Hello Vinitha,

I'll try my best to clarify this :)

First thing, which would be nice is, where does your code crash.
But I take now some wild guessings.

1:
You've double instanciated the factory.

outside the declare and inside (since the declare statement marks the class boundaries and we need the factory inside)

2:
You're using methods inside the constructor where he doesn't know what to do.
this._existingid = new String(this.workingCopy.getItemId());
Workingcopy is nothing there. Probably here fires the "not fetched" error.

3: Because there are some missing infos, your "var exparams" are not correct. The ID at least.

4: What are the params you've send to the run method?
Because that's where the fetch should happen.
var newProxy = WorkItemProxyFactory.getWorkItemProxy(params);

If it's not one of this this, let me know what happens and where the code went through. So I might recreate the problem you have.

HI,
did you resolve your problem? I'm trying to button for create children workitem and on StoreWorkitem I'm getting error:
Uncaught TypeError: Cannot read property 'id' of undefined
at Object._getSaveAppArgs_$77 [as _getSaveAppArgs] (com.ibm.team.workitem.web.cache.internal.WorkItemProxyClient.js?debug=true&etag=aT34qru&locale=en-us&_proxyURL=%2Fjazz:2020)
at Object.storeWorkItem_$64 [as storeWorkItem] (com.ibm.team.workitem.web.cache.internal.WorkItemProxyClient.js?debug=true&etag=aT34qru&locale=en-us&_proxyURL=%2Fjazz:1515)
at Object.run_$1 [as run] (corp.bury.webui.findingButton.ui.createFindingAction.js?debug=true&locale=en-us&_proxyURL=%2Fjazz:65)
at Object._doRun_$2 [as _doRun] (com.ibm.team.workitem.web.ui2.internal.action.AbstractAction.js?debug=true&etag=aT34qru&locale=en-us&_proxyURL=%2Fjazz:59)
at Object.method_$16 [as onClick] (dojo._base.lang.js?debug=true&etag=aL4Yoz2&locale=en-us&_proxyURL=%2Fjazz:375)
at Object._onClick_$3 [as _onClick] (jazz.ui.toolbar.Button.js?debug=true&etag=aT18Sli&locale=en-us&_proxyURL=%2Fjazz:126)
at Object.onClick_$9 (net.jazz.ajax.ui.ScenarioRegistry.js?debug=true&etag=aT174Ja&locale=en-us&_proxyURL=%2Fjazz:204)
at Object.<anonymous> (dojo._base.lang.js?debug=true&etag=aL4Yoz2&locale=en-us&_proxyURL=%2Fjazz:327)
at HTMLAnchorElement.method_$16 (dojo._base.lang.js?debug=true&etag=aL4Yoz2&locale=en-us&_proxyURL=%2Fjazz:375)

My code is here:
        
dojo.provide("corp.bury.webui.findingButton.ui.createFindingAction"); //$NON-NLS-1$    
dojo.require("com.ibm.team.workitem.web.ui2.internal.action.AbstractAction"); //$NON-NLS-1$  
dojo.require("com.ibm.team.workitem.web.client.util"); //$NON-NLS-1$    
dojo.require("com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory"); 
(function() 
    
// WorkItem Types list of entities that for which the actions apply    
var workItemEnabledType = "review";      
// Link Type to use    
var linkType = "com.ibm.team.workitem.linktype.parentworkitem";
// WorkItem Type to generate    
var workItem2Gen = "finding";      
var WorkItemUtil = com.ibm.team.workitem.web.client.util; 
dojo.declare("corp.bury.webui.findingButton.ui.createFindingAction",     
com.ibm.team.workitem.web.ui2.internal.action.AbstractAction,    
constructor: function() 
      
// Calculate current Project Area and Work Item Type    
this._currentWIType = new String(this.workingCopy.getValue(
path: "attributes.workItemType.id"
}));
this._currentPArea = new String(this.workingCopy.getValue(
path: "attributes.projectArea.id"
}));
this._currentWIId = this.workingCopy.getItemId();
},  
run: function(parms) 
    

var WorkItemProxyFactory = com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory;
            var params = {createIfNeeded: true};
            var newProxy = WorkItemProxyFactory.getWorkItemProxy(params); 
            
var initializeParams = 
{
projectAreaItemId: this._currentPArea,
                    type: workItem2Gen, 
                    newWorkItem: true,
                    includeHistory: false
            }; 
newProxy.initialize(initializeParams);
var addTargetLinkParams = 
addLinkIsSource: false, 
addLinkType: linkType, 
addLinkedProjectAreaItemId: this._currentPArea, 
addLinkedItemId: newProxy.object.itemId    
};
newProxy.addLinkTarget(addTargetLinkParams);
var attributesToAdd = 
{
attributeList : { description : "Test", summary : "Test Summary" }
};
newProxy.setAttributes(attributesToAdd);
newProxy.storeWorkItem(
{
                                self: this,
                                operationMsg: "Saving",
                                applyDelta: true,
                                onSuccess: function(param) {
                                     //Do what you need
                                }
});
},   
isEnabled: function() 
    
// Our action is to be only enabled in the Story Work Item and when no change in "on-fly"      
return !this.workingCopy.isNew() && !this.workingCopy.isChanged() && (this._currentWIType==workItemEnabledType);
},   
isVisible: function(parms)   
    
// The action is visible just in workItemEnabledType Work Item    
return this._currentWIType==workItemEnabledType;   
   
}); 
})();
    </pre>
</div>
Where I'm making mistake?


One other answer

Permanent link
I don't think you can create or follow links in the javascript api.

0 votes

Comments

Hy Sam,

But under Version 4.x it worked for me.
Was there a mayor change within the Link system?

A guess:
If I use the "Create WorkItem Copy" it doesn't copy the ParentLink, but it adds the "Copied from" Link, which is in the same Hierarchy as a parent link.

No idea.. never got links to work (list, create, delete, or follow) in javascript.

the 'copied from' is a side effect by the server side code, cause you did a 'copy' operation


There is a distinction between JavaScript in workitemCustomization, where you can't even access links and creating your own web pages and contributions to them, where you potentially could (as the tool has such capabilities as well)

thanks for that clarification.. I've never done the latter.. (UI is not my thing!)

So I got in a bit deeper.
But I need your help now.

I've found "addLinkTarget()" in workitemProxy

addLinkTarget: function addLinkTarget_$79(parms / addLinkType addLinkedProjectAreaItemId addLinkedItemId addLinkIsSource/) {}

But the params are a bit confusing.
addLinkType: com.ibm.team.workitem.linktype.parentworkitem
addLinkedProjectAreaItemId: //I don't know so I set it to "null"
addLinkedItemId:I don't know, itemId of the Parent won't work.
addLinkIsSource: What's the meaning of this?

Always get this message:
WorkItemProxy: Could not find source for new link item [object Object]

Maybe this could be a timing error.
Because I use it between
newProxy.initialize()
newProxy.storeWorkItem();

Maybe I can only use the addFunction when it's stored?

This is beyond my expertise as well. Sorry.

It would be great is this could be shared somewhere. If it was my work and I knew how it works, I would blog about it. If you really want to it would be cool if you blogged about it e.g. on DeveloperWorks and link that back here.

showing 5 of 7 show 2 more comments

Your answer

Register or log in to post your answer.

Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.

Search context
Follow this question

By Email: 

Once you sign in you will be able to subscribe for any updates here.

By RSS:

Answers
Answers and Comments
Question details
× 10,943

Question asked: Oct 29 '14, 9:06 a.m.

Question was seen: 5,413 times

Last updated: Nov 27 '17, 12:46 p.m.

Confirmation Cancel Confirm