def tasks_from_calendar(self, year: int, month: int, data: Dict) -> Dict: if not data or KEY_TASKS not in data: raise ValueError("Incomplete data for calendar") if not all([ KEY_NORMAL_TASK in data[KEY_TASKS], KEY_REPETITIVE_TASK in data[KEY_TASKS], KEY_REPETITIVE_HIDDEN_TASK in data[KEY_TASKS] ]): raise ValueError("Incomplete data for calendar") tasks = {} # type: Dict current_day, current_month, current_year = GregorianCalendar.current_date( ) for day in GregorianCalendar.month_days(year, month): month_str = str(day.month) year_str = str(day.year) if (year_str in data[KEY_TASKS][KEY_NORMAL_TASK] and month_str in data[KEY_TASKS][KEY_NORMAL_TASK][year_str] and month_str not in tasks): tasks[month_str] = data[KEY_TASKS][KEY_NORMAL_TASK][year_str][ month_str] return tasks
def main_calendar_action(calendar_id: str) -> Response: GregorianCalendar.setfirstweekday(current_app.config["WEEK_STARTING_DAY"]) current_day, current_month, current_year = GregorianCalendar.current_date() year = int(request.args.get("y", current_year)) year = max(min(year, current_app.config["MAX_YEAR"]), current_app.config["MIN_YEAR"]) month = int(request.args.get("m", current_month)) month = max(min(month, 12), 1) month_name = GregorianCalendar.MONTH_NAMES[month - 1] if current_app.config["HIDE_PAST_TASKS"]: view_past_tasks = False else: view_past_tasks = request.cookies.get("ViewPastTasks", "1") == "1" calendar_data = CalendarData(current_app.config["DATA_FOLDER"], current_app.config["WEEK_STARTING_DAY"]) try: data = calendar_data.load_calendar(calendar_id) except FileNotFoundError: abort(404) tasks = calendar_data.tasks_from_calendar(year, month, data) tasks = calendar_data.add_repetitive_tasks_from_calendar( year, month, data, tasks) if not view_past_tasks: calendar_data.hide_past_tasks(year, month, tasks) if current_app.config[ "WEEK_STARTING_DAY"] == constants.WEEK_START_DAY_MONDAY: weekdays_headers = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"] else: weekdays_headers = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"] return cast( Response, render_template( "calendar.html", calendar_id=calendar_id, year=year, month=month, month_name=month_name, current_year=current_year, current_month=current_month, current_day=current_day, month_days=GregorianCalendar.month_days(year, month), previous_month_link=previous_month_link(year, month), next_month_link=next_month_link(year, month), base_url=current_app.config["BASE_URL"], tasks=tasks, display_view_past_button=current_app. config["SHOW_VIEW_PAST_BUTTON"], weekdays_headers=weekdays_headers, ), )
def new_task_action(calendar_id: str, year: int, month: int) -> Response: GregorianCalendar.setfirstweekday(current_app.config["WEEK_STARTING_DAY"]) calendar_data = CalendarData(current_app.config["DATA_FOLDER"], current_app.config["WEEK_STARTING_DAY"]) try: data = calendar_data.load_calendar(calendar_id) except FileNotFoundError: abort(404) current_day, current_month, current_year = GregorianCalendar.current_date() year = max(min(int(year), current_app.config["MAX_YEAR"]), current_app.config["MIN_YEAR"]) month = max(min(int(month), 12), 1) month_names = GregorianCalendar.MONTH_NAMES accounts = calendar_data.accounts_from_calendar(data) if current_month == month and current_year == year: day = current_day else: day = 1 day = int(request.args.get("day", day)) task = { "date": CalendarData.date_for_frontend(year, month, day), "repeats": False, "details": "", } emojis_enabled = current_app.config.get("EMOJIS_ENABLED", False) return cast( Response, render_template( "task.html", calendar_id=calendar_id, year=year, month=month, min_year=current_app.config["MIN_YEAR"], max_year=current_app.config["MAX_YEAR"], month_names=month_names, task=task, accounts=accounts, base_url=current_app.config["BASE_URL"], editing=False, emojis_enabled=emojis_enabled, button_default_color_value=current_app. config["BUTTON_CUSTOM_COLOR_VALUE"], buttons_colors=current_app.config["BUTTONS_COLORS_LIST"], buttons_emojis=current_app.config["BUTTONS_EMOJIS_LIST"] if emojis_enabled else tuple(), ), )
def _repetitive_tasks_from_calendar(self, year: int, month: int, data: Dict) -> Dict: if KEY_TASKS not in data: ValueError("Incomplete data for calendar") if KEY_REPETITIVE_TASK not in data[KEY_TASKS]: ValueError("Incomplete data for calendar") repetitive_tasks = {} # type: Dict year_and_months = set([ (source_day.year, source_day.month) for source_day in GregorianCalendar.month_days(year, month) ]) for source_year, source_month in year_and_months: month_str = str(source_month) year_str = str(source_year) repetitive_tasks[month_str] = {} for task in data[KEY_TASKS][KEY_REPETITIVE_TASK]: id_str = str(task["id"]) monthly_task_assigned = False for week in GregorianCalendar.month_days_with_weekday( source_year, source_month): for weekday, day in enumerate(week): if day == 0: continue day_str = str(day) if (task["repetition_type"] == self.REPETITION_TYPE_WEEKLY and not self._is_repetition_hidden_for_day( data, id_str, year_str, month_str, str(day)) and task["repetition_value"] == weekday): self.add_task_to_list(repetitive_tasks, day_str, month_str, task) elif (task["repetition_type"] == self.REPETITION_TYPE_MONTHLY and not self._is_repetition_hidden( data, id_str, year_str, month_str)): if task["repetition_subtype"] == self.REPETITION_SUBTYPE_WEEK_DAY: if task["repetition_value"] == weekday and not monthly_task_assigned: monthly_task_assigned = True self.add_task_to_list( repetitive_tasks, day_str, month_str, task) else: if task["repetition_value"] == day: self.add_task_to_list( repetitive_tasks, day_str, month_str, task) return repetitive_tasks
def hide_past_tasks(self, year: int, month: int, tasks: Dict) -> None: current_day, current_month, current_year = GregorianCalendar.current_date( ) for day in GregorianCalendar.month_days(year, month): month_str = str(day.month) if self.is_past(day.year, day.month, current_year, current_month): tasks[month_str] = {} for task_day_number in tasks[month_str]: if day.month == current_month and int( task_day_number) < current_day: tasks[month_str][task_day_number] = []
def new_task_action(calendar_id: str, year: int, month: int) -> Response: current_day, current_month, current_year = GregorianCalendar.current_date() year = max(min(int(year), config.MAX_YEAR), config.MIN_YEAR) month = max(min(int(month), 12), 1) month_names = GregorianCalendar.MONTH_NAMES if current_month == month and current_year == year: day = current_day else: day = 1 day = int(request.args.get("day", day)) task = { "date": CalendarData.date_for_frontend(year, month, day), "is_all_day": True, "repeats": False, "details": "" } return cast( Response, render_template("task.html", calendar_id=calendar_id, year=year, month=month, min_year=config.MIN_YEAR, max_year=config.MAX_YEAR, month_names=month_names, task=task, base_url=config.BASE_URL, editing=False))
def next_month_link(year: int, month: int) -> str: month, year = GregorianCalendar.next_month_and_year(year=year, month=month) return ( "" if year < current_app.config['MIN_YEAR'] or year > current_app.config['MAX_YEAR'] else "?y={}&m={}".format(year, month) )
def main_calendar_action(calendar_id: str) -> Response: current_day, current_month, current_year = GregorianCalendar.current_date() year = int(request.args.get("y", current_year)) year = max(min(year, config.MAX_YEAR), config.MIN_YEAR) month = int(request.args.get("m", current_month)) month = max(min(month, 12), 1) month_name = GregorianCalendar.MONTH_NAMES[month - 1] if config.HIDE_PAST_TASKS: view_past_tasks = False else: view_past_tasks = request.cookies.get("ViewPastTasks", "1") == "1" calendar_data = CalendarData(config.DATA_FOLDER) try: data = calendar_data.load_calendar(calendar_id) except FileNotFoundError: abort(404) tasks = calendar_data.tasks_from_calendar(year, month, data) tasks = calendar_data.add_repetitive_tasks_from_calendar( year, month, data, tasks) if not view_past_tasks: calendar_data.hide_past_tasks(year, month, tasks) return cast( Response, render_template("calendar.html", calendar_id=calendar_id, year=year, month=month, month_name=month_name, current_year=current_year, current_month=current_month, current_day=current_day, month_days=GregorianCalendar.month_days(year, month), previous_month_link=previous_month_link(year, month), next_month_link=next_month_link(year, month), base_url=config.BASE_URL, tasks=tasks, display_view_past_button=config.SHOW_VIEW_PAST_BUTTON))
def add_repetitive_tasks_from_calendar(self, year: int, month: int, data: Dict, tasks: Dict) -> Dict: current_day, current_month, current_year = GregorianCalendar.current_date( ) repetitive_tasks = self._repetitive_tasks_from_calendar( year, month, data) for repetitive_tasks_month in repetitive_tasks: for day, day_tasks in repetitive_tasks[ repetitive_tasks_month].items(): if repetitive_tasks_month not in tasks: tasks[repetitive_tasks_month] = {} if day not in tasks[repetitive_tasks_month]: tasks[repetitive_tasks_month][day] = [] for task in day_tasks: tasks[repetitive_tasks_month][day].append(task) return tasks
def _clear_past_hidden_entries(data: Dict) -> None: _, current_month, current_year = GregorianCalendar.current_date() # normalize to 1st day of month current_date = datetime(current_year, current_month, 1, 0, 0) tasks_to_delete = [] for task_id in data[KEY_TASKS][KEY_REPETITIVE_HIDDEN_TASK]: for year in data[KEY_TASKS][KEY_REPETITIVE_HIDDEN_TASK][task_id]: for month in data[KEY_TASKS][KEY_REPETITIVE_HIDDEN_TASK][ task_id][year]: task_date = datetime(int(year), int(month), 1, 0, 0) if (current_date - task_date).days > current_app.config[ 'DAYS_PAST_TO_KEEP_HIDDEN_TASKS']: tasks_to_delete.append((year, month, task_id)) for task_info in tasks_to_delete: year, month, task_id = task_info del (data[KEY_TASKS][KEY_REPETITIVE_HIDDEN_TASK][task_id][year] [month]) if len(data[KEY_TASKS][KEY_REPETITIVE_HIDDEN_TASK][task_id]) == 0: del (data[KEY_TASKS][KEY_REPETITIVE_HIDDEN_TASK][task_id])
def previous_month_link(year: int, month: int) -> str: month, year = GregorianCalendar.previous_month_and_year(year=year, month=month) return ("" if year < current_app.config["MIN_YEAR"] or year > current_app.config["MAX_YEAR"] else "?y={}&m={}".format( year, month))
def next_month_link(year: int, month: int) -> str: month, year = GregorianCalendar.next_month_and_year(year=year, month=month) return "" if year < config.MIN_YEAR or year > config.MAX_YEAR else "?y={}&m={}".format( year, month)