1
0
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:
Darko Draskovic 2019-03-20 14:30:38 +01:00 committed by Manuel Imperiale
parent e95e010a3a
commit d504c4f67d
10 changed files with 120 additions and 126 deletions

View File

@ -3,42 +3,7 @@ Dashboard made with [elm-bootstrap](http://elm-bootstrap.info/).
## Install ## Install
### Install GUI as a part of Mainflux build ### Docker container GUI 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
Install Docker (https://docs.docker.com/install/) and Docker compose Install Docker (https://docs.docker.com/install/) and Docker compose
(https://docs.docker.com/compose/install/), `cd` to Mainflux root directory and (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` `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` `docker-compose -f docker/docker-compose.yml up ui`
if you want to launch just GUI. 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 Install Elm (https://guide.elm-lang.org/install.html) and then run the following
it. Launch Mainflux without ui service, either natively or as a Docker commands:
composition. Follow the guidelines for Mainflux contributors found here
```
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/. https://mainflux.readthedocs.io/en/latest/CONTRIBUTING/.

View File

@ -24,7 +24,7 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Http import Http
import HttpMF exposing (path) import HttpMF exposing (paths)
import Json.Decode as D import Json.Decode as D
import Json.Encode as E import Json.Encode as E
import ModalMF import ModalMF
@ -123,7 +123,7 @@ update msg model token =
ProvisionChannel -> ProvisionChannel ->
( resetEdit model ( resetEdit model
, HttpMF.provision , HttpMF.provision
(B.relative [ path.channels ] []) (B.relative [ paths.channels ] [])
token token
{ emptyChannel { emptyChannel
| name = Just model.name | name = Just model.name
@ -160,7 +160,7 @@ update msg model token =
UpdateChannel -> UpdateChannel ->
( resetEdit { model | editMode = False } ( resetEdit { model | editMode = False }
, HttpMF.update , HttpMF.update
(B.relative [ path.channels, model.channel.id ] []) (B.relative [ paths.channels, model.channel.id ] [])
token token
{ emptyChannel { emptyChannel
| name = Just model.name | name = Just model.name
@ -181,7 +181,7 @@ update msg model token =
RetrieveChannel channelid -> RetrieveChannel channelid ->
( model ( model
, HttpMF.retrieve , HttpMF.retrieve
(B.relative [ path.channels, channelid ] []) (B.relative [ paths.channels, channelid ] [])
token token
RetrievedChannel RetrievedChannel
channelDecoder channelDecoder
@ -198,7 +198,7 @@ update msg model token =
RetrieveChannels -> RetrieveChannels ->
( model ( model
, HttpMF.retrieve , HttpMF.retrieve
(B.relative [ path.channels ] (Helpers.buildQueryParamList model.offset model.limit)) (B.relative [ paths.channels ] (Helpers.buildQueryParamList model.offset model.limit))
token token
RetrievedChannels RetrievedChannels
channelsDecoder channelsDecoder
@ -207,7 +207,7 @@ update msg model token =
RetrieveChannelsForThing thingid -> RetrieveChannelsForThing thingid ->
( model ( model
, HttpMF.retrieve , 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 token
RetrievedChannels RetrievedChannels
channelsDecoder channelsDecoder
@ -224,7 +224,7 @@ update msg model token =
RemoveChannel id -> RemoveChannel id ->
( resetEdit model ( resetEdit model
, HttpMF.remove , HttpMF.remove
(B.relative [ path.channels, id ] []) (B.relative [ paths.channels, id ] [])
token token
RemovedChannel RemovedChannel
) )
@ -433,12 +433,12 @@ updateChannelList model token =
( model ( model
, Cmd.batch , Cmd.batch
[ HttpMF.retrieve [ HttpMF.retrieve
(B.relative [ path.channels ] (Helpers.buildQueryParamList model.offset model.limit)) (B.relative [ paths.channels ] (Helpers.buildQueryParamList model.offset model.limit))
token token
RetrievedChannels RetrievedChannels
channelsDecoder channelsDecoder
, HttpMF.retrieve , HttpMF.retrieve
(B.relative [ path.channels, model.channel.id ] []) (B.relative [ paths.channels, model.channel.id ] [])
token token
RetrievedChannel RetrievedChannel
channelDecoder channelDecoder
@ -450,7 +450,7 @@ updateChannelListForThing : Model -> String -> String -> ( Model, Cmd Msg )
updateChannelListForThing model token thingid = updateChannelListForThing model token thingid =
( model ( model
, HttpMF.retrieve , 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 token
RetrievedChannels RetrievedChannels
channelsDecoder channelsDecoder

View File

@ -24,7 +24,7 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Http import Http
import HttpMF exposing (path) import HttpMF exposing (paths)
import List.Extra import List.Extra
import Thing import Thing
import Url.Builder as B import Url.Builder as B
@ -207,7 +207,7 @@ connect checkedThingsIds checkedChannelsIds method token =
List.map List.map
(\channelid -> (\channelid ->
HttpMF.request HttpMF.request
(B.relative [ path.channels, channelid, path.things, thingid ] []) (B.relative [ paths.channels, channelid, paths.things, thingid ] [])
method method
token token
Http.emptyBody Http.emptyBody

12
ui/src/Env.elm Normal file
View File

@ -0,0 +1,12 @@
-- Copyright (c) 2019
-- Mainflux
--
-- SPDX-License-Identifier: Apache-2.0
module Env exposing (env)
env =
{ url = "http://localhost:80/"
}

View File

@ -4,9 +4,10 @@
-- SPDX-License-Identifier: Apache-2.0 -- 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 Dict
import Env exposing (env)
import Helpers import Helpers
import Http import Http
import Json.Decode as D import Json.Decode as D
@ -14,12 +15,11 @@ import Json.Encode as E
import Url.Builder as B import Url.Builder as B
url = baseURL =
{ base = "http://localhost" env.url
}
path = paths =
{ users = "users" { users = "users"
, tokens = "tokens" , tokens = "tokens"
, things = "things" , things = "things"
@ -107,12 +107,30 @@ expectRetrieve toMsg decoder =
-- REQUEST -- 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 : 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 Http.request
{ method = method { method = method
, headers = [ Http.header "Authorization" token ] , headers = [ Http.header "Authorization" token ]
, url = u , url = baseURL ++ path
, body = b , body = b
, expect = expectStatus msg , expect = expectStatus msg
, timeout = Nothing , 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 : String -> String -> (Result Http.Error a -> msg) -> D.Decoder a -> Cmd msg
retrieve u token msg decoder = retrieve path token msg decoder =
Http.request Http.request
{ method = "GET" { method = "GET"
, headers = [ Http.header "Authorization" token ] , headers = [ Http.header "Authorization" token ]
, url = u , url = baseURL ++ path
, body = Http.emptyBody , body = Http.emptyBody
, expect = expectRetrieve msg decoder , expect = expectRetrieve msg decoder
, timeout = Nothing , 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 : 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 Http.request
{ method = "POST" { method = "POST"
, headers = [ Http.header "Authorization" token ] , headers = [ Http.header "Authorization" token ]
, url = u , url = baseURL ++ path
, body = , body =
encoder e encoder e
|> Http.jsonBody |> 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 : 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 Http.request
{ method = "PUT" { method = "PUT"
, headers = [ Http.header "Authorization" token ] , headers = [ Http.header "Authorization" token ]
, url = u , url = baseURL ++ path
, body = , body =
encoder e encoder e
|> Http.jsonBody |> Http.jsonBody
@ -164,11 +182,11 @@ update u token e encoder msg =
remove : String -> String -> (Result Http.Error String -> msg) -> Cmd msg remove : String -> String -> (Result Http.Error String -> msg) -> Cmd msg
remove u token msg = remove path token msg =
Http.request Http.request
{ method = "DELETE" { method = "DELETE"
, headers = [ Http.header "Authorization" token ] , headers = [ Http.header "Authorization" token ]
, url = u , url = baseURL ++ path
, body = Http.emptyBody , body = Http.emptyBody
, expect = expectStatus msg , expect = expectStatus msg
, timeout = Nothing , timeout = Nothing

View File

@ -299,7 +299,7 @@ mfStylesheet =
view : Model -> Browser.Document Msg view : Model -> Browser.Document Msg
view model = view model =
{ title = "Gateflux" { title = "Mainflux"
, body = , body =
let let
buttonAttrs = buttonAttrs =

View File

@ -23,7 +23,7 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Http import Http
import HttpMF exposing (path) import HttpMF exposing (paths)
import List.Extra import List.Extra
import Thing import Thing
import Url.Builder as B import Url.Builder as B
@ -217,7 +217,7 @@ genChannelRows checkedChannelsIds channels =
send : String -> String -> String -> Cmd Msg send : String -> String -> String -> Cmd Msg
send channelid thingkey message = send channelid thingkey message =
HttpMF.request HttpMF.request
(B.relative [ "http", path.channels, channelid, path.messages ] []) (B.relative [ "http", paths.channels, channelid, paths.messages ] [])
"POST" "POST"
thingkey thingkey
(Http.stringBody "application/json" message) (Http.stringBody "application/json" message)

View File

@ -27,7 +27,7 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Http import Http
import HttpMF exposing (path) import HttpMF exposing (paths)
import Json.Decode as D import Json.Decode as D
import Json.Encode as E import Json.Encode as E
import ModalMF import ModalMF
@ -143,7 +143,7 @@ update msg model token =
ProvisionThing -> ProvisionThing ->
( resetEdit model ( resetEdit model
, HttpMF.provision , HttpMF.provision
(B.relative [ path.things ] []) (B.relative [ paths.things ] [])
token token
{ emptyThing { emptyThing
| name = Just model.name | name = Just model.name
@ -181,7 +181,7 @@ update msg model token =
UpdateThing -> UpdateThing ->
( resetEdit { model | editMode = False } ( resetEdit { model | editMode = False }
, HttpMF.update , HttpMF.update
(B.relative [ path.things, model.thing.id ] []) (B.relative [ paths.things, model.thing.id ] [])
token token
{ emptyThing { emptyThing
| name = Just model.name | name = Just model.name
@ -203,7 +203,7 @@ update msg model token =
RetrieveThing thingid -> RetrieveThing thingid ->
( model ( model
, HttpMF.retrieve , HttpMF.retrieve
(B.relative [ path.things, thingid ] []) (B.relative [ paths.things, thingid ] [])
token token
RetrievedThing RetrievedThing
thingDecoder thingDecoder
@ -220,7 +220,7 @@ update msg model token =
RetrieveThings -> RetrieveThings ->
( model ( model
, HttpMF.retrieve , HttpMF.retrieve
(B.relative [ path.things ] (Helpers.buildQueryParamList model.offset model.limit)) (B.relative [ paths.things ] (Helpers.buildQueryParamList model.offset model.limit))
token token
RetrievedThings RetrievedThings
thingsDecoder thingsDecoder
@ -237,7 +237,7 @@ update msg model token =
RemoveThing id -> RemoveThing id ->
( model ( model
, HttpMF.remove , HttpMF.remove
(B.relative [ path.things, id ] []) (B.relative [ paths.things, id ] [])
token token
RemovedThing RemovedThing
) )
@ -491,12 +491,12 @@ updateThingList model token =
( model ( model
, Cmd.batch , Cmd.batch
[ HttpMF.retrieve [ HttpMF.retrieve
(B.relative [ path.things ] (Helpers.buildQueryParamList model.offset model.limit)) (B.relative [ paths.things ] (Helpers.buildQueryParamList model.offset model.limit))
token token
RetrievedThings RetrievedThings
thingsDecoder thingsDecoder
, HttpMF.retrieve , HttpMF.retrieve
(B.relative [ path.things, model.thing.id ] []) (B.relative [ paths.things, model.thing.id ] [])
token token
RetrievedThing RetrievedThing
thingDecoder thingDecoder

View File

@ -19,7 +19,7 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Http import Http
import HttpMF exposing (path) import HttpMF exposing (baseURL, paths)
import Json.Decode as D import Json.Decode as D
import Json.Encode as E import Json.Encode as E
import Url.Builder as B import Url.Builder as B
@ -66,10 +66,12 @@ update msg model =
Create -> Create ->
( model ( model
, create , HttpMF.user
model.email model.email
model.password model.password
(B.relative [ path.users ] []) (B.relative [ paths.users ] [])
(encode (User model.email model.password))
(HttpMF.expectStatus Created)
) )
Created result -> Created result ->
@ -82,10 +84,15 @@ update msg model =
GetToken -> GetToken ->
( model ( model
, getToken , HttpMF.user
model.email model.email
model.password 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 -> GotToken result ->
@ -182,43 +189,6 @@ decoder =
-- HTTP -- 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 -> Bool
loggedIn model = loggedIn model =
if String.length model.token > 0 then if String.length model.token > 0 then

View File

@ -10,7 +10,7 @@ import Error
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Http import Http
import HttpMF exposing (path) import HttpMF exposing (paths)
import Json.Decode as D import Json.Decode as D
import Json.Encode as E import Json.Encode as E
import Url.Builder as B import Url.Builder as B
@ -35,10 +35,10 @@ update msg model =
case msg of case msg of
GetVersion -> GetVersion ->
( model ( model
, Http.get , HttpMF.version
{ url = B.relative [ path.version ] [] (B.relative [ paths.version ] [])
, expect = Http.expectJson GotVersion (D.field "version" D.string) GotVersion
} (D.field "version" D.string)
) )
GotVersion result -> GotVersion result ->