I'm trying to write a Multi Project Picker custom field using plugin development. I have pulled all the projects and listed in the UI and saved the custom field with two projects. everything was successful.
But, the issue i'm facing right now is - In UI Edit screen, i'm just clicking the Update button without modifying any of the values. But in DB a new entry is created like the previous values are deleted and again the same two selected projects was pushed as new entry.
getValueFromCustomFieldParams function by default it stored the value into DB. How can i stop this?? I want a solution like if the custom field value gets changed only means the value should be updated in the DB.
Here is attached the History of the issue.
Java file:
package com.athena.plugins.jira_features.jira.customfields;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.customfields.impl.AbstractMultiCFType;
import com.atlassian.jira.issue.customfields.impl.FieldValidationException;
import com.atlassian.jira.issue.customfields.manager.GenericConfigManager;
import com.atlassian.jira.issue.customfields.persistence.CustomFieldValuePersister;
import com.atlassian.jira.issue.customfields.persistence.PersistenceFieldType;
import com.atlassian.jira.issue.customfields.view.CustomFieldParams;
import com.atlassian.jira.issue.fields.config.FieldConfig;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.jira.util.ErrorCollection;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import java.util.*;
import java.lang.Object;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
@Scanned
public class MultiProjectPickerField extends AbstractMultiCFType<String> {
@ComponentImport
private ProjectManager projectManager;
public MultiProjectPickerField(
@ComponentImport CustomFieldValuePersister customFieldValuePersister,
@ComponentImport GenericConfigManager genericConfigManager,
@ComponentImport ProjectManager projectManager
) {
super(
customFieldValuePersister,
genericConfigManager
);
this.projectManager = projectManager;
}
@Override
protected Comparator<String> getTypeComparator() {
return null;
}
@Override
protected Object convertTypeToDbValue(String value) {
return value;
}
@Override
protected String convertDbValueToType(Object dbValue) {
return (String) dbValue;
}
@Override
protected PersistenceFieldType getDatabaseType() {
return PersistenceFieldType.TYPE_LIMITED_TEXT;
}
@Override
public String getStringFromSingularObject(String stringFormObject) {
return stringFormObject;
}
@Override
public String getSingularObjectFromString(String objectFromString) throws FieldValidationException {
return objectFromString;
}
@Override
public void validateFromParams(CustomFieldParams customFieldParams, ErrorCollection errorCollection, FieldConfig fieldConfig) {
}
@Override
@SuppressWarnings("unchecked")
public Collection<String> getValueFromCustomFieldParams(CustomFieldParams customFieldParams) throws FieldValidationException {
return customFieldParams.getAllValues();
}
public Map<String, Object> getVelocityParameters(
final Issue issue,
final CustomField field,
final FieldLayoutItem fieldLayoutItem
) {
final Map<String, Object> velocityParams = super.getVelocityParameters(issue, field, fieldLayoutItem);
// This method is also called to get the default value, in
// which case issue is null so we can't use it
if (field != null && issue != null) {
final Map<String, String> selectedProjectsMap = new HashMap<>();
List<String> projects = new ArrayList<>();
for (final Project project : projectManager.getProjectObjects()) {
projects.add(project.getName());
}
velocityParams.put("projects", projects);
ArrayList testing = (ArrayList) field.getValue(issue);
try {
for (Object o : testing) {
String str = (String) o;
selectedProjectsMap.put(str, projectManager.getProjectObjByName(str).getKey());
}
} catch (Exception e) {
}
velocityParams.put("selectedProjects", selectedProjectsMap);
}
return velocityParams;
}
@Override
public Object getStringValueFromCustomFieldParams(CustomFieldParams customFieldParams) {
return customFieldParams.getValuesForNullKey();
}
}
Edit.VM
#controlHeader ($action $customField.id $customField.name $fieldLayoutItem.required $displayParameters.noHeader)
<select class="select cf-select" size="5" id="$customField.id" name="$customField.id" multiple="multiple">
#foreach($project in $projects)
#set($selected = false)
#if($selectedProjects && $selectedProjects.keySet().contains($project))
#set($selected = true)
#end
<option
#if($selected)
selected="selected"
#end
title="$!project" value="$!project">$!project
</option>
#end
</select>
#controlFooter ($action $fieldLayoutItem.fieldDescription $displayParameters.noHeader)
C
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.