Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom drop down fields? #52

Open
SamirKharchi opened this issue Oct 19, 2020 · 10 comments
Open

Custom drop down fields? #52

SamirKharchi opened this issue Oct 19, 2020 · 10 comments

Comments

@SamirKharchi
Copy link

I am trying to create an issue with custom fields (drop downs!) but I always get a bad request response upon issue creation.

Custom fields I can set without problems but only string type fields. The two fields I would like to set are drop downs and nothing seems to work for them, the client call always returns a 400 bad request (Exception message: "Field 'Change Reason' cannot be set. It is not on the appropriate screen, or unknown.").

Here is how I try to set such a drop down field:

new Issue { Fields = new IssueFields { CustomFields = { {"customfield_10401", "Sonstiges"} } ...

I am not sure if it's fine to simply pass a string of the drop down item to select as the value. I also tried a single-entry anonymous array and id (e.g. 10305) instead of the value ("Sonstiges") but that didn't change anything. Is it possible to set a custom field that is a combobox?

Btw. the field is definetly available in the issue type (required even). And I can create the issue with a simple Jira CLI client without a problem. The field is also available when I use client.Server.GetFieldsAsync()

@toertchn
Copy link

We also had a lot of custom fields. What type is your CustomField?
For customfieldtypes:select and customfieldtypes:cascadingselect I use the following code:

[DebuggerDisplay("{Value}")]
class SelectCFType
{
    [JsonProperty("value")]
    public string Value { get; set; }

    public SelectCFType() { }

    public SelectCFType(string value)
    {
        this.Value = value;
    }
}

[DebuggerDisplay("{Value} => {child?.Value}")]
class CascadingSelectCFType : SelectCFType
{
    public CascadingSelectCFType child;

    [JsonIgnore]
    public string ChildValue
    {
        get { return child?.Value; }
    }

    public CascadingSelectCFType() { }

    public CascadingSelectCFType(string value) : base(value) { }

    public CascadingSelectCFType(string value, string child)
    {
        this.Value = value;
        this.child = new CascadingSelectCFType(child);
    }
}

To get the values:

var issue = await Client.Issue.GetAsync("TICKET-1");
var category = JsonConvert.DeserializeObject<CascadingSelectCFType>(issue.Fields.CustomFields[OwnJiraFields.Category].ToString());
var grund = JsonConvert.DeserializeObject<SelectCFType>(issue.Fields.CustomFields[OwnJiraFields.Grund].ToString());

And the update part:

var updateIssue = new IssueEdit();
updateIssue.Fields = new Dapplo.Jira.Entities.IssueFields();
//updateIssue.Fields.Priority = new Priority { Name = "High" };
updateIssue.Fields.CustomFields.Add(OwnJiraFields.Menge, "1");
updateIssue.Fields.CustomFields.Add(OwnJiraFields.Category, new CascadingSelectCFType("Abteilung", "Extern"));
updateIssue.Fields.CustomFields.Add(OwnJiraFields.Grund, new SelectCFType("Beschwerde"));

await Client.Issue.EditAsync("TICKET-1", updateIssue);

@Lakritzator
Copy link
Member

Lakritzator commented Jan 3, 2021

I'd love to hear how I can simplify that process @toertchn ?

What about a:
issue.GetCustomField<ctype>(string fieldName)
and
issue.AddCustomField(string fieldName, object)

Your "get value" code might look like this:

var issue = await Client.Issue.GetAsync("TICKET-1");
var category = issue.GetCustomField<CascadingSelectCFType>(OwnJiraFields.Category);
var grund = issue.GetCustomField<SelectCFType>(OwnJiraFields.Grund);

And the update part:

var updateIssue = new IssueEdit();
updateIssue.AddCustomField(OwnJiraFields.Menge, "1");
updateIssue.AddCustomField(OwnJiraFields.Category, new CascadingSelectCFType("Abteilung", "Extern"));
updateIssue.AddCustomField(OwnJiraFields.Grund, new SelectCFType("Beschwerde"));

await Client.Issue.EditAsync("TICKET-1", updateIssue);

Other suggestions are also welcome.

Lakritzator added a commit that referenced this issue Jan 4, 2021
@Lakritzator
Copy link
Member

I've implemented what I suggested, it's in PR #63 you can see the code how it could work here:

public async Task Test_Create_and_Retrieve_IssueWithCustomFields()

I'd love to get some feedback on this...

@Lakritzator
Copy link
Member

Btw.. In the example code I use e.g. "customfield_10001", but this is the name I used to create the field, in the code it will figure out the read ID. I was also confused, this shows how complex the part of getting the right custom field IDs is...

@toertchn
Copy link

toertchn commented Jan 4, 2021

Thank you - I try to test it on my next free day (maybe 6.1.2021)

To get all fields with type and schema you can call:
https://www.jiraserver.com/rest/api/2/field

There you can find the id, name, name of the field in clauses and the type.

All known implementations of the CustomFieldType are listet there:
https://docs.atlassian.com/software/jira/docs/api/8.5.3/com/atlassian/jira/issue/customfields/CustomFieldType.html

Our Jira server hosts the whole Company. So we have nearly 400 different custom fields over all projects. This is also the reason why I don't need all this information in the results. This costs a lot of traffic.

The hardest part is testing all these different things.

@Lakritzator
Copy link
Member

Lakritzator commented Jan 4, 2021

Thank you - I try to test it on my next free day (maybe 6.1.2021)

Ah yes, Heilige Drei Könige! Due to the epidemic I don't have many days, as I need them for my kid, so I'm glad we have at least one "Feiertag"

To get all fields with type and schema you can call:
https://www.jiraserver.com/rest/api/2/field
There you can find the id, name, name of the field in clauses and the type.

Yes, var fields = await Client.Server.GetFieldsAsync();

All known implementations of the CustomFieldType are listed there:
https://docs.atlassian.com/software/jira/docs/api/8.5.3/com/atlassian/jira/issue/customfields/CustomFieldType.html

I think will add a FieldDomain for this, to have better field support (creating etc.).

Our Jira server hosts the whole Company. So we have nearly 400 different custom fields over all projects. This is also the reason why I don't need all this information in the results. This costs a lot of traffic.

Sounds very familiar, it's the same with the company I work for.
Maybe I will also consider caching, or a way you can plug-in your own cache.
There is also another way to get the fields for a project, might make sense to provide multiple ways to do this.

The hardest part is testing all these different things.

Yeah, in this case I already tested the code, as what I pointed to is the unit test for the field handling.

@toertchn
Copy link

toertchn commented Jan 6, 2021

The extensions AddCustomField & GetCustomField works as expected.

There exists an api for custom fields (api/2/customFields) but I'm just a little admin without the rights to access them.

So I found the api createmeta

https://jiraserver/rest/api/2/issue/createmeta?projectKeys=PROJECTKEY&expand=projects.issuetypes.fields
Gets all fields, custom fields and allowedValues ... but it's marked as deprecated.

The new way seems to be:
https://jiraserver/rest/api/2/issue/createmeta/PROJECTKEY/issuetypes
To get all issuetypes for the project and later call
https://jiraserver/rest/api/2/issue/createmeta/PROJECTKEY/issuetypes/ISUETYPEID
to get the rest of the definition.

But this doesn't list me one custom field we use. Don't know why. I also can't check this but i can imagine that a custom field also needs to be assigned to a project to get listet there? Its correctly listed in the GetFieldsAsync() result.

@Lakritzator
Copy link
Member

Lakritzator commented Jan 6, 2021

But this doesn't list me one custom field we use. Don't know why. I also can't check this but i can imagine that a custom field also needs to be assigned to a project to get listed there? Its correctly listed in the GetFieldsAsync() result.

That is actually valuable information, thanks

@toertchn
Copy link

toertchn commented Jan 9, 2021

Can you change the GetCustomField(this Issue issue, string customFieldName) to return null if the requested field ist null?

The question mark should do the fix:
return issue.Fields.CustomFields[customFieldName]?.ToString();

Lakritzator added a commit that referenced this issue Jan 10, 2021
@Lakritzator
Copy link
Member

I did this but I've also change the code to include a TryGetCustomField, otherwise you don't know the difference between a null value and not having the field at all. Also I've added a HasCustomField.

Lakritzator added a commit that referenced this issue Oct 18, 2021
Improvements of custom field usage as suggested in #52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants