Skip to content

Commit

Permalink
cameronwhite4121-Issue#317-EventsCalendarDisplay (#347)
Browse files Browse the repository at this point in the history
* Added Fullcalendar with testcode and responsive modals

* Added responsive calendar styles

* removed old calendar code

* Added action that sends json from the db to calendar javascript file

* Added Starting and ending date time properties to calendar events for fullcalendar compatability

* Decided to leave js in cshmtl file instead to simplify data transfer

* Added background colors to events on the calendar

* Added calendar code and checks for if current window is PC2 or County events

* Comment is redundant because method is self-explanatory

* Add integrity hash to fullcalendar js file

* Remove unnecessary using directives

* Remove unecessary using directives in EventsController

---------

Co-authored-by: Joseph Ortiz <[email protected]>
  • Loading branch information
cameronwhite4121 and JoeProgrammer88 authored Nov 25, 2024
1 parent d28fe93 commit 130c1c9
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 102 deletions.
5 changes: 1 addition & 4 deletions PC2/Controllers/AboutController.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
using Humanizer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.DotNet.Scaffolding.Shared.Project;
using Microsoft.EntityFrameworkCore;
using PC2.Data;
using PC2.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace PC2.Controllers
{
Expand Down
28 changes: 27 additions & 1 deletion PC2/Controllers/EventsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,37 @@ public async Task<IActionResult> Index(string? eventType)
bool getPc2Events = eventType == null;
EventsModel eventsModel = new()
{
IsPC2EventCalendar = getPc2Events,
IsPC2EventCalendar = getPc2Events,
CalendarEvents = await CalendarEventDB.GetAllEvents(_context, getPc2Events)
};

return View(eventsModel);
}

// Returns events in JSON format for FullCalendar
public async Task<IActionResult> GetEvents(string? eventType)
{
bool getPc2Events = string.IsNullOrEmpty(eventType) || eventType == "PC2";

// Get events from the database
List<CalendarEvent> events = await CalendarEventDB.GetAllEvents(_context, getPc2Events);

// Create a list to hold FullCalendar-compatible events
List<object> fullCalendarEvents = new List<object>();

// Loop through the events and add them to the list
foreach (var e in events)
{
var calendarEvent = new
{
title = e.EventDescription,
start = e.StartingDateTime.ToString("yyyy-MM-ddTHH:mm:ss"), // FullCalendar format
end = e.EndingDateTime.ToString("yyyy-MM-ddTHH:mm:ss"), // FullCalendar format
};
fullCalendarEvents.Add(calendarEvent);
}

return Json(fullCalendarEvents);
}
}
}
17 changes: 17 additions & 0 deletions PC2/Models/CalendarEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ public class CalendarEvent : IComparable<CalendarEvent>
/// </summary>
public bool CountyEvent { get; set; }

// Convert DateOnly and TimeOnly to DateTime
public DateTime StartingDateTime
{
get
{
return DateOfEvent.ToDateTime(StartingTime);
}
}

public DateTime EndingDateTime
{
get
{
return DateOfEvent.ToDateTime(EndingTime);
}
}

public int CompareTo(CalendarEvent? other)
{
return this.DateOfEvent.CompareTo(other.DateOfEvent);

Check warning on line 62 in PC2/Models/CalendarEvent.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 62 in PC2/Models/CalendarEvent.cs

View workflow job for this annotation

GitHub Actions / build-and-deploy

Dereference of a possibly null reference.
Expand Down
188 changes: 91 additions & 97 deletions PC2/Views/Events/Index.cshtml
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
@model PC2.Models.EventsModel

@{
// Allows calendar to switch between PC2 and County events by grabbing the eventType
var eventType = Context.Request.Query["eventType"].ToString();
if (string.IsNullOrEmpty(eventType) || eventType == "PC2")
{
Model.IsPC2EventCalendar = true;
}
else
{
Model.IsPC2EventCalendar = false;
}

if (Model.IsPC2EventCalendar)
{
ViewData["Title"] = "PC2 Events and Activities";
Expand All @@ -8,12 +20,6 @@
{
ViewData["Title"] = "County-wide Events and Activities";
}

List<List<CalendarEvent>> eventDateGroups =
Model.CalendarEvents
.GroupBy(calEvent => calEvent.DateOfEvent)
.Select(group => group.ToList())
.ToList();
}

<div class="d-flex justify-content-center">
Expand All @@ -22,46 +28,22 @@
<img src=~/images/events/events3.jpg />
<img src=~/images/events/events4.jpg />
</div>

<br />
<h1>@ViewData["Title"]</h1>

<div class="divider"></div>

<br />


@section Head{
@section Head {
<style>
.img-flyer {
max-width: 625px;
max-height: 875px;
}
.agenda .agenda-date {
width: 170px;
}
.agenda .agenda-date .dayofmonth {
width: 40px !important;
font-size: 36px !important;
line-height: 36px !important;
float: left;
text-align: right;
margin-right: 10px;
}
.agenda .agenda-date .shortdate {
font-size: 0.75em;
}
/* Times */
.agenda .agenda-time {
width: 140px;
}
</style>
}

<!-- Links to toggle between PC2 and County events -->
@if (Model.IsPC2EventCalendar)
{
<p>
Expand All @@ -71,79 +53,91 @@
else
{
<p>
<a asp-action="Index">View PC2 Events</a>
<a asp-action="Index" asp-route-eventType="PC2">View PC2 Events</a>
</p>
}

<br />

@if (Model.CalendarEvents.Count > 0)
{
<div class="agenda">
<div class="table-responsive">
<table class="table table-condensed table-bordered">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Event</th>
</tr>
</thead>
<tbody>
@for (int currentDate = 0; currentDate < eventDateGroups.Count; currentDate++)
{
<tr>
<td class="agenda-date" class="active" rowspan="@eventDateGroups[currentDate].Count">
<div class="dayofmonth">@eventDateGroups[currentDate][0].DateOfEvent.Day</div>
<div class="dayofweek">@eventDateGroups[currentDate][0].DateOfEvent.DayOfWeek</div>
<div class="shortdate text-muted">@eventDateGroups[currentDate][0].DateOfEvent.ToString("MMMM"),&nbsp;@eventDateGroups[currentDate][0].DateOfEvent.Year</div>
</td>
@*loop through all events on this date*@
@for (int currentEvent = 0; currentEvent < eventDateGroups[currentDate].Count; currentEvent++)
{
string eventDescription = eventDateGroups[currentDate][currentEvent].EventDescription;
@if (currentEvent > 0) // if this is not the first event on this date, then start a new row
{
<tr>
<td class="agenda-time">
@eventDateGroups[currentDate][currentEvent].StartingTime &nbsp;-&nbsp; @eventDateGroups[currentDate][currentEvent].EndingTime
</td>
<td class="agenda-events">
<div class="agenda-event">
@*// use partial view, pass in eventdescription as ViewData*@
@(await Html.PartialAsync("~/Views/Calendar/_IndexPartial.cshtml", new ViewDataDictionary(ViewData) { { "eventDescription", eventDescription } }))
</div>
</td>
</tr>
}
else
{
<td class="agenda-time">
@eventDateGroups[currentDate][currentEvent].StartingTime &nbsp;-&nbsp; @eventDateGroups[currentDate][currentEvent].EndingTime
</td>
<td class="agenda-events">
<div class="agenda-event">
@*// use partial view, pass in eventdescription as ViewData*@
@(await Html.PartialAsync("~/Views/Calendar/_IndexPartial.cshtml", new ViewDataDictionary(ViewData) { { "eventDescription", eventDescription } }))
</div>
</td>
}
}
</tr>
}
</tbody>
</table>
<!-- Modal popup -->
<div class="modal fade" id="eventModal" tabindex="-1" aria-labelledby="eventModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="eventModalLabel">Event Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<h5 id="modalEventTitle" style="font-weight: normal;"></h5>
<p><strong>Start Time:</strong> <span id="modalEventDate"></span></p>
<p><strong>End Time:</strong> <span id="modalEventEndTime"></span></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
}
else
{
<h2>There are no upcoming @ViewData["Title"] on the Calendar</h2>
<br />
}
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js"
integrity="sha384-B1OFx8Gy9GjPu8UbUyXbGQpzll9ubAUQ9agInFJ8NnD7nYG1u/CLR+Sqr5yifl4q"
crossorigin="anonymous"></script>

<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarContainer = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarContainer, {
initialView: 'dayGridMonth',
eventColor: '#ff9f89',
events: function(info, successCallback, failureCallback) {
// Get the eventType from the query string
var urlParams = new URLSearchParams(window.location.search);
var eventType = urlParams.get('eventType') || 'PC2';
// Fetch events from the controller based on eventType
fetch('@Url.Action("GetEvents", "Events")?eventType=' + eventType)
.then(function(response) {
return response.json();
})
.then(function(events) {
successCallback(events);
})
.catch(function(error) {
console.error('Error fetching events:', error);
failureCallback(error);
});
},
eventClick: function(info) {
var startTime = info.event.start.toLocaleString();
var endTime;
if (info.event.end) {
endTime = info.event.end.toLocaleString();
} else {
endTime = 'N/A';
}
document.getElementById('modalEventTitle').innerText = info.event.title;
document.getElementById('modalEventDate').innerText = startTime;
document.getElementById('modalEventEndTime').innerText = endTime;
var myModal = new bootstrap.Modal(document.getElementById('eventModal'));
myModal.show();
}
});
calendar.render();
});
</script>

<div id="calendar"></div>

@if (Model.IsPC2EventCalendar)
{
<img class="d-block mx-auto img-fluid img-flyer" src="~/images/events/ActivitiesFlyer2024.jpg" alt="PC2 Activities and Social Gatherings - Events Flyer">
<br />
<p class="text-center"><a target="_blank" href="~/PDF/Events/ActivitiesFlyer2024.pdf">Downloadable 2024 Activities Flyer</a></p>
}
}
38 changes: 38 additions & 0 deletions PC2/wwwroot/css/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -591,3 +591,41 @@ div.results:hover, div.results:hover #agencyName2 {
max-height : 550px;
overflow-y: auto;
}

/* Event Calendar CSS*/

/* Calendar styles for small screen sizes */
@media (max-width: 768px) {
#calendar {
font-size: 13px;
}

.fc-header-toolbar {
flex-direction: column;
align-items: center;
}

.fc-button {
padding: 5px 10px;
font-size: 12px;
}
}

/* Modal styles for small screen sizes */
@media (max-width: 767px) {
.modal-dialog {
max-width: 75%;
}
}

/* Make current day more obvious */
.fc-day-today {
font-weight: bold;
}

.fc-event {
background-color: cornflowerblue !important;
}



0 comments on commit 130c1c9

Please sign in to comment.