markqvist / NomadNet

Communicate Freely
GNU General Public License v3.0
1.23k stars 47 forks source link

Feature Request: CGI-style interface for script pages #19

Closed acehoss closed 1 year ago

acehoss commented 1 year ago

I've been having a blast scripting pages for nomadnet. I'd love to see a few CGI-like features for scripts:

These things, especially query string, would allow for more interactive content.

markqvist commented 1 year ago

Hi @acehoss! That's awesome to hear :) I've been checking out your node, and must say it's really cool.

The plan is definitely to add ability to pass more advanced data back and forth, but I haven't yet gotten down to exactly what the best way to do this is.

A few notes:

I'd love to hear your thoughts, ideas and anything else on the above and anything else related. Would also love to hear how you'd ideally like it implemented. I think something like passing this data as environment variables would probably be the most universal way of doing it, since all scripting languages and even ELF executables have access to those.

acehoss commented 1 year ago

The issue of form elements definitely came to mind, and there is plenty to think through with that. But I was thinking query strings could be added before form elements or even if form elements never happen. Query strings would enable pages to create dynamic links, for example a message board linking to a message.

A first pass idea is to do the same thing as CGI--any characters after a ? in the URL are set into the QUERY_STRING environment variable for the subprocess. Any of the other available data could be set into environment variables as well.

markqvist commented 1 year ago

I'm working on your input fields btw ;) I'll answer the other stuff later (regarding query strings), just wanted to let you know. There might be something really basic in the next release, but don't get too hyped, it'll be pretty simple ;)

acehoss commented 1 year ago

Wow, working on the hard part first! 😂

markqvist commented 1 year ago

Ok, this is getting somewhere at least :)

micron_fields

Even the most minimal thinkable implementation seems to balloon almost uncontrollably though ;) Here's what I am thinking to implement for now:

I'm interested to hear if you have any thoughts or comments on this approach.

acehoss commented 1 year ago

I totally agree on the ballooning. If I let my brain go on it for a while, I always end up with "HTML, but with ticks instead of angle brackets."

That feature list seems plenty usable. Down the road it might be nice to have a single line/multiline switch. Multiline fields maybe pop open a text input dialog. Single line inputs edit in place.

markqvist commented 1 year ago

I just pushed the latest on this to the repo in c134ee180a1e7c9056fc5fb809f0fa722b1ecdd3.

There's still some issues with keyboard navigation (you'll have to use the mouse to focus the fields), and probably a few other things as well, but the basics are working now:

fields_2

There's nothing about it in the internal guide/documentation yet, but at least there's now a small example included in the examples folder:

#!/usr/bin/env python3
import os
env_string = ""
for e in os.environ:
  env_string += "{}={}\n".format(e, os.environ[e])

template = """>Fields and Submitting Data

Nomad Network let's you use simple input fields for submitting data to node-side applications. Submitted data, along with other session variables will be available to the node-side script / program as environment variables. This page contains a few examples.

>>Read Environment Variables

{@ENV}
>>Examples of Fields and Submissions

The following section contains a simple set of fields, and a few different links that submit the field data in different ways.

-=

An input field    : `B444`<username`Entered data>`b

An masked field   : `B444`<!|password`Value of Field>`b

An small field    : `B444`<8|small`test>`b, and some more text.

Two fields        : `B444`<8|one`One>`b `B444`<8|two`Two>`b

The data can be `!`[submitted`:/page/input_fields.mu`username|two]`!.

You can `!`[submit`:/page/input_fields.mu`one|password|small]`! other fields, or just `!`[a single one`:/page/input_fields.mu`username]`!

Or simply `!`[submit them all`:/page/input_fields.mu`*]`!.

-=
"""
print(template.replace("{@ENV}", env_string))

If you give it a try, let me know if you bump into any issues!

acehoss commented 1 year ago

That looks very cool. The thing I keep thinking about with this is the public message board, and I think one feature that is needed yet to make it complete is the ability to send hidden text. Then it would be possible to make links that would open up messages, or a delete link for a message.

Maybe add an = to the field name in the submit link?

`[submit`:/page/delete_post.mu`post_id=1234]`
markqvist commented 1 year ago

Ah, of course, I honestly must've had a bit of tunnel vision here. That's really necessary. As you probably know, the paths themselves cannot contain extra "query string" paramaters, since they are registered and hashed preliminarily on the listener side. But there's no problem in adding them in some kind of syntactical way to the links, and then just including them with the request data in the same way as with the fields. So doing it like that would probably be the most sensible way. Should be pretty easy to implement as well.

markqvist commented 1 year ago

In 1a84e0c019efda22c4da4cfeaf895e51192da451 you can now create variables in links like so:

`[fields and variables variables`:/page/fields.mu`username|two|entitiy_id=4611|action=view]

`[all fields and variables`:/page/fields.mu`*|entitiy_id=4611|action=view]

`[only variables`:/page/fields.mu`entitiy_id=4688|task=something]

I think this should be flexible enough to cover most use-cases, while still being relatively simple to deal with :)

acehoss commented 1 year ago

Awesome! Now I can build a destination detail page for my nomadnet stats generator 😁

markqvist commented 1 year ago

Very nice! I just pushed a few commits that fixes the keyboard navigation for pages with fields as well. It's still a little shoddy, but it works :)

acehoss commented 1 year ago

Something tangential that keeps coming to mind is being able to get the viewport dimensions. You'd have to have some mechanism to send that over from the client, and maybe there's a privacy concern there too. But for laying out tabular data, it would be nice to be able to fit it to the screen.

markqvist commented 1 year ago

Yes, I've been thinking about this myself a bit, but haven't found any good solutions yet. One alternative I thought of was to let the node send a "min-width" header, that tells the client the minimum expected width of the viewport. That way, the client can at least display a message to the user if the viewport is too small, and prompt the user to go into fullscreen mode with Ctrl-G.

acehoss commented 1 year ago

With the link id (and identity if identified), it would be possible to make a width picker page that caches that information for subsequent pages generated in the same session (or later sessions with the same remote identity). Solution-wise it's not as glove-fit as sending the viewport size, but there are no privacy concerns and you don't have to build anything else to make it happen.

markqvist commented 1 year ago

I like all aspects of this solution :)

markqvist commented 1 year ago

Closing issue now since this is already released :)