Skip to content

Conversation

@calebtrepowski
Copy link
Contributor

@calebtrepowski calebtrepowski commented Nov 11, 2025

This is the first approach for #92, retrieving custom fields in hydrated time entries.
Next steps include:

  • Parsing custom fields in time entry creation command
  • Including custom field in DTO during time entry creation in API call

Description

Include CustomFields attribute in TimeEntry DTO. Modify CustomField DTO to match APIs response. Parse custom field values to CSV and Markdown reports.

  • CSV Report
    Add new column customFields... at end.
    Format is:
    CustomField1Name(CustomField1Id)=CustomField1Value;CustomField2Name(CustomField2Id)=CustomField2Value

Modify column tags.... Semi-colon is now the separator between multiple tags. This is a breaking change for CSV reports. New format is:
Tag1Value(Tag1Id);Tag2Value(Tag2Id)

  • Markdown Report
    Added row Custom Fields with pairs key: value separated by commas. Example:
_Time and date_
**1:00:00** | 19:00 - 20:00 🗓 11/02/2025

|                 |                                                                            |
|-----------------|----------------------------------------------------------------------------|
| _Description_   | Some task                                                                  |
| _Project_       | **My Project**                                                             |
| _Tags_          | My Tag 1, My Tag 2                                                         |
| _Billable_      | No                                                                         |
| _Custom Fields_ | Custom Field 1: Custom field value 1, Custom field 2: Custom field value 2 |

Include `CustomFields` attribute in TimeEntry DTO. Modify CustomField
DTO to match APIs response. Parse custom field values to CSV and
Markdown reports.

- CSV Report
Add new column `customFields...` at end.
Format is:
CustomField1Name(CustomField1Id)=CustomField1Value;CustomField2Name(CustomField2Id)=CustomField2Value

Modify column `tags...`. Semi-colon is now the separator between
multiple tags. This is a breaking change for CSV reports.
New format is:
Tag1Value(Tag1Id);Tag2Value(Tag2Id)

- Markdown Report
Added row _Custom Fields_ with pairs `key: value` separated by commas.
Example:
```md

_Time and date_
**1:00:00** | 19:00 - 20:00 🗓 11/02/2025

|                 |                                                                            |
|-----------------|----------------------------------------------------------------------------|
| _Description_   | Some task                                                                  |
| _Project_       | **My Project**                                                             |
| _Tags_          | My Tag 1, My Tag 2                                                         |
| _Billable_      | No                                                                         |
| _Custom Fields_ | Custom Field 1: Custom field value 1, Custom field 2: Custom field value 2 |
```
@calebtrepowski calebtrepowski changed the title feat: add support for custom fields in report feat: #92 add support for custom fields in report Nov 11, 2025
Copy link
Owner

@lucassabreu lucassabreu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @calebtrepowski , since some people don't have access/use the custom fields i think would be good to add a new config for the person to tell if they want it on the reports.

similar to how i did for the tasks column, can you setup a new config "show-custom-fields" for it?

if options.ShowTasks {

if config.GetBool(cmdutil.CONF_SHOW_TASKS) {
opts = opts.WithShowTasks()
}

Example column:

```
+---------------------------------------------------------------+
|                         CUSTOM FIELDS                         |
+---------------------------------------------------------------+
| Custom Field 1(5e4117fe8c625f38930d57b7)=Custom field value 1 |
| Custom field 2(5e4117fe8c625f38930d57b8)=Custom field value 2 |
| Custom field 3(5e4117fe8c625f38930d57b9)=Custom field value 3 |
+---------------------------------------------------------------+
```

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Add config for custom field with value `show-custom-fields`.

Add custom fields column in default report conditionally
based on this new config.

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Additionally remove extra line in markdown template.

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
updateFlag(i, config, cmdutil.CONF_SHOW_TASKS,
`Should show task on time entries as a separated column?`,
),
updateFlag(i, config, cmdutil.CONF_SHOW_CUSTOM_FIELDS,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi, i think you will need to add tests to this:

c.ExpectString("show task on time entries")
c.SendLine("")
c.ExpectString("Yes")

you can run make test to see where it fails

Include custom fields option.

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Since config is not passed to mardown time entries report, the condition
to show custom fields row is based on the existance of any of them.

If there are no custom fields, or there are custom fields with empty
values, the row is not displayed. However the tests are updated to
match the padding for the `Custom fields` row in the first column.

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Custom field value can be either a string or an array of strings. The
DTO is modified to support both types, and a function is added as getter
of the value. Single string is returned as-is, multiple strings are
joined together using `|` as separator.

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
@calebtrepowski
Copy link
Contributor Author

calebtrepowski commented Nov 21, 2025

Hi @lucassabreu! Sorry for the delay, haven't had much time lately.

I have updated the test for the init config command, it now does support the custom field param!

Also I have updated the markdown report tests. I had some trouble there because it happens that custom field can be of type "dropdown multiple", and in that case the value field in the json is an array of strings rather than a string (found this testing with a real workspace, didn't found in the documentation).
Since Go does not support type unions, the alternative solution I've implemented is to modify the DTO type for the field to interface{} (equivalent to any) and use a getter function to get the value always as a string. Maybe not the most elegant implementation, do you have any improvement suggestion on this?
In case there are multiple values, instead of using again comma (,) or semi-colon (;) as separator, to avoid confusion in csv, markdown and default report formats, it came to my mind that could be possible to use the & symbol, but reading the text itself seemed to me that the pipe (|) is more friendly to execute the join of the values. So an example output for a time entry with a multiple-value custom field would be:

## _Time Entry_: 123456abcdef

_Time and date_
**1:00:00** | 22:00 - 23:00 🗓 11/11/2025

|                 |                                                                              |
|-----------------|------------------------------------------------------------------------------|
| _Description_   | Another description                                                          |
| _Project_       | No Project                                                                   |
| _Tags_          | No Tags                                                                      |
| _Billable_      | No                                                                           |
| _Custom Fields_ | My first custom field: Option 2, my multiple custom field: Option 1|Option 2 |

Having your recommendation in mind that not everyone uses or has access to custom fields, and since in markdown report we don't have access to the opts object, I have chosen to not show custom fields row if there aren't any or if the value is empty.

Finally, there were some trailing spaces in the markdown template, specifically in _Time and date_ line, so I deleted them and updated the tests to match the new output :).

Since the last review it's been more than just adding tests, so pleased to know your thoughts on all of this!

## _Time Entry_: {{ .ID }}

_Time and date_
_Time and date_
Copy link
Owner

@lucassabreu lucassabreu Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are necessary to markdown interpreters to know that the line break is intensional

Suggested change
_Time and date_
_Time and date_

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I've just uploaded the fix

These are necessary to markdown interpreters to know that the line break
is intentional.

Signed-off-by: Caleb Trepowski <calebtrepowski@gmail.com>
@lucassabreu lucassabreu merged commit 2418227 into lucassabreu:main Nov 24, 2025
6 of 7 checks passed
@lucassabreu
Copy link
Owner

k11m1 added a commit to k11m1/clockify-cli-flake that referenced this pull request Dec 30, 2025
This repository is superseded by the original repository
lucassabreu/clockify-cli#282
lucassabreu/clockify-cli#280
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

Successfully merging this pull request may close these issues.

2 participants