commit
57374668c0
@ -0,0 +1,15 @@ |
|||||||
|
body:after { |
||||||
|
position:absolute; width:0; height:0; overflow:hidden; z-index:-1; |
||||||
|
content: |
||||||
|
url(/images/network-selector-icons/callisto-mainnet.png) |
||||||
|
url(/images/network-selector-icons/ethereum-mainnet.png) |
||||||
|
url(/images/network-selector-icons/ethereum-classic.png) |
||||||
|
url(/images/network-selector-icons/goerli-testnet.png) |
||||||
|
url(/images/network-selector-icons/kovan-testnet.png) |
||||||
|
url(/images/network-selector-icons/poa-core.png) |
||||||
|
url(/images/network-selector-icons/poa-sokol.png) |
||||||
|
url(/images/network-selector-icons/rinkeby-testnet.png) |
||||||
|
url(/images/network-selector-icons/rsk-mainnet.png) |
||||||
|
url(/images/network-selector-icons/ropsten-testnet.png) |
||||||
|
url(/images/network-selector-icons/xdai-chain.png) |
||||||
|
}; |
@ -0,0 +1,5 @@ |
|||||||
|
$modal-overlay-color: rgba($primary, 0.9) !default; |
||||||
|
$modal-horizontal-padding: 30px !default; |
||||||
|
$modal-vertical-padding: 25px !default; |
||||||
|
$modal-border-radius: 10px !default; |
||||||
|
$modal-gray-background: #f6f7f9 !default; |
@ -0,0 +1,2 @@ |
|||||||
|
$stakes-banned-background: #fff3f7 !default; |
||||||
|
$stakes-banned-color: #ff7986 !default; |
@ -1,8 +1,6 @@ |
|||||||
$stakes-dashboard-copy-icon-color: $copy-icon-color !default; |
$stakes-dashboard-copy-icon-color: $copy-icon-color !default; |
||||||
$stakes-address-color: $primary !default; |
$stakes-address-color: $primary !default; |
||||||
$stakes-control-color: $primary !default; |
$stakes-control-color: $primary !default; |
||||||
$stakes-banned-color: #ff7986 !default; |
|
||||||
$stakes-banned-background: #fff3f7 !default; |
|
||||||
$stakes-stats-item-color: #fff !default; |
$stakes-stats-item-color: #fff !default; |
||||||
$stakes-stats-item-border-color: #fff !default; |
$stakes-stats-item-border-color: #fff !default; |
||||||
|
|
@ -0,0 +1,17 @@ |
|||||||
|
// Bootstrap Core CSS |
||||||
|
@import "node_modules/bootstrap/scss/functions"; |
||||||
|
@import "node_modules/bootstrap/scss/mixins"; |
||||||
|
|
||||||
|
@import "theme/variables-non-critical"; |
||||||
|
|
||||||
|
@import "node_modules/bootstrap/scss/modal"; |
||||||
|
@import "node_modules/bootstrap/scss/tooltip"; |
||||||
|
|
||||||
|
@import "components/i_tooltip"; |
||||||
|
@import "components/check_tooltip"; |
||||||
|
@import "components/tooltip"; |
||||||
|
|
||||||
|
@import "components/qr-code"; |
||||||
|
@import "components/modal_variables"; |
||||||
|
@import "components/modal"; |
||||||
|
@import "components/modal_status"; |
@ -0,0 +1,20 @@ |
|||||||
|
@import "./mixins"; |
||||||
|
|
||||||
|
// Bootstrap Core CSS |
||||||
|
@import "node_modules/bootstrap/scss/functions"; |
||||||
|
@import "node_modules/bootstrap/scss/mixins"; |
||||||
|
|
||||||
|
@import "theme/variables"; |
||||||
|
|
||||||
|
@import "components/stakes_variables"; |
||||||
|
@import "components/stakes/copy_icon"; |
||||||
|
@import "components/stakes/stakes"; |
||||||
|
@import "components/stakes/progress_from_to"; |
||||||
|
@import "components/stakes/stakes_empty_content"; |
||||||
|
@import "components/stakes/stakes_btn_remove_pool"; |
||||||
|
@import "components/modal_variables"; |
||||||
|
@import "components/stakes/stakes_progress"; |
||||||
|
@import "components/stakes/modal_stake"; |
||||||
|
@import "components/stakes/modal_become_candidate"; |
||||||
|
@import "components/stakes/modal_validator_info"; |
||||||
|
@import "components/stakes/modal_bottom_disclaimer"; |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #17314f; |
||||||
|
$secondary: #15bba6; |
||||||
|
$tertiary: #93d7ff; |
||||||
|
$additional-font: #fff; |
||||||
|
|
||||||
|
$btn-line-color: $secondary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #840032; |
||||||
|
$secondary: #343434; |
||||||
|
$tertiary: #7f7f7f; |
||||||
|
$additional-font: #ff95db; |
||||||
|
|
||||||
|
$btn-line-color: #4b021e; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #1c1c3d; |
||||||
|
$secondary: #4ad7a7; |
||||||
|
$tertiary: #5959d8; |
||||||
|
$additional-font: #bdbdff; |
||||||
|
|
||||||
|
$btn-line-color: $tertiary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #153550; |
||||||
|
$secondary: #49a2ee; |
||||||
|
$tertiary: #4ad7a7; |
||||||
|
$additional-font: #89cae6; |
||||||
|
|
||||||
|
$btn-line-color: $secondary; // button border and font color && hover bg color |
@ -0,0 +1,8 @@ |
|||||||
|
// general |
||||||
|
$primary: #2b2b2b; |
||||||
|
$secondary: #eac247; |
||||||
|
$tertiary: #929292; |
||||||
|
$additional-font: #ffffff; |
||||||
|
$sub-accent-color: #a46f30; |
||||||
|
|
||||||
|
$btn-line-color: $sub-accent-color; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #101f25; |
||||||
|
$secondary: #35e3d8; |
||||||
|
$tertiary: #1f857f; |
||||||
|
$additional-font: #99fff9; |
||||||
|
|
||||||
|
$btn-line-color: $tertiary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #1d3154; |
||||||
|
$secondary: #fdcec4; |
||||||
|
$tertiary: #a96c55; |
||||||
|
$additional-font: #a1ded1; |
||||||
|
|
||||||
|
$btn-line-color: $primary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #5c34a2; |
||||||
|
$secondary: #87e1a9; |
||||||
|
$tertiary: #bf9cff; |
||||||
|
$additional-font: #fff; |
||||||
|
|
||||||
|
$btn-line-color: $primary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #5c34a2; |
||||||
|
$secondary: #87e1a9; |
||||||
|
$tertiary: #bf9cff; |
||||||
|
$additional-font: #fff; |
||||||
|
|
||||||
|
$btn-line-color: $primary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #153550; |
||||||
|
$secondary: #38a9f5; |
||||||
|
$tertiary: #76f1ff; |
||||||
|
$additional-font: #89cae6; |
||||||
|
|
||||||
|
$btn-line-color: $secondary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #153550; |
||||||
|
$secondary: #38a9f5; |
||||||
|
$tertiary: #76f1ff; |
||||||
|
$additional-font: #89cae6; |
||||||
|
|
||||||
|
$btn-line-color: $secondary; // button border and font color && hover bg color |
@ -0,0 +1,7 @@ |
|||||||
|
// general |
||||||
|
$primary: #101f25; |
||||||
|
$secondary: #27ac8d; |
||||||
|
$tertiary: #e39a54; |
||||||
|
$additional-font: #a1ded1; |
||||||
|
|
||||||
|
$btn-line-color: $secondary; // button border and font color && hover bg color |
@ -0,0 +1,8 @@ |
|||||||
|
// general |
||||||
|
$primary: #093731; |
||||||
|
$secondary: #40bfb2; |
||||||
|
$tertiary: #25c9ff; |
||||||
|
$additional-font: #93e8dd; |
||||||
|
$sub-accent-color: #1c9f90; |
||||||
|
|
||||||
|
$btn-line-color: $sub-accent-color; // button border and font color && hover bg color |
@ -0,0 +1,22 @@ |
|||||||
|
@import "theme/base_variables"; |
||||||
|
@import "neutral_variables-non-critical"; |
||||||
|
// @import "dai_variables-non-critical"; |
||||||
|
// @import "ethereum_classic_variables-non-critical"; |
||||||
|
// @import "ethereum_variables-non-critical"; |
||||||
|
// @import "ether1_variables-non-critical"; |
||||||
|
// @import "expanse_variables-non-critical"; |
||||||
|
// @import "gochain_variables-non-critical"; |
||||||
|
// @import "goerli_variables-non-critical"; |
||||||
|
// @import "kovan_variables-non-critical"; |
||||||
|
// @import "lukso_variables-non-critical"; |
||||||
|
// @import "musicoin_variables-non-critical"; |
||||||
|
// @import "pirl_variables-non-critical"; |
||||||
|
// @import "poa_variables-non-critical"; |
||||||
|
// @import "posdao_variables-non-critical"; |
||||||
|
// @import "rinkeby_variables-non-critical"; |
||||||
|
// @import "ropsten_variables-non-critical"; |
||||||
|
// @import "social_variables-non-critical"; |
||||||
|
// @import "sokol_variables-non-critical"; |
||||||
|
// @import "tobalaba_variables-non-critical"; |
||||||
|
// @import "tomochain_variables-non-critical"; |
||||||
|
// @import "rsk_variables-non-critical"; |
@ -0,0 +1,637 @@ |
|||||||
|
/* eslint-env browser */ |
||||||
|
/* global Awesomplete */ |
||||||
|
/* exported AwesompleteUtil */ |
||||||
|
|
||||||
|
/* |
||||||
|
* Library endorsing Lea Verou's Awesomplete widget, providing: |
||||||
|
* - dynamic remote data loading |
||||||
|
* - labels with HTML markup |
||||||
|
* - events and styling for exact matches |
||||||
|
* - events and styling for mismatches |
||||||
|
* - select item when TAB key is used |
||||||
|
* |
||||||
|
* (c) Nico Hoogervorst |
||||||
|
* License: MIT |
||||||
|
* |
||||||
|
*/ |
||||||
|
window.AwesompleteUtil = (function () { |
||||||
|
//
|
||||||
|
// event names and css classes
|
||||||
|
//
|
||||||
|
var _AWE = 'awesomplete-' |
||||||
|
var _AWE_LOAD = _AWE + 'loadcomplete' |
||||||
|
var _AWE_CLOSE = _AWE + 'close' |
||||||
|
var _AWE_MATCH = _AWE + 'match' |
||||||
|
var _AWE_PREPOP = _AWE + 'prepop' |
||||||
|
var _AWE_SELECT = _AWE + 'select' |
||||||
|
var _CLS_FOUND = 'awe-found' |
||||||
|
var _CLS_NOT_FOUND = 'awe-not-found' |
||||||
|
var $ = Awesomplete.$ /* shortcut for document.querySelector */ |
||||||
|
|
||||||
|
//
|
||||||
|
// private functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// Some parts are shamelessly copied from Awesomplete.js like the logic inside this _suggestion function.
|
||||||
|
// Returns an object with label and value properties. Data parameter is plain text or Object/Array with label and value.
|
||||||
|
function _suggestion (data) { |
||||||
|
var lv = Array.isArray(data) |
||||||
|
? { label: data[0], value: data[1] } |
||||||
|
: typeof data === 'object' && 'label' in data && 'value' in data ? data : { label: data, value: data } |
||||||
|
return {label: lv.label || lv.value, value: lv.value} |
||||||
|
} |
||||||
|
|
||||||
|
// Helper to send events with detail property.
|
||||||
|
function _fire (target, name, detail) { |
||||||
|
// $.fire uses deprecated methods but other methods don't work in IE11.
|
||||||
|
return $.fire(target, name, {detail: detail}) |
||||||
|
} |
||||||
|
|
||||||
|
// Look if there is an exact match or a mismatch, set awe-found, awe-not-found css class and send match events.
|
||||||
|
function _matchValue (awe, prepop) { |
||||||
|
var input = awe.input /* the input field */ |
||||||
|
var classList = input.classList |
||||||
|
var utilprops = awe.utilprops /* extra properties piggybacked on Awesomplete object */ |
||||||
|
var selected = utilprops.selected /* the exact selected Suggestion with label and value */ |
||||||
|
var val = utilprops.convertInput.call(awe, input.value) /* trimmed lowercased value */ |
||||||
|
var opened = awe.opened /* is the suggestion list opened? */ |
||||||
|
var result = [] /* matches with value */ |
||||||
|
var list = awe._list /* current list of suggestions */ |
||||||
|
var suggestion, fake, rec, j /* function scoped variables */ |
||||||
|
utilprops.prepop = false /* after the first call it's not a prepopulation phase anymore */ |
||||||
|
if (list) { /* if there is a suggestion list */ |
||||||
|
for (j = 0; j < list.length; j++) { /* loop all suggestions */ |
||||||
|
rec = list[j] |
||||||
|
suggestion = _suggestion(awe.data(rec, val)) /* call data convert function */ |
||||||
|
// with maxItems = 0 cannot look if suggestion list is opened to determine if there are still matches,
|
||||||
|
// instead call the filter method to see if there are still some options.
|
||||||
|
if (awe.maxItems === 0) { |
||||||
|
// Awesomplete.FILTER_CONTAINS and Awesomplete.FILTER_STARTSWITH use the toString method.
|
||||||
|
suggestion.toString = function () { return '' + this.label } |
||||||
|
if (awe.filter(suggestion, val)) { |
||||||
|
// filter returns true, so there is at least one partial match.
|
||||||
|
opened = true |
||||||
|
} |
||||||
|
} |
||||||
|
// Don't want to change the real input field, emulate a fake one.
|
||||||
|
fake = {input: {value: ''}} |
||||||
|
// Determine how this suggestion would look like if it is replaced in the input field,
|
||||||
|
// it is an exact match if somebody types exactly that.
|
||||||
|
// Use the fake input here. fake.input.value will contain the result of the replace function.
|
||||||
|
awe.replace.call(fake, suggestion) |
||||||
|
// Trim and lowercase also the fake input and compare that with the currently typed-in value.
|
||||||
|
if (utilprops.convertInput.call(awe, fake.input.value) === val) { |
||||||
|
// This is an exact match. However there might more suggestions with the same value.
|
||||||
|
// If the user selected a suggestion from the list, check if this one matches, assuming that
|
||||||
|
// value + label is unique (if not it will be difficult for the user to make an informed decision).
|
||||||
|
if (selected && selected.value === suggestion.value && selected.label === suggestion.label) { |
||||||
|
// this surely is the selected one
|
||||||
|
result = [rec] |
||||||
|
break |
||||||
|
} |
||||||
|
// add the matching record to the result set.
|
||||||
|
result.push(rec) |
||||||
|
} // end if
|
||||||
|
} // end loop
|
||||||
|
|
||||||
|
// if the result differs from the previous result
|
||||||
|
if (utilprops.prevSelected !== result) { |
||||||
|
// if there is an exact match
|
||||||
|
if (result.length > 0) { |
||||||
|
// if prepopulation phase (initial/autofill value); not triggered by user input
|
||||||
|
if (prepop) { |
||||||
|
_fire(input, _AWE_PREPOP, result) |
||||||
|
} else if (utilprops.changed) { /* if input is changed */ |
||||||
|
utilprops.prevSelected = result /* new result */ |
||||||
|
classList.remove(_CLS_NOT_FOUND) /* remove class */ |
||||||
|
classList.add(_CLS_FOUND) /* add css class */ |
||||||
|
_fire(input, _AWE_MATCH, result) /* fire event */ |
||||||
|
} |
||||||
|
} else if (prepop) { /* no exact match, if in prepopulation phase */ |
||||||
|
_fire(input, _AWE_PREPOP, []) |
||||||
|
} else if (utilprops.changed) { /* no exact match, if input is changed */ |
||||||
|
utilprops.prevSelected = [] |
||||||
|
classList.remove(_CLS_FOUND) |
||||||
|
// Mark as not-found if there are no suggestions anymore or if another field is now active
|
||||||
|
if (!opened || (input !== document.activeElement)) { |
||||||
|
if (val.length > 0) { |
||||||
|
classList.add(_CLS_NOT_FOUND) |
||||||
|
_fire(input, _AWE_MATCH, []) |
||||||
|
} |
||||||
|
} else { |
||||||
|
classList.remove(_CLS_NOT_FOUND) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Listen to certain events of THIS awesomplete object to trigger input validation.
|
||||||
|
function _match (ev) { |
||||||
|
var awe = this |
||||||
|
if ((ev.type === _AWE_CLOSE || ev.type === _AWE_LOAD || ev.type === 'blur') && ev.target === awe.input) { |
||||||
|
_matchValue(awe, awe.utilprops.prepop && ev.type === _AWE_LOAD) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Select currently selected item if tab or shift-tab key is used.
|
||||||
|
function _onKeydown (ev) { |
||||||
|
var awe = this |
||||||
|
if (ev.target === awe.input && ev.keyCode === 9) { // TAB key
|
||||||
|
awe.select() // take current selected item
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Handle selection event. State changes when an item is selected.
|
||||||
|
function _select (ev) { |
||||||
|
var awe = this |
||||||
|
awe.utilprops.changed = true // yes, user made a change
|
||||||
|
awe.utilprops.selected = ev.text // Suggestion object
|
||||||
|
} |
||||||
|
|
||||||
|
// check if the object is empty {} object
|
||||||
|
function _isEmpty (val) { |
||||||
|
return Object.keys(val).length === 0 && val.constructor === Object |
||||||
|
} |
||||||
|
|
||||||
|
// Need an updated suggestion list if:
|
||||||
|
// - There is no result yet, or there is a result but not for the characters we entered
|
||||||
|
// - or there might be more specific results because the limit was reached.
|
||||||
|
function _ifNeedListUpdate (awe, val, queryVal) { |
||||||
|
var utilprops = awe.utilprops |
||||||
|
return (!utilprops.listQuery || |
||||||
|
(!utilprops.loadall && /* with loadall, if there is a result, there is no need for new lists */ |
||||||
|
val.lastIndexOf(queryVal, 0) === 0 && |
||||||
|
(val.lastIndexOf(utilprops.listQuery, 0) !== 0 || |
||||||
|
(typeof utilprops.limit === 'number' && awe._list.length >= utilprops.limit)))) |
||||||
|
} |
||||||
|
|
||||||
|
// Set a new suggestion list. Trigger loadcomplete event.
|
||||||
|
function _loadComplete (awe, list, queryVal) { |
||||||
|
awe.list = list |
||||||
|
awe.utilprops.listQuery = queryVal |
||||||
|
_fire(awe.input, _AWE_LOAD, queryVal) |
||||||
|
} |
||||||
|
|
||||||
|
// Handle ajax response. Expects HTTP OK (200) response with JSON object with suggestion(s) (array).
|
||||||
|
function _onLoad () { |
||||||
|
var t = this |
||||||
|
var awe = t.awe |
||||||
|
var xhr = t.xhr |
||||||
|
var queryVal = t.queryVal |
||||||
|
var val = awe.utilprops.val |
||||||
|
var data |
||||||
|
var prop |
||||||
|
if (xhr.status === 200) { |
||||||
|
data = JSON.parse(xhr.responseText) |
||||||
|
if (awe.utilprops.convertResponse) data = awe.utilprops.convertResponse(data) |
||||||
|
if (!Array.isArray(data)) { |
||||||
|
if (awe.utilprops.limit === 0 || awe.utilprops.limit === 1) { |
||||||
|
// if there is max 1 result expected, the array is not needed.
|
||||||
|
// Fur further processing, take the whole result and put it as one element in an array.
|
||||||
|
data = _isEmpty(data) ? [] : [data] |
||||||
|
} else { |
||||||
|
// search for the first property that contains an array
|
||||||
|
for (prop in data) { |
||||||
|
if (Array.isArray(data[prop])) { |
||||||
|
data = data[prop] |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// can only handle arrays
|
||||||
|
if (Array.isArray(data)) { |
||||||
|
// are we still interested in this response?
|
||||||
|
if (_ifNeedListUpdate(awe, val, queryVal)) { |
||||||
|
// accept the new suggestion list
|
||||||
|
_loadComplete(awe, data, queryVal || awe.utilprops.loadall) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Perform suggestion list lookup for the current value and validate. Use ajax when there is an url specified.
|
||||||
|
function _lookup (awe, val) { |
||||||
|
var xhr |
||||||
|
if (awe.utilprops.url) { |
||||||
|
// are we still interested in this response?
|
||||||
|
if (_ifNeedListUpdate(awe, val, val)) { |
||||||
|
xhr = new XMLHttpRequest() |
||||||
|
awe.utilprops.ajax.call(awe, |
||||||
|
awe.utilprops.url, |
||||||
|
awe.utilprops.urlEnd, |
||||||
|
awe.utilprops.loadall ? '' : val, |
||||||
|
_onLoad.bind({awe: awe, xhr: xhr, queryVal: val}), |
||||||
|
xhr |
||||||
|
) |
||||||
|
} else { |
||||||
|
_matchValue(awe, awe.utilprops.prepop) |
||||||
|
} |
||||||
|
} else { |
||||||
|
_matchValue(awe, awe.utilprops.prepop) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Restart autocomplete search: clear css classes and send match-event with empty list.
|
||||||
|
function _restart (awe) { |
||||||
|
var elem = awe.input |
||||||
|
var classList = elem.classList |
||||||
|
// IE11 only handles the first parameter of the remove method.
|
||||||
|
classList.remove(_CLS_NOT_FOUND) |
||||||
|
classList.remove(_CLS_FOUND) |
||||||
|
_fire(elem, _AWE_MATCH, []) |
||||||
|
} |
||||||
|
|
||||||
|
// handle new input value
|
||||||
|
function _update (awe, val, prepop) { |
||||||
|
// prepop parameter is optional. Default value is false.
|
||||||
|
awe.utilprops.prepop = prepop || false |
||||||
|
// if value changed
|
||||||
|
if (awe.utilprops.val !== val) { |
||||||
|
// new value, clear previous selection
|
||||||
|
awe.utilprops.selected = null |
||||||
|
// yes, user made a change
|
||||||
|
awe.utilprops.changed = true |
||||||
|
awe.utilprops.val = val |
||||||
|
// value is empty or smaller than minChars
|
||||||
|
if (val.length < awe.minChars || val.length === 0) { |
||||||
|
// restart autocomplete search
|
||||||
|
_restart(awe) |
||||||
|
} |
||||||
|
if (val.length >= awe.minChars) { |
||||||
|
// lookup suggestions and validate input
|
||||||
|
_lookup(awe, val) |
||||||
|
} |
||||||
|
} |
||||||
|
return awe |
||||||
|
} |
||||||
|
|
||||||
|
// handle input changed event for THIS awesomplete object
|
||||||
|
function _onInput (e) { |
||||||
|
var awe = this |
||||||
|
var val |
||||||
|
if (e.target === awe.input) { |
||||||
|
// lowercase and trim input value
|
||||||
|
val = awe.utilprops.convertInput.call(awe, awe.input.value) |
||||||
|
_update(awe, val) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// item function (as specified in Awesomplete) which just creates the 'li' HTML tag.
|
||||||
|
function _item (html /* , input */) { |
||||||
|
return $.create('li', { |
||||||
|
innerHTML: html, |
||||||
|
'aria-selected': 'false' |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// Escape HTML characters in text.
|
||||||
|
function _htmlEscape (text) { |
||||||
|
return text.replace('&', '&').replace('<', '<').replace('>', '>') |
||||||
|
} |
||||||
|
|
||||||
|
// Function to copy a field from the selected autocomplete item to another DOM element.
|
||||||
|
function _copyFun (e) { |
||||||
|
var t = this |
||||||
|
var sourceId = t.sourceId |
||||||
|
var dataField = t.dataField |
||||||
|
var targetId = t.targetId |
||||||
|
var elem |
||||||
|
var val |
||||||
|
if (e.target === $(sourceId)) { |
||||||
|
if (typeof targetId === 'function') { |
||||||
|
targetId(e, dataField) |
||||||
|
} else { |
||||||
|
// lookup target element if it isn't resolved yet
|
||||||
|
elem = $(targetId) |
||||||
|
// don't override target inputs if user is currently editing it.
|
||||||
|
if (elem && elem !== document.activeElement) { |
||||||
|
// event must contain 1 item from suggestion list
|
||||||
|
val = Array.isArray(e.detail) && e.detail.length === 1 ? e.detail[0] : null |
||||||
|
// if a datafield is specified, take that value
|
||||||
|
val = (dataField && val ? val[dataField] : val) || '' |
||||||
|
// if it is an input control
|
||||||
|
if (typeof elem.value !== 'undefined') { |
||||||
|
// set new value
|
||||||
|
elem.value = val |
||||||
|
// not really sure if it is an input control, check if it has a classList
|
||||||
|
if (elem.classList && elem.classList.remove) { |
||||||
|
// it might be another awesomplete control, if so the input is not wrong anymore because it's changed now
|
||||||
|
elem.classList.remove(_CLS_NOT_FOUND) |
||||||
|
} |
||||||
|
} else if (typeof elem.src !== 'undefined') { /* is it an image tag? */ |
||||||
|
elem.src = val |
||||||
|
} else { |
||||||
|
// use innerHTML to set the new value, because value might intentionally contain HTML markup
|
||||||
|
elem.innerHTML = val |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// click function for the combobox button
|
||||||
|
function _clickFun (e) { |
||||||
|
var t = this |
||||||
|
var awe |
||||||
|
var minChars |
||||||
|
if (e.target === $(t.btnId)) { |
||||||
|
e.preventDefault() |
||||||
|
awe = t.awe |
||||||
|
// toggle open/close
|
||||||
|
if (awe.ul.childNodes.length === 0 || awe.ul.hasAttribute('hidden')) { |
||||||
|
minChars = awe.minChars |
||||||
|
// ignore that the input value is empty
|
||||||
|
awe.minChars = 0 |
||||||
|
// show the suggestion list
|
||||||
|
awe.evaluate() |
||||||
|
awe.minChars = minChars |
||||||
|
} else { |
||||||
|
awe.close() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Return text with mark tags arround matching input. Don't replace inside <HTML> tags.
|
||||||
|
// When startsWith is true, mark only the matching begin text.
|
||||||
|
function _mark (text, input, startsWith) { |
||||||
|
var searchText = $.regExpEscape(_htmlEscape(input).trim()) |
||||||
|
var regExp = searchText.length <= 0 ? null : startsWith ? RegExp('^' + searchText, 'i') : RegExp('(?!<[^>]+?>)' + searchText + '(?![^<]*?>)', 'gi') |
||||||
|
return text.replace(regExp, '<mark>$&</mark>') |
||||||
|
} |
||||||
|
|
||||||
|
// Recursive jsonFlatten function
|
||||||
|
function _jsonFlatten (result, cur, prop, level, opts) { |
||||||
|
var root = opts.root /* filter resulting json tree on root property (optional) */ |
||||||
|
var value = opts.value /* search for this property and copy it's value to a new 'value' property |
||||||
|
(optional, do not specify it if the json array contains plain strings) */ |
||||||
|
var label = opts.label || opts.value /* search this property and copy it's value to a new 'label' property. |
||||||
|
If there is a 'opts.value' field but no 'opts.label', assume label is the same. */ |
||||||
|
var isEmpty = true |
||||||
|
var arrayResult = [] |
||||||
|
var j |
||||||
|
// at top level, look if there is a property which starts with root (if specified)
|
||||||
|
if (level === 0 && root && prop && (prop + '.').lastIndexOf(root + '.', 0) !== 0 && (root + '.').lastIndexOf(prop + '.', 0) !== 0) { |
||||||
|
return result |
||||||
|
} |
||||||
|
// handle current part of the json tree
|
||||||
|
if (Object(cur) !== cur) { |
||||||
|
if (prop) { |
||||||
|
result[prop] = cur |
||||||
|
} else { |
||||||
|
result = cur |
||||||
|
} |
||||||
|
} else if (Array.isArray(cur)) { |
||||||
|
for (j = 0; j < cur.length; j++) { |
||||||
|
arrayResult.push(_jsonFlatten({}, cur[j], '', level + 1, opts)) |
||||||
|
} |
||||||
|
if (prop) { |
||||||
|
result[prop] = arrayResult |
||||||
|
} else { |
||||||
|
result = arrayResult |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (j in cur) { |
||||||
|
isEmpty = false |
||||||
|
_jsonFlatten(result, cur[j], prop ? prop + '.' + j : j, level, opts) |
||||||
|
} |
||||||
|
if (isEmpty && prop) result[prop] = {} |
||||||
|
} |
||||||
|
// for arrays at top and subtop level
|
||||||
|
if (level < 2 && prop) { |
||||||
|
// if a 'value' is specified and found a mathing property, create extra 'value' property.
|
||||||
|
if (value && (prop + '.').lastIndexOf(value + '.', 0) === 0) { result['value'] = result[prop] } |
||||||
|
// if a 'label' is specified and found a mathing property, create extra 'label' property.
|
||||||
|
if (label && (prop + '.').lastIndexOf(label + '.', 0) === 0) { result['label'] = result[prop] } |
||||||
|
} |
||||||
|
if (level === 0) { |
||||||
|
// Make sure that both value and label properties exist, even if they are nil.
|
||||||
|
// This is handy with limit 0 or 1 when the result doesn't have to contain an array.
|
||||||
|
if (value && !('value' in result)) { result['value'] = null } |
||||||
|
if (label && !('label' in result)) { result['label'] = null } |
||||||
|
} |
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
// Stop AwesompleteUtil; detach event handlers from the Awesomplete object.
|
||||||
|
function _detach () { |
||||||
|
var t = this |
||||||
|
var elem = t.awe.input |
||||||
|
var boundMatch = t.boundMatch |
||||||
|
var boundOnInput = t.boundOnInput |
||||||
|
var boundOnKeydown = t.boundOnKeydown |
||||||
|
var boundSelect = t.boundSelect |
||||||
|
|
||||||
|
elem.removeEventListener(_AWE_SELECT, boundSelect) |
||||||
|
elem.removeEventListener(_AWE_LOAD, boundMatch) |
||||||
|
elem.removeEventListener(_AWE_CLOSE, boundMatch) |
||||||
|
elem.removeEventListener('blur', boundMatch) |
||||||
|
elem.removeEventListener('input', boundOnInput) |
||||||
|
elem.removeEventListener('keydown', boundOnKeydown) |
||||||
|
} |
||||||
|
|
||||||
|
//
|
||||||
|
// public methods
|
||||||
|
//
|
||||||
|
|
||||||
|
return { |
||||||
|
|
||||||
|
// ajax call for url + val + urlEnd. fn is the callback function. xhr parameter is optional.
|
||||||
|
ajax: function (url, urlEnd, val, fn, xhr) { |
||||||
|
xhr = xhr || new XMLHttpRequest() |
||||||
|
xhr.open('GET', url + encodeURIComponent(val) + (urlEnd || '')) |
||||||
|
xhr.onload = fn |
||||||
|
xhr.send() |
||||||
|
return xhr |
||||||
|
}, |
||||||
|
|
||||||
|
// Convert input before comparing it with suggestion. lowercase and trim the text
|
||||||
|
convertInput: function (text) { |
||||||
|
return typeof text === 'string' ? text.trim().toLowerCase() : '' |
||||||
|
}, |
||||||
|
|
||||||
|
// item function as defined in Awesomplete.
|
||||||
|
// item(html, input). input is optional and ignored in this implementation
|
||||||
|
item: _item, |
||||||
|
|
||||||
|
// Set a new suggestion list. Trigger loadcomplete event.
|
||||||
|
// load(awesomplete, list, queryVal)
|
||||||
|
load: _loadComplete, |
||||||
|
|
||||||
|
// Return text with mark tags arround matching input. Don't replace inside <HTML> tags.
|
||||||
|
// When startsWith is true, mark only the matching begin text.
|
||||||
|
// mark(text, input, startsWith)
|
||||||
|
mark: _mark, |
||||||
|
|
||||||
|
// highlight items: Marks input in the first line, not in the optional description
|
||||||
|
itemContains: function (text, input) { |
||||||
|
var arr |
||||||
|
if (input.trim().length > 0) { |
||||||
|
arr = ('' + text).split(/<p>/) |
||||||
|
arr[0] = _mark(arr[0], input) |
||||||
|
text = arr.join('<p>') |
||||||
|
} |
||||||
|
return _item(text, input) |
||||||
|
}, |
||||||
|
|
||||||
|
// highlight items: mark all occurrences of the input text
|
||||||
|
itemMarkAll: function (text, input) { |
||||||
|
return _item(input.trim() === '' ? '' + text : _mark('' + text, input), input) |
||||||
|
}, |
||||||
|
|
||||||
|
// highlight items: mark input in the begin text
|
||||||
|
itemStartsWith: function (text, input) { |
||||||
|
return _item(input.trim() === '' ? '' + text : _mark('' + text, input, true), input) |
||||||
|
}, |
||||||
|
|
||||||
|
// create Awesomplete object for input control elemId. opts are passed unchanged to Awesomplete.
|
||||||
|
create: function (elemId, utilOpts, opts) { |
||||||
|
opts.item = opts.item || this.itemContains /* by default uses itemContains, can be overriden */ |
||||||
|
var awe = new Awesomplete(elemId, opts) |
||||||
|
awe.utilprops = utilOpts || {} |
||||||
|
// loadall is true if there is no url (there is a static data-list)
|
||||||
|
if (!awe.utilprops.url && typeof awe.utilprops.loadall === 'undefined') { |
||||||
|
awe.utilprops.loadall = true |
||||||
|
} |
||||||
|
awe.utilprops.ajax = awe.utilprops.ajax || this.ajax /* default ajax function can be overriden */ |
||||||
|
awe.utilprops.convertInput = awe.utilprops.convertInput || this.convertInput /* the same applies for convertInput */ |
||||||
|
return awe |
||||||
|
}, |
||||||
|
|
||||||
|
// attach Awesomplete object to event listeners
|
||||||
|
attach: function (awe) { |
||||||
|
var elem = awe.input |
||||||
|
var boundMatch = _match.bind(awe) |
||||||
|
var boundOnKeydown = _onKeydown.bind(awe) |
||||||
|
var boundOnInput = _onInput.bind(awe) |
||||||
|
var boundSelect = _select.bind(awe) |
||||||
|
var boundDetach = _detach.bind({awe: awe, |
||||||
|
boundMatch: boundMatch, |
||||||
|
boundOnInput: boundOnInput, |
||||||
|
boundOnKeydown: boundOnKeydown, |
||||||
|
boundSelect: boundSelect |
||||||
|
}) |
||||||
|
var events = { |
||||||
|
'keydown': boundOnKeydown, |
||||||
|
'input': boundOnInput |
||||||
|
} |
||||||
|
events['blur'] = events[_AWE_CLOSE] = events[_AWE_LOAD] = boundMatch |
||||||
|
events[_AWE_SELECT] = boundSelect |
||||||
|
$.bind(elem, events) |
||||||
|
|
||||||
|
awe.utilprops.detach = boundDetach |
||||||
|
// Perform ajax call if prepop is true and there is an initial input value, or when all values must be loaded (loadall)
|
||||||
|
if (awe.utilprops.prepop && (awe.utilprops.loadall || elem.value.length > 0)) { |
||||||
|
awe.utilprops.val = awe.utilprops.convertInput.call(awe, elem.value) |
||||||
|
_lookup(awe, awe.utilprops.val) |
||||||
|
} |
||||||
|
return awe |
||||||
|
}, |
||||||
|
|
||||||
|
// update input value via javascript. Use prepop=true when this is an initial/prepopulation value.
|
||||||
|
update: function (awe, value, prepop) { |
||||||
|
awe.input.value = value |
||||||
|
return _update(awe, value, prepop) |
||||||
|
}, |
||||||
|
|
||||||
|
// create and attach Awesomplete object for input control elemId. opts are passed unchanged to Awesomplete.
|
||||||
|
start: function (elemId, utilOpts, opts) { |
||||||
|
return this.attach(this.create(elemId, utilOpts, opts)) |
||||||
|
}, |
||||||
|
|
||||||
|
// Stop AwesompleteUtil; detach event handlers from the Awesomplete object.
|
||||||
|
detach: function (awe) { |
||||||
|
if (awe.utilprops.detach) { |
||||||
|
awe.utilprops.detach() |
||||||
|
delete awe.utilprops.detach |
||||||
|
} |
||||||
|
return awe |
||||||
|
}, |
||||||
|
|
||||||
|
// Create function to copy a field from the selected autocomplete item to another DOM element.
|
||||||
|
// dataField can be null.
|
||||||
|
createCopyFun: function (sourceId, dataField, targetId) { |
||||||
|
return _copyFun.bind({sourceId: sourceId, dataField: dataField, targetId: $(targetId) || targetId}) |
||||||
|
}, |
||||||
|
|
||||||
|
// attach copy function to event listeners. prepop is optional and by default true.
|
||||||
|
// if true the copy function will also listen to awesomplete-prepop events.
|
||||||
|
// The optional listenEl is the element that listens, defaults to document.body.
|
||||||
|
attachCopyFun: function (fun, prepop, listenEl) { |
||||||
|
// prepop parameter defaults to true
|
||||||
|
prepop = typeof prepop === 'boolean' ? prepop : true |
||||||
|
listenEl = listenEl || document.body |
||||||
|
listenEl.addEventListener(_AWE_MATCH, fun) |
||||||
|
if (prepop) listenEl.addEventListener(_AWE_PREPOP, fun) |
||||||
|
return fun |
||||||
|
}, |
||||||
|
|
||||||
|
// Create and attach copy function.
|
||||||
|
startCopy: function (sourceId, dataField, targetId, prepop) { |
||||||
|
var sourceEl = $(sourceId) |
||||||
|
return this.attachCopyFun(this.createCopyFun(sourceEl || sourceId, dataField, targetId), prepop, sourceEl) |
||||||
|
}, |
||||||
|
|
||||||
|
// Stop copy function. Detach it from event listeners.
|
||||||
|
// The optional listenEl must be the same element that was used during startCopy/attachCopyFun;
|
||||||
|
// in general: Awesomplete.$(sourceId). listenEl defaults to document.body.
|
||||||
|
detachCopyFun: function (fun, listenEl) { |
||||||
|
listenEl = listenEl || document.body |
||||||
|
listenEl.removeEventListener(_AWE_PREPOP, fun) |
||||||
|
listenEl.removeEventListener(_AWE_MATCH, fun) |
||||||
|
return fun |
||||||
|
}, |
||||||
|
|
||||||
|
// Create function for combobox button (btnId) to toggle dropdown list.
|
||||||
|
createClickFun: function (btnId, awe) { |
||||||
|
return _clickFun.bind({btnId: btnId, awe: awe}) |
||||||
|
}, |
||||||
|
|
||||||
|
// Attach click function for combobox to click event.
|
||||||
|
// The optional listenEl is the element that listens, defaults to document.body.
|
||||||
|
attachClickFun: function (fun, listenEl) { |
||||||
|
listenEl = listenEl || document.body |
||||||
|
listenEl.addEventListener('click', fun) |
||||||
|
return fun |
||||||
|
}, |
||||||
|
|
||||||
|
// Create and attach click function for combobox button. Toggles open/close of suggestion list.
|
||||||
|
startClick: function (btnId, awe) { |
||||||
|
var btnEl = $(btnId) |
||||||
|
return this.attachClickFun(this.createClickFun(btnEl || btnId, awe), btnEl) |
||||||
|
}, |
||||||
|
|
||||||
|
// Stop click function. Detach it from event listeners.
|
||||||
|
// The optional listenEl must be the same element that was used during startClick/attachClickFun;
|
||||||
|
// in general: Awesomplete.$(btnId). listenEl defaults to document.body.
|
||||||
|
detachClickFun: function (fun, listenEl) { |
||||||
|
listenEl = listenEl || document.body |
||||||
|
listenEl.removeEventListener('click', fun) |
||||||
|
return fun |
||||||
|
}, |
||||||
|
|
||||||
|
// filter function as specified in Awesomplete. Filters suggestion list on items containing input value.
|
||||||
|
// Awesomplete.FILTER_CONTAINS filters on data.label, however
|
||||||
|
// this function filters on value and not on the shown label which may contain markup.
|
||||||
|
filterContains: function (data, input) { |
||||||
|
return Awesomplete.FILTER_CONTAINS(data.value, input) |
||||||
|
}, |
||||||
|
|
||||||
|
// filter function as specified in Awesomplete. Filters suggestion list on matching begin text.
|
||||||
|
// Awesomplete.FILTER_STARTSWITH filters on data.label, however
|
||||||
|
// this function filters on value and not on the shown label which may contain markup.
|
||||||
|
filterStartsWith: function (data, input) { |
||||||
|
return Awesomplete.FILTER_STARTSWITH(data.value, input) |
||||||
|
}, |
||||||
|
|
||||||
|
// Flatten JSON.
|
||||||
|
// { "a":{"b":{"c":[{"d":{"e":1}}]}}} becomes {"a.b.c":[{"d.e":1}]}.
|
||||||
|
// This function can be bind to configure it with extra options;
|
||||||
|
// bind({root: '<root path>', value: '<value property>', label: '<label property>'})
|
||||||
|
jsonFlatten: function (data) { |
||||||
|
// start json tree recursion
|
||||||
|
return _jsonFlatten({}, data, '', 0, this) |
||||||
|
} |
||||||
|
} |
||||||
|
}()) |
@ -0,0 +1,2 @@ |
|||||||
|
import 'awesomplete/awesomplete.css' |
||||||
|
import 'awesomplete' |
@ -1,20 +1,17 @@ |
|||||||
import $ from 'jquery' |
import $ from 'jquery' |
||||||
|
|
||||||
const tokenTransferToggle = (element) => { |
$(document.body).on('click', '[data-selector="token-transfer-open"]', event => { |
||||||
const $element = $(element) |
const $tokenTransferOpen = event.target |
||||||
const $tokenTransferClose = $element.find("[data-selector='token-transfer-close']") |
const $parent = $tokenTransferOpen.parentElement |
||||||
const $tokenTransferOpen = $element.find("[data-selector='token-transfer-open']") |
const $tokenTransferClose = $parent.querySelector("[data-selector='token-transfer-close']") |
||||||
|
$tokenTransferOpen.classList.add('d-none') |
||||||
|
$tokenTransferClose.classList.remove('d-none') |
||||||
|
}) |
||||||
|
|
||||||
$element.on('show.bs.collapse', () => { |
$(document.body).on('click', '[data-selector="token-transfer-close"]', event => { |
||||||
$tokenTransferOpen.addClass('d-none') |
const $tokenTransferClose = event.target |
||||||
$tokenTransferClose.removeClass('d-none') |
const $parent = $tokenTransferClose.parentElement |
||||||
}) |
const $tokenTransferOpen = $parent.querySelector("[data-selector='token-transfer-open']") |
||||||
|
$tokenTransferClose.classList.add('d-none') |
||||||
$element.on('hide.bs.collapse', () => { |
$tokenTransferOpen.classList.remove('d-none') |
||||||
$tokenTransferClose.addClass('d-none') |
}) |
||||||
$tokenTransferOpen.removeClass('d-none') |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
// Initialize the script scoped for each card.
|
|
||||||
$("[data-selector='token-transfers-toggle']").each((_index, element) => tokenTransferToggle(element)) |
|
||||||
|
@ -1,5 +1,5 @@ |
|||||||
import $ from 'jquery' |
import $ from 'jquery' |
||||||
|
|
||||||
$(function () { |
$(function () { |
||||||
$('[data-toggle="tooltip"]').tooltip() |
$('body').tooltip({ selector: '[data-toggle="tooltip"]' }) |
||||||
}) |
}) |
||||||
|
@ -0,0 +1,70 @@ |
|||||||
|
import $ from 'jquery' |
||||||
|
|
||||||
|
function composeCurlCommand (data) { |
||||||
|
return `curl -H "content-type: application/json" -X POST --data '${JSON.stringify(data)}'` |
||||||
|
} |
||||||
|
|
||||||
|
function handleResponse (data, xhr, clickedButton) { |
||||||
|
const module = clickedButton.attr('data-module') |
||||||
|
const action = clickedButton.attr('data-action') |
||||||
|
const curl = $(`[data-selector="${module}-${action}-curl"]`)[0] |
||||||
|
const code = $(`[data-selector="${module}-${action}-server-response-code"]`)[0] |
||||||
|
const body = $(`[data-selector="${module}-${action}-server-response-body"]`)[0] |
||||||
|
|
||||||
|
curl.innerHTML = composeCurlCommand(data) |
||||||
|
code.innerHTML = xhr.status |
||||||
|
body.innerHTML = JSON.stringify(xhr.responseJSON, undefined, 2) |
||||||
|
$(`[data-selector="${module}-${action}-try-api-ui-result"]`).show() |
||||||
|
$(`[data-selector="${module}-${action}-btn-try-api-clear"]`).show() |
||||||
|
clickedButton.html(clickedButton.data('original-text')) |
||||||
|
clickedButton.prop('disabled', false) |
||||||
|
} |
||||||
|
|
||||||
|
function wrapJsonRpc (method, params) { |
||||||
|
return { |
||||||
|
id: 0, |
||||||
|
jsonrpc: '2.0', |
||||||
|
method: method, |
||||||
|
params: params |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function parseInput (input) { |
||||||
|
const type = $(input).attr('data-parameter-type') |
||||||
|
const value = $(input).val() |
||||||
|
|
||||||
|
switch (type) { |
||||||
|
case 'string': |
||||||
|
return value |
||||||
|
case 'json': |
||||||
|
return JSON.parse(value) |
||||||
|
default: |
||||||
|
return value |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$('button[data-try-eth-api-ui-button-type="execute"]').click(event => { |
||||||
|
const clickedButton = $(event.target) |
||||||
|
const module = clickedButton.attr('data-module') |
||||||
|
const action = clickedButton.attr('data-action') |
||||||
|
const inputs = $(`input[data-selector="${module}-${action}-try-api-ui"]`) |
||||||
|
const params = $.map(inputs, parseInput) |
||||||
|
const formData = wrapJsonRpc(action, params) |
||||||
|
console.log(formData) |
||||||
|
const loadingText = '<span class="loading-spinner-small mr-2"><span class="loading-spinner-block-1"></span><span class="loading-spinner-block-2"></span></span> Loading...' |
||||||
|
|
||||||
|
clickedButton.prop('disabled', true) |
||||||
|
clickedButton.data('original-text', clickedButton.html()) |
||||||
|
|
||||||
|
if (clickedButton.html() !== loadingText) { |
||||||
|
clickedButton.html(loadingText) |
||||||
|
} |
||||||
|
|
||||||
|
$.ajax({ |
||||||
|
url: '/api/eth_rpc', |
||||||
|
type: 'POST', |
||||||
|
data: JSON.stringify(formData), |
||||||
|
dataType: 'json', |
||||||
|
contentType: 'application/json; charset=utf-8' |
||||||
|
}).then((_data, _status, xhr) => handleResponse(formData, xhr, clickedButton)) |
||||||
|
}) |
@ -0,0 +1 @@ |
|||||||
|
import '../../css/stakes.scss' |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,73 @@ |
|||||||
|
defmodule RPCTranslatorForwarder do |
||||||
|
@moduledoc """ |
||||||
|
Phoenix router limits forwarding, |
||||||
|
so this module is to forward old paths for backward compatibility |
||||||
|
""" |
||||||
|
alias BlockScoutWeb.API.RPC.RPCTranslator |
||||||
|
defdelegate init(opts), to: RPCTranslator |
||||||
|
defdelegate call(conn, opts), to: RPCTranslator |
||||||
|
end |
||||||
|
|
||||||
|
defmodule BlockScoutWeb.ApiRouter do |
||||||
|
@moduledoc """ |
||||||
|
Router for API |
||||||
|
""" |
||||||
|
use BlockScoutWeb, :router |
||||||
|
|
||||||
|
pipeline :api do |
||||||
|
plug(:accepts, ["json"]) |
||||||
|
end |
||||||
|
|
||||||
|
scope "/v1", BlockScoutWeb.API.V1, as: :api_v1 do |
||||||
|
pipe_through(:api) |
||||||
|
get("/health", HealthController, :health) |
||||||
|
|
||||||
|
if Application.get_env(:block_scout_web, __MODULE__)[:writing_enabled] do |
||||||
|
post("/decompiled_smart_contract", DecompiledSmartContractController, :create) |
||||||
|
post("/verified_smart_contracts", VerifiedSmartContractController, :create) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do |
||||||
|
scope "/" do |
||||||
|
alias BlockScoutWeb.API.{RPC, V1} |
||||||
|
pipe_through(:api) |
||||||
|
|
||||||
|
scope "/v1", as: :api_v1 do |
||||||
|
get("/supply", V1.SupplyController, :supply) |
||||||
|
post("/eth_rpc", RPC.EthController, :eth_request) |
||||||
|
end |
||||||
|
|
||||||
|
# For backward compatibility. Should be removed |
||||||
|
post("/eth_rpc", RPC.EthController, :eth_request) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
scope "/" do |
||||||
|
pipe_through(:api) |
||||||
|
alias BlockScoutWeb.API.RPC |
||||||
|
|
||||||
|
scope "/v1", as: :api_v1 do |
||||||
|
forward("/", RPC.RPCTranslator, %{ |
||||||
|
"block" => {RPC.BlockController, []}, |
||||||
|
"account" => {RPC.AddressController, []}, |
||||||
|
"logs" => {RPC.LogsController, []}, |
||||||
|
"token" => {RPC.TokenController, []}, |
||||||
|
"stats" => {RPC.StatsController, []}, |
||||||
|
"contract" => {RPC.ContractController, [:verify]}, |
||||||
|
"transaction" => {RPC.TransactionController, []} |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
# For backward compatibility. Should be removed |
||||||
|
forward("/", RPCTranslatorForwarder, %{ |
||||||
|
"block" => {RPC.BlockController, []}, |
||||||
|
"account" => {RPC.AddressController, []}, |
||||||
|
"logs" => {RPC.LogsController, []}, |
||||||
|
"token" => {RPC.TokenController, []}, |
||||||
|
"stats" => {RPC.StatsController, []}, |
||||||
|
"contract" => {RPC.ContractController, [:verify]}, |
||||||
|
"transaction" => {RPC.TransactionController, []} |
||||||
|
}) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,12 @@ |
|||||||
|
defmodule BlockScoutWeb.Cldr do |
||||||
|
@moduledoc """ |
||||||
|
Cldr global configuration. |
||||||
|
""" |
||||||
|
|
||||||
|
use Cldr, |
||||||
|
default_locale: "en", |
||||||
|
locales: ["en"], |
||||||
|
gettext: BlockScoutWeb.Gettext, |
||||||
|
generate_docs: false, |
||||||
|
providers: [Cldr.Number, Cldr.Unit] |
||||||
|
end |
@ -0,0 +1,182 @@ |
|||||||
|
<div class="api-doc-list-item" > |
||||||
|
<div class="api-doc-list-item-contents" href="#<%= @action %>"> |
||||||
|
<div class="api-doc-list-item-description"> |
||||||
|
<h3 class="api-doc-list-item-title"><%= @action %></h3> |
||||||
|
<p class="api-doc-list-item-contents"><%= raw @info.notes %></p> |
||||||
|
<span class="api-doc-list-item-query api-text-monospace api-text-monospace-background btn" |
||||||
|
data-clipboard-text="curl -X POST --data '{"id":0,"jsonrpc":"2.0","method": "<%= @action %>", params: []}'" |
||||||
|
> |
||||||
|
curl -X POST --data '{"id":0,"jsonrpc":"2.0","method": "<%= @action %>", params: []}' |
||||||
|
</span> |
||||||
|
<p class="api-doc-list-item-text"> |
||||||
|
<div class="tile tile-muted p-1"> |
||||||
|
<pre |
||||||
|
class="m-2" |
||||||
|
data-json='<%= @info.example %>' |
||||||
|
></pre> |
||||||
|
</div> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
<div class="api-doc-list-item-controls" |
||||||
|
aria-controls="<%= @action %>" |
||||||
|
aria-expanded="false" |
||||||
|
data-toggle="collapse" |
||||||
|
href="#<%= @action %>"> |
||||||
|
<div class="api-doc-list-item-controls-badges"> |
||||||
|
<span class="badge badge-neutral api-badge"><%= gettext "POST" %></span> |
||||||
|
</div> |
||||||
|
<span class="api-doc-list-item-controls-view-more"> |
||||||
|
<span class="api-doc-list-item-controls-view-more-open">More Details <span class="fa fa-chevron-down"></span></span> |
||||||
|
<span class="api-doc-list-item-controls-view-more-close">Hide Details <span class="fa fa-chevron-up"></span></span> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<!-- Parameters --> |
||||||
|
<div |
||||||
|
class="collapse multi-collapse api-doc-parameters-container" |
||||||
|
id="<%= @action %>" |
||||||
|
> |
||||||
|
<h3 class="card-title margin-bottom-md"> |
||||||
|
<%= gettext "Parameters" %> |
||||||
|
<button |
||||||
|
class="btn-full-primary float-right" |
||||||
|
data-action="<%= @action %>" |
||||||
|
data-module="eth" |
||||||
|
data-selector='<%= "eth-#{@action}-btn-try-api" %>' |
||||||
|
role="button" |
||||||
|
><%= gettext "Try it out" %></button> |
||||||
|
<button |
||||||
|
class="collapse btn-line float-right" |
||||||
|
data-action="<%= @action %>" |
||||||
|
data-module="eth" |
||||||
|
data-selector='<%= "eth-#{@action}-btn-try-api-cancel" %>' |
||||||
|
role="button" |
||||||
|
><%= gettext "Cancel" %></button> |
||||||
|
</h3> |
||||||
|
<!-- Parameters description list --> |
||||||
|
<div class="api-doc-parameters-list"> |
||||||
|
<div class="row d-none d-md-flex"> |
||||||
|
<h4 class="col-2 api-doc-parameters-list-title"><%= gettext "Name" %></h4> |
||||||
|
<h3 class="col-10 api-doc-parameters-list-title"><%= gettext "Description" %></h3> |
||||||
|
</div> |
||||||
|
<!-- Params --> |
||||||
|
<%= for param <- @info.params do %> |
||||||
|
<div class="row api-doc-parameters-list-item"> |
||||||
|
<div class="col-sm-4 col-md-2"> |
||||||
|
<h5 class="api-doc-parameters-list-item-title"> |
||||||
|
<%= param.name %> |
||||||
|
<%= if param.required do %> |
||||||
|
<span class="align-text-bottom text-danger"> |
||||||
|
*<small><%= gettext "required" %></small> |
||||||
|
</span> |
||||||
|
<% end %> |
||||||
|
</h5> |
||||||
|
</div> |
||||||
|
<div class="col-sm-8 col-md-10"> |
||||||
|
<p class="api-doc-parameters-list-item-description"><%= param.description %></p> |
||||||
|
<input |
||||||
|
class="collapse form-control border-rounded <%= if param.required && !param.default, do: "form-control-danger is-invalid" %>" |
||||||
|
data-parameter-type='<%= param.type %>' |
||||||
|
data-required='<%= if param.required, do: "true", else: "false" %>' |
||||||
|
data-selector='<%= "eth-#{@action}-try-api-ui" %>' |
||||||
|
type="text", |
||||||
|
value='<%= param.default %>' |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<!-- Buttons for Other / Extra --> |
||||||
|
<div class="row"> |
||||||
|
<div class="offset-sm-4 offset-md-2 col-10"> |
||||||
|
<button |
||||||
|
class="collapse button button-primary" |
||||||
|
data-action="<%= @action %>" |
||||||
|
data-module="eth" |
||||||
|
data-selector='<%= "eth-#{@action}-try-api-ui" %>' |
||||||
|
data-try-eth-api-ui-button-type="execute" |
||||||
|
role="button" |
||||||
|
><%= gettext "Execute" %></button> |
||||||
|
<button |
||||||
|
class="collapse button button-secondary" |
||||||
|
data-action="<%= @action %>" |
||||||
|
data-module="eth" |
||||||
|
data-selector='<%= "eth-#{@action}-btn-try-api-clear" %>' |
||||||
|
role="button" |
||||||
|
><%= gettext "Clear" %></button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- CURL / Request URL / Server Response --> |
||||||
|
<div |
||||||
|
class="tile text-dark mt-5 collapse" |
||||||
|
data-selector='<%= "eth-#{@action}-try-api-ui-result" %>' |
||||||
|
> |
||||||
|
<div class="mb-3"> |
||||||
|
<h5 class="api-doc-parameters-list-item-title"><%= gettext "Curl" %></h5> |
||||||
|
<div class="tile tile-muted p-1"> |
||||||
|
<pre |
||||||
|
class="m-2" |
||||||
|
data-selector='<%= "eth-#{@action}-curl" %>' |
||||||
|
></pre> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<h5 class="api-doc-parameters-list-item-title"><%= gettext "Server Response" %></h5> |
||||||
|
<div class="row"> |
||||||
|
<h4 class="col-2 api-doc-parameters-list-title"><%= gettext "Code" %></h4> |
||||||
|
<h4 class="col-10 api-doc-parameters-list-title"><%= gettext "Details" %></h4> |
||||||
|
</div> |
||||||
|
<div class="row"> |
||||||
|
<div |
||||||
|
class="col-2 pr-0 pr-md-2 col-md-2" |
||||||
|
><strong data-selector='<%= "eth-#{@action}-server-response-code" %>'></strong></div> |
||||||
|
<div class="col-10 col-md-10"> |
||||||
|
<p class="api-doc-parameters-list-item-description"><%= gettext "Response Body" %></p> |
||||||
|
<div class="tile tile-muted p-1 card-server-response-body"> |
||||||
|
<pre |
||||||
|
class="m-2" |
||||||
|
data-selector='<%= "eth-#{@action}-server-response-body" %>' |
||||||
|
></pre> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- Responses --> |
||||||
|
<h3 class="card-title margin-bottom-md"><%= gettext "Responses" %></h3> |
||||||
|
<div class="row api-doc-parameters-list-item mb-0"> |
||||||
|
<h4 class="col-2 api-doc-parameters-list-title"><%= gettext "Code" %></h4> |
||||||
|
<h5 class="col-10 api-doc-parameters-list-title"><%= gettext "Description" %></h5> |
||||||
|
</div> |
||||||
|
<div class="row api-doc-parameters-list-item"> |
||||||
|
<div class="col-2 pr-0 pr-md-2"><strong>200</strong></div> |
||||||
|
<div class="col-10"> |
||||||
|
<div class="tile tile-muted p-1 mb-3"> |
||||||
|
<pre class="m-2"><strong>successful operation</strong></pre> |
||||||
|
</div> |
||||||
|
<!-- Tabs --> |
||||||
|
<ul |
||||||
|
class="nav nav-pills mb-3" |
||||||
|
role="tablist" |
||||||
|
> |
||||||
|
<li class="nav-item"> |
||||||
|
<a class="nav-link api-doc-tab active"><%= gettext "Example Value" %></a> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<!-- Tab Content --> |
||||||
|
<div class="tab-content"> |
||||||
|
<!-- Example Value Tab --> |
||||||
|
<div class="tab-pane fade show active"> |
||||||
|
<div class="tile tile-muted p-1"> |
||||||
|
<pre |
||||||
|
class="m-2" |
||||||
|
data-json='<%= @info.result %>' |
||||||
|
></pre> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue