Commit f641a6ca authored by Cédric F.'s avatar Cédric F.

Ajaxify links

parent 5297e3a0
......@@ -26,7 +26,7 @@
<script>
// CONFIGURE ME:
const coin = 'BCH';
const coin = 'DCR';
// TODO: use fuzzy search to guess coin based on hostname?
document.title = coin + " blockchain - Trappisto";
......@@ -70,6 +70,12 @@
.fetching {
opacity: 0.5;
}
.rotate {
animation: spin 2s linear infinite;
}
@keyframes spin { 100% { transform:rotate(360deg); } }
</style>
</head>
<body class="bg-black text-white">
......@@ -87,7 +93,7 @@
document.getElementsByTagName('head')[0].appendChild(style);
</script>
<div class="container-fluid">
<div class="container">
<div class="row" style="position:absolute;width:100%;height:100%">
<div class="col">
<div id="particles-js"></div>
......@@ -104,14 +110,19 @@
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
<script>
particlesJS.load('particles-js', 'assets/js/particles.json', function() {
console.log('callback - particles.js config loaded');
});
//particlesJS.load('particles-js', 'assets/js/particles.json', function() {
//console.log('callback - particles.js config loaded');
//});
window.addEventListener('load', () => {
const elmAppDiv = document.querySelector('#elm-app');
const elmApp = Elm.Trappisto.embed(elmAppDiv, { coin: coin });
query = (query) => {
console.log("Query: ", query);
elmApp.ports.jsToElm.send(["query", query]);
};
elmApp.ports.elmToJs.subscribe((params) => {
const command = params.shift();
console.log('Received command: ' + command, params);
......
......@@ -95,7 +95,7 @@ view model =
)
in
div [ class "row" ]
[ div [ class "col-8 offset-2" ]
[ div [ class "col" ]
[ div [ class "card bg-dark" ]
[ h5 [ class "card-header" ]
[ span [] [ text <| "Address " ++ model.address ]
......@@ -109,14 +109,14 @@ view model =
[ h4 [ class "text-center" ]
[ span [ class "badge badge-pill badge-info" ]
[ text <|
toString (List.length model.transactions)
++ " transactions"
pluralize (List.length model.transactions)
"transaction"
]
]
, table [ class "table table-dark table-striped" ]
[ thead []
[ tr []
[ th [] [ text "ID" ]
[ th [] [ text "hash" ]
, th [] [ text "type" ]
, th [] [ text "credit" ]
, th [] [ text "time" ]
......@@ -221,7 +221,7 @@ decodeSearchRawTransactions address =
maxTransactionCount : Int
maxTransactionCount =
50
500
missingTransactions : Model -> Bool
......
......@@ -2,7 +2,6 @@ module Components.Block exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http exposing (Error)
import Json.Encode as Encode
import Json.Decode as Decode
......@@ -90,19 +89,22 @@ type Msg
view : Model -> Html Msg
view model =
let
sibbling maybeHash html =
[ case maybeHash of
sibbling maybeHash direction =
case maybeHash of
Nothing ->
span [] []
Just hash ->
a
[ class "btn btn-secondary"
, href "javascript:void(0)"
, onClick (GetBlock hash)
]
[ text html ]
]
let
( label, classes ) =
if direction == "right" then
( "Next block", " float-right ml-2" )
else
( "Previous block", "" )
in
queryLink hash
("<span class=\"oi oi-chevron-" ++ direction ++ "\"></span>")
[ class <| "btn btn-secondary" ++ classes, title label ]
transactions list color =
case list of
......@@ -114,9 +116,9 @@ view model =
((span [ class "mr-2" ] [ text (toString <| List.length list) ])
:: (List.map
(\tx ->
a
[ href tx, class <| "ml-1 badge badge-" ++ color ]
[ text <| shortHash tx ]
queryLink tx
(shortHash tx)
[ class <| "ml-1 badge badge-" ++ color ]
)
list
)
......@@ -127,19 +129,21 @@ view model =
case model.coin of
DCR ->
[ ( "stake transactions", transactions model.tickets "secondary" )
, ( "normal transactions", transactions model.transactions "light" )
, ( "regular transactions", transactions model.transactions "light" )
]
_ ->
[ ( "transactions", transactions model.transactions "light" ) ]
in
div [ class "row align-items-center" ]
[ div [ class "col-1 text-right" ] (sibbling model.previousBlockHash "<")
, div [ class "col-10" ]
[ div [ class "col" ]
[ div
[ class "card bg-dark" ]
[ h5 [ class "card-header" ]
[ span [] [ text <| "Block " ++ model.hash ]
[ sibbling model.previousBlockHash "left"
, span [ class "ml-4" ]
[ text <| "Block " ++ model.hash ]
, sibbling model.nextBlockHash "right"
, dcrDataLink <| "block/" ++ model.hash
]
, div [ class "card-body" ]
......@@ -159,7 +163,7 @@ view model =
, ( "confirmations"
, Just <|
span []
[ text <| toString model.confirmations ]
[ text <| formatNumber model.confirmations ]
)
, ( "size"
, Just <|
......@@ -174,7 +178,6 @@ view model =
]
]
]
, div [ class "col-1 text-left" ] (sibbling model.nextBlockHash ">")
]
......
......@@ -6,6 +6,7 @@ import Http exposing (Error)
import Json.Encode
import Json.Decode
import Lib.JsonRpc as JsonRpc
import Trappisto.Helpers exposing (..)
type alias Model =
......@@ -38,12 +39,27 @@ type Msg
view : Model -> Html a
view model =
div [ class "col text-center" ]
[ h3 []
[ text "Last block: "
, a [ href (toString model.blocks) ] [ text <| toString model.blocks ]
let
block =
if model.blocks < 0 then
span [] [ text "??????" ]
else
queryLink (toString model.blocks) (toString model.blocks) []
in
div []
[ span
[ class "badge badge-info" ]
[ h5 []
[ span [] [ text "Last block: " ]
, block
, br [] []
, span [] [ text "N minutes ago" ]
]
]
, span
[ class "badge badge-pill badge-danger" ]
[ text "Live updating:<br>websocket disconnected" ]
]
]
update : Msg -> Model -> ( Model, Cmd Msg )
......
......@@ -113,13 +113,13 @@ view model =
span [] [ text "N/A (unconfirmed)" ]
( Just hash, Nothing ) ->
a [ href hash ] [ text <| shortHash hash ]
queryLink hash (shortHash hash) []
( Nothing, Just height ) ->
a [ href <| toString height ] [ text <| toString height ]
queryLink (toString height) (toString height) []
( Just hash, Just height ) ->
a [ href hash ] [ text <| toString height ]
queryLink hash (toString height) []
formatFees model =
case model.coin of
......@@ -142,7 +142,7 @@ view model =
formatAddresses scriptPubKey =
div [] <|
(List.map
(\address -> div [] [ a [ href address ] [ text address ] ])
(\address -> div [] [ queryLink address address [] ])
scriptPubKey.addresses
)
......@@ -162,19 +162,15 @@ view model =
)
]
, span [ class "float-right" ]
[ text <|
(if vIn.amountIn > 0 then
toString vIn.amountIn
else
""
)
[ if vIn.amountIn > 0 then
formatAmount vIn.amountIn
else
span [] []
]
, div []
[ (case vIn.txId of
Just hash ->
a
[ href hash ]
[ text <| "Transaction " ++ shortHash hash ]
queryLink hash ("Transaction " ++ shortHash hash) []
Nothing ->
span [] []
......@@ -196,7 +192,7 @@ view model =
)
in
div [ class "row" ]
[ div [ class "col-12 col-xl-10 offset-xl-1" ]
[ div [ class "col" ]
[ div
[ class "card bg-dark" ]
[ h5 [ class "card-header" ]
......@@ -349,8 +345,7 @@ computeType : JsonModel -> String
computeType jsonModel =
let
hasVOutType type_ jsonModel =
List.map (\i -> i.scriptPubKey.type_) jsonModel.vOut
|> List.member type_
List.any (\i -> i.scriptPubKey.type_ == type_) jsonModel.vOut
in
--- XXX: simplified detection
--- full rules can be found in dcrd/blockchain/stake/staketx.go
......
......@@ -2,6 +2,7 @@ module Trappisto.Helpers exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Lib.HtmlAttributesExtra as HtmlAttributesExtra
type Coin
......@@ -22,7 +23,7 @@ pluralize count singular =
phrase ++ "s"
formatAmount : Float -> Html a
formatAmount : Float -> Html msg
formatAmount float =
let
rounded =
......@@ -53,7 +54,7 @@ shortHash hash =
String.concat [ String.left 2 hash, "...", String.right 2 hash ]
dlBuilder : List ( String, Maybe (Html a) ) -> Html a
dlBuilder : List ( String, Maybe (Html msg) ) -> Html msg
dlBuilder list =
let
filter ( label, value ) =
......@@ -70,10 +71,22 @@ dlBuilder list =
dl [ class "row" ] (List.concat <| List.filterMap filter list)
dcrDataLink : String -> Html a
queryLink : String -> String -> List (Attribute msg) -> Html msg
queryLink query label attributes =
let
hrefAttribute =
href <| "javascript:query('" ++ query ++ "')"
innerHtml =
HtmlAttributesExtra.innerHtml label
in
a (List.concat [ attributes, [ hrefAttribute, innerHtml ] ]) []
dcrDataLink : String -> Html msg
dcrDataLink path =
a
[ class "float-right"
[ class "btn btn-secondary float-right"
, target "_blank"
, title "Open on dcrdata.org"
, href <| "https://explorer.dcrdata.org/explorer/" ++ path
......
......@@ -67,9 +67,8 @@ type Msg
| AddressMsg AddressComponent.Msg
| BlockMsg BlockComponent.Msg
| TransactionMsg TransactionComponent.Msg
| JsMsg String
| JsMsg (List String)
| Query String
| QueryForce String
| KeyChange Bool Keyboard.KeyCode
| Resize Window.Size
| Tick Time
......
......@@ -16,7 +16,7 @@ import Trappisto.Helpers as Coin exposing (Coin)
port elmToJs : List String -> Cmd msg
port jsToElm : (String -> msg) -> Sub msg
port jsToElm : (List String -> msg) -> Sub msg
init : Flags -> Navigation.Location -> ( Model, Cmd Msg )
......@@ -100,13 +100,19 @@ update action model =
"298e5cc3d985bfe7f81dc135f360abe089edd4396b86d2de66b0cef42b21d980"
possibleAddress query =
String.length query >= 26 && String.length query <= 34
String.length query >= 26 && String.length query <= 35
-- XXX: Remove a few zeros in the future... 00000000
possibleBlockHash query =
(String.length query == 64 && String.left 8 query == "00000000")
|| (query == genesis)
parseBlockHeight string =
String.toInt string |> Result.toMaybe |> Maybe.withDefault -1
possibleBlockHeight query =
parseBlockHeight query /= -1
possibleTransaction query =
(String.length query == 64 && String.left 8 query /= "00000000")
&& (query /= genesis)
......@@ -125,27 +131,7 @@ update action model =
fetchBlockByHash query updatedModel
else if possibleAddress query then
fetchAddress query updatedModel
else
( { updatedModel
| template = Status
, error = Just "Not sure what you're looking for :|"
}
, Cmd.none
)
|> updateUrl
QueryForce query ->
let
parseBlockHeight string =
String.toInt string |> Result.toMaybe |> Maybe.withDefault -1
possibleBlockHeight query =
parseBlockHeight query /= -1
updatedModel =
{ model | query = query, error = Nothing }
in
if possibleBlockHeight query then
else if possibleBlockHeight query then
fetchBlockByHeight (parseBlockHeight query) updatedModel
else
( { updatedModel
......@@ -219,8 +205,13 @@ update action model =
)
|> updateUrl
JsMsg _ ->
( model, Cmd.none )
JsMsg params ->
case params of
[ "query", query ] ->
update (Query query) model
_ ->
Debug.crash <| "WTF? " ++ toString params
KeyChange bool code ->
let
......@@ -243,7 +234,7 @@ update action model =
else if updatedModel.query /= model.query then
update (Query updatedModel.query) updatedModel
else if keys.enter then
update (QueryForce updatedModel.query) updatedModel
update (Query updatedModel.query) updatedModel
else
( updatedModel, Cmd.none )
......
......@@ -64,9 +64,10 @@ errorView model =
searchView : Model -> Html Msg
searchView model =
let
search =
div [ class "row" ]
[ div [ class "col-8 offset-2" ]
search model =
div [ class "row align-items-center" ]
[ div [ class "col-2" ] [ logo model ]
, div [ class "col-8" ]
[ input
[ id "query"
, name "query"
......@@ -78,6 +79,11 @@ searchView model =
]
[]
]
, div
[ class "col-2"
, style [ ( "background-color", "rgba(255,255,255,0.5)" ) ]
]
[ (StatusComponent.view model.statusModel) ]
]
vim =
......@@ -88,11 +94,33 @@ searchView model =
]
]
logo model =
div [ class "row" ]
[ div
[ class "col text-center"
, style [ ( "background-color", "rgba(255,255,255,0.5)" ) ]
]
[ a [ href "/" ]
[ img
[ class
(if isFetching model then
"rotate"
else
""
)
, src "assets/images/decred.png"
, alt "logo"
]
[]
]
]
]
view =
if model.vimMode then
[ search, vim ]
[ search model, vim ]
else
[ search ]
[ search model ]
in
div [ class "row" ] [ div [ class "col" ] view ]
......@@ -120,22 +148,15 @@ transactionView model =
view : Model -> Html Msg
view model =
let
header =
[ div [ class "row" ]
ascii =
div [ class "row text-center mt-3" ]
[ div [ class "col" ]
[ if model.query /= "" then
span [] []
else
pre [ id "logo", class "text-white" ]
[ text
" ______ _______ _______ _______ _______ ______ \n( __ \\ ( ____ \\( ____ \\( ____ )( ____ \\( __ \\ \n| ( \\ )| ( \\/| ( \\/| ( )|| ( \\/| ( \\ )\n| | ) || (__ | | | (____)|| (__ | | ) |\n| | | || __) | | | __)| __) | | | |\n| | ) || ( | | | (\\ ( | ( | | ) |\n| (__/ )| (____/\\| (____/\\| ) \\ \\__| (____/\\| (__/ )\n(______/ (_______/(_______/|/ \\__/(_______/(______/ \n"
]
[ pre [ id "logo", class "text-white" ]
[ text
" ______ _______ _______ _______ _______ ______ \n( __ \\ ( ____ \\( ____ \\( ____ )( ____ \\( __ \\ \n| ( \\ )| ( \\/| ( \\/| ( )|| ( \\/| ( \\ )\n| | ) || (__ | | | (____)|| (__ | | ) |\n| | | || __) | | | __)| __) | | | |\n| | ) || ( | | | (\\ ( | ( | | ) |\n| (__/ )| (____/\\| (____/\\| ) \\ \\__| (____/\\| (__/ )\n(______/ (_______/(_______/|/ \\__/(_______/(______/ \n"
]
]
]
]
status model =
div [ class "row" ] [ statusView model ]
content =
if model.error /= Nothing then
......@@ -143,13 +164,18 @@ view model =
else
case model.template of
Status ->
if model.query == "particles" then
[ div [ class "row" ]
[ div [ class "col" ] [ text "Reticulating splines..." ]
case model.query of
"" ->
[ searchView model, errorView model, ascii ]
"particles" ->
[ div [ class "row" ]
[ div [ class "col" ] [ text "Reticulating splines..." ]
]
]
]
else
[ searchView model, errorView model, status model ]
_ ->
[ searchView model, errorView model ]
Address ->
if isError model then
......@@ -169,30 +195,13 @@ view model =
else
[ searchView model, transactionView model ]
debug =
[ hr [] []
, div [ class "row" ]
[ div [ class "col" ]
[ div
[ style
[ ( "font-size", "1rem" )
, ( "color", "white" )
, ( "text-align", "center" )
]
]
[ text <| toString model ]
]
]
]
headerAndContent model =
[ div [ class "row text-center" ] [ div [ class "col" ] header ]
, div [ class "row" ]
wrapper model =
[ div [ class "row" ]
[ div
[ class <|
"col"
++ (if isFetching model then
" fetching glow"
" fetching"
else
""
)
......@@ -203,8 +212,24 @@ view model =
sections =
if model.debug then
List.concat [ headerAndContent model, debug ]
List.concat [ wrapper model, debug ]
else
headerAndContent model
wrapper model
debug =
[ hr [] []
, div [ class "row" ]
[ div [ class "col" ]
[ div
[ style
[ ( "font-size", "1rem" )
, ( "color", "white" )
, ( "text-align", "center" )
]
]
[ text <| toString model ]
]
]
]
in
div [ class "row text-white" ] [ div [ class "col" ] sections ]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment