Add redesign for Homework 4c.
This commit is contained in:
parent
7b7b543416
commit
125d6391ba
5
elm.json
5
elm.json
|
@ -9,10 +9,13 @@
|
||||||
"elm/browser": "1.0.2",
|
"elm/browser": "1.0.2",
|
||||||
"elm/core": "1.0.5",
|
"elm/core": "1.0.5",
|
||||||
"elm/html": "1.0.0",
|
"elm/html": "1.0.0",
|
||||||
|
"elm/http": "2.0.0",
|
||||||
|
"elm/json": "1.1.3",
|
||||||
"feathericons/elm-feather": "1.5.0"
|
"feathericons/elm-feather": "1.5.0"
|
||||||
},
|
},
|
||||||
"indirect": {
|
"indirect": {
|
||||||
"elm/json": "1.1.3",
|
"elm/bytes": "1.0.8",
|
||||||
|
"elm/file": "1.0.5",
|
||||||
"elm/svg": "1.0.1",
|
"elm/svg": "1.0.1",
|
||||||
"elm/time": "1.0.0",
|
"elm/time": "1.0.0",
|
||||||
"elm/url": "1.0.0",
|
"elm/url": "1.0.0",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Lora&family=Roboto+Mono&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Lora&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" media="screen" href="css/style.css">
|
<link rel="stylesheet" media="screen" href="css/style.css">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="#elm">
|
<div id="#elm">
|
||||||
|
|
116
scss/style.scss
116
scss/style.scss
|
@ -22,7 +22,7 @@ body {
|
||||||
|
|
||||||
.split-elem {
|
.split-elem {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
flex-shrink: 0;
|
flex-shrink: 1;
|
||||||
flex-basis: 40%;
|
flex-basis: 40%;
|
||||||
margin: 0.25rem;
|
margin: 0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -36,15 +36,20 @@ body {
|
||||||
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;
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.class-table {
|
.class-table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
table-layout: fixed;
|
||||||
|
|
||||||
th, td {
|
th, td {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
|
@ -54,17 +59,9 @@ body {
|
||||||
tr {
|
tr {
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
&:nth-child(2n+3) {
|
|
||||||
background-color: $off-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hoverable:hover {
|
&.hoverable:hover {
|
||||||
background-color: lighten(yellow, 30%);
|
background-color: lighten(yellow, 30%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border: 1px dashed black;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,24 +84,17 @@ body {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.week-grid {
|
.week-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 70vh;
|
height: 70vh;
|
||||||
grid-template-columns: auto repeat(5, 1fr);
|
grid-template-columns: auto repeat(5, 1fr);
|
||||||
grid-template-rows: auto repeat(10, 1fr);
|
grid-template-rows: auto repeat(12, 1fr);
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
border-style: dashed;
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-block {
|
.course-block {
|
||||||
|
@ -114,11 +104,6 @@ body {
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border-style: dashed;
|
|
||||||
border-width: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-top: 0.1rem;
|
margin-top: 0.1rem;
|
||||||
margin-bottom: 0.1rem;
|
margin-bottom: 0.1rem;
|
||||||
|
@ -146,3 +131,80 @@ body {
|
||||||
.time-column {
|
.time-column {
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bubble {
|
||||||
|
padding: 0.2rem;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
border: 0.1rem solid;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
background-color: lighten(#86b2ff, 10%);
|
||||||
|
border-color: #86b2ff;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course {
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border-style: dashed;
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2n) {
|
||||||
|
background-color: $off-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: 1px dashed black;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-content {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-add-remove {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 40vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.course-info {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feather {
|
||||||
|
height: 1.3rem;
|
||||||
|
stroke-width: 0.15rem;
|
||||||
|
margin-right: 0.1rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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%);
|
||||||
|
}
|
||||||
|
|
47
src/ClassSchedule/Decode.elm
Normal file
47
src/ClassSchedule/Decode.elm
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
module ClassSchedule.Decode exposing (..)
|
||||||
|
import ClassSchedule.Model exposing (..)
|
||||||
|
import Json.Decode exposing (..)
|
||||||
|
|
||||||
|
dayOfWeek : Decoder DayOfWeek
|
||||||
|
dayOfWeek =
|
||||||
|
let
|
||||||
|
runDayOfWeek s =
|
||||||
|
case s of
|
||||||
|
"M" -> succeed Monday
|
||||||
|
"T" -> succeed Tuesday
|
||||||
|
"W" -> succeed Wednesday
|
||||||
|
"R" -> succeed Thursday
|
||||||
|
"F" -> succeed Friday
|
||||||
|
_ -> fail "Not a valid day of the week!"
|
||||||
|
in
|
||||||
|
string |> andThen runDayOfWeek
|
||||||
|
|
||||||
|
duration : Decoder (Time, Time)
|
||||||
|
duration =
|
||||||
|
let mkRange i j = (from24 i, addMinutes (round (j*60)) (from24 i))
|
||||||
|
in field "hour" int |> andThen (\i -> field "duration" float |> map (mkRange i))
|
||||||
|
|
||||||
|
time : Decoder (DayOfWeek, Time, Time)
|
||||||
|
time = map2 (\x (y, z) -> (x, y, z))
|
||||||
|
(field "day" dayOfWeek)
|
||||||
|
duration
|
||||||
|
|
||||||
|
crn : Decoder Crn
|
||||||
|
crn = string
|
||||||
|
|> andThen (\s ->
|
||||||
|
case String.split " " s of
|
||||||
|
[c, is] ->
|
||||||
|
case String.toInt is of
|
||||||
|
Just i -> succeed (c, i)
|
||||||
|
Nothing -> fail "Invalid course number!"
|
||||||
|
_ -> fail "Invalid course code!")
|
||||||
|
|
||||||
|
course : Decoder Course
|
||||||
|
course = map4 Course
|
||||||
|
(field "code" crn)
|
||||||
|
(field "title" string)
|
||||||
|
(field "instructor" (map List.singleton string))
|
||||||
|
(field "times" (list time))
|
||||||
|
|
||||||
|
response : Decoder (List Course)
|
||||||
|
response = field "courses" (list course)
|
|
@ -1,13 +1,8 @@
|
||||||
module ClassSchedule.Model exposing (..)
|
module ClassSchedule.Model exposing (..)
|
||||||
import Dict exposing (..)
|
import Dict exposing (..)
|
||||||
|
import Http exposing (Error)
|
||||||
|
|
||||||
type Department
|
type alias Crn = (String, Int)
|
||||||
= ComputerScience
|
|
||||||
| Mathematics
|
|
||||||
| Art
|
|
||||||
| Biology
|
|
||||||
|
|
||||||
type alias Crn = (Department, Int)
|
|
||||||
|
|
||||||
type DayOfWeek
|
type DayOfWeek
|
||||||
= Monday
|
= Monday
|
||||||
|
@ -28,6 +23,12 @@ flipDayHalf dh =
|
||||||
AM -> PM
|
AM -> PM
|
||||||
PM -> AM
|
PM -> AM
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
addHours : Int -> Time -> Time
|
addHours : Int -> Time -> Time
|
||||||
addHours hh (h, m, dh) =
|
addHours hh (h, m, dh) =
|
||||||
if h + hh >= 12
|
if h + hh >= 12
|
||||||
|
@ -59,6 +60,7 @@ type Msg
|
||||||
| SelectCourse Int
|
| SelectCourse Int
|
||||||
| AddCourse Int
|
| AddCourse Int
|
||||||
| RemoveCourse Int
|
| RemoveCourse Int
|
||||||
|
| ReceiveData (Result Error (List Course))
|
||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ terms : Dict String (List (CourseStatus, Course))
|
{ terms : Dict String (List (CourseStatus, Course))
|
||||||
|
|
|
@ -11,16 +11,8 @@ iconButton : String -> FeatherIcons.Icon -> String -> List (Attribute Msg) -> Ht
|
||||||
iconButton c i s attrs = span ([ class "button", class ("color-" ++ c) ] ++ attrs)
|
iconButton c i s attrs = span ([ class "button", class ("color-" ++ c) ] ++ attrs)
|
||||||
[ FeatherIcons.toHtml [] i, text s ]
|
[ FeatherIcons.toHtml [] i, text s ]
|
||||||
|
|
||||||
viewDept : Department -> String
|
|
||||||
viewDept d =
|
|
||||||
case d of
|
|
||||||
ComputerScience -> "CS"
|
|
||||||
Mathematics -> "MTH"
|
|
||||||
Art -> "ART"
|
|
||||||
Biology -> "BIO"
|
|
||||||
|
|
||||||
viewCrn : Crn -> String
|
viewCrn : Crn -> String
|
||||||
viewCrn (d, i) = viewDept d ++ " " ++ (String.pad 3 '0' <| String.fromInt i)
|
viewCrn (d, i) = d ++ " " ++ (String.pad 3 '0' <| String.fromInt i)
|
||||||
|
|
||||||
viewTimeNumber : Int -> String
|
viewTimeNumber : Int -> String
|
||||||
viewTimeNumber i = String.pad 2 '0' <| String.fromInt i
|
viewTimeNumber i = String.pad 2 '0' <| String.fromInt i
|
||||||
|
@ -72,41 +64,89 @@ extractTimeCodes c =
|
||||||
in dayCodes ++ " " ++ viewTimeRange tr
|
in dayCodes ++ " " ++ viewTimeRange tr
|
||||||
in List.map fromTime <| extractTimes c
|
in List.map fromTime <| extractTimes c
|
||||||
|
|
||||||
|
-- viewClass : Maybe Int -> Int -> (CourseStatus, Course) -> Html Msg
|
||||||
|
-- viewClass sel i (cs, c) =
|
||||||
|
-- let
|
||||||
|
-- isSelected = sel == Just i
|
||||||
|
-- addedIndicator =
|
||||||
|
-- case cs of
|
||||||
|
-- Added -> [ FeatherIcons.check |> FeatherIcons.toHtml [] ]
|
||||||
|
-- NotAdded -> []
|
||||||
|
-- in
|
||||||
|
-- tr [ class "hoverable", onClick (SelectCourse i), classList [("selected", isSelected)] ]
|
||||||
|
-- [ td [] addedIndicator
|
||||||
|
-- , td [] [ text <| viewCrn (c.crn) ]
|
||||||
|
-- , td [] [ text <| c.name ]
|
||||||
|
-- , td [] [ text <| String.join ", " <| c.instructors ]
|
||||||
|
-- , td [] [ text <| String.join ", " <| extractTimeCodes c ]
|
||||||
|
-- , td [] <|
|
||||||
|
-- case (isSelected, cs) of
|
||||||
|
-- (True, NotAdded) -> [ iconButton "green" (FeatherIcons.check) "Add" [ onClick (AddCourse i)] ]
|
||||||
|
-- (True, Added) -> [ iconButton "red" (FeatherIcons.x) "Remove" [onClick (RemoveCourse i)] ]
|
||||||
|
-- _ -> []
|
||||||
|
-- ]
|
||||||
|
|
||||||
|
crnIcon : Html Msg
|
||||||
|
crnIcon = FeatherIcons.code |> FeatherIcons.toHtml []
|
||||||
|
|
||||||
|
instructorIcon : Html Msg
|
||||||
|
instructorIcon = FeatherIcons.user |> FeatherIcons.toHtml []
|
||||||
|
|
||||||
|
instructorsIcon : Html Msg
|
||||||
|
instructorsIcon = FeatherIcons.users |> FeatherIcons.toHtml []
|
||||||
|
|
||||||
|
timeIcon : Html Msg
|
||||||
|
timeIcon = FeatherIcons.clock |> FeatherIcons.toHtml []
|
||||||
|
|
||||||
|
checkIcon : Html Msg
|
||||||
|
checkIcon = FeatherIcons.check |> FeatherIcons.toHtml []
|
||||||
|
|
||||||
|
viewCrnBubble : Crn -> Html Msg
|
||||||
|
viewCrnBubble crn = span [ class "bubble" ] [ crnIcon, text <| viewCrn crn ]
|
||||||
|
|
||||||
|
viewTimeBubble : Course -> Html Msg
|
||||||
|
viewTimeBubble c = span [ class "bubble" ] [ timeIcon, text <| String.join ", " <| extractTimeCodes c ]
|
||||||
|
|
||||||
|
viewAddedBubble : Bool -> List (Html Msg)
|
||||||
|
viewAddedBubble b = if b then [ span [ class "bubble", class "color-green" ] [ checkIcon, text "Added!" ] ] else []
|
||||||
|
|
||||||
|
viewInstructorBubble : List String -> Html Msg
|
||||||
|
viewInstructorBubble is = span [ class "bubble" ] <|
|
||||||
|
case is of
|
||||||
|
[] -> [ instructorIcon, text <| "(no instructor assigned)" ]
|
||||||
|
[i] -> [ instructorIcon, text <| i ]
|
||||||
|
_ -> [ instructorsIcon, text <| String.join ", " is ]
|
||||||
|
|
||||||
viewClass : Maybe Int -> Int -> (CourseStatus, Course) -> Html Msg
|
viewClass : Maybe Int -> Int -> (CourseStatus, Course) -> Html Msg
|
||||||
viewClass sel i (cs, c) =
|
viewClass sel i (cs, c) =
|
||||||
let
|
let
|
||||||
isSelected = sel == Just i
|
isSelected = sel == Just i
|
||||||
addedIndicator =
|
isAdded = cs == Added
|
||||||
case cs of
|
|
||||||
Added -> [ FeatherIcons.check |> FeatherIcons.toHtml [] ]
|
|
||||||
NotAdded -> []
|
|
||||||
in
|
in
|
||||||
tr [ class "hoverable", onClick (SelectCourse i), classList [("selected", isSelected)] ]
|
div [ class "course", onClick (SelectCourse i), classList [("selected", isSelected )] ]
|
||||||
[ td [] addedIndicator
|
[ div [ class "course-content" ]
|
||||||
, td [] [ text <| viewCrn (c.crn) ]
|
[ p [ class "course-title" ] <|
|
||||||
, td [] [ text <| c.name ]
|
[ text <| c.name ]
|
||||||
, td [] [ text <| String.join ", " <| c.instructors ]
|
, p [ class "course-info" ] <|
|
||||||
, td [] [ text <| String.join ", " <| extractTimeCodes c ]
|
viewAddedBubble isAdded ++
|
||||||
, td [] <|
|
[ viewCrnBubble c.crn
|
||||||
case (isSelected, cs) of
|
, viewInstructorBubble c.instructors
|
||||||
(True, NotAdded) -> [ iconButton "green" (FeatherIcons.check) "Add" [ onClick (AddCourse i)] ]
|
, viewTimeBubble c
|
||||||
(True, Added) -> [ iconButton "red" (FeatherIcons.x) "Remove" [onClick (RemoveCourse i)] ]
|
]
|
||||||
_ -> []
|
]
|
||||||
|
, div [ class "course-add-remove" ] <|
|
||||||
|
case (isSelected, cs) of
|
||||||
|
(True, NotAdded) -> [ iconButton "green" (FeatherIcons.check) "Add" [ onClick (AddCourse i)] ]
|
||||||
|
(True, Added) -> [ iconButton "red" (FeatherIcons.x) "Remove" [onClick (RemoveCourse i)] ]
|
||||||
|
_ -> []
|
||||||
]
|
]
|
||||||
|
|
||||||
viewClassTable : Maybe Int -> List (CourseStatus, Course) -> Html Msg
|
viewVisibleClass : String -> Maybe Int -> Int -> (CourseStatus, Course) -> List (Html Msg)
|
||||||
viewClassTable sel =
|
viewVisibleClass s mi i p = if courseContains s p then [ viewClass mi i p ] else []
|
||||||
let
|
|
||||||
header = tr []
|
viewClassTable : String -> Maybe Int -> List (CourseStatus, Course) -> Html Msg
|
||||||
[ th [] [ ]
|
viewClassTable s sel =
|
||||||
, th [] [ text "Crn." ]
|
div [ class "table-wrapper" ] << List.concat << List.indexedMap (viewVisibleClass s sel)
|
||||||
, th [] [ text "Course Name" ]
|
|
||||||
, th [] [ text "Instructors" ]
|
|
||||||
, th [] [ text "Times" ]
|
|
||||||
, th [] []
|
|
||||||
]
|
|
||||||
in
|
|
||||||
div [ class "table-wrapper" ] << List.singleton << table [ class "class-table" ] << (::) header << List.indexedMap (viewClass sel)
|
|
||||||
|
|
||||||
viewToolbar : Model -> Html Msg
|
viewToolbar : Model -> Html Msg
|
||||||
viewToolbar m = div []
|
viewToolbar m = div []
|
||||||
|
@ -114,18 +154,10 @@ viewToolbar m = div []
|
||||||
]
|
]
|
||||||
|
|
||||||
viewClassList : Model -> Html Msg
|
viewClassList : Model -> Html Msg
|
||||||
viewClassList m = div []
|
viewClassList m =
|
||||||
[ viewToolbar m
|
case get (m.term) (m.terms) of
|
||||||
, case get (m.term) (m.terms) of
|
Just cs -> viewClassTable m.searchInput m.selected cs
|
||||||
Just cs -> viewClassTable (m.selected) <| List.filter (courseContains m.searchInput) cs
|
|
||||||
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 : Time -> Int
|
||||||
timeSortable (h, m, th) = hour24 (h,m,th) * 60 + m
|
timeSortable (h, m, th) = hour24 (h,m,th) * 60 + m
|
||||||
|
@ -254,7 +286,7 @@ viewClassSchedule m =
|
||||||
let
|
let
|
||||||
header = span [] [] :: List.map viewTableDayHeader (List.take 5 days)
|
header = span [] [] :: List.map viewTableDayHeader (List.take 5 days)
|
||||||
cellDict = buildCellDict m.selected (Maybe.withDefault [] <| Dict.get m.term m.terms)
|
cellDict = buildCellDict m.selected (Maybe.withDefault [] <| Dict.get m.term m.terms)
|
||||||
times = List.range 0 10
|
times = List.range 0 12
|
||||||
time h = List.map (\w -> Maybe.withDefault [] <| Maybe.andThen (Dict.get h) <| Dict.get w cellDict) (List.range 0 4)
|
time h = List.map (\w -> Maybe.withDefault [] <| Maybe.andThen (Dict.get h) <| Dict.get w cellDict) (List.range 0 4)
|
||||||
container xs = div [ class "column-container" ] <|
|
container xs = div [ class "column-container" ] <|
|
||||||
List.map (\(c, ci) -> viewCourseBlock ci c) xs
|
List.map (\(c, ci) -> viewCourseBlock ci c) xs
|
||||||
|
@ -268,7 +300,7 @@ viewModel : Model -> Html Msg
|
||||||
viewModel m = div [ class "main" ]
|
viewModel m = div [ class "main" ]
|
||||||
[ h1 [] [ text "Oregon State University Course Schedule" ]
|
[ h1 [] [ text "Oregon State University Course Schedule" ]
|
||||||
, div [ class "split-pane" ]
|
, div [ class "split-pane" ]
|
||||||
[ div [ class "split-elem" ] [ viewClassList m ]
|
[ div [ class "split-elem" ] [ viewToolbar m, viewClassList m ]
|
||||||
, div [ class "split-elem" ] [ viewClassSchedule m ]
|
, div [ class "split-elem" ] [ viewClassSchedule m ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
52
src/Main.elm
52
src/Main.elm
|
@ -1,9 +1,11 @@
|
||||||
module Main exposing (..)
|
module Main exposing (..)
|
||||||
import ClassSchedule.Model exposing (..)
|
import ClassSchedule.Model exposing (..)
|
||||||
import ClassSchedule.View exposing (..)
|
import ClassSchedule.View exposing (..)
|
||||||
|
import ClassSchedule.Decode exposing (..)
|
||||||
import Browser exposing (Document, document)
|
import Browser exposing (Document, document)
|
||||||
import Dict exposing (..)
|
import Dict exposing (..)
|
||||||
import Tuple exposing (..)
|
import Tuple exposing (..)
|
||||||
|
import Http exposing (..)
|
||||||
|
|
||||||
oneHour : Time -> (Time, Time)
|
oneHour : Time -> (Time, Time)
|
||||||
oneHour t = (t, addMinutes 50 t)
|
oneHour t = (t, addMinutes 50 t)
|
||||||
|
@ -20,46 +22,14 @@ nPm i = (i, 0, PM)
|
||||||
onDays : List DayOfWeek -> (Time, Time) -> List (DayOfWeek, Time, Time)
|
onDays : List DayOfWeek -> (Time, Time) -> List (DayOfWeek, Time, Time)
|
||||||
onDays dds (t1, t2) = List.map (\d -> (d, t1, t2)) dds
|
onDays dds (t1, t2) = List.map (\d -> (d, t1, t2)) dds
|
||||||
|
|
||||||
classes : List Course
|
|
||||||
classes =
|
|
||||||
[ { crn = (ComputerScience, 517)
|
|
||||||
, name = "Theory of Comp"
|
|
||||||
, instructors = ["Mike Rosulek"]
|
|
||||||
, times = onDays [Monday, Wednesday, Friday] <| oneHour <| nPm 2
|
|
||||||
}
|
|
||||||
, { crn = (ComputerScience, 531)
|
|
||||||
, name = "Artificial Intelligence"
|
|
||||||
, instructors = ["John Doe"]
|
|
||||||
, times = onDays [Monday, Wednesday, Friday] <| oneHour <| nPm 0
|
|
||||||
}
|
|
||||||
, { crn = (ComputerScience, 533)
|
|
||||||
, name = "Intelligent Somethings"
|
|
||||||
, instructors = ["Alan Fern"]
|
|
||||||
, times = onDays [Monday, Wednesday] <| twoHours <| nAm 10
|
|
||||||
}
|
|
||||||
, { crn = (ComputerScience, 535)
|
|
||||||
, name = "Deep Learning"
|
|
||||||
, instructors = ["F. Li"]
|
|
||||||
, times = onDays [Tuesday, Thursday] <| twoHours <| nPm 2
|
|
||||||
}
|
|
||||||
, { crn = (ComputerScience, 551)
|
|
||||||
, name = "Computer Graphics"
|
|
||||||
, instructors = ["Mike Bailey"]
|
|
||||||
, times = onDays [Monday, Wednesday] <| twoHours <| nPm 0
|
|
||||||
}
|
|
||||||
, { crn = (ComputerScience, 565)
|
|
||||||
, name = "Human-Computer Interaction"
|
|
||||||
, instructors = ["Minsuk Kahng"]
|
|
||||||
, times = onDays [Tuesday, Thursday] <| twoHours <| nPm 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
terms : Dict String (List (CourseStatus, Course))
|
|
||||||
terms = Dict.singleton "Spring 2021"
|
|
||||||
<| List.map (pair NotAdded) classes
|
|
||||||
|
|
||||||
init : Flags -> (Model, Cmd Msg)
|
init : Flags -> (Model, Cmd Msg)
|
||||||
init () = ({ terms = terms, term = "Spring 2021", searchInput = "", selected = Nothing }, Cmd.none)
|
init () =
|
||||||
|
( { terms = Dict.empty, term = "Spring 2021", searchInput = "", selected = Nothing }
|
||||||
|
, Http.get
|
||||||
|
{ url = "cs565_hw4c_schedule_data.json"
|
||||||
|
, expect = expectJson ReceiveData response
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
view : Model -> Document Msg
|
view : Model -> Document Msg
|
||||||
view m =
|
view m =
|
||||||
|
@ -82,6 +52,10 @@ update msg m =
|
||||||
AddCourse i -> (modifyCurrent (changeCourse i Added) m, Cmd.none)
|
AddCourse i -> (modifyCurrent (changeCourse i Added) m, Cmd.none)
|
||||||
RemoveCourse i -> (modifyCurrent (changeCourse i NotAdded) m, Cmd.none)
|
RemoveCourse i -> (modifyCurrent (changeCourse i NotAdded) m, Cmd.none)
|
||||||
SearchInput s -> ({ m | searchInput = s }, Cmd.none)
|
SearchInput s -> ({ m | searchInput = s }, Cmd.none)
|
||||||
|
ReceiveData e ->
|
||||||
|
case e of
|
||||||
|
Err er -> Debug.log (Debug.toString er) (m, Cmd.none)
|
||||||
|
Ok d -> ({ m | terms = Dict.singleton "Spring 2021" <| List.map (pair NotAdded) d }, Cmd.none)
|
||||||
_ -> (m, Cmd.none)
|
_ -> (m, Cmd.none)
|
||||||
|
|
||||||
subscriptions : Model -> Sub Msg
|
subscriptions : Model -> Sub Msg
|
||||||
|
|
Loading…
Reference in New Issue
Block a user