core-geonetwork icon indicating copy to clipboard operation
core-geonetwork copied to clipboard

GeoNetwork app as web components.

Open fxprunayre opened this issue 2 years ago • 11 comments

Add support to embed GeoNetwork app in other website using webcomponents and evaluate what are the limitation of using webcomponents with current libraries.

The web component can be added using an iframe or as shadow DOM mode. Custom configuration can be defined to customize the app. Webcomponent can only show a full text box with some facets

image

or the search app only

image

or the full app. Use the UI configuration to configure your component.

Webcomponent can facilitate embedding of GeoNetwork in another website. In theory, it will help avoiding JS and CSS conflicts compared to trying to embed the JS app directly in the page by providing some isolation (as it is done in Sextant https://sextant.ifremer.fr/Donnees/Catalogue). This PR evaluates what are the limitation and difficulties and demonstrate what is operational.

Examples

Examples are available http://localhost:8080/geonetwork/catalog/webcomponents/index.html

The UI configuration is used to customize the component. Examples demonstrate how to add a simple search box which can point to your catalogue, display numbers using facets, show a simple list of results corresponding to a particular search, embed the map viewer...

image

image

Shadow DOM mode

To embed GeoNetwork in a page use:

<gn-app url="http://localhost:8080/geonetwork"
                portal="srv"
                config='{"mods": {
                  "home": {"enabled": false},
                  "footer": {"enabled": false},
                  "header": {"enabled": false}
                  }}'></gn-app>

<script src="webcomponents.js"></script>

When using shadow DOM mode, fonts used in the application needs to be loaded in the main HTML page. This is done by adding gn_web_components.css in the parent page.

Angularjs does not allow to be loaded more than once, so adding 2 webcomponents using shadow DOM mode will trigger WARNING: Tried to load AngularJS more than once. Use iframe mode instead.

Iframe mode

To embed GeoNetwork in a page use:

    <gn-app-frame
      url="http://localhost:8080/geonetwork"
      portal="srv"
      config='{"mods": {
                  "home": {"enabled": false},
                  "footer": {"enabled": false},
                  "header": {"enabled": false}
                  }}'
    ></gn-app-frame>

<script src="webcomponents.js"></script>

Iframe mode is less responsive in height compared to the shadow DOM mode which automatically extend itself.

Other example with third party HTML page layout

image

image

Changes:

  • [x] Home page / Add configuration to customize information tabs
  • [x] Home page / Add support to link to the catalogue if only the home page is in a webcomponent
  • [x] Hotkeys / Add configuration to disable keyword shortcuts
  • [x] Library / jQuery / Listen events on shadow root https://github.com/jquery/jquery/issues/4317 - changes backported in this PR
  • [x] Library / Bootstrap / Interaction with document.body not accessible from the webcomponent (eg. popover, dropdown) - Add the possibility to set a context root node (which is not document - https://github.com/geonetwork/core-geonetwork/blob/0b89278c1b05042ed3ffbbb85d1dffa63ce3901e/web-ui/src/main/resources/catalog/lib/bootstrap.js#L28-L29).

image

Known limitations

  • 2 webcomponent using Shadow DOM mode can't be included in the same page due to angularjs limitation. For better webcomponent support migration to more modern UI framework would be required.
  • All bootstrap JS components may not work properly when embedded using Shadow DOM mode (but the default home and search apps work fine)

Funded by Ifremer

fxprunayre avatar Aug 29 '22 14:08 fxprunayre

Nice! this looks a little bit like the approach we experimented in Sextant. One of the big limitations I found is that jQuery is global to the document, so you might have conflicts and other unexpected issues. For instance the bootstrap dropdowns and modals do not work in that configuration.

Fonts are always a bit annoying in web components since (at least in current browsers) they are not used if they are not defined in the host document as well, but that can be worked around with a bit of code (like you did for icons).

Also I think this part here is risky: https://github.com/geonetwork/core-geonetwork/blob/c2ee8381a9ff5544d8db48f3ac60c48be9e67818/web-ui/src/main/resources/catalog/webcomponents/webcomponents.js#L30

IMO this needs some sanitizing to make sure that baseUrl does not contain malicious code (same with portal).

jahow avatar Aug 29 '22 14:08 jahow

Do you have options to solve "the big limitations"? It looks like the main point is that the $ fn is contextualized to document and in web component case, it would be needed to contextualize it to the root of the shadowDOM. Not sure if we can override this.

fxprunayre avatar Aug 30 '22 06:08 fxprunayre

Do you have options to solve "the big limitations"? It looks like the main point is that the $ fn is contextualized to document and in web component case, it would be needed to contextualize it to the root of the shadowDOM. Not sure if we can override this.

Last time I checked, the option to "hack" jQuery to work with the component root instead of the document was tempting but not really feasible in practice (that would mean changing many different parts of the jquery code and create a maintenance nightmare).

Another option would be to rewrite all the components and directives relying on bootstrap/jquery with custom ones. This would be a lot of work but theoretically doable.

I think it's worthwhile to put that in perspective with the actual benefits from using web components instead of an iframe:

  • an iframe provide an even higher level of encapsulation at the cost of some security limitations (which we solved in Sextant I think)
  • the main downside of the iframe is that nothing can go "out" (e.g. modals), and it cannot determine its own size
  • it is still possible to provide a similar API for including GeoNetwork as you did in that PR, but instead of
    <gn-app url="http://localhost:8080/geonetwork"
            portal="srv"
            config='{"mods": {"map": {"enabled": false}}}'>
    </gn-app>
    <script src="webcomponents.js"></script>
    
    you would do something like
    <script src="webcomponents.js"
            url="http://localhost:8080/geonetwork"
            portal="srv"
            config='{"mods": {"map": {"enabled": false}}}'>
    </script>
    
    and this script would be responsible for creating the iframe for example (or including the angularjs application right in the page like in Sextant).

jahow avatar Aug 30 '22 08:08 jahow

or other options, upgrade bootstrap maybe ?

fxprunayre avatar Aug 30 '22 08:08 fxprunayre

or other options, upgrade bootstrap maybe ?

Boostrap 5 does not use jquery any more, so it might work better in a shadow DOM (to be confirmed). Upgrading Bootstrap would be quite the undertaking though, probably comparable to rewriting the modals/dropdowns/datepicker/etc. directives.

Sorry for not having better alternatives. As a matter of fact this situation was one of the big motivations for starting the gn-ui project.

jahow avatar Aug 30 '22 08:08 jahow

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

sonarqubecloud[bot] avatar Sep 12 '22 14:09 sonarqubecloud[bot]

Impressive work, did you manage to avoid having conflicts if jquery is also included in the host page? This was very common in Sextant, two versions (sometimes more) of jquery with different versions would end up being in conflict.

jahow avatar Feb 12 '24 12:02 jahow

Quality Gate Passed Quality Gate passed

Issues
0 New issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

sonarqubecloud[bot] avatar Feb 13 '24 16:02 sonarqubecloud[bot]

@fxprunayre maybe you missed my last question, I'd be keen to hear whether you managed to avoid conflicts when jquery is already in the page, as this isn't listed in the limitations. Thanks!

jahow avatar Feb 14 '24 08:02 jahow

did you manage to avoid having conflicts if jquery is also included in the host page? This was very common in Sextant, two versions (sometimes more) of jquery with different versions would end up being in conflict.

So far, we did not observed issue related to that. Adding a JQuery version in the webcomponent test pages does not look to introduce issues.

fxprunayre avatar Mar 28 '24 10:03 fxprunayre