Adding a Custom Calendar Filtered by ID from Page URL in Power Pages

Integrating a calendar into a Power Pages portal can enhance the user experience by displaying scheduled events dynamically. This article guides you through adding a FullCalendar instance to Power Pages, retrieving events via Web API, and filtering them by an ID retrieved from the page URL.

Prerequisites

  • A Power Pages website

  • A configured Web API endpoint

  • FullCalendar library

Utilizing Web API in Power Pages

For a deeper understanding of using Web API in Power Pages, refer to the following guide: Utilizing Web API in Power Pages: A Comprehensive Guide.

Implementation

Step 1: Add FullCalendar to Your Page

Ensure that the FullCalendar library is included in your page.

<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.css'/>
<link rel='stylesheet' href='//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css'/>
<script src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.js'></script>
<script src='//code.jquery.com/ui/1.12.1/jquery-ui.js'></script>

Step 2: Implement JavaScript to Retrieve and Display Events

Create a JavaScript function to fetch event records using the Web API and display them in FullCalendar.

$(document).ready(function() {
    var urlParams = new URLSearchParams(window.location.search);
    var caseId = urlParams.get("id"); // Retrieve the ID from the URL
    var eventsArray = [];

    if (!caseId) {
        initializeCalendar(eventsArray);
        return;
    }

    webapi.safeAjax({
        type: "GET",
        url: "/_api/caseeventtimelines?" +
             "$select=caseeventtimelineid,eventdatetime,name,description" +
             "&$filter=_workcaseid_value eq " + caseId,
        contentType: "application/json",
        headers: {
            "Prefer": "odata.include-annotations=*"
        },
        success: function (data) {
            for (var i = 0; i < data.value.length; i++) {
                var item = data.value[i];
                eventsArray.push({
                    id: item["caseeventtimelineid"],
                    title: item["name"] || "No Title",
                    start: item["eventdatetime"],
                    description: item["description"] || ""
                });
            }
            initializeCalendar(eventsArray);
        },
        error: function () {
            console.log("Error fetching event data.");
            initializeCalendar(eventsArray);
        }
    });

    function initializeCalendar(calendarEvents) {
        $('#milestoneCalendar').fullCalendar({
            defaultView: 'month',
            height: 500,
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'month,basicWeek,basicDay'
            },
            events: calendarEvents,
            eventClick: function(calEvent) {
                var modalContent = `<p><strong>Title:</strong> ${calEvent.title}</p>
                                    <p><strong>Description:</strong> ${calEvent.description}</p>
                                    <p><strong>Start:</strong> ${calEvent.start.format('MMMM Do YYYY, h:mm:ss a')}</p>`;
               
                $("#eventDetailDialog").html(modalContent).dialog({
                    modal: true,
                    width: 400,
                    buttons: {
                        "Details": function() {
                            window.location.href = "/Case-Milestone?id=" + calEvent.id;
                        },
                        "Close Window": function() {
                            $(this).dialog("close");
                        }
                    }
                });
            }
        });
    }
});


Step 3: Add an HTML Container for the Calendar

<div id='milestoneCalendar' style='margin-right: auto; margin-bottom: 0px; margin-left: auto; width: 90%; max-width: 1200px; margin-top: 20px;'></div>
<div id='eventDetailDialog' title='Event Details' style='display: none;'></div>

Step 4: Add Entity Form to Display Work Case Details


<div class="row sectionBlockLayout text-start" style="display: flex; flex-wrap: wrap; margin: 0px; min-height: auto; padding: 8px;">
  <div class="container" style="padding: 0px; display: flex; flex-wrap: wrap;">
    <div class="col-lg-12 columnBlockLayout" style="flex-grow: 1; display: flex; flex-direction: column; min-width: 250px;">
      {% entityform name: 'Work Case - Read' %}
    </div>
  </div>
</div>

Full HTML Code

<!-- FullCalendar and dependencies -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="milestoneCalendar" style="margin-right: auto; margin-bottom: 0px; margin-left: auto; width: 90%; max-width: 1200px; margin-top: 20px;"></div>
<div id="eventDetailDialog" title="Event Details" style="display: none;"></div>
<script>
  /**
   * Retrieves case milestone records via Portal Web API and displays them on a FullCalendar instance.
   */
  $(document).ready(function()
  {
      var urlParams = new URLSearchParams(window.location.search);
      var caseId = urlParams.get("id"); // The case GUID from query string
      var eventsArray = [];

      if (!caseId)
      {
          // If no case ID found, still load calendar (empty) to avoid errors
          initializeCalendar(eventsArray);
          return;
      }

      webapi.safeAjax({
          type: "GET",
          url: "/_api/bcfirb_caseeventtimelines?" +
               "$select=bcfirb_caseeventtimelineid,bcfirb_eventdatetime,bcfirb_name,bcfirb_description" +
               "&$filter=_bcfirb_workcaseid_value eq " + caseId,
          contentType: "application/json",
          headers:
          {
              "Prefer": "odata.include-annotations=*"
          },
          success: function (data, textStatus, xhr)
          {
              for (var i = 0; i < data.value.length; i++)
              {
                  var item = data.value[i];
                  var recordId = item["bcfirb_caseeventtimelineid"];
                  var recordTitle = item["bcfirb_name"] || "No Title";
                  var recordStart = item["bcfirb_eventdatetime"];
                  var recordDesc = item["bcfirb_description"] || "";

                  eventsArray.push({
                      id: recordId,
                      title: recordTitle,
                      start: recordStart,
                      description: recordDesc
                  });
              }
              initializeCalendar(eventsArray);
          },
          error: function (xhr, textStatus, errorThrown)
          {
              console.log(xhr);
              initializeCalendar(eventsArray);
          }
      });

      /**
       * Initializes the FullCalendar with given events
       * @param {Array} calendarEvents Array of events to load into the calendar
       */
      function initializeCalendar(calendarEvents)
      {
          $('#milestoneCalendar').fullCalendar({
              defaultView: 'month',
              height: 500,
              header:
              {
                  left: 'prev,next today',
                  center: 'title',
                  right: 'month,basicWeek,basicDay'
              },
              events: calendarEvents,
              eventClick: function(calEvent)
              {
                  var modalContent = "<p><strong>Title:</strong> " + calEvent.title + "</p>" +
                                     "<p><strong>Description:</strong> " + calEvent.description + "</p>" +
                                     "<p><strong>Start:</strong> " + calEvent.start.format('MMMM Do YYYY, h:mm:ss a') + "</p>";

                  $("#eventDetailDialog").html(modalContent).dialog({
                      modal: true,
                      width: 400,
                      buttons:
                      {
                          "Details": function()
                          {
                              window.location.href = "/Case-Milestone?id=" + calEvent.id;
                          },
                          "Close Window": function()
                          {
                              $(this).dialog("close");
                          }
                      }
                  });
              }
          });
      }
  });
</script>
<div class="row sectionBlockLayout text-start" style="display: flex; flex-wrap: wrap; margin: 0px; min-height: auto; padding: 8px;">
  <div class="container" style="padding: 0px; display: flex; flex-wrap: wrap;"><div class="col-lg-12 columnBlockLayout" style="flex-grow: 1; display: flex; flex-direction: column; min-width: 250px;">{% entityform name: 'Work Case - Read' %}</div></div>
</div>

Summary

By following these steps, you can successfully integrate a dynamic calendar in Power Pages that fetches and displays event data from the Web API, filtered based on an ID from the page URL. This approach enables real-time event tracking and enhances user engagement with your Power Pages site.

No comments:

Post a Comment