Add slush bucket page
This commit is contained in:
parent
f362fa8c93
commit
0326c0c27a
|
|
@ -2,7 +2,7 @@ use std::net::SocketAddr;
|
|||
use axum::{
|
||||
middleware, routing::{get, get_service}, Extension, Router
|
||||
};
|
||||
use secret_gift_exchange::{giftexchange, giftexchanges};
|
||||
use secret_gift_exchange::{giftexchange, giftexchange_save, giftexchanges};
|
||||
use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};
|
||||
use sqlx::migrate::Migrator;
|
||||
use tower_http::services::ServeDir;
|
||||
|
|
@ -65,7 +65,7 @@ async fn main() {
|
|||
.route("/userwishlist/bought/:user_id", get(user_wishlist_bought_item))
|
||||
.route("/userwishlist/received/:user_id", get(user_wishlist_received_item))
|
||||
.route("/giftexchanges", get(giftexchanges))
|
||||
.route("/giftexchange/:giftexchange_id", get(giftexchange))
|
||||
.route("/giftexchange/:giftexchange_id", get(giftexchange).post(giftexchange_save))
|
||||
.nest_service("/assets", ServeDir::new("templates/assets")
|
||||
.fallback(get_service(ServeDir::new("templates/assets"))))
|
||||
.route("/", get(index))
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use askama::Template;
|
||||
use askama_axum::{IntoResponse, Response};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
response::Redirect,
|
||||
Extension,
|
||||
extract::{Path, State}, response::Redirect, routing::post, Extension, Form
|
||||
};
|
||||
use axum_extra::response::Html;
|
||||
use chrono::Utc;
|
||||
use http::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{FromRow, SqlitePool};
|
||||
|
|
@ -143,7 +142,7 @@ struct GiftExchangeTemplate {
|
|||
name: String,
|
||||
user_roles: Vec<crate::user::UserRolesDisplay>,
|
||||
giftexchange: GiftExchange,
|
||||
participants: Vec<GiftExchangeParticipant>,
|
||||
participants: Vec<UserData>,
|
||||
non_participants: Vec<UserData>,
|
||||
}
|
||||
|
||||
|
|
@ -162,17 +161,21 @@ pub async fn giftexchange(
|
|||
let user_roles = get_user_roles_display(userid, &db_pool.clone()).await;
|
||||
|
||||
// Get gift exchange
|
||||
let giftexchange = match sqlx::query_as!(GiftExchange, "SELECT * FROM gift_exchange WHERE id = ?", exchange_id)
|
||||
let giftexchange = match sqlx::query_as!(
|
||||
GiftExchange,
|
||||
"SELECT * FROM gift_exchange WHERE id = ?",
|
||||
exchange_id
|
||||
)
|
||||
.fetch_one(&db_pool)
|
||||
.await {
|
||||
.await
|
||||
{
|
||||
Ok(giftexchange) => giftexchange,
|
||||
Err(_) => {
|
||||
GiftExchange::default()
|
||||
}};
|
||||
Err(_) => GiftExchange::default(),
|
||||
};
|
||||
|
||||
// Get participants
|
||||
let participants = sqlx::query_as::<_, GiftExchangeParticipant>(
|
||||
"SELECT * FROM gift_exchange_participants WHERE exchange_id = ?",
|
||||
let participants = sqlx::query_as::<_, UserData>(
|
||||
"select * from users where users.id in (select participant_id from gift_exchange_participants where exchange_id = ?)",
|
||||
)
|
||||
.bind(exchange_id)
|
||||
.fetch_all(&db_pool)
|
||||
|
|
@ -202,5 +205,24 @@ pub async fn giftexchange(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn select_gifters() {}
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ExchangeForm {
|
||||
name: String,
|
||||
exchange_date: String,
|
||||
non_participants: Vec<i64>,
|
||||
}
|
||||
|
||||
pub async fn giftexchange_save(
|
||||
Path(exchange_id): Path<i64>,
|
||||
Extension(user_data): Extension<Option<UserData>>,
|
||||
State(db_pool): State<SqlitePool>,
|
||||
Form(item_form): Form<ExchangeForm>,
|
||||
) -> impl IntoResponse {
|
||||
println!("Saving gift exchange: {:?}", item_form);
|
||||
if is_authorized("/giftexchange", user_data.clone(), db_pool.clone()).await {
|
||||
// Insert new item to database
|
||||
let now = Utc::now().timestamp();
|
||||
|
||||
}
|
||||
Redirect::to("/").into_response()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="container-fluid" height="100%">
|
||||
<div class="row fixed-top sticky-top">
|
||||
<nav class="navbar navbar-expand-sm bg-light">
|
||||
<!-- Links -->
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.5/dist/bootstrap-table.min.js"></script>
|
||||
{% block script %}{% endblock script %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,52 +1,148 @@
|
|||
{% extends "authorized.html" %}
|
||||
{% block title %}Gift Exchange{% endblock %}
|
||||
{% block center %}
|
||||
<div class="row">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<a role="button" class="btn btn-primary" href="/giftexchange/{{ giftexchange.id }}">Save</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
Exchange Name: <input id="name" name="name" type="text" value="{{ giftexchange.name }}" required>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sortable="true" data-field="name"scope="col">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for participant in non_participants %}
|
||||
<tr>
|
||||
<td>{{ participant.name }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="btn-group-vertical" role="group">
|
||||
<button type="button" class="btn btn-primary">Add</button>
|
||||
<button type="button" class="btn btn-primary">Remove</button>
|
||||
<form action="/giftexchange/{{ giftexchange.id }}" method="post">
|
||||
<div class="row">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<a role="button" class="btn btn-primary" href="/giftexchange/{{ giftexchange.id }}">Save</a>
|
||||
<button type="submit" class="btn btn-danger">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sortable="true" data-field="name" scope="col">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for participant in participants %}
|
||||
<tr>
|
||||
<td>{{ participant.participant_id }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="name">Exchange Name:</label>
|
||||
<input id="name" class="form-control" name="name" type="text" value="{{ giftexchange.name }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="exchange_date">Exchange Date:</label>
|
||||
<input id="exchange_date" name="exchange_date" type="date" value="{{ giftexchange.exchange_date }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-center text-center">
|
||||
<div class="col">
|
||||
<table id="non_participants" data-toggle="table" data-click-to-select="true" class="table table-bordered"
|
||||
height="400">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-field="state" data-checkbox="true"></th>
|
||||
<th data-sortable="true" data-field="name" scope="col">Name</th>
|
||||
<th data-hidden="true" data-field="id" scope="col">ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="np_tbody">
|
||||
{% for participant in non_participants %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ participant.name }}</td>
|
||||
<td>{{ participant.id }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="btn-group-vertical text-center" role="group">
|
||||
<button id="add" type="button" class="btn btn-primary">Add</button>
|
||||
<button id="remove" type="button" class="btn btn-primary">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<table id="participants" data-toggle="table" data-click-to-select="true" class="table table-bordered"
|
||||
height="400">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-field="state" data-checkbox="true"></th>
|
||||
<th data-sortable="true" data-field="name" scope="col">Name</th>
|
||||
<th data-hidden="true" data-field="id" scope="col">ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="p_tbody">
|
||||
{% for participant in participants %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ participant.name }}</td>
|
||||
<td>{{ participant.id }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock center %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
$(document).ready(() => {
|
||||
var npRows = [];
|
||||
var pRows = [];
|
||||
|
||||
$('#non_participants').bootstrapTable('hideColumn', 'id');
|
||||
$('#participants').bootstrapTable('hideColumn', 'id');
|
||||
|
||||
$('#non_participants').on('check.bs.table', function (e, row) {
|
||||
npRows.push({ name: row.name, id: row.id });
|
||||
console.log(npRows);
|
||||
});
|
||||
|
||||
$('#non_participants').on('uncheck.bs.table', function (e, row) {
|
||||
$.each(npRows, function (index, value) {
|
||||
if (value.id === row.id) {
|
||||
npRows.splice(index, 1);
|
||||
}
|
||||
});
|
||||
console.log(npRows);
|
||||
});
|
||||
|
||||
$('#participants').on('check.bs.table', function (e, row) {
|
||||
pRows.push({ name: row.name, id: row.id });
|
||||
console.log(pRows);
|
||||
});
|
||||
|
||||
$('#participants').on('uncheck.bs.table', function (e, row) {
|
||||
$.each(pRows, function (index, value) {
|
||||
if (value.id === row.id) {
|
||||
pRows.splice(index, 1);
|
||||
}
|
||||
});
|
||||
console.log(pRows);
|
||||
});
|
||||
|
||||
$("#add").click(function () {
|
||||
$("#output").empty();
|
||||
$.each(npRows, function (index, value) {
|
||||
$('#non_participants').bootstrapTable('remove', {
|
||||
field: 'id',
|
||||
values: [value.id]
|
||||
});
|
||||
$('#participants').bootstrapTable('insertRow', {
|
||||
index: 0,
|
||||
row: {
|
||||
name: value.name,
|
||||
id: value.id
|
||||
}
|
||||
});
|
||||
});
|
||||
npRows = [];
|
||||
});
|
||||
|
||||
$("#remove").click(function () {
|
||||
$("#p_output").empty();
|
||||
$.each(pRows, function (index, value) {
|
||||
$('#participants').bootstrapTable('remove', {
|
||||
field: 'id',
|
||||
values: [value.id]
|
||||
});
|
||||
$('#non_participants').bootstrapTable('insertRow', {
|
||||
index: 0,
|
||||
row: {
|
||||
name: value.name,
|
||||
id: value.id
|
||||
}
|
||||
});
|
||||
});
|
||||
pRows = [];
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock script %}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
{% block title %}User Administration{% endblock %}
|
||||
{% block center %}
|
||||
<h1>Users</h1>
|
||||
<table data-toggle="table" class="table table-striped table-bordered">
|
||||
<table data-toggle="table" data-height="400" class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sortable="true" data-field="name" scope="col">Name</th>
|
||||
|
|
|
|||
Loading…
Reference in New Issue