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
, eventDetailSidebar event eventInstances
]
Nothing ->
div [ class "row" ]
[ h4 [] [ text "Event not found." ]
, a [ href "#" ] [ text "Click here to go the schedule overview." ]
]
eventDetailContent : Event -> Html Msg
eventDetailContent event =
div [ class "col-sm-9" ]
[ a [ onClick BackInHistory, classList [ ( "btn", True ), ( "btn-default", True ) ] ] [ a [ onClick BackInHistory, classList [ ( "btn", True ), ( "btn-default", True ) ] ]
[ i [ classList [ ( "fa", True ), ( "fa-chevron-left", True ) ] ] [] [ i [ classList [ ( "fa", True ), ( "fa-chevron-left", True ) ] ] []
, text " Back" , text " Back"
] ]
, h4 [] [ text event.title ] , h3 [] [ text event.title ]
, p [] [ Markdown.toHtml [] event.abstract ] , p [] [ Markdown.toHtml [] event.abstract ]
, hr [] []
, eventInstancesList eventSlug model.eventInstances
] ]
, div
eventDetailSidebar : Event -> List EventInstance -> Html Msg
eventDetailSidebar event eventInstances =
let
videoRecordingLink =
case event.videoUrl of
"" ->
[]
_ ->
[ a [ href event.videoUrl, classList [ ( "btn", True ), ( "btn-success", True ) ] ]
[ i [ classList [ ( "fa", True ), ( "fa-film", True ) ] ] []
, text " Watch recording here!"
]
]
in
div
[ classList [ classList
[ ( "col-sm-3", True ) [ ( "col-sm-3", True )
, ( "schedule-sidebar", True ) , ( "schedule-sidebar", True )
, ( "sticky", True ) , ( "sticky", True )
] ]
] ]
[ videoRecordingSidebar event (videoRecordingLink
, speakerSidebar event.speakers ++ [ speakerSidebar event.speakers
] , eventMetaDataSidebar event
, eventInstancesSidebar eventInstances
] ]
)
Nothing ->
div [ class "row" ] eventMetaDataSidebar : Event -> Html Msg
[ text eventMetaDataSidebar event =
(case model.dataLoaded of let
videoRecording =
case event.videoRecording of
True -> True ->
"Event not found." "Yes"
False -> False ->
"Loading..." "No"
)
]
videoRecordingSidebar : Event -> Html Msg
videoRecordingSidebar event =
let
( video, willBeRecorded ) =
if event.videoUrl /= "" then
( 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 )
in in
div [ classList [ ( "alert", True ), ( "alert-danger", not willBeRecorded ), ( "alert-info", willBeRecorded ) ] ] div []
[ video ] [ 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
instances =
List.filter (\instance -> instance.eventSlug == eventSlug) eventInstances
in
div [] div []
[ h4 [] [ h4 []
[ text "This event will occur at:" ] [ text "This event will occur at:" ]
, ul , ul
[] []
(List.map eventInstanceItem instances) (List.map eventInstanceItem eventInstances)
] ]
eventInstanceItem : EventInstance -> Html Msg eventInstanceItem : EventInstance -> Html Msg
eventInstanceItem eventInstance = eventInstanceItem eventInstance =
let
toFormat =
if Date.day eventInstance.from == Date.day eventInstance.to then
"HH:mm"
else
"E HH:mm"
in
li [] li []
[ text [ text
((Date.Extra.toFormattedString "y-MM-dd HH:mm" eventInstance.from) ((Date.Extra.toFormattedString "E HH:mm" eventInstance.from)
++ " to " ++ " to "
++ (Date.Extra.toFormattedString "y-MM-d HH:mm" eventInstance.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;
} }