Some initial cleanup changes for Moe/Ursula status pages now that the blockchain agent is being used.

remotes/upstream/doubtfire
derekpierre 2019-09-17 14:57:41 -04:00 committed by Kieran R. Prasch
parent 722ebc30eb
commit 268b811084
3 changed files with 71 additions and 64 deletions

View File

@ -36,6 +36,8 @@ flask-limiter = "*"
dash = {extras = ["testing"],version = "*"}
dash-core-components = "*"
dash-html-components = "*"
dash_daq = "*"
plotly = "3.10.0"
[dev-packages]
# Pytest

View File

@ -26,7 +26,7 @@ from nucypher.network.nodes import Learner
class NetworkStatusPage:
COLUMNS = ['Status', 'Icon', 'Checksum', 'Nickname', 'Timestamp', 'Last Seen', 'Fleet State']
NODE_TABLE_COLUMNS = ['Status', 'Icon', 'Checksum', 'Nickname', 'Timestamp', 'Last Seen', 'Fleet State']
def __init__(self, title: str, flask_server: Flask, route_url: str):
self.log = Logger(self.__class__.__name__)
@ -74,10 +74,10 @@ class NetworkStatusPage:
html.Span(state['updated'], className='small'),
], className='state')
def known_nodes(self, learner: Learner) -> html.Div:
def known_nodes(self, character: Character) -> html.Div:
nodes = list()
nodes_dict = learner.known_nodes.abridged_nodes_dict()
teacher_node = learner.current_teacher_node()
nodes_dict = character.known_nodes.abridged_nodes_dict()
teacher_node = character.current_teacher_node()
teacher_index = None
for checksum in nodes_dict:
node_data = nodes_dict[checksum]
@ -86,11 +86,38 @@ class NetworkStatusPage:
nodes.append(node_data)
return html.Div([
html.Div([self.nodes_table(nodes, teacher_index)], className='row')
html.Div([self.nodes_table(nodes, teacher_index, character.registry)],
className='row')
], className='row')
def nodes_table(self, nodes, teacher_index, registry) -> html.Table:
rows = []
for index, node_info in enumerate(nodes):
row = []
for col in self.NODE_TABLE_COLUMNS:
components = self.generate_node_table_components(node_info=node_info, registry=registry)
cell = components[col]
if cell:
row.append(cell)
style_dict = {'overflowY': 'scroll'}
# highlight teacher
if index == teacher_index:
style_dict['backgroundColor'] = '#1E65F3'
style_dict['color'] = 'white'
rows.append(html.Tr(row, style=style_dict, className='row'))
table = html.Table(
# header
[html.Tr([html.Th(col) for col in self.NODE_TABLE_COLUMNS], className='row')] +
rows,
id='node-table'
)
return table
@staticmethod
def generate_components(node_info: dict, registry):
def generate_node_table_components(node_info: dict, registry):
"""
Update this depending on which columns you want to show links for
and what you want those links to be.
@ -117,25 +144,9 @@ class NetworkStatusPage:
agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry)
current_period = agent.get_current_period()
last_confirmed_period = agent.get_last_active_period(node_info['staker_address'])
missing_confirmations = current_period - last_confirmed_period
worker = agent.get_worker_from_staker(node_info['staker_address'])
if worker == BlockchainInterface.NULL_ADDRESS:
missing_confirmations = BlockchainInterface.NULL_ADDRESS
color_codex = {-1: ('green', ''), # Confirmed Next Period
0: ('#e0b32d', 'Pending'), # Pending Confirmation of Next Period
current_period: ('#4d525ae3', 'Idle'), # Never confirmed
BlockchainInterface.NULL_ADDRESS: ('red', 'Headless') # Headless Staker (No Worker)
}
try:
color, status_message = color_codex[missing_confirmations]
except KeyError:
color, status_message = 'red', f'{missing_confirmations} Missed Confirmations'
status_cell = [daq.Indicator(id='Status', color=color, value=True), status_message]
status = html.Td(status_cell, className='status-indicator')
staker_address = node_info['staker_address']
last_confirmed_period = agent.get_last_active_period(staker_address)
status = create_status_component(agent, staker_address, current_period, last_confirmed_period)
etherscan_url = f'https://goerli.etherscan.io/address/{node_info["checksum_address"]}'
components = {
@ -152,6 +163,28 @@ class NetworkStatusPage:
return components
@staticmethod
def create_status_component(agent, staker_address, current_period, last_confirmed_period):
missing_confirmations = current_period - last_confirmed_period
worker = agent.get_worker_from_staker(staker_address)
if worker == BlockchainInterface.NULL_ADDRESS:
missing_confirmations = BlockchainInterface.NULL_ADDRESS
color_codex = {-1: ('green', ''), # Confirmed Next Period
0: ('#e0b32d', 'Pending'), # Pending Confirmation of Next Period
current_period: ('#4d525ae3', 'Idle'), # Never confirmed
BlockchainInterface.NULL_ADDRESS: ('red', 'Headless') # Headless Staker (No Worker)
}
try:
color, status_message = color_codex[missing_confirmations]
except KeyError:
color, status_message = 'red', f'{missing_confirmations} Missed Confirmations'
status_cell = [daq.Indicator(id='Status', color=color, value=True), status_message]
status = html.Td(status_cell, className='status-indicator')
return status
class MoeStatusPage(NetworkStatusPage):
"""
@ -240,7 +273,7 @@ class MoeStatusPage(NetworkStatusPage):
@self.dash_app.callback(Output('time-remaining', 'children'),
[Input('interval-component', 'n_intervals')])
def time_remaining(n):
tomorrow = datetime.now() + timedelta(1)
tomorrow = datetime.now() + timedelta(days=1)
midnight = datetime(year=tomorrow.year, month=tomorrow.month,
day=tomorrow.day, hour=0, minute=0, second=0)
seconds_remaining = MayaDT.from_datetime(midnight).slang_time()
@ -354,7 +387,7 @@ class MoeStatusPage(NetworkStatusPage):
title="Ursula Fleet Staking Schedule",
bar_width=0.3,
showgrid_x=True,
showgrid_y=True.bit_length())
showgrid_y=True)
fig['layout'].update(autosize=True,
width=None,
@ -369,33 +402,6 @@ class MoeStatusPage(NetworkStatusPage):
schedule_graph = dcc.Graph(figure=fig, id='llamas-graph', config=config)
return schedule_graph
def nodes_table(self, nodes, teacher_index) -> html.Table:
rows = []
for index, node_info in enumerate(nodes):
row = []
for col in self.COLUMNS:
components = self.generate_components(node_info=node_info, registry=self.moe.registry)
cell = components[col]
if cell:
row.append(cell)
style_dict = {'overflowY': 'scroll'}
# highlight teacher
if index == teacher_index:
style_dict['backgroundColor'] = '#1E65F3'
style_dict['color'] = 'white'
rows.append(html.Tr(row, style=style_dict, className='row'))
table = html.Table(
# header
[html.Tr([html.Th(col) for col in self.COLUMNS], className='row')] +
rows,
id='node-table'
)
return table
class UrsulaStatusPage(NetworkStatusPage):
"""
@ -421,16 +427,6 @@ class UrsulaStatusPage(NetworkStatusPage):
def header(pathname):
return self.header()
@self.dash_app.callback(Output('domains', 'children'), [Input('url', 'pathname')]) # on page-load
def domains(pathname):
domains = ''
for domain in ursula.learning_domains:
domains += f' | {domain} '
return html.Div([
html.H4('Domains', className='one column'),
html.H5(domains, className='eleven columns'),
], className='row')
@self.dash_app.callback(Output('ursula_info', 'children'), [Input('url', 'pathname')]) # on page-load
def ursula_info(pathname):
info = html.Div([
@ -445,6 +441,14 @@ class UrsulaStatusPage(NetworkStatusPage):
], className='row')
return info
@self.dash_app.callback(Output('domains', 'children'), [Input('url', 'pathname')]) # on page-load
def domains(pathname):
domains = ' | '.join(ursula.learning_domains)
return html.Div([
html.H4('Domains', className='one column'),
html.H5(domains, className='eleven columns'),
], className='row')
@self.dash_app.callback(Output('prev-states', 'children'), [Input('status-update', 'n_intervals')])
def state(n):
"""Simply update periodically"""

View File

@ -26,6 +26,7 @@ dash-html-components==1.0.1
dash-renderer==1.0.1
dash-table==4.2.0
dash[testing]==1.2.0
dash_daq==0.1.7
dateparser==0.7.1
eth-abi==2.0.0
eth-account==0.4.0