Working on event detail. Also small visual help in DayView. Also some favorite stuff.

This commit is contained in:
Vidir Valberg Gudmundsson 2017-07-27 23:21:16 +02:00
parent 974694bd5f
commit a447ca476f
7 changed files with 131 additions and 69 deletions

View file

@ -7,7 +7,7 @@ import Models exposing (Day, Speaker, Event, EventInstance, EventLocation, Event
-- Core modules -- Core modules
import Json.Decode exposing (int, string, float, list, bool, dict, Decoder) import Json.Decode exposing (int, string, float, list, bool, dict, Decoder, nullable)
import Json.Decode.Pipeline exposing (decode, required, optional, hardcoded) import Json.Decode.Pipeline exposing (decode, required, optional, hardcoded)
import Date exposing (Date, Month(..)) import Date exposing (Date, Month(..))
@ -55,6 +55,7 @@ eventDecoder =
|> required "speakers" (list speakerDecoder) |> required "speakers" (list speakerDecoder)
|> required "video_recording" bool |> required "video_recording" bool
|> optional "video_url" string "" |> optional "video_url" string ""
|> required "event_type" string
dateDecoder : Decoder Date dateDecoder : Decoder Date
@ -86,6 +87,7 @@ eventInstanceDecoder =
|> required "location_icon" string |> required "location_icon" string
|> required "video_recording" bool |> required "video_recording" bool
|> optional "video_url" string "" |> optional "video_url" string ""
|> optional "is_favorited" (nullable bool) Nothing
eventLocationDecoder : Decoder EventLocation eventLocationDecoder : Decoder EventLocation

View file

@ -75,6 +75,7 @@ type alias EventInstance =
, locationIcon : String , locationIcon : String
, videoRecording : Bool , videoRecording : Bool
, videoUrl : String , videoUrl : String
, isFavorited : Maybe Bool
} }
@ -85,6 +86,7 @@ type alias Event =
, speakers : List Speaker , speakers : List Speaker
, videoRecording : Bool , videoRecording : Bool
, videoUrl : String , videoUrl : String
, eventType : String
} }

View file

@ -52,12 +52,12 @@ dayView day model =
div div
[ classList [ ( "row", True ) ] ] [ classList [ ( "row", True ) ] ]
[ gutter minutes [ gutter minutes
, locationColumns filteredEventInstances model.eventLocations model.flags.schedule_midnight_offset_hours , locationColumns filteredEventInstances model.eventLocations model.flags.schedule_midnight_offset_hours minutes
] ]
locationColumns : List EventInstance -> List EventLocation -> Int -> Html Msg locationColumns : List EventInstance -> List EventLocation -> Int -> List Date -> Html Msg
locationColumns eventInstances eventLocations offset = locationColumns eventInstances eventLocations offset minutes =
let let
columnWidth = columnWidth =
100.0 / toFloat (List.length eventLocations) 100.0 / toFloat (List.length eventLocations)
@ -71,11 +71,11 @@ locationColumns eventInstances eventLocations offset =
[ ( "col-sm-11", True ) [ ( "col-sm-11", True )
] ]
] ]
(List.map (\location -> locationColumn columnWidth eventInstances offset location) eventLocations) (List.map (\location -> locationColumn columnWidth eventInstances offset minutes location) eventLocations)
locationColumn : Float -> List EventInstance -> Int -> EventLocation -> Html Msg locationColumn : Float -> List EventInstance -> Int -> List Date -> EventLocation -> Html Msg
locationColumn columnWidth eventInstances offset location = locationColumn columnWidth eventInstances offset minutes location =
let let
locationInstances = locationInstances =
List.filter (\instance -> instance.location == location.slug) eventInstances List.filter (\instance -> instance.location == location.slug) eventInstances
@ -102,6 +102,23 @@ locationColumn columnWidth eventInstances offset location =
] ]
[ text location.name ] [ text location.name ]
] ]
++ (List.map
(\x ->
div
[ style
[ ( "backgroundColor"
, if Date.minute x == 30 || Date.minute x == 45 then
"#f8f8f8"
else
"#fff"
)
, ( "height", px blockHeight )
]
]
[]
)
minutes
)
++ (List.map (\group -> renderGroup offset group) overlappingGroups) ++ (List.map (\group -> renderGroup offset group) overlappingGroups)
) )

View file

@ -6,9 +6,14 @@ import Messages exposing (Msg(..))
import Models exposing (..) import Models exposing (..)
-- Core modules
import Date
-- External modules -- External modules
import Html exposing (Html, text, div, ul, li, span, i, h4, a, p, hr) import Html exposing (Html, text, div, ul, li, span, i, h3, h4, a, p, hr, strong)
import Html.Attributes exposing (class, classList, href) import Html.Attributes exposing (class, classList, href)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Markdown import Markdown
@ -22,58 +27,84 @@ eventDetailView eventSlug model =
model.events model.events
|> List.filter (\e -> e.slug == eventSlug) |> List.filter (\e -> e.slug == eventSlug)
|> List.head |> List.head
eventInstances =
List.filter (\instance -> instance.eventSlug == eventSlug) model.eventInstances
in in
case event of case event of
Just event -> Just event ->
div [ class "row" ] div [ class "row" ]
[ div [ class "col-sm-9" ] [ eventDetailContent event
[ a [ onClick BackInHistory, classList [ ( "btn", True ), ( "btn-default", True ) ] ] , eventDetailSidebar event eventInstances
[ i [ classList [ ( "fa", True ), ( "fa-chevron-left", True ) ] ] []
, text " Back"
]
, h4 [] [ text event.title ]
, p [] [ Markdown.toHtml [] event.abstract ]
, hr [] []
, eventInstancesList eventSlug model.eventInstances
]
, div
[ classList
[ ( "col-sm-3", True )
, ( "schedule-sidebar", True )
, ( "sticky", True )
]
]
[ videoRecordingSidebar event
, speakerSidebar event.speakers
]
] ]
Nothing -> Nothing ->
div [ class "row" ] div [ class "row" ]
[ text [ h4 [] [ text "Event not found." ]
(case model.dataLoaded of , a [ href "#" ] [ text "Click here to go the schedule overview." ]
True ->
"Event not found."
False ->
"Loading..."
)
] ]
videoRecordingSidebar : Event -> Html Msg eventDetailContent : Event -> Html Msg
videoRecordingSidebar event = eventDetailContent event =
div [ class "col-sm-9" ]
[ a [ onClick BackInHistory, classList [ ( "btn", True ), ( "btn-default", True ) ] ]
[ i [ classList [ ( "fa", True ), ( "fa-chevron-left", True ) ] ] []
, text " Back"
]
, h3 [] [ text event.title ]
, p [] [ Markdown.toHtml [] event.abstract ]
]
eventDetailSidebar : Event -> List EventInstance -> Html Msg
eventDetailSidebar event eventInstances =
let let
( video, willBeRecorded ) = videoRecordingLink =
if event.videoUrl /= "" then case event.videoUrl of
( h4 [] [ text "Watch the video here!" ], True ) "" ->
else if event.videoRecording == True then []
( h4 [] [ text "This event will be recorded!" ], True )
else _ ->
( h4 [] [ text "This event will NOT be recorded!" ], False ) [ a [ href event.videoUrl, classList [ ( "btn", True ), ( "btn-success", True ) ] ]
[ i [ classList [ ( "fa", True ), ( "fa-film", True ) ] ] []
, text " Watch recording here!"
]
]
in in
div [ classList [ ( "alert", True ), ( "alert-danger", not willBeRecorded ), ( "alert-info", willBeRecorded ) ] ] div
[ video ] [ classList
[ ( "col-sm-3", True )
, ( "schedule-sidebar", True )
, ( "sticky", True )
]
]
(videoRecordingLink
++ [ speakerSidebar event.speakers
, eventMetaDataSidebar event
, eventInstancesSidebar eventInstances
]
)
eventMetaDataSidebar : Event -> Html Msg
eventMetaDataSidebar event =
let
videoRecording =
case event.videoRecording of
True ->
"Yes"
False ->
"No"
in
div []
[ h4 [] [ text "Metadata" ]
, ul []
[ li [] [ strong [] [ text "Type: " ], text event.eventType ]
, li [] [ strong [] [ text "Recording: " ], text videoRecording ]
]
]
speakerSidebar : List Speaker -> Html Msg speakerSidebar : List Speaker -> Html Msg
@ -94,27 +125,30 @@ speakerDetail speaker =
] ]
eventInstancesList : String -> List EventInstance -> Html Msg eventInstancesSidebar : List EventInstance -> Html Msg
eventInstancesList eventSlug eventInstances = eventInstancesSidebar eventInstances =
let div []
instances = [ h4 []
List.filter (\instance -> instance.eventSlug == eventSlug) eventInstances [ text "This event will occur at:" ]
in , ul
div [] []
[ h4 [] (List.map eventInstanceItem eventInstances)
[ text "This event will occur at:" ] ]
, ul
[]
(List.map eventInstanceItem instances)
]
eventInstanceItem : EventInstance -> Html Msg eventInstanceItem : EventInstance -> Html Msg
eventInstanceItem eventInstance = eventInstanceItem eventInstance =
li [] let
[ text toFormat =
((Date.Extra.toFormattedString "y-MM-dd HH:mm" eventInstance.from) if Date.day eventInstance.from == Date.day eventInstance.to then
++ " to " "HH:mm"
++ (Date.Extra.toFormattedString "y-MM-d HH:mm" eventInstance.to) else
) "E HH:mm"
] in
li []
[ text
((Date.Extra.toFormattedString "E HH:mm" eventInstance.from)
++ " to "
++ (Date.Extra.toFormattedString toFormat eventInstance.to)
)
]

View file

@ -438,6 +438,7 @@ class Event(CampRelatedModel):
for speaker in self.speakers.all() for speaker in self.speakers.all()
], ],
'video_recording': self.video_recording, 'video_recording': self.video_recording,
'event_type': self.event_type.name,
} }
if self.video_url: if self.video_url:

View file

@ -5,7 +5,7 @@
{% block extra_head %} {% block extra_head %}
<noscript> <noscript>
<meta http-equiv="refresh" content="3; url={% url "noscript_schedule_index" camp_slug=camp.slug %}" /> <meta http-equiv="refresh" content="0; url={% url "noscript_schedule_index" camp_slug=camp.slug %}" />
</noscript> </noscript>
{% endblock %} {% endblock %}

View file

@ -220,10 +220,16 @@ footer {
.schedule-filter ul { .schedule-filter ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
display: flex;
flex-wrap: wrap;
}
.schedule-filter ul li {
flex: 1;
} }
.schedule-filter .btn { .schedule-filter .btn {
min-width: 200px; width: 100%;
text-align: left; text-align: left;
} }