Added ability to load example from server
This commit is contained in:
parent
1701a5ea08
commit
0aa08315d1
3
elm.json
3
elm.json
@ -9,9 +9,12 @@
|
|||||||
"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"
|
"elm/json": "1.1.3"
|
||||||
},
|
},
|
||||||
"indirect": {
|
"indirect": {
|
||||||
|
"elm/bytes": "1.0.8",
|
||||||
|
"elm/file": "1.0.5",
|
||||||
"elm/time": "1.0.0",
|
"elm/time": "1.0.0",
|
||||||
"elm/url": "1.0.0",
|
"elm/url": "1.0.0",
|
||||||
"elm/virtual-dom": "1.0.2"
|
"elm/virtual-dom": "1.0.2"
|
||||||
|
@ -89,6 +89,10 @@
|
|||||||
--color-arrow-text: var(--color-white);
|
--color-arrow-text: var(--color-white);
|
||||||
--color-arrow-text-hover: var(--color-white-light2);
|
--color-arrow-text-hover: var(--color-white-light2);
|
||||||
--color-arrow-border: var(--color-black-light1);
|
--color-arrow-border: var(--color-black-light1);
|
||||||
|
|
||||||
|
--color-modal: var(--color-white-light1);
|
||||||
|
--color-modal-text: var(--color-black);
|
||||||
|
--color-modal-shadow: rgba( 0,0,0, 0.4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,6 +162,10 @@ button {
|
|||||||
margin-bottom: -1em;
|
margin-bottom: -1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pc .scroller table {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.pc .scroller table thead.head {
|
.pc .scroller table thead.head {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
@ -508,6 +512,62 @@ th.address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MODALS */
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.modal.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-card {
|
||||||
|
z-index: 1500;
|
||||||
|
display: block;
|
||||||
|
width: 40em;
|
||||||
|
min-width: 45vw;
|
||||||
|
min-height: 5em;
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
padding: 2.5em 2em 1em 2em;
|
||||||
|
|
||||||
|
background-color: var(--color-modal);
|
||||||
|
color: var(--color-modal-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal > :first-child {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-color: var(--color-modal-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .modal-close {
|
||||||
|
position: absolute;
|
||||||
|
top: .5em;
|
||||||
|
right: .5em;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .modal-close::before {
|
||||||
|
content: "❌";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* HELPERS */
|
/* HELPERS */
|
||||||
.text-center {
|
.text-center {
|
||||||
|
1522
out/elm.js
1522
out/elm.js
File diff suppressed because it is too large
Load Diff
201
src/Main.elm
201
src/Main.elm
@ -14,8 +14,10 @@ import Html exposing (address)
|
|||||||
import Json.Encode as JE
|
import Json.Encode as JE
|
||||||
import Json.Decode as JD
|
import Json.Decode as JD
|
||||||
import Html.Events exposing (targetValue)
|
import Html.Events exposing (targetValue)
|
||||||
|
import Http
|
||||||
|
|
||||||
modelVersion = 1
|
modelVersion = 1
|
||||||
|
examplesListUrl = "examples-list.json"
|
||||||
|
|
||||||
-- Note that general Stuff is at the end of the document
|
-- Note that general Stuff is at the end of the document
|
||||||
-- PORTS
|
-- PORTS
|
||||||
@ -45,8 +47,21 @@ type alias Model =
|
|||||||
{ pc : PC
|
{ pc : PC
|
||||||
, uCode : List UAction
|
, uCode : List UAction
|
||||||
, autoscroll : Bool
|
, autoscroll : Bool
|
||||||
|
, examples : List Example
|
||||||
|
, exampleChooserOpen : Bool
|
||||||
|
, examplesListStatus : LoaderState
|
||||||
|
, exampleLoaderStatus : LoaderState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type alias Example =
|
||||||
|
{ title : String
|
||||||
|
, version : String
|
||||||
|
, url : String
|
||||||
|
, enabled : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoaderState = Failure String | Waiting | Success
|
||||||
|
|
||||||
|
|
||||||
type UAction
|
type UAction
|
||||||
= ActAccumulator2DataBus
|
= ActAccumulator2DataBus
|
||||||
@ -64,7 +79,6 @@ type UAction
|
|||||||
| ActProgrammCounter2AddressBus
|
| ActProgrammCounter2AddressBus
|
||||||
| ActNothing
|
| ActNothing
|
||||||
|
|
||||||
|
|
||||||
uCodeDescriptions : List ( UAction, String )
|
uCodeDescriptions : List ( UAction, String )
|
||||||
uCodeDescriptions =
|
uCodeDescriptions =
|
||||||
[ ( ActAccumulator2DataBus, "Acc -> DataBus" )
|
[ ( ActAccumulator2DataBus, "Acc -> DataBus" )
|
||||||
@ -230,6 +244,11 @@ type Msg
|
|||||||
| MsgAluEdit String
|
| MsgAluEdit String
|
||||||
| MsgLocalSessionExport
|
| MsgLocalSessionExport
|
||||||
| MsgLocalSessionRecieve String
|
| MsgLocalSessionRecieve String
|
||||||
|
| MsgToggleLoadExample
|
||||||
|
| MsgLoadExamplesList
|
||||||
|
| MsgLoadExample Int
|
||||||
|
| MsgLoadExampleArrived (Result Http.Error Model)
|
||||||
|
| MsgExamplesArrived (Result Http.Error (List Example))
|
||||||
|
|
||||||
|
|
||||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||||
@ -361,13 +380,52 @@ update msg model =
|
|||||||
( model, cmdUpdateLocalStorage model )
|
( model, cmdUpdateLocalStorage model )
|
||||||
|
|
||||||
MsgLocalSessionRecieve message_in ->
|
MsgLocalSessionRecieve message_in ->
|
||||||
case decodeModel message_in of
|
case decodeModel model message_in of
|
||||||
Just new_model ->
|
Just new_model ->
|
||||||
( new_model , Cmd.none )
|
( { new_model | examples = model.examples } , Cmd.none )
|
||||||
_ -> ( model, Cmd.none )
|
_ -> ( model, Cmd.none )
|
||||||
|
|
||||||
|
MsgToggleLoadExample ->
|
||||||
|
if model.exampleChooserOpen then
|
||||||
|
( { model | exampleChooserOpen = False }
|
||||||
|
, Cmd.none )
|
||||||
|
else
|
||||||
|
( { model | exampleChooserOpen = True }
|
||||||
|
, cmdLoadExamples model)
|
||||||
|
|
||||||
|
|
||||||
|
MsgLoadExamplesList ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
MsgLoadExample i ->
|
||||||
|
case valueAt i model.examples of
|
||||||
|
Just example ->
|
||||||
|
({ model | exampleChooserOpen = False }
|
||||||
|
, cmdLoadExampleSing model example )
|
||||||
|
Nothing ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
MsgLoadExampleArrived result ->
|
||||||
|
case result of
|
||||||
|
Ok new_model ->
|
||||||
|
updateModel { model | pc = new_model.pc
|
||||||
|
, uCode = new_model.uCode
|
||||||
|
, exampleLoaderStatus = Success }
|
||||||
|
Err err ->
|
||||||
|
( { model | exampleLoaderStatus = Failure <| httpError2String err }
|
||||||
|
, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
|
MsgExamplesArrived result ->
|
||||||
|
case result of
|
||||||
|
Ok exampleList ->
|
||||||
|
( { model | examples = exampleList, examplesListStatus = Success }
|
||||||
|
, Cmd.none )
|
||||||
|
Err err ->
|
||||||
|
( { model | examplesListStatus = Failure <| httpError2String err }
|
||||||
|
, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
-- Practically a part of uStepPC but sepeated for manual mode
|
-- Practically a part of uStepPC but sepeated for manual mode
|
||||||
getAction : UAction -> (PC -> PC)
|
getAction : UAction -> (PC -> PC)
|
||||||
getAction uAction =
|
getAction uAction =
|
||||||
@ -443,41 +501,53 @@ encodeModel model =
|
|||||||
]
|
]
|
||||||
|> JE.encode 0
|
|> JE.encode 0
|
||||||
|
|
||||||
|
decodeModel : Model -> String -> Maybe Model
|
||||||
decodeModel : String -> Maybe Model
|
decodeModel model text =
|
||||||
decodeModel text =
|
|
||||||
let
|
let
|
||||||
error2maybe err =
|
error2maybe err =
|
||||||
case err of
|
case err of
|
||||||
Ok val -> Just val
|
Ok val -> Just val
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
uCodeDecoder =
|
|
||||||
JD.map
|
|
||||||
(\s -> Maybe.withDefault ActNothing <| string2uAction s )
|
|
||||||
(JD.string)
|
|
||||||
in
|
in
|
||||||
text
|
text
|
||||||
|> JD.decodeString
|
|> JD.decodeString modelDecoder
|
||||||
( JD.map3
|
|
||||||
Model
|
|
||||||
( JD.field "pc"
|
|
||||||
( JD.map7
|
|
||||||
PC
|
|
||||||
(JD.field "ram" (JD.list JD.int))
|
|
||||||
(JD.field "dataBus" JD.int)
|
|
||||||
(JD.field "addressBus" JD.int)
|
|
||||||
(JD.field "instructionReg" JD.int)
|
|
||||||
(JD.field "programmCounter" JD.int)
|
|
||||||
(JD.field "uCounter" JD.int)
|
|
||||||
(JD.field "accumulator" JD.int)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
( JD.field "uCode" (JD.list uCodeDecoder) )
|
|
||||||
( JD.field "autoscroll" JD.bool )
|
|
||||||
)
|
|
||||||
|> error2maybe
|
|> error2maybe
|
||||||
|
|
||||||
|
exampleListDecoder : JD.Decoder (List Example)
|
||||||
|
exampleListDecoder =
|
||||||
|
JD.field "available"
|
||||||
|
<| JD.list
|
||||||
|
<| JD.map4
|
||||||
|
Example
|
||||||
|
( JD.field "title" JD.string )
|
||||||
|
( JD.field "version" JD.string )
|
||||||
|
( JD.field "url" JD.string )
|
||||||
|
( JD.field "enabled" (JD.map (\s -> s == 1) JD.int) )
|
||||||
|
|
||||||
|
modelDecoder : JD.Decoder Model
|
||||||
|
modelDecoder =
|
||||||
|
JD.map3
|
||||||
|
(\a b c -> Model a b c [] False Waiting Waiting)
|
||||||
|
( JD.field "pc"
|
||||||
|
( JD.map7
|
||||||
|
PC
|
||||||
|
(JD.field "ram" (JD.list JD.int))
|
||||||
|
(JD.field "dataBus" JD.int)
|
||||||
|
(JD.field "addressBus" JD.int)
|
||||||
|
(JD.field "instructionReg" JD.int)
|
||||||
|
(JD.field "programmCounter" JD.int)
|
||||||
|
(JD.field "uCounter" JD.int)
|
||||||
|
(JD.field "accumulator" JD.int)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
( JD.field "uCode"
|
||||||
|
<| JD.list
|
||||||
|
<| JD.map (\s -> Maybe.withDefault ActNothing <| string2uAction s )
|
||||||
|
<| JD.string
|
||||||
|
)
|
||||||
|
( JD.field "autoscroll" JD.bool )
|
||||||
|
|
||||||
|
|
||||||
cmdUpdateLocalStorage : Model -> Cmd Msg
|
cmdUpdateLocalStorage : Model -> Cmd Msg
|
||||||
cmdUpdateLocalStorage model =
|
cmdUpdateLocalStorage model =
|
||||||
localStorageSend (encodeModel model)
|
localStorageSend (encodeModel model)
|
||||||
@ -489,6 +559,30 @@ cmdSenduUpdate model =
|
|||||||
, sendUUpdate "update"
|
, sendUUpdate "update"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
cmdLoadExamples : Model -> Cmd Msg
|
||||||
|
cmdLoadExamples model =
|
||||||
|
Http.get
|
||||||
|
{ url = examplesListUrl
|
||||||
|
, expect = Http.expectJson MsgExamplesArrived exampleListDecoder
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdLoadExampleSing : Model -> Example -> Cmd Msg
|
||||||
|
cmdLoadExampleSing model example =
|
||||||
|
Http.get
|
||||||
|
{ url = example.url
|
||||||
|
, expect = Http.expectJson MsgLoadExampleArrived modelDecoder
|
||||||
|
}
|
||||||
|
|
||||||
|
httpError2String : Http.Error -> String
|
||||||
|
httpError2String err =
|
||||||
|
case err of
|
||||||
|
Http.BadUrl str -> "Bad Url: " ++ str
|
||||||
|
Http.Timeout -> "Timeout"
|
||||||
|
Http.NetworkError -> "Network Error"
|
||||||
|
Http.BadStatus num -> "Bad Status: " ++ String.fromInt num
|
||||||
|
Http.BadBody str -> "Bad Body: " ++ str
|
||||||
|
|
||||||
-- VIEWERS
|
-- VIEWERS
|
||||||
|
|
||||||
view : Model -> Html Msg
|
view : Model -> Html Msg
|
||||||
@ -523,12 +617,15 @@ viewPC model =
|
|||||||
[ text "Autoscroll" ]
|
[ text "Autoscroll" ]
|
||||||
]
|
]
|
||||||
, button [ onClick MsgLocalSessionExport ] [ text "Export" ]
|
, button [ onClick MsgLocalSessionExport ] [ text "Export" ]
|
||||||
|
, button [ onClick MsgToggleLoadExample ] [ text "Load Example" ]
|
||||||
]
|
]
|
||||||
, div [ class "grid-fullwidth" ] [ lazy viewAddressBus model ]
|
, div [ class "grid-fullwidth" ] [ lazy viewAddressBus model ]
|
||||||
, lazy viewRam model
|
, lazy viewRam model
|
||||||
, lazy viewCu model
|
, lazy viewCu model
|
||||||
, lazy viewAlu model
|
, lazy viewAlu model
|
||||||
, div [ class "grid-fullwidth" ] [ lazy viewDataBus model ]
|
, div [ class "grid-fullwidth" ] [ lazy viewDataBus model ]
|
||||||
|
, lazy viewExamples model
|
||||||
|
, lazy viewExamplesLoaderError model
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -800,8 +897,50 @@ viewInstrEntry i =
|
|||||||
text ( (addLeadingZero instruction 3) ++ " " ++ (addLeadingZero address 5) )
|
text ( (addLeadingZero instruction 3) ++ " " ++ (addLeadingZero address 5) )
|
||||||
|
|
||||||
|
|
||||||
|
viewExamples : Model -> Html Msg
|
||||||
|
viewExamples model =
|
||||||
|
div [ classList [("modal", True), ("hidden", (not model.exampleChooserOpen))] ]
|
||||||
|
[ div [] []
|
||||||
|
, div [ class "modal-card" ]
|
||||||
|
[ Html.a [ class "modal-close", onClick MsgToggleLoadExample ] []
|
||||||
|
, lazy viewExamplesEntrys model
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
viewExamplesEntrys : Model -> Html Msg
|
||||||
|
viewExamplesEntrys model =
|
||||||
|
let
|
||||||
|
entry2html (id, example) =
|
||||||
|
Html.tr []
|
||||||
|
[ Html.td [] [ text <| "Example: " ++ example.title ]
|
||||||
|
, Html.td [] [ button [ onClick <| MsgLoadExample id ] [ text "Laden" ] ]
|
||||||
|
]
|
||||||
|
in
|
||||||
|
case model.examplesListStatus of
|
||||||
|
Failure msg ->
|
||||||
|
div [] [ text <| "That didn't work: " ++ msg]
|
||||||
|
Waiting ->
|
||||||
|
div [] [ text "Loading..." ]
|
||||||
|
Success ->
|
||||||
|
div [ class "scroller" ]
|
||||||
|
[ Html.table []
|
||||||
|
<| List.map entry2html
|
||||||
|
<| List.indexedMap Tuple.pair model.examples
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewExamplesLoaderError : Model -> Html Msg
|
||||||
|
viewExamplesLoaderError model =
|
||||||
|
case model.exampleLoaderStatus of
|
||||||
|
Failure msg ->
|
||||||
|
div [ class "modal" ]
|
||||||
|
[ div [] []
|
||||||
|
, div [ class "modal-card" ]
|
||||||
|
[ Html.p [] [ text "Something didn't work. Please refresh the page"]
|
||||||
|
, Html.p [] [ text msg ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
_ -> text ""
|
||||||
|
|
||||||
-- END VIEWERS
|
-- END VIEWERS
|
||||||
-- ACTIONS
|
-- ACTIONS
|
||||||
@ -1013,7 +1152,7 @@ subscriptions model =
|
|||||||
|
|
||||||
init : () -> ( Model, Cmd Msg )
|
init : () -> ( Model, Cmd Msg )
|
||||||
init flags =
|
init flags =
|
||||||
( Model initialPC initialUCodes True, Cmd.none )
|
( Model initialPC initialUCodes True [] False Waiting Waiting, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
main : Program () Model Msg
|
main : Program () Model Msg
|
||||||
|
Loading…
x
Reference in New Issue
Block a user