Compare commits

...

2 Commits

Author SHA1 Message Date
61c67d78da Merge pull request 'allow admin to send notifications' (#351) from staging into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 11m31s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 5m36s
Reviewed-on: #351
2024-04-08 19:36:35 +02:00
64d32e2688 allow admin to send notifications
Some checks failed
CI/CD Pipeline / deploy-main (push) Waiting to run
CI/CD Pipeline / test (push) Successful in 11m20s
CI/CD Pipeline / deploy-staging (push) Has been cancelled
2024-04-08 19:35:31 +02:00
4 changed files with 97 additions and 0 deletions

View File

@ -10,6 +10,7 @@ use crate::{
pub mod boat;
pub mod mail;
pub mod notification;
pub mod planned_event;
pub mod schnupper;
pub mod user;
@ -77,6 +78,7 @@ pub fn routes() -> Vec<Route> {
ret.append(&mut user::routes());
ret.append(&mut schnupper::routes());
ret.append(&mut boat::routes());
ret.append(&mut notification::routes());
ret.append(&mut mail::routes());
ret.append(&mut planned_event::routes());
ret.append(&mut routes![rss, show_rss, show_list, list]);

View File

@ -0,0 +1,72 @@
use crate::model::{
log::Log,
notification::Notification,
role::Role,
user::{AdminUser, User, UserWithRoles},
};
use rocket::{
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
};
use rocket_dyn_templates::{tera::Context, Template};
use sqlx::SqlitePool;
#[get("/notification")]
async fn index(
db: &State<SqlitePool>,
user: AdminUser,
flash: Option<FlashMessage<'_>>,
) -> Template {
let mut context = Context::new();
if let Some(msg) = flash {
context.insert("flash", &msg.into_inner());
}
context.insert(
"loggedin_user",
&UserWithRoles::from_user(user.user.into(), db).await,
);
context.insert("roles", &Role::all(db).await);
Template::render("admin/notification", context.into_json())
}
#[derive(FromForm, Debug)]
pub struct NotificationToSend {
pub(crate) role_id: i32,
pub(crate) category: String,
pub(crate) message: String,
}
#[post("/notification", data = "<data>")]
async fn send(
db: &State<SqlitePool>,
data: Form<NotificationToSend>,
admin: AdminUser,
) -> Flash<Redirect> {
let d = data.into_inner();
Log::create(
db,
format!("{admin:?} trying to send this notification: {d:?}"),
)
.await;
let Some(role) = Role::find_by_id(db, d.role_id).await else {
return Flash::error(Redirect::to("/admin/notification"), "Rolle gibt's ned");
};
for user in User::all_with_role(&db, &role).await {
Notification::create(db, &user, &d.message, &d.category, None).await;
}
Log::create(db, "Notification successfully sent".into()).await;
Flash::success(
Redirect::to("/admin/notification"),
"Nachricht ausgeschickt",
)
}
pub fn routes() -> Vec<Route> {
routes![index, send]
}

View File

@ -0,0 +1,20 @@
{% import "includes/macros" as macros %}
{% import "includes/forms/boat" as boat %}
{% extends "base" %}
{% block content %}
<div class="max-w-screen-lg w-full dark:text-white">
<h1 class="h1">Nachricht</h1>
<div class="grid ">
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
role="alert">
<h2 class="h2">Nachricht senden</h2>
<form action="/admin/notification" method="post">
{{ macros::select(label="Gruppe", data=roles, name="role_id") }}
{{ macros::input(label="Überschrift", name="category", type="text", required=true) }}
{{ macros::input(label="Nachricht", name="message", type="text", required=true) }}
<input type="submit" value="Abschicken" />
</form>
</div>
</div>
</div>
{% endblock content %}

View File

@ -153,6 +153,9 @@
<li class="py-1">
<a href="/admin/list" class="block w-100 py-2 hover:text-primary-600">Fingerabdruck-Liste überprüfen</a>
</li>
<li class="py-1">
<a href="/admin/notification" class="block w-100 py-2 hover:text-primary-600">Nachricht ausschreiben</a>
</li>
</ul>
</div>
{% endif %}