Filtering by video recording is now possible. Also show video recording states.
This commit is contained in:
parent
4279653fcb
commit
a938f2406f
|
@ -52,6 +52,8 @@ eventDecoder =
|
||||||
|> required "slug" string
|
|> required "slug" string
|
||||||
|> required "abstract" string
|
|> required "abstract" string
|
||||||
|> required "speakers" (list speakerDecoder)
|
|> required "speakers" (list speakerDecoder)
|
||||||
|
|> required "video_recording" bool
|
||||||
|
|> optional "video_url" string ""
|
||||||
|
|
||||||
|
|
||||||
dateDecoder : Decoder Date
|
dateDecoder : Decoder Date
|
||||||
|
|
|
@ -35,7 +35,7 @@ init flags location =
|
||||||
parseLocation location
|
parseLocation location
|
||||||
|
|
||||||
emptyFilter =
|
emptyFilter =
|
||||||
Filter [] []
|
Filter [] [] []
|
||||||
|
|
||||||
initModel =
|
initModel =
|
||||||
(Model [] [] [] [] [] flags Nothing emptyFilter currentRoute)
|
(Model [] [] [] [] [] flags Nothing emptyFilter currentRoute)
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Messages exposing (Msg(..))
|
||||||
|
|
||||||
-- Local modules
|
-- Local modules
|
||||||
|
|
||||||
import Models exposing (Day, EventType, EventLocation)
|
import Models exposing (Day, EventType, EventLocation, EventInstance)
|
||||||
|
|
||||||
|
|
||||||
-- External modules
|
-- External modules
|
||||||
|
@ -17,4 +17,5 @@ type Msg
|
||||||
| RemoveActiveDay
|
| RemoveActiveDay
|
||||||
| ToggleEventTypeFilter EventType
|
| ToggleEventTypeFilter EventType
|
||||||
| ToggleEventLocationFilter EventLocation
|
| ToggleEventLocationFilter EventLocation
|
||||||
|
| ToggleVideoRecordingFilter { name : String, filter : EventInstance -> Bool }
|
||||||
| OnLocationChange Location
|
| OnLocationChange Location
|
||||||
|
|
|
@ -26,6 +26,7 @@ type alias Model =
|
||||||
type alias Filter =
|
type alias Filter =
|
||||||
{ eventTypes : List EventType
|
{ eventTypes : List EventType
|
||||||
, eventLocations : List EventLocation
|
, eventLocations : List EventLocation
|
||||||
|
, videoRecording : List { name : String, filter : EventInstance -> Bool }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ type alias Event =
|
||||||
, slug : EventSlug
|
, slug : EventSlug
|
||||||
, abstract : String
|
, abstract : String
|
||||||
, speakers : List Speaker
|
, speakers : List Speaker
|
||||||
|
, videoRecording : Bool
|
||||||
|
, videoUrl : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ update msg model =
|
||||||
"init" ->
|
"init" ->
|
||||||
case Json.Decode.decodeString initDataDecoder str of
|
case Json.Decode.decodeString initDataDecoder str of
|
||||||
Ok m ->
|
Ok m ->
|
||||||
m model.flags Nothing (Filter [] []) model.route
|
m model.flags Nothing (Filter [] [] []) model.route
|
||||||
|
|
||||||
Err error ->
|
Err error ->
|
||||||
model
|
model
|
||||||
|
@ -79,6 +79,22 @@ update msg model =
|
||||||
in
|
in
|
||||||
{ model | filter = newFilter } ! []
|
{ model | filter = newFilter } ! []
|
||||||
|
|
||||||
|
ToggleVideoRecordingFilter videoRecording ->
|
||||||
|
let
|
||||||
|
videoRecordingFilter =
|
||||||
|
if List.member videoRecording model.filter.videoRecording then
|
||||||
|
List.filter (\x -> x /= videoRecording) model.filter.videoRecording
|
||||||
|
else
|
||||||
|
videoRecording :: model.filter.videoRecording
|
||||||
|
|
||||||
|
currentFilter =
|
||||||
|
model.filter
|
||||||
|
|
||||||
|
newFilter =
|
||||||
|
{ currentFilter | videoRecording = videoRecordingFilter }
|
||||||
|
in
|
||||||
|
{ model | filter = newFilter } ! []
|
||||||
|
|
||||||
OnLocationChange location ->
|
OnLocationChange location ->
|
||||||
let
|
let
|
||||||
newRoute =
|
newRoute =
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Models exposing (..)
|
||||||
import Html exposing (Html, text, div, ul, li, span, i, h4, a, p, hr)
|
import Html exposing (Html, text, div, ul, li, span, i, h4, a, p, hr)
|
||||||
import Html.Attributes exposing (class, classList, href)
|
import Html.Attributes exposing (class, classList, href)
|
||||||
import Markdown
|
import Markdown
|
||||||
import Date.Extra as Date
|
import Date.Extra as DateExtra
|
||||||
|
|
||||||
|
|
||||||
eventDetailView : EventSlug -> Model -> Html Msg
|
eventDetailView : EventSlug -> Model -> Html Msg
|
||||||
|
@ -23,7 +23,7 @@ eventDetailView eventSlug model =
|
||||||
event
|
event
|
||||||
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
{ title = "", slug = "", abstract = "", speakers = [] }
|
{ title = "", slug = "", abstract = "", speakers = [], videoRecording = False, videoUrl = "" }
|
||||||
in
|
in
|
||||||
div [ class "row" ]
|
div [ class "row" ]
|
||||||
[ div [ class "col-sm-9" ]
|
[ div [ class "col-sm-9" ]
|
||||||
|
@ -41,15 +41,38 @@ eventDetailView eventSlug model =
|
||||||
, ( "schedule-sidebar", True )
|
, ( "schedule-sidebar", True )
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[ h4 []
|
[ videoRecordingSidebar event
|
||||||
[ text "Speakers" ]
|
, speakerSidebar event.speakers
|
||||||
, ul
|
|
||||||
[]
|
|
||||||
(List.map speakerDetail event.speakers)
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
div [ classList [ ( "alert", True ), ( "alert-danger", not willBeRecorded ), ( "alert-info", willBeRecorded ) ] ]
|
||||||
|
[ video ]
|
||||||
|
|
||||||
|
|
||||||
|
speakerSidebar : List Speaker -> Html Msg
|
||||||
|
speakerSidebar speakers =
|
||||||
|
div []
|
||||||
|
[ h4 []
|
||||||
|
[ text "Speakers" ]
|
||||||
|
, ul
|
||||||
|
[]
|
||||||
|
(List.map speakerDetail speakers)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
speakerDetail : Speaker -> Html Msg
|
speakerDetail : Speaker -> Html Msg
|
||||||
speakerDetail speaker =
|
speakerDetail speaker =
|
||||||
li []
|
li []
|
||||||
|
@ -76,8 +99,8 @@ eventInstanceItem : EventInstance -> Html Msg
|
||||||
eventInstanceItem eventInstance =
|
eventInstanceItem eventInstance =
|
||||||
li []
|
li []
|
||||||
[ text
|
[ text
|
||||||
((Date.toFormattedString "y-MM-dd HH:mm" eventInstance.from)
|
((DateExtra.toFormattedString "y-MM-dd HH:mm" eventInstance.from)
|
||||||
++ " to "
|
++ " to "
|
||||||
++ (Date.toFormattedString "y-MM-d HH:mm" eventInstance.to)
|
++ (DateExtra.toFormattedString "y-MM-d HH:mm" eventInstance.to)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
module Views.FilterView exposing (filterSidebar)
|
module Views.FilterView exposing (filterSidebar, videoRecordingFilters, applyVideoRecordingFilters)
|
||||||
|
|
||||||
-- Local modules
|
-- Local modules
|
||||||
|
|
||||||
import Messages exposing (Msg(..))
|
import Messages exposing (Msg(..))
|
||||||
import Models exposing (Model)
|
import Models exposing (Model, EventInstance)
|
||||||
|
|
||||||
|
|
||||||
-- External modules
|
-- External modules
|
||||||
|
@ -27,10 +27,43 @@ filterSidebar model =
|
||||||
, div [ class "form-group" ]
|
, div [ class "form-group" ]
|
||||||
[ filterView "Type" model.eventTypes model.filter.eventTypes ToggleEventTypeFilter
|
[ filterView "Type" model.eventTypes model.filter.eventTypes ToggleEventTypeFilter
|
||||||
, filterView "Location" model.eventLocations model.filter.eventLocations ToggleEventLocationFilter
|
, filterView "Location" model.eventLocations model.filter.eventLocations ToggleEventLocationFilter
|
||||||
|
, filterView "Video" videoRecordingFilters model.filter.videoRecording ToggleVideoRecordingFilter
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
notRecordedFilter : EventInstance -> Bool
|
||||||
|
notRecordedFilter eventInstance =
|
||||||
|
eventInstance.videoRecording == False
|
||||||
|
|
||||||
|
|
||||||
|
recordedFilter : EventInstance -> Bool
|
||||||
|
recordedFilter eventInstance =
|
||||||
|
eventInstance.videoRecording == True
|
||||||
|
|
||||||
|
|
||||||
|
hasRecordingFilter : EventInstance -> Bool
|
||||||
|
hasRecordingFilter eventInstance =
|
||||||
|
eventInstance.videoUrl /= ""
|
||||||
|
|
||||||
|
|
||||||
|
videoRecordingFilters : List { name : String, filter : EventInstance -> Bool }
|
||||||
|
videoRecordingFilters =
|
||||||
|
[ { name = "Will not be recorded", filter = notRecordedFilter }
|
||||||
|
, { name = "Will recorded", filter = recordedFilter }
|
||||||
|
, { name = "Has recording", filter = hasRecordingFilter }
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
applyVideoRecordingFilters : List (EventInstance -> Bool) -> EventInstance -> Bool
|
||||||
|
applyVideoRecordingFilters filters eventInstance =
|
||||||
|
let
|
||||||
|
results =
|
||||||
|
List.map (\filter -> filter eventInstance) filters
|
||||||
|
in
|
||||||
|
List.member True (Debug.log "results" results)
|
||||||
|
|
||||||
|
|
||||||
filterView :
|
filterView :
|
||||||
String
|
String
|
||||||
-> List { a | name : String }
|
-> List { a | name : String }
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Views.ScheduleOverview exposing (scheduleOverviewView)
|
||||||
|
|
||||||
import Messages exposing (Msg(..))
|
import Messages exposing (Msg(..))
|
||||||
import Models exposing (Model, Day, EventInstance)
|
import Models exposing (Model, Day, EventInstance)
|
||||||
import Views.FilterView exposing (filterSidebar)
|
import Views.FilterView exposing (filterSidebar, videoRecordingFilters, applyVideoRecordingFilters)
|
||||||
|
|
||||||
|
|
||||||
-- External modules
|
-- External modules
|
||||||
|
@ -48,6 +48,14 @@ dayRowView day model =
|
||||||
model.filter.eventLocations
|
model.filter.eventLocations
|
||||||
)
|
)
|
||||||
|
|
||||||
|
videoFilters =
|
||||||
|
List.map (\filter -> filter.filter)
|
||||||
|
(if List.isEmpty model.filter.videoRecording then
|
||||||
|
videoRecordingFilters
|
||||||
|
else
|
||||||
|
model.filter.videoRecording
|
||||||
|
)
|
||||||
|
|
||||||
filteredEventInstances =
|
filteredEventInstances =
|
||||||
List.filter
|
List.filter
|
||||||
(\eventInstance ->
|
(\eventInstance ->
|
||||||
|
@ -55,6 +63,7 @@ dayRowView day model =
|
||||||
&& (Date.equalBy Date.Day eventInstance.from day.date)
|
&& (Date.equalBy Date.Day eventInstance.from day.date)
|
||||||
&& List.member eventInstance.location locations
|
&& List.member eventInstance.location locations
|
||||||
&& List.member eventInstance.eventType types
|
&& List.member eventInstance.eventType types
|
||||||
|
&& applyVideoRecordingFilters videoFilters eventInstance
|
||||||
)
|
)
|
||||||
model.eventInstances
|
model.eventInstances
|
||||||
in
|
in
|
||||||
|
@ -76,15 +85,33 @@ dayEventInstanceView eventInstance =
|
||||||
, ( "color", eventInstance.forgroundColor )
|
, ( "color", eventInstance.forgroundColor )
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[ small []
|
([ small []
|
||||||
[ text
|
[ text
|
||||||
((Date.toFormattedString "H:m" eventInstance.from)
|
((Date.toFormattedString "H:m" eventInstance.from)
|
||||||
++ " - "
|
++ " - "
|
||||||
++ (Date.toFormattedString "H:m" eventInstance.to)
|
++ (Date.toFormattedString "H:m" eventInstance.to)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
, i [ classList [ ( "fa", True ), ( "fa-" ++ eventInstance.locationIcon, True ), ( "pull-right", True ) ] ] []
|
]
|
||||||
, p
|
++ (dayEventInstanceIcons eventInstance)
|
||||||
[]
|
++ [ p
|
||||||
[ text eventInstance.title ]
|
[]
|
||||||
|
[ text eventInstance.title ]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dayEventInstanceIcons : EventInstance -> List (Html Msg)
|
||||||
|
dayEventInstanceIcons eventInstance =
|
||||||
|
let
|
||||||
|
videoIcon =
|
||||||
|
if eventInstance.videoUrl /= "" then
|
||||||
|
[ i [ classList [ ( "fa", True ), ( "fa-film", True ), ( "pull-right", True ) ] ] [] ]
|
||||||
|
else if eventInstance.videoRecording then
|
||||||
|
[ i [ classList [ ( "fa", True ), ( "fa-video-camera", True ), ( "pull-right", True ) ] ] [] ]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
in
|
||||||
|
[ i [ classList [ ( "fa", True ), ( "fa-" ++ eventInstance.locationIcon, True ), ( "pull-right", True ) ] ] []
|
||||||
]
|
]
|
||||||
|
++ videoIcon
|
||||||
|
|
|
@ -437,7 +437,12 @@ class Event(CampRelatedModel):
|
||||||
speaker.serialize()
|
speaker.serialize()
|
||||||
for speaker in self.speakers.all()
|
for speaker in self.speakers.all()
|
||||||
],
|
],
|
||||||
|
'video_recording': self.video_recording,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.video_url:
|
||||||
|
data['video_url'] = self.video_url
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue