Skip to content

Commit

Permalink
Add routing primitives
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Simmerl committed Dec 2, 2016
1 parent 9adf121 commit a616f49
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 48 deletions.
20 changes: 15 additions & 5 deletions cmd/console/App.elm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import Html.Events exposing (onClick, onInput, onSubmit)
import Http
import Json.Decode as Decode
import Json.Encode as Encode
import Navigation

import Route

-- MODEL
Expand All @@ -23,6 +25,7 @@ type alias Model =
{ apps : List App
, description : String
, name : String
, selected : (Maybe App)
}

init : (Model, Cmd Msg)
Expand All @@ -31,7 +34,7 @@ init =

initModel : Model
initModel =
Model [] "" ""
Model [] "" "" Nothing

-- UPDATE

Expand All @@ -40,6 +43,7 @@ type Msg
| Description String
| Name String
| New (Result Http.Error App)
| Select String
| Submit

update : Msg -> Model -> (Model, Cmd Msg)
Expand All @@ -57,6 +61,8 @@ update msg model =
({ model | apps = model.apps ++ [ app ], description = "", name = "" }, Cmd.none)
New (Err _) ->
(model, Cmd.none)
Select id ->
({ model | selected = (selectApp id model.apps) }, Navigation.newUrl (Route.construct (Route.App id)))
Submit ->
(model, create model.name model.description)

Expand Down Expand Up @@ -97,9 +103,8 @@ viewItem app =
else
span [ class "nc-icon-glyph ui-1_circle-remove" ] []
in
tr []
tr [ onClick (Select app.id) ]
[ td [ class "status" ] [ enabled ]
, td [] [ text app.id ]
, td [] [ text app.name ]
, td [] [ text app.description ]
, td [] [ text app.token ]
Expand All @@ -114,7 +119,6 @@ viewList apps =
[ thead []
[ tr []
[ th [ class "status" ] [ text "status" ]
, th [] [ text "id" ]
, th [] [ text "name" ]
, th [] [ text "description" ]
, th [] [ text "token" ]
Expand Down Expand Up @@ -150,4 +154,10 @@ encode name description =

getList : Cmd Msg
getList =
Http.send AppList (Http.get "/api/apps" decodeList)
Http.send AppList (Http.get "/api/apps" decodeList)

selectApp : String -> List App -> Maybe App
selectApp id apps =
apps
|> List.filter (\app -> app.id == id)
|> List.head
110 changes: 68 additions & 42 deletions cmd/console/Console.elm
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
module Console exposing (..)

import Html exposing (..)
import Html.Attributes exposing (class, href, placeholder, title, type_, value)
import Html.Attributes exposing (class, href, id, placeholder, title, type_, value)
import Html.Events exposing (onClick, onInput, onSubmit)
import Navigation
import UrlParser as Url exposing ((</>), (<?>), s, int, stringParam, top)

import App
import Route

main : Program Flags Model Msg
main =
Navigation.programWithFlags UrlChange
Navigation.programWithFlags LocationChange
{ init = init
, subscriptions = subscriptions
, update = update
Expand All @@ -27,35 +28,38 @@ type alias Flags =
type alias Model =
{ appModel : App.Model
, debug : Bool
, route : (Maybe Route)
, route : (Maybe Route.Route)
, zone : String
}

type alias Tag = List (Html Msg) -> Html Msg

type Route
= Apps
| Home

init : Flags -> Navigation.Location -> (Model, Cmd Msg)
init {zone} location =
case (Url.parsePath route location) of
Nothing ->
(Model App.initModel (isDebug location) (Url.parsePath route location) zone, Cmd.none)
Just Apps ->
let
(appModel, appCmd) = App.init
in
(Model appModel (isDebug location) (Url.parsePath route location) zone, Cmd.map AppMsg appCmd)
Just Home ->
(Model App.initModel (isDebug location) (Url.parsePath route location) zone, Cmd.none)
let
route = Route.parse location
in
case route of
Nothing ->
(Model App.initModel (isDebug location) route zone, Cmd.none)
Just (Route.App id) ->
(Model App.initModel (isDebug location) route zone, Cmd.none)
Just Route.Apps ->
let
(appModel, appCmd) = App.init
in
(Model appModel (isDebug location) route zone, Cmd.map AppMsg appCmd)
Just Route.Home ->
(Model App.initModel (isDebug location) route zone, Cmd.none)

-- UPDATE

type Msg
= AppMsg App.Msg
| Navigate String
| UrlChange Navigation.Location
| LocationChange Navigation.Location
| NavigateApp String
| NavigateApps
| NavigateHome

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
Expand All @@ -65,19 +69,24 @@ update msg model =
(appModel, appCmd) = App.update appMsg model.appModel
in
({ model | appModel = appModel }, Cmd.map AppMsg appCmd)
Navigate path ->
(model, Navigation.newUrl path)
UrlChange location ->
LocationChange location ->
let
newRoute = Url.parsePath route location
newRoute = Route.parse location
in
if newRoute == Just Apps then
if newRoute == Just Route.Apps then
let
(appModel, appCmd) = App.init
in
({ model | appModel = appModel, route = newRoute }, Cmd.map AppMsg appCmd)
else
({ model | route = newRoute }, Cmd.none)
NavigateApp id ->
(model, Navigation.newUrl (Route.construct (Route.App id)))
NavigateApps ->
(model, Navigation.newUrl (Route.construct Route.Apps))
NavigateHome ->
(model, Navigation.newUrl (Route.construct Route.Home))


-- SUBSCRIPTION

Expand All @@ -93,28 +102,52 @@ view model =
content = case model.route of
Nothing ->
h3 [] [ text "Looks like we couldn't find the page you were looking for." ]
Just Apps ->
Just (Route.App id) ->
h3 [] [ text ("App single view for " ++ id) ]
Just Route.Apps ->
Html.map AppMsg (App.view model.appModel)
Just Home ->
Just Route.Home ->
h3 [] [ text "You are home now." ]
in
div [ class "content" ]
[ viewContainer (header [])
[ viewHeader
, nav [] [ span [] [ text model.zone ] ]
]
, viewContainer (section [])
[ h2 []
[ a [ onClick (Navigate "/apps"), title "Apps" ]
[ span [ class "icon nc-icon-glyph ui-2_layers" ] []
, span [] [ text "Apps" ]
]
]
]
, viewContext model
, viewContainer (section [ class "highlight" ]) [ content ]
, viewContainer (footer []) [ viewDebug model ]
]

viewContext : Model -> Html Msg
viewContext model =
let
(sectionClass, info) =
case model.appModel.selected of
Nothing ->
("", span [] [])
Just app ->
("selected", viewAppSelected app)

in
viewContainer (section [ class sectionClass, id "context" ])
[ h2 []
[ a [ onClick NavigateApps, title "Apps" ]
[ span [ class "icon nc-icon-glyph ui-2_layers" ] []
, span [] [ text "Apps" ]
]
]
, info
]

viewAppSelected : App.App -> Html Msg
viewAppSelected app =
nav []
[ a [ onClick (NavigateApp app.id), title app.name ]
[ span [] [ text app.name ]
]
]

viewContainer : Tag -> List (Html Msg) -> Html Msg
viewContainer elem content =
elem
Expand All @@ -134,21 +167,14 @@ viewDebug model =
viewHeader : Html Msg
viewHeader =
h1 []
[ a [ onClick (Navigate "/"), title "Home" ]
[ a [ onClick NavigateHome, title "Home" ]
[ strong [] [ text "SocialPath" ]
, span [] [ text "Console" ]
]
]

-- ROUTING

route : Url.Parser (Route -> a) a
route =
Url.oneOf
[ Url.map Apps (Url.s "apps")
, Url.map Home (Url.s "")
]

isDebug : Navigation.Location -> Bool
isDebug location =
let
Expand Down
31 changes: 31 additions & 0 deletions cmd/console/Route.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Route exposing (..)

import Navigation exposing (Location)
import UrlParser exposing (Parser, (</>), map, oneOf, parsePath, top, s, string)

type Route
= App String
| Apps
| Home

construct : Route -> String
construct route =
case route of
App id ->
"/apps/" ++ id
Apps ->
"/apps"
Home ->
"/"

routes : Parser (Route -> a) a
routes =
oneOf
[ map Home top
, map App (s "apps" </> string)
, map Apps (s "apps")
]

parse : Location -> (Maybe Route)
parse location =
parsePath routes location
16 changes: 15 additions & 1 deletion cmd/console/styles/console.css
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ header {

header div.container {
align-items: baseline;
border-bottom: 0.1rem solid rgb(63, 91, 96);
border-bottom: 0.2rem solid rgb(63, 91, 96);
display: flex;
justify-content: space-between;
}
Expand All @@ -121,6 +121,20 @@ input.description {
width: 40rem;
}

section#context div.container {
align-items: baseline;
display: flex;
justify-content: space-between;
}

section#context.selected div.container {
border-bottom: 0.1rem solid rgb(63, 91, 96);
}

section#context nav {
font-size: 2.4rem;
}

section.highlight {
background: rgb(255, 255, 255);
border-top: 0.1rem solid rgba(144, 144, 144, 0.25);
Expand Down

0 comments on commit a616f49

Please sign in to comment.