Code Monkey home page Code Monkey logo

Comments (17)

pat1510 avatar pat1510 commented on June 12, 2024 2

from dash.

AnnMarieW avatar AnnMarieW commented on June 12, 2024 1

Hi @pat1510
Look for a component that looks like:

dcc.Link("link name", href="")

and change it to:

dcc.Link("link name", href="/")

If that doesn't work, could you please make a minimal example so I could run it, and see the error?

from dash.

AnnMarieW avatar AnnMarieW commented on June 12, 2024 1

@pat1510

In the last callback I see you are returning the csv data to the href prop. This is being flagged as an invalid (dangerous) link.

I recommend using the dcc.Download component instead. See more info in the Dash docs

If you have any more questions, please feel free to ask them on the Dash Community Forum

from dash.

AnnMarieW avatar AnnMarieW commented on June 12, 2024 1

@pat1510 That's a great topic for the forum - please ask over there 🙂

from dash.

alexcjohnson avatar alexcjohnson commented on June 12, 2024

Thanks @ghaarsma - we closed an XSS vulnerability in v2.15 -> #2732
It looks like perhaps you have a blank href in a dcc.Link component, is that right? @T4rk1n we can presumably let blanks pass through the validation?

from dash.

ghaarsma avatar ghaarsma commented on June 12, 2024

I do have an html.A where we set href to "", also several dcc.Link where we set href to "/". We also have locations where we set href within a callback dynamically.

I did do a quick try to give them a temporary value. This did not make the problem go away. My testing was not comprehensive or I might not understand the problem al together.

from dash.

T4rk1n avatar T4rk1n commented on June 12, 2024

dcc.Link.href is marked as required so I thought it was going to be always there and didn't put a check on that like the other ones in html.

from dash.

pat1510 avatar pat1510 commented on June 12, 2024

@ann-marie-ward could you please explain me the detail steps to avoid this 'Dangerous link error' ? Please see that I am new to software development , hence please do not presume about my software development knowledge ? I am getting this error when I try to save data table on web app to the csv. The error looks similar to what @ghaarsma posted in his comment.

from dash.

ghaarsma avatar ghaarsma commented on June 12, 2024

I figured out where the trouble spot was (dynamic building of dcc.Links), after changing href="" to href="/", we had no more issues in the Dash Debug Window.

Thank you to everyone who responded and helped out solving the issue.

from dash.

pat1510 avatar pat1510 commented on June 12, 2024

from dash.

AnnMarieW avatar AnnMarieW commented on June 12, 2024

@pat1510
The target='_blank' will open a blank browser tab
I don't get an error when I run your example. Can you make a complete example that shows the error?

from dash.

pat1510 avatar pat1510 commented on June 12, 2024

from dash.

AnnMarieW avatar AnnMarieW commented on June 12, 2024

Hi @pat1510 I can't see your attachment. Can you please copy the code directly as a comment here? You can enclose the code with three back ticks so it's formatted correctly.

You can also upload files by clicking here:
image

from dash.

pat1510 avatar pat1510 commented on June 12, 2024
import dash
import numpy as np
from dash import dcc, html
from dash.dash_table import DataTable
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output
from base64 import b64encode

# Demo DataFrame
data = {
    'Plastic': ['A', 'A', 'B', 'B', 'A', 'B','A', 'A', 'B', 'B', 'A', 'B'],
    'Make': [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2],
    'Block': [10, 20, 30, 10, 20, 30, 10, 20, 30, 10, 20, 30],
    'Measurement': [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2],
    'Actual_Yield': [85, 90, 88, 92, 87, 91, 85, 90, 88, 92, 87, 91],
    'Min': [80, 85, 85, 88, 82, 90, 80, 85, 85, 88, 82, 90],
    'Max': [88, 92, 90, 94, 89, 94, 88, 92, 90, 94, 89, 94]
}

df = pd.DataFrame(data)

# Calculate average yield for each grade and additional filters
average_yield_per_grade = df.groupby(['Plastic', 'Make', 'Block', 'Measurement'])['Actual_Yield'].mean().reset_index()

# Calculate overall average yield
overall_avg_yield = df['Actual_Yield'].mean()

app = dash.Dash(__name__)

app.layout = html.Div(className='row', children=[
    # Left column for Production Line Chart
    html.Div(className='six columns', children=[
        html.H1(children='KPI Dashboard', style={'textAlign': 'center'}),

        # Dropdown for selecting plastic grades
        dcc.Dropdown(
            id='plastic-dropdown',
            options=[
                {'label': plastic, 'value': plastic} for plastic in df['Plastic'].unique()
            ],
            value=df['Plastic'].iloc[0],  # Set default value to the first grade in the dataframe
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Plastic Grade'
        ),

        # Dropdown for selecting Make
        dcc.Dropdown(
            id='make-dropdown',
            options=[],  # Will be populated dynamically
            value='',  # Set default value to empty
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Make'
        ),

        # Dropdown for selecting Block
        dcc.Dropdown(
            id='block-dropdown',
            options=[],  # Will be populated dynamically
            value='',  # Set default value to empty
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Block'
        ),

        # Dropdown for selecting Measurement
        dcc.Dropdown(
            id='measurement-dropdown',
            options=[],  # Will be populated dynamically
            value='',  # Set default value to empty
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Measurement'
        ),

        # Line Chart
        dcc.Graph(
            id='production-line-chart',
            figure=px.line(title='Default Actual_Yield Trend')  # Set default figure
        ),
        # Download Button
        html.A(html.Button('Download Data as Excel'), id='download-link', href='/', download='your_file_name.xlsx',
               target='_blank')
    ]),

    # Center column for DataTable
    html.Div(className='four columns', children=[
        html.H3(children='Selected Combinations Data Table', style={'textAlign': 'center'}),

        DataTable(
            id='selected-data-table',
            columns=[
                {'name': 'Plastic', 'id': 'Plastic'},
                {'name': 'Make', 'id': 'Make'},
                {'name': 'Block', 'id': 'Block'},
                {'name': 'Measurement', 'id': 'Measurement'},
                {'name': 'Actual_Yield', 'id': 'Actual_Yield'},
                {'name': 'Min', 'id': 'Min'},
                {'name': 'Max', 'id': 'Max'},
                # Add more columns as needed
            ],
            style_table={'height': '300px', 'overflowY': 'auto'},
        ),
    ]),

    # Right column for Yield Gauge Charts
    html.Div(className='six columns', children=[
        # Yield Gauge Chart for Selected Grade
        html.Div(className='graph-container', children=[
            dcc.Graph(id='yield-gauge-chart-selected-grade',
                      style={'width': '700px', 'height': '500px', 'marginLeft': '280px'}
                      ),
        ]),

        # Yield Gauge Chart for Overall Average
        html.Div(className='graph-container', children=[
            dcc.Graph(id='yield-gauge-chart-overall-average',
                      style={'width': '700px', 'height': '500px', 'marginLeft': '-10px'}
                      ),
        ]),
    ], style={'display': 'flex'}),

    # Interval component for updating gauge value
    dcc.Interval(
        id='interval-component',
        interval=1 * 1000,  # in milliseconds (1 second)
        n_intervals=0
    ),
])


# Callback to populate Make dropdown based on selected plastic grade
@app.callback(
    Output('make-dropdown', 'options'),
    [Input('plastic-dropdown', 'value')]
)
def update_make_dropdown(selected_plastic):
    make_options = [{'label': str(make), 'value': make} for make in
                    df[df['Plastic'] == selected_plastic]['Make'].unique()]
    return make_options


# Callback to populate Block dropdown based on selected plastic grade and Make
@app.callback(
    Output('block-dropdown', 'options'),
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value')]
)
def update_block_dropdown(selected_plastic, selected_make):
    # Check if selected_make is not empty
    if not selected_make:
        return []

    block_options = [{'label': str(block), 'value': block} for block in
                     df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make))]['Block'].unique()]
    return block_options


# Callback to populate Measurement dropdown based on selected plastic grade, Make, and Block
@app.callback(
    Output('measurement-dropdown', 'options'),
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value')]
)
def update_measurement_dropdown(selected_plastic, selected_make, selected_block):
    # Check if selected_block is not empty
    if not selected_block:
        return []

    measurement_options = [{'label': str(measurement), 'value': measurement} for measurement in
                           df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                              (df['Block'] == float(selected_block))]['Measurement'].unique()]
    return measurement_options


# Callback to update line chart based on selected plastic grade and filters
@app.callback(
    Output('production-line-chart', 'figure'),
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value'),
     Input('measurement-dropdown', 'value'),
     Input('interval-component', 'n_intervals')]
)
def update_line_chart(selected_plastic, selected_make, selected_block, selected_measurement, n_intervals):
    # Check if any selected value is empty
    if any(value is None or value == '' for value in
           [selected_plastic, selected_make, selected_block, selected_measurement]):
        return px.line(title='No data available')  # Return a default line chart with a title

    selected_df = df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                     (df['Block'] == float(selected_block)) & (df['Measurement'] == float(selected_measurement))].copy()

    if selected_df.empty:
        return px.line(title='No data available')  # Return a default line chart with a title

    selected_df['Count'] = range(1, len(selected_df) + 1)

    # Check if 'Min' and 'Max' columns are present in the DataFrame
    if 'Min' not in selected_df.columns or 'Max' not in selected_df.columns:
        return px.line(title='Missing data columns')  # Return a default line chart with a title

    line_chart = px.line(selected_df, x='Count', y=['Min', 'Max'],
                         title=f'Plastic-{selected_plastic}, Make-{selected_make}, Block-{selected_block}, Measurement-{selected_measurement} Min'
                               f' and Max Trend')
    # Update marker properties for Min and Max
    line_chart.update_traces(
        line=dict(width=2),  # Adjust the width of the line
        mode='markers+lines',  # Show markers and lines
        marker=dict(size=10)  # Adjust the size of the marker
    )
    line_chart.update_layout(xaxis_title='Count')

    return line_chart


@app.callback(
    [Output('yield-gauge-chart-selected-grade', 'figure'),
     Output('yield-gauge-chart-overall-average', 'figure')],
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value'),
     Input('measurement-dropdown', 'value'),
     Input('interval-component', 'n_intervals')]
)
def update_gauge_charts(selected_plastic, selected_make, selected_block, selected_measurement, n_intervals):
    # Check if any selected value is None or an empty string
    if any(value is None or value == '' for value in
           [selected_plastic, selected_make, selected_block, selected_measurement]):
        return go.Figure(), go.Figure()  # Return default figures

    # Check if selected_block and selected_measurement are not None or empty string before converting to float
    selected_block_float = float(selected_block) if selected_block and selected_block != '' else None
    selected_measurement_float = float(
        selected_measurement) if selected_measurement and selected_measurement != '' else None

    selected_df = df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                     (df['Block'] == selected_block_float) & (df['Measurement'] == selected_measurement_float)].copy()

    if selected_df.empty:
        return go.Figure(), go.Figure()

    selected_df['Count'] = range(1, len(selected_df) + 1)

    current_yield = average_yield_per_grade.loc[
        (average_yield_per_grade['Plastic'] == selected_plastic) &
        (average_yield_per_grade['Make'] == int(selected_make)) &
        (average_yield_per_grade['Block'] == selected_block_float) &
        (average_yield_per_grade['Measurement'] == selected_measurement_float), 'Actual_Yield'].values

    if len(current_yield) > 0:
        current_yield = current_yield[0]
    else:
        current_yield = 0

    steps_selected_grade = [
        dict(range=[0, current_yield], color="green"),
        dict(range=[current_yield, 100], color="red")
    ]

    yield_gauge_chart_selected_grade = go.Figure(go.Indicator(
        mode='gauge+number',
        value=current_yield,
        title=f'Average Yield for Plastic {selected_plastic}',
        gauge=dict(
            axis=dict(range=[None, 100]),
            bar=dict(color="green"),
            steps=steps_selected_grade,
            threshold=dict(line=dict(color="red", width=2), thickness=0.75)
        )
    ))

    steps_overall_avg = [
        dict(range=[0, overall_avg_yield], color="green"),
        dict(range=[overall_avg_yield, 100], color="red")
    ]

    yield_gauge_chart_overall_avg = go.Figure(go.Indicator(
        mode='gauge+number',
        value=overall_avg_yield,
        title='Overall Average Yield',
        gauge=dict(
            axis=dict(range=[None, 100]),
            bar=dict(color="green"),
            steps=steps_overall_avg,
            threshold=dict(line=dict(color="red", width=2), thickness=0.75)
        )
    ))

    return yield_gauge_chart_selected_grade, yield_gauge_chart_overall_avg


# Callback to update data table based on selected plastic grade, Make, Block, and Measurement
@app.callback(
    [Output('selected-data-table', 'data'),
     Output('download-link', 'href')],
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value'),
     Input('measurement-dropdown', 'value')]
)
def update_data_table(selected_plastic, selected_make, selected_block, selected_measurement):
    # Check if all selected values are not None or empty string
    if all(value is not None and value != '' for value in
           [selected_plastic, selected_make, selected_block, selected_measurement]):
        selected_df = df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                         (df['Block'] == float(selected_block)) & (df['Measurement'] == float(selected_measurement))]

        # Convert DataFrame to CSV and encode as base64 for download link
        csv_string = selected_df.to_csv(index=False, encoding='utf-8')
        csv_base64 = 'data:text/csv;base64,' + b64encode(csv_string.encode()).decode()

        return selected_df.to_dict('records'), csv_base64
    else:
        return [], ''


# Run the app
if __name__ == '__main__':
    app.run_server(host='127.0.0.1', port=8058, debug=True)

@AnnMarieW I have added the code here as you suggested.

from dash.

pat1510 avatar pat1510 commented on June 12, 2024

Hello All, thanks for the input. But I am still getting the same error. I may be doing something incorrect, could anyone look into my code and see what I am doing wrong?

import dash
import numpy as np
from dash import dcc, html
from dash.dash_table import DataTable
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output
from base64 import b64encode

# Demo DataFrame
data = {
    'Plastic': ['A', 'A', 'B', 'B', 'A', 'B', 'A', 'A', 'B', 'B', 'A', 'B'],
    'Make': [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2],
    'Block': [10, 20, 30, 10, 20, 30, 10, 20, 30, 10, 20, 30],
    'Measurement': [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2],
    'Actual_Yield': [85, 90, 88, 92, 87, 91, 85, 90, 88, 92, 87, 91],
    'Min': [80, 85, 85, 88, 82, 90, 80, 85, 85, 88, 82, 90],
    'Max': [88, 92, 90, 94, 89, 94, 88, 92, 90, 94, 89, 94]
}

df = pd.DataFrame(data)

# Calculate average yield for each grade and additional filters
average_yield_per_grade = df.groupby(['Plastic', 'Make', 'Block', 'Measurement'])['Actual_Yield'].mean().reset_index()

# Calculate overall average yield
overall_avg_yield = df['Actual_Yield'].mean()

app = dash.Dash(__name__)

app.layout = html.Div(className='row', children=[
    # Left column for Production Line Chart
    html.Div(className='six columns', children=[
        html.H1(children='KPI Dashboard', style={'textAlign': 'center'}),

        # Dropdown for selecting plastic grades
        dcc.Dropdown(
            id='plastic-dropdown',
            options=[
                {'label': plastic, 'value': plastic} for plastic in df['Plastic'].unique()
            ],
            value=df['Plastic'].iloc[0],  # Set default value to the first grade in the dataframe
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Plastic Grade'
        ),

        # Dropdown for selecting Make
        dcc.Dropdown(
            id='make-dropdown',
            options=[],  # Will be populated dynamically
            value='',  # Set default value to empty
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Make'
        ),

        # Dropdown for selecting Block
        dcc.Dropdown(
            id='block-dropdown',
            options=[],  # Will be populated dynamically
            value='',  # Set default value to empty
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Block'
        ),

        # Dropdown for selecting Measurement
        dcc.Dropdown(
            id='measurement-dropdown',
            options=[],  # Will be populated dynamically
            value='',  # Set default value to empty
            style={'width': '50%', 'margin': '20px auto'},
            placeholder='Select Measurement'
        ),

        # Line Chart
        dcc.Graph(
            id='production-line-chart',
            figure=px.line(title='Default Actual_Yield Trend')  # Set default figure
        ),
        # Download Button
        # html.Button('Download Data as Excel', id='download-link'),
        # dcc.Download(id="download-dataframe-csv"),

        dcc.Link('Download Data as Excel', id='download-link', href='/'),
        dcc.Download(id="download-dataframe-csv"),
    ]),

    # Center column for DataTable
    html.Div(className='four columns', children=[
        html.H3(children='Selected Combinations Data Table', style={'textAlign': 'center'}),

        DataTable(
            id='selected-data-table',
            columns=[
                {'name': 'Plastic', 'id': 'Plastic'},
                {'name': 'Make', 'id': 'Make'},
                {'name': 'Block', 'id': 'Block'},
                {'name': 'Measurement', 'id': 'Measurement'},
                {'name': 'Actual_Yield', 'id': 'Actual_Yield'},
                {'name': 'Min', 'id': 'Min'},
                {'name': 'Max', 'id': 'Max'},
                # Add more columns as needed
            ],
            style_table={'height': '300px', 'overflowY': 'auto'},
        ),
    ]),

    # Right column for Yield Gauge Charts
    html.Div(className='six columns', children=[
        # Yield Gauge Chart for Selected Grade
        html.Div(className='graph-container', children=[
            dcc.Graph(id='yield-gauge-chart-selected-grade',
                      style={'width': '700px', 'height': '500px', 'marginLeft': '280px'}
                      ),
        ]),

        # Yield Gauge Chart for Overall Average
        html.Div(className='graph-container', children=[
            dcc.Graph(id='yield-gauge-chart-overall-average',
                      style={'width': '700px', 'height': '500px', 'marginLeft': '-10px'}
                      ),
        ]),
    ], style={'display': 'flex'}),

    # Interval component for updating gauge value
    dcc.Interval(
        id='interval-component',
        interval=1 * 1000,  # in milliseconds (1 second)
        n_intervals=0
    ),
])


# Callback to populate Make dropdown based on selected plastic grade
@app.callback(
    Output('make-dropdown', 'options'),
    [Input('plastic-dropdown', 'value')]
)
def update_make_dropdown(selected_plastic):
    make_options = [{'label': str(make), 'value': make} for make in
                    df[df['Plastic'] == selected_plastic]['Make'].unique()]
    return make_options


# Callback to populate Block dropdown based on selected plastic grade and Make
@app.callback(
    Output('block-dropdown', 'options'),
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value')]
)
def update_block_dropdown(selected_plastic, selected_make):
    # Check if selected_make is not empty
    if not selected_make:
        return []

    block_options = [{'label': str(block), 'value': block} for block in
                     df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make))]['Block'].unique()]
    return block_options


# Callback to populate Measurement dropdown based on selected plastic grade, Make, and Block
@app.callback(
    Output('measurement-dropdown', 'options'),
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value')]
)
def update_measurement_dropdown(selected_plastic, selected_make, selected_block):
    # Check if selected_block is not empty
    if not selected_block:
        return []

    measurement_options = [{'label': str(measurement), 'value': measurement} for measurement in
                           df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                              (df['Block'] == float(selected_block))]['Measurement'].unique()]
    return measurement_options


# Callback to update line chart based on selected plastic grade and filters
@app.callback(
    Output('production-line-chart', 'figure'),
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value'),
     Input('measurement-dropdown', 'value'),
     Input('interval-component', 'n_intervals')]
)
def update_line_chart(selected_plastic, selected_make, selected_block, selected_measurement, n_intervals):
    # Check if any selected value is empty
    if any(value is None or value == '' for value in
           [selected_plastic, selected_make, selected_block, selected_measurement]):
        return px.line(title='No data available')  # Return a default line chart with a title

    selected_df = df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                     (df['Block'] == float(selected_block)) & (df['Measurement'] == float(selected_measurement))].copy()

    if selected_df.empty:
        return px.line(title='No data available')  # Return a default line chart with a title

    selected_df['Count'] = range(1, len(selected_df) + 1)

    # Check if 'Min' and 'Max' columns are present in the DataFrame
    if 'Min' not in selected_df.columns or 'Max' not in selected_df.columns:
        return px.line(title='Missing data columns')  # Return a default line chart with a title

    line_chart = px.line(selected_df, x='Count', y=['Min', 'Max'],
                         title=f'Plastic-{selected_plastic}, Make-{selected_make}, Block-{selected_block}, Measurement-{selected_measurement} Min'
                               f' and Max Trend')
    # Update marker properties for Min and Max
    line_chart.update_traces(
        line=dict(width=2),  # Adjust the width of the line
        mode='markers+lines',  # Show markers and lines
        marker=dict(size=10)  # Adjust the size of the marker
    )
    line_chart.update_layout(xaxis_title='Count')

    return line_chart


@app.callback(
    [Output('yield-gauge-chart-selected-grade', 'figure'),
     Output('yield-gauge-chart-overall-average', 'figure')],
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value'),
     Input('measurement-dropdown', 'value'),
     Input('interval-component', 'n_intervals')]
)
def update_gauge_charts(selected_plastic, selected_make, selected_block, selected_measurement, n_intervals):
    # Check if any selected value is None or an empty string
    if any(value is None or value == '' for value in
           [selected_plastic, selected_make, selected_block, selected_measurement]):
        return go.Figure(), go.Figure()  # Return default figures

    # Check if selected_block and selected_measurement are not None or empty string before converting to float
    selected_block_float = float(selected_block) if selected_block and selected_block != '' else None
    selected_measurement_float = float(
        selected_measurement) if selected_measurement and selected_measurement != '' else None

    selected_df = df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                     (df['Block'] == selected_block_float) & (df['Measurement'] == selected_measurement_float)].copy()

    if selected_df.empty:
        return go.Figure(), go.Figure()

    selected_df['Count'] = range(1, len(selected_df) + 1)

    current_yield = average_yield_per_grade.loc[
        (average_yield_per_grade['Plastic'] == selected_plastic) &
        (average_yield_per_grade['Make'] == int(selected_make)) &
        (average_yield_per_grade['Block'] == selected_block_float) &
        (average_yield_per_grade['Measurement'] == selected_measurement_float), 'Actual_Yield'].values

    if len(current_yield) > 0:
        current_yield = current_yield[0]
    else:
        current_yield = 0

    steps_selected_grade = [
        dict(range=[0, current_yield], color="green"),
        dict(range=[current_yield, 100], color="red")
    ]

    yield_gauge_chart_selected_grade = go.Figure(go.Indicator(
        mode='gauge+number',
        value=current_yield,
        title=f'Average Yield for Plastic {selected_plastic}',
        gauge=dict(
            axis=dict(range=[None, 100]),
            bar=dict(color="green"),
            steps=steps_selected_grade,
            threshold=dict(line=dict(color="red", width=2), thickness=0.75)
        )
    ))

    steps_overall_avg = [
        dict(range=[0, overall_avg_yield], color="green"),
        dict(range=[overall_avg_yield, 100], color="red")
    ]

    yield_gauge_chart_overall_avg = go.Figure(go.Indicator(
        mode='gauge+number',
        value=overall_avg_yield,
        title='Overall Average Yield',
        gauge=dict(
            axis=dict(range=[None, 100]),
            bar=dict(color="green"),
            steps=steps_overall_avg,
            threshold=dict(line=dict(color="red", width=2), thickness=0.75)
        )
    ))

    return yield_gauge_chart_selected_grade, yield_gauge_chart_overall_avg


@app.callback(
    [Output('selected-data-table', 'data'),
     Output('download-link', 'href')],
    [Input('plastic-dropdown', 'value'),
     Input('make-dropdown', 'value'),
     Input('block-dropdown', 'value'),
     Input('measurement-dropdown', 'value')]
)
def update_data_table(selected_plastic, selected_make, selected_block, selected_measurement):
    # Check if all selected values are not None or empty string
    if all(value is not None and value != '' for value in
           [selected_plastic, selected_make, selected_block, selected_measurement]):
        selected_df = df[(df['Plastic'] == selected_plastic) & (df['Make'] == int(selected_make)) &
                         (df['Block'] == float(selected_block)) & (df['Measurement'] == float(selected_measurement))]

        # Convert DataFrame to CSV and encode as base64 for download link
        csv_string = selected_df.to_csv(index=False, encoding='utf-8')
        csv_base64 = 'data:text/csv;base64,' + b64encode(csv_string.encode()).decode()

        return selected_df.to_dict('records'), csv_base64
    else:
        return [], ''


# Run the app
if __name__ == '__main__':
    app.run_server(host='127.0.0.1', port=8058, debug=True)

from dash.

AnnMarieW avatar AnnMarieW commented on June 12, 2024

@pat1510 Please ask your question on the Dash Community Forum. I'll be happy to help you over there.

This issue is now closed.

from dash.

pat1510 avatar pat1510 commented on June 12, 2024

from dash.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.