Hi community!
I have Portfolio plugin for jira.
We need to copy value from the field "Team" (this is plugin field) in Custom field "Team of portfolio" (Text-type)
But after command:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.rm.teams.api.team.GeneralTeamService
import com.atlassian.jira.event.type.EventDispatchOption
import com.onresolve.scriptrunner.runner.customisers.*
import com.atlassian.jira.issue.MutableIssue
def issueManager = ComponentAccessor.getIssueManager()
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def teamportfolio = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def value_team = issue.getCustomFieldValue(teamportfolio)
I get ID number of Team :(
How do I copy the value to get the command name?
Jira version: 7.3.7
ScriptRunner version: 5.4.12
Portfolio for Jira version: 2.17.1
Thanks!
Best regards!
Hi
it's returning a default team. I'm not sure what that is,
but i'm pretty sure if you add
import com.atlassian.rm.teams.core.team.data.DefaultTeam;
and then cast to (DefaultTeam) you will get past - although maybe to next error
Are you using BitBucket?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here's a script:
"import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.rm.teams.core.team.data.DefaultTeam
import com.atlassian.crowd.embedded.api.Group
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def teamCf = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def grp =(DefaultTeam) issue.getCustomFieldValue(teamCf);"
Returns the command ID of the portfolio plugin field
our case it = 4
I need the name of the team, not the ID.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Need more info - and whole script to run up locally
You should be getting a DefaultTeam object returned
and I'd expect it have have a method that equates to
grp.getName() to return more info.
Are you using Portfolio?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes! We use Portfolio plugin.
Teams are created in this plugin.
The only thing I found on Portfolio:
https://docs.atlassian.com/portfolio-for-jira-server/javadoc/2.13.0/?_ga=2.79039444.1908712679.1540779183-1082209775.1537843438
But I don't know how use this API :(
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I can run up a trial version of Portfolio on my server and take a look at the returned values.
DefaultTeam doesn't seem to show up the api docs for some reason. Although if it implements the TeamAPI if should have a value() method that returns a Field object - I think.
It'll be a useful learning exercise for this morning!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi
I've been dipping in and out of the problem today and have hit a wall to be honest. I can set up Portfolio and reproduce your script function. I can get as far as getting a DefaultTeam returned but can't import it or get a handle on its methods. Opened up the plugin jar, but no sign of class in packages.
Sorry - I may tinker a bit more but don't think I can help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
one last try
i used reflection on DefaultTeam and this method call may work for you
value_team.getDescription().getTitle()
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
hi @Tom Lister
I tried use this question https://community.atlassian.com/t5/Jira-questions/How-to-set-Portfolio-Team-field-on-an-issue-with-ScriptRunner/qaq-p/928890 but my script dont work
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
PERFECT!
This is work!
Thanks for you help!
def grp =(DefaultTeam) issue.getCustomFieldValue(Filed)
def teamPortfolio = grp.getDescription().getTitle()
it's give me name Team!)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
this is not part of the published API so may change
here is snippet to find what methods are on a class
Class aClass = value_team.class
Method[] methods = aClass.getMethods();
for( Method meth : methods )
{
log.warn "DefaultTeam " + meth.getName()
}
Class tClass = value_team.getDescription().class
Method[] methodss = tClass.getMethods();
for( Method meth : methodss )
{
log.warn "DTDesc " + meth.getName()
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi,
We are able to achieve this with help of script listener.
Might help some other customer who need similar solution.
--------------------------------------------------------------------------------
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.rm.teams.core.team.data.DefaultTeam
import com.atlassian.crowd.embedded.api.Group
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.atlassian.rm.teams.api.team.GeneralTeamService
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
@WithPlugin("com.atlassian.teams")
def issue = event.issue
def teamCf = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Team")[0]
def grp =(DefaultTeam) issue.getCustomFieldValue(teamCf);
def teamPortfolio = grp.getDescription().getTitle()
//'Team Copy' is a text field where I want to copy the 'Team' field value either during update/create/edit etc..
def team_copy = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Team Copy")[0]
team_copy.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(team_copy), teamPortfolio), new DefaultIssueChangeHolder())
------------------------------------------------------------------------------
regards,
Prashant
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Try this Listener:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
def issue = event.issue as Issue
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def trgtField = customFieldManager.getCustomFieldObjects(event.issue).find {it.name == "Team"}
def CFportfolioTeam = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def select_singlechoice_field = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("TeamCF")
def fieldConfig = select_singlechoice_field.getRelevantConfig(issue)
def Options_0 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "None" }
def Options_1 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value1" }
def Options_2 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value2" }
def Options_3 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value3" }
def Options_4 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value4" }
def Options_5 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value5" }
def Options_6 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value6" }
def Options_7 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value7" }
def Options_8 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value8" }
def Options_9 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Value9" }
def changeHolder = new DefaultIssueChangeHolder()
def grp = issue.getCustomFieldValue(CFportfolioTeam)
if (grp == null) //if value = null then None
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_0),changeHolder)
}
else
{
def teamPortfolio = grp.getDescription().getTitle()
if (teamPortfolio == "value1_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_1),changeHolder)
}
else if (teamPortfolio == "value2_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_2),changeHolder)
}
else if (teamPortfolio == "value3_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_3),changeHolder)
}
else if (teamPortfolio == "value4_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_4),changeHolder)
}
else if (teamPortfolio == "value5_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_5),changeHolder)
}
else if (teamPortfolio == "value6_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_6),changeHolder)
}
else if (teamPortfolio == "value7_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_7),changeHolder)
}
else if (teamPortfolio == "value8_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_8),changeHolder)
}
else if (teamPortfolio == "value9_for_portfolio")
{
select_singlechoice_field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(select_singlechoice_field), Options_9),changeHolder)
}
}
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @SMAtlassianMber
I also have this error. This does not interfere with the code.
I don't find method that run no error(
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I have it working now too, but the error is still there.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Alexander - Do you have any suggestions how to update this listeners to also trigger "copy field to new CF" when the jira issues are transitioned to another status?
Thank you
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
After re-reading over the comments, I'm still not sure how you modified this script to display the name not the number?
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.onresolve.scriptrunner.runner.customisers.*
import com.atlassian.jira.issue.MutableIssue
def issueManager = ComponentAccessor.getIssueManager()
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def teamportfolio = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def value_team = issue.getCustomFieldValue(teamportfolio)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @SMAtlassianMber
Of course i help you :)
My script:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.rm.teams.core.team.data.DefaultTeam
MutableIssue issue = issue
//Take the values
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def CFportfolioTeam = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def select_singlechoice_field = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("TeamCF")
def team_value = issue.getCustomFieldValue (CFportfolioTeam)
def grp =(DefaultTeam) issue.getCustomFieldValue(CFportfolioTeam)
def teamPortfolio = grp.getDescription().getTitle()
//Options from select list's
def fieldConfig1 = select_singlechoice_field.getRelevantConfig(issue)
def Options_1 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value1" }
def fieldConfig2 = select_singlechoice_field.getRelevantConfig(issue)
def Options_2 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value2" }
def fieldConfig3 = select_singlechoice_field.getRelevantConfig(issue)
def Options_3 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value3" }
def fieldConfig4 = select_singlechoice_field.getRelevantConfig(issue)
def Options_4 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value4" }
def fieldConfig5 = select_singlechoice_field.getRelevantConfig(issue)
def Options_5 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value5" }
def fieldConfig6 = select_singlechoice_field.getRelevantConfig(issue)
def Options_6 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value6" }
def fieldConfig7 = select_singlechoice_field.getRelevantConfig(issue)
def Options_7 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value7" }
def fieldConfig8 = select_singlechoice_field.getRelevantConfig(issue)
def Options_8 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value8" }
def fieldConfig9 = select_singlechoice_field.getRelevantConfig(issue)
def Options_9 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value9" }
//Set Values
if (teamPortfolio == "value1_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_1)
}
else if (teamPortfolio == "value2_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_2)
}
else if (teamPortfolio == "value3_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_3)
}
else if (teamPortfolio == "value4_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_4)
}
else if (teamPortfolio == "value5_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_5)
}
else if (teamPortfolio == "value6_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_6)
}
else if (teamPortfolio == "value7_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_7)
}
else if (teamPortfolio == "value8_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_8)
}
else if (teamPortfolio == "value9_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_9)
}
My script listener:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.event.issue.AbstractIssueEventListener;
import com.atlassian.jira.event.issue.IssueEvent
def issue = event.issue as Issue
if (event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "Team"})
{
//Take the values
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def CFportfolioTeam = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def select_singlechoice_field = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("TeamCF")
def team_value = issue.getCustomFieldValue (CFportfolioTeam)
def grp =(DefaultTeam) issue.getCustomFieldValue(CFportfolioTeam)
def teamPortfolio = grp.getDescription().getTitle()
//Options from select list's
def fieldConfig1 = select_singlechoice_field.getRelevantConfig(issue)
def Options_1 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value1" }
def fieldConfig2 = select_singlechoice_field.getRelevantConfig(issue)
def Options_2 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value2" }
def fieldConfig3 = select_singlechoice_field.getRelevantConfig(issue)
def Options_3 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value3" }
def fieldConfig4 = select_singlechoice_field.getRelevantConfig(issue)
def Options_4 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value4" }
def fieldConfig5 = select_singlechoice_field.getRelevantConfig(issue)
def Options_5 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value5" }
def fieldConfig6 = select_singlechoice_field.getRelevantConfig(issue)
def Options_6 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value6" }
def fieldConfig7 = select_singlechoice_field.getRelevantConfig(issue)
def Options_7 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value7" }
def fieldConfig8 = select_singlechoice_field.getRelevantConfig(issue)
def Options_8 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value8" }
def fieldConfig9 = select_singlechoice_field.getRelevantConfig(issue)
def Options_9 = ComponentAccessor.optionsManager.getOptions(fieldConfig1)?.find { it.toString() == "Value9" }
def changeHolder = new DefaultIssueChangeHolder()
//Set Values
if (teamPortfolio == "value1_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_1)
}
else if (teamPortfolio == "value2_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_2)
}
else if (teamPortfolio == "value3_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_3)
}
else if (teamPortfolio == "value4_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_4)
}
else if (teamPortfolio == "value5_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_5)
}
else if (teamPortfolio == "value6_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_6)
}
else if (teamPortfolio == "value7_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_7)
}
else if (teamPortfolio == "value8_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_8)
}
else if (teamPortfolio == "value9_for portfolio")
{
issue.setCustomFieldValue(select_singlechoice_field, Options_9)
}
}
Good luck @SMAtlassianMber :)
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello -
I tried out both Listeners, but I'm still get errors
Error from your first example "unable to resolve class com.atlassian.rm.teams.core.team.data.DefaultTeam
import com.atlassian.rm.teams.core.team.data.DefaultTeam
Error from your second example "unable to resolve class Default Team"
def grp =(DefaultTeam) issue.getCustomFieldValue(CFportfolioTeam)
Thanks in advance for your help
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Alexander
Can I ask where you are executing this script?
workflow - I think there is a field copy supplied with scriptrunner
scripted field?
Below is copied from a sample script to set issue field in workflow function
private void setValue( MutableIssue issue, ApplicationUser user, CustomField field)
{
issue.setCustomFieldValue( field, user);
Map modifiedFields = issue.getModifiedFields();
FieldLayoutItem fieldLayoutItem = ComponentAccessor.getFieldLayoutManager() .getFieldLayout( issue). getFieldLayoutItem( field);
DefaultIssueChangeHolder issueChangeHolder = new DefaultIssueChangeHolder();
final ModifiedValue modifiedValue = (ModifiedValue) modifiedFields.get( field.getId());
field.updateValue( fieldLayoutItem, issue, modifiedValue, issueChangeHolder);
}
Refer
JIRA Development Cookbook Third Edition
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
For group name try
def
grp =(Group) myIssue.getCustomFieldValue(field);
def name = grp.getName();
for multipicker use List<Group> and iterate even if only one value
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello @Tom Lister.
Thanks for your answer! But it's doesn't work :(
Error log:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: Script1492.groovy: 16: unable to resolve class Group @ line 16, column 11. def grp = (Group) myIssue.getCustomFieldValue(teamCf); ^ 1 error
maybe i not right used this script...
I not understand how use this:
private void setValue( MutableIssue issue, ApplicationUser user, CustomField field)
{
issue.setCustomFieldValue( field, user);
Map modifiedFields = issue.getModifiedFields();
FieldLayoutItem fieldLayoutItem = ComponentAccessor.getFieldLayoutManager() .getFieldLayout( issue). getFieldLayoutItem( field);
DefaultIssueChangeHolder issueChangeHolder = new DefaultIssueChangeHolder();
final ModifiedValue modifiedValue = (ModifiedValue) modifiedFields.get( field.getId());
field.updateValue( fieldLayoutItem, issue, modifiedValue, issueChangeHolder);
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Alexander
did you add an import for the Group object?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Alexander
add this to the list of imports at the start of your script
import com.atlassian.crowd.embedded.api.Group;
post the whole script if you get further issues
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Tom ListerThanks!
I did it:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.crowd.embedded.api.Group
def teamCf = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Team")
def grp =(Group) issue.getCustomFieldValue(teamCf);
def name = grp.getName()
Result log:
Cannot cast object '4' with class 'com.atlassian.rm.teams.core.team.data.DefaultTeam' to class 'com.atlassian.crowd.embedded.api.Group'
Logs:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '4' with class 'com.atlassian.rm.teams.core.team.data.DefaultTeam' to class 'com.atlassian.crowd.embedded.api.Group'
at Script1582.run(Script1582.groovy:10)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I get the same error. Did anyone ever respond how to correct your script?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.