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