Add code to display table.
This commit is contained in:
parent
39764dd4a5
commit
3a237d0d0e
|
@ -1,13 +1,18 @@
|
||||||
$off-grey-color: #ededed;
|
$off-grey-color: #ededed;
|
||||||
$off-color: #eef2f9;
|
$off-color: #eef2f9;
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
|
margin: 2rem;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
max-width: 1600px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.split-pane {
|
.split-pane {
|
||||||
|
@ -17,6 +22,9 @@ body {
|
||||||
|
|
||||||
.split-elem {
|
.split-elem {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-basis: 40%;
|
||||||
|
margin: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-wrapper {
|
.table-wrapper {
|
||||||
|
@ -27,6 +35,7 @@ body {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
box-shadow: 0px 0px 5px rgba(grey, 0.1);
|
box-shadow: 0px 0px 5px rgba(grey, 0.1);
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.class-table {
|
.class-table {
|
||||||
|
@ -70,16 +79,52 @@ body {
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
|
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
&.color-green {
|
.color-green {
|
||||||
background-color: lighten(#5bc275, 30%);
|
background-color: lighten(#5bc275, 30%);
|
||||||
border-color: #5bc275;
|
border-color: #5bc275;
|
||||||
color: darken(#5bc275, 30%);
|
color: darken(#5bc275, 30%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.color-red {
|
.color-red {
|
||||||
background-color: lighten(#c25b75, 30%);
|
background-color: lighten(#c25b75, 30%);
|
||||||
border-color: #c25b75;
|
border-color: #c25b75;
|
||||||
color: darken(#c25b75, 30%);
|
color: darken(#c25b75, 30%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.week-grid {
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
height: 50vh;
|
||||||
|
grid-template-columns: auto repeat(7, 1fr);
|
||||||
|
grid-template-rows: auto repeat(10, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-block {
|
||||||
|
position: absolute;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border-style: dashed;
|
||||||
|
border-width: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.column-container {
|
||||||
|
position: relative;
|
||||||
|
padding: 0.25rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-left: 0.5px solid lighten(grey, 20%);
|
||||||
|
border-right: 0.5px solid lighten(grey, 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-day-header {
|
||||||
|
padding: 0.25rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module ClassSchedule.View exposing (..)
|
module ClassSchedule.View exposing (..)
|
||||||
import ClassSchedule.Model exposing (..)
|
import ClassSchedule.Model exposing (..)
|
||||||
import Html exposing (Html, Attribute, div, text, table, td, th, tr, span, input, h1)
|
import Html exposing (Html, Attribute, div, text, table, td, th, tr, span, input, h1)
|
||||||
import Html.Attributes exposing (class, classList, type_)
|
import Html.Attributes exposing (class, classList, type_, style)
|
||||||
import Html.Events exposing (onClick)
|
import Html.Events exposing (onClick)
|
||||||
import Tuple exposing (..)
|
import Tuple exposing (..)
|
||||||
import Dict exposing (..)
|
import Dict exposing (..)
|
||||||
|
@ -35,7 +35,7 @@ viewTime : Time -> String
|
||||||
viewTime (m, h, dh) = viewTimeNumber m ++ ":" ++ viewTimeNumber h ++ viewDayHalf dh
|
viewTime (m, h, dh) = viewTimeNumber m ++ ":" ++ viewTimeNumber h ++ viewDayHalf dh
|
||||||
|
|
||||||
viewTimeRange : (Time, Time) -> String
|
viewTimeRange : (Time, Time) -> String
|
||||||
viewTimeRange (t1, t2) = viewTime t1 ++ " to " ++ viewTime t2
|
viewTimeRange (t1, t2) = viewTime t1 ++ "-" ++ viewTime t2
|
||||||
|
|
||||||
viewDayCode : DayOfWeek -> String
|
viewDayCode : DayOfWeek -> String
|
||||||
viewDayCode dw =
|
viewDayCode dw =
|
||||||
|
@ -121,10 +121,143 @@ viewClassList m = div []
|
||||||
Nothing -> text "Please select a term!"
|
Nothing -> text "Please select a term!"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
hour24 : Time -> Int
|
||||||
|
hour24 (h, _, th) = if th == AM then h else h + 12
|
||||||
|
|
||||||
|
from24 : Int -> Time
|
||||||
|
from24 i = (modBy 12 i, 0, if i >= 12 then PM else AM)
|
||||||
|
|
||||||
|
timeSortable : Time -> Int
|
||||||
|
timeSortable (h, m, th) = hour24 (h,m,th) * 60 + m
|
||||||
|
|
||||||
|
rangeSortable : (Time, Time) -> (Int, Int)
|
||||||
|
rangeSortable (t1, t2) = (timeSortable t1, -(timeSortable t2))
|
||||||
|
|
||||||
|
toHourCount : Time -> Time -> Float
|
||||||
|
toHourCount t1 t2 = toFloat (timeSortable t2 - timeSortable t1) / 60
|
||||||
|
|
||||||
|
maxTime : Time -> Time -> Time
|
||||||
|
maxTime t1 t2 = if timeSortable t1 > timeSortable t2 then t1 else t2
|
||||||
|
|
||||||
|
index : List a -> List (Int, a)
|
||||||
|
index =
|
||||||
|
let
|
||||||
|
indexWith n l =
|
||||||
|
case l of
|
||||||
|
[] -> []
|
||||||
|
(x::xs) -> (n,x) :: indexWith (n+1) xs
|
||||||
|
in indexWith 0
|
||||||
|
|
||||||
|
type alias SelectionReason = (CourseStatus, Bool)
|
||||||
|
|
||||||
|
findDay : Maybe Int -> DayOfWeek -> List (CourseStatus, Course) -> List (Course, SelectionReason, (Time, Time))
|
||||||
|
findDay ms dw l =
|
||||||
|
let
|
||||||
|
find (cs, b, c) = List.filter (\(ndw, _, _) -> ndw == dw) c.times
|
||||||
|
|> List.map (\(_, t1, t2) -> (c, (cs, b), (t1, t2)))
|
||||||
|
active (i, (cs, c)) =
|
||||||
|
if cs == Added || ms == Just i
|
||||||
|
then Just (cs, ms == Just i, c)
|
||||||
|
else Nothing
|
||||||
|
in
|
||||||
|
index l
|
||||||
|
|> List.filterMap active
|
||||||
|
|> List.concatMap find
|
||||||
|
|
||||||
|
findGroups : List (Course, SelectionReason, (Time, Time)) -> List (List (Course, SelectionReason, (Time, Time)))
|
||||||
|
findGroups cs =
|
||||||
|
let
|
||||||
|
findGroupsRec acc mt rcs =
|
||||||
|
case rcs of
|
||||||
|
[] ->
|
||||||
|
case acc of
|
||||||
|
[] -> []
|
||||||
|
_ -> [List.reverse acc]
|
||||||
|
((c, sr, (t1, t2))::trcs) ->
|
||||||
|
if timeSortable mt > timeSortable t1
|
||||||
|
then findGroupsRec ((c,sr,(t1,t2))::acc) (maxTime t2 mt) trcs
|
||||||
|
else List.reverse acc :: findGroupsRec [(c, sr, (t1, t2))] (maxTime t2 mt) trcs
|
||||||
|
in
|
||||||
|
findGroupsRec [] (0, 0, AM) <| List.sortBy (\(_, _, r) -> rangeSortable r) cs
|
||||||
|
|
||||||
|
type alias CellInfo =
|
||||||
|
{ width : Float
|
||||||
|
, height : Float
|
||||||
|
, verticalOffset : Float
|
||||||
|
, index : Int
|
||||||
|
, reason : SelectionReason
|
||||||
|
}
|
||||||
|
|
||||||
|
const : a -> b -> a
|
||||||
|
const x _ = x
|
||||||
|
|
||||||
|
mergeDicts : (a -> a -> a) -> Dict comparable a -> Dict comparable a -> Dict comparable a
|
||||||
|
mergeDicts f d1 d2 = Dict.merge Dict.insert (\k a b -> Dict.insert k (f a b)) Dict.insert d1 d2 Dict.empty
|
||||||
|
|
||||||
|
groupDims : List (Course, SelectionReason, (Time, Time)) -> Dict Int (List (Course, CellInfo))
|
||||||
|
groupDims l =
|
||||||
|
let
|
||||||
|
width = 100.0 / toFloat (List.length l)
|
||||||
|
courseInfo i (c, cr, (t1, t2)) = Dict.singleton (hour24 t1 - 8)
|
||||||
|
<| List.singleton
|
||||||
|
<| pair c
|
||||||
|
<|
|
||||||
|
{ width = width
|
||||||
|
, height = 100 * toHourCount t1 t2
|
||||||
|
, verticalOffset = let (_, m, _) = t1 in 100 * toFloat m / 60
|
||||||
|
, index = i
|
||||||
|
, reason = cr
|
||||||
|
}
|
||||||
|
in
|
||||||
|
List.foldl (mergeDicts (++)) Dict.empty <| List.indexedMap courseInfo l
|
||||||
|
|
||||||
|
days : List DayOfWeek
|
||||||
|
days = [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
|
||||||
|
|
||||||
|
buildCellDict : Maybe Int -> List (CourseStatus, Course) -> Dict Int (Dict Int (List (Course, CellInfo)))
|
||||||
|
buildCellDict ms l =
|
||||||
|
let
|
||||||
|
singleDay i dw = findDay ms dw l
|
||||||
|
|> findGroups
|
||||||
|
|> List.map groupDims
|
||||||
|
|> List.foldl (mergeDicts (++)) Dict.empty
|
||||||
|
|> Dict.singleton i
|
||||||
|
in
|
||||||
|
List.foldl Dict.union Dict.empty <| List.indexedMap singleDay days
|
||||||
|
|
||||||
|
viewCourseBlock : CellInfo -> String -> Html Msg
|
||||||
|
viewCourseBlock ci s =
|
||||||
|
let
|
||||||
|
ps f = String.fromFloat f ++ "%"
|
||||||
|
nw = if (ci.width) == 100.0 then 100.0 else (ci.width)*0.95
|
||||||
|
(ad, sel) = ci.reason
|
||||||
|
in div
|
||||||
|
[ class "course-block"
|
||||||
|
, style "width" (ps nw)
|
||||||
|
, style "height" (ps (ci.height))
|
||||||
|
, style "left" (ps (toFloat ci.index * ci.width))
|
||||||
|
, style "top" (ps (ci.verticalOffset))
|
||||||
|
, classList [("selected", sel), ("color-green", ad == Added)]
|
||||||
|
]
|
||||||
|
[ text s ]
|
||||||
|
|
||||||
|
viewTableDayHeader : DayOfWeek -> Html Msg
|
||||||
|
viewTableDayHeader dw = span [ class "table-day-header" ] [ text <| viewDayCode dw ]
|
||||||
|
|
||||||
viewClassSchedule : Model -> Html Msg
|
viewClassSchedule : Model -> Html Msg
|
||||||
viewClassSchedule m = div [ class "table-wrapper" ]
|
viewClassSchedule m =
|
||||||
[ text "Nothing here yet!"
|
let
|
||||||
]
|
header = span [] [] :: List.map viewTableDayHeader days
|
||||||
|
cellDict = buildCellDict m.selected (Maybe.withDefault [] <| Dict.get m.term m.terms)
|
||||||
|
times = List.range 0 10
|
||||||
|
time h = List.map (\w -> Maybe.withDefault [] <| Maybe.andThen (Dict.get h) <| Dict.get w cellDict) (List.range 0 6)
|
||||||
|
container xs = div [ class "column-container" ] <|
|
||||||
|
List.map (\(c, ci) -> viewCourseBlock ci (viewCrn c.crn)) xs
|
||||||
|
in
|
||||||
|
Debug.log (Debug.toString cellDict) <| div [ class "table-wrapper", style "width" "100%", style "padding" "1rem" ]
|
||||||
|
[ div [ class "week-grid" ] <|
|
||||||
|
header ++ (List.concatMap (\i -> span [ style "padding-right" "1rem" ] [ text <| viewTime <| from24 (i+8)] :: List.map container (time i)) times)
|
||||||
|
]
|
||||||
|
|
||||||
viewModel : Model -> Html Msg
|
viewModel : Model -> Html Msg
|
||||||
viewModel m = div [ class "main" ]
|
viewModel m = div [ class "main" ]
|
||||||
|
|
13
src/Main.elm
13
src/Main.elm
|
@ -8,6 +8,9 @@ import Tuple exposing (..)
|
||||||
oneHour : Time -> (Time, Time)
|
oneHour : Time -> (Time, Time)
|
||||||
oneHour t = (t, addMinutes 50 t)
|
oneHour t = (t, addMinutes 50 t)
|
||||||
|
|
||||||
|
twoHours : Time -> (Time, Time)
|
||||||
|
twoHours t = (t, addMinutes 110 t)
|
||||||
|
|
||||||
nAm : Int -> Time
|
nAm : Int -> Time
|
||||||
nAm i = (i, 0, AM)
|
nAm i = (i, 0, AM)
|
||||||
|
|
||||||
|
@ -34,6 +37,16 @@ classes =
|
||||||
, instructors = ["Eric Walkingshaw"]
|
, instructors = ["Eric Walkingshaw"]
|
||||||
, times = onDays [Monday, Wednesday] <| oneHour <| nAm 10
|
, times = onDays [Monday, Wednesday] <| oneHour <| nAm 10
|
||||||
}
|
}
|
||||||
|
, { crn = (ComputerScience, 583)
|
||||||
|
, name = "Advanced Functional Programming"
|
||||||
|
, instructors = ["Eric Walkingshaw"]
|
||||||
|
, times = onDays [Monday, Wednesday] <| oneHour <| nAm 11
|
||||||
|
}
|
||||||
|
, { crn = (ComputerScience, 583)
|
||||||
|
, name = "Advanced Functional Programming"
|
||||||
|
, instructors = ["Eric Walkingshaw"]
|
||||||
|
, times = onDays [Monday, Wednesday] <| twoHours <| nAm 10
|
||||||
|
}
|
||||||
, { crn = (ComputerScience, 582)
|
, { crn = (ComputerScience, 582)
|
||||||
, name = "Programming Languages II"
|
, name = "Programming Languages II"
|
||||||
, instructors = ["Martin Erwig"]
|
, instructors = ["Martin Erwig"]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user