Compare commits
2 Commits
7cbf75d6a8
...
db30fa9b4e
Author | SHA1 | Date | |
---|---|---|---|
db30fa9b4e | |||
814f88932d |
@ -2,3 +2,4 @@ timestamp,category,comment
|
|||||||
2025-09-11 05:15:04,dashboard_table,"AIR: P853275 - most smaller issues related to this air should be eliminated"
|
2025-09-11 05:15:04,dashboard_table,"AIR: P853275 - most smaller issues related to this air should be eliminated"
|
||||||
2025-09-11 05:15:52,source_table,"SO: 53013308 - this should be erraddicated"
|
2025-09-11 05:15:52,source_table,"SO: 53013308 - this should be erraddicated"
|
||||||
2025-09-11 05:37:58,dashboard_table,"AIR: P892467 - ABZT: need some more explanation"
|
2025-09-11 05:37:58,dashboard_table,"AIR: P892467 - ABZT: need some more explanation"
|
||||||
|
2025-09-13 09:38:40,source_table,"SO: None - tralalal"
|
||||||
|
|
@ -2,10 +2,12 @@ import pandas as pd
|
|||||||
import plotly.express as px
|
import plotly.express as px
|
||||||
from dash import Dash, dcc, html
|
from dash import Dash, dcc, html
|
||||||
from dash.dependencies import Input, Output
|
from dash.dependencies import Input, Output
|
||||||
|
import dash_bootstrap_components as dbc
|
||||||
|
|
||||||
from ..data.loader_gz import MTBFSchema
|
from ..data.loader_gz import MTBFSchema
|
||||||
from . import ids
|
from . import ids
|
||||||
|
|
||||||
|
|
||||||
def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output(ids.BAR_CHART, "children"),
|
Output(ids.BAR_CHART, "children"),
|
||||||
@ -17,32 +19,33 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def update_bar_chart(
|
def update_bar_chart(
|
||||||
years: list[str], weeks: list[str], hits_type: str, single_hitter_filter: list[str]
|
years: list[str], weeks: list[str], u_hits: bool, remove_single: bool
|
||||||
) -> html.Div:
|
) -> html.Div:
|
||||||
filtered_data = data.query(
|
filtered_data = data.query("year in @years and week in @weeks")
|
||||||
"year in @years and week in @weeks"
|
|
||||||
)
|
|
||||||
if filtered_data.shape[0] == 0:
|
if filtered_data.shape[0] == 0:
|
||||||
return html.Div("No data selected.")
|
return html.Div("No data selected.")
|
||||||
|
|
||||||
if hits_type == "p-hits":
|
hits_col = MTBFSchema.U_HITS if u_hits else MTBFSchema.P_HITS
|
||||||
hits_col = MTBFSchema.P_HITS
|
hits_type = "U-Hits" if u_hits else "P-Hits"
|
||||||
else:
|
|
||||||
hits_col = MTBFSchema.U_HITS
|
|
||||||
|
|
||||||
# Count 'Y' values and create pareto
|
# Count 'Y' values and create pareto
|
||||||
pareto_data = filtered_data[filtered_data[hits_col] == 'Y'].groupby(MTBFSchema.AIR).size().reset_index(name='count')
|
pareto_data = (
|
||||||
|
filtered_data[filtered_data[hits_col] == "Y"]
|
||||||
|
.groupby(MTBFSchema.AIR)
|
||||||
|
.size()
|
||||||
|
.reset_index(name="count")
|
||||||
|
)
|
||||||
|
|
||||||
if 'remove_single' in single_hitter_filter:
|
if remove_single:
|
||||||
pareto_data = pareto_data[pareto_data['count'] > 1]
|
pareto_data = pareto_data[pareto_data["count"] > 1]
|
||||||
|
|
||||||
pareto_data = pareto_data.sort_values('count', ascending=False)
|
pareto_data = pareto_data.sort_values("count", ascending=False)
|
||||||
|
|
||||||
fig = px.bar(
|
fig = px.bar(
|
||||||
pareto_data,
|
pareto_data,
|
||||||
x=MTBFSchema.AIR,
|
x=MTBFSchema.AIR,
|
||||||
y="count",
|
y="count",
|
||||||
title=f"{hits_type.capitalize()} per AIR (Pareto)",
|
title=f"{hits_type} per AIR (Pareto)",
|
||||||
labels={
|
labels={
|
||||||
MTBFSchema.AIR: "AIR",
|
MTBFSchema.AIR: "AIR",
|
||||||
"count": "Count",
|
"count": "Count",
|
||||||
@ -52,20 +55,15 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
|
|
||||||
return html.Div(
|
return html.Div(
|
||||||
children=[
|
children=[
|
||||||
dcc.RadioItems(
|
dbc.Switch(
|
||||||
id=ids.PU_HITS_SELECTOR,
|
id=ids.PU_HITS_SELECTOR,
|
||||||
options=[
|
label="P-Hits / U-Hits",
|
||||||
{'label': 'P-Hits', 'value': 'p-hits'},
|
value=False,
|
||||||
{'label': 'U-Hits', 'value': 'u-hits'},
|
|
||||||
],
|
|
||||||
value='p-hits',
|
|
||||||
labelStyle={'display': 'inline-block'}
|
|
||||||
),
|
),
|
||||||
dcc.Checklist(
|
dbc.Switch(
|
||||||
id=ids.SINGLE_HITTER_FILTER,
|
id=ids.SINGLE_HITTER_FILTER,
|
||||||
options=[{'label': 'Remove single hitters', 'value': 'remove_single'}],
|
label="Remove single hitters",
|
||||||
value=[],
|
value=False,
|
||||||
labelStyle={'display': 'inline-block'}
|
|
||||||
),
|
),
|
||||||
html.Div(id=ids.BAR_CHART),
|
html.Div(id=ids.BAR_CHART),
|
||||||
]
|
]
|
||||||
|
@ -7,6 +7,15 @@ import dash_bootstrap_components as dbc
|
|||||||
from ..data.loader_gz import MTBFSchema
|
from ..data.loader_gz import MTBFSchema
|
||||||
from . import ids
|
from . import ids
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
from dash import Dash, dcc, html, dash_table, Input, Output, State, callback_context
|
||||||
|
from datetime import datetime
|
||||||
|
import os
|
||||||
|
import dash_bootstrap_components as dbc
|
||||||
|
|
||||||
|
from ..data.loader_gz import MTBFSchema
|
||||||
|
from . import ids
|
||||||
|
|
||||||
def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output(ids.DATA_TABLE, "children"),
|
Output(ids.DATA_TABLE, "children"),
|
||||||
@ -18,7 +27,7 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def update_data_table(
|
def update_data_table(
|
||||||
years: list[str], weeks: list[str], hits_type: str, single_hitter_filter: list[str]
|
years: list[str], weeks: list[str], u_hits: bool, remove_single: bool
|
||||||
) -> html.Div:
|
) -> html.Div:
|
||||||
filtered_data = data.query(
|
filtered_data = data.query(
|
||||||
"year in @years and week in @weeks"
|
"year in @years and week in @weeks"
|
||||||
@ -26,10 +35,7 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
if filtered_data.shape[0] == 0:
|
if filtered_data.shape[0] == 0:
|
||||||
return html.Div("No data selected.")
|
return html.Div("No data selected.")
|
||||||
|
|
||||||
if hits_type == "p-hits":
|
hits_col = MTBFSchema.U_HITS if u_hits else MTBFSchema.P_HITS
|
||||||
hits_col = MTBFSchema.P_HITS
|
|
||||||
else:
|
|
||||||
hits_col = MTBFSchema.U_HITS
|
|
||||||
|
|
||||||
# Count 'Y' values
|
# Count 'Y' values
|
||||||
hits_data = filtered_data[filtered_data[hits_col] == 'Y']
|
hits_data = filtered_data[filtered_data[hits_col] == 'Y']
|
||||||
@ -40,10 +46,8 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
close_notes=(MTBFSchema.CLOSE_NOTES, lambda x: ', '.join(x.dropna().astype(str).unique()))
|
close_notes=(MTBFSchema.CLOSE_NOTES, lambda x: ', '.join(x.dropna().astype(str).unique()))
|
||||||
).reset_index()
|
).reset_index()
|
||||||
|
|
||||||
if 'remove_single' in single_hitter_filter:
|
if remove_single:
|
||||||
table_data = table_data[table_data['count'] > 1]
|
table_data = table_data[table_data['count'] > 1]
|
||||||
else:
|
|
||||||
table_data = table_data[table_data['count'] == 1]
|
|
||||||
|
|
||||||
table_data = table_data.sort_values('count', ascending=False)
|
table_data = table_data.sort_values('count', ascending=False)
|
||||||
|
|
||||||
@ -51,7 +55,7 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
table_data = table_data[[MTBFSchema.AIR, 'air_issue_description', 'close_notes', 'count']]
|
table_data = table_data[[MTBFSchema.AIR, 'air_issue_description', 'close_notes', 'count']]
|
||||||
|
|
||||||
return dash_table.DataTable(
|
return dash_table.DataTable(
|
||||||
id=ids.CATEGORY_TABLE, # Using this ID for feedback callbacks
|
id=ids.MTBF_PAR_TABLE, # Using this ID for feedback callbacks
|
||||||
data=table_data.to_dict("records"),
|
data=table_data.to_dict("records"),
|
||||||
columns=[{"name": i, "id": i} for i in table_data.columns],
|
columns=[{"name": i, "id": i} for i in table_data.columns],
|
||||||
page_size=10,
|
page_size=10,
|
||||||
@ -64,11 +68,11 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
@app.callback(
|
@app.callback(
|
||||||
Output(ids.FEEDBACK_MODAL, "is_open"),
|
Output(ids.FEEDBACK_MODAL, "is_open"),
|
||||||
Output(ids.FEEDBACK_MESSAGE, "children"),
|
Output(ids.FEEDBACK_MESSAGE, "children"),
|
||||||
Input(ids.CATEGORY_TABLE, "selected_rows"),
|
Input(ids.MTBF_PAR_TABLE, "selected_rows"),
|
||||||
Input(ids.SAVE_FEEDBACK_BUTTON_POPUP, "n_clicks"),
|
Input(ids.SAVE_FEEDBACK_BUTTON_POPUP, "n_clicks"),
|
||||||
Input(ids.CLOSE_FEEDBACK_BUTTON_POPUP, "n_clicks"),
|
Input(ids.CLOSE_FEEDBACK_BUTTON_POPUP, "n_clicks"),
|
||||||
State(ids.FEEDBACK_MODAL, "is_open"),
|
State(ids.FEEDBACK_MODAL, "is_open"),
|
||||||
State(ids.CATEGORY_TABLE, "data"),
|
State(ids.MTBF_PAR_TABLE, "data"),
|
||||||
State(ids.FEEDBACK_INPUT, "value"),
|
State(ids.FEEDBACK_INPUT, "value"),
|
||||||
)
|
)
|
||||||
def handle_feedback_modal(selected_rows, save_clicks, close_clicks, is_open, table_data, comment):
|
def handle_feedback_modal(selected_rows, save_clicks, close_clicks, is_open, table_data, comment):
|
||||||
@ -78,7 +82,7 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
|
|
||||||
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
||||||
|
|
||||||
if triggered_id == ids.CATEGORY_TABLE and selected_rows:
|
if triggered_id == ids.MTBF_PAR_TABLE and selected_rows:
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
if triggered_id == ids.SAVE_FEEDBACK_BUTTON_POPUP and selected_rows:
|
if triggered_id == ids.SAVE_FEEDBACK_BUTTON_POPUP and selected_rows:
|
||||||
@ -107,8 +111,8 @@ def render(app: Dash, data: pd.DataFrame) -> html.Div:
|
|||||||
|
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output("feedback-category-label", "children"),
|
Output("feedback-category-label", "children"),
|
||||||
Input(ids.CATEGORY_TABLE, "selected_rows"),
|
Input(ids.MTBF_PAR_TABLE, "selected_rows"),
|
||||||
State(ids.CATEGORY_TABLE, "data"),
|
State(ids.MTBF_PAR_TABLE, "data"),
|
||||||
prevent_initial_call=True
|
prevent_initial_call=True
|
||||||
)
|
)
|
||||||
def update_feedback_air_label(selected_rows, data):
|
def update_feedback_air_label(selected_rows, data):
|
||||||
|
@ -11,7 +11,7 @@ SELECT_ALL_YEARS_BUTTON = "select-all-years-button"
|
|||||||
WEEK_DROPDOWN = "week-dropdown"
|
WEEK_DROPDOWN = "week-dropdown"
|
||||||
SELECT_ALL_WEEKS_BUTTON = "select-all-weeks-button"
|
SELECT_ALL_WEEKS_BUTTON = "select-all-weeks-button"
|
||||||
|
|
||||||
CATEGORY_TABLE = "category-table"
|
MTBF_PAR_TABLE = "mtbf-par-table"
|
||||||
|
|
||||||
FEEDBACK_INPUT = "feedback-input"
|
FEEDBACK_INPUT = "feedback-input"
|
||||||
FEEDBACK_MESSAGE = "feedback-message"
|
FEEDBACK_MESSAGE = "feedback-message"
|
||||||
|
Reference in New Issue
Block a user