From 3f70d4266e01f40d9cf55768e69f96497872d21c Mon Sep 17 00:00:00 2001
From: James2Tulloch <146088090+James2Tulloch@users.noreply.github.com>
Date: Wed, 5 Mar 2025 14:38:33 +0000
Subject: [PATCH] Working group search

---
 django_project/django_project/settings.py     |  7 +++--
 django_project/django_project/urls.py         |  5 ++--
 django_project/myapp/context_processors.py    |  5 ++++
 .../myapp/templates/myapp/base.html           |  6 ++++
 .../myapp/templates/myapp/group_search.html   | 29 +++++++++++++++++++
 django_project/myapp/views/groupviews.py      | 17 +++++++++--
 rust_crud_api/src/db/groups.rs                | 18 ++++++++++++
 rust_crud_api/src/db/mod.rs                   |  2 +-
 rust_crud_api/src/lib.rs                      |  1 +
 9 files changed, 83 insertions(+), 7 deletions(-)
 create mode 100644 django_project/myapp/context_processors.py
 create mode 100644 django_project/myapp/templates/myapp/group_search.html

diff --git a/django_project/django_project/settings.py b/django_project/django_project/settings.py
index 6260cbc..b8db664 100644
--- a/django_project/django_project/settings.py
+++ b/django_project/django_project/settings.py
@@ -71,7 +71,10 @@ ROOT_URLCONF = 'django_project.urls'
 TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [BASE_DIR / "templates"],
+        'DIRS': [
+            BASE_DIR / "myapp" / "templates" / "myapp", 
+            BASE_DIR / "myapp" / "templates",  
+        ],
         'APP_DIRS': True,
         'OPTIONS': {
             'context_processors': [
@@ -79,6 +82,7 @@ TEMPLATES = [
                 'django.template.context_processors.request',
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
+                'myapp.context_processors.global_search',
             ],
         },
     },
@@ -86,7 +90,6 @@ TEMPLATES = [
 
 WSGI_APPLICATION = 'django_project.wsgi.application'
 
-
 # Database
 # https://docs.djangoproject.com/en/5.1/ref/settings/#databases
 
diff --git a/django_project/django_project/urls.py b/django_project/django_project/urls.py
index 0e0131b..5a365f3 100644
--- a/django_project/django_project/urls.py
+++ b/django_project/django_project/urls.py
@@ -21,7 +21,7 @@ from django.conf.urls.static import static
 
 from myapp.views.authviews import login_view, logout_view
 from myapp.views.userviews import register_view, account_view, delete_account_view, welcome_view, edit_account_view
-from myapp.views.groupviews import group_list_view, group_create_view, group_update_view, group_delete_view, group_detail_view
+from myapp.views.groupviews import group_list_view, group_create_view, group_update_view, group_delete_view, group_detail_view, group_search_view
 from myapp.views.postviews import create_post_view, feed_view
 from myapp.views.initview import init_db_view
 
@@ -41,7 +41,8 @@ urlpatterns = [
     path('post/create/', create_post_view, name='create_post'),
     path('feed/', feed_view, name='feed'),
     path('welcome/', welcome_view, name='welcome'),
-    path('edit_account/', edit_account_view, name='edit_account')
+    path('edit_account/', edit_account_view, name='edit_account'),
+    path('group_search', group_search_view, name='group_search')
 ]
 
 if settings.DEBUG:
diff --git a/django_project/myapp/context_processors.py b/django_project/myapp/context_processors.py
new file mode 100644
index 0000000..e49d6ec
--- /dev/null
+++ b/django_project/myapp/context_processors.py
@@ -0,0 +1,5 @@
+def global_search(request):
+    """
+    Makes the search query globally available in all templates.
+    """
+    return {"search_query": request.GET.get("q", "")}
diff --git a/django_project/myapp/templates/myapp/base.html b/django_project/myapp/templates/myapp/base.html
index 13acf3d..e1e4c4e 100644
--- a/django_project/myapp/templates/myapp/base.html
+++ b/django_project/myapp/templates/myapp/base.html
@@ -40,7 +40,13 @@
             <li><a href="{% url 'account' %}">Account</a></li>
             <li><a href="{% url 'group_list' %}">Groups</a></li>
             <li><a href="{% url 'logout' %}">Logout</a></li>
+            
         </ul>
+
+        <form method="GET" action="{% url 'group_search' %}">
+            <input type="text" name="q" placeholder="Search for groups..." value="{{ search_query }}">
+            <button type="submit">Search</button>
+        </form>
     </nav>
 
     <!-- Page Content -->
diff --git a/django_project/myapp/templates/myapp/group_search.html b/django_project/myapp/templates/myapp/group_search.html
new file mode 100644
index 0000000..aebe2a2
--- /dev/null
+++ b/django_project/myapp/templates/myapp/group_search.html
@@ -0,0 +1,29 @@
+{% extends "base.html" %}
+
+{% block content %}
+    <h2>Search for Groups</h2>
+
+    <!-- Search Form -->
+    <form method="GET" action="{% url 'group_search' %}">
+        <input type="text" name="q" placeholder="Search for groups..." value="{{ query }}">
+        <button type="submit">Search</button>
+    </form>
+
+    <!-- Error Message -->
+    {% if error %}
+        <p style="color: red;">{{ error }}</p>
+    {% endif %}
+
+    <!-- Search Results -->
+    {% if groups %}
+        <h3>Results:</h3>
+        <ul>
+            {% for group in groups %}
+                <li>{{ group.name }}</li>
+            {% endfor %}
+        </ul>
+    {% else %}
+        <p>No groups found.</p>
+    {% endif %}
+{% endblock %}
+
diff --git a/django_project/myapp/views/groupviews.py b/django_project/myapp/views/groupviews.py
index e5e6b58..4617d49 100644
--- a/django_project/myapp/views/groupviews.py
+++ b/django_project/myapp/views/groupviews.py
@@ -61,7 +61,6 @@ def group_update_view(request, group_id):
             context['group'] = group
             return render(request, 'myapp/group_update.html', context)
         try:
-            # This assumes you've implemented an `update_group` function in your Rust library.
             rust_crud_api.update_group(db_url, int(group_id), new_name)
             return redirect('group_list')
         except Exception as e:
@@ -80,7 +79,6 @@ def group_delete_view(request, group_id):
     context = {}
     if request.method == 'POST':
         try:
-            # This assumes you have a `delete_group` function in your Rust library.
             success = rust_crud_api.delete_group(db_url, int(group_id))
             if success:
                 return redirect('group_list')
@@ -111,3 +109,18 @@ def group_detail_view(request, group_id):
         context['error'] = f"An error occurred: {e}"
     return render(request, 'myapp/group_detail.html', context)
 
+def group_search_view(request):
+    """
+    Handles searching for groups using Rust.
+    """
+    db_url = settings.DATABASE_URL  
+    query = request.GET.get("q", "").strip()  
+    groups = [] 
+    if query:
+        try:
+            groups = rust_crud_api.search_groups(db_url, query) 
+        except Exception as e:
+            return render(request, "group_search.html", {"error": str(e), "query": query})
+
+    return render(request, "group_search.html", {"groups": groups, "query": query})
+
diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs
index 5ef592d..d98d1f7 100644
--- a/rust_crud_api/src/db/groups.rs
+++ b/rust_crud_api/src/db/groups.rs
@@ -102,3 +102,21 @@ pub fn delete_group(db_url: &str, group_id: i32) -> PyResult<bool> {
     ).map_err(pg_err)?;
     Ok(deleted > 0)
 }
+
+#[pyfunction]
+pub fn search_groups(db_url: &str, query: &str) -> PyResult<Vec<Group>> {
+    let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
+    let rows = client.query(
+        "SELECT id, name FROM groups WHERE name ILIKE $1",
+        &[&format!("%{}%", query)] 
+    ).map_err(pg_err)?;
+
+    let groups: Vec<Group> = rows.iter()
+        .map(|row| Group {
+            id: Some(row.get(0)),
+            name: row.get(1),
+        })
+        .collect();
+
+    Ok(groups)
+}
diff --git a/rust_crud_api/src/db/mod.rs b/rust_crud_api/src/db/mod.rs
index b59c637..5d9ae31 100644
--- a/rust_crud_api/src/db/mod.rs
+++ b/rust_crud_api/src/db/mod.rs
@@ -5,5 +5,5 @@ pub mod posts;
 
 pub use init::init_db;
 pub use users::{create_user, get_user, get_all_users, update_user, delete_user, update_first_login};
-pub use groups::{create_group, get_group, get_all_groups, add_user_to_group, get_group_members, delete_group};
+pub use groups::{create_group, get_group, get_all_groups, add_user_to_group, get_group_members, delete_group, search_groups};
 pub use posts::{create_post, get_user_posts, get_group_posts, get_feed};
diff --git a/rust_crud_api/src/lib.rs b/rust_crud_api/src/lib.rs
index 6daa866..05e21a9 100644
--- a/rust_crud_api/src/lib.rs
+++ b/rust_crud_api/src/lib.rs
@@ -36,6 +36,7 @@ fn rust_crud_api(_py: Python, m: &PyModule) -> PyResult<()> {
     m.add_function(wrap_pyfunction!(db::groups::add_user_to_group, m)?)?;
     m.add_function(wrap_pyfunction!(db::groups::get_group_members, m)?)?;
     m.add_function(wrap_pyfunction!(db::groups::delete_group, m)?)?;
+    m.add_function(wrap_pyfunction!(db::groups::search_groups, m)?)?;
     // Posts
     m.add_function(wrap_pyfunction!(db::posts::create_post, m)?)?;
     m.add_function(wrap_pyfunction!(db::posts::get_user_posts, m)?)?;
-- 
GitLab