Adding small indicators of the number of events instances for the different filters. Resulted in some cleanup as well.
This commit is contained in:
parent
9f8ab54a34
commit
d44ef3bbd8
|
@ -57,8 +57,8 @@ eventDecoder =
|
||||||
|> required "slug" string
|
|> required "slug" string
|
||||||
|> required "abstract" string
|
|> required "abstract" string
|
||||||
|> required "speaker_slugs" (list string)
|
|> required "speaker_slugs" (list string)
|
||||||
|> required "video_recording" bool
|
|> required "video_state" string
|
||||||
|> optional "video_url" string ""
|
|> optional "video_url" (nullable string) Nothing
|
||||||
|> required "event_type" string
|
|> required "event_type" string
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,8 +89,8 @@ eventInstanceDecoder =
|
||||||
|> required "timeslots" float
|
|> required "timeslots" float
|
||||||
|> required "location" string
|
|> required "location" string
|
||||||
|> required "location_icon" string
|
|> required "location_icon" string
|
||||||
|> required "video_recording" bool
|
|> required "video_state" string
|
||||||
|> optional "video_url" string ""
|
|> optional "video_url" (nullable string) Nothing
|
||||||
|> optional "is_favorited" (nullable bool) Nothing
|
|> optional "is_favorited" (nullable bool) Nothing
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,9 @@ type alias Filter =
|
||||||
|
|
||||||
|
|
||||||
type alias VideoRecordingFilter =
|
type alias VideoRecordingFilter =
|
||||||
{ name : String, slug : String, filter : EventInstance -> Bool }
|
{ name : String
|
||||||
|
, slug : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type alias Day =
|
type alias Day =
|
||||||
|
@ -99,8 +101,8 @@ type alias EventInstance =
|
||||||
, timeslots : Float
|
, timeslots : Float
|
||||||
, location : String
|
, location : String
|
||||||
, locationIcon : String
|
, locationIcon : String
|
||||||
, videoRecording : Bool
|
, videoState : String
|
||||||
, videoUrl : String
|
, videoUrl : Maybe String
|
||||||
, isFavorited : Maybe Bool
|
, isFavorited : Maybe Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +112,8 @@ type alias Event =
|
||||||
, slug : EventSlug
|
, slug : EventSlug
|
||||||
, abstract : String
|
, abstract : String
|
||||||
, speakerSlugs : List SpeakerSlug
|
, speakerSlugs : List SpeakerSlug
|
||||||
, videoRecording : Bool
|
, videoState : String
|
||||||
, videoUrl : String
|
, videoUrl : Maybe String
|
||||||
, eventType : String
|
, eventType : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,11 +100,11 @@ eventDetailSidebar event model =
|
||||||
let
|
let
|
||||||
videoRecordingLink =
|
videoRecordingLink =
|
||||||
case event.videoUrl of
|
case event.videoUrl of
|
||||||
"" ->
|
Nothing ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
_ ->
|
Just url ->
|
||||||
[ a [ href event.videoUrl, classList [ ( "btn", True ), ( "btn-success", True ) ] ]
|
[ a [ href url, classList [ ( "btn", True ), ( "btn-success", True ) ] ]
|
||||||
[ i [ classList [ ( "fa", True ), ( "fa-film", True ) ] ] []
|
[ i [ classList [ ( "fa", True ), ( "fa-film", True ) ] ] []
|
||||||
, text " Watch recording here!"
|
, text " Watch recording here!"
|
||||||
]
|
]
|
||||||
|
@ -134,20 +134,30 @@ eventDetailSidebar event model =
|
||||||
eventMetaDataSidebar : Event -> Html Msg
|
eventMetaDataSidebar : Event -> Html Msg
|
||||||
eventMetaDataSidebar event =
|
eventMetaDataSidebar event =
|
||||||
let
|
let
|
||||||
videoRecording =
|
( showVideoRecoring, videoRecording ) =
|
||||||
case event.videoRecording of
|
case event.videoState of
|
||||||
True ->
|
"to-be-recorded" ->
|
||||||
"Yes"
|
( True, "Yes" )
|
||||||
|
|
||||||
False ->
|
"not-to-be-recorded" ->
|
||||||
"No"
|
( True, "No" )
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
( False, "" )
|
||||||
in
|
in
|
||||||
div []
|
div []
|
||||||
[ h4 [] [ text "Metadata" ]
|
[ h4 [] [ text "Metadata" ]
|
||||||
, ul []
|
, ul []
|
||||||
[ li [] [ strong [] [ text "Type: " ], text event.eventType ]
|
([ li [] [ strong [] [ text "Type: " ], text event.eventType ]
|
||||||
, li [] [ strong [] [ text "Recording: " ], text videoRecording ]
|
|
||||||
]
|
]
|
||||||
|
++ (case showVideoRecoring of
|
||||||
|
True ->
|
||||||
|
[ li [] [ strong [] [ text "Recording: " ], text videoRecording ] ]
|
||||||
|
|
||||||
|
False ->
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ module Views.FilterView exposing (filterSidebar, applyFilters, parseFilterFromQu
|
||||||
-- Local modules
|
-- Local modules
|
||||||
|
|
||||||
import Messages exposing (Msg(..))
|
import Messages exposing (Msg(..))
|
||||||
import Models exposing (Model, EventInstance, Filter, Day, FilterQuery, Route(OverviewFilteredRoute), VideoRecordingFilter)
|
import Models exposing (Model, EventInstance, Filter, Day, FilterQuery, Route(OverviewFilteredRoute), VideoRecordingFilter, EventType, EventLocation)
|
||||||
import Routing exposing (routeToString)
|
import Routing exposing (routeToString)
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import Regex
|
||||||
|
|
||||||
-- External modules
|
-- External modules
|
||||||
|
|
||||||
import Html exposing (Html, text, div, ul, li, span, i, h4)
|
import Html exposing (Html, text, div, ul, li, span, i, h4, small)
|
||||||
import Html.Attributes exposing (class, classList)
|
import Html.Attributes exposing (class, classList)
|
||||||
import Html.Events exposing (onClick)
|
import Html.Events exposing (onClick)
|
||||||
import Date.Extra exposing (Interval(..), equalBy)
|
import Date.Extra exposing (Interval(..), equalBy)
|
||||||
|
@ -23,29 +23,22 @@ import Date.Extra exposing (Interval(..), equalBy)
|
||||||
applyFilters : Day -> Model -> List EventInstance
|
applyFilters : Day -> Model -> List EventInstance
|
||||||
applyFilters day model =
|
applyFilters day model =
|
||||||
let
|
let
|
||||||
types =
|
slugs default filters =
|
||||||
List.map (\eventType -> eventType.slug)
|
List.map .slug
|
||||||
(if List.isEmpty model.filter.eventTypes then
|
(if List.isEmpty filters then
|
||||||
model.eventTypes
|
default
|
||||||
else
|
else
|
||||||
model.filter.eventTypes
|
filters
|
||||||
)
|
)
|
||||||
|
|
||||||
|
types =
|
||||||
|
slugs model.eventTypes model.filter.eventTypes
|
||||||
|
|
||||||
locations =
|
locations =
|
||||||
List.map (\eventLocation -> eventLocation.slug)
|
slugs model.eventLocations model.filter.eventLocations
|
||||||
(if List.isEmpty model.filter.eventLocations then
|
|
||||||
model.eventLocations
|
|
||||||
else
|
|
||||||
model.filter.eventLocations
|
|
||||||
)
|
|
||||||
|
|
||||||
videoFilters =
|
videoFilters =
|
||||||
List.map (\filter -> filter.filter)
|
slugs videoRecordingFilters model.filter.videoRecording
|
||||||
(if List.isEmpty model.filter.videoRecording then
|
|
||||||
videoRecordingFilters
|
|
||||||
else
|
|
||||||
model.filter.videoRecording
|
|
||||||
)
|
|
||||||
|
|
||||||
filteredEventInstances =
|
filteredEventInstances =
|
||||||
List.filter
|
List.filter
|
||||||
|
@ -54,7 +47,7 @@ applyFilters day model =
|
||||||
&& (Date.Extra.equalBy Date.Extra.Day eventInstance.from day.date)
|
&& (Date.Extra.equalBy Date.Extra.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
|
&& List.member eventInstance.videoState videoFilters
|
||||||
)
|
)
|
||||||
model.eventInstances
|
model.eventInstances
|
||||||
in
|
in
|
||||||
|
@ -74,70 +67,84 @@ filterSidebar model =
|
||||||
]
|
]
|
||||||
[ h4 [] [ text "Filter" ]
|
[ h4 [] [ text "Filter" ]
|
||||||
, div [ class "form-group" ]
|
, div [ class "form-group" ]
|
||||||
[ filterView "Type" model.eventTypes model.filter.eventTypes ToggleEventTypeFilter
|
[ filterView
|
||||||
, filterView "Location" model.eventLocations model.filter.eventLocations ToggleEventLocationFilter
|
"Type"
|
||||||
, filterView "Video" videoRecordingFilters model.filter.videoRecording ToggleVideoRecordingFilter
|
model.eventTypes
|
||||||
|
model.filter.eventTypes
|
||||||
|
ToggleEventTypeFilter
|
||||||
|
model.eventInstances
|
||||||
|
.eventType
|
||||||
|
, filterView
|
||||||
|
"Location"
|
||||||
|
model.eventLocations
|
||||||
|
model.filter.eventLocations
|
||||||
|
ToggleEventLocationFilter
|
||||||
|
model.eventInstances
|
||||||
|
.location
|
||||||
|
, filterView
|
||||||
|
"Video"
|
||||||
|
videoRecordingFilters
|
||||||
|
model.filter.videoRecording
|
||||||
|
ToggleVideoRecordingFilter
|
||||||
|
model.eventInstances
|
||||||
|
.videoState
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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 VideoRecordingFilter
|
videoRecordingFilters : List VideoRecordingFilter
|
||||||
videoRecordingFilters =
|
videoRecordingFilters =
|
||||||
[ { name = "Will not be recorded", slug = "not-to-be-recorded", filter = notRecordedFilter }
|
[ { name = "Will not be recorded", slug = "not-to-be-recorded" }
|
||||||
, { name = "Will recorded", slug = "to-be-recorded", filter = recordedFilter }
|
, { name = "Will recorded", slug = "to-be-recorded" }
|
||||||
, { name = "Has recording", slug = "has-recording", filter = hasRecordingFilter }
|
, { name = "Has recording", slug = "has-recording" }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
applyVideoRecordingFilters : List (EventInstance -> Bool) -> EventInstance -> Bool
|
|
||||||
applyVideoRecordingFilters filters eventInstance =
|
|
||||||
let
|
|
||||||
results =
|
|
||||||
List.map (\filter -> filter eventInstance) filters
|
|
||||||
in
|
|
||||||
List.member True results
|
|
||||||
|
|
||||||
|
|
||||||
filterView :
|
filterView :
|
||||||
String
|
String
|
||||||
-> List { a | name : String }
|
-> List { a | name : String, slug : String }
|
||||||
-> List { a | name : String }
|
-> List { a | name : String, slug : String }
|
||||||
-> ({ a | name : String } -> Msg)
|
-> ({ a | name : String, slug : String } -> Msg)
|
||||||
|
-> List EventInstance
|
||||||
|
-> (EventInstance -> String)
|
||||||
-> Html Msg
|
-> Html Msg
|
||||||
filterView name possibleFilters currentFilters action =
|
filterView name possibleFilters currentFilters action eventInstances slugLike =
|
||||||
div []
|
div []
|
||||||
[ text (name ++ ":")
|
[ text (name ++ ":")
|
||||||
, ul [] (List.map (\filter -> filterChoiceView filter currentFilters action) possibleFilters)
|
, ul []
|
||||||
|
(possibleFilters
|
||||||
|
|> List.map
|
||||||
|
(\filter ->
|
||||||
|
filterChoiceView
|
||||||
|
filter
|
||||||
|
currentFilters
|
||||||
|
action
|
||||||
|
eventInstances
|
||||||
|
slugLike
|
||||||
|
)
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
filterChoiceView :
|
filterChoiceView :
|
||||||
{ a | name : String }
|
{ a | name : String, slug : String }
|
||||||
-> List { a | name : String }
|
-> List { a | name : String, slug : String }
|
||||||
-> ({ a | name : String } -> Msg)
|
-> ({ a | name : String, slug : String } -> Msg)
|
||||||
|
-> List EventInstance
|
||||||
|
-> (EventInstance -> String)
|
||||||
-> Html Msg
|
-> Html Msg
|
||||||
filterChoiceView filter currentFilters action =
|
filterChoiceView filter currentFilters action eventInstances slugLike =
|
||||||
let
|
let
|
||||||
active =
|
active =
|
||||||
List.member filter currentFilters
|
List.member filter currentFilters
|
||||||
|
|
||||||
notActive =
|
notActive =
|
||||||
not active
|
not active
|
||||||
|
|
||||||
|
eventInstanceCount =
|
||||||
|
eventInstances
|
||||||
|
|> List.filter (\eventInstance -> slugLike eventInstance == filter.slug)
|
||||||
|
|> List.length
|
||||||
in
|
in
|
||||||
li []
|
li []
|
||||||
[ div
|
[ div
|
||||||
|
@ -151,6 +158,7 @@ filterChoiceView filter currentFilters action =
|
||||||
[ span []
|
[ span []
|
||||||
[ i [ classList [ ( "fa", True ), ( "fa-minus", active ), ( "fa-plus", notActive ) ] ] []
|
[ i [ classList [ ( "fa", True ), ( "fa-minus", active ), ( "fa-plus", notActive ) ] ] []
|
||||||
, text (" " ++ filter.name)
|
, text (" " ++ filter.name)
|
||||||
|
, small [] [ text <| " (" ++ (toString eventInstanceCount) ++ ")" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
|
@ -77,11 +77,20 @@ dayEventInstanceIcons : EventInstance -> List (Html Msg)
|
||||||
dayEventInstanceIcons eventInstance =
|
dayEventInstanceIcons eventInstance =
|
||||||
let
|
let
|
||||||
videoIcon =
|
videoIcon =
|
||||||
if eventInstance.videoUrl /= "" then
|
case eventInstance.videoState of
|
||||||
[ i [ classList [ ( "fa", True ), ( "fa-film", True ), ( "pull-right", True ) ] ] [] ]
|
"has-recording" ->
|
||||||
else if eventInstance.videoRecording then
|
[ i
|
||||||
[ i [ classList [ ( "fa", True ), ( "fa-video-camera", True ), ( "pull-right", True ) ] ] [] ]
|
[ classList [ ( "fa", True ), ( "fa-film", True ), ( "pull-right", True ) ] ]
|
||||||
else
|
[]
|
||||||
|
]
|
||||||
|
|
||||||
|
"to-be-recorded" ->
|
||||||
|
[ i
|
||||||
|
[ classList [ ( "fa", True ), ( "fa-video-camera", True ), ( "pull-right", True ) ] ]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
|
||||||
|
_ ->
|
||||||
[]
|
[]
|
||||||
in
|
in
|
||||||
[ i [ classList [ ( "fa", True ), ( "fa-" ++ eventInstance.locationIcon, True ), ( "pull-right", True ) ] ] []
|
[ i [ classList [ ( "fa", True ), ( "fa-" ++ eventInstance.locationIcon, True ), ( "pull-right", True ) ] ] []
|
||||||
|
|
|
@ -439,12 +439,18 @@ class Event(CampRelatedModel):
|
||||||
speaker.slug
|
speaker.slug
|
||||||
for speaker in self.speakers.all()
|
for speaker in self.speakers.all()
|
||||||
],
|
],
|
||||||
'video_recording': self.video_recording,
|
|
||||||
'event_type': self.event_type.name,
|
'event_type': self.event_type.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.video_url:
|
if self.video_url:
|
||||||
|
video_state = 'has-recording'
|
||||||
data['video_url'] = self.video_url
|
data['video_url'] = self.video_url
|
||||||
|
elif self.video_recording:
|
||||||
|
video_state = 'to-be-recorded'
|
||||||
|
elif not self.video_recording:
|
||||||
|
video_state = 'not-to-be-recorded'
|
||||||
|
|
||||||
|
data['video_state'] = video_state
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -525,11 +531,17 @@ class EventInstance(CampRelatedModel):
|
||||||
'location': self.location.slug,
|
'location': self.location.slug,
|
||||||
'location_icon': self.location.icon,
|
'location_icon': self.location.icon,
|
||||||
'timeslots': self.timeslots,
|
'timeslots': self.timeslots,
|
||||||
'video_recording': self.event.video_recording,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.event.video_url:
|
if self.event.video_url:
|
||||||
|
video_state = 'has-recording'
|
||||||
data['video_url'] = self.event.video_url
|
data['video_url'] = self.event.video_url
|
||||||
|
elif self.event.video_recording:
|
||||||
|
video_state = 'to-be-recorded'
|
||||||
|
elif not self.event.video_recording:
|
||||||
|
video_state = 'not-to-be-recorded'
|
||||||
|
|
||||||
|
data['video_state'] = video_state
|
||||||
|
|
||||||
if user and user.is_authenticated:
|
if user and user.is_authenticated:
|
||||||
is_favorited = user.favorites.filter(event_instance=self).exists()
|
is_favorited = user.favorites.filter(event_instance=self).exists()
|
||||||
|
|
Loading…
Reference in a new issue