shell bypass 403
/**
* App Calendar
*/
/**
* ! If both start and end dates are same Full calendar will nullify the end date value.
* ! Full calendar will end the event on a day before at 12:00:00AM thus, event won't extend to the end date.
* ! We are getting events from a separate file named app-calendar-events.js. You can add or remove events from there.
**/
'use-strict';
// RTL Support
var direction = 'ltr',
assetPath = '../../../app-assets/';
if ($('html').data('textdirection') == 'rtl') {
direction = 'rtl';
}
if ($('body').attr('data-framework') === 'laravel') {
assetPath = $('body').attr('data-asset-path');
}
$(document).on('click', '.fc-sidebarToggle-button', function (e) {
$('.app-calendar-sidebar, .body-content-overlay').addClass('show');
});
$(document).on('click', '.body-content-overlay', function (e) {
$('.app-calendar-sidebar, .body-content-overlay').removeClass('show');
});
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar'),
eventToUpdate,
sidebar = $('.event-sidebar'),
calendarsColor = {
Business: 'primary',
Holiday: 'success',
Personal: 'danger',
Family: 'warning',
ETC: 'info'
},
eventForm = $('.event-form'),
addEventBtn = $('.add-event-btn'),
cancelBtn = $('.btn-cancel'),
updateEventBtn = $('.update-event-btn'),
toggleSidebarBtn = $('.btn-toggle-sidebar'),
eventTitle = $('#title'),
eventLabel = $('#select-label'),
startDate = $('#start-date'),
endDate = $('#end-date'),
eventUrl = $('#event-url'),
eventGuests = $('#event-guests'),
eventLocation = $('#event-location'),
allDaySwitch = $('.allDay-switch'),
selectAll = $('.select-all'),
calEventFilter = $('.calendar-events-filter'),
filterInput = $('.input-filter'),
btnDeleteEvent = $('.btn-delete-event'),
calendarEditor = $('#event-description-editor');
// --------------------------------------------
// On add new item, clear sidebar-right field fields
// --------------------------------------------
$('.add-event button').on('click', function (e) {
$('.event-sidebar').addClass('show');
$('.sidebar-left').removeClass('show');
$('.app-calendar .body-content-overlay').addClass('show');
});
// Label select
if (eventLabel.length) {
function renderBullets(option) {
if (!option.id) {
return option.text;
}
var $bullet =
"<span class='bullet bullet-" +
$(option.element).data('label') +
" bullet-sm me-50'> " +
'</span>' +
option.text;
return $bullet;
}
eventLabel.wrap('<div class="position-relative"></div>').select2({
placeholder: 'Select value',
dropdownParent: eventLabel.parent(),
templateResult: renderBullets,
templateSelection: renderBullets,
minimumResultsForSearch: -1,
escapeMarkup: function (es) {
return es;
}
});
}
// Guests select
if (eventGuests.length) {
function renderGuestAvatar(option) {
if (!option.id) {
return option.text;
}
var $avatar =
"<div class='d-flex flex-wrap align-items-center'>" +
"<div class='avatar avatar-sm my-0 me-50'>" +
"<span class='avatar-content'>" +
"<img src='" +
assetPath +
'images/avatars/' +
$(option.element).data('avatar') +
"' alt='avatar' />" +
'</span>' +
'</div>' +
option.text +
'</div>';
return $avatar;
}
eventGuests.wrap('<div class="position-relative"></div>').select2({
placeholder: 'Select value',
dropdownParent: eventGuests.parent(),
closeOnSelect: false,
templateResult: renderGuestAvatar,
templateSelection: renderGuestAvatar,
escapeMarkup: function (es) {
return es;
}
});
}
// Start date picker
if (startDate.length) {
var start = startDate.flatpickr({
enableTime: true,
altFormat: 'Y-m-dTH:i:S',
onReady: function (selectedDates, dateStr, instance) {
if (instance.isMobile) {
$(instance.mobileInput).attr('step', null);
}
}
});
}
// End date picker
if (endDate.length) {
var end = endDate.flatpickr({
enableTime: true,
altFormat: 'Y-m-dTH:i:S',
onReady: function (selectedDates, dateStr, instance) {
if (instance.isMobile) {
$(instance.mobileInput).attr('step', null);
}
}
});
}
// Event click function
function eventClick(info) {
eventToUpdate = info.event;
if (eventToUpdate.url) {
info.jsEvent.preventDefault();
window.open(eventToUpdate.url, '_blank');
}
sidebar.modal('show');
addEventBtn.addClass('d-none');
cancelBtn.addClass('d-none');
updateEventBtn.removeClass('d-none');
btnDeleteEvent.removeClass('d-none');
eventTitle.val(eventToUpdate.title);
start.setDate(eventToUpdate.start, true, 'Y-m-d');
eventToUpdate.allDay === true ? allDaySwitch.prop('checked', true) : allDaySwitch.prop('checked', false);
eventToUpdate.end !== null
? end.setDate(eventToUpdate.end, true, 'Y-m-d')
: end.setDate(eventToUpdate.start, true, 'Y-m-d');
sidebar.find(eventLabel).val(eventToUpdate.extendedProps.calendar).trigger('change');
eventToUpdate.extendedProps.location !== undefined ? eventLocation.val(eventToUpdate.extendedProps.location) : null;
eventToUpdate.extendedProps.guests !== undefined
? eventGuests.val(eventToUpdate.extendedProps.guests).trigger('change')
: null;
eventToUpdate.extendedProps.guests !== undefined
? calendarEditor.val(eventToUpdate.extendedProps.description)
: null;
// Delete Event
btnDeleteEvent.on('click', function () {
eventToUpdate.remove();
// removeEvent(eventToUpdate.id);
sidebar.modal('hide');
$('.event-sidebar').removeClass('show');
$('.app-calendar .body-content-overlay').removeClass('show');
});
}
// Modify sidebar toggler
function modifyToggler() {
$('.fc-sidebarToggle-button')
.empty()
.append(feather.icons['menu'].toSvg({ class: 'ficon' }));
}
// Selected Checkboxes
function selectedCalendars() {
var selected = [];
$('.calendar-events-filter input:checked').each(function () {
selected.push($(this).attr('data-value'));
});
return selected;
}
// --------------------------------------------------------------------------------------------------
// AXIOS: fetchEvents
// * This will be called by fullCalendar to fetch events. Also this can be used to refetch events.
// --------------------------------------------------------------------------------------------------
function fetchEvents(info, successCallback) {
// Fetch Events from API endpoint reference
/* $.ajax(
{
url: '../../../app-assets/data/app-calendar-events.js',
type: 'GET',
success: function (result) {
// Get requested calendars as Array
var calendars = selectedCalendars();
return [result.events.filter(event => calendars.includes(event.extendedProps.calendar))];
},
error: function (error) {
console.log(error);
}
}
); */
var calendars = selectedCalendars();
// We are reading event object from app-calendar-events.js file directly by including that file above app-calendar file.
// You should make an API call, look into above commented API call for reference
selectedEvents = events.filter(function (event) {
// console.log(event.extendedProps.calendar.toLowerCase());
return calendars.includes(event.extendedProps.calendar.toLowerCase());
});
// if (selectedEvents.length > 0) {
successCallback(selectedEvents);
// }
}
// Calendar plugins
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
events: fetchEvents,
editable: true,
dragScroll: true,
dayMaxEvents: 2,
eventResizableFromStart: true,
customButtons: {
sidebarToggle: {
text: 'Sidebar'
}
},
headerToolbar: {
start: 'sidebarToggle, prev,next, title',
end: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
},
direction: direction,
initialDate: new Date(),
navLinks: true, // can click day/week names to navigate views
eventClassNames: function ({ event: calendarEvent }) {
const colorName = calendarsColor[calendarEvent._def.extendedProps.calendar];
return [
// Background Color
'bg-light-' + colorName
];
},
dateClick: function (info) {
var date = moment(info.date).format('YYYY-MM-DD');
resetValues();
sidebar.modal('show');
addEventBtn.removeClass('d-none');
updateEventBtn.addClass('d-none');
btnDeleteEvent.addClass('d-none');
startDate.val(date);
endDate.val(date);
},
eventClick: function (info) {
eventClick(info);
},
datesSet: function () {
modifyToggler();
},
viewDidMount: function () {
modifyToggler();
}
});
// Render calendar
calendar.render();
// Modify sidebar toggler
modifyToggler();
// updateEventClass();
// Validate add new and update form
if (eventForm.length) {
eventForm.validate({
submitHandler: function (form, event) {
event.preventDefault();
if (eventForm.valid()) {
sidebar.modal('hide');
}
},
title: {
required: true
},
rules: {
'start-date': { required: true },
'end-date': { required: true }
},
messages: {
'start-date': { required: 'Start Date is required' },
'end-date': { required: 'End Date is required' }
}
});
}
// Sidebar Toggle Btn
if (toggleSidebarBtn.length) {
toggleSidebarBtn.on('click', function () {
cancelBtn.removeClass('d-none');
});
}
// ------------------------------------------------
// addEvent
// ------------------------------------------------
function addEvent(eventData) {
calendar.addEvent(eventData);
calendar.refetchEvents();
}
// ------------------------------------------------
// updateEvent
// ------------------------------------------------
function updateEvent(eventData) {
var propsToUpdate = ['id', 'title', 'url'];
var extendedPropsToUpdate = ['calendar', 'guests', 'location', 'description'];
updateEventInCalendar(eventData, propsToUpdate, extendedPropsToUpdate);
}
// ------------------------------------------------
// removeEvent
// ------------------------------------------------
function removeEvent(eventId) {
removeEventInCalendar(eventId);
}
// ------------------------------------------------
// (UI) updateEventInCalendar
// ------------------------------------------------
const updateEventInCalendar = (updatedEventData, propsToUpdate, extendedPropsToUpdate) => {
const existingEvent = calendar.getEventById(updatedEventData.id);
// --- Set event properties except date related ----- //
// ? Docs: https://fullcalendar.io/docs/Event-setProp
// dateRelatedProps => ['start', 'end', 'allDay']
// eslint-disable-next-line no-plusplus
for (var index = 0; index < propsToUpdate.length; index++) {
var propName = propsToUpdate[index];
existingEvent.setProp(propName, updatedEventData[propName]);
}
// --- Set date related props ----- //
// ? Docs: https://fullcalendar.io/docs/Event-setDates
existingEvent.setDates(updatedEventData.start, updatedEventData.end, { allDay: updatedEventData.allDay });
// --- Set event's extendedProps ----- //
// ? Docs: https://fullcalendar.io/docs/Event-setExtendedProp
// eslint-disable-next-line no-plusplus
for (var index = 0; index < extendedPropsToUpdate.length; index++) {
var propName = extendedPropsToUpdate[index];
existingEvent.setExtendedProp(propName, updatedEventData.extendedProps[propName]);
}
};
// ------------------------------------------------
// (UI) removeEventInCalendar
// ------------------------------------------------
function removeEventInCalendar(eventId) {
calendar.getEventById(eventId).remove();
}
// Add new event
$(addEventBtn).on('click', function () {
if (eventForm.valid()) {
var newEvent = {
id: calendar.getEvents().length + 1,
title: eventTitle.val(),
start: startDate.val(),
end: endDate.val(),
startStr: startDate.val(),
endStr: endDate.val(),
display: 'block',
extendedProps: {
location: eventLocation.val(),
guests: eventGuests.val(),
calendar: eventLabel.val(),
description: calendarEditor.val()
}
};
if (eventUrl.val().length) {
newEvent.url = eventUrl.val();
}
if (allDaySwitch.prop('checked')) {
newEvent.allDay = true;
}
addEvent(newEvent);
}
});
// Update new event
updateEventBtn.on('click', function () {
if (eventForm.valid()) {
var eventData = {
id: eventToUpdate.id,
title: sidebar.find(eventTitle).val(),
start: sidebar.find(startDate).val(),
end: sidebar.find(endDate).val(),
url: eventUrl.val(),
extendedProps: {
location: eventLocation.val(),
guests: eventGuests.val(),
calendar: eventLabel.val(),
description: calendarEditor.val()
},
display: 'block',
allDay: allDaySwitch.prop('checked') ? true : false
};
updateEvent(eventData);
sidebar.modal('hide');
}
});
// Reset sidebar input values
function resetValues() {
endDate.val('');
eventUrl.val('');
startDate.val('');
eventTitle.val('');
eventLocation.val('');
allDaySwitch.prop('checked', false);
eventGuests.val('').trigger('change');
calendarEditor.val('');
}
// When modal hides reset input values
sidebar.on('hidden.bs.modal', function () {
resetValues();
});
// Hide left sidebar if the right sidebar is open
$('.btn-toggle-sidebar').on('click', function () {
btnDeleteEvent.addClass('d-none');
updateEventBtn.addClass('d-none');
addEventBtn.removeClass('d-none');
$('.app-calendar-sidebar, .body-content-overlay').removeClass('show');
});
// Select all & filter functionality
if (selectAll.length) {
selectAll.on('change', function () {
var $this = $(this);
if ($this.prop('checked')) {
calEventFilter.find('input').prop('checked', true);
} else {
calEventFilter.find('input').prop('checked', false);
}
calendar.refetchEvents();
});
}
if (filterInput.length) {
filterInput.on('change', function () {
$('.input-filter:checked').length < calEventFilter.find('input').length
? selectAll.prop('checked', false)
: selectAll.prop('checked', true);
calendar.refetchEvents();
});
}
});