diff --git a/add_entry.py b/add_entry.py new file mode 100644 index 0000000..768c99c --- /dev/null +++ b/add_entry.py @@ -0,0 +1,50 @@ +import os +import csv +from datetime import datetime + +from clear_console import clear + + +def add_entry(): + print('Date of the task') + while True: + try: + date = input('Please use DD/MM/YYYY: ') + valid_date = datetime.strptime(date, '%d/%m/%Y') + break + except: + clear() + print(f'{date} is not a valid date') + input('Press enter to try again') + continue + clear() + title = input('Title of the task: ') + clear() + while True: + try: + time = input('Time spent (rounded minutes): ') + valid_time = int(time) + break + except: + clear() + print(f'{time} is not a valid number') + input('Press enter to try again') + continue + clear() + notes = input('Notes (Optional, you can leave this empty): ') + clear() + # https://stackoverflow.com/questions/2507808/how-to-check-whether-a-file-is-empty-or-not + file_exist = os.path.isfile('log.csv') and os.path.getsize('log.csv') > 0 + # write csv file + with open('log.csv', 'a', newline='') as csvfile: + fieldnames = ['date', 'title', 'time', 'notes'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + if not file_exist: + writer.writeheader() + writer.writerow({ + 'date': valid_date.date(), + 'title': title, + 'time': valid_time, + 'notes': notes + }) + input('The entry has been added. Press enter to return to the menu.') diff --git a/clear_console.py b/clear_console.py new file mode 100644 index 0000000..77c375d --- /dev/null +++ b/clear_console.py @@ -0,0 +1,6 @@ +import os + + +def clear(): + # https://stackoverflow.com/questions/517970/how-to-clear-the-interpreter-console + os.system('cls' if os.name == 'nt' else 'clear') diff --git a/edit_entry.py b/edit_entry.py new file mode 100644 index 0000000..d853cd5 --- /dev/null +++ b/edit_entry.py @@ -0,0 +1,76 @@ +import csv +from datetime import datetime + +from clear_console import clear + + +def edit_entry(line, entry_to_edit=None): + clear() + entries = [] + fieldnames = ['date', 'title', 'time', 'notes'] + with open('log.csv', 'r', newline='') as csvfile: + reader = csv.DictReader(csvfile, fieldnames=fieldnames) + for line_number, entry in enumerate(reader): + if line_number == 0: + continue + if line_number == line: + # entry=None => delete entry + if entry_to_edit is None: + continue + # edit entry + else: + clear() + print('What whould you like to edit?') + while True: + choice = input( + '1: Date\n' + + '2: Title\n' + + '3: Time\n' + + '4: Notes\n') + if choice in '1234': + break + else: + clear() + print(f'Option {choice} is not in the menu') + input('Press enter to try again') + continue + clear() + if choice in '1': + while True: + try: + date = input('Please use DD/MM/YYYY: ') + entry['date'] = datetime.strptime( + date, '%d/%m/%Y').date() + break + except: + clear() + print(f'{date} is not a valid date') + input('Press enter to try again') + continue + if choice in '2': + entry['title'] = input('Enter new title: ') + if choice in '3': + while True: + try: + time = input( + 'Time spent (rounded minutes): ') + entry['time'] = int(time) + break + except: + clear() + print(f'{time} is not a valid number') + input('Press enter to try again') + continue + if choice in '4': + entry['notes'] = input('Enter new notes: ') + entries.append(entry) + with open('log.csv', 'w', newline='') as csvfile: + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + for entry in entries: + writer.writerow({ + 'date': entry['date'], + 'title': entry['title'], + 'time': entry['time'], + 'notes': entry['notes'] + }) diff --git a/entry_search.py b/entry_search.py new file mode 100644 index 0000000..7e5d38e --- /dev/null +++ b/entry_search.py @@ -0,0 +1,35 @@ +from clear_console import clear +from search_options import date_search, date_range_search, regex_search + + +def search_entry(): + print('Do you want to search by:') + while True: + choice = input( + '1: Exact Date\n' + + '2: Range of Dates\n' + + '3: Exact Search\n' + + '4: Regex pattern\n' + + '5: Return to menu\n') + if choice in '12345': + break + else: + clear() + print(f'Option {choice} is not in the menu') + input('Press enter to try again') + continue + clear() + if choice in '1': + date_search() + elif choice in '2': + date_range_search() + elif choice in '3': + print('Enter search pattern') + # normal search can use regex function to search + regex_search() + elif choice in '4': + print('Enter regex pattern') + regex_search() + elif choice in '5': + # return to the start menu + return diff --git a/log.csv b/log.csv new file mode 100644 index 0000000..7d211e7 --- /dev/null +++ b/log.csv @@ -0,0 +1,6 @@ +date,title,time,notes +2015-03-19,task-1-edit,850,task-1-note-edit +2018-02-21,task-2,150,task 2 notes +2019-02-24,task-4,550,task 4 note +2019-02-26,task-5,1500,task 5 note +2019-03-25,names,485,note diff --git a/menu.py b/menu.py new file mode 100644 index 0000000..87f97a2 --- /dev/null +++ b/menu.py @@ -0,0 +1,20 @@ +from clear_console import clear + + +def menu(): + # prints the main menu + print('WORK LOG') + print('What whould you like to do?') + while True: + answer = input( + '1: Add new entry \n' + + '2: Search in existing entries\n' + + '3: Quit Program\n') + if answer in '123': + break + else: + clear() + print(f'Option {answer} is not in the menu. Please choose again.') + continue + clear() + return answer diff --git a/print_entries.py b/print_entries.py new file mode 100644 index 0000000..d85029c --- /dev/null +++ b/print_entries.py @@ -0,0 +1,56 @@ +from clear_console import clear +from edit_entry import edit_entry + + +def print_entries(entries): + clear() + if len(entries) == 0: + print('No entries found') + input('Press enter to return to menu') + return + index = 0 + while True: + clear() + line_number, entry = entries[index] + print(f'Date: {entry["date"]}') + print(f'Title: {entry["title"]}') + print(f'Time spent: {entry["time"]}') + print(f'Notes: {entry["notes"]}\n') + print(f'Result {index + 1} of {len(entries)}\n') + option_without_prev = ('[N]ext, [E]dit, [D]elete, ' + + '[R]eturn to search menu\n') + option_with_prev = ('[P]revious, [N]ext, [E]dit, [D]elete, ' + + '[R]eturn to search menu\n') + option_without_next = ('[P]revious, [E]dit, [D]elete, ' + + '[R]eturn to search menu\n') + option_without_next_prev = ('[E]dit, [D]elete, ' + + '[R]eturn to search menu\n') + if index == 0 and len(entries) == 1: + option = input(option_without_next_prev) + elif index == 0: + option = input(option_without_prev) + elif index + 1 == len(entries): + option = input(option_without_next) + else: + option = input(option_with_prev) + option = option.upper() + if option in 'NPEDR': + if option in 'N': + if index + 1 == len(entries): + continue + index += 1 + if option in 'P': + if index == 0: + continue + index -= 1 + # return in options E and D because the data displayed will be old + if option in 'E': + edit_entry(line_number, entry_to_edit=entries[index]) + return + if option in 'D': + edit_entry(line_number) + return + if option in 'R': + return + else: + continue diff --git a/search_options.py b/search_options.py new file mode 100644 index 0000000..10448b1 --- /dev/null +++ b/search_options.py @@ -0,0 +1,79 @@ +import csv +from datetime import datetime +import re + +from clear_console import clear +from print_entries import print_entries + + +def date_search(): + entries = [] + while True: + try: + print('Enter the date') + date = input('Please use DD/MM/YYYY: ') + valid_date = datetime.strptime(date, '%d/%m/%Y') + break + except: + print(f'{date} is not a valid date') + input('Press enter to try again') + clear() + continue + with open('log.csv', 'r', newline='') as csvfile: + fieldnames = ['date', 'title', 'time', 'notes'] + reader = csv.DictReader(csvfile, fieldnames=fieldnames) + for line_number, entry in enumerate(reader): + if line_number == 0: + continue + if valid_date == datetime.strptime(entry['date'], '%Y-%m-%d'): + entries.append((line_number, entry)) + print_entries(entries) + + +def date_range_search(): + entries = [] + while True: + try: + print('Enter the date range') + date1 = input('Please use DD/MM/YYYY date #1: ') + date2 = input('Please use DD/MM/YYYY date #2: ') + valid_date1 = datetime.strptime(date1, '%d/%m/%Y') + valid_date2 = datetime.strptime(date2, '%d/%m/%Y') + break + except: + print('One of the date are not a valid date') + input('Press enter to try again') + clear() + continue + with open('log.csv', 'r', newline='') as csvfile: + fieldnames = ['date', 'title', 'time', 'notes'] + reader = csv.DictReader(csvfile, fieldnames=fieldnames) + for line_number, entry in enumerate(reader): + if line_number == 0: + continue + date = datetime.strptime(entry['date'], '%Y-%m-%d') + # does not matter which value is higher + if valid_date1 < valid_date2: + if valid_date1 <= date <= valid_date2: + entries.append((line_number, entry)) + else: + if valid_date1 >= date >= valid_date2: + entries.append((line_number, entry)) + print_entries(entries) + + +def regex_search(): + entries = [] + pattern = input() + raw_pattern = r'{}'.format(pattern) + compiled_pattern = re.compile(raw_pattern, re.I) + with open('log.csv', 'r', newline='') as csvfile: + fieldnames = ['date', 'title', 'time', 'notes'] + reader = csv.DictReader(csvfile, fieldnames=fieldnames) + for line_number, entry in enumerate(reader): + if line_number == 0: + continue + if (compiled_pattern.search(entry['title']) or + compiled_pattern.search(entry['notes'])): + entries.append((line_number, entry)) + print_entries(entries) diff --git a/work_log.py b/work_log.py new file mode 100644 index 0000000..c7112cc --- /dev/null +++ b/work_log.py @@ -0,0 +1,15 @@ +from menu import menu +from clear_console import clear +from add_entry import add_entry +from entry_search import search_entry + +if __name__ == "__main__": + while True: + clear() + choice = menu() + if choice == '3': + break + elif choice == '1': + add_entry() + elif choice == '2': + search_entry()