diff --git a/django_project/myapp/templates/myapp/base.html b/django_project/myapp/templates/myapp/base.html index e1e4c4ee583317f2196a9018da3028102fd3902f..e8b3af8583c86c36ca60ea3d3104047b49de919a 100644 --- a/django_project/myapp/templates/myapp/base.html +++ b/django_project/myapp/templates/myapp/base.html @@ -26,6 +26,10 @@ nav li a:hover { background-color: #111; } + nav form { + float: right; + margin: 10px; + } .container { margin: 20px; } @@ -40,15 +44,12 @@ <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> - + <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> </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 --> <div class="container"> {% block content %} diff --git a/django_project/myapp/templates/myapp/group_create.html b/django_project/myapp/templates/myapp/group_create.html index d1a52b690eb98f1b616f4e5e6f92e5a734312b44..3017595604d87f84ae93de4f80911891a76c0044 100644 --- a/django_project/myapp/templates/myapp/group_create.html +++ b/django_project/myapp/templates/myapp/group_create.html @@ -17,6 +17,6 @@ <button type="submit">Create Group</button> </form> <p><a href="{% url 'group_list' %}">Back to Group List</a></p> -</body> +</body> </html> diff --git a/django_project/myapp/templates/myapp/group_list.html b/django_project/myapp/templates/myapp/group_list.html index 9f1d94d3c8f95945d111cfa4b310c58b735ff31a..9c012dc5f98672513480e6be6a485cd03e055a45 100644 --- a/django_project/myapp/templates/myapp/group_list.html +++ b/django_project/myapp/templates/myapp/group_list.html @@ -4,17 +4,21 @@ {% block content %} <h1>Groups</h1> - {% if error %} - <p style="color: red;">{{ error }}</p> - {% endif %} - <ul> - {% for group in groups %} - <li> - <a href="{% url 'group_detail' group.id %}">{{ group.name }}</a> - </li> - {% empty %} - <li>No groups available.</li> - {% endfor %} - </ul> + + {% if error %} + <p style="color: red;">{{ error }}</p> + {% endif %} + + <ul> + {% for group in groups %} + <li> + <!-- Hyperlinked Group Name --> + <a href="{% url 'group_detail' group.id %}">{{ group.name }}</a> + + </li> + {% empty %} + <li>No groups available.</li> + {% endfor %} + </ul> {% endblock %} diff --git a/django_project/myapp/views/groupviews.py b/django_project/myapp/views/groupviews.py index 4617d49d9c4671464b61f707f40cd88a7acba706..f73ac8a45f07274db93d13d722f4601c02de73aa 100644 --- a/django_project/myapp/views/groupviews.py +++ b/django_project/myapp/views/groupviews.py @@ -100,15 +100,27 @@ def group_detail_view(request, group_id): """ db_url = settings.DATABASE_URL context = {} + try: + # Fetch group details group = rust_crud_api.get_group(db_url, group_id) if group is None: return HttpResponseNotFound("Group not found.") + + # Fetch group members and member count + members, member_count = rust_crud_api.get_group_members(db_url, group_id) + + # Populate context with group details context['group'] = group + context['members'] = members + context['member_count'] = member_count + except Exception as e: 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. diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs index d98d1f78bc5f057c24822b870a9963e035d6cd8f..e553482d0a816c4dd6c52c29acf502803fbf3b63 100644 --- a/rust_crud_api/src/db/groups.rs +++ b/rust_crud_api/src/db/groups.rs @@ -13,8 +13,8 @@ fn pg_err(e: postgres::Error) -> PyErr { pub fn create_group(db_url: &str, name: &str) -> PyResult<()> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; client.execute( - "INSERT INTO groups (name) VALUES ($1)", - &[&name] + "INSERT INTO groups (name, member_count) VALUES ($1, $2)", // Use $2 for member_count + &[&name, &0] // Pass 0 explicitly as an i32 ).map_err(pg_err)?; Ok(()) } @@ -24,7 +24,7 @@ pub fn create_group(db_url: &str, name: &str) -> PyResult<()> { pub fn get_group(db_url: &str, group_id: i32) -> PyResult<Option<Group>> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; let row_opt = client.query_opt( - "SELECT id, name FROM groups WHERE id = $1", + "SELECT id, name, member_count FROM groups WHERE id = $1", &[&group_id] ).map_err(pg_err)?; @@ -32,6 +32,7 @@ pub fn get_group(db_url: &str, group_id: i32) -> PyResult<Option<Group>> { let group = Group { id: row.get(0), name: row.get(1), + member_count: row.get(2), }; Ok(Some(group)) } else { @@ -43,12 +44,13 @@ pub fn get_group(db_url: &str, group_id: i32) -> PyResult<Option<Group>> { #[pyfunction] pub fn get_all_groups(db_url: &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", &[]) + let rows = client.query("SELECT id, name, member_count FROM groups", &[]) .map_err(pg_err)?; let groups = rows.into_iter().map(|row| Group { id: row.get(0), name: row.get(1), + member_count: row.get(2), }).collect(); Ok(groups) @@ -62,21 +64,27 @@ pub fn add_user_to_group(db_url: &str, group_id: i32, user_id: i32) -> PyResult< "INSERT INTO group_members (group_id, user_id) VALUES ($1, $2)", &[&group_id, &user_id] ).map_err(pg_err)?; + client.execute( + "UPDATE groups SET member_count = member_count + 1 WHERE id = $1", + &[&group_id] + ).map_err(pg_err)?; Ok(()) } /// Get all members of a group. #[pyfunction] -pub fn get_group_members(db_url: &str, group_id: i32) -> PyResult<Vec<User>> { +pub fn get_group_members(db_url: &str, group_id: i32) -> PyResult<(Vec<User>, i32)> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; + + // Fetch group members let rows = client.query( - "SELECT u.id, u.name, u.email + "SELECT u.id, u.name, u.email, u.username, u.studentid, u.startyear, u.endyear, u.profilepicture, u.firstlogin FROM users u JOIN group_members gm ON u.id = gm.user_id WHERE gm.group_id = $1", - &[&group_id] + &[&group_id] ).map_err(pg_err)?; - + let users = rows.into_iter().map(|row| User { id: row.get(0), name: row.get(1), @@ -86,12 +94,19 @@ pub fn get_group_members(db_url: &str, group_id: i32) -> PyResult<Vec<User>> { startyear: row.get(5), endyear: row.get(6), profilepicture: row.get(7), - firstlogin: row.get(8) + firstlogin: row.get(8), }).collect(); - - Ok(users) + + // Fetch member count + let count: i32 = client.query_one( + "SELECT member_count FROM groups WHERE id = $1", + &[&group_id] + ).map_err(pg_err)?.get(0); + + Ok((users, count)) } + /// Group Delete Function #[pyfunction] pub fn delete_group(db_url: &str, group_id: i32) -> PyResult<bool> { @@ -107,7 +122,7 @@ pub fn delete_group(db_url: &str, group_id: i32) -> PyResult<bool> { 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", + "SELECT id, name, member_count FROM groups WHERE name ILIKE $1", &[&format!("%{}%", query)] ).map_err(pg_err)?; @@ -115,6 +130,7 @@ pub fn search_groups(db_url: &str, query: &str) -> PyResult<Vec<Group>> { .map(|row| Group { id: Some(row.get(0)), name: row.get(1), + member_count: row.get(2), }) .collect(); diff --git a/rust_crud_api/src/db/init.rs b/rust_crud_api/src/db/init.rs index 045676d1694b20b24dae3ec5550dae545a202e05..9e090aca00dac164a115e7c1f2e7d9c6d947e2b3 100644 --- a/rust_crud_api/src/db/init.rs +++ b/rust_crud_api/src/db/init.rs @@ -25,7 +25,8 @@ pub fn init_db(db_url: &str) -> PyResult<()> { ); CREATE TABLE IF NOT EXISTS groups ( id SERIAL PRIMARY KEY, - name VARCHAR NOT NULL + name VARCHAR NOT NULL, + member_count INTEGER DEFAULT 0 ); CREATE TABLE IF NOT EXISTS group_members ( group_id INTEGER REFERENCES groups(id), diff --git a/rust_crud_api/src/models/group.rs b/rust_crud_api/src/models/group.rs index ab2ebe36cf78d770dded31f21216dee76002080c..c95423a4216085ec19154c84ce83eaf9140e1a0b 100644 --- a/rust_crud_api/src/models/group.rs +++ b/rust_crud_api/src/models/group.rs @@ -8,5 +8,8 @@ pub struct Group { pub id: Option<i32>, #[pyo3(get, set)] pub name: String, + #[pyo3(get, set)] + pub member_count: i32, + }