From 3528273b483bfd955392b382e70e4261827eec79 Mon Sep 17 00:00:00 2001 From: Ankan <ankan@kali.Thelair> Date: Wed, 16 Oct 2024 16:58:34 +0200 Subject: [PATCH] =?UTF-8?q?fixa=20errors=20f=C3=B6rhoppningsviss?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyPortfolio/__pycache__/data.cpython-312.pyc | Bin 0 -> 10149 bytes MyPortfolio/data.py | 136 ++++++------------- MyPortfolio/myFlaskProject.py | 25 +++- MyPortfolio/templates/list.html | 50 +++---- MyPortfolio/templates/project_details.html | 52 +++++++ 5 files changed, 141 insertions(+), 122 deletions(-) create mode 100644 MyPortfolio/__pycache__/data.cpython-312.pyc create mode 100644 MyPortfolio/templates/project_details.html diff --git a/MyPortfolio/__pycache__/data.cpython-312.pyc b/MyPortfolio/__pycache__/data.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..618aacba8c6a151f14829d0b0838c58ff65ae75e GIT binary patch literal 10149 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 literal 0 HcmV?d00001 diff --git a/MyPortfolio/data.py b/MyPortfolio/data.py index 0ed38f3..f6a7152 100644 --- a/MyPortfolio/data.py +++ b/MyPortfolio/data.py @@ -4,8 +4,6 @@ # Gör project_id dynamisk sÃ¥ att den uppdateras efter borttagning/addering av projekt. - - # ---- IMPORTS ---- # import os import json @@ -16,9 +14,7 @@ from operator import itemgetter # ---- IMPORTS ---- # - def load(filename): - try: with open(filename, 'r', encoding='utf-8') as file: data = json.load(file) @@ -29,18 +25,14 @@ def load(filename): return None - def save(data): - with open('data.json', 'w', encoding='utf-8') as file: json.dump(data, file, ensure_ascii=False, indent=4) file.close() - # Reload data load() - # Get project count @@ -48,19 +40,15 @@ def get_project_count(data): return len(data) - # Get project by ID def get_project(data, id): - for n in range(0, get_project_count(data)): if data[n]['project_id'] == id: return data[n] - # Get all unique techniques from project def get_techniques(data): - techniques = [] for project in data: for tech in project['techniques_used']: @@ -68,14 +56,12 @@ def get_techniques(data): techniques.append(tech) techniques.sort() - - return techniques + return techniques # Gets all unique techniques from all projects ! COULD USE SOME FILTERING ! def get_technique_stats(data): - technique_list = get_techniques(data) technique_stats = {} current_techniques = [] @@ -83,21 +69,17 @@ def get_technique_stats(data): for technique in technique_list: for project in data: if technique in project['techniques_used']: - current_techniques.append({'id' : project['project_id'], 'name' : project['project_name']}) + current_techniques.append({'id': project['project_id'], 'name': project['project_name']}) - technique_stats.update({technique : current_techniques.copy()}) + technique_stats.update({technique: current_techniques.copy()}) current_techniques.clear() - return technique_stats - # Fetches and sorts projects matching criteria from the specified list. def search(data, sort_by='start_date', sort_order='desc', techniques=None, search=None, search_fields=None): - - if type(search) == str: - + if isinstance(search, str): search = search.lower() results = [] @@ -107,88 +89,78 @@ def search(data, sort_by='start_date', sort_order='desc', techniques=None, searc # sort it results = sorted(results, key=itemgetter(sort_by)) - + # order it - if sort_order == 'desc': results.reverse() + if sort_order == 'desc': + results.reverse() - # filter it (by techniques) - if techniques != None: + if techniques is not None: for technique in get_techniques(data): for project in results: - - if all(n in project['techniques_used'] for n in techniques): pass else: results.pop(results.index(project)) # search for it - if search != None: - + if search is not None: search_results = [] for project in results: - - if search_fields != None and search_fields != "" and search != "": - + if search_fields is not None and search_fields != "" and search != "": for field in search_fields: substring = project[field] - if type(substring) == str: + # Check type before calling lower() + if isinstance(substring, str): substring = substring.lower() if substring.find(search) != -1: search_results.append(project) break - if type(substring) == int: + elif isinstance(substring, int): if str(substring).find(search) != -1: search_results.append(project) break - if type(substring) == list: + elif isinstance(substring, list): for subsubstring in substring: - if type(subsubstring) == str: - if subsubstring.find(search) != -1: + if isinstance(subsubstring, str): + if subsubstring.lower().find(search) != -1: search_results.append(project) break - if type(subsubstring) == int: + elif isinstance(subsubstring, int): if str(subsubstring).find(search) != -1: search_results.append(project) break - - - elif search_fields == "": results.clear() break - + else: for substring in list(project.values()): - substring = substring.lower() - print(type(substring)) - if type(substring) == str: - if substring.find(search) != -1: + # Check type before calling lower() + if isinstance(substring, str): + if substring.lower().find(search) != -1: search_results.append(project) break - if type(substring) == int: + elif isinstance(substring, int): if str(substring).find(search) != -1: search_results.append(project) break - if type(substring) == list: + elif isinstance(substring, list): for subsubstring in substring: - if type(subsubstring) == str: - if subsubstring.find(search) != -1: + if isinstance(subsubstring, str): + if subsubstring.lower().find(search) != -1: search_results.append(project) break - if type(subsubstring) == int: + elif isinstance(subsubstring, int): if str(subsubstring).find(search) != -1: search_results.append(project) break - + results = search_results - - #pprint.pp(results) - return results + return results def cls(): @@ -196,14 +168,12 @@ def cls(): pass - def new_project(data): - cls() # ---- COLLECT INFO ---- project_title = input("Project title: ") - project_id = get_project_count(data)+1 + project_id = get_project_count(data) + 1 techniques = input("\nWhat techniques does your project use? Write them out in the following format: python, java, html, css\n\nTechniques: ").replace(" ", "").lower().split(",") description = input("Provide a description of your project: ") url = input("Provide a link to the source code/demo of your project: ") @@ -212,32 +182,29 @@ def new_project(data): # lexicographical order sort aka alphabetical techniques.sort() - + new_project = { - "project_name": project_title, - "project_id": project_id, - "used_techniques": techniques, - "long_description": description, - "img_url": img_url, - "url": url + "project_name": project_title, + "project_id": project_id, + "used_techniques": techniques, + "long_description": description, + "img_url": img_url, + "url": url } - + cls() - + print("\n\nProject preview:\n") pprint.pp(new_project) option = int(input("\n1: Create\n2: Cancel\n> ")) if option == 1: - data.append(new_project) - save(data) - + pass - def list_projects(data): cls() @@ -246,46 +213,37 @@ def list_projects(data): print("\n") - def edit_project(data, id): - while True: if id > get_project_count(data) or id < 0: print("Project ID doesn't exist.\n") id = int(input("Project_ID to edit: ")) else: - cls() - project = get_project(data, id) - project.pop('project_id') # Project ID shouldn't be changed + project.pop('project_id') # Project ID shouldn't be changed print(f"Editing project: {project['title']}\n") - pprint.pp(project) print("") for field in enumerate(project): print(f"{field[0]}: {field[1]}") - + input("\nField to edit: ") - - + def delete_project(data): pass - def menu(data): - menu_items = ["Add new project", "List projects", "Edit existing project", "Delete project", "Quit"] menu_index = 0 while True: - cls() - + titular = r""" ____ _ __ _ _ | _ \ ___ _ __ | |_ / _| ___ | | (_) ___ @@ -297,7 +255,7 @@ def menu(data): print(titular) for i in menu_items: - print(f"{menu_items.index(i)+1}: {i}") + print(f"{menu_items.index(i) + 1}: {i}") try: option = int(input(f"> ")) @@ -317,17 +275,11 @@ def menu(data): break except: print("") - - - - def main(): - data = load('MyPortfolio/data.json') - if __name__ == "__main__": main() diff --git a/MyPortfolio/myFlaskProject.py b/MyPortfolio/myFlaskProject.py index 63c3209..aadc3af 100644 --- a/MyPortfolio/myFlaskProject.py +++ b/MyPortfolio/myFlaskProject.py @@ -1,7 +1,7 @@ -from flask import Flask, render_template +from flask import Flask, render_template, request from data import * -app = Flask(__name__,template_folder='./templates') +app = Flask(__name__, template_folder='./templates') data = load('data.json') @@ -9,7 +9,22 @@ data = load('data.json') def index(): return render_template('index.html') -@app.route("/list.html") +@app.route("/list.html", methods=['GET', 'POST']) def list(): - return render_template('list.html', - projects = data) \ No newline at end of file + search_query = request.form.get('search', '') + sort_by = request.form.get('sort_by', 'start_date') + sort_order = request.form.get('sort_order', 'desc') + + filtered_projects = search(data, sort_by=sort_by, sort_order=sort_order, search=search_query) + return render_template('list.html', projects=filtered_projects, search_query=search_query, sort_by=sort_by, sort_order=sort_order) + +@app.route("/project/<int:project_id>") +def project_details(project_id): + project = get_project(data, project_id) + if project: + return render_template('project_details.html', project=project) + else: + return "Project not found", 404 + +if __name__ == "__main__": + app.run(debug=True) diff --git a/MyPortfolio/templates/list.html b/MyPortfolio/templates/list.html index a2361d0..96eef4e 100644 --- a/MyPortfolio/templates/list.html +++ b/MyPortfolio/templates/list.html @@ -2,46 +2,46 @@ <html> <head> <link rel="stylesheet" href="../static/style/main.css"> - <link rel="preconnect" href="https://fonts.googleapis.com"> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Afacad+Flux:wght@100..1000&display=swap" rel="stylesheet"> + <title>Projects</title> </head> <body> <header> <ul> <li><a href="/">Home</a></li> <li><a href="techniques.html">Techniques</a></li> - <li><pre class="logo"> -██████╗ ██╗ ██████╗ -██╔â•â•â–ˆâ–ˆâ•—██║██╔â•â•â•â–ˆâ–ˆâ•— -██████╔â•â–ˆâ–ˆâ•‘██║ ██║ -██╔â•â•â•â• ██║██║ ██║ -██║██╗ ██║╚██████╔╠-â•šâ•â•â•šâ•â• â•šâ•â• â•šâ•â•â•â•â•â•</pre></li> <li><a href="list.html">Projects</a></li> <li><a href="https://github.com/olma957">GitHub</a></li> - </ul> + </ul> </header> <div class="content-container"> - <div class="project-table"> + <!-- Search and Sort Form --> + <form method="POST" action="/list.html"> + <input type="text" name="search" placeholder="Search projects" value="{{ search_query }}"> + <select name="sort_by"> + <option value="start_date" {% if sort_by == 'start_date' %}selected{% endif %}>Start Date</option> + <option value="project_name" {% if sort_by == 'project_name' %}selected{% endif %}>Project Name</option> + <option value="group_size" {% if sort_by == 'group_size' %}selected{% endif %}>Group Size</option> + <option value="lulz_had" {% if sort_by == 'lulz_had' %}selected{% endif %}>Lulz Had</option> + </select> + <select name="sort_order"> + <option value="desc" {% if sort_order == 'desc' %}selected{% endif %}>Descending</option> + <option value="asc" {% if sort_order == 'asc' %}selected{% endif %}>Ascending</option> + </select> + <button type="submit">Search</button> + </form> + <!-- Project List --> + <div class="project-table"> {% for p in projects %} - <div class="project"> - - - - <img class="project-img" src={{ p['small_image'] }}> - - <p class="project-title"> >{{ p['project_name'] }} </p> - - <p class="project-desc"> {{ p['short_description'] }}</p> - + <a href="/project/{{ p['project_id'] }}"> + <img class="project-img" src="{{ p['small_image'] }}"> + <p class="project-title"> >{{ p['project_name'] }} </p> + <p class="project-desc"> {{ p['short_description'] }}</p> + </a> </div> - {% endfor %} - </div> </div> @@ -61,4 +61,4 @@ </p> </footer> </body> -</html> \ No newline at end of file +</html> diff --git a/MyPortfolio/templates/project_details.html b/MyPortfolio/templates/project_details.html new file mode 100644 index 0000000..4bb6004 --- /dev/null +++ b/MyPortfolio/templates/project_details.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="stylesheet" href="../static/style/main.css"> + <title>{{ project['project_name'] }}</title> +</head> +<body> + <header> + <ul> + <li><a href="/">Home</a></li> + <li><a href="techniques.html">Techniques</a></li> + <li><a href="list.html">Projects</a></li> + <li><a href="https://github.com/olma957">GitHub</a></li> + </ul> + </header> + + <div class="content-container"> + <h1>{{ project['project_name'] }}</h1> + <img src="{{ project['big_image'] }}" alt="Project Image"> + + <ul> + <li><strong>Course Name:</strong> {{ project['course_name'] }}</li> + <li><strong>Group Size:</strong> {{ project['group_size'] }}</li> + <li><strong>Start Date:</strong> {{ project['start_date'] }}</li> + <li><strong>End Date:</strong> {{ project['end_date'] }}</li> + <li><strong>Techniques Used:</strong> {{ project['techniques_used'] | join(', ') }}</li> + <li><strong>Description:</strong> {{ project['long_description'] }}</li> + <li><strong>Academic Credits:</strong> {{ project['academic_credits'] }}</li> + <li><strong>Lulz Had:</strong> {{ project['lulz_had'] }}</li> + <li><strong>External Link:</strong> <a href="{{ project['external_link'] }}" target="_blank">{{ project['external_link'] }}</a></li> + </ul> + + <a href="/list.html">Back to Projects</a> + </div> + + <footer> + <p>Authors:<br> + <a href="mailto:olima957@student.liu.se">Oliwer Mattsson: olima957@student.liu.se</a><br> + <a href="mailto:taiku983@student.liu.se">Taif Kurji: taiku983@student.liu.se</a> + </p> + <p>License:<br> + <a href="https://www.gnu.org/licenses/gpl-3.0.html">GPLv3 License</a> + </p> + <p>Links:<br> + <a href="/">Home</a><br> + <a href="techniques.html">Techniques</a><br> + <a href="list.html">Projects</a><br> + <a href="https://github.com/olma957">GitHub</a> + </p> + </footer> +</body> +</html> -- GitLab