github.com/simpleiot/simpleiot@v0.18.3/docs/ref/frontend.md (about) 1 # Frontend 2 3 ## Elm Reference Implementation 4 5 The reference Simple IoT frontend is implemented in Elm as a Single Page 6 Application (SPA) and is located in the 7 [`frontend/`](https://github.com/simpleiot/simpleiot/tree/master/frontend) 8 directory. 9 10 ### Code Structure 11 12 The frontend is based on [elm-spa](https://www.elm-spa.dev/), and is split into 13 the following directories: 14 15 - **Api**: contains core data structures and API code to communicate with 16 backend (currently REST). 17 - **Pages**: the various pages of the application 18 - **Components**: each node type has a separate module that is used to render 19 it. `NodeOptions.elm` contains a struct that is used to pass options into the 20 component views. 21 - **UI**: Various UI pieces we used 22 - **Utils**: Code that does not fit anywhere else (time, etc) 23 24 We'd like to keep the UI 25 [optimistic](https://blog.meteor.com/optimistic-ui-with-meteor-67b5a78c3fcf) if 26 possible. 27 28 ### Creating Custom Icons 29 30 SIOT icons are 24x24px pixels (based on feather icon format). One way to create 31 them is to: 32 33 - create a 24x24px drawing in InkScape, scale=1.0 34 - draw your icon 35 - if you use text 36 - convert text to path: select text, and then menu Path -> Object to Path 37 - make sure fill is set for path 38 - save as plain SVG 39 - set up a new Icon in `frontend/src/UI/Icon.elm` and use an existing custom 40 icon like `variable` as a template. 41 - copy the SVG path strings from the SVG file into the new Icon 42 - you'll likely need to adjust the scaling transform numbers to get the icon to 43 the right size 44 45 (I've tried using: https://levelteams.com/svg-to-elm, but this has not been real 46 useful, so I usually end up just copying the path strings into an elm template 47 and hand edit the rest) 48 49 ### File upload 50 51 The [File node UI](../user/file.md) has the capability to upload files in the 52 browser and then store them in a node point. The default max payload of NATS is 53 1MB, so that is currently the file size limit, but NATS 54 [can be configured](https://docs.nats.io/reference/faq#is-there-a-message-size-limitation-in-nats) 55 for a payload size up to 64MB. 8MB is recommended. 56 57 Currently the payload is stored in the Point `String` field for simplicity. If 58 the binary option is selected, the data is base64 encoded. Long term it may make 59 sense to support Jetstream Object store, local file store, etc. 60 61 The [elm/file](https://package.elm-lang.org/packages/elm/file/latest/) package 62 is used upload a file into the browser. Once the data is in the browser, it is 63 sent to the backup as a standard point payload. Because we are currently using a 64 JSON api, binary data is base64 encoded. 65 66 The process by which a file is uploaded is: 67 68 - The NodeOptions struct, which is passed to all nodes has a onUploadFile field, 69 which is used to triggers the `UploadFile` message which runs a browser file 70 select. The result of this select is a `UploadSelected` message. 71 - This message calls `UploadFile node.node.id` in `Home_.elm`. 72 - `File.Select.file` is called to select the file, which triggers the 73 `UploadContents` message. 74 - `UploadContents` is called with the node id, file name, and file contents, 75 which then sends the data via points to the backend. 76 77 ## SIOT JavaScript library using NATS over WebSockets 78 79 This is a JavaScript library avaiable in the 80 [`frontend/lib`](https://github.com/simpleiot/simpleiot/tree/master/frontend/lib) 81 directory that can be used to interface a frontend with the SIOT backend. 82 83 Usage: 84 85 ```js 86 import { connect } from "./lib/nats" 87 88 async function connectAndGetNodes() { 89 const conn = await connect() 90 const [root] = await conn.getNode("root") 91 const children = await conn.getNodeChildren(root.id, { recursive: "flat" }) 92 return [root].concat(children) 93 } 94 ``` 95 96 This library is also published on NPM (in the near future). 97 98 (see [#357](https://github.com/simpleiot/simpleiot/pull/357)) 99 100 (Note, we are not currently using this yet in the SIOT frontend -- we still poll 101 the backend over REST and fetch the entire node tree, but we are building out 102 infrastructure so we don't have to do this.) 103 104 ## Custom UIs 105 106 The current SIOT UI is more an engineering type view than something that might 107 be used by end users. For a custom/company product IoT portal where you want a 108 custom web UI optimized for your products, there are several options: 109 110 1. modify the existing SIOT frontend. 111 1. write a new frontend, mobile app, desktop app, etc. The SIOT backend and 112 frontend are decoupled so that this is possible. 113 114 ### Passing a custom UI to SIOT 115 116 There are ways to use a custom UI with SIOT at the app and package level: 117 118 1. **Application:** pass a directory containing your public web assets to the 119 app using: `siot serve -customUIDir <your web assets>` 120 1. **Package:** populate CustomUIFS with a [fs.FS](https://pkg.go.dev/io/fs#FS) 121 in the SIOT 122 [Server options](https://pkg.go.dev/github.com/simpleiot/simpleiot/server#Options). 123 124 In both cases, the filesystem should contain a `index.html` in the root 125 directory. If it does not, you can use the 126 [fs.Sub](https://pkg.go.dev/io/fs#Sub) function to return a subtree of a fs.FS.