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

Fixes #14329: Improve diffs for custom fields #14332

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

JCWasmx86
Copy link
Contributor

@JCWasmx86 JCWasmx86 commented Nov 23, 2023

Fixes: #14329

This improves the diff by comparing the changes dicts recursively. It changes the Diff and the Pre/Post-Change Data

image

That's one issue I found, but it seems unrelated, as even without my patch, the type of the floating-point field seems to change:
image

netbox/extras/views.py Outdated Show resolved Hide resolved
netbox/utilities/utils.py Outdated Show resolved Hide resolved
Copy link
Contributor

This PR has been automatically marked as stale because it has not had recent activity. It will be closed automatically if no further action is taken.

@github-actions github-actions bot added the pending closure Requires immediate attention to avoid being closed for inactivity label Mar 14, 2024
@netbox-community netbox-community deleted a comment from JCWasmx86 Apr 22, 2024
@jeremystretch
Copy link
Member

@arthanson @jeffgdotorg and I talked about this today. The consensus was that we need to address the inconsistency in how the summary difference and the pre-/post-change data are presented. Looking at the screenshot below, note that while the "difference" panel is accurate, the changes highlighted in the pre- & post-change panels still show the entire custom_fields as having changed. (@JCWasmx86 does call this out in the original PR description above.)

screenshot

IMO the pre-/post-change panel highlights should exactly match the summary above, or we should remove the highlighting in that section.

@JCWasmx86
Copy link
Contributor Author

JCWasmx86 commented Apr 23, 2024

I've implemented the requested changes: (Only works for custom_fields, not e.g. for tag lists) But it will only show the changed fields, asI'm not sure how to mix them with unchanged fields in an elegant manner

image

Sadly I wasn't able to find the reason that ffield changes from float to str despite just editing another custom field.

image

@jeremystretch jeremystretch removed the pending closure Requires immediate attention to avoid being closed for inactivity label Apr 24, 2024
@JCWasmx86
Copy link
Contributor Author

I've got it working in a somewhat unelegant manner.

image

image

I take the list of custom_fields, convert it into such a list:

[
  ('cf_name', 'cf_value', True)
  ('cf_name2', 'cf_value2', False)
]

And within django templates I parse this and transform this into JSON like that:

"custom_fields": {
  "cf_name": "cf_value" // Will be colored red/green as the third item in the tuple is True
  "cf_name2": "cf_value2" // Won't be colored, as it's False
}

sadly this won't work with MultiObject Custom Fields, as it would end up like this:

"custom_fields": {
  "cf_name": [
1,
2,
3,
]
}

For that I've created a custom template tag. It transforms a string by:

  • Preserving everything from the first line
  • Indenting everything else, so it looks aligned in the GUI

I don't claim this is the best solution, but it's honestly the only one I could come up with. I'm open for alternative ideas how to make this work

@JCWasmx86
Copy link
Contributor Author

JCWasmx86 commented May 6, 2024

Hello @jeremystretch,

I would love to get this merged in near future. Can you either review this (Especially how I solved those diffs in the Pre/Post Change Data!) please or give me a list of open points that are missing?

@JCWasmx86 JCWasmx86 force-pushed the develop branch 3 times, most recently from 8e51bcc to d765d95 Compare May 6, 2024 17:58
Comment on lines 735 to 742
cfr_list = []
if custom_fields_added:
for cf, cf_value in prechange_data['custom_fields'].items():
cfr_list.append((cf, cf_value, cf in custom_fields_added))
cfa_list = []
if custom_fields_removed:
for cf, cf_value in instance.postchange_data['custom_fields'].items():
cfa_list.append((cf, cf_value, cf in custom_fields_removed))
Copy link
Member

Choose a reason for hiding this comment

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

I'm afraid this sort of approach isn't going to be maintainable long-term. The diffing implementation needs to operate generically; we can't give custom fields specifically any special treatment. (Consider what changes would be needed to support some similarly structured field in a future release.) Ultimately, we want a solution that can follow nested data structures and roll back up their diffs, without any context about the data contained within.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I have one last idea how to implement this in a sane manner:

  • Dump "Object before" and "Object after into a formatted JSON-string => One Attribute = One line (Except for arrays/nested objects).
  • Diff line by line (With a bit of smartness for arrays/objects) into two lists removed and added that are just lists of (line_as_string, has_changed)
  • Convert the lists to HTML within the templates

Do you think this could be a more maintainable approach?

Copy link
Contributor Author

@JCWasmx86 JCWasmx86 May 26, 2024

Choose a reason for hiding this comment

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

I made this script: https://gist.github.com/JCWasmx86/95f449abf2a8958b22d0e48279b07ba7

Do you think that goes into the right direction? It's a bit less efficient than it could be, but I think it gives good results, e.g.

image

It works some-what generic on strings, but a sorted JSON-like thing (Like in the changelog pre/post data), it should work great

return substr


def make_diff(old: str, new: str):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will have to be cleaned up a bit, if you think this approach is better. If you don't think this approach has a future, this PR can be closed, as I'm out of ideas.

We basically just convert two strings (Before/After) into two lists of tuples (str, bool).

image

image

And it needs a few more tests, but I only write them if this approach has a future

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.

Improve diffs for custom_fields
2 participants