Scarab commit: svn commit: r10768 - trunk/src: conf/conf java/org/tigris/scarab/actions java/org/tigris/scarab/om schema sql/upgrade webapp/WEB-INF/templates/screens/admin webapp/WEB-INF/templates/viewIssue
Hussayn Dabbous <[email protected]>
| Newsgroups | gmane.comp.java.scarab.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: dabbous
Date: 2009-07-03 11:19:26-0700
New Revision: 10768
Modified:
trunk/src/conf/conf/intake.xml
trunk/src/java/org/tigris/scarab/actions/AssignIssue.java
trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java
trunk/src/java/org/tigris/scarab/om/Attribute.java
trunk/src/java/org/tigris/scarab/om/AttributeValue.java
trunk/src/java/org/tigris/scarab/om/ScarabUserImpl.java
trunk/src/schema/scarab-schema.xml
trunk/src/sql/upgrade/upgrade-0.23-attribute.sql
trunk/src/webapp/WEB-INF/templates/screens/admin/ModuleAttributeEdit.vm
trunk/src/webapp/WEB-INF/templates/screens/admin/UserAttributeEdit.vm
trunk/src/webapp/WEB-INF/templates/viewIssue/ViewIssueTab2.vm
Log:
SCB2977: Aded new flag to support 'only one single assigned to' user per issue. rewrote the AssignIssue template to allow much simpler user interaction.Note: You must run the upgrade-0.23-attribute.sql to get the new feature up and running
Modified: trunk/src/conf/conf/intake.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/conf/intake.xml?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/conf/conf/intake.xml (original)
+++ trunk/src/conf/conf/intake.xml 2009-07-03 11:19:26-0700
@@ -50,7 +50,8 @@
<rule name="minLength" value="1">intake_ActionNotAllowedEmpty</rule>
<rule name="maxLength" value="255">intake_ActionMustBeLessThan255Characters</rule>
</field>
- <field name="Deleted" key="del" type="boolean" />
+ <field name="Deleted" key="del" type="boolean" />
+ <field name="MultiValue" key="multival" type="boolean" />
</group>
<group name="ConditionEdit" key="cndtn" mapToObject="om.Condition">
Modified: trunk/src/java/org/tigris/scarab/actions/AssignIssue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/AssignIssue.java?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/AssignIssue.java (original)
+++ trunk/src/java/org/tigris/scarab/actions/AssignIssue.java 2009-07-03 11:19:26-0700
@@ -47,12 +47,14 @@
*/
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Logger;
import org.apache.fulcrum.parser.ParameterParser;
import org.apache.torque.TorqueException;
@@ -67,6 +69,7 @@
import org.tigris.scarab.om.AttributeManager;
import org.tigris.scarab.om.AttributeValue;
import org.tigris.scarab.om.Issue;
+import org.tigris.scarab.om.IssueManager;
import org.tigris.scarab.om.Module;
import org.tigris.scarab.om.ScarabUser;
import org.tigris.scarab.om.ScarabUserManager;
@@ -109,24 +112,12 @@
{
userAttributes.put(userIds[i], params.get("user_attr_" + userIds[i]));
}
- returnCode = addUsersToList(user, module, userAttributes, msg);
- if (returnCode == USERS_ADDED)
- {
- scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereAdded);
- }
- if (returnCode == USERS_REMOVED)
- {
- L10NMessage l10nMsg = new L10NMessage(L10NKeySet.UserAttributeRemoved,
- msg.toString());
- scarabR.setAlertMessage(l10nMsg);
- }
- if (returnCode == ERR_NO_USERS_SELECTED)
- {
- scarabR.setAlertMessage(L10NKeySet.NoUsersSelected);
- }
+ returnCode = addUsersToList(user, module, userAttributes, msg);
+ setGUIMessage(returnCode, scarabR, msg);
}
}
+
/**
* Adds the current user to the temporary working list.
* @param data
@@ -137,13 +128,36 @@
throws Exception
{
ScarabRequestTool scarabR = getScarabRequestTool(context);
+ Issue issue = scarabR.getIssue();
ScarabUser user = (ScarabUser)data.getUser();
+
+ // clean up first. I may already be in the list
+ // [HD]Note: Here i assume, that one user may only show up ONCE
+ // in the list. Apparently it does not make sense to
+ // assign someone AND let the same person observe an issue
+ // at the same time. But OTOH it might be possible, that
+ // other use cases exist, which make it necessary to
+ // have multiple assignments of the same user in the list.
+ // (to be discussed?)
+ removeUserFromIssue(user, issue);
+
String attributeId = data.getParameters().get("myself_attribute");
String userId = user.getUserId().toString();
Map map = new HashMap();
map.put(userId, attributeId);
StringBuffer msg = new StringBuffer();
int returnCode = addUsersToList(user, scarabR.getCurrentModule(), map, msg);
+ setGUIMessage(returnCode, scarabR, msg);
+ }
+
+ /**
+ * Set the appropriate GUI message for the given returnCode.
+ * @param returnCode
+ * @param scarabR
+ * @param msg
+ */
+ private void setGUIMessage(int returnCode, ScarabRequestTool scarabR, StringBuffer msg)
+ {
if (returnCode == USERS_ADDED)
{
scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereAdded);
@@ -157,37 +171,22 @@
if (returnCode == ERR_NO_USERS_SELECTED)
{
scarabR.setAlertMessage(L10NKeySet.NoUsersSelected);
- }
+ }
}
/**
- * Adds the current user to the temporary working list.
+ * Removes the current user from the temporary working list.
* @param data
* @param context
* @throws Exception
*/
public void doRemovemyself(RunData data, TemplateContext context)
- throws Exception
+ throws Exception
{
ScarabRequestTool scarabR = this.getScarabRequestTool(context);
ScarabUser user = (ScarabUser) data.getUser();
- Integer myUid = user.getUserId();
Issue issue = scarabR.getIssue();
- Set userSet = issue.getAssociatedUsers();
- Iterator iter = userSet.iterator();
- int removeCounter = 0;
- int index = 0;
- while(iter.hasNext())
- {
- ArrayList entry = (ArrayList)iter.next();
- ScarabUser su = (ScarabUser)entry.get(1);
- if (su.getUserId().equals(myUid))
- {
- userSet.remove(entry); // now the iterator is potentially invalid
- iter = userSet.iterator(); // rebuild the iterator (suboptimal)
- removeCounter++;
- }
- }
+ int removeCounter = removeUserFromIssue(user, issue);
if(removeCounter>0)
{
scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereRemoved);
@@ -197,7 +196,52 @@
scarabR.setAlertMessage(L10NKeySet.NoUsersSelected);
}
}
+
+ private int removeUserFromIssue(ScarabUser user, Issue issue) throws TorqueException
+ {
+ return removeUserFromIssue(user, null, issue);
+ }
+
+ private int removeUserFromIssue(ScarabUser user, Attribute attribute, Issue issue) throws TorqueException
+ {
+ Set<ArrayList> userSet = issue.getAssociatedUsers();
+ return removeUserFromUserSet(user, attribute, userSet);
+ }
+
+ private int removeUserFromUserSet(ScarabUser user, Attribute attribute, Set<ArrayList> userSet) throws TorqueException
+ {
+ Integer userId = user.getUserId();
+ Iterator<ArrayList> iter = userSet.iterator();
+ Collection toBeRemoved = new ArrayList();
+
+ while(iter.hasNext())
+ {
+ ArrayList entry = iter.next();
+ ScarabUser su = (ScarabUser)entry.get(1);
+
+ if (su.equals(user))
+ {
+ if(attribute != null)
+ {
+ Attribute entryAttribute = (Attribute)entry.get(0);
+ if (!entryAttribute.equals(attribute))
+ {
+ continue;
+ }
+ }
+ toBeRemoved.add(entry);
+ }
+
+ }
+
+
+ userSet.removeAll(toBeRemoved);
+ int removeCounter = toBeRemoved.size();
+
+ return removeCounter;
+ }
+
/**
* Decoupled method that adds users to the temporary working list of the AssignIssue screen.
* @param user Currently connected user
@@ -237,7 +281,7 @@
{
userList = new HashSet();
}
- List attributeList = module
+ List<Attribute> attributeList = module
.getUserAttributes(issue.getIssueType(), true);
if (!attributeList.contains(attribute))
{
@@ -258,6 +302,8 @@
}
else
{
+ removeUserFromUserSet(su, null, userList); // remove all user entries from set.
+ cleanupMultiAssignEntries(attribute, userList, attributeList);
userList.add(item);
// userMap.put(issueId, userList);
// user.setAssociatedUsersMap(userMap);
@@ -279,8 +325,72 @@
}
return returnCode;
}
+
+ /**
+ * Reassigns all user in the list with given attribute to the first available
+ * multiValue enabled attribute.
+ * @param attribute
+ * @param userList
+ * @param attributeList
+ */
+ private void cleanupMultiAssignEntries(Attribute attribute, Set userList, List<Attribute> attributeList)
+ {
+ // If attribute is marked multiValue, this is interpreted here as
+ // "multiple users may be assigned to this attribute"
+ // So here we only need to take care of non singleValue attributes
+ if (attribute.getMultiValue()==false)
+ {
+
+ // well, sort of a hack...
+ // If the list already contains this user attribute
+ // replace that one by "the first available multiValue user attribute"
+ // uhhh... i don't like that. Any better ideas around ???
+
+ Iterator iter = userList.iterator();
+ Collection toBeRemoved = new ArrayList();
+ while(iter.hasNext())
+ {
+ List entry = (List)iter.next();
+ Attribute entryAttr = (Attribute)entry.get(0);
+
+ if(entryAttr.getAttributeId() == attribute.getAttributeId())
+ {
+ Attribute newAttrib = findFirstMultiAssignAttribute(attributeList);
+ if (newAttrib == null)
+ {
+ toBeRemoved.add(entry); // remember entry for removement (see below)
+ }
+ else
+ {
+ entry.remove(0); // remove the old attribute
+ entry.add(0,newAttrib); // and move the new attribute in place
+ }
+ }
+ }
+ userList.remove(toBeRemoved); // remove all collected entries
+ }
+ }
/**
+ * Find the first multiValue enabled attribute in the list.
+ * @param attributeList
+ * @return
+ */
+ private Attribute findFirstMultiAssignAttribute(List<Attribute> attributeList)
+ {
+ Iterator<Attribute> iter = attributeList.iterator();
+ while(iter.hasNext())
+ {
+ Attribute att = iter.next();
+ if (att.getMultiValue())
+ {
+ return att;
+ }
+ }
+ return null;
+ }
+
+ /**
* Removes users from temporary working list.
*/
private void remove(RunData data, TemplateContext context, Long issueId)
@@ -288,7 +398,7 @@
{
ScarabUser user = (ScarabUser)data.getUser();
ScarabRequestTool scarabR = getScarabRequestTool(context);
- Set userList = (Set) user.getAssociatedUsersMap().get(issueId);
+ Set userSet = (Set) user.getAssociatedUsersMap().get(issueId);
ParameterParser params = data.getParameters();
String[] selectedUsers = params.getStrings(SELECTED_USER);
if (selectedUsers != null && selectedUsers.length > 0)
@@ -299,13 +409,10 @@
String selectedUser = selectedUsers[i];
String userId = selectedUser.substring(1, selectedUser.indexOf('_')-1);
String attrId = selectedUser.substring(selectedUser.indexOf('_')+1, selectedUser.length());
- Attribute attribute = AttributeManager
- .getInstance(new Integer(attrId));
- ScarabUser su = ScarabUserManager
- .getInstance(new Integer(userId));
- item.add(attribute);
- item.add(su);
- userList.remove(item);
+ Attribute attribute = AttributeManager.getInstance(new Integer(attrId));
+ ScarabUser su = ScarabUserManager.getInstance(new Integer(userId));
+ Issue issue = IssueManager.getInstance(issueId);
+ removeUserFromUserSet(su, attribute, userSet);
}
scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereRemoved);
}
@@ -326,29 +433,31 @@
Set userList = (Set) user.getAssociatedUsersMap().get(issueId);
ParameterParser params = data.getParameters();
String[] selectedUsers = params.getStrings(SELECTED_USER);
+
if (selectedUsers != null && selectedUsers.length > 0)
{
+ Issue issue = IssueManager.getInstance(issueId);
+ Module module = issue.getModule();
+ List<Attribute> attributeList = module.getUserAttributes(issue.getIssueType(), true);
for (int i =0; i < selectedUsers.length; i++)
{
String selectedUser = selectedUsers[i];
String userId = selectedUser.substring(1, selectedUser.indexOf('_')-1);
String attrId = selectedUser.substring(selectedUser.indexOf('_')+1, selectedUser.length());
- Attribute attribute = AttributeManager
- .getInstance(new Integer(attrId));
- ScarabUser su = ScarabUserManager
- .getInstance(new Integer(userId));
- List item = new ArrayList(2);
- List newItem = new ArrayList(2);
- item.add(attribute);
- item.add(su);
- userList.remove(item);
+ Attribute attribute = AttributeManager.getInstance(new Integer(attrId));
+ ScarabUser su = ScarabUserManager.getInstance(new Integer(userId));
+ removeUserFromUserSet(su, attribute, userList);
+
+ List newItem = new ArrayList(2);
String newKey = "asso_user_{" + userId + "}_attr_{" + attrId + "}_issue_{" + issueId + '}';
String newAttrId = params.get(newKey);
- Attribute newAttribute = AttributeManager
- .getInstance(new Integer(newAttrId));
+ Attribute newAttribute = AttributeManager.getInstance(new Integer(newAttrId));
+ cleanupMultiAssignEntries(newAttribute, userList, attributeList);
+
newItem.add(newAttribute);
newItem.add(su);
+
userList.add(newItem);
}
scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereModified);
@@ -556,3 +665,4 @@
}
}
+
Modified: trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java (original)
+++ trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java 2009-07-03 11:19:26-0700
@@ -149,6 +149,8 @@
/** set to true while the setInitialAttributesAndIssueTypes() method is in process */
private boolean isInitializing = false;
+
+ static private final List EmptyList = new ArrayList(); // to be used instead of null
/**
* Should be called when the parentage is modified.
@@ -1284,53 +1286,53 @@
}
+ /**
+ * If no moduleOptions are available, this method returns a final EmptyList.
+ * @param attribute
+ * @param issueType
+ * @return
+ * @throws TorqueException
+ */
private List getAllRModuleOptions(Attribute attribute, IssueType issueType)
throws TorqueException
{
- if(attribute == null)
- {
- // during initilaization of a new query, no
- // attributes are available.
- // This check avoids a NLP
- return null;
- }
+ List rModOpts = EmptyList;
- List rModOpts = null;
- Object obj = getMethodResult().get(this, GET_ALL_R_MODULE_OPTIONS,
- attribute, issueType);
- if (obj == null)
- {
- List options = attribute.getAttributeOptions(true);
- Integer[] optIds = null;
- if (options == null)
- {
- optIds = new Integer[0];
- }
- else
+ if(attribute != null)
+ {
+ Object obj = getMethodResult().get(this, GET_ALL_R_MODULE_OPTIONS, attribute, issueType);
+ if (obj == null)
{
- optIds = new Integer[options.size()];
+ List options = attribute.getAttributeOptions(true);
+ if (options != null && options.size() > 0)
+ {
+ Integer[] optIds = new Integer[options.size()];
+ for (int i=optIds.length-1; i>=0; i--)
+ {
+ optIds[i] = ((AttributeOption)options.get(i)).getOptionId();
+ }
+
+ Criteria crit = new Criteria();
+ crit.add(RModuleOptionPeer.ISSUE_TYPE_ID, issueType.getIssueTypeId());
+ crit.add(RModuleOptionPeer.MODULE_ID, getModuleId());
+ crit.addIn(RModuleOptionPeer.OPTION_ID, optIds);
+ crit.addAscendingOrderByColumn(RModuleOptionPeer.PREFERRED_ORDER);
+ crit.addAscendingOrderByColumn(RModuleOptionPeer.DISPLAY_VALUE);
+ rModOpts = getRModuleOptions(crit);
+
+ // It would be extremely suspicious to see a null value here.
+ assert (rModOpts != null); // for development
+ if(rModOpts == null) // for production
+ {
+ rModOpts = EmptyList;
+ }
+ }
+ getMethodResult().put(rModOpts, this, GET_ALL_R_MODULE_OPTIONS, attribute, issueType);
}
- for (int i=optIds.length-1; i>=0; i--)
+ else
{
- optIds[i] = ((AttributeOption)options.get(i)).getOptionId();
+ rModOpts = (List)obj;
}
-
- if (optIds.length > 0)
- {
- Criteria crit = new Criteria();
- crit.add(RModuleOptionPeer.ISSUE_TYPE_ID, issueType.getIssueTypeId());
- crit.add(RModuleOptionPeer.MODULE_ID, getModuleId());
- crit.addIn(RModuleOptionPeer.OPTION_ID, optIds);
- crit.addAscendingOrderByColumn(RModuleOptionPeer.PREFERRED_ORDER);
- crit.addAscendingOrderByColumn(RModuleOptionPeer.DISPLAY_VALUE);
- rModOpts = getRModuleOptions(crit);
- }
- getMethodResult().put(rModOpts, this, GET_ALL_R_MODULE_OPTIONS,
- attribute, issueType);
- }
- else
- {
- rModOpts = (List)obj;
}
return rModOpts;
}
Modified: trunk/src/java/org/tigris/scarab/om/Attribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Attribute.java?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/Attribute.java (original)
+++ trunk/src/java/org/tigris/scarab/om/Attribute.java 2009-07-03 11:19:26-0700
@@ -722,6 +722,7 @@
newAttribute.setCreatedBy(user.getUserId());
newAttribute.setCreatedDate(new Date());
newAttribute.setDeleted(getDeleted());
+ newAttribute.setMultiValue(getMultiValue());
newAttribute.save();
List attributeOptions = getAttributeOptions();
@@ -1088,5 +1089,20 @@
// Reuses existing cache-enabled method
return TransitionManager.getAllTransitions(this);
}
+
+ public boolean equals(Attribute other)
+ {
+ boolean result = super.equals(other);
+
+ int oid = other.getAttributeId();
+ int tid = this.getAttributeId();
+
+ if (result != (oid==tid))
+ {
+ int x=0; // very suspect...
+ }
+
+ return result;
+ }
}
Modified: trunk/src/java/org/tigris/scarab/om/AttributeValue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/AttributeValue.java?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/AttributeValue.java (original)
+++ trunk/src/java/org/tigris/scarab/om/AttributeValue.java 2009-07-03 11:19:26-0700
@@ -811,6 +811,13 @@
.getNewInstance(getAttributeId(), getIssue());
return copyInto(copyObj);
}
+
+ public AttributeValue copy(Connection con) throws TorqueException
+ {
+ throw new RuntimeException("Unimplemented method AttributeValue:copy(Connection conn)");
+ //return copy();
+ }
+
public void save(Connection dbcon)
throws TorqueException
Modified: trunk/src/java/org/tigris/scarab/om/ScarabUserImpl.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/ScarabUserImpl.java?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/ScarabUserImpl.java (original)
+++ trunk/src/java/org/tigris/scarab/om/ScarabUserImpl.java 2009-07-03 11:19:26-0700
@@ -1280,5 +1280,18 @@
{
return ScarabUser.DELETED.equals(getConfirmed());
}
+
+ /**
+ * Needed to allow consistent List.remove(entry) behaviour
+ * @param other
+ * @return
+ */
+ public boolean equals(ScarabUser other)
+ {
+ int ouid = other.getUserId();
+ int uid = getUserId();
+
+ return (ouid == uid);
+ }
}
Modified: trunk/src/schema/scarab-schema.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/schema/scarab-schema.xml?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/schema/scarab-schema.xml (original)
+++ trunk/src/schema/scarab-schema.xml 2009-07-03 11:19:26-0700
@@ -127,21 +127,22 @@
<column name="ATTACHMENT_TYPE_NAME" javaName="Name" required="true" type="VARCHAR" size="255" description="Name."/>
<column name="SEARCHABLE" default="0" type="BOOLEANINT" javaType="primitive" description="Flag marking text/searchable attachments"/>
</table>
- <table name="SCARAB_ATTRIBUTE" idMethod="idbroker" javaName="Attribute" description="Possible attributes of an issue. Example: Operating System. Example: Severity">
- <column name="ATTRIBUTE_ID" primaryKey="true" required="true" type="INTEGER" description="Unique identifier."/>
- <column name="ATTRIBUTE_NAME" javaName="Name" required="true" type="VARCHAR" size="255" description="Name."/>
- <column name="STYLE" javaName="Style" required="false" type="VARCHAR" size="255" description="optional string added as markup for css class or style information"/>
- <column name="FORMAT" javaName="Format" required="false" type="VARCHAR" size="255" description="An optional Format String."/>
- <column name="HINT" javaName="Hint" required="false" type="VARCHAR" size="255" description="An optional Hint string for the Format."/>
- <column name="FIELDSIZE" javaName="FieldSize" required="false" type="INTEGER" default="0" description="Maximum size of Display field"/>
- <column name="ATTRIBUTE_TYPE_ID" javaName="TypeId" required="true" type="INTEGER" description="Type."/>
- <column name="PERMISSION" required="false" type="VARCHAR" size="255" description="A permission related to this attribute."/>
- <column name="REQUIRED_OPTION_ID" required="false" type="INTEGER" description="A required option for this attribute to be active."/>
- <column name="DESCRIPTION" javaName="Description" required="true" type="VARCHAR" size="255" description="Description."/>
- <column name="ACTION" required="false" type="VARCHAR" size="255" description="For user attributes, whether the user will be emailed, will get a mail as cc, or neither."/>
- <column name="CREATED_BY" javaName="CreatedBy" required="false" type="INTEGER" description="Person that set value to the column of the table initially."/>
- <column name="CREATED_DATE" javaName="CreatedDate" required="false" type="TIMESTAMP" description="Date of the initial set of the column of the table."/>
- <column name="DELETED" required="false" type="BOOLEANINT" default="0" javaType="primitive" description="Flag, which marks that attribute has been deleted."/>
+ <table name="SCARAB_ATTRIBUTE" javaName="Attribute" idMethod="idbroker" description="Possible attributes of an issue. Example: Operating System. Example: Severity">
+ <column name="ATTRIBUTE_ID" primaryKey="true" required="true" type="INTEGER" description="Unique identifier."/>
+ <column name="ATTRIBUTE_NAME" javaName="Name" required="true" type="VARCHAR" size="255" description="Name."/>
+ <column name="STYLE" javaName="Style" required="false" type="VARCHAR" size="255" description="optional string added as markup for css class or style information"/>
+ <column name="FORMAT" javaName="Format" required="false" type="VARCHAR" size="255" description="An optional Format String."/>
+ <column name="HINT" javaName="Hint" required="false" type="VARCHAR" size="255" description="An optional Hint string for the Format."/>
+ <column name="FIELDSIZE" javaName="FieldSize" required="false" type="INTEGER" default="0" description="Maximum size of Display field"/>
+ <column name="ATTRIBUTE_TYPE_ID" javaName="TypeId" required="true" type="INTEGER" description="Type."/>
+ <column name="PERMISSION" required="false" type="VARCHAR" size="255" description="A permission related to this attribute."/>
+ <column name="REQUIRED_OPTION_ID" required="false" type="INTEGER" description="A required option for this attribute to be active."/>
+ <column name="DESCRIPTION" javaName="Description" required="true" type="VARCHAR" size="255" description="Description."/>
+ <column name="ACTION" required="false" type="VARCHAR" size="255" description="For user attributes, whether the user will be emailed, will get a mail as cc, or neither."/>
+ <column name="CREATED_BY" javaName="CreatedBy" required="false" type="INTEGER" description="Person that set value to the column of the table initially."/>
+ <column name="CREATED_DATE" javaName="CreatedDate" required="false" type="TIMESTAMP" description="Date of the initial set of the column of the table."/>
+ <column name="MULTI_VALUE" javaName="MultiValue" required="false" type="BOOLEANINT" default="0" javaType="primitive" description="if set to true, the attribute may contain multiple values"/>
+ <column name="DELETED" required="false" type="BOOLEANINT" default="0" javaType="primitive" description="Flag, which marks that attribute has been deleted."/>
<foreign-key foreignTable="SCARAB_ATTRIBUTE_TYPE">
<reference local="ATTRIBUTE_TYPE_ID" foreign="ATTRIBUTE_TYPE_ID"/>
</foreign-key>
Modified: trunk/src/sql/upgrade/upgrade-0.23-attribute.sql
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/sql/upgrade/upgrade-0.23-attribute.sql?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/sql/upgrade/upgrade-0.23-attribute.sql (original)
+++ trunk/src/sql/upgrade/upgrade-0.23-attribute.sql 2009-07-03 11:19:26-0700
@@ -16,4 +16,4 @@
ALTER TABLE SCARAB_ATTRIBUTE ADD ( FORMAT VARCHAR(255) );
ALTER TABLE SCARAB_ATTRIBUTE ADD ( HINT VARCHAR(255) );
ALTER TABLE SCARAB_ATTRIBUTE ADD ( FIELDSIZE INTEGER );
-
+ALTER TABLE SCARAB_ATTRIBUTE ADD ( MULTI_VALUE INTEGER NOT NULL DEFAULT 0);
Modified: trunk/src/webapp/WEB-INF/templates/screens/admin/ModuleAttributeEdit.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/admin/ModuleAttributeEdit.vm?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/admin/ModuleAttributeEdit.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/screens/admin/ModuleAttributeEdit.vm 2009-07-03 11:19:26-0700
@@ -58,6 +58,15 @@
$format.getDate($scarabR.DateFormat, $attribute.CreatedDate)
</td>
</tr>
+
+ <tr>
+ <th>Multi Value </th>
+ <td>attribute.MultiValue</td>
+ </tr>
+
+
+
+
#if (!$attribute.isUserAttribute())
<tr>
<th>$l10n.AlwaysRequired</th>
Modified: trunk/src/webapp/WEB-INF/templates/screens/admin/UserAttributeEdit.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/admin/UserAttributeEdit.vm?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/admin/UserAttributeEdit.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/screens/admin/UserAttributeEdit.vm 2009-07-03 11:19:26-0700
@@ -114,6 +114,17 @@
<h3>$l10n.UserAttributeProperties</h3>
<div class="axial">
<table width="100%" cellpadding="3" cellspacing="2" border="1">
+
+
+<tr>
+ <th>Multiple Instances</th>
+ #if(!$immutable)
+ <td>#booleanCheckbox ($attgroup.MultiValue)</td>
+ #else
+ <td>#booleanCheckboxLock ($attgroup.MultiValue $immutable)</td>
+ #end
+</tr>
+
<tr>
<th width="120">* $l10n.EmailAction</th>
<td class="b">
Modified: trunk/src/webapp/WEB-INF/templates/viewIssue/ViewIssueTab2.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/viewIssue/ViewIssueTab2.vm?view=diff&pathrev=10768&r1=10767&r2=10768
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/viewIssue/ViewIssueTab2.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/viewIssue/ViewIssueTab2.vm 2009-07-03 11:19:26-0700
@@ -23,6 +23,7 @@
#set ($assignedUser = $scarabR.getUser($userId))
#if ($data.User.userId.equals($userId))
#set ($myselfInList = true)
+ #set ($myattid = $attVal.AttributeId)
#end
<td>
<a href="mailto:$assignedUser.Email">$!assignedUser.Name</a>
@@ -62,15 +63,44 @@
##<input type="submit" value="$l10n.DeleteSelected" name="eventSubmit_doUnassign" /> 
#if ($scarabR.hasPermission($scarabG.Permission.ISSUE__ASSIGN, $module))
<input type="submit" value="$l10n.EditList" name="eventSubmit_doEditassignees" />
- <input type="submit" name="eventSubmit_doAddmyself" value="$l10n.AssignMyself" />
- <select name="myself_attribute">
- #foreach ($selectUserAttr in $module.getUserAttributes($currentIssue.issueType))
- #if ($!data.User.hasPermission($selectUserAttr.Permission, $module))
+
+ ## ============================================================================
+ ## Find all selectable User Attributes in the given context.
+ ## Note: If a userAttribute/user combination is allready in the list,
+ ## it can not be selected anymore here.
+ ## ============================================================================
+ #set ($options = [] )
+ #foreach ($selectUserAttr in $module.getUserAttributes($currentIssue.issueType))
+ #if ($!data.User.hasPermission($selectUserAttr.Permission, $module))
+ #set ($attid = $selectUserAttr.AttributeId)
+ #if ($myattid != $attid) ## if this attribute/user is already in list, discard it
+ #set ($selectUserAttrName = $module.getRModuleAttribute($selectUserAttr,$currentIssue.issueType).displayValue)
+ #set ($dummy = $options.add($selectUserAttr))
+ #end
+ #end
+ #end
+
+ #if ( $options.size() == 1)
+ ## Just create a button. We do not need a selector box in this case.
+ #foreach ($selectUserAttr in $options)
+ #set ($attid = $selectUserAttr.AttributeId)
#set ($selectUserAttrName = $module.getRModuleAttribute($selectUserAttr,$currentIssue.issueType).displayValue)
- <option value="$selectUserAttr.AttributeId">$selectUserAttrName:</option>
+ <input type="hidden" name="myself_attribute" value="$selectUserAttr.AttributeId"/>
+ <input type="submit" name="eventSubmit_doAddmyself" value="$l10n.AssignMyself $selectUserAttrName" />
#end
- #end
- </select>
+
+ #elseif ( $options.size() > 1 )
+ ## Create a selection box
+ <input type="submit" name="eventSubmit_doAddmyself" value="$l10n.AssignMyself" />
+ <select name="myself_attribute">
+ #foreach ($selectUserAttr in $options)
+ #set ($attid = $selectUserAttr.AttributeId)
+ #set ($selectUserAttrName = $module.getRModuleAttribute($selectUserAttr,$currentIssue.issueType).displayValue)
+ <option value="$selectUserAttr.AttributeId">$selectUserAttrName</option>
+ #end
+ </select>
+ #end
+
#if ($myselfInList)
<input type="submit" name="eventSubmit_doRemovemyself" value="$l10n.RemoveMe" />
#end
------------------------------------------------------
http://scarab.tigris.org/ds/viewMessage.do?dsForumId=3577&dsMessageId=2367862