I recently created my first Forge app. It is a simple text field that counts the number of Helpscout links added to a Jira issue.
My hope is to use this as a way of prioritizing feature requests and bug reports in Jira.
I have successfully
created the field
attached it to an issue
calculated the correct number of links
had the Scout Count field show in JQL
The last problem that I just can’t seem to get is that the JQL cannot search or sort the values of the field. i.e. “Scout Count” > 0 returns nothing, even though there are issues with a correctly calculated number above zero.
I have also determined that the field is set to be searchable and sortable by fetching it.
I know that the fieldID is correct as the JQL search field suggests it
I feel like it has to do with the idea that it’s an unknown field type, but I have not been able to find how to adjust that. The manifest says it’s a number and I’ve tried to apply the type and searcher key.
This is my index.jsx
import api from '@forge/api';
import ForgeUI, { CustomField, CustomFieldEdit, render, Text, TextField, useProductContext, useState, Badge} from "@forge/ui";
//get the remote web links for the current issue
const fetchLinksForIssue = async (issueId) => {
const response = await api.asApp().requestJira(`/rest/api/3/issue/${issueId}/remotelink`);
let scouts = 0,
urlText = "";
const data = await response.json();
//count the HelpScout links
for(let i = 0; i < data.length; i++) {
urlText = data[i]["object"]["url"];
if(urlText.includes("helpscout")) {
scouts += 1;
}
}
return scouts;
};
function setFieldOptions (fieldId) {
var bodyData = `{
"searcherKey": "com.atlassian.jira.plugin.system.customfieldtypes:exactnumber",
"type": "com.atlassian.jira.plugin.system.customfieldtypes:textfield"
}`;
let response = api.asApp().requestJira('/rest/api/3/field/{fieldId}', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: bodyData
});
//console.log(bodyData);
console.log('Are my prints even working?' + response);
};
const View = () => {
const context = useProductContext();
const [fieldValue] = useState(async () => await fetchLinksForIssue(context.platformContext.issueKey));
setFieldOptions(10035);
return (
<CustomField>
<Text>
<Badge appearance = 'primary' text ={fieldValue} />
</Text>
</CustomField>
);
};
const Edit = () => {
const onSubmit = values => {
return values.text
};
return (
<CustomFieldEdit onSubmit={onSubmit}>
<TextField name="text" label="Say hello to:"></TextField>
</ CustomFieldEdit>
);
}
export const runView = render(
<View/>
);
export const runEdit = render(<Edit/>)
This is my manifest.yml, excluding app:id
modules:
jira:customField:
- key: scoutcount
name: Scout Count
description: A count of HelpScout links for an issue.
type: number
validation:
expression: value == null || (value >= 0)
errorMessage: The value must consist only of numbers
readOnly: true
function: main
edit:
function: edit
function:
- key: main
handler: index.runView
- key: edit
handler: index.runEdit
app:
name: scoutCount
permissions:
scopes:
- manage:jira-configuration
- read:jira-work
- write:jira-work
- storage:app