The following block of code defines the layout of one of my tabs, there is a radio button in my index file which switches between day & night shift. So I have 4 files similar to this, & all of them experience the same issue when this happens. Otherwise everything works fine.
staffing_layout_2da = dbc.Container([
dbc.Row(
[
dbc.Col(
modelHeader,
width={'size': 3, 'offset': 0}),
dbc.Col(
html.Div(html.P('STEP 2--> View the current mapping', style={"color": "blue", 'fontSize': 13})),
width={'offset': 1, 'size': 4}),
dbc.Col(
headcountHeader,
width={'offset': 1}),
]),
html.Br()
,
dbc.Row(
[
dbc.Col(modelDropdown, width={'size': 3, 'offset': 0}),
dbc.Col(dbc.Card(card_content, color="light", inverse=True, className='text-center'),
width={'size': 3, 'offset': 1}),
dbc.Col(html.Div(id="output-data-upload_2da", style={"color": "red", 'fontSize': 12},
className='text-center mb-4'),
width={'size': 2, 'offset': 0}),
dbc.Col(dbc.Input(
placeholder="Headcount at ULD loading", size="sm", className="mb-3", value=100, id='headcount_2da'
), className='text-center success', width={'size': 3, 'offset': 0})
]),
dbc.Row(
[
dbc.Col(download, className='text-center mb-4', width={'size': 1, "offset": 5}),
# dbc.Col(upload, className='text-center mb-4', width={'size': 2, "offset": 0}),
],
className="mb-4",
),
# dbc.Row(dbc.Col(html.Div(id='map_1_2da', children=[]), width={'offset': 5})),
# dbc.Row(dbc.Col(html.Div(id='map_2_2da', children=[]), width={'offset': 5})),
# dbc.Row([dbc.Col(html.H2('Current Mapping ---->', style={"color": "blue"}), width={'size': 4, 'offset': 0}),
# dbc.Col(html.Div(id='map_3_2da', children=[]), width={'offset': 1})]),
# dbc.Row(dbc.Col(html.Div(id='map_4_2da', children=[]), width={'offset': 5})),
# dbc.Row(dbc.Col(html.Div(id='map_5_2da', children=[]), width={'offset': 5})),
# dbc.Row(dbc.Col(html.Div(id='map_6_2da', children=[]), width={'offset': 5})),
dbc.Row(
[dbc.Col(html.Div(id='line-container_2da'), width=6)
]),
html.Br(),
dbc.Row(
[
dbc.Col(html.H5(id='staffingTitle_2da', children=staffingRate['title'], style={"color": "orange"},
className='text-center bold mb-4'),
width={'size': 6, 'offset': 0}),
dbc.Col(chartDropdown
, className='text-center', width={'size': 2, 'offset': 0}),
]
),
dbc.Row(
[dbc.Col(html.Div(id='legend_2da', children=[], style={'float': 'left'}), width={'offset': 3}),
]),
dbc.Row(
[dbc.Col(staffingRate['object'], width=6),
dbc.Col(html.Div(id='line-container_2da'), width=6)
]),
dbc.Row(
[dbc.Col(html.H5(id='stackingTitle_2da', children=topStacking['title'], style={"color": "orange"},
className='text-center bold mb-4'),
width=6)
]),
dbc.Row(
[dbc.Col(topStacking['object'], width=12)]),
html.Br(),
dbc.Row(
[dbc.Col(html.H5(id='flightTitle_2da', children=divertVol['title'], style={"color": "orange"},
className='text-center bold mb-4'),
width=6),
dbc.Col(html.H5(id='fingerTitle_2da', children=fingerVol['title'], style={"color": "orange"},
className='text-center bold mb-4'),
width=6)
]),
dbc.Row(
[dbc.Col(divertVol['object'], width=6),
dbc.Col(fingerVol['object'], width=6),
]),
dcc.Store(id='store-flight-data_2da', data=[], storage_type='memory'),
dcc.Store(id='store-finger-data_2da', data=[], storage_type='memory'),
dcc.Store(id='store-rates_2da', data=[], storage_type='memory'),
dcc.Interval(
id='my_interval',
disabled=False, # if True, the counter will no longer update
interval=1 * 6000, # increment the counter n_intervals every interval milliseconds
n_intervals=0, # number of times the interval has passed
max_intervals=-1, # number of times the interval will be fired.
# if -1, then the interval has no limit (the default)
# and if 0 then the interval stops running.
),
dcc.Interval(
id='my_interval_1',
disabled=False, # if True, the counter will no longer update
interval=20 * 6000, # increment the counter n_intervals every interval milliseconds
n_intervals=0, # number of times the interval has passed
max_intervals=-1, # number of times the interval will be fired.
# if -1, then the interval has no limit (the default)
# and if 0 then the interval stops running.
)
], fluid=True)
# *************************************************************
""" CALLBACKS """
# *************************************************************
# Callback to store the flight refresh the flight & rates data periodically so this will ensure the data is refreshed
# properly & we are able to detect the daily backend data updates
@app.callback(
[Output('datatable-interactivity-1_2da', 'data'),
Output('datatable-interactivity-1_2da', 'columns'),
Output('flightTitle_2da', 'children'),
Output('fingerTitle_2da', 'children'),
Output('staffingTitle_2da', 'children')],
[Input('my_interval', 'n_intervals'),
Input('modelDropdown_2da', 'value')]
)
def flightData(num, modelSelection):
print(num)
print('***************')
if num == 0:
if modelSelection == 'sorttech cpt view + wwde ML forecast (recommended)':
flightForecast, currentDate = flightProcessor()
else:
flightForecast, currentDate = flightProcessor(cpt=False)
# need to return the cols & data for the first dash table
col = [{"name": i, "id": i, "deletable": False, "selectable": False, "hideable": False}
for i in flightForecast.columns
if i != 'id'
]
var1 = f'Expected Divert Volume per flight - {currentDate}'
var2 = f'Expected Divert Volume per finger - {currentDate}'
var3 = f'Hourly Staffing recommended per finger - {currentDate}'
return flightForecast.to_dict('records'), col, var1, var2, var3
else:
if modelSelection == 'sorttech cpt view + wwde ML forecast (recommended)':
flightForecast, currentDate = flightProcessor()
else:
flightForecast, currentDate = flightProcessor(cpt=False)
col = [{"name": i, "id": i, "deletable": False, "selectable": False, "hideable": False}
for i in flightForecast.columns
if i != 'id'
]
var1 = f'Expected Divert Volume per flight - {currentDate}'
var2 = f'Expected Divert Volume per finger - {currentDate}'
var3 = f'Hourly Staffing recommended per finger - {currentDate}'
return flightForecast.to_dict('records'), col, var1, var2, var3
# Visualizing the expected divert Volume across the shift
# Consuming the new flight finger mapping uplaoded by the user
@app.callback(
[Output('output-data-upload_2da', 'children'),
Output('datatable-interactivity-2_2da', 'data'),
Output('datatable-interactivity-2_2da', 'columns')],
[Input('datatable-interactivity-1_2da', 'data'),
Input('my_interval_1', 'n_intervals')]
)
def store_data(flightData, num):
# hypothetical enormous dataset with millions of rows
if num == 0:
flight = pd.DataFrame(flightData)
print(flight)
print('**********')
fingerForecast, fileMsg = fingerProcessor(flight)
col = [{"name": i, "id": i, "deletable": False, "selectable": False, "hideable": False}
for i in fingerForecast.columns
if i != 'id'
]
print(fileMsg)
return fileMsg, fingerForecast.to_dict('records'), col
else:
flight = pd.DataFrame(flightData)
print(flight)
print('**********')
fingerForecast, fileMsg = fingerProcessor(flight)
col = [{"name": i, "id": i, "deletable": False, "selectable": False, "hideable": False}
for i in fingerForecast.columns
if i != 'id'
]
print(fileMsg)
return fileMsg, fingerForecast.to_dict('records'), col
# Giving an option to the user for downlaoding the current mapping
@app.callback(
Output("download-mapping_2da", "data"),
Input("btn-download-txt_2da", "n_clicks"),
prevent_initial_call=True,
)
def downloadFunc(n_clicks):
return dcc.send_file('Finger_flight_mapping_2DA.xlsx')
# https://stackoverflow.com/questions/69916523/dash-callback-taking-multiple-inputs-where-some-may-or-may-not-exist-depending
@app.callback(
[Output(component_id='datatable-interactivity-3_2da', component_property='data'),
Output(component_id='datatable-interactivity-3_2da', component_property='columns'),
Output(component_id='datatable-interactivity-3_2da', component_property='style_data_conditional'),
Output(component_id='legend_2da', component_property='children')],
[Input(component_id='headcount_2da', component_property='value'),
Input(component_id='datatable-interactivity-2_2da', component_property='data')
]
)
def updateStaffing(headcount, data):
# https://stackoverflow.com/questions/72229774/schema-length-validation-error-on-python-dash-datatable
data = pd.DataFrame(data)
"""
Diving each element of the dataframe by the total volume convert it to percentage
& multiply by the headcount & round it to the next integer
"""
if headcount:
data_temp = data.drop(['id'], axis=1)
data_temp.set_index(['Finger'], inplace=True)
headcount = int(headcount)
data_temp = data_temp.div(data_temp.sum(axis=0), axis=1)
data_temp = data_temp.apply(lambda x: np.round(x * headcount, 0))
(styles, legend) = discrete_background_color_bins(data_temp)
data_temp = data_temp.reset_index()
col = [
{"name": i, "id": i, "deletable": False, "selectable": False, "hideable": False}
for i in data.columns
if i != 'id'
]
print(data_temp)
# data_temp.loc['Grand Total'] = data_temp.sum(numeric_only=True, axis=0) - todo -> this causes the staffing
# line chart to break fix it
return data_temp.to_dict('rows'), col, styles, legend
else:
raise PreventUpdate
# Create bar chart
@app.callback(
[Output(component_id='line-container_2da', component_property='children')],
[Input(component_id='datatable-interactivity-1_2da', component_property='selected_rows'),
Input(component_id='datatable-interactivity-2_2da', component_property='selected_rows'),
Input(component_id='datatable-interactivity-3_2da', component_property='selected_rows'),
Input(component_id='datatable-interactivity-1_2da', component_property='data'),
Input(component_id='datatable-interactivity-2_2da', component_property='data'),
Input(component_id='datatable-interactivity-3_2da', component_property='data'),
Input(component_id='chartDropdown_2da', component_property='value'),
Input('flightTitle_2da', 'children'),
Input('fingerTitle_2da', 'children'),
Input('staffingTitle_2da', 'children')
]
)
def update_line(selected_rows_1, selected_rows_2, selected_rows_3,
flightData, fingerData, staffingData, chartParam, var1, var2, var3):
print('***************************************************************************')
# print('Data across all pages pre or post filtering: {}'.format(all_rows_data))
# print("Indices of selected rows regardless of filtering results: {}".format(selected_rows_1))
# print("Indices of selected rows regardless of filtering results: {}".format(selected_rows_2))
if chartParam == 'Flight':
dff = pd.DataFrame(flightData)
if selected_rows_1:
dff = dff.iloc[selected_rows_1]
# else:
# dff = dff.iloc[order_of_rows_indices]
# # We need to unpivot the data frame , the line below will make the plotting simpler
dff = dff.reset_index()
# print(dff['Flight'])
dff = dff.drop(['id'], axis=1) # to remove the unneccesary string fields
dff = dff.drop(['index'], axis=1) # to remove the unneccesary string fields
dff_unpivoted = dff.melt(id_vars=['Flight'], var_name='time', value_name='Package Count')
fig = px.line(dff_unpivoted, x='time', y='Package Count', color='Flight')
fig.update_layout(
yaxis_title='Package Count',
title="<b>" + var1 + "</b>"
)
return [
dcc.Graph(id='line-chart_2da',
figure=fig)
]
elif chartParam == 'Staffing':
dff = pd.DataFrame(staffingData)
if selected_rows_3:
dff = dff.iloc[selected_rows_3]
# # We need to unpivot the data frame , the line below will make the plotting simpler
dff = dff.reset_index()
# print(dff['Finger'])
dff = dff.drop(['index'], axis=1) # to remove the unneccesary string fields
dff_unpivoted = dff.melt(id_vars=['Finger'], var_name='time', value_name='Associate Count')
fig = px.line(dff_unpivoted, x='time', y='Associate Count', color='Finger')
fig.update_layout(
yaxis_title='Associate Count',
title="<b>" + var3 + "</b>"
)
return [
dcc.Graph(id='line-chart_2da',
figure=fig)
]
else:
dff = pd.DataFrame(fingerData)
if selected_rows_2:
dff = dff.iloc[selected_rows_2]
# print(dff)
# else:
# dff = dff.iloc[order_of_rows_indices]
# # We need to unpivot the data frame , the line below will make the plotting simpler
dff = dff.reset_index()
dff = dff.drop(['index'], axis=1) # to remove the unneccesary string fields
dff = dff.drop(['id'], axis=1) # to remove the unneccesary string fields
dff_unpivoted = dff.melt(id_vars=['Finger'], var_name='time', value_name='Package Count')
fig = px.line(dff_unpivoted, x='time', y='Package Count', color='Finger')
fig.update_layout(
yaxis_title='Package Count',
title="<b>" + var2 + "</b>"
)
return [
dcc.Graph(id='line-chart_2da',
figure=fig)
]