QoL for routing panel: Add data field in the properties panel(could be an advanced tab)

Show a field with the value of key “data”

{
      "path": "/partner/register",
      "url": "",
      "routeType": "page",
      "layout": "partner/auth",
      "page": "partner/_register",
      "data": {
        "id": "partner_register",
        "i18nfile": "partner_register",
        "js": [
          "dmxAppConnect/dmxValidator/dmxValidator.js"
        ],
        "css": [
          "dmxAppConnect/dmxValidator/dmxValidator.css"
        ]
      }
    },

Is it me the only weirdo who is using the data field in the routes?

As I add more and more info to the route itself I see myself opening routes.json in code view more and more often. Actually, I can’t remember the last time I opened the routes panel.

@JonL I’m very curious to see what use case you have for passing data in the routes?
This might be exactly what I am looking for.

Also where can I find some more documentation? A search in the community gave me another post from you New ejs tag added. Parsing ejs templates with Server Connect that didn’t make me much wiser :sweat_smile:

Ok.

So here are a few examples where I use data in the routes.

"layouts": {
    "admin": {
      "data": {
        "js": [
          "dmxAppConnect/dmxBootstrap4PagingGenerator/dmxBootstrap4PagingGenerator.js",
          "dmxAppConnect/dmxStateManagement/dmxStateManagement.js",
          "js/formatters.js",
          "dmxAppConnect/dmxBootstrap4Tooltips/dmxBootstrap4Tooltips.js"
        ],
        "css": [
          "dmxAppConnect/dmxBootstrap4TableGenerator/dmxBootstrap4TableGenerator.css"
        ]
      }
    },

I like to specify js and css files in them. I find it easier to manage. I have a small script in the header partial that will load all the files for each route.

<!-- Load js defined in routes.json -->
<%
  var routesJS = "";
  if (typeof js !== 'undefined') {
    js.forEach(jsItem => { 
      routesJS += '<script src="./'+jsItem+'"></script>'
    })}
%>

<%- routesJS %>
<!-- Load css defined in routes.json -->
<%
  var routesCSS = "";
  if (typeof css !== 'undefined') {
    css.forEach(cssItem => { 
      routesCSS += '<link rel="stylesheet" type="text/css" href="./'+cssItem+'">'
    })}
%>
<%- routesCSS %>

You can add any 3rd party and some Wappler libraries, but not all. i.e. app connect. The UI will get in your way and keep on adding it to the page.

{
      "path": "/admin/users",
      "page": "/admin/resource",
      "layout": "admin",
      "data": {
        "resource": "user",
        "dt": "user",
        "id": "users",
        "i18nfile": "admin"
      },
      "routeType": "page",
      "name": "Admin Users"
    },

In this route I am specifying the id of the page, some data I need for the page to load the right data from SC and what is the name of the translation file.

resource is used in a SC ajax call.

<dmx-serverconnect id="getResource" dmx-bind:url="'/api/<%=resource%>/admin/getAllPaged'" dmx-param:offset="query1.data.offset" dmx-param:limit="10"></dmx-serverconnect>

dt is used to specify if the route will load a default datatable or a custom one(user datatable in my example).

<%- await include( typeof dt !== 'undefined' ? '/partials/admin/datatables/_dt_'+resource : '/partials/admin/datatables/_dt_default', Object.assign({}, locals)) %>

ì18nfile is used in my i18next integration to specify which translation file to load.

.init({
                    debug: <%= $_ENV['NODE_ENV'] == 'development' %>,
                    whitelist: ['en', 'es'],
                    lng: dmx.parse("i18n.data[0].language") ? dmx.parse("i18n.data[0].language") : dmx.parse('browser.language.substr(0, 2)'),
                    fallbackLng: 'en',
                    ns: ['<%- i18nfile %>', 'common'],
                    defaultNS: '<%- i18nfile %>',
                    backend: { loadPath: '/assets/translations/{{lng}}/{{ns}}.ftl' }
                })
                .then(updateDOM)

id is used in the layout body tag

<body class="application application-offset" is="dmx-app" dmx-show="translationLoaded" id=<%= id %>>

3 Likes

Hey @JonL thanks for this.

I’ve been revisiting this post often.
This example you gave:

The data in there are variables?

Context: I want to get the first parameter of every url and check if it exists in the database. If it does, append the original slug. If it doesn’t then remove the parameter from the url and leave the slug.

Example :
Homepage with param: site.com/:school/home
Lecture watch page with param: site.com/:school/watch/:course_id/:lecture_id

  1. Middleware gets the :school param and checks if it exists in the database
  2. If exists, redirect to site.com/school_A/home or site.com/school_C/39/20

Here’s the code I got so far that doesn’t work (everything is 404’ing now):

exports.handler = function (app) {
    const schools = ['school_A', 'school_B', 'school_C'];

    app.get('/*:school', function (req, res, next) => {
        if(schools.includes(req.params.school)) {
        req.url = req.params.school + req.url;
    }
    next();
});
}

PS If there’s a more wappler native solution for this… I would be very happy!

Nope. The data is supposed to be fixed. Think of it as a constant.

Custom route seems to me the wappler way so I would insist in that piece of code.

Custom route as in custom middleware as in, try get the code to work that I’m writing here?

Exactly. Because you need to rewrite the URL that approach seems ideal.

Thanks Jon, will keep trying :slight_smile:

@JonL I need your genius for a minute please.

I want to execute two server connects on page load (asap as middleware):

  1. Security check (if logged in) On certain pages
  2. Subdomain check (if the subdomain exists in the database, example: nonexistingschool.site.com has subdomain nonexistingschool which redirects the user to site.com On 99% of pages

Is this possible with using data’s or adding something to routes.json?
Pseudocode example of what I want

      "path": "/login",
      "url": "",
      "routeType": "page",
      "page": "login",
      "layout": "loginLayout",
      "exec": "/api/Routing/check_subdomain", "/api/Security/access_check"
    }

Could you not create a server action that checks this stuff and if returns false then redirects? then to trigger this using the onload dynamic event on your page? maybe I misunderstood this

Not that I know. I think the routing middleware doesn’t iterate over a list of SCs(I would need to double check).

Try to include them inside [ ].

As a workaround you could move your two SCs into library and then include them in a single SC which would be called in the exec of the route.

1 Like

Thanks I’m trying the including through the library now. Will also try between square brackets.

And do you recommend to just check the domain name in server connect or create an express extension?
I don’t know the difference, I’m guessing that express is even faster/more optimised?

(The domain check is basically:

  1. Query database for all existing names
  2. See if current subdomain equals one of those values
  3. If false: redirect.
  4. If true: do nothing

Have a wildcard setup in traefik, so any subdomain will be routed to the webserver)

I would do the check in a workflow. The difference would be negligible.

If you will have a high traffic site that needs to perform that check constantly I would optimize by caching. If not, you are fine doing real time checks.

1 Like

Workflow = server connect?

Ah and yes caching is my next question, if all goes to plan we will soon have a lot of traffic. Then I can cache it using redis and server connect I guess? Or is it a mysql View that I need?

Or is this better done in express?

Yup. I try to do my best to keep up and share the new terminology :slight_smile:

You can use Redis for caching indeed. Additionally you could check the database own cache functionality. Each db engine has its own.

1 Like

You’re great JonL, appreciate your input a lot!

1 Like