I am trying to retrieve all the fields that get presented when one clicks Edit Issue in a specific project, including custom fields. Then later on show these on the UI in my plugin.
As far as my development and test environments go I thought I had achieved this with, but trying it out in a production environment has shown me that there are some fields missing and I can not find the root cause of it.
I had to obfuscate sanitise the code. But I tried to include as much as I can to provide a full picture, hoping it will be easier to understand. I know that the both methods are very similar to each other, refactoring and optimising would be my next step but I must use 2 methods because of the underlying architecture.
Thank you.
This is how I retrieve the Mandatory Fields:
@Override
public List<JsonObject> getMandatoryFields(String projectKey, String issueTypeName) {
Project project = projectManager.getProjectByCurrentKey(projectKey);
Optional<IssueType> optionalIssueType = getIssueTypeObjectByName(issueTypeName);
if (projectKey.isEmpty() || issueTypeName.isEmpty() || !optionalIssueType.isPresent()) {
return new ArrayList<>();
}
FieldLayoutManager fieldLayoutManager = ComponentAccessor.getFieldLayoutManager();
FieldLayout fieldLayout = fieldLayoutManager.getFieldLayout(project.getId(), optionalIssueType.get().getId());
List<FieldLayoutItem> mandatoryFieldLayoutItems =
fieldLayout.getRequiredFieldLayoutItems(project, Collections.singletonList(optionalIssueType.get().getName()));
List<JsonObject> fields = new ArrayList<>();
for (FieldLayoutItem fieldLayoutItem : mandatoryFieldLayoutItems) {
OrderableField<Object> orderableField = fieldLayoutItem.getOrderableField();
String fieldId = orderableField.getId();
JsonObject fieldAsJson = new JsonObject();
fieldAsJson.addProperty(KEY_ID, fieldId);
String fieldName = orderableField.getName();
fieldAsJson.addProperty(KEY_NAME, fieldName);
String fieldDescription = fieldLayoutItem.getRawFieldDescription();
fieldAsJson.addProperty(KEY_DESCRIPTION, fieldDescription == null ? DEFAULT_FIELD_DESCRIPTION : fieldDescription);
fields.add(fieldAsJson);
}
return fields;
}
And here is how I retrieve the remaining optional fields:
@Override
public List<JsonObject> getOptionalFields(String projectKey, String issueTypeName) {
Project project = projectManager.getProjectByCurrentKey(projectKey);
Optional<IssueType> optionalIssueType = getIssueTypeObjectByName(issueTypeName);
if (projectKey.isEmpty() || issueTypeName.isEmpty() || !optionalIssueType.isPresent()) {
return new ArrayList<>();
}
FieldLayoutManager fieldLayoutManager = ComponentAccessor.getFieldLayoutManager();
FieldLayout fieldLayout = fieldLayoutManager.getFieldLayout(project.getId(), optionalIssueType.get().getId());
List<FieldLayoutItem> visibleOptionalFieldLayoutItems =
fieldLayout.getVisibleLayoutItems(project, Collections.singletonList(optionalIssueType.get().getName()));
List<FieldLayoutItem> optionalFieldsLayoutItems =
visibleOptionalFieldLayoutItems.stream().filter(e -> !e.isRequired()).collect(Collectors.toList());
Collections.sort(optionalFieldsLayoutItems, Collections.reverseOrder());
List<OrderableField> editScreenFields = getAllFieldsFromEditScreen(projectKey, issueTypeName);
List<JsonObject> optionalFields = new ArrayList<>();
for (FieldLayoutItem fieldLayoutItem : optionalFieldsLayoutItems) {
OrderableField<Object> orderableField = fieldLayoutItem.getOrderableField();
if (!editScreenFields.contains(orderableField)) {
continue;
}
String fieldId = orderableField.getId();
if (!"issuetype".equalsIgnoreCase(fieldId) && !"reporter".equalsIgnoreCase(orderableField.getName()) &&
!"attachment".equalsIgnoreCase(orderableField.getName())) {
JsonObject fieldAsJson = new JsonObject();
fieldAsJson.addProperty(KEY_ID, fieldId);
String fieldName = orderableField.getName();
fieldAsJson.addProperty(KEY_NAME, fieldName);
String fieldDescription = fieldLayoutItem.getRawFieldDescription();
fieldAsJson.addProperty(KEY_DESCRIPTION, fieldDescription == null ? DEFAULT_FIELD_DESCRIPTION : fieldDescription);
optionalFields.add(fieldAsJson);
}
}
return optionalFields;
}
All the retrieved fields later on get inserted with JS into the UI.
Which looks like this:
function addDynamicFieldsForProjectAndIssueType(index, value, identifier) {
let mandatoryFields = jQuery('#tcm-mandatory-fields-header');
let fieldId = value["id"];
let fieldName = value["name"];
let fieldDescription = value["description"] === "No description available" ? "" : value["description"];
let currentRow = $('<div class="ui-state-default g-row tcm-' + identifier + '-field"></div>');
let checkbox;
if (identifier == "mandatory") {
checkbox = '<div class="checkbox"><input class="checkbox" type="checkbox" id="checkbox-' + fieldId + '" name="' + fieldId + '[check]" checked disabled>' +
'<input name="' + fieldId + '[fieldtype]" value="mandatory" hidden><label for="checkbox-' + fieldId + '">' + fieldName + '</label></div>';
} else {
checkbox = '<div class="checkbox"><input class="checkbox" type="checkbox" id="checkbox-' + fieldId + '" name="' + fieldId + '[check]">' +
'<input name="' + fieldId + '[fieldtype]" value="optional" hidden><label for="checkbox-' + fieldId + '">' + fieldName + '</label></div>';
}
let inputField = '<input class="text" type="hidden" id="tcm-creation-optional-field-' + fieldId + '" name="' + fieldId + '[value]" value="' + fieldName + '">';
let description = ' <input class="text long-field" type="text" name="' + fieldId + '[description]"' +
'id="tcm-creation-issuetype-description" placeholder="No description available"' +
'value="' + fieldDescription + '"/></div>';
currentRow.append(checkbox);
currentRow.append(inputField);
currentRow.append(description);
$(".tcs-optional-fields-grid").append(currentRow);
mandatoryFields.after(currentRow);
}