KlausSchaefers / quant-ux

Quant-UX - Prototype, Test and Learn
GNU General Public License v3.0
1.95k stars 200 forks source link

Contribution Guidelines, tagging issues #80

Closed TimHal closed 2 years ago

TimHal commented 2 years ago

It would be helpful to add contribution guidelines to streamline the development process.

Also making use of tags and labels or even a roadmap to coordinate the project. I would love to start contributing, adding some tags like "good-first-issue", "bug" or "feature" and also the state of approval for new feature ideas according to the teams vision of the project would be very helpful to get started.

KlausSchaefers commented 2 years ago

Hi Tim,

thanks for contacting me. I have a roadmap, but it is a simple .md file :D

Are you suggesting to make this more transparent and use issues? The tool has become quite complex, writing contribution guidelines and documentation will be a large effort. There is some documentation.

TimHal commented 2 years ago

Awesome, I think a md file would be nice, just some orientation for (potential) collaborators to see where the project will be going to judge if they can contribute in that direction.

That is a cool guide! But I thought more of using the github tags on the existing issues, especially to point out the "easier" ones like fixing typos or straight-forward bugs which people can use as stepping stones to start contributing to the project. Talking of which, I am going to spend a bit of time playing around with the current state now but would like to to help you with the development in the near future, any suggestions where to start?

KlausSchaefers commented 2 years ago

ok

KlausSchaefers commented 2 years ago

@TimHal: There is one big chunk of work ahead. Scripting. I would like to allow to include also "JavaScript" components, like the REST ones. The users could enter some simple JS script, e.g to hide elements or calculate something based on user data, e.g. the sum of an array.

This would require some sandboxing, and also the definition of a clean api. If you feel like working on this, let me know.

TimHal commented 2 years ago

Hi @KlausSchaefers , that sounds very interesting! I suppose it is related to #79 ? I would be very excited to give it a shot, I could start working on it from some time next week onwards. Do you already have an idea how this could fit nicely into the existing code base? And would the Luisa project require us to keep a Figma counterpart to these components in mind? (Sorry, I have not yet used Luisa, so I am not 100% sure if this question is relevant here)

KlausSchaefers commented 2 years ago

Hi,

Luisa shares some code with Quant-UX. The execution of the JavaScript would be one of these components. But that is a problem for a different time. I found some links about the topic:

- https://joyofcode.xyz/create-a-coding-sandbox
- https://www.figma.com/blog/how-we-built-the-figma-plugin-system/
- https://www.verygoodsecurity.com/blog/posts/iframes-as-a-security-feature
- https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
- https://www.npmjs.com/package/esprima
- https://github.com/acornjs/acorn
- https://www.skypack.dev/

I guess the easiest way would be to execute the custom JS in an Iframe and pass messages back and forth. I am not sure yet:

1) If we should have one big JS file with many functions? This would allow to resume some code if needed. For each JS element in the canvas, one would just have to select the right method. Or we have for each element a single JS file.

2) How the API should look like. I could image something like

function customCode () {
     // qux object is global and wraps messages
     data = qux.data

    // set data
    qux.data.order.sum = 42

   qux.getScreen('a').navigate()
   qux.getScreen('a').getWidget('textfield').setStyle({'hidden':true})

}

This are still very rough ideas... Any idea from your side?

TimHal commented 2 years ago

I think it mostly depends on the use cases we aim to support.

If it would be just the simple stuff like getting/setting attributes of elements and transitions such as fade-in or fade-out an API with exactly these functions would be sufficient. In that case I would not touch JS elements at all but allow simple building blocks like the ones for REST endpoints. Data aggregation could maybe be added directly to the containers (instead of showing the full list, just display the calculated sum?).

For arbitrary code execution a web worker seems reasonable. It would allow for a reasonable isolation (no unsafe-eval in main thread), not block the UI and could be killed by the main thread. In that case we should expose the application state and context to the worker whenever it gets executed. I think it could look something like this:

async function run(quxState, quxContext) {
    // aggregate the sum of some input and post it back to the main thread
    const sum = quxContext.data["random_numbers"].readuce((a,c) => a+c, 0);

    // if the sum is 0, request the main thread to hide "my_image"
    if (sum === 0) {

        // this actually sends a message to the main thread, requesting the change, rather than changing it directly
       quxState.getScreen('a').getWidget('textfield').setStyle({'hidden':true}); 
    }
}

quxContext could hold the data and quxState be some kind of "snapshot" of the current screen. One big advantage I see with this approach is that the workers could never directly change the state of the UI or data, but always kind of "request" a change. This would make it easier to trace bugs, seeing which worker is requesting which changes.

I would keep the worker code separated for each worker, that way they can be started and terminated independently. I did some work in that direction in the past with a project for university, it was a python-based online IDE https://github.com/TU-Blueberry/bluestberry and web workers turned out to be the best solution there (but that does of course not mean they are also the best solution here).

KlausSchaefers commented 2 years ago

Hi,

for now we should aim for the simple stuff. Allowing some calculations on data, and setting styles + navigation. I created a new branch 'jssandbox' and a playground file.

Having two objects is also fine for me. In Figma there is a single object, but I guess this is a matter of test. I would rename the context to "quxViewModel".

https://github.com/KlausSchaefers/quant-ux/blob/jssandbox/src/unit/JSSandboxTest.vue

I am not sure about the web workers. I have the feeling iframe are saver, but a web worker would be more convenient to develop. I have to read more into this topic.

[Update] This link looks interesting: http://blog.namangoel.com/replacing-eval-with-a-web-worker

TimHal commented 2 years ago

Looks good! From next week on I will have the time to work on this too, I would just check out the branch then and catch up with you about the next steps to take, if that is okay with you. Another thing that came to my mind: What triggers should be supported to trigger code execution? Probably click events on widgets and maybe something like "onCreate" whenever the component is loaded?

KlausSchaefers commented 2 years ago

Hi,

I go the code isolation running with a web worker, but I needed to update all NPM dependencies. So if you checkout the branch, please delete the node_modules and run npm install.

I added a simple test case how I would imagine the API to work:

    const api = new ScriptAPI(app, viewModel)
    const screenA = api.getScreen('a')
    const widgetB = screenA.getWidget('b')

   const widgetD = api?.getScreen('c')?.getWidget('d')

    // change some style, delta should be stored in API
    screenA.setStyle({'background': 'black'})
    const deltas = api.getAppDeltas()

https://github.com/KlausSchaefers/quant-ux/blob/jssandbox/tests/unit/ScriptAPI.spec.js

TimHal commented 2 years ago

Looking very good. Are the deltas sent back to the main thread and executed there, or directly applied from within the worker?

KlausSchaefers commented 2 years ago

The deltas need to be applied in the main thread. From my understanding, the worker does not have access to the memory of the main thread. Data is passed as value / serialised.

KlausSchaefers commented 2 years ago

https://quant-ux.com/#/help/scripts.html