CreeperPanel in Elm: Researching Ports
I don't even know where to start on the connection of actions or whatever to ports, so I'm going to start with just those facts I do know:
The output port must be a signal of some kind. Probably API Requests or whatever I define it as. It doesn't matter what it is, just that it's a signal of it. The type can be defined elsewhere.
Signals can't be created from nothing, and must always have a source, whether it's user input, a ticker, or whatever. Something environmental can be made into a signal, but it has to be something and not nothing.
Signals can be manipulated with various functions such as merge to combine multiple signals into one which has all their events, map to transform values from one signal into values in a new signal, filter to selectively accept or reject certain values from a signal for inclusion in a new signal, and so on.
I need to trigger API requests in reaction to various things:
The Console Log needs to refresh periodically, but not too often. The point being it needs to do this without user interaction. (The exact timing may be set up in JS at first until I have a better grasp of signal manipulation.)
Later on, Console commands need to be sent when the user hits enter on the command line, triggers a macro, or some other thing which trigger console commands.
It sounds like ultimately, my signal source is going to be a signal merged from a couple places:
Certain user actions (Console commands, server restart, etc.)
A Timer for various automatic periodic things. (Console log, server stats...)
As far as how to event start researching this, User Actions seems to be a pretty good place. I use StartApp because it simplifies starting the app, but I currently have no idea what goes on under the hood. I know that user actions are sent to addresses, but I'm not sure how that becomes a signal of actions.
Addresses, it turns out, are usually part of another structure called a Mailbox, which as it happens is a record with two parts: An address and a signal. Ah ha.
Another thing that helped was peering through the code of Evan's Elm implementation of TodoMVC, as he did not use StartApp here. Down at the bottom of Todo.elm, we see this: actions : Signal.Mailbox Action followed by a definition actions = Signal.mailbox NoOp and lo, a Mailbox is created. (As mentioned in the Docs, this also creates a Signal, which is itself impure, thus bolstering my statement of "pure, mostly". This also shows one of my 'facts' was incorrect, and that signals can be created willy nilly.) We also see the definition of main with type Signal Html, and model with type Signal Model. What's in these?
With main, we have main = Signal.map (view actions.address) model. Signal.map has the type Signal.map : (a -> result) -> Signal a -> Signal result, so we know that (view actions.address) is a function that takes a single Model value and returns a single Html value. view is of course Address Action -> Model -> Html but Address Action is already supplied with actions.address, so we're left with just Model -> Html, which looks correct. That leaves model on the end, there, which has the type Signal Model.
I see here that model has the definition model = Signal.foldp update initialModel actions.signal, and finally I see how actions ultimately result in new models. New messages are sent to actions.address, which thus result in those new actions appearing in actions.signal, which itself can be manipulated with the various Signal functions of map, foldp, filter, or whatever.
But wait, how do I use this knowledge with StartApp? StartApp doesn't appear to expose anything to do with a signal of actions. Indeed, it doesn't, as checking StartApp's source code it's plainly seen that actions : Signal.Mailbox Action only shows up in the let part of a let in block. That's no good. So there must be another way to do this without interacting with the Mailbox Action thing. I'll need to look around for an app that does pull information from a server on some user action and see what they do, presuming of course they're doing it correctly, whatever correctly is.
Just as an aside, while I don't know if it will actually make a difference here, Server APIs such as CreeperHost's are usually exposed as Services in JS frameworks, which live outside of the MVC portion.
At any rate, we'll see what further research yields.