Fix cottage calendar requests
This commit is contained in:
parent
8032019807
commit
e9edd3e82a
|
|
@ -0,0 +1,29 @@
|
||||||
|
-- Add down migration script here
|
||||||
|
ALTER TABLE if exists calendar_event_types
|
||||||
|
drop column if exists state;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
-- Check if the constraint 'unique_calendar_et_name' already exists
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM pg_constraint
|
||||||
|
WHERE conname = 'unique_calendar_et_name'
|
||||||
|
AND conrelid = 'public.calendar_event_types'::regclass -- Specify table to narrow down
|
||||||
|
) THEN
|
||||||
|
-- If it exists, drop the constraint
|
||||||
|
ALTER TABLE IF EXISTS public.calendar_event_types
|
||||||
|
DROP CONSTRAINT unique_calendar_et_name;
|
||||||
|
|
||||||
|
RAISE NOTICE 'Constraint unique_calendar_et_name dropped from table calendar_event_types.';
|
||||||
|
ELSE
|
||||||
|
RAISE NOTICE 'Constraint unique_calendar_et_name doesn''t exist on table calendar_event_types.';
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
-- Add the constraint
|
||||||
|
ALTER TABLE IF EXISTS public.calendar_event_types
|
||||||
|
ADD CONSTRAINT unique_calendar_et_name UNIQUE (name);
|
||||||
|
|
||||||
|
RAISE NOTICE 'Constraint unique_calendar_et_name added to table calendar_event_types.';
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
-- Add up migration script here
|
||||||
|
ALTER TABLE if exists calendar_event_types
|
||||||
|
ADD COLUMN IF NOT EXISTS state character varying(25);
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
-- Check if the constraint 'unique_calendar_et_name' already exists
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM pg_constraint
|
||||||
|
WHERE conname = 'unique_calendar_et_name'
|
||||||
|
AND conrelid = 'public.calendar_event_types'::regclass -- Specify table to narrow down
|
||||||
|
) THEN
|
||||||
|
-- If it exists, drop the constraint
|
||||||
|
ALTER TABLE IF EXISTS public.calendar_event_types
|
||||||
|
DROP CONSTRAINT unique_calendar_et_name;
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
-- Add the constraint
|
||||||
|
ALTER TABLE IF EXISTS public.calendar_event_types
|
||||||
|
ADD CONSTRAINT unique_calendar_et_name UNIQUE (name, state);
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
-- Add down migration script here
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
-- Truncate tables
|
||||||
|
TRUNCATE TABLE calendar_event_types, calendar;
|
||||||
|
|
||||||
|
-- Add default calendar and event types
|
||||||
|
insert into calendar (created_by, updated_by, name, colour)
|
||||||
|
select id, id, 'Cottage', 'blue' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar (created_by, updated_by, name, colour)
|
||||||
|
select id, id, 'Family tree', 'brown' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Reservation', 'Requested', 'purple' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Reservation', 'Approved', 'green' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Reservation', 'Confirmed', 'blue' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Reservation', 'Tentative', 'light-purple' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Reservation', 'Rejected', 'red' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Reservation', 'Cancelled', 'light-red' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Life event', 'Birthday', 'green' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Life event', 'Anniversary', 'orange' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
||||||
|
insert into calendar_event_types (created_by, updated_by, name, state, colour)
|
||||||
|
select id, id, 'Life event', 'Other', 'light-orange' from users where email = 'admin@jean-marie.ca';
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, Query, State}, response::{Html, IntoResponse, Redirect, Response}, Extension, Form
|
extract::{Query, State},
|
||||||
|
response::{Html, IntoResponse, Redirect, Response},
|
||||||
|
Extension, Form,
|
||||||
};
|
};
|
||||||
|
use chrono::Days;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{FromRow, PgPool, Row};
|
use sqlx::{postgres::PgRow, Error, FromRow, PgPool, Row};
|
||||||
|
use tracing::event;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -94,13 +98,41 @@ pub async fn get_calendars(db_pool: PgPool) -> Vec<Calendar> {
|
||||||
calendars
|
calendars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_event(event_id: Uuid, db_pool: &PgPool) -> String {
|
||||||
|
// Set default events
|
||||||
|
let mut eventstring: String = "[]".to_string();
|
||||||
|
|
||||||
|
let event: Result<PgRow, Error> = Ok(sqlx::query(
|
||||||
|
r#"select to_json(json_build_object(
|
||||||
|
'title', ce.title,
|
||||||
|
'start', ce.start_time,
|
||||||
|
'end', ce.end_time,
|
||||||
|
'allDay', false,
|
||||||
|
'backgroundColor', cet.colour))
|
||||||
|
from calendar_events ce
|
||||||
|
join calendar_event_types cet on cet.id = ce.event_type_id
|
||||||
|
where ce.id = $1"#,
|
||||||
|
)
|
||||||
|
.bind(event_id)
|
||||||
|
.fetch_one(db_pool)
|
||||||
|
.await
|
||||||
|
.unwrap());
|
||||||
|
|
||||||
|
if let Ok(json_string) = event {
|
||||||
|
if let Ok(stringevents) = json_string.try_get_raw(0).map(|v| v.as_str().unwrap_or("")) {
|
||||||
|
//println!("Event: {:?}", stringevents);
|
||||||
|
eventstring = stringevents.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventstring
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_events(
|
pub async fn get_events(
|
||||||
Path(calendar): Path<String>,
|
|
||||||
State(db_pool): State<PgPool>,
|
State(db_pool): State<PgPool>,
|
||||||
Query(params): Query<EventParams>,
|
Query(params): Query<EventParams>,
|
||||||
Extension(user_data): Extension<Option<AccountData>>,
|
Extension(user_data): Extension<Option<AccountData>>,
|
||||||
) -> String {
|
) -> String {
|
||||||
//println!("Calendar: {}", calendar);
|
|
||||||
//println!("Paramters: {:?}", params);
|
//println!("Paramters: {:?}", params);
|
||||||
// Is the user logged in?
|
// Is the user logged in?
|
||||||
let logged_in = user_data.is_some();
|
let logged_in = user_data.is_some();
|
||||||
|
|
@ -109,32 +141,40 @@ pub async fn get_events(
|
||||||
let mut eventstring: String = "[]".to_string();
|
let mut eventstring: String = "[]".to_string();
|
||||||
|
|
||||||
if logged_in {
|
if logged_in {
|
||||||
|
// User is logged in
|
||||||
|
//println!("User is logged in");
|
||||||
|
|
||||||
// Extract the user data.
|
// Extract the user data.
|
||||||
let _user = user_data.as_ref().unwrap().clone();
|
let _user = user_data.as_ref().unwrap().clone();
|
||||||
let _userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default();
|
let _userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default();
|
||||||
|
|
||||||
if is_authorized("/calendar", user_data, db_pool.clone()).await {
|
if is_authorized("/calendar", user_data, db_pool.clone()).await {
|
||||||
|
// User is authorized
|
||||||
|
//println!("User is authorized");
|
||||||
|
|
||||||
// Get requested calendar events from database
|
// Get requested calendar events from database
|
||||||
let events = sqlx::query(
|
let events = sqlx::query(
|
||||||
r#"select to_json(json_agg(json_build_object(
|
r#"select to_json(json_agg(json_build_object(
|
||||||
'title', ce.title,
|
'title', ce.title,
|
||||||
'start', ce.start_time,
|
'start', ce.start_time,
|
||||||
'end', ce.end_time,
|
'end', ce.end_time,
|
||||||
'allDay', false)))
|
'allDay', false,
|
||||||
|
'backgroundColor', cet.colour)))
|
||||||
from calendar_events ce
|
from calendar_events ce
|
||||||
join calendar c on c.id = ce.calendar_id
|
join calendar c on c.id = ce.calendar_id
|
||||||
join calendar_event_types cet on cet.id = ce.event_type_id
|
join calendar_event_types cet on cet.id = ce.event_type_id
|
||||||
where ce.celebrate = true
|
where ce.celebrate = true
|
||||||
and c.name = $1
|
and c.name = 'Cottage'
|
||||||
and start_time > $2
|
and start_time > $1
|
||||||
and start_time < $3"#,
|
and start_time < $2"#,
|
||||||
)
|
)
|
||||||
.bind(calendar)
|
|
||||||
.bind(chrono::DateTime::parse_from_rfc3339(¶ms.start).unwrap())
|
.bind(chrono::DateTime::parse_from_rfc3339(¶ms.start).unwrap())
|
||||||
.bind(chrono::DateTime::parse_from_rfc3339(¶ms.end).unwrap())
|
.bind(chrono::DateTime::parse_from_rfc3339(¶ms.end).unwrap())
|
||||||
.fetch_one(&db_pool)
|
.fetch_one(&db_pool)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
//println!("Events: {:?}", events);
|
||||||
|
|
||||||
if let Ok(json_string) = events {
|
if let Ok(json_string) = events {
|
||||||
if let Ok(stringevents) =
|
if let Ok(stringevents) =
|
||||||
json_string.try_get_raw(0).map(|v| v.as_str().unwrap_or(""))
|
json_string.try_get_raw(0).map(|v| v.as_str().unwrap_or(""))
|
||||||
|
|
@ -185,7 +225,7 @@ pub async fn create_event(
|
||||||
if is_authorized("/calendar", user_data.clone(), db_pool.clone()).await {
|
if is_authorized("/calendar", user_data.clone(), db_pool.clone()).await {
|
||||||
let fmt = "%Y-%m-%d";
|
let fmt = "%Y-%m-%d";
|
||||||
let start_date = chrono::NaiveDate::parse_from_str(&event.start_time, fmt).unwrap();
|
let start_date = chrono::NaiveDate::parse_from_str(&event.start_time, fmt).unwrap();
|
||||||
let end_date = chrono::NaiveDate::parse_from_str(&event.end_time, fmt).unwrap();
|
let end_date = chrono::NaiveDate::parse_from_str(&event.end_time, fmt).unwrap().checked_sub_days(Days::new(1)).unwrap();
|
||||||
let start_datetime = start_date.and_hms_opt(14, 0, 0).unwrap();
|
let start_datetime = start_date.and_hms_opt(14, 0, 0).unwrap();
|
||||||
let end_datetime = end_date.and_hms_opt(10, 0, 0).unwrap();
|
let end_datetime = end_date.and_hms_opt(10, 0, 0).unwrap();
|
||||||
|
|
||||||
|
|
@ -215,6 +255,89 @@ pub async fn create_event(
|
||||||
Redirect::to(&redirect_url).into_response()
|
Redirect::to(&redirect_url).into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct NewRequest {
|
||||||
|
pub start: String,
|
||||||
|
pub end: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn new_request(
|
||||||
|
State(db_pool): State<PgPool>,
|
||||||
|
Extension(user_data): Extension<Option<AccountData>>,
|
||||||
|
request: axum::http::Request<axum::body::Body>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let logged_in = user_data.is_some();
|
||||||
|
|
||||||
|
// Set default events
|
||||||
|
let mut eventstring: String = "[]".to_string();
|
||||||
|
|
||||||
|
if logged_in {
|
||||||
|
// User is logged in
|
||||||
|
//println!("User is logged in");
|
||||||
|
|
||||||
|
// Extract the user data.
|
||||||
|
let _user = user_data.as_ref().unwrap().clone();
|
||||||
|
let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default();
|
||||||
|
let personid = user_data
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.person_id.clone())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
if is_authorized("/calendar", user_data, db_pool.clone()).await {
|
||||||
|
let (_parts, body) = request.into_parts();
|
||||||
|
let bytes = axum::body::to_bytes(body, usize::MAX).await.unwrap();
|
||||||
|
let body_str = String::from_utf8(bytes.to_vec()).unwrap();
|
||||||
|
//println!("Body: {}", body_str);
|
||||||
|
|
||||||
|
let params: NewRequest = serde_json::from_str(&body_str).unwrap();
|
||||||
|
|
||||||
|
let fmt = "%Y-%m-%d";
|
||||||
|
let start_date = chrono::NaiveDate::parse_from_str(¶ms.start, fmt).unwrap();
|
||||||
|
let end_date = chrono::NaiveDate::parse_from_str(¶ms.end, fmt).unwrap().checked_sub_days(Days::new(1)).unwrap();
|
||||||
|
let start_datetime = start_date.and_hms_opt(14, 0, 0).unwrap();
|
||||||
|
let end_datetime = end_date.and_hms_opt(10, 0, 0).unwrap();
|
||||||
|
|
||||||
|
let event = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||||
|
r#"insert into calendar_events (created_by, updated_by, calendar_id, event_type_id, title, start_time, end_time)
|
||||||
|
select p.id as created_by,
|
||||||
|
p.id as updated_by,
|
||||||
|
c.id as calendar_id,
|
||||||
|
cet.id as event_type_id,
|
||||||
|
p.given_name as title,
|
||||||
|
$1 as start_time,
|
||||||
|
$2 as end_time
|
||||||
|
from calendar c,
|
||||||
|
calendar_event_types cet,
|
||||||
|
people p
|
||||||
|
where c.name = 'Cottage'
|
||||||
|
and cet.name = 'Reservation'
|
||||||
|
and cet.state = 'Requested'
|
||||||
|
and p.id = $3
|
||||||
|
returning id"#
|
||||||
|
)
|
||||||
|
.bind(start_datetime)
|
||||||
|
.bind(end_datetime)
|
||||||
|
.bind(personid)
|
||||||
|
.fetch_one(&db_pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("Error creating event: {}", e),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
//println!("Event: {:#?}", &event.unwrap());
|
||||||
|
|
||||||
|
let event_id = event.clone();
|
||||||
|
|
||||||
|
eventstring = get_event(event_id.unwrap(), &db_pool).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventstring
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "newevent.html")]
|
#[template(path = "newevent.html")]
|
||||||
struct EventTemplate {
|
struct EventTemplate {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use axum::{
|
use axum::{
|
||||||
middleware,
|
middleware,
|
||||||
routing::{get, get_service, post, put},
|
routing::{get, get_service, post},
|
||||||
Extension, Router,
|
Extension, Router,
|
||||||
};
|
};
|
||||||
use dotenvy::var;
|
use dotenvy::var;
|
||||||
|
|
@ -31,6 +31,8 @@ use wishlist::{
|
||||||
user_wishlist_delete_item, user_wishlist_edit_item, user_wishlist_received_item,
|
user_wishlist_delete_item, user_wishlist_edit_item, user_wishlist_received_item,
|
||||||
user_wishlist_returned_item, user_wishlist_save_item, wishlists,
|
user_wishlist_returned_item, user_wishlist_save_item, wishlists,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::calendar::new_request;
|
||||||
//use email::send_emails;
|
//use email::send_emails;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -86,9 +88,10 @@ async fn main() {
|
||||||
)
|
)
|
||||||
// Calendar
|
// Calendar
|
||||||
.route("/calendar", get(calendar))
|
.route("/calendar", get(calendar))
|
||||||
.route("/getevents/{calendar}", get(get_events))
|
.route("/calendar/getevents", get(get_events))
|
||||||
.route("/createevent", post(create_event))
|
.route("/calendar/createevent", post(create_event))
|
||||||
.route("/newevent", get(new_event))
|
.route("/calendar/newevent", get(new_event))
|
||||||
|
.route("/calendar/newrequest", post(new_request))
|
||||||
// Wishlist
|
// Wishlist
|
||||||
.route("/wishlists", get(wishlists))
|
.route("/wishlists", get(wishlists))
|
||||||
.route("/userwishlist/{user_id}", get(user_wishlist))
|
.route("/userwishlist/{user_id}", get(user_wishlist))
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/@fullcalendar/daygrid@4.3.0/main.min.css'>
|
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/@fullcalendar/daygrid@4.3.0/main.min.css'>
|
||||||
{% endblock links %}
|
{% endblock links %}
|
||||||
{% block center %}
|
{% block center %}
|
||||||
<h1>Calendar</h1>
|
|
||||||
<div class="mh-100">
|
<div class="mh-100">
|
||||||
<div id="calendar" class="fc"></div>
|
<div id="calendar" class="fc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -13,25 +12,34 @@
|
||||||
<div class="modal fade" id="eventDetailsModal" tabindex="-1" role="dialog" aria-labelledby="eventDetailsModalTitle"
|
<div class="modal fade" id="eventDetailsModal" tabindex="-1" role="dialog" aria-labelledby="eventDetailsModalTitle"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<form id="eventDetailsModalForm">
|
||||||
<div class="modal-header">
|
<div class="modal-content">
|
||||||
<h5 class="modal-title" id="eventDetailsModalTitle">Event details</h5>
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="eventDetailsModalTitle">Request dates</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="eventStart">Starting</label>
|
||||||
|
<input type="date" class="form-control" id="eventStart" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="eventEnd">Leaving</label>
|
||||||
|
<input type="date" class="form-control" id="eventEnd" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" id="eventDetailsModalClose" class="btn btn-secondary"
|
||||||
|
data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Send Request</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
</form>
|
||||||
<p id="eventDetailsModalDateRange"></p>
|
|
||||||
<p id="eventDetailsModalBody">Cottage request</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
||||||
<button type="button" class="btn btn-primary">Save changes</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock center %}
|
{% endblock center %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js'></script>
|
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.17/index.global.min.js'></script>
|
||||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js'></script>
|
<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js'></script>
|
||||||
<script src='https://cdn.jsdelivr.net/npm/uuid@8.3.2/dist/umd/uuidv4.min.js'></script>
|
<script src='https://cdn.jsdelivr.net/npm/uuid@8.3.2/dist/umd/uuidv4.min.js'></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -50,29 +58,58 @@
|
||||||
center: 'title',
|
center: 'title',
|
||||||
right: 'dayGridMonth,timeGridWeek,timeGridDay,multiMonthYear'
|
right: 'dayGridMonth,timeGridWeek,timeGridDay,multiMonthYear'
|
||||||
},
|
},
|
||||||
eventSources: [
|
events: '/calendar/getevents',
|
||||||
{% for calendar in calendars %}
|
select: function (info) {
|
||||||
{
|
$('#eventStart').val(info.startStr);
|
||||||
url: '/getevents/{{calendar.name}}',
|
$('#eventEnd').val(info.endStr);
|
||||||
color: '{{calendar.colour}}',
|
$('#eventDetailsModal').modal('show');
|
||||||
},
|
}
|
||||||
{% endfor %}
|
|
||||||
],
|
|
||||||
select: function (info) {
|
|
||||||
$('#eventDetailsModal').modal('show');
|
|
||||||
$('#eventDetailsModalDateRange').text(info.startStr + ' to ' + info.endStr);
|
|
||||||
|
|
||||||
info.view.calendar.addEvent({
|
|
||||||
id: uuidv4(),
|
|
||||||
title: 'Cottage request',
|
|
||||||
start: info.startStr + 'T14:00:00',
|
|
||||||
end: info.endStr + 'T10:00:00',
|
|
||||||
allDay: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
calendar.render();
|
calendar.render();
|
||||||
|
|
||||||
|
document.getElementById('eventDetailsModalForm').addEventListener('submit', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var start = document.getElementById('eventStart').value;
|
||||||
|
var end = document.getElementById('eventEnd').value;
|
||||||
|
|
||||||
|
// Prepare the event data
|
||||||
|
var eventData = {
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send data to the API
|
||||||
|
fetch('/calendar/newrequest', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(eventData)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) throw new Error('Network response was not ok');
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
// Optionally, use the response to add the event to the calendar
|
||||||
|
$('#eventDetailsModal').modal('hide');
|
||||||
|
calendar.addEvent({
|
||||||
|
title: data.title,
|
||||||
|
start: data.start,
|
||||||
|
end: data.end,
|
||||||
|
allDay: data.allDay,
|
||||||
|
backgroundColor: data.backgroundColor
|
||||||
|
});
|
||||||
|
e.target.reset();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error creating event:', error);
|
||||||
|
alert('An error occurred while creating the event.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('eventDetailsModalClose').addEventListener('click', function () {
|
||||||
|
$('#eventDetailsModal').modal('hide');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock scripts %}
|
{% endblock scripts %}
|
||||||
Loading…
Reference in New Issue