Skip to content

[18.0][ADD] web_json_widget - #3231

Open
len-foss wants to merge 2 commits into
OCA:18.0from
lambdao-dev:18.0-web_json_widget-len
Open

len-foss wants to merge 2 commits into
OCA:18.0from
lambdao-dev:18.0-web_json_widget-len

Conversation

@len-foss

Copy link
Copy Markdown
Contributor

Add a Json editor widget.
Supports edits, dark mode (should work on OCA's version, since it relies on setting the color_theme cookie to dark). Can even be put in a tree view, although you probably don't want to do that.

This module uses the library jsoneditor.
It is released under the Apache-2.0 license.

Screenshot_20250727_140139 Screenshot_20250727_140217

@len-foss
len-foss force-pushed the 18.0-web_json_widget-len branch from 68c5758 to b13df6a Compare July 27, 2025 12:50
@ivs-cetmix

Copy link
Copy Markdown
Member

Hello @len-foss and thank you for your contribution!
Could you please create a simple web_json_widget_demo module like this one that would serve as an example and also will allow to do functional review of your PR? Just add a field to the res.partner module same way as on your screenshot.

@len-foss

Copy link
Copy Markdown
Contributor Author

@ivs-cetmix should be ready to test 👍

@ivs-cetmix ivs-cetmix left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Perfect, thank you @len-foss!

Here are some glitches I encountered during testing on MacOs 15.6 (24G84) in Safari Version 18.6 (20621.3.11.11.3)

Issue 1

Steps to reproduce (on runboat)

  • In the second (text) key start typing "qwerty"

Expected behaviour

  • The entire string can be typed in without loosing the focus

Current behaviour

  • Need to click in the widget after each symbol is typed in. Eg "q" -> click, "w" -> click , ....

Issue2

Field properties drop down is rendered below the chatter buttons.

Video of both issues.

@len-foss
len-foss force-pushed the 18.0-web_json_widget-len branch from 26e4630 to 8cd2914 Compare August 17, 2025 14:53
@len-foss

Copy link
Copy Markdown
Contributor Author

@ivs-cetmix
First, thank you for the testing. This is valuable feedback.

Easy point 2; I've added a CSS rule to increase the z-index. Good catch.

So, point 1. I actually broke editing trying to do a "quick patch" of a very specific problem: if the user calls the record switcher while the recordset is dirty, the component does not go through onWillUpdateProps, like it does if changes were already saved. As a result, you'd get outdated data in these cases. I'm not sure what is the proper solution, but I followed the approach of the chatter (which is to keep track of the displayed record, so that we can update if it changed). In any case, everything should be working now.

@ivs-cetmix ivs-cetmix left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Functional review LGTM
@len-foss works now, thank you!
P.S. If you have LinkedIn we can promote this module to get more attention and have it merged faster 😄

};
static defaultProps = {};

setup() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your createEditor() already has a great docstring. Adding the same for setup() and detect_dark_mode() helps future developers:
/**

  • Setup lifecycle hooks and state initialization.
    • Tracks record resId and resModel
    • Binds editor creation on mount
    • Cleans up editor on unmount
      */
      setup() { ... }

/**

  • Detect if dark mode is active.
  • Currently relies on cookie color_scheme.
    */
    detect_dark_mode() { ... }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Currently, the code is pretty short, at barely a 100 lines of logic. Adding such fluff would only make it less readable, and would only serve a purpose if it was used by some automatic documentation generation tool, which aren't used within the project.

onChange: () => {
try {
const new_value = this.editor.get();
this.state.value = new_value;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

also update state with setter
this.state.value = { ...newValue };

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done 👍

@antoniodavid antoniodavid left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM

@OCA-git-bot

Copy link
Copy Markdown
Contributor

This PR has the approved label and has been created more than 5 days ago. It should therefore be ready to merge by a maintainer (or a PSC member if the concerned addon has no declared maintainer). 🤖

@ivs-cetmix

Copy link
Copy Markdown
Member

Hi @len-foss , could you please check the code review comment and reply or apply them? Would be really great to have your excellent module merged!

@len-foss

Copy link
Copy Markdown
Contributor Author

Hi @ivs-cetmix done 👍

Thank you @ShehbajTechultra for the suggestions.

@ivs-cetmix

Copy link
Copy Markdown
Member

@ShehbajTechultra could you please do an after-update review? Than you in advance!

@ShehbajTechultra ShehbajTechultra left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved

@ivs-cetmix

Copy link
Copy Markdown
Member

Approved

@ShehbajTechultra , perfect, thank you!
@len-foss could you please prepare the PR for merge?

@len-foss

Copy link
Copy Markdown
Contributor Author

@ivs-cetmix do you mean you prefer to have the commits squashed?

@ivs-cetmix

Copy link
Copy Markdown
Member

@len-foss , yes, we need to squash commits so we have two - one per module.

@len-foss
len-foss force-pushed the 18.0-web_json_widget-len branch from 9fa5534 to d700636 Compare August 26, 2025 18:51
@ivs-cetmix

Copy link
Copy Markdown
Member

Hey @OCA/web-maintainers looks like we have a new cool widget ready to join the OCA family. Would appreciate your review)

hbrunn
hbrunn previously requested changes Aug 29, 2025

@hbrunn hbrunn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread web_json_widget/__manifest__.py Outdated
# content from https://app.unpkg.com/jsoneditor@10.2.0/files/dist
# source: https://github.com/josdejong/jsoneditor?tab=readme-ov-file
# licenced under Apache-2.0 license
"/web_json_widget/static/src/lib/dark-theme.css",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

those usually go into /static/lib

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍

// Improvements: add supportedOptions, ExtractProps...
};

registry.category("fields").add("json_editor", JsonEditor);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd suggest

Suggested change
registry.category("fields").add("json_editor", JsonEditor);
registry.category("fields").add("json", JsonEditor);

because then Odoo should pick the widget automatically, given there's not standard json widget

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍

this.resId = this.props.record.resId;
this.resModel = this.props.record.resModel;
if (this.editor) {
this.editor.set(this.props.record.data[this.props.name] || {});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
this.editor.set(this.props.record.data[this.props.name] || {});
this.editor.set(this.state.value);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So, this one is pretty bad. Because of the very stupid OCA rule I squashed my commits, but basically if your recordset is dirty, using the record switcher makes it so that none of the widget lifecycle hooks are called. So, this.state.value is not updated, so you switch and the widget is not updated. I couldn't find anything that seemed to make sense and the odoo dev I asked was a clueless. This is inspired by how it's done by the mail JS code.

To clarify, onParched is a lifecycle hook but that is called continuously, whereas you'd want a 1-time one like onWillUpdateProps.

So, if there's a good explanation and solution, I'd like to know it.


const isDarkMode = this.detect_dark_mode();
if (isDarkMode) {
this.editorRef.el.classList.add("json-editor-theme-dark");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder why you don't do this in the template?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not sure exactly but the doc about the Json editor was a bit confusing to me, and I found confusing answers as to how to instantiate a dark version. I think the 'Odoo way' is to put that in a CSS without the dark mangling which is put into the dark assets bundle. As of now I find it simpler to keep it this way because I copy-pasted this from recommended setup, but it wouldn't be hard to change afterwards.

Comment thread web_json_widget/static/src/components/json_editor/json_editor.esm.js Outdated
@len-foss

Copy link
Copy Markdown
Contributor Author

@hbrunn
Regarding the test, in my opinion, it would be much more cost much more that what it's worth, so I won't implement it on my limited free time.
You're free to disagree of course, but I'm seeing test_web_systray_button_init_action make the tests red for everything, so consider the time lost for all (potential) contributors.

@flotho

flotho commented Apr 15, 2026

Copy link
Copy Markdown
Member

Hi @len-foss thnaks for your contribution.
Any chance to rebase ?

@simahawk simahawk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LG overall. Couldn't test as Runboat is hanging.

@@ -0,0 +1,11 @@
To insert a json editor in a form view, you can use the widget:
```xml
<field name="json_field" widget="json_editor"/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this needed since it's now registered for all json fields?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure this was a good idea, since in 19.0 there is a default json widget -- that is just a json string dump on the content (which I don't understand why you didn't have that since the introduction of the field).

So if you use json_editor, you can migrate without any view change, whereas json means it won't, you'll get the default one.

Comment thread web_json_widget_demo/models/res_partner.py Outdated
@len-foss
len-foss force-pushed the 18.0-web_json_widget-len branch from 1e7b2d0 to d56ccf9 Compare April 16, 2026 07:34
@OCA-git-bot OCA-git-bot added series:18.0 mod:web_json_widget_demo Module web_json_widget_demo mod:web_json_widget Module web_json_widget labels Apr 16, 2026
@len-foss

Copy link
Copy Markdown
Contributor Author

Rebased 👍

@simahawk

Copy link
Copy Markdown
Contributor

@hbrunn ping

@hbrunn
hbrunn dismissed their stale review September 15, 2026 17:17

won't continue reviewing this

@OCA-git-bot

Copy link
Copy Markdown
Contributor

This PR has the approved label and has been created more than 5 days ago. It should therefore be ready to merge by a maintainer (or a PSC member if the concerned addon has no declared maintainer). 🤖

@simahawk

Copy link
Copy Markdown
Contributor

@len-foss pls squash and I would set the maturity level to alpha if you don't mind (cheaper than adding tests 😉 )

@etobella

Copy link
Copy Markdown
Member

@simahawk it is true that alpha doesn't require tests, but we should encourage people to add them, isn't it? 😉

@simahawk

Copy link
Copy Markdown
Contributor

@simahawk it is true that alpha doesn't require tests, but we should encourage people to add them, isn't it? 😉

We should and we did (Holger did) and @len-foss didn't ignore that, he provided an answer.
Now, we have 2 choices:

  1. keep this PR stuck forever
  2. let it go and have someone using it for real

In this particular case, I'm for opt 2, but this is a democracy and you can still block the PR 😉

@etobella

Copy link
Copy Markdown
Member

@simahawk I was not going to block the PR don't worry for that. I already know how hard it is to add tests (even more JS). I can understand that it is not an easy step and it was not blocking me.

My only concern was that your comment could be interpreted as "add everything as alpha and then we don't need to care about tests" 😉 (I know what you were thinking and I agree, however I wanted to clarify to avoid confusion).

One last thing, @len-foss can you squash all commits in a single one?

@simahawk

Copy link
Copy Markdown
Contributor

My only concern was that your comment could be interpreted as "add everything as alpha and then we don't need to care about tests" 😉 (I know what you were thinking and I agree, however I wanted to clarify to avoid confusion).

Totally fair ☺️ Thank you!

@len-foss
len-foss force-pushed the 18.0-web_json_widget-len branch from d56ccf9 to 1c58802 Compare September 18, 2026 13:51
@len-foss

Copy link
Copy Markdown
Contributor Author

There's just the fact that in that version the widget is registered as json, which in 19.0 will migrate to the default Odoo json, which isn't editable; so I'd change that to json_editor by default, so that it's clean across migrations. Rebase/squashed commits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants