Add code to display table.
This commit is contained in:
		
							parent
							
								
									39764dd4a5
								
							
						
					
					
						commit
						3a237d0d0e
					
				@ -1,13 +1,18 @@
 | 
			
		||||
$off-grey-color: #ededed;
 | 
			
		||||
$off-color: #eef2f9;
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    font-family: sans-serif;
 | 
			
		||||
    margin: 2rem;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.main {
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    max-width: 1600px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.split-pane {
 | 
			
		||||
@ -17,6 +22,9 @@ body {
 | 
			
		||||
 | 
			
		||||
.split-elem {
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
    flex-shrink: 0;
 | 
			
		||||
    flex-basis: 40%;
 | 
			
		||||
    margin: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.table-wrapper {
 | 
			
		||||
@ -27,6 +35,7 @@ body {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-top: 1rem;
 | 
			
		||||
    box-shadow: 0px 0px 5px rgba(grey, 0.1);
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.class-table {
 | 
			
		||||
@ -70,16 +79,52 @@ body {
 | 
			
		||||
    border-radius: 0.25rem;
 | 
			
		||||
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    &.color-green {
 | 
			
		||||
        background-color: lighten(#5bc275, 30%);
 | 
			
		||||
        border-color: #5bc275;
 | 
			
		||||
        color: darken(#5bc275, 30%);
 | 
			
		||||
    }
 | 
			
		||||
.color-green {
 | 
			
		||||
    background-color: lighten(#5bc275, 30%);
 | 
			
		||||
    border-color: #5bc275;
 | 
			
		||||
    color: darken(#5bc275, 30%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    &.color-red {
 | 
			
		||||
        background-color: lighten(#c25b75, 30%);
 | 
			
		||||
        border-color: #c25b75;
 | 
			
		||||
        color: darken(#c25b75, 30%);
 | 
			
		||||
.color-red {
 | 
			
		||||
    background-color: lighten(#c25b75, 30%);
 | 
			
		||||
    border-color: #c25b75;
 | 
			
		||||
    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 (..)
 | 
			
		||||
import ClassSchedule.Model exposing (..)
 | 
			
		||||
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 Tuple exposing (..)
 | 
			
		||||
import Dict exposing (..)
 | 
			
		||||
@ -35,7 +35,7 @@ viewTime : Time -> String
 | 
			
		||||
viewTime (m, h, dh) = viewTimeNumber m ++ ":" ++ viewTimeNumber h ++ viewDayHalf dh
 | 
			
		||||
 | 
			
		||||
viewTimeRange : (Time, Time) -> String
 | 
			
		||||
viewTimeRange (t1, t2) = viewTime t1 ++ " to " ++ viewTime t2
 | 
			
		||||
viewTimeRange (t1, t2) = viewTime t1 ++ "-" ++ viewTime t2
 | 
			
		||||
 | 
			
		||||
viewDayCode : DayOfWeek -> String
 | 
			
		||||
viewDayCode dw =
 | 
			
		||||
@ -121,10 +121,143 @@ viewClassList m = div []
 | 
			
		||||
        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 m = div [ class "table-wrapper" ]
 | 
			
		||||
    [ text "Nothing here yet!" 
 | 
			
		||||
    ]
 | 
			
		||||
viewClassSchedule m =
 | 
			
		||||
    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 m = div [ class "main" ]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								src/Main.elm
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/Main.elm
									
									
									
									
									
								
							@ -8,6 +8,9 @@ import Tuple exposing (..)
 | 
			
		||||
oneHour : Time -> (Time, Time)
 | 
			
		||||
oneHour t = (t, addMinutes 50 t)
 | 
			
		||||
 | 
			
		||||
twoHours : Time -> (Time, Time)
 | 
			
		||||
twoHours t = (t, addMinutes 110 t)
 | 
			
		||||
 | 
			
		||||
nAm : Int -> Time
 | 
			
		||||
nAm i = (i, 0, AM)
 | 
			
		||||
 | 
			
		||||
@ -34,6 +37,16 @@ classes =
 | 
			
		||||
      , instructors = ["Eric Walkingshaw"]
 | 
			
		||||
      , 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)
 | 
			
		||||
      , name = "Programming Languages II"
 | 
			
		||||
      , instructors = ["Martin Erwig"]
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user