mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-29 13:49:28 +08:00
MF-571 - Add Env.elm to set custom base URL (#654)
* Add Env module Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Modify README.md Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Remove literal vals from Env.elm Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Replace protocol, host and port env setting by url Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Remove default env.url value and update README.md Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add http://localhost:80/ as a default baseURL val Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Replace Gateflux by Mainflux Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com>
This commit is contained in:
parent
e95e010a3a
commit
d504c4f67d
76
ui/README.md
76
ui/README.md
@ -3,42 +3,7 @@ Dashboard made with [elm-bootstrap](http://elm-bootstrap.info/).
|
||||
|
||||
## Install
|
||||
|
||||
### Install GUI as a part of Mainflux build
|
||||
|
||||
Install Elm (https://guide.elm-lang.org/install.html) and then
|
||||
|
||||
```
|
||||
git clone https://github.com/mainflux/mainflux
|
||||
cd mainflux/ui
|
||||
make
|
||||
```
|
||||
|
||||
This will produce `index.html` in the _ui_ directory. In order to use it, `cd`
|
||||
to _ui_ and do
|
||||
|
||||
`make run`
|
||||
|
||||
### Build a standalone native GUI
|
||||
|
||||
Install Elm (https://guide.elm-lang.org/install.html), `cd` to _ui_ and then
|
||||
|
||||
`elm make --optimize src/Main.elm`
|
||||
|
||||
This will produce `index.html` in the _ui_ directory. In order to use it do
|
||||
|
||||
`make run`
|
||||
|
||||
### About Elm `make`
|
||||
|
||||
`make` does `elm make src/Main.elm`.
|
||||
|
||||
`make run` just executes `elm reactor`. You can execute `elm reactor` in other
|
||||
terminal window and keep it running, and then see changes as you change-compile
|
||||
in the first window. You can even use something as
|
||||
[entr](http://eradman.com/entrproject/) to have your source compiled
|
||||
automatically when you change and save some files.
|
||||
|
||||
### Build as a part of Docker composition
|
||||
### Docker container GUI build
|
||||
|
||||
Install Docker (https://docs.docker.com/install/) and Docker compose
|
||||
(https://docs.docker.com/compose/install/), `cd` to Mainflux root directory and
|
||||
@ -46,15 +11,44 @@ then
|
||||
|
||||
`docker-compose -f docker/docker-compose.yml up`
|
||||
|
||||
if you want to launch a whole Mainflux docker composition or just
|
||||
if you want to launch a whole Mainflux docker composition, or just
|
||||
|
||||
`docker-compose -f docker/docker-compose.yml up ui`
|
||||
|
||||
if you want to launch just GUI.
|
||||
|
||||
### Contribute to the GUI development
|
||||
### Native GUI build
|
||||
|
||||
Install GUI as a part of Mainflux build or as a standalone native GUI and run
|
||||
it. Launch Mainflux without ui service, either natively or as a Docker
|
||||
composition. Follow the guidelines for Mainflux contributors found here
|
||||
Install Elm (https://guide.elm-lang.org/install.html) and then run the following
|
||||
commands:
|
||||
|
||||
```
|
||||
git clone https://github.com/mainflux/mainflux
|
||||
cd mainflux/ui
|
||||
make
|
||||
```
|
||||
|
||||
This will produce `index.html` in the _ui_ directory. Still in the _mainflux/ui_
|
||||
folder, enter
|
||||
|
||||
`make run`
|
||||
|
||||
and follow the instructions on screen.
|
||||
|
||||
**NB:** `make` does `elm make src/Main.elm` and `make run` executes `elm
|
||||
reactor`. Cf. _Makefile_ for more options.
|
||||
|
||||
## Configuration
|
||||
|
||||
Open the _src/Env.elm_ file and edit the values of the `env` record.
|
||||
|
||||
## Contribute to the GUI development
|
||||
|
||||
Follow the instructions above to install and run GUI as a native build. Instead
|
||||
of `make run` you can install `elm-live` (https://github.com/wking-io/elm-live)
|
||||
and execute `elm-live src/Main.elm` to get a live reload when your `.Elm` pages
|
||||
change.
|
||||
|
||||
Launch Mainflux without ui service, either natively or as a Docker composition.
|
||||
Please follow the guidelines for Mainflux contributors found here
|
||||
https://mainflux.readthedocs.io/en/latest/CONTRIBUTING/.
|
||||
|
@ -24,7 +24,7 @@ import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import HttpMF exposing (path)
|
||||
import HttpMF exposing (paths)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
import ModalMF
|
||||
@ -123,7 +123,7 @@ update msg model token =
|
||||
ProvisionChannel ->
|
||||
( resetEdit model
|
||||
, HttpMF.provision
|
||||
(B.relative [ path.channels ] [])
|
||||
(B.relative [ paths.channels ] [])
|
||||
token
|
||||
{ emptyChannel
|
||||
| name = Just model.name
|
||||
@ -160,7 +160,7 @@ update msg model token =
|
||||
UpdateChannel ->
|
||||
( resetEdit { model | editMode = False }
|
||||
, HttpMF.update
|
||||
(B.relative [ path.channels, model.channel.id ] [])
|
||||
(B.relative [ paths.channels, model.channel.id ] [])
|
||||
token
|
||||
{ emptyChannel
|
||||
| name = Just model.name
|
||||
@ -181,7 +181,7 @@ update msg model token =
|
||||
RetrieveChannel channelid ->
|
||||
( model
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.channels, channelid ] [])
|
||||
(B.relative [ paths.channels, channelid ] [])
|
||||
token
|
||||
RetrievedChannel
|
||||
channelDecoder
|
||||
@ -198,7 +198,7 @@ update msg model token =
|
||||
RetrieveChannels ->
|
||||
( model
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
(B.relative [ paths.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
token
|
||||
RetrievedChannels
|
||||
channelsDecoder
|
||||
@ -207,7 +207,7 @@ update msg model token =
|
||||
RetrieveChannelsForThing thingid ->
|
||||
( model
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.things, thingid, path.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
(B.relative [ paths.things, thingid, paths.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
token
|
||||
RetrievedChannels
|
||||
channelsDecoder
|
||||
@ -224,7 +224,7 @@ update msg model token =
|
||||
RemoveChannel id ->
|
||||
( resetEdit model
|
||||
, HttpMF.remove
|
||||
(B.relative [ path.channels, id ] [])
|
||||
(B.relative [ paths.channels, id ] [])
|
||||
token
|
||||
RemovedChannel
|
||||
)
|
||||
@ -433,12 +433,12 @@ updateChannelList model token =
|
||||
( model
|
||||
, Cmd.batch
|
||||
[ HttpMF.retrieve
|
||||
(B.relative [ path.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
(B.relative [ paths.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
token
|
||||
RetrievedChannels
|
||||
channelsDecoder
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.channels, model.channel.id ] [])
|
||||
(B.relative [ paths.channels, model.channel.id ] [])
|
||||
token
|
||||
RetrievedChannel
|
||||
channelDecoder
|
||||
@ -450,7 +450,7 @@ updateChannelListForThing : Model -> String -> String -> ( Model, Cmd Msg )
|
||||
updateChannelListForThing model token thingid =
|
||||
( model
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.things, thingid, path.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
(B.relative [ paths.things, thingid, paths.channels ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
token
|
||||
RetrievedChannels
|
||||
channelsDecoder
|
||||
|
@ -24,7 +24,7 @@ import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import HttpMF exposing (path)
|
||||
import HttpMF exposing (paths)
|
||||
import List.Extra
|
||||
import Thing
|
||||
import Url.Builder as B
|
||||
@ -207,7 +207,7 @@ connect checkedThingsIds checkedChannelsIds method token =
|
||||
List.map
|
||||
(\channelid ->
|
||||
HttpMF.request
|
||||
(B.relative [ path.channels, channelid, path.things, thingid ] [])
|
||||
(B.relative [ paths.channels, channelid, paths.things, thingid ] [])
|
||||
method
|
||||
token
|
||||
Http.emptyBody
|
||||
|
12
ui/src/Env.elm
Normal file
12
ui/src/Env.elm
Normal file
@ -0,0 +1,12 @@
|
||||
-- Copyright (c) 2019
|
||||
-- Mainflux
|
||||
--
|
||||
-- SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
||||
module Env exposing (env)
|
||||
|
||||
|
||||
env =
|
||||
{ url = "http://localhost:80/"
|
||||
}
|
@ -4,9 +4,10 @@
|
||||
-- SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
||||
module HttpMF exposing (expectID, expectRetrieve, expectStatus, path, provision, remove, request, retrieve, update, url)
|
||||
module HttpMF exposing (baseURL, expectID, expectRetrieve, expectStatus, paths, provision, remove, request, retrieve, update, user, version)
|
||||
|
||||
import Dict
|
||||
import Env exposing (env)
|
||||
import Helpers
|
||||
import Http
|
||||
import Json.Decode as D
|
||||
@ -14,12 +15,11 @@ import Json.Encode as E
|
||||
import Url.Builder as B
|
||||
|
||||
|
||||
url =
|
||||
{ base = "http://localhost"
|
||||
}
|
||||
baseURL =
|
||||
env.url
|
||||
|
||||
|
||||
path =
|
||||
paths =
|
||||
{ users = "users"
|
||||
, tokens = "tokens"
|
||||
, things = "things"
|
||||
@ -107,12 +107,30 @@ expectRetrieve toMsg decoder =
|
||||
-- REQUEST
|
||||
|
||||
|
||||
version : String -> (Result Http.Error String -> msg) -> D.Decoder String -> Cmd msg
|
||||
version path msg decoder =
|
||||
Http.get
|
||||
{ url = baseURL ++ path
|
||||
, expect = Http.expectJson msg decoder
|
||||
}
|
||||
|
||||
|
||||
user : String -> String -> String -> E.Value -> Http.Expect msg -> Cmd msg
|
||||
user email password u value expect =
|
||||
Http.post
|
||||
{ url = baseURL ++ u
|
||||
, body =
|
||||
value |> Http.jsonBody
|
||||
, expect = expect
|
||||
}
|
||||
|
||||
|
||||
request : String -> String -> String -> Http.Body -> (Result Http.Error String -> msg) -> Cmd msg
|
||||
request u method token b msg =
|
||||
request path method token b msg =
|
||||
Http.request
|
||||
{ method = method
|
||||
, headers = [ Http.header "Authorization" token ]
|
||||
, url = u
|
||||
, url = baseURL ++ path
|
||||
, body = b
|
||||
, expect = expectStatus msg
|
||||
, timeout = Nothing
|
||||
@ -121,11 +139,11 @@ request u method token b msg =
|
||||
|
||||
|
||||
retrieve : String -> String -> (Result Http.Error a -> msg) -> D.Decoder a -> Cmd msg
|
||||
retrieve u token msg decoder =
|
||||
retrieve path token msg decoder =
|
||||
Http.request
|
||||
{ method = "GET"
|
||||
, headers = [ Http.header "Authorization" token ]
|
||||
, url = u
|
||||
, url = baseURL ++ path
|
||||
, body = Http.emptyBody
|
||||
, expect = expectRetrieve msg decoder
|
||||
, timeout = Nothing
|
||||
@ -134,11 +152,11 @@ retrieve u token msg decoder =
|
||||
|
||||
|
||||
provision : String -> String -> entity -> (entity -> E.Value) -> (Result Http.Error String -> msg) -> String -> Cmd msg
|
||||
provision u token e encoder msg prefix =
|
||||
provision path token e encoder msg prefix =
|
||||
Http.request
|
||||
{ method = "POST"
|
||||
, headers = [ Http.header "Authorization" token ]
|
||||
, url = u
|
||||
, url = baseURL ++ path
|
||||
, body =
|
||||
encoder e
|
||||
|> Http.jsonBody
|
||||
@ -149,11 +167,11 @@ provision u token e encoder msg prefix =
|
||||
|
||||
|
||||
update : String -> String -> entity -> (entity -> E.Value) -> (Result Http.Error String -> msg) -> Cmd msg
|
||||
update u token e encoder msg =
|
||||
update path token e encoder msg =
|
||||
Http.request
|
||||
{ method = "PUT"
|
||||
, headers = [ Http.header "Authorization" token ]
|
||||
, url = u
|
||||
, url = baseURL ++ path
|
||||
, body =
|
||||
encoder e
|
||||
|> Http.jsonBody
|
||||
@ -164,11 +182,11 @@ update u token e encoder msg =
|
||||
|
||||
|
||||
remove : String -> String -> (Result Http.Error String -> msg) -> Cmd msg
|
||||
remove u token msg =
|
||||
remove path token msg =
|
||||
Http.request
|
||||
{ method = "DELETE"
|
||||
, headers = [ Http.header "Authorization" token ]
|
||||
, url = u
|
||||
, url = baseURL ++ path
|
||||
, body = Http.emptyBody
|
||||
, expect = expectStatus msg
|
||||
, timeout = Nothing
|
||||
|
@ -299,7 +299,7 @@ mfStylesheet =
|
||||
|
||||
view : Model -> Browser.Document Msg
|
||||
view model =
|
||||
{ title = "Gateflux"
|
||||
{ title = "Mainflux"
|
||||
, body =
|
||||
let
|
||||
buttonAttrs =
|
||||
|
@ -23,7 +23,7 @@ import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import HttpMF exposing (path)
|
||||
import HttpMF exposing (paths)
|
||||
import List.Extra
|
||||
import Thing
|
||||
import Url.Builder as B
|
||||
@ -217,7 +217,7 @@ genChannelRows checkedChannelsIds channels =
|
||||
send : String -> String -> String -> Cmd Msg
|
||||
send channelid thingkey message =
|
||||
HttpMF.request
|
||||
(B.relative [ "http", path.channels, channelid, path.messages ] [])
|
||||
(B.relative [ "http", paths.channels, channelid, paths.messages ] [])
|
||||
"POST"
|
||||
thingkey
|
||||
(Http.stringBody "application/json" message)
|
||||
|
@ -27,7 +27,7 @@ import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import HttpMF exposing (path)
|
||||
import HttpMF exposing (paths)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
import ModalMF
|
||||
@ -143,7 +143,7 @@ update msg model token =
|
||||
ProvisionThing ->
|
||||
( resetEdit model
|
||||
, HttpMF.provision
|
||||
(B.relative [ path.things ] [])
|
||||
(B.relative [ paths.things ] [])
|
||||
token
|
||||
{ emptyThing
|
||||
| name = Just model.name
|
||||
@ -181,7 +181,7 @@ update msg model token =
|
||||
UpdateThing ->
|
||||
( resetEdit { model | editMode = False }
|
||||
, HttpMF.update
|
||||
(B.relative [ path.things, model.thing.id ] [])
|
||||
(B.relative [ paths.things, model.thing.id ] [])
|
||||
token
|
||||
{ emptyThing
|
||||
| name = Just model.name
|
||||
@ -203,7 +203,7 @@ update msg model token =
|
||||
RetrieveThing thingid ->
|
||||
( model
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.things, thingid ] [])
|
||||
(B.relative [ paths.things, thingid ] [])
|
||||
token
|
||||
RetrievedThing
|
||||
thingDecoder
|
||||
@ -220,7 +220,7 @@ update msg model token =
|
||||
RetrieveThings ->
|
||||
( model
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.things ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
(B.relative [ paths.things ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
token
|
||||
RetrievedThings
|
||||
thingsDecoder
|
||||
@ -237,7 +237,7 @@ update msg model token =
|
||||
RemoveThing id ->
|
||||
( model
|
||||
, HttpMF.remove
|
||||
(B.relative [ path.things, id ] [])
|
||||
(B.relative [ paths.things, id ] [])
|
||||
token
|
||||
RemovedThing
|
||||
)
|
||||
@ -491,12 +491,12 @@ updateThingList model token =
|
||||
( model
|
||||
, Cmd.batch
|
||||
[ HttpMF.retrieve
|
||||
(B.relative [ path.things ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
(B.relative [ paths.things ] (Helpers.buildQueryParamList model.offset model.limit))
|
||||
token
|
||||
RetrievedThings
|
||||
thingsDecoder
|
||||
, HttpMF.retrieve
|
||||
(B.relative [ path.things, model.thing.id ] [])
|
||||
(B.relative [ paths.things, model.thing.id ] [])
|
||||
token
|
||||
RetrievedThing
|
||||
thingDecoder
|
||||
|
@ -19,7 +19,7 @@ import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import HttpMF exposing (path)
|
||||
import HttpMF exposing (baseURL, paths)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
import Url.Builder as B
|
||||
@ -66,10 +66,12 @@ update msg model =
|
||||
|
||||
Create ->
|
||||
( model
|
||||
, create
|
||||
, HttpMF.user
|
||||
model.email
|
||||
model.password
|
||||
(B.relative [ path.users ] [])
|
||||
(B.relative [ paths.users ] [])
|
||||
(encode (User model.email model.password))
|
||||
(HttpMF.expectStatus Created)
|
||||
)
|
||||
|
||||
Created result ->
|
||||
@ -82,10 +84,15 @@ update msg model =
|
||||
|
||||
GetToken ->
|
||||
( model
|
||||
, getToken
|
||||
, HttpMF.user
|
||||
model.email
|
||||
model.password
|
||||
(B.relative [ path.tokens ] [])
|
||||
(B.relative [ paths.tokens ] [])
|
||||
(encode (User model.email model.password))
|
||||
(HttpMF.expectRetrieve
|
||||
GotToken
|
||||
(D.field "token" D.string)
|
||||
)
|
||||
)
|
||||
|
||||
GotToken result ->
|
||||
@ -182,43 +189,6 @@ decoder =
|
||||
-- HTTP
|
||||
|
||||
|
||||
create : String -> String -> String -> Cmd Msg
|
||||
create email password u =
|
||||
Http.request
|
||||
{ method = "POST"
|
||||
, headers = []
|
||||
, url = u
|
||||
, body =
|
||||
encode (User email password)
|
||||
|> Http.jsonBody
|
||||
, expect = HttpMF.expectStatus Created
|
||||
, timeout = Nothing
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
|
||||
getToken : String -> String -> String -> Cmd Msg
|
||||
getToken email password u =
|
||||
Http.request
|
||||
{ method = "POST"
|
||||
, headers = []
|
||||
, url = u
|
||||
, body =
|
||||
encode (User email password)
|
||||
|> Http.jsonBody
|
||||
, expect =
|
||||
HttpMF.expectRetrieve
|
||||
GotToken
|
||||
(D.field "token" D.string)
|
||||
, timeout = Nothing
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Helpers
|
||||
|
||||
|
||||
loggedIn : Model -> Bool
|
||||
loggedIn model =
|
||||
if String.length model.token > 0 then
|
||||
|
@ -10,7 +10,7 @@ import Error
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Http
|
||||
import HttpMF exposing (path)
|
||||
import HttpMF exposing (paths)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
import Url.Builder as B
|
||||
@ -35,10 +35,10 @@ update msg model =
|
||||
case msg of
|
||||
GetVersion ->
|
||||
( model
|
||||
, Http.get
|
||||
{ url = B.relative [ path.version ] []
|
||||
, expect = Http.expectJson GotVersion (D.field "version" D.string)
|
||||
}
|
||||
, HttpMF.version
|
||||
(B.relative [ paths.version ] [])
|
||||
GotVersion
|
||||
(D.field "version" D.string)
|
||||
)
|
||||
|
||||
GotVersion result ->
|
||||
|
Loading…
x
Reference in New Issue
Block a user