Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Browser minor improvements #727

Merged
merged 23 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8e1cfc9
Put whole api under /api umbrella
swistak35 Apr 30, 2020
cbb65ab
Use nesting in tests
swistak35 Apr 30, 2020
2e2d1f4
Use Routing in rendering the page too
swistak35 Apr 30, 2020
3b76e8f
Refactoring: Extract method Routing#base_url
swistak35 Apr 30, 2020
a661e86
Very spike-ish solution for parsing without fragments
swistak35 Apr 30, 2020
c09cad8
Don't include excessive slash in the URL
swistak35 Apr 30, 2020
eae18d5
Add possibility to specify mount point
swistak35 Apr 30, 2020
e6d50af
Parse URLs provided to app just after app initialization
swistak35 Apr 30, 2020
8d0bc86
Rename ViewStream -> ShowStream
swistak35 Apr 30, 2020
9ee9315
Distinguish between different HTTP state when displaying Event
swistak35 Apr 30, 2020
3dd8f18
Use RemoteResource when fetching causedEvents
swistak35 Apr 30, 2020
3df0c00
decodeLocation now works with Url, not String
swistak35 May 1, 2020
d2cad04
Extract Route tests
swistak35 May 1, 2020
4278249
Remove dead code
swistak35 May 1, 2020
a4ec1a5
Extract common method and add tests for URL generation
swistak35 May 1, 2020
7f2851c
Added more Route tests
swistak35 May 1, 2020
cdf724f
Fix browser_integration_spec after changing API url
swistak35 May 8, 2020
4626006
Add apiUrl to the data passed to frontend
swistak35 May 15, 2020
80d3f75
Base the requests only based on apiUrl
swistak35 May 15, 2020
949e08a
Make it possible to customize backend api_url
swistak35 May 15, 2020
d077238
Use different pagination url
swistak35 May 15, 2020
9e28708
Add spinner for event loading screen
swistak35 May 16, 2020
94937a6
Prettify
swistak35 May 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions rails_event_store/spec/browser_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ module RailsEventStore
specify 'api' do
event_store.publish(events = 21.times.map { DummyEvent.new })
request = ::Rack::MockRequest.new(app)
response = request.get('/res/streams/all/relationships/events')
response = request.get('/res/api/streams/all/relationships/events')

expect(JSON.parse(response.body)["links"]).to eq({
"last" => "http://example.org/res/streams/all/relationships/events/head/forward/20",
"next" => "http://example.org/res/streams/all/relationships/events/#{events[1].event_id}/backward/20"
"last" => "http://example.org/res/api/streams/all/relationships/events/head/forward/20",
"next" => "http://example.org/res/api/streams/all/relationships/events/#{events[1].event_id}/backward/20"
})
end

Expand Down
8 changes: 7 additions & 1 deletion ruby_event_store-browser/devserver/config.ru
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ RELATED_STREAMS_QUERY = ->(stream_name) do
end
end

run RubyEventStore::Browser::App.for(
browser_app = RubyEventStore::Browser::App.for(
event_store_locator: -> { event_store },
related_streams_query: RELATED_STREAMS_QUERY,
)
mount_point = "/"
run (Rack::Builder.new do
map mount_point do
run browser_app
end
end)
23 changes: 20 additions & 3 deletions ruby_event_store-browser/elm/src/Api.elm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Api exposing (Event, PaginatedList, PaginationLink, PaginationLinks, Stream, emptyPaginatedList, eventDecoder, eventsDecoder, getEvent, getEvents, getStream)
module Api exposing (Event, PaginatedList, PaginationLink, PaginationLinks, RemoteResource(..), Stream, emptyPaginatedList, eventDecoder, eventsDecoder, getEvent, getEvents, getStream)

import Flags exposing (Flags)
import Http
Expand All @@ -10,6 +10,13 @@ import Time
import Url


type RemoteResource a
= Loading
| Loaded a
| NotFound
| Failure


type alias Event =
{ eventType : String
, eventId : String
Expand Down Expand Up @@ -52,18 +59,28 @@ buildUrl baseUrl id =
baseUrl ++ "/" ++ Url.percentEncode id


eventUrl : Flags -> String -> String
eventUrl flags eventId =
buildUrl (Url.toString flags.apiUrl ++ "/events") eventId


streamUrl : Flags -> String -> String
streamUrl flags streamId =
buildUrl (Url.toString flags.apiUrl ++ "/streams") streamId


getEvent : (Result Http.Error Event -> msg) -> Flags -> String -> Cmd msg
getEvent msgBuilder flags eventId =
Http.get
{ url = buildUrl flags.eventsUrl eventId
{ url = eventUrl flags eventId
, expect = Http.expectJson msgBuilder eventDecoder
}


getStream : (Result Http.Error Stream -> msg) -> Flags -> String -> Cmd msg
getStream msgBuilder flags streamId =
Http.get
{ url = buildUrl flags.streamsUrl streamId
{ url = streamUrl flags streamId
, expect = Http.expectJson msgBuilder streamDecoder
}

Expand Down
21 changes: 17 additions & 4 deletions ruby_event_store-browser/elm/src/Flags.elm
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
module Flags exposing (Flags)
module Flags exposing (Flags, RawFlags, buildFlags)

import Url

type alias Flags =

type alias RawFlags =
{ rootUrl : String
, streamsUrl : String
, eventsUrl : String
, apiUrl : String
, resVersion : String
}


type alias Flags =
{ rootUrl : Url.Url
, apiUrl : Url.Url
, resVersion : String
}


buildFlags : RawFlags -> Maybe Flags
buildFlags { rootUrl, apiUrl, resVersion } =
Maybe.map3 Flags (Url.fromString rootUrl) (Url.fromString apiUrl) (Just resVersion)
12 changes: 9 additions & 3 deletions ruby_event_store-browser/elm/src/Layout.elm
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module Layout exposing (Model, Msg, buildModel, update, view, viewNotFound)
module Layout exposing (Model, Msg, buildModel, update, view, viewIncorrectConfig, viewNotFound)

import Browser.Navigation
import Flags exposing (Flags)
import Html exposing (..)
import Html.Attributes exposing (class, disabled, href, placeholder, value)
import Html.Events exposing (onClick, onInput, onSubmit)
import Route
import Url
import WrappedModel exposing (..)


Expand All @@ -29,7 +30,7 @@ update : Msg -> WrappedModel Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GoToStream ->
( { goToStream = "" }, Browser.Navigation.pushUrl model.key (Route.streamUrl model.internal.goToStream) )
( { goToStream = "" }, Browser.Navigation.pushUrl model.key (Route.streamUrl model.flags.rootUrl model.internal.goToStream) )

GoToStreamChanged newValue ->
( { goToStream = newValue }, Cmd.none )
Expand All @@ -49,11 +50,16 @@ viewNotFound =
h1 [] [ text "404" ]


viewIncorrectConfig : Html a
viewIncorrectConfig =
h1 [] [ text "Incorrect RES Browser config" ]


browserNavigation : WrappedModel Model -> Html Msg
browserNavigation model =
nav [ class "navigation" ]
[ div [ class "navigation__brand" ]
[ a [ href model.flags.rootUrl, class "navigation__logo" ] [ text "Ruby Event Store" ]
[ a [ href (Url.toString model.flags.rootUrl), class "navigation__logo" ] [ text "Ruby Event Store" ]
]
, div [ class "navigation__links" ] []
, div [ class "navigation__go-to-stream" ]
Expand Down
112 changes: 65 additions & 47 deletions ruby_event_store-browser/elm/src/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ module Main exposing (main)

import Browser
import Browser.Navigation
import Flags exposing (Flags)
import Flags exposing (Flags, RawFlags, buildFlags)
import Html exposing (Html)
import Layout
import Maybe exposing (andThen)
import Page.ShowEvent
import Page.ViewStream
import Page.ShowStream
import Route
import Url
import Url.Parser exposing ((</>))
import WrappedModel exposing (..)


main : Program Flags Model Msg
main : Program RawFlags Model Msg
main =
Browser.application
{ init = buildModel
Expand All @@ -27,7 +28,7 @@ main =

type alias Model =
{ page : Page
, flags : Flags
, flags : Maybe Flags
, key : Browser.Navigation.Key
, layout : Layout.Model
}
Expand All @@ -38,26 +39,26 @@ type Msg
| ClickedLink Browser.UrlRequest
| GotLayoutMsg Layout.Msg
| GotShowEventMsg Page.ShowEvent.Msg
| GotViewStreamMsg Page.ViewStream.Msg
| GotShowStreamMsg Page.ShowStream.Msg


type Page
= NotFound
| ShowEvent Page.ShowEvent.Model
| ViewStream Page.ViewStream.Model
| ShowStream Page.ShowStream.Model


subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none


buildModel : Flags -> Url.Url -> Browser.Navigation.Key -> ( Model, Cmd Msg )
buildModel flags location key =
buildModel : RawFlags -> Url.Url -> Browser.Navigation.Key -> ( Model, Cmd Msg )
buildModel rawFlags location key =
let
initModel =
{ page = NotFound
, flags = flags
, flags = buildFlags rawFlags
, key = key
, layout = Layout.buildModel
}
Expand All @@ -83,20 +84,25 @@ update msg model =
, Browser.Navigation.load url
)

( GotViewStreamMsg viewStreamUIMsg, ViewStream viewStreamModel ) ->
Page.ViewStream.update viewStreamUIMsg viewStreamModel
|> updateWith ViewStream GotViewStreamMsg model
( GotShowStreamMsg showStreamUIMsg, ShowStream showStreamModel ) ->
Page.ShowStream.update showStreamUIMsg showStreamModel
|> updateWith ShowStream GotShowStreamMsg model

( GotShowEventMsg openedEventUIMsg, ShowEvent showEventModel ) ->
Page.ShowEvent.update openedEventUIMsg showEventModel
|> updateWith ShowEvent GotShowEventMsg model

( GotLayoutMsg layoutMsg, _ ) ->
let
( layoutModel, layoutCmd ) =
Layout.update layoutMsg (wrapModel model model.layout)
in
( { model | layout = layoutModel }, Cmd.map GotLayoutMsg layoutCmd )
case model.flags of
Nothing ->
( model, Cmd.none )

Just flags ->
let
( layoutModel, layoutCmd ) =
Layout.update layoutMsg (wrapModel model model.layout flags)
in
( { model | layout = layoutModel }, Cmd.map GotLayoutMsg layoutCmd )

( _, _ ) ->
( model, Cmd.none )
Expand All @@ -111,40 +117,52 @@ updateWith toPageModel toMsg model ( subModel, subCmd ) =

urlUpdate : Model -> Url.Url -> ( Model, Cmd Msg )
urlUpdate model location =
case Route.decodeLocation location of
Just (Route.BrowseEvents encodedStreamId) ->
case Url.percentDecode encodedStreamId of
Just streamId ->
( { model | page = ViewStream (Page.ViewStream.initModel streamId) }
, Cmd.map GotViewStreamMsg (Page.ViewStream.initCmd model.flags streamId)
)
case model.flags of
Nothing ->
( model, Cmd.none )

Nothing ->
( { model | page = NotFound }, Cmd.none )
Just flags ->
case Route.decodeLocation flags.rootUrl location of
Just (Route.BrowseEvents encodedStreamId) ->
case Url.percentDecode encodedStreamId of
Just streamId ->
( { model | page = ShowStream (Page.ShowStream.initModel flags streamId) }
, Cmd.map GotShowStreamMsg (Page.ShowStream.initCmd flags streamId)
)

Just (Route.ShowEvent encodedEventId) ->
case Url.percentDecode encodedEventId of
Just eventId ->
( { model | page = ShowEvent (Page.ShowEvent.initModel model.flags eventId) }
, Cmd.map GotShowEventMsg (Page.ShowEvent.initCmd model.flags eventId)
)
Nothing ->
( { model | page = NotFound }, Cmd.none )

Just (Route.ShowEvent encodedEventId) ->
case Url.percentDecode encodedEventId of
Just eventId ->
( { model | page = ShowEvent (Page.ShowEvent.initModel flags eventId) }
, Cmd.map GotShowEventMsg (Page.ShowEvent.initCmd flags eventId)
)

Nothing ->
( { model | page = NotFound }, Cmd.none )

Nothing ->
( { model | page = NotFound }, Cmd.none )

Nothing ->
( { model | page = NotFound }, Cmd.none )


view : Model -> Browser.Document Msg
view model =
let
( maybePageTitle, pageContent ) =
viewPage model.page
in
{ body = [ Layout.view GotLayoutMsg (wrapModel model model.layout) pageContent ]
, title = fullTitle maybePageTitle
}
case model.flags of
Nothing ->
{ title = fullTitle Nothing
, body = [ Layout.viewIncorrectConfig ]
}

Just flags ->
let
( maybePageTitle, pageContent ) =
viewPage model.page
in
{ body = [ Layout.view GotLayoutMsg (wrapModel model model.layout flags) pageContent ]
, title = fullTitle maybePageTitle
}


fullTitle : Maybe String -> String
Expand All @@ -160,8 +178,8 @@ fullTitle maybePageTitle =
viewPage : Page -> ( Maybe String, Html Msg )
viewPage page =
case page of
ViewStream viewStreamUIModel ->
viewOnePage GotViewStreamMsg Page.ViewStream.view viewStreamUIModel
ShowStream showStreamUIModel ->
viewOnePage GotShowStreamMsg Page.ShowStream.view showStreamUIModel

ShowEvent openedEventUIModel ->
viewOnePage GotShowEventMsg Page.ShowEvent.view openedEventUIModel
Expand All @@ -179,9 +197,9 @@ viewOnePage pageMsgBuilder pageViewFunction pageModel =
( Just pageTitle, Html.map pageMsgBuilder pageContent )


wrapModel : Model -> a -> WrappedModel a
wrapModel globalModel internalModel =
wrapModel : Model -> a -> Flags -> WrappedModel a
wrapModel globalModel internalModel flags =
{ internal = internalModel
, key = globalModel.key
, flags = globalModel.flags
, flags = flags
}
Loading