def generate_dashboard(self, title, charts, theme): """ layout 0 [1] """ tmpl = pn.Template(theme.layout_head + layout_0) tmpl.add_panel("title", '<div class="nav-title"> ' + str(title) + "</div>") num_of_charts_added = 0 widgets = pn.Column() for chart in charts.values(): if hasattr(chart, "apply_theme"): chart.apply_theme(theme.chart_properties) if ("widget" in chart.chart_type or chart.chart_type == "datasize_indicator"): chart.chart.sizing_mode = "scale_both" chart.chart.width = 280 widgets.append(chart.view()) continue num_of_charts_added += 1 if num_of_charts_added == 1: chart.chart.sizing_mode = "scale_both" chart.width = 1600 chart.height = int(round(90 * 1.0)) * 10 tmpl.add_panel("chart1", chart.view()) else: break tmpl.add_panel("widgets", widgets) return tmpl
def generate_dashboard(self, title, charts, theme): """ layout 7 [ 1 ] [2 3 4] """ tmpl = pn.Template(theme.layout_head + layout_7) tmpl.add_panel("title", '<div class="nav-title"> ' + str(title) + "</div>") num_of_charts_added = 0 widgets = pn.Column() for chart in charts.values(): if hasattr(chart, "apply_theme"): chart.apply_theme(theme.chart_properties) if ("widget" in chart.chart_type or chart.chart_type == "datasize_indicator"): chart.chart.sizing_mode = "scale_both" chart.chart.width = 280 widgets.append(chart.view()) continue num_of_charts_added += 1 if num_of_charts_added == 1: chart.chart.sizing_mode = "scale_both" chart.width = 1600 chart.height = 600 tmpl.add_panel("chart1", chart.view()) elif num_of_charts_added == 2: chart.chart.sizing_mode = "scale_both" chart.width = int(1600 / 3) chart.height = 300 tmpl.add_panel("chart2", chart.view()) elif num_of_charts_added == 3: chart.chart.sizing_mode = "scale_both" chart.width = int(1600 / 3) chart.height = 300 tmpl.add_panel("chart3", chart.view()) elif num_of_charts_added == 4: chart.chart.sizing_mode = "scale_both" chart.width = int(1600 / 3) chart.height = 300 tmpl.add_panel("chart4", chart.view()) else: break n = 4 - num_of_charts_added for i in range(n): chart = 4 - i tmpl.add_panel("chart" + str(chart), "") tmpl.add_panel("widgets", widgets) return tmpl
def compose(self, golden_layout: str) -> None: """ Creates a servable template from a golden layout js code string. :param golden_layout_string: Result of nesting stacks, columns, rows, and panels using the methods in this class. """ template = ClientSideCodeStrings.JINJA2_BASE % golden_layout self.app = pn.Template(template=template) for panel_ID, panel in self.panels.items(): self.app.add_panel(panel_ID, panel)
def render(self): template = pn.Template(self._template) template.add_variable("subtitle", "CHIME Daily Validation") template.add_variable("app_title", "BON DIA") template.add_variable("username", self.current_user) template.add_variable("num_unvalidated", 19) template.add_variable("root_url", self._root_url) return self.populate_template(template)
def compose(self, golden_layout: str) -> None: """ Creates a servable template from a golden layout js code string. Any GoldenPanel object needs to call compose exactly once to function as expected. :param golden_layout: Result of nesting stacks, columns, rows, and panels using the methods in this class. """ template = ClientSideCodeStrings.JINJA2_BASE % golden_layout self.app = pn.Template(template=template) for panel_ID, panel in self.panels.items(): self.app.add_panel(panel_ID, panel)
def main(): pn.config.raw_css.append(CSS) app_title = pn.Row( pn.layout.HSpacer(), pn.pane.Markdown(f"Bootstrap Dashboard"), pn.layout.HSpacer(), width=SIDEBAR_WIDTH, css_classes=["app-title"], ) header = pn.Row(app_title, pn.layout.HSpacer(), sizing_mode="stretch_width", css_classes=["header"]) sidebar = pn.Column( "Sidebar", pn.layout.HSpacer(height_policy="max"), height_policy="max", width=SIDEBAR_WIDTH, css_classes=["sidebar"], ) content = pn.Column(width_policy="max", margin=(25, 50, 25, 50), css_classes=["content"]) about = pn.layout.Row(pn.pane.Markdown(ABOUT)) image = pn.pane.PNG(IMAGE) info = pn.pane.Markdown(INFO, background="#d1ecf1") page = pn.Column(about, image, info, sizing_mode="stretch_width", css_classes=["about"]) content.append(page) body = pn.Column(header, pn.Row(sidebar, content), sizing_mode="stretch_width", background="darkgray") items = { "body": body, } template = pn.Template(template=TEMPLATE, items=items) template.servable()
def build_dashboard(tweets, predictions_streamz_df): """Build the dashboard. changes the css, styles and creates empty place holders for tables, tweets and graphs """ template = """ {% extends base %} <!-- goes in body --> {% block postamble %} <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.0/solar/bootstrap.min.css"> {% endblock %} <!-- goes in body --> {% block contents %} {{ app_title }} <p/> <p style="text-align:center;"> <img src="https://user-images.githubusercontent.com/4336187/87214331-6d9ef280-c2f9-11ea-9c87-231f5c828a4e.png" height='108'> </p> <br> <div class="container"> <div class="row"> <div class="col-sm"> {{ embed(roots.B) }} </div> </div> <div class="container"> <div class="row"> <div class="col-sm"> {{ embed(roots.C) }} </div> </div> </div> </div> {% endblock %} <div style="background:<%= (function colorfromint(){ if(cola > colb ){ return("green")} }()) %>; color: black"> <%= value %> </div> """ css = ''' .panel-widget-box { background: #f0f0f0; border-radius: 5px; border: 1px black solid; } ''' theme = Theme( json={ 'attrs': { 'Figure': { 'background_fill_color': 'black', 'border_fill_color': 'black', 'outline_line_color': '#444444', }, 'Grid': { 'grid_line_dash': [6, 4], 'grid_line_alpha': .3, }, 'Axis': { 'major_label_text_color': 'white', 'axis_label_text_color': 'white', 'major_tick_line_color': 'white', 'minor_tick_line_color': 'white', 'axis_line_color': "white" } } }) hv.renderer('bokeh').theme = theme dashboard = pn.Template(template) tweets_table = pn.Column("##### Live Tweet Sentiments:", tweets.hvplot.table( columns=[ 'created_at', 'user_name', 'tweets', 'sentiments', 'polarity' ], backlog=10, ).opts(bgcolor='blue', height=272), css_classes=['panel-widget-box']) price = pn.Column( "##### Pricing Model", predictions_streamz_df.hvplot.line(width=1400, grid=True, backlog=500, title="prices").opts( bgcolor='black', legend_position='right')) positive_cloud = pn.Column( "##### Postive Word Cloud:", pn.pane.PNG('Images/postive_sentiments.png', height=272)) negative_cloud = pn.Column( "##### Negative Word Cloud:", pn.pane.PNG('Images/negative_sentiments.png', height=272)) clouds = pn.Row(positive_cloud, negative_cloud) sentiments = pn.Row(tweets_table, clouds) # dashboard.add_panel('B',tweets_table) dashboard.add_panel('B', sentiments) dashboard.add_panel('C', price) return dashboard
def load_app(config_file): pn.config.sizing_mode = 'stretch_both' impact_hour_data_1, impact_hour_data_2 = read_impact_hour_data() impact_hours_data = ImpactHoursData() # ImpactHoursData i = ImpactHoursData() # TECH t = TECH(total_impact_hours=i.total_impact_hours, impact_hour_data=impact_hour_data_1, total_cstk_tokens=1000000, config=config_file['tech']) # ImpactHoursFormula #impact_hours_rewards = ImpactHoursFormula(i.total_impact_hours, impact_hour_data_1) #impact_rewards_view = pn.Column(impact_hours_rewards.impact_hours_rewards, # impact_hours_rewards.redeemable, # impact_hours_rewards.cultural_build_tribute) # Hatch cstk_data = read_cstk_data() #hatch = Hatch(cstk_data, impact_hours_rewards.target_raise, # i.total_impact_hours, # impact_hours_rewards.target_impact_hour_rate) # DandelionVoting dandelion = DandelionVoting(17e6, config=config_file['dandelion_voting']) # Import Params Button import_params_button = pn.widgets.Button(name='Import params', button_type='primary') import_description = pn.pane.Markdown( '<h4>To import the parameters, click on the button below:</h4>') # Share Button comments = pn.widgets.TextAreaInput( name='Comments', max_length=1024, placeholder='Explain your thoughts on why you choose the params...') share_button = pn.widgets.Button(name='Share your results on GitHub!', button_type='primary') url = pn.widgets.TextInput(name='URL', value='') share_button.js_on_click(args={'target': url}, code='window.open(target.value)') results_button = pn.widgets.Button(name='See your results', button_type='success') def update_params_by_url_query(): queries = curdoc().session_context.request.arguments queries = {i: j[0] for i, j in queries.items()} if queries: if 'ihminr' in queries: t.min_raise = int(queries['ihminr']) if 'ihmaxr' in queries: t.max_raise = int(queries['ihmaxr']) if 'hs' in queries: t.impact_hour_slope = float(queries['hs']) if 'maxihr' in queries: t.maximum_impact_hour_rate = float(queries['maxihr']) if 'ihtr' in queries: t.target_raise = int(queries['ihtr']) if 'hor' in queries: t.hatch_oracle_ratio = float(queries['hor']) if 'hpd' in queries: t.hatch_period_days = int(queries['hpd']) if 'her' in queries: t.hatch_exchange_rate = float(queries['her']) if 'ht' in queries: t.hatch_tribute_percentage = int(queries['ht']) if 'sr' in queries: dandelion.support_required_percentage = int(queries['sr']) if 'maq' in queries: dandelion.minimum_accepted_quorum_percentage = int( queries['maq']) if 'vdd' in queries: dandelion.vote_duration_days = int(queries['vdd']) if 'vbh' in queries: dandelion.vote_buffer_hours = int(queries['vbh']) if 'rqh' in queries: dandelion.rage_quit_hours = int(queries['rqh']) if 'tfx' in queries: dandelion.tollgate_fee_xdai = float(queries['tfx']) t.param.trigger('action') # Update dashboard @pn.depends(results_button) def update_result_score(results_button_on): data_table = { 'Parameters': [ "Target raise (wxDai)", "Maximum raise (wxDai)", "Minimum raise (wxDai)", "Impact hour slope (wxDai/IH)", "Maximum impact hour rate (wxDai/IH)", "Hatch oracle ratio (wxDai/CSTK)", "Hatch period (days)", "Hatch exchange rate (TECH/wxDai)", "Hatch tribute (%)", "Support required (%)", "Minimum accepted quorum (%)", "Vote duration (days)", "Vote buffer (hours)", "Rage quit (hours)", "Tollgate fee (wxDai)" ], 'Values': [ int(t.target_raise), int(t.max_raise), int(t.min_raise), t.impact_hour_slope, t.maximum_impact_hour_rate, t.hatch_oracle_ratio, t.hatch_period_days, t.hatch_exchange_rate, t.hatch_tribute_percentage, dandelion.support_required_percentage, dandelion.minimum_accepted_quorum_percentage, dandelion.vote_duration_days, dandelion.vote_buffer_hours, dandelion.rage_quit_hours, dandelion.tollgate_fee_xdai ] } df = pd.DataFrame(data=data_table) if results_button_on: # Define output pane output_pane = pn.Row( pn.Column(t.impact_hours_view, t.redeemable_plot, t.cultural_build_tribute_plot), pn.Column(dandelion.vote_pass_view, t.funding_pool_view)) output_pane.save('output.html') pn.panel(t.output_scenarios_out_issue().hvplot.table()).save( 'out_scenarios.html') scenarios = codecs.open("out_scenarios.html", 'r') charts = codecs.open("output.html", 'r') data_charts = { 'html': charts.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto" } data_scenarios = { 'html': scenarios.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto" } charts = requests.post(url=HCTI_API_ENDPOINT, data=data_charts, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) scenarios = requests.post(url=HCTI_API_ENDPOINT, data=data_scenarios, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) output_data = """ <h1>Output Charts</h1> ![image]({image_charts}) <h1>Output Scenarios</h1> ![image]({image_scenarios}) """.format(image_charts=charts.json()['url'], image_scenarios=scenarios.json()['url']) parameters_data = """ <h1>Parameters</h1> {params_table} """.format( params_table=df.to_markdown(index=False, floatfmt=",.2f")) string_data = """ <h1>Results</h1> <p>{comments}</p> - It costs {tollgate_fee_xdai} wxDAI to make a proposal. - Votes will be voted on for {vote_duration_days} days. - TECH token holders will have {rage_quit_hours} Hours to exit the DAO if they don't like the result of a vote (as long as they don't vote yes). - There will be a minimum of {vote_buffer_hours} hours between proposals so people can exit safely in weird edge case scenarios. - A proposal that passes can be executed {proposal_execution_hours} hours after it was proposed. - A CSTK Token holder that has 2000 CSTK can send a max of {max_wxdai_ratio} wxDai to the Hatch. Play with my parameters [here]({url}?ihminr={ihf_minimum_raise}&hs={hour_slope}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}). """.format(comments=comments.value, tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), hour_slope=t.impact_hour_slope, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion. minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, proposal_execution_hours=dandelion.vote_buffer_hours + dandelion.rage_quit_hours, max_wxdai_ratio=int(2000 * t.hatch_oracle_ratio), url=config_file['url']) markdown_panel = pn.pane.Markdown(parameters_data + string_data + output_data) body = urllib.parse.quote(markdown_panel.object, safe='') url.value = config_file[ 'repo'] + "/issues/new?title=Vote%20for%20My%20Params&labels=" + config_file[ 'label'] + "&body=" + body results_button.name = "Update your results" else: string_data = "" markdown_panel = pn.pane.Markdown(string_data) return pn.Row(df.hvplot.table(), markdown_panel) pn.state.onload(update_params_by_url_query) # Front-end tmpl = pn.Template(template=template) tmpl.add_variable('app_title', config_file['title']) tmpl.add_panel('A', i.impact_hours_accumulation) tmpl.add_panel('B', t) tmpl.add_panel('C', t.funding_pool_data_view) tmpl.add_panel('E', t.payout_view) tmpl.add_panel( 'D', pn.Column(t.impact_hours_view, t.redeemable_plot, t.cultural_build_tribute_plot)) tmpl.add_panel('M', t.trigger_target_cultural_build_tribute_too_high) tmpl.add_panel('F', t.funding_pool_view) tmpl.add_panel('V', dandelion) tmpl.add_panel('W', dandelion.vote_pass_view) tmpl.add_panel('G', pn.pane.GIF('media/inputs_outputs.gif')) tmpl.add_panel('R', update_result_score) tmpl.add_panel('CO', comments) tmpl.add_panel('BU', pn.Column(results_button, share_button, url)) tmpl.servable(title=config_file['title'])
from static.description import description from static.blockquote import blockquote from static.extras import extras from static.returns import returns from static.js import js from attributes import Attributes from correction import Correction import config as c settings.resources = 'cdn' pn.config.raw_css = [ css, ] name = 'ufunc-correct' tmpl = pn.Template(template) tmpl.add_variable('app_title', name) tmpl.add_variable('description', description) tmpl.add_variable('blockquote', blockquote) tmpl.add_variable('extras', extras) tmpl.add_variable('returns', returns) tmpl.add_variable('js', js) class Interact(param.Parameterized): ''' ''' def __init__(self): super(Interact, self).__init__() self.datapath = name + '/data'
def load_app(config_file): pn.config.sizing_mode = 'stretch_both' impact_hour_data = read_impact_hour_data() # TECH t = TECH( total_impact_hours=impact_hour_data['Assumed IH'].sum(), impact_hour_data=impact_hour_data, total_cstk_tokens=1000000, config=config_file['tech']) # DandelionVoting dandelion = DandelionVoting(17e6, config=config_file['dandelion_voting']) updating_results = pn.widgets.Button(name="Updating", disabled=True) # Share Button comments_tech = pn.widgets.TextAreaInput( name='What is your Hatch Strategy?', max_length=1024, placeholder='Tell us why you configured the Hatch this way') comments_dandelion = pn.widgets.TextAreaInput( name='What is your Dandelion Voting strategy?', max_length=1024, placeholder='What intended effects will your Dandelion Voting Parameters have?') share_button = pn.widgets.Button(name='Submit Hatch Config Proposal', button_type='primary', disabled=True) url = pn.widgets.TextInput(name='URL', value='') share_button.js_on_click(args={'target': url}, code='window.open(target.value)') results_button = pn.widgets.Button(name='See your results', button_type='success') # Run buttons run_dandelion = pn.widgets.Button(name='Run simulation', button_type='success') run_impact_hours = pn.widgets.Button(name='Run simulation', button_type='success') def update_params_by_url_query(): queries = curdoc().session_context.request.arguments queries = {i: j[0] for i, j in queries.items()} if queries: if 'ihminr' in queries: t.min_raise = int(queries['ihminr']) if 'ihmaxr' in queries: t.max_raise = int(queries['ihmaxr']) if 'tgihr' in queries: t.impact_hour_rate_at_target_goal = float(queries['tgihr']) if 'maxihr' in queries: t.maximum_impact_hour_rate = float(queries['maxihr']) if 'ihtr' in queries: t.target_raise = int(queries['ihtr']) if 'hor' in queries: t.hatch_oracle_ratio = float(queries['hor']) if 'hpd' in queries: t.hatch_period_days = int(queries['hpd']) if 'her' in queries: t.hatch_exchange_rate = float(queries['her']) if 'ht' in queries: t.hatch_tribute_percentage = int(queries['ht']) if 'sr' in queries: dandelion.support_required_percentage = int(queries['sr']) if 'maq' in queries: dandelion.minimum_accepted_quorum_percentage = int(queries['maq']) if 'vdd' in queries: dandelion.vote_duration_days = int(queries['vdd']) if 'vbh' in queries: dandelion.vote_buffer_hours = int(queries['vbh']) if 'rqh' in queries: dandelion.rage_quit_hours = int(queries['rqh']) if 'tfx' in queries: dandelion.tollgate_fee_xdai = float(queries['tfx']) t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') @pn.depends(updating_results) def update_input_output_pane(results_button_on): if results_button_on: input_output_pane = pn.pane.GIF('media/inputs_outputs.gif') else: input_output_pane = pn.pane.Markdown('') return input_output_pane @pn.depends(updating_results) def update_output_scenarios(results_button_on): if results_button_on: output_scenarios = pn.panel(t.output_scenarios_view() .hvplot.table()) else: output_scenarios = pn.pane.Markdown('') return output_scenarios @pn.depends(updating_results) def update_result_score(results_button_on): if results_button_on: t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') data_table = { 'Parameters': [ "Target Goal (wxDai)", "Maximum Goal (wxDai)", "Minimum Goal (wxDai)", "Impact Hour Rate at Target Goal (wxDai/IH)", "Impact Hour Rate at Infinity (wxDai/IH)", "Hatch Membership Ratio (wxDai/CSTK)", "Hatch Period (days)", "Hatch Minting rate (TECH/wxDai)", "Hatch Tribute (%)", "Support Required (%)", "Minimum Quorum (%)", "Vote Duration (days)", "Vote Buffer (hours)", "Ragequit Delay (hours)", "Tollgate Fee (wxDai)"], 'Values': [ int(t.target_raise), int(t.max_raise), int(t.min_raise), t.impact_hour_rate_at_target_goal, t.maximum_impact_hour_rate, t.hatch_oracle_ratio, t.hatch_period_days, t.hatch_exchange_rate, t.hatch_tribute_percentage, dandelion.support_required_percentage, dandelion.minimum_accepted_quorum_percentage, dandelion.vote_duration_days, dandelion.vote_buffer_hours, dandelion.rage_quit_hours, dandelion.tollgate_fee_xdai] } df = pd.DataFrame(data=data_table) # Define output pane output_pane = pn.Row(pn.Column(t.impact_hours_plot, t.redeemable_plot), pn.Column(dandelion.vote_pass_view, t.pie_charts_view)) output_pane.save('output.html') pn.panel(t.output_scenarios_view() .hvplot.table()).save('out_scenarios.html') scenarios = codecs.open("out_scenarios.html", 'r') charts = codecs.open("output.html", 'r') data_charts = { 'html': charts.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto"} data_scenarios = { 'html': scenarios.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto"} charts = requests.post(url=HCTI_API_ENDPOINT, data=data_charts, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) scenarios = requests.post(url=HCTI_API_ENDPOINT, data=data_scenarios, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) # Parameters string url_fork = '{url}?ihminr={ihf_minimum_raise}&tgihr={impact_hour_rate_at_target_goal}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}"'.format(tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), impact_hour_rate_at_target_goal=t.impact_hour_rate_at_target_goal, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, max_wxdai_ratio=int(1125*t.hatch_oracle_ratio), total_votes_per_year=int(24/dandelion.vote_buffer_hours*365), single_tech_mint=float(1/t.hatch_exchange_rate), url=config_file['url']) # Title title = '## Check out my proposal for the Hatch! <a href="' + url_fork + ' target="_blank">Click here to preload the Hatch Configuration Dashboard with my parameters if you think you can do better</a>.' meme_image = """ ![image](https://i.imgflip.com/57zyrl.jpg) """ graphical_summary = """ # Graphical Summary ![image]({image_charts}) """.format(image_charts=charts.json()['url']) graph_descriptions = """ ## Graph Descriptions - Top Left, **Impact Hour Rate vs wxDai Collected**: The Impact Hour Rate determines the Minting Rate for Builders, making 1 Impact Hour equivalent to sending this amount of wxDai to the Hatch. - Top Right, **Proposal Acceptance Criteria**: Shows the range of possibilities for DAO vote outcomes and whether they succeed or not given the Support Required & Minimum Quorum I chose. - Bottom Left, **Backer's Rage Quit % vs wxDai Collected**: The Backer's Rage Quit % is the percent of wxDai that the Backers sent to the Hatch that would be returned if they decide to Ragequit. - Bottom Right, **Redeem-ability of the DAO's wxDai**: Shows who has rights to the wxDai held by the DAO. All of the DAO's funds are collectively governed but some can be withdrawn if token holders Ragequit. This shows the results of my parameter choices at the 3 different goals. """ simulated_outcomes = """ # Simulated Outcomes ![image]({image_scenarios}) """.format(image_scenarios=scenarios.json()['url']) parameters_data = """ # My Hatch Configuration | Parameter|Value| |:-|-:| |Target Goal (wxDai)|{target_goal:,}| |Maximum Goal (wxDai)|{max_goal:,}| |Minimum Goal (wxDai)|{min_goal:,}| |Impact Hour Rate at Target Goal (wxDai/IH)|{ih_rate_tg_goal:,}| |Impact Hour Rate at Infinity (wxDai/IH)|{ih_rate_infinity:,}| |Hatch Membership Ratio (wxDai/CSTK)|{hatch_membership_ratio:,}| |Hatch Period (days)|{hatch_period_days}| |Hatch Minting rate (TECH/wxDai)|{hatch_minting_rate:,}| |Hatch Tribute (%)|{hatch_tribute}| |Support Required (%)|{support_required}| |Minimum Quorum (%)|{minimum_quorum}| |Vote Duration (days)|{vote_duration_days}| |Vote Buffer (hours)|{vote_buffer_hours}| |Ragequit (hours)|{ragequit}| |Tollgate Fee (wxDai)|{tollgate_fee:,}|</a>""".format(target_goal=t.target_raise, max_goal=t.max_raise, min_goal=t.min_raise, ih_rate_tg_goal=t.impact_hour_rate_at_target_goal, ih_rate_infinity=t.maximum_impact_hour_rate, hatch_membership_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_minting_rate=t.hatch_exchange_rate, hatch_tribute=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_quorum=dandelion.minimum_accepted_quorum_percentage, vote_duration_days=dandelion.vote_duration_days, vote_buffer_hours=dandelion.vote_buffer_hours, ragequit=dandelion.rage_quit_hours, tollgate_fee=dandelion.tollgate_fee_xdai) results_header = """ # Summary """ default_comment = "To use the defaults... Technocracy for the win" if not comments_tech.value: print(comments_tech.value) comment_tech = default_comment else: comment_tech = comments_tech.value if not comments_dandelion.value: comment_dandelion = default_comment else: comment_dandelion = comments_dandelion.value string_comments_tech = """ ## Hatch Strategy <p>{comments}</p> """.format(comments=comment_tech) string_comments_dandelion = """ ## DAO Strategy <p>{comments}</p> """.format(comments=comment_dandelion) string_data = """ <h2>Hatch Details</h2> - Trusted Seed members can send wxDai to the Hatch for {hatch_period_days} days. - The target goal will be {ihf_target_raise} wxDai, with a minimum of {ihf_minimum_raise} wxDai necessary for the TEC Hatch DAO to be launched and a cap at {ifh_maximum_raise} wxDai. - Backers will need to send in {single_tech_mint} wxDai to mint 1 TECH. - The membership ratio is set at {hatch_oracle_ratio} wxDai/CSTK, so a Trusted Seed member with the minimum CSTK Score of 1125 CSTK can send up to {max_wxdai_ratio} wxDai to the Hatch. <h2>TEC Hatch DAO Voting Details</h2> - Proposals will be voted on for {vote_duration_days} days. They will require at least {support_required}% support, and a minimum of {minimum_accepted_quorum}% of the TECH Tokens will have to vote yes for a proposal to pass. - TECH token holders will have {rage_quit_hours} hours to exit the DAO if they don't like the result of a vote (as long as they didn't vote yes) before it is executed. - There will be a minimum of {vote_buffer_hours} hours between proposals so people always have time to exit safely if they voted yes on a previous vote, this means we can have at most {total_votes_per_year} votes per year. - To prevent griefing attacks, it will cost {tollgate_fee_xdai} wxDai to make a proposal. If you have Impact Hours, you can see how much money you will get with my configuration <a href="{url}?ihminr={ihf_minimum_raise}&tgihr={impact_hour_rate_at_target_goal}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}" target="_blank">here, just check out the Impact Hour Results table. """.format(tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), impact_hour_rate_at_target_goal=t.impact_hour_rate_at_target_goal, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, max_wxdai_ratio=int(1125*t.hatch_oracle_ratio), total_votes_per_year=int(24/dandelion.vote_buffer_hours*365), single_tech_mint=float(1/t.hatch_exchange_rate), url=config_file['url']) markdown_panel = pn.pane.Markdown(parameters_data + string_comments_tech + string_comments_dandelion + results_header + string_data + graphical_summary) markdown_panel = pn.pane.Markdown(title + meme_image + graphical_summary + graph_descriptions + simulated_outcomes + string_comments_tech + string_comments_dandelion + results_header + string_data + parameters_data) body = urllib.parse.quote(markdown_panel.object, safe='') url.value = (config_file['repo'] + "/issues/new?title=Vote%20for%20My%20Params&labels=" + config_file['label'] + "&body=" + body) results_button.name = "Update your results" markdown_panel = pn.pane.Markdown(results_header + string_data) return markdown_panel pn.state.onload(update_params_by_url_query) def help_icon(href, text): return """ <style> .tooltip {{ position: relative; display: inline-block; align-self: flex-end; }} .tooltip .tooltiptext {{ visibility: hidden; width: 200px; background-color: #555; color: #fff; text-align: center; border-radius: 6px; padding: 10px; position: absolute; z-index: 1; bottom: 125%; left: 50%; margin-left: -110px; opacity: 0; transition: opacity 0.3s; }} .tooltip .tooltiptext::after {{ content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-style: solid; border-color: #555 transparent transparent transparent; }} .tooltip:hover .tooltiptext {{ visibility: visible; opacity: 1; }} .icon {{ width: 24px; height: 24px; }} .flex {{ height: 100%; display: flex; justify-content: center; }} </style> <div class="flex"> <div class="tooltip"> <a href="{href}" target="_blank"> <img class="icon" src="http://cdn.onlinewebfonts.com/svg/img_295214.png" /> </a> <span class="tooltiptext">{text}</span> </div> </div> """.format(href=href, text=text) def param_with_tooltip(param, tooltip, height=50): return pn.Row(pn.Column(param, sizing_mode="stretch_width"), pn.pane.HTML(help_icon(tooltips[tooltip]['href'], tooltips[tooltip]['text']), sizing_mode="fixed", width=30, height=height, align="end")) def run_simulation_dandelion(event): dandelion.param.trigger('action') def run_simulation_impact_hours(event): t.param.trigger('action') def update_results(event): results_button.disabled = True share_button.disabled = True updating_results.value = True share_button.disabled = False results_button.disabled = False updating_results.value = False results_button.on_click(update_results) run_dandelion.on_click(run_simulation_dandelion) run_impact_hours.on_click(run_simulation_impact_hours) # Front-end tmpl = pn.Template(template=template) tmpl.add_variable('app_title', config_file['title']) tmpl.add_panel('B', pn.Column( param_with_tooltip( t.param.min_raise, tooltip='min_raise'), param_with_tooltip( t.param.max_raise, tooltip='max_raise'), param_with_tooltip( t.param.target_raise, tooltip='target_raise'), param_with_tooltip( t.param.impact_hour_rate_at_target_goal, tooltip='impact_hour_rate_at_target_goal'), param_with_tooltip( t.param.maximum_impact_hour_rate, tooltip='maximum_impact_hour_rate', height=40), param_with_tooltip( t.param.hatch_tribute_percentage, tooltip='hatch_tribute_percentage'), param_with_tooltip( t.param.hatch_oracle_ratio, tooltip='hatch_oracle_ratio'), param_with_tooltip( t.param.hatch_period_days, tooltip='hatch_period_days'), param_with_tooltip( t.param.hatch_exchange_rate, tooltip='hatch_exchange_rate'), run_impact_hours )) tmpl.add_panel('C', t.outputs_overview_view) tmpl.add_panel('E', t.payout_view) tmpl.add_panel('D', pn.Column(t.redeemable_plot, t.impact_hours_plot)) tmpl.add_panel('M', t.trigger_unbalanced_parameters) tmpl.add_panel('F', t.pie_charts_view) tmpl.add_panel('V', pn.Column( param_with_tooltip( pn.Column(dandelion.param.support_required_percentage), tooltip='support_required_percentage', height=40), param_with_tooltip( dandelion.param.minimum_accepted_quorum_percentage, tooltip='minimum_accepted_quorum_percentage', height=40), param_with_tooltip( dandelion.param.vote_buffer_hours, tooltip='vote_buffer_hours'), param_with_tooltip( dandelion.param.tollgate_fee_xdai, tooltip='tollgate_fee_xdai'), param_with_tooltip( dandelion.param.vote_duration_days, tooltip='vote_duration_days'), param_with_tooltip( dandelion.param.rage_quit_hours, tooltip='rage_quit_hours'), run_dandelion )) tmpl.add_panel('W', dandelion.vote_pass_view) tmpl.add_panel('G', update_input_output_pane) tmpl.add_panel('R', update_result_score) tmpl.add_panel('CO', pn.Column(comments_tech, comments_dandelion)) tmpl.add_panel('BU', pn.Column(results_button, share_button, url)) tmpl.add_panel('OU', update_output_scenarios) tmpl.servable(title=config_file['title'])
def data_explorer_app(doc): tmpl = pn.Template('') # Load the modules we want. obs_explorer = ObservationsExplorer(name='Search Observations') stats = Stats(name='Overall Stats') def _stat_card(label, value): return pn.pane.HTML(f''' <div class="card"> <div class="card-body"> <h1><span class="badge badge-info">{value}</span></h1> <h3>{label}</h3> </div> </div> ''') stats_row = pn.Row( pn.Column( pn.Row( _stat_card('Hours Exptime', int(stats.df['Total Hours'].sum())), _stat_card('Total Images', int(stats.df['Images'].sum())), ), pn.Row( _stat_card('Observations', int(stats.df['Observations'].sum())), _stat_card('Contributing Units', len(stats.df['Unit'].unique())), )), stats.widget_box, stats.plot, sizing_mode='stretch_both', ) obs_widget_box = pn.WidgetBox(pn.Param( obs_explorer.param, widgets={ 'unit_id': pn.widgets.MultiChoice, 'search_name': { "type": pn.widgets.TextInput, "placeholder": "Lookup RA/Dec by object name", }, }, disabled=True), sizing_mode='stretch_both', max_width=320) observations_row = pn.Column( pn.panel('#### Observations'), pn.Row( obs_widget_box, obs_explorer.table, pn.Column( obs_explorer.selected_title, obs_explorer.image_preview, # obs_explorer.image_table, obs_explorer.table_download_button, obs_explorer.sources_download_button), sizing_mode='stretch_both', )) main_layout = pn.Column(stats_row, observations_row) tmpl.add_panel('mainArea', main_layout) return tmpl.server_doc(doc=doc)
def jinja(self): debug("jinja") tmpl = pn.Template(dashboard_html_template) data_repo_widget = pn.panel(self.param.data_repository, show_labels=False) data_repo_widget.width = 300 data_repo_row = pn.Row(data_repo_widget, self._submit_repository) data_repo_row.css_classes = ["data-repo-input"] query_filter_widget = pn.panel(self.param.query_filter) query_filter_widget.width = 260 query_filter_active_widget = pn.panel(self.param.query_filter_active) query_filter_active_widget.width = 260 query_filter_active_widget.disabled = True new_column_widget = pn.panel(self.param.new_column_expr) new_column_widget.width = 260 datastack_switcher = pn.Row(self._switch_stack) datastack_switcher.css_classes = ["stack-switcher"] view_switcher = pn.Row(self._switch_view) view_switcher.css_classes = ["view-switcher"] clear_button_row = pn.Row(self._clear_metrics_button) overview_map = self.overview.panel() components = [ ("metrics_clear_button", clear_button_row), ("data_repo_path", data_repo_row), ("status_message_queue", self.status_message), ("adhoc_js", self.adhoc_js), ("infobar", self._info), ("stack_switcher", datastack_switcher), ("view_switcher", view_switcher), ("metrics_selectors", self._metric_layout), # ('metrics_plots', self._plot_layout), # ('plot_top', self._plot_top), ("plot_top", None), ("metrics_plots", self.detail_plots_layout), ("skyplot_metrics_plots", self.skyplot_layout), ("overview_plots", overview_map), ( "flags", pn.Column( pn.Row(self.flag_filter_select, self.flag_state_select), pn.Row(self.flag_submit), pn.Row(self.flag_filter_selected), pn.Row(self.flag_remove), ), ), ( "query_filter", pn.Column( query_filter_widget, query_filter_active_widget, pn.Row(self.query_filter_clear, self.query_filter_submit), ), ), ("new_column", pn.Column(new_column_widget, pn.Row(self.new_column_submit)),), ] for l, c in components: tmpl.add_panel(l, c) return tmpl
def jinja(self): from ._jinja2_templates import quicklook import holoviews as hv tmpl = pn.Template(dashboard_html_template) data_repo_widget = pn.panel(self.param.data_repository, show_labels=False) data_repo_widget.width = 300 # data_repo_row = pn.Row(pn.panel('Data Repository', align='end'), # data_repo_widget, self._submit_repository) data_repo_row = pn.Row(data_repo_widget, self._submit_repository) data_repo_row.css_classes = ['data-repo-input'] query_filter_widget = pn.panel(self.param.query_filter) query_filter_widget.width = 260 new_column_widget = pn.panel(self.param.new_column_expr) new_column_widget.width = 260 datastack_switcher = pn.Row(self._switch_stack) datastack_switcher.css_classes = ['stack-switcher'] view_switcher = pn.Row(self._switch_view) view_switcher.css_classes = ['view-switcher'] clear_button_row = pn.Row(self._clear_metrics_button) components = [ ('metrics_clear_button', clear_button_row), ('data_repo_path', data_repo_row), ('status_message_queue', self.status_message), ('adhoc_js', self.adhoc_js), ('infobar', self._info), # ('view_switcher', switcher_row), ('stack_switcher', datastack_switcher), ('view_switcher', view_switcher), ('metrics_selectors', self._metric_layout), ('metrics_plots', self._plot_layout), ('skyplot_metrics_plots', self.skyplot_layout), ('plot_top', self._plot_top), ('flags', pn.Column(pn.Row(self.flag_filter_select, self.flag_state_select), pn.Row(self.flag_submit), pn.Row(self.flag_filter_selected), pn.Row(self.flag_remove))), ( 'query_filter', pn.Column( query_filter_widget, pn.Row(self.query_filter_submit, self.query_filter_clear)), ), ( 'new_column', pn.Column(new_column_widget, pn.Row(self.new_column_submit)), ), ] for l, c in components: tmpl.add_panel(l, c) return tmpl
def instantiate_button(self): ''' ''' self.button = pn.widgets.Button(name='Save hist-adjusted tifs to disk') self.button.on_click(self._save_on_click) @param.depends('rgb_scalar', 'red_scalar', 'grn_scalar', 'blu_scalar') def serve_plots(self): ''' ''' arr = self._adjust_array(arr=self.lowres_arr) return self._plot_array(arr, self.hist_kwargs) bands = ('red', 'grn', 'blu') sources = [rasterio.open(f"geotiffs/1_toa/center_{b}.tif") for b in bands] tune = Tune(sources=sources) tune.instantiate_button() env = Environment(loader=FileSystemLoader('.')) jinja_template = env.get_template('templates/tune.html') tmpl = pn.Template(jinja_template) tmpl.add_variable('app_title', '<h1>Histogram Reference Generator</h1>') tmpl.add_panel('A', tune.serve_plots) tmpl.add_panel('B', tune.param) tmpl.add_panel('C', tune.button) tmpl.servable()
def load_app(config_file): pn.config.sizing_mode = 'stretch_both' impact_hour_data = read_impact_hour_data() # ImpactHoursData i = ImpactHoursData() # TECH t = TECH(total_impact_hours = impact_hour_data['Assumed IH'].sum(), impact_hour_data=impact_hour_data, total_cstk_tokens=1000000, config=config_file['tech']) # ImpactHoursFormula #impact_hours_rewards = ImpactHoursFormula(i.total_impact_hours, impact_hour_data_1) #impact_rewards_view = pn.Column(impact_hours_rewards.impact_hours_rewards, # impact_hours_rewards.redeemable, # impact_hours_rewards.cultural_build_tribute) # Hatch cstk_data = read_cstk_data() #hatch = Hatch(cstk_data, impact_hours_rewards.target_raise, # i.total_impact_hours, # impact_hours_rewards.target_impact_hour_rate) # DandelionVoting dandelion = DandelionVoting(17e6,config=config_file['dandelion_voting']) # Import Params Button import_params_button = pn.widgets.Button(name='Import params', button_type = 'primary') import_description = pn.pane.Markdown('<h4>To import the parameters, click on the button below:</h4>') # Share Button comments = pn.widgets.TextAreaInput(name='Comments', max_length=1024, placeholder='Explain your thoughts on why you choose the params...') share_button = pn.widgets.Button(name='Share your results on GitHub!', button_type = 'primary') url = pn.widgets.TextInput(name='URL', value = '') share_button.js_on_click(args={'target': url}, code='window.open(target.value)') results_button = pn.widgets.Button(name='See your results', button_type = 'success') def update_params_by_url_query(): queries = curdoc().session_context.request.arguments queries = { i: j[0] for i, j in queries.items() } if queries: if 'ihminr' in queries: t.min_raise = int(queries['ihminr']) if 'ihmaxr' in queries: t.max_raise = int(queries['ihmaxr']) if 'hs' in queries: t.impact_hour_slope = float(queries['hs']) if 'maxihr' in queries: t.maximum_impact_hour_rate = float(queries['maxihr']) if 'ihtr' in queries: t.target_raise = int(queries['ihtr']) if 'hor' in queries: t.hatch_oracle_ratio = float(queries['hor']) if 'hpd' in queries: t.hatch_period_days = int(queries['hpd']) if 'her' in queries: t.hatch_exchange_rate = float(queries['her']) if 'ht' in queries: t.hatch_tribute_percentage = int(queries['ht']) if 'sr' in queries: dandelion.support_required_percentage = int(queries['sr']) if 'maq' in queries: dandelion.minimum_accepted_quorum_percentage = int(queries['maq']) if 'vdd' in queries: dandelion.vote_duration_days = int(queries['vdd']) if 'vbh' in queries: dandelion.vote_buffer_hours = int(queries['vbh']) if 'rqh' in queries: dandelion.rage_quit_hours = int(queries['rqh']) if 'tfx' in queries: dandelion.tollgate_fee_xdai = float(queries['tfx']) t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') @pn.depends(results_button) def update_input_output_pane(results_button_on): if results_button_on: input_output_pane = pn.pane.GIF('media/inputs_outputs.gif') else: input_output_pane = pn.pane.Markdown('') return input_output_pane @pn.depends(results_button) def update_result_score(results_button_on): if results_button_on: t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') data_table = {'Parameters': ["Target raise (wxDai)", "Maximum raise (wxDai)", "Minimum raise (wxDai)", "Impact hour slope (wxDai/IH)", "Maximum impact hour rate (wxDai/IH)", "Hatch oracle ratio (wxDai/CSTK)", "Hatch period (days)", "Hatch exchange rate (TECH/wxDai)", "Hatch tribute (%)", "Support required (%)", "Minimum accepted quorum (%)", "Vote duration (days)", "Vote buffer (hours)", "Rage quit (hours)", "Tollgate fee (wxDai)"], 'Values': [int(t.target_raise), int(t.max_raise), int(t.min_raise), t.impact_hour_slope, t.maximum_impact_hour_rate, t.hatch_oracle_ratio, t.hatch_period_days, t.hatch_exchange_rate, t.hatch_tribute_percentage, dandelion.support_required_percentage, dandelion.minimum_accepted_quorum_percentage, dandelion.vote_duration_days, dandelion.vote_buffer_hours, dandelion.rage_quit_hours, dandelion.tollgate_fee_xdai]} df = pd.DataFrame(data=data_table) # Define output pane output_pane = pn.Row(pn.Column(t.impact_hours_view, t.redeemable_plot), pn.Column(dandelion.vote_pass_view, t.funding_pool_view)) output_pane.save('output.html') pn.panel(t.output_scenarios_out_issue().hvplot.table()).save('out_scenarios.html') scenarios = codecs.open("out_scenarios.html", 'r') charts = codecs.open("output.html", 'r') data_charts = { 'html': charts.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto" } data_scenarios = { 'html': scenarios.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto" } charts = requests.post(url = HCTI_API_ENDPOINT, data = data_charts, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) scenarios = requests.post(url = HCTI_API_ENDPOINT, data = data_scenarios, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) output_data = """ <h1>Output Charts</h1> ![image]({image_charts}) <h1>Output Scenarios</h1> ![image]({image_scenarios}) """.format(image_charts=charts.json()['url'], image_scenarios=scenarios.json()['url']) parameters_data = """ <h1>Parameters</h1> {params_table} """.format(params_table=df.to_markdown(index=False, floatfmt=",.2f")) string_data = """ <h1>Results</h1> <p>{comments}</p> - It costs {tollgate_fee_xdai} wxDai to make a proposal. - Votes will be voted on for {vote_duration_days} days. - TECH token holders will have {rage_quit_hours} Hours to exit the DAO if they don't like the result of a vote (as long as they don't vote yes). - There will be a minimum of {vote_buffer_hours} hours between proposals so people can exit safely in weird edge case scenarios. - A proposal that passes can be executed {proposal_execution_hours} hours after it was proposed. - A CSTK Token holder that has 2000 CSTK can send a max of {max_wxdai_ratio} wxDai to the Hatch. Play with my parameters [here]({url}?ihminr={ihf_minimum_raise}&hs={hour_slope}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}). To see the value of your individual Impact Hours, click [here to go to the Hatch Config Dashboard with these parameters]({url}?ihminr={ihf_minimum_raise}&hs={hour_slope}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}) and explore the Impact Hour Results table. """.format(comments=comments.value, tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), hour_slope=t.impact_hour_slope, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, proposal_execution_hours=dandelion.vote_buffer_hours+dandelion.rage_quit_hours, max_wxdai_ratio=int(2000*t.hatch_oracle_ratio), url=config_file['url']) markdown_panel = pn.pane.Markdown(parameters_data + string_data + output_data) body = urllib.parse.quote(markdown_panel.object, safe='') url.value = config_file['repo'] + "/issues/new?title=Vote%20for%20My%20Params&labels=" + config_file['label'] + "&body=" + body results_button.name = "Update your results" markdown_panel = pn.pane.Markdown(string_data) return pn.Row(df.hvplot.table(),markdown_panel) pn.state.onload(update_params_by_url_query) def help_icon(text): return """ <style> .tooltip {{ position: relative; display: inline-block; align-self: flex-end; }} .tooltip .tooltiptext {{ visibility: hidden; width: 200px; background-color: #555; color: #fff; text-align: center; border-radius: 6px; padding: 10px; position: absolute; z-index: 1; bottom: 125%; left: 50%; margin-left: -110px; opacity: 0; transition: opacity 0.3s; }} .tooltip .tooltiptext::after {{ content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-style: solid; border-color: #555 transparent transparent transparent; }} .tooltip:hover .tooltiptext {{ visibility: visible; opacity: 1; }} .icon {{ width: 24px; height: 24px; }} .flex {{ height: 100%; display: flex; justify-content: center; }} </style> <div class="flex"> <div class="tooltip"> <a href="https://forum.tecommons.org/t/tec-test-hatch-implementation-specification/226" target="_blank"> <img class="icon" src="http://cdn.onlinewebfonts.com/svg/img_295214.png" /> </a> <span class="tooltiptext">{text}</span> </div> </div> """.format(text=text) def param_with_tooltip(param, tooltip, height=50): return pn.Row(pn.Column(param, sizing_mode="stretch_width"), pn.pane.HTML(help_icon(tooltips[tooltip]), sizing_mode="fixed", width=30, height=height, align="end")) # Front-end tmpl = pn.Template(template=template) tmpl.add_variable('app_title', config_file['title']) tmpl.add_panel('B', pn.Column( param_with_tooltip(t.param.target_raise, tooltip='target_raise'), param_with_tooltip(t.param.min_raise, tooltip='min_raise'), param_with_tooltip(t.param.max_raise, tooltip='max_raise'), param_with_tooltip(t.param.hatch_tribute_percentage, tooltip='hatch_tribute_percentage'), param_with_tooltip(t.param.maximum_impact_hour_rate, tooltip='maximum_impact_hour_rate', height=40), param_with_tooltip(t.param.impact_hour_slope, tooltip='impact_hour_slope', height=40), param_with_tooltip(t.param.hatch_oracle_ratio, tooltip='hatch_oracle_ratio'), param_with_tooltip(t.param.hatch_period_days, tooltip='hatch_period_days'), param_with_tooltip(t.param.hatch_exchange_rate, tooltip='hatch_exchange_rate'), t.param.action, #t.param.target_impact_hour_rate, #t.param.target_redeemable, #t.param.target_cultural_build_tribute )) tmpl.add_panel('C', t.funding_pool_data_view) tmpl.add_panel('E', t.payout_view) tmpl.add_panel('D', pn.Column(t.impact_hours_view, t.redeemable_plot)) tmpl.add_panel('M', t.trigger_unbalanced_parameters) tmpl.add_panel('F', t.funding_pool_view) tmpl.add_panel('V', pn.Column( param_with_tooltip(pn.Column(dandelion.param.support_required_percentage), tooltip='support_required_percentage', height=40), param_with_tooltip(dandelion.param.minimum_accepted_quorum_percentage, tooltip='minimum_accepted_quorum_percentage', height=40), param_with_tooltip(dandelion.param.vote_duration_days, tooltip='vote_duration_days'), param_with_tooltip(dandelion.param.vote_buffer_hours, tooltip='vote_buffer_hours'), param_with_tooltip(dandelion.param.rage_quit_hours, tooltip='rage_quit_hours'), param_with_tooltip(dandelion.param.tollgate_fee_xdai, tooltip='tollgate_fee_xdai'), dandelion.param.action )) tmpl.add_panel('W', dandelion.vote_pass_view) tmpl.add_panel('G', update_input_output_pane) tmpl.add_panel('R', update_result_score) tmpl.add_panel('CO', comments) tmpl.add_panel('BU', pn.Column(results_button, share_button, url)) tmpl.servable(title=config_file['title'])
{% endblock %} """ def b(event): if fileInput.value is not None: fig.object = chart_log(fileInput.value) else: print('Loading...') text = pn.pane.Str() fileInput = pn.widgets.FileInput() button = pn.widgets.Button(name='Parse', button_type='primary') button.on_click(b) fig = pn.pane.Plotly() tmpl = pn.Template(TEMPLATE) tmpl.add_panel("file_input", fileInput) tmpl.add_panel("button", button) tmpl.add_panel("fig", fig) tmpl.add_panel('text', text) tmpl.servable()
def setup_template(self, height=600): self.tmpl = pn.Template(template=(template % "server"), nb_template=(template % "notebook")) self.tmpl.nb_template.globals["get_id"] = make_globally_unique_id self.tmpl.add_variable("height", f"{height}px")