diff --git a/.gitignore b/.gitignore index bc755a3..6b632c7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /data db.sqlite3 /uploads +.DS_Store diff --git a/src/admin.rs b/src/admin.rs index 6318674..02a5cbf 100644 --- a/src/admin.rs +++ b/src/admin.rs @@ -182,7 +182,9 @@ struct DashboardTemplate<'a> { lang: Lang, admin_name: &'a str, today_visits: Vec, - recent_feedbacks: Vec, + feedbacks: Vec, + feedback_page: usize, + feedback_total_pages: usize, } #[derive(Debug, Template)] @@ -494,13 +496,10 @@ async fn admin_index(request: Request, session: Session, db: Database) -> cot::R .collect(); today_visits.sort_by(|a, b| a.visit.time_start.cmp(&b.visit.time_start)); - let week_ago = today - chrono::Duration::days(7); - let mut recent_feedbacks: Vec = all_visits + let mut all_feedbacks: Vec = all_visits .iter() .filter(|v| { - v.user_id.primary_key().unwrap() == user_id - && v.client_feedback.is_some() - && v.updated_at.date() >= week_ago + v.user_id.primary_key().unwrap() == user_id && v.client_feedback.is_some() }) .map(|v| { let cid: i64 = v.client_id.primary_key().unwrap(); @@ -517,14 +516,34 @@ async fn admin_index(request: Request, session: Session, db: Database) -> cot::R } }) .collect(); - recent_feedbacks.sort_by(|a, b| b.visit_date.cmp(&a.visit_date)); + all_feedbacks.sort_by(|a, b| b.visit_date.cmp(&a.visit_date)); + + const PER_PAGE: usize = 10; + let feedback_page: usize = request + .uri() + .query() + .and_then(|q| { + q.split('&') + .find_map(|p| p.strip_prefix("page=")) + .and_then(|v| v.parse().ok()) + }) + .unwrap_or(1) + .max(1); + let feedback_total_pages = (all_feedbacks.len() + PER_PAGE - 1).max(1) / PER_PAGE.max(1); + let feedbacks: Vec = all_feedbacks + .into_iter() + .skip((feedback_page - 1) * PER_PAGE) + .take(PER_PAGE) + .collect(); let body = DashboardTemplate { t: lang.t(), lang, admin_name: &admin_name, today_visits, - recent_feedbacks, + feedbacks, + feedback_page, + feedback_total_pages, } .render()?; html_response(body, lang) @@ -1569,7 +1588,12 @@ async fn media_upload_submit( media.save(&db).await?; } - Redirect::new(format!("/admin/?lang={}", lang.code())).into_response() + Redirect::new(format!( + "/admin/schedule/{}/edit?lang={}", + visit_id, + lang.code() + )) + .into_response() } async fn media_delete( @@ -1582,11 +1606,19 @@ async fn media_delete( if let Err(resp) = require_auth(&session, lang).await { return Ok(resp); } + let referer = request + .headers() + .get("referer") + .and_then(|v| v.to_str().ok()) + .map(|s| s.to_string()); if let Some(mut m) = query!(Media, $id == media_id).get(&db).await? { m.status = "archived".to_string(); m.save(&db).await?; } - Redirect::new(format!("/admin/media?lang={}", lang.code())).into_response() + let redirect_url = referer + .filter(|r| r.contains("/schedule/") && r.contains("/edit")) + .unwrap_or_else(|| format!("/admin/media?lang={}", lang.code())); + Redirect::new(redirect_url).into_response() } /// Serve uploaded files by media ID. diff --git a/src/i18n.rs b/src/i18n.rs index e8a15fb..cb56709 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -360,7 +360,7 @@ static RU: Translations = Translations { media_delete_confirm: "Удалить этот файл?", media_all_clients: "Все клиенты", - portal_title: "Мои визиты", + portal_title: "Визиты", portal_upcoming: "Предстоящие визиты", portal_past: "Прошлые визиты", portal_no_upcoming: "Нет предстоящих визитов.", @@ -559,7 +559,7 @@ static EN: Translations = Translations { media_delete_confirm: "Delete this file?", media_all_clients: "All clients", - portal_title: "My Visits", + portal_title: "Visits", portal_upcoming: "Upcoming visits", portal_past: "Past visits", portal_no_upcoming: "No upcoming visits.", diff --git a/src/tz.rs b/src/tz.rs index e922890..41c966e 100644 --- a/src/tz.rs +++ b/src/tz.rs @@ -1,6 +1,5 @@ -use chrono::TimeZone; use chrono_tz::Tz; -use cot::db::{Database, Model, query}; +use cot::db::{Database, query}; use crate::models::Setting; diff --git a/templates/admin/dashboard.html b/templates/admin/dashboard.html index 8478645..4bb8aa6 100644 --- a/templates/admin/dashboard.html +++ b/templates/admin/dashboard.html @@ -47,19 +47,37 @@ {% endfor %} {% endif %} - +

{{ t.dashboard_recent_feedbacks }}

-{% if recent_feedbacks.is_empty() %} +{% if feedbacks.is_empty() %}

{{ t.dashboard_no_feedbacks }}

{% else %} - {% for fb in &recent_feedbacks %} -
+ {% for fb in &feedbacks %} +
{{ fb.feedback }}
-
+ {% endfor %} + + {% if feedback_total_pages > 1 %} +
+ {% if feedback_page > 1 %} + « + {% endif %} + {% for p in 1..=feedback_total_pages %} + {% if p == feedback_page %} + {{ p }} + {% else %} + {{ p }} + {% endif %} + {% endfor %} + {% if feedback_page < feedback_total_pages %} + » + {% endif %} +
+ {% endif %} {% endif %} {% endblock %} diff --git a/templates/admin/schedule_edit.html b/templates/admin/schedule_edit.html index 5bcb7a4..986c028 100644 --- a/templates/admin/schedule_edit.html +++ b/templates/admin/schedule_edit.html @@ -97,55 +97,79 @@ + {% if let Some(fb) = visit.client_feedback.as_deref() %} +
+ +
{{ fb }}
+
+ {% endif %} + +
+ + +
+ + +
+ {% if media.is_empty() %} +

{{ t.media_empty }}

+ {% else %} +
+ {% for m in &media %} +
+ {% if m.file_type == "photo" %} + + + + {% else %} + +
🎬
+
+ {% endif %} + {% if let Some(cap) = m.caption.as_deref() %} +
{{ cap }}
+ {% endif %} +
+ {% endfor %} +
+ {% endif %} + +
+ - {% if let Some(fb) = visit.client_feedback.as_deref() %} -
- -
{{ fb }}
-
- {% endif %} - -
- - -
- - 📷 {{ t.media_upload }} -
- {% if media.is_empty() %} -

{{ t.media_empty }}

- {% else %} -
- {% for m in &media %} -
- {% if m.file_type == "photo" %} - - - - {% else %} - -
🎬
-
- {% endif %} - {% if let Some(cap) = m.caption.as_deref() %} -
{{ cap }}
- {% endif %} -
- -
-
- {% endfor %} -
- {% endif %} -
+ +
+
+
+

{{ t.media_upload_title }}

+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+
+ + + {% endblock %}