def project_picker(filter_projects: Optional[List] = None) -> List: """ Returns controls for filtering by projects. """ # Controls for filtering by activity if filter_projects is None: # Query activities from DB activities = (db.session.query( Activity.activity_id.label("value"), Activity.activity_name.label("label"), ).filter(Team.team_id.in_(current_user.writable_team_ids)).order_by( Activity.activity_id).distinct().all()) else: # Use only filtered projects activities = filter_projects options = [activity._asdict() for activity in activities] selected_value = options[0]["value"] if options else None selected_value = load_slicer_value( "project_picker", value_type=int, available_options=[i["value"] for i in options], default=selected_value, ) return [ tdc.Dropdown( id="projectPicker", label="Project", options=options, value=selected_value, ) ]
def team_picker( selected_teams: Optional[IntOrList] = None, html_element_id="teamPicker", multi: bool = True, ) -> List: """ Returns controls for filtering by teams. :param selected_teams: You can pass a dataframe or List of team-ids to set the initial selection of this control. Default = None (= all teams selected) :param html_element_id: The HTML-ID for the dropdown menu created by this function. :param multi: Enable multi select """ # Controls for filtering by team # Query all teams from database teams = (Team.query.with_entities( Team.team_id.label("value"), Team.name.label("label")).filter( Team.team_id.in_(current_user.listable_team_ids)).order_by( Team.name).all()) if selected_teams is None: # by default, select all if multi, select first if not multi if multi: selected_teams = [team_id for team_id, _ in teams] else: try: selected_teams = teams[0].value except IndexError: selected_teams = None selected_teams = load_slicer_value( "team_picker", value_type=list if multi else int, available_options=[team_id for team_id, _ in teams], default=selected_teams, ) return [ tdc.Dropdown( id=html_element_id, label="Teams", options=[team._asdict() for team in teams], value=selected_teams, multi=multi, searchable=True, enableSelectAll="All Teams", ), ]
def date_range_picker( max_date=datetime.today(), min_date=None, start_date=datetime.today(), end_date=datetime.today(), display_format="YY/MM/DD", display_format_month="MMM, YY", html_element_id="date_range_picker", ) -> List: """ Creates a control for selecting a range of dates. """ max_date = convert_date_to_str(max_date) if max_date else None min_date = convert_date_to_str(min_date) if min_date else None start_date = convert_date_to_str(start_date) if start_date else None end_date = convert_date_to_str(end_date) if end_date else None saved_values = load_slicer_value( "date_range_picker", value_type=list, default=[start_date, end_date, min_date, max_date], ) *_, saved_min_date, saved_max_date = saved_values if saved_min_date == min_date and saved_max_date == max_date: saved_start_date, saved_end_date, *_ = saved_values start_date = saved_start_date end_date = saved_end_date picker = dcc.DatePickerRange( id=html_element_id, min_date_allowed=min_date, max_date_allowed=max_date, initial_visible_month=start_date, start_date=start_date, end_date=end_date, first_day_of_week=1, display_format=display_format, month_format=display_format_month, ) return [picker]
def department_picker(selected_department: Optional[int] = None, html_element_id="departmentPicker") -> List: """ Return a dropdown for filtering by department (which is a team with parent-team=0) :param selected_department: This department is selected when the control gets drawn. :param html_element_id: The HTML-ID for the dropdown menu created by this function. """ # If no department has been pre-selected, select *All departments* if selected_department is None: selected_department = ALL_ITEMS_OPTION_ID # Query database for a list of all departments departments = (Team.query.with_entities( Team.team_id.label("value"), Team.name.label("label")).filter( Team.team_id.in_(current_user.listable_department_ids)).order_by( Team.name).all()) options = [{"label": "<All departments>", "value": ALL_ITEMS_OPTION_ID}] options.extend([department._asdict() for department in departments]) selected_department = load_slicer_value( "department_picker", value_type=int, available_options=[i["value"] for i in options], default=selected_department, ) return [ tdc.Dropdown( id=html_element_id, label="Departments", options=options, value=selected_department, ), ]
def sprint_picker(filter_sprints: Optional[List] = None, html_element_id: str = "sprintPicker") -> List: """ Returns controls for filtering by sprints """ # Controls for filtering by sprint if filter_sprints is None: activities_subq = (Activity.query.filter( Activity.team_id.in_( current_user.readable_team_ids)).with_entities( Activity.activity_id).subquery()) sprints = (Sprint.query.filter( Sprint.activity_id.in_(activities_subq)).with_entities( Sprint.sprint_id.label("value"), Sprint.name.label("label")).order_by( Sprint.start_date.desc()).all()) else: # Use only filtered projects sprints = filter_sprints options = [sprint._asdict() for sprint in sprints] selected_value = options[-1]["value"] if options else None selected_value = load_slicer_value( "sprint_picker", value_type=int, available_options=[i["value"] for i in options], default=selected_value, ) return [ tdc.Dropdown( id=html_element_id, label="Sprint", options=options, value=selected_value, multi=False, ) ]
def thc_session_picker( selected_session1: str, selected_cmp_session: str, html_element_ids: Tuple = ("session1Picker", "cmpSessionPicker"), ) -> List: """ Returns controls for filtering THC table by sessions. """ # Init controls list and DB session controls = [] selected_sessions = (selected_session1, selected_cmp_session) # Query sessions from DB & add min-/max date for measurement sessions = pd.read_sql( db.session.query( THCMeasurement.session_name.label("session"), func.min(THCMeasurement.measurement_date).label("min_date"), func.max(THCMeasurement.measurement_date).label("max_date"), ) .filter(Team.team_id.in_(current_user.readable_team_ids)) .group_by(THCMeasurement.session_name) .order_by(desc("min_date")) # Order sessions from newest to oldest .statement, db.session.bind, ) # Add controls to list def __session_dropdown_label(row) -> str: """ Creates label for the session dropdown given a row from the DataFrame containing the sessions """ d_min = row["min_date"] d_max = row["max_date"] try: if d_min.month == d_max.month and d_min.year == d_max.year: d1 = d_min.strftime("%b/%d") d2 = d_max.strftime("%d") else: d1 = d_min.strftime("%Y/%b") d2 = d_max.strftime("%b") return f"{row['session']} ({d1}~{d2})" except AttributeError: return f"{row['session']}" options = [ {"label": __session_dropdown_label(row), "value": row["session"]} for _, row in sessions.iterrows() ] for control_i in [0, 1]: selected_value = selected_sessions[control_i] selected_value = state.load_slicer_value( f"thc_session_picker_{control_i}", value_type=str, available_options=[i["value"] for i in options], default=selected_value, ) controls.append( tdc.Dropdown( id=html_element_ids[control_i], labelPrefix="Compare to" if control_i == 1 else "", label="Session", options=options, value=selected_value, ) ) return [ButtonGroup(controls)]