Extract Live Data to make it reusable outside XWiki

Hello all,

With @surli we are currently working on the definition of reusable UI elements. By reusable, I mean that the UI elements are customizable enough to be applicable in other projects than XWiki. The main other project we have in mind is Cristal, but it is conceptually not the only one.

In this context, we are currently studying how to refactor the Live Data (LD) webjar to make it reusable.

I have a PoC of the extraction of the UI elements themselves. Which is relatively straightforward except for the bundling and packaging issues that are not relevant to the current discussion. What I’d like to discuss here is the extraction and generalization of the application logic. Currently, while I have extracted the UI part, the only backend to which LD can connect is XWiki (instead of arbitrary backends).

A note on how LD is working currently

There are two “API” ways to add an LD:

Implementation-wise, the two methods share the same parameters and call the same logic that does the following steps:

  1. Call jsfx to inject uicomponents/widgets/liveData.js
  2. Generate an HTML div element with the following properties:
  • Two classes: liveData and loading

  • Optionally an id

  • A data-config property with a serialization of the resolved configuration

  • A data-config-content-trusted set to true when the user has enough rights to define sanitation.

  • through uicomponents/widgets/liveData.js a jQuery initialization script is called. This script observes for div elements with a liveData class and performs a complex series of actions that can be summarized to

    1. Initialize a Vue application with a XWikiLivedata as its root, and mount it on div.liveData
    2. Inject a “logic” instance, which is the component that deals with the business logic.

Limitations in the context of reuse

The initialization process of LD makes sense in the context of XWiki but isn’t good for reuse.

Assuming LD would be reused inside Vue applications (or inside web apps in general with web components, but that’s another discussion), all the div substitution logic must be avoided.

Instead, we need to aim for a Vue component that can simply be called with the right parameters (or props, as they call them) and then let the library do its usual job.

Discussions

Do we consider the XWikiLivedata component API?

As explained earlier, the two main entry points to add an LD for XWiki developers are currently a wiki macro and a velocity script service.

The XWikiLivedata component itself is currently never publicly exposed and cannot be imported outside the LD webjars.

Therefore, I’d like to confirm that this component is not considered an API and that we can freely change its API to make it more (re)usable.
Note that at the end of this refactoring, XWikiLivedata would become API (and unstable of course).

Do we want to make the logic resolution internal or external?

In the case of an internal resolution, no specific logic is passed when the component is declared.

It’s the job of the component to look up the relevant component based on its context (e.g., an “XWiki” logic in the case of XWiki).

We could imagine having a global configuration for the default logic to look for and an optional component parameter to override it.

In the case of an external resolution, the caller of the LD component is responsible for resolving the logic and for passing the resolved object when declaring the component. The LD component is then only dependent on the LD logic API and does not have to perform lookup.

I tend to prefer the internal resolution logic as it allows for a simpler component encapsulation.

PS: I’ll make a separate proposal for how client side inversion of control can help.

Do we want to declare an abstract API already

The end goal of the LD extraction is to have a backend-agnostic API allowing the declaration of connectors to arbitrary backends by extension.

We could, for instance, have a LiveDataLogic (to keep the existing terminology) “role” and implementations like XWikiLiveDataLogic or FileSystemLiveDataLogic.

But, since we currently have domain knowledge of XWikiLiveDataLogic only, there is a risk of defining LiveDataLogic by relying overly on XWiki, with the risk of having to introduce breaking changes when applying it for another domain.

So I can think of two strategies.

Option 1: Extract the API

Declare an API early and accept the risk and declare the API now. Since we are early in the 18 cycle, the API will be left to be considered stable at the start of the 20 cycle which leaves us almost 2 years.

Option 2: Do not extract an API

Only have an XWiki specific logic (which is basically moving the current logic to its own package), and wait for the need to connect to another connector before extracting a generic API.

This goes well with the internal resolution discussed above since the API would leak in the LD component interface.

I tend to prefer option 2 as it allows us to break the extraction into smaller steps and leaves us a bit of time before exposing APIs.

I have started to write a design page https://design.xwiki.org/xwiki/bin/view/Proposal/LiveDataextractionforreuse

Not answering the other questions as I don’t have enough knowledge.

Let me try to provide input to the following:

One use case we have (albeit being a secondary use case), is to make LD usable inside Cristal Standalone, and thus without an XWiki backend. For example, by defining static data to be displayed in a LD (the data could be stored in the macro content or a wiki page, using a certain format). I think this means being able to implement a different LD source (which would control how it gets its data). But for this to work, we need to define the expected source output format, ie the format of the data to be displayed in the table.

So I don’t know if we need an API but we do need at least to have a defined data format, no?

Thanks

The PR is here XWIKI-23908: Extract Live Data to make it reusable outside XWiki by manuelleduc · Pull Request #5098 · xwiki/xwiki-platform · GitHub
I ended up extracting an API in the form of types for the concepts that are used:

  • inside Live Data vue components
  • in the piece of code I extracted to keep the xwiki-specific code in a separate package