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

Turn Linz into a React App #220

Open
allanchau opened this issue Oct 9, 2018 · 10 comments
Open

Turn Linz into a React App #220

allanchau opened this issue Oct 9, 2018 · 10 comments
Assignees

Comments

@allanchau
Copy link
Contributor

Just an idea, we should turn Linz into a react app.

Benefits

  • Make iteration + testing much easier.
  • Easier development using ES6 for client side code.
  • Speed improvements!!! 🚀

Notes

  • create-react-app should be used.
  • Routes will need to be updated to return json responses instead of rendering a page.
const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, 'build')));

app.get('/someroute', function(req, res) {
  res.json({ test: 'test' });
});

// Handles any requests that don't match the ones above
app.get('*', (req,res) =>{
    res.sendFile(path.join(__dirname+'/client/build/index.html'));
});

Things to be aware of

  • How to support linz.api.views.render?
@allanchau allanchau self-assigned this Oct 9, 2018
@smebberson
Copy link
Contributor

@allanchau, I think this is a great idea and I've been thinking about it a lot lately. I've come to the conclusion that it would be better to start turning Linz into multiple react apps (i.e one for the model index, one for the record edit, one for the overview page, etc).

This allows us to dip our toes in rather than biting off the whole damn thing allowing us to make some progress and release something better than what we have today, sooner than what we can if we migrate the whole app.

At present, I can't get my head around permissions, record/overview actions and a few other things and how they fit in to a react workflow without MASSIVE breaking changes required.

What are your thoughts on that?

@allanchau
Copy link
Contributor Author

I think permissions can be handled using the example above with middleware. As long as the react route is last, the api should kick in first?

We would just need to standardise the success and error responses coming from the routes.

I'm thinking 1 React App would be better though, it would allow us to take full advantage of code splitting out of the box assuming we go with create-react-app. I think to make these changes incrementally, we just need to update (remove the rendering component) of routes as we go and let the React app handle getting the data? Anything else would just render using Jade as it currently does.

@allanchau
Copy link
Contributor Author

I might fork Linz and eventually create a feature branch here once I get most of the routes working.

@smebberson
Copy link
Contributor

smebberson commented Oct 9, 2018

I don't see how the permissions will work as they currently stand? The react app would just be one HTML request, all subsequent being XMLHTTPRequest/Fetch requests?

Could you explain a little more about how we could do it as one app but incrementally roll it out?

A more complete list of the things I'm unsure of are:

  • Authentication
  • Permissions
  • Wrap in Linz view functionality
  • Defining custom widgets (they'd need to be react and hydrated server-side?)
  • Defining custom overview cells (again, react and hydrated server-side?)
  • Flash functionality

A couple of workflows that I can see as being tricky to do in React would be:

  • A record action that displays some HTML in modal.
  • A record action that:
    • Presents a form (HTML) in a modal
    • Updates the database when the form is POSTed
    • Refreshes the page (because of the post) and the data is updated

Could you detail how would they work a little more?

@allanchau
Copy link
Contributor Author

So using the example

const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, 'build')));

// All existing routes go here
// Updated routes will need to have the render method and all middleware replaced with a res.json

// Handles any requests that don't match the ones above
app.get('*', (req,res) =>{
    res.sendFile(path.join(__dirname+'/client/build/index.html'));
});

The fetch requests from the react app will now receive a structured response from the routes that it can use to display information to the user.

{
    "data": {},
}

{
    "error": {}
}

If there is a permission issue, the app will receive an error and display that to the user.

I'm not really sure how we can get around these either:

  • Defining custom widgets (they'd need to be react and hydrated server-side?)
  • Defining custom overview cells (again, react and hydrated server-side?)

Flash functionality will probably be removed as it is now and replaced with a specific property in the son response, maybe

{
    "data": {},
    "flash": {
        "message": "",
        "options": { noty options },
    }
}

{
    "error": {},
    "flash": {
        "message": "",
        "options": { noty options },
    }
}

The modal record actions would work the same as the currently do (although I wouldn't mind getting rid of the query bind data plugin), the react app would still have access to query etc so click -> react app fetches HTML -> react app puts it in a modal (new component) -> trigger the modal.

In terms of the page refreshing with new data, that can be handled by React animations, I haven't used it yet, but I assume it can be made to fade in and out like when an iOS Table View is updated.

@smebberson
Copy link
Contributor

Yeah, I thought more about it last night and I can see how the permissions will work, and how we can do it progressively too.

We'll have to do a little more homework on the widgets side of things. Some sort of means to package them up via the Express app (where all of the DSL is defined) and deliver to the client.

@smebberson
Copy link
Contributor

The page refreshing the data can't be handled by React animations alone? How would it would know when a particular modal needs data to be refreshed and another doesn't? I have seen some solutions in which a websocket connection receives data table updates from the server, but it seems quite complex when you think about filtering and paging too.

In terms of refreshing the data, I think we'll need to expose some sort of client-side Linz API so that we can offer modals and widgets a means to refresh the view when needed...

@allanchau
Copy link
Contributor Author

Wouldn't the child component (filter etc) just update the state on the parent? Once the state has changed, that would automatically cause a refresh.

In terms of when the data is updated directly and not through the UI it would be up to the user to refresh the page just like it is now.

I'd imagine the parent component would need to have a state with properties that match what we need to make the mongoose query or even store the query itself.

@smebberson
Copy link
Contributor

Yeah, the child component would update the state on the parent, and cause a refresh. The client-size Linz API was to solve the problem of a record action showing in a modal with the workflow:

  • Presents a form (HTML) in a modal
  • Updates the database when the form is POSTed
  • Refreshes the page (because of the post) and the data is updated

Because it's POSTed, the data is automatically redrawn as it is today. So we'll need something to say, Okay Linz, I've done some stuff that altered the state, please reload from the server... type of thing.

@smebberson
Copy link
Contributor

I think anything we do should also involve GraphQL. I've been using it lately and it would be really useful for this project. Also, I think we should take a look at https://nextjs.org/ and see if it would be useful? I can see how using something like https://github.com/zeit/next.js/tree/master/examples/custom-server-express would make it much easier for us to wrap it custom cell renders, widgets, etc...

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

No branches or pull requests

2 participants