Skip to content

Commit

Permalink
made table filterable
Browse files Browse the repository at this point in the history
  • Loading branch information
jmbhughes committed Nov 17, 2024
1 parent 708b35b commit be814c1
Showing 1 changed file with 79 additions and 5 deletions.
84 changes: 79 additions & 5 deletions punchpipe/monitor/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"flow_run_name", "flow_type", "call_data", "creation_time", "end_time",
"priority", "start_time", "state"]
schedule_columns =[{'name': v, 'id': v} for v in column_names]
PAGE_SIZE = 15

def create_app():
app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
Expand All @@ -29,22 +30,95 @@ def create_app():
),
dash_table.DataTable(id='flows',
data=pd.DataFrame({name: [] for name in column_names}).to_dict('records'),
columns=schedule_columns),
columns=schedule_columns,
page_current=0,
page_size=PAGE_SIZE,
page_action='custom',

filter_action='custom',
filter_query='',

sort_action='custom',
sort_mode='multi',
sort_by=[]
),
dcc.Interval(
id='interval-component',
interval=REFRESH_RATE * 1000, # in milliseconds
n_intervals=0)
])

operators = [['ge ', '>='],
['le ', '<='],
['lt ', '<'],
['gt ', '>'],
['ne ', '!='],
['eq ', '='],
['contains '],
['datestartswith ']]

def split_filter_part(filter_part):
for operator_type in operators:
for operator in operator_type:
if operator in filter_part:
name_part, value_part = filter_part.split(operator, 1)
name = name_part[name_part.find('{') + 1: name_part.rfind('}')]

value_part = value_part.strip()
v0 = value_part[0]
if (v0 == value_part[-1] and v0 in ("'", '"', '`')):
value = value_part[1: -1].replace('\\' + v0, v0)
else:
try:
value = float(value_part)
except ValueError:
value = value_part

# word operators need spaces after them in the filter string,
# but we don't want these later
return name, operator_type[0].strip(), value

return [None] * 3

@callback(
Output('flows', 'data'),
Input('interval-component', 'n_intervals'),
)
def update_flows(n):
Input('table-sorting-filtering', "page_current"),
Input('table-sorting-filtering', "page_size"),
Input('table-sorting-filtering', 'sort_by'),
Input('table-sorting-filtering', 'filter_query'))
def update_flows(n, page_current, page_size, sort_by, filter):
query = "SELECT * FROM flows;"
with get_database_session() as session:
df = pd.read_sql_query(query, session.connection())
return df.to_dict('records')
dff = pd.read_sql_query(query, session.connection())

filtering_expressions = filter.split(' && ')
for filter_part in filtering_expressions:
col_name, operator, filter_value = split_filter_part(filter_part)

if operator in ('eq', 'ne', 'lt', 'le', 'gt', 'ge'):
# these operators match pandas series operator method names
dff = dff.loc[getattr(dff[col_name], operator)(filter_value)]
elif operator == 'contains':
dff = dff.loc[dff[col_name].str.contains(filter_value)]
elif operator == 'datestartswith':
# this is a simplification of the front-end filtering logic,
# only works with complete fields in standard format
dff = dff.loc[dff[col_name].str.startswith(filter_value)]

if len(sort_by):
dff = dff.sort_values(
[col['column_id'] for col in sort_by],
ascending=[
col['direction'] == 'asc'
for col in sort_by
],
inplace=False
)

page = page_current
size = page_size
return dff.iloc[page * size: (page + 1) * size].to_dict('records')

@callback(
Output('status-cards', 'children'),
Expand Down

0 comments on commit be814c1

Please sign in to comment.