Skip to content
Snippets Groups Projects
Commit 9120827e authored by Miniontoby's avatar Miniontoby :writing_hand_tone1:
Browse files

Added some files for editing the roster....

parent 6b4d55ce
No related branches found
No related tags found
No related merge requests found
......@@ -101,3 +101,15 @@ ALTER TABLE `roles_permissions` ADD PRIMARY KEY (`role_id`,`perm_id`);
INSERT INTO `roles_permissions` (`role_id`, `perm_id`) VALUES
(1, 1), (1, 2), (2, 2);
CREATE TABLE IF NOT EXISTS roster (
`id` INTEGER PRIMARY KEY,
`name` TEXT,
`start` DATETIME,
`end` DATETIME,
`description` TEXT,
`location` TEXT,
`type` INTEGER,
`allday` INTEGER
)
\ No newline at end of file
<?php
include('../functions/class.php');
$app = new MySchoolDay();
$json = file_get_contents('php://input');
$params = json_decode($json);
$start = $params->start;
$end = $params->end;
$text = $params->text;
$description = $params->description;
$location = $params->location;
$allday = $params->allday;
$type = $params->type;
$insert = "INSERT INTO events (name, start, end, description, location, allday, type) VALUES ($name, $start, $end, $description, $location, $allday, $type)";
$app->db->query($insert);
class Result {}
$response = new Result();
$response->result = 'OK';
$response->id = $app->db->lastInsertId();
$response->message = 'Created with id: '.$app->db->lastInsertId();
header('Content-Type: application/json');
echo json_encode($response);
<?php
include('../functions/class.php');
$app = new MySchoolDay();
// .events.load() passes start and end as query string parameters by default
$start = $_GET["start"];
$end = $_GET["end"];
$type = $_GET["type"] ?? "";
$app->db->query("SELECT * FROM roster WHERE NOT ((end <= $start) OR (start >= $end))");
if ($app->db->numRows() == 0){
exit;
}
$result = $app->db->fetchArray();
class Event {}
$events = array();
if ($type == "planning"){
foreach($result as $row) {
$e = new Event();
$e->id = $row['id'];
$e->title = $row['name'];
$e->start = $row['start'];
$e->end = $row['end'];
$e->description = $row['description'];
$e->location = $row['location'];
$allday = 0;
if($row['allday'] == "1") $allday = 1;
$e->allDay = $allday;
$events[] = $e;
}
} else {
foreach($result as $row) {
$e = new Event();
$e->id = $row['id'];
$e->text = $row['name'];
$e->start = $row['start'];
$e->end = $row['end'];
$e->description = $row['description'];
$e->location = $row['location'];
$allday = 0;
if($row['allday'] == "1") $allday = 1;
$e->allday = $allday;
switch($row['type']){
case 1:
$type = "info";
break;
case 2:
$type = "homework";
break;
case 3:
$type = "test";
break;
default:
$type = "";
}
$e->tags = ['type' => $type];
$events[] = $e;
}
}
header('Content-Type: application/json');
echo json_encode($events);
html, body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
max-height: 80%;
margin: 40px auto;
}
.popper,
.tooltip {
position: absolute;
z-index: 9999;
background: #FFC107;
color: black;
width: 150px;
border-radius: 3px;
box-shadow: 0 0 2px rgba(0,0,0,0.5);
padding: 10px;
text-align: center;
}
.style5 .tooltip {
background: #1E252B;
color: #FFFFFF;
max-width: 200px;
width: auto;
font-size: .8rem;
padding: .5em 1em;
}
.popper .popper__arrow,
.tooltip .tooltip-arrow {
width: 0;
height: 0;
border-style: solid;
position: absolute;
margin: 5px;
}
.tooltip .tooltip-arrow,
.popper .popper__arrow {
border-color: #FFC107;
}
.style5 .tooltip .tooltip-arrow {
border-color: #1E252B;
}
.popper[x-placement^="top"],
.tooltip[x-placement^="top"] {
margin-bottom: 5px;
}
.popper[x-placement^="top"] .popper__arrow,
.tooltip[x-placement^="top"] .tooltip-arrow {
border-width: 5px 5px 0 5px;
border-left-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
bottom: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.popper[x-placement^="bottom"],
.tooltip[x-placement^="bottom"] {
margin-top: 5px;
}
.tooltip[x-placement^="bottom"] .tooltip-arrow,
.popper[x-placement^="bottom"] .popper__arrow {
border-width: 0 5px 5px 5px;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: transparent;
top: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.tooltip[x-placement^="right"],
.popper[x-placement^="right"] {
margin-left: 5px;
}
.popper[x-placement^="right"] .popper__arrow,
.tooltip[x-placement^="right"] .tooltip-arrow {
border-width: 5px 5px 5px 0;
border-left-color: transparent;
border-top-color: transparent;
border-bottom-color: transparent;
left: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
.popper[x-placement^="left"],
.tooltip[x-placement^="left"] {
margin-right: 5px;
}
.popper[x-placement^="left"] .popper__arrow,
.tooltip[x-placement^="left"] .tooltip-arrow {
border-width: 5px 0 5px 5px;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
right: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
.tooltip {
opacity: 100;
}
.tooltip-inner{
background: #FFC107;
color: #000;
}
.context-menu {
position: absolute;
text-align: center;
background: lightgray;
border: 1px solid black;
display: none;
z-index: 10;
}
.context-menu--active {
display: block;
}
.context-menu ul {
padding: 0px;
margin: 0px;
min-width: 150px;
list-style: none;
}
.context-menu ul li {
padding-bottom: 7px;
padding-top: 7px;
border: 1px solid black;
}
.context-menu ul li a {
text-decoration: none;
color: black;
}
.context-menu ul li:hover {
background: darkgray !important;
}
.fa, .fas, .far, .fal, .fad, .fab{
line-height: 1.5;
}
\ No newline at end of file
......@@ -34,11 +34,21 @@ class MySchoolDay {
private function setupGettext() {
$translationDir = dirname(__DIR__) . "/locale";
$lang = $this->config['app_language'];
// Set the language.
if(defined('LC_MESSAGES')) {
// For Linux-based distributions.
setlocale(LC_MESSAGES, $lang);
} else {
// For Windows.
putenv("LC_ALL=$lang");
}
putenv("LANG=$lang");
putenv("LANGUAGE=$lang");
setlocale(LC_CTYPE,$lang);
$mtime = 0;
$originals = glob($translationDir . "/*/LC_MESSAGES/myschoolday.mo");
putenv("LANG=" . $lang);
putenv("LANGUAGE=" . $lang);
setlocale(LC_ALL, $lang);
foreach ($originals as $file) {
$mtime = max($mtime, filemtime($file));
}
......
......@@ -66,7 +66,7 @@ class db {
return $this;
}
public function fetchAll($callback = null) {
public function fetchAll($callback = null): array {
$params = array();
$row = array();
$meta = $this->query->result_metadata();
......@@ -92,7 +92,7 @@ class db {
return $result;
}
public function fetchArray() {
public function fetchArray(): array {
$params = array();
$row = array();
$meta = $this->query->result_metadata();
......
......@@ -62,7 +62,7 @@ $url = $app->config['app_folder']; //($_SERVER['REQUEST_URI'] == $app->config['a
<link rel="icon" type="image/ico" href="<?=$url?>favicon.ico"/>
<link rel="manifest" href="<?=$url?>manifest.json"/>
<link rel="shortcut" type="image/png" href="<?=$url?>images/LogoMint.png"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href='https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.css'>
<link rel="stylesheet" href="<?=$url?>css/style.css"/>
</head>
<body>
......
......@@ -21,5 +21,6 @@ header("Content-Type: application/json; charset=utf-8");
],
"start_url": "<?=$url?>index.php",
"scope": "<?=$url?>",
"prefer_related_applications": false
"prefer_related_applications": false,
"id": "<?=$url?>index.php"
}
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.css' rel="stylesheet">
<link href='https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13.1/css/all.css' rel='stylesheet'>
<link rel="stylesheet" href="<?=$url?>css/style.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/rrule@2.6.4/dist/es5/rrule.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/rrule@5.5.0/main.global.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.min.js"></script>
<script src='https://unpkg.com/popper.js/dist/umd/popper.min.js'></script>
<script src='https://unpkg.com/tooltip.js/dist/umd/tooltip.min.js'></script>
<div id='calendar'></div>
<div class="modal fade" id="schedule-edit">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Edit Your Schedule</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<form>
<div class="form-group">
<label>Schedule Name:</label>
<input type="text" class="form-control" id="newname">
</div>
</form>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" id="deleteitem" data-dismiss="modal">DELETE</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-success">Save Your Schedule</button>
</div>
</div>
</div>
</div>
<div id="contextMenu" class="context-menu" style="display: none">
<ul></ul>
</div>
<script>
var menu = document.querySelector("#context-menu");
var menuState = 0;
var active = "context-menu--active";
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
bootstrapFontAwesome: { close: 'fa-times', prev: 'fa-chevron-left', next: 'fa-chevron-right' },
businessHours: { daysOfWeek: [ 1, 2, 3, 4, 5 ], startTime: '08:25', endTime: '15:00' },
dayHeaderFormat: { year: 'numeric', month: 'long', day: 'numeric' },
dayMaxEvents: false,
editable: true,
events: '<?=$url?>api/get_roster.php?type=planning&school=<?=$_SESSION["user"]["school_id"]?>',
firstDay: 1,
footerToolbar: { left: 'prev,next today', center: '', right: 'timeGridWeek,timeGridDay' },
headerToolbar: { left: 'prev,next today', center: 'title', right: 'timeGridWeek,timeGridDay' },
locale: "nl",
navLinks: true,
nowIndicator: true,
initialDate: '2021-12-09',
initialView: 'timeGridWeek',
selectable: true,
selectMirror: true,
slotMinTime: '08:25:00',
slotMaxTime: '15:00:00',
themeSystem: 'bootstrap',
timeZone: 'UTC+1',
titleFormat: { year: 'numeric', month: 'long', day: 'numeric' },
weekends: false,
weekNumbers: true,
eventClick: function(args) {
args.jsEvent.preventDefault();
showDetails(args.event)
},
eventChange: function (args) {
handleEditEvent({title: args.event.title}, args.event);
},
eventContent: function(args, createElement) {
var innerText = args.event.title;
element = document.createElement('div');
element2 = document.createElement('div');
element3 = document.createElement('div');
elementmain = document.createElement('div');
element.className = "fc-event-time";
element2.className = "fc-event-title-container";
element3.className = "fc-event-title fc-sticky";
elementmain.className = "fc-event-main-frame";
if (args.event.extendedProps.description){
args.backgroundColor = "green";
}
if (args.event.extendedProps.location) {
console.log(args);
innerText += " - " + args.event.extendedProps.location;
}
element3.innerText = innerText;
element2.appendChild(element3);
element.textContent = args.timeText;
elementmain.appendChild(element);
elementmain.appendChild(element2);
let arrayOfDomNodes = [ elementmain ]
return { domNodes: arrayOfDomNodes }
},
eventDidMount: function(args) {
var tooltip = new Tooltip(args.el, {
title: args.event.extendedProps.description,
placement: 'top',
trigger: 'hover',
container: 'body'
});
contextListener(args.el, args.event, calendar);
},
select: function(args) {
createEvent(args, calendar);
}
});
calendar.render();
});
function httpajax(args){
const t = new XMLHttpRequest();
var a = "object" == typeof args.data, r = args.data, o = args.method || (args.data ? "POST" : "GET"), n = args.success || function() {}, i = args.error || function() {}, d = args.url, s = args.contentType || (a ? "application/json" : "text/plain");
t.open(o, d, !0),
t.setRequestHeader("Content-type", s),
t.onreadystatechange = function() {
if (4 === t.readyState)
if (200 === t.status || 201 === t.status || 204 === t.status || 304 === t.status) {
var e = {};
e.request = t,
t.responseText && (e.data = JSON.parse(t.responseText)),
n(e)
} else if (i) {
var e = {};
e.request = t,
i(e)
} else
window.console && console.log("HTTP error " + t.status)
},
4 !== t.readyState && (a && (r = JSON.stringify(r)),
t.send(r))
}
document.onclick = hideMenu;
function hideMenu() {
document.getElementById("contextMenu").style.display = "none"
}
var modal = '';
class Modal {
constructor (config){
this.config = config;
this.root = document.getElementById('modal');
if (!this.root) {
var elements = {};
elements.main = document.createElement('div');
elements.dialog = document.createElement('div');
elements.content = document.createElement('div');
elements.header = document.createElement('div');
elements.body = document.createElement('div');
elements.footer = document.createElement('div');
elements.title = document.createElement('h4');
elements.button1 = document.createElement('button');
elements.form = document.createElement('form');
elements.button2 = document.createElement('button');
elements.button3 = document.createElement('button');
elements.body.className = "modal-body";
elements.button1.className = "close";
elements.button2.className = "btn btn-danger";
elements.button3.className = "btn btn-success";
elements.content.className = "modal-content";
elements.dialog.className = "modal-dialog";
elements.footer.className = "modal-footer";
elements.header.className = "modal-header";
elements.main.className = "modal fade";
elements.title.className = "modal-title";
elements.button3.id = "form-submit-button";
elements.form.id = "form-group";
elements.main.id = "modal";
elements.title.id = "modal-title";
elements.button1.setAttribute("data-dismiss", "modal");
elements.button2.setAttribute("data-dismiss", "modal");
elements.button1.innerHTML = "&times;";
elements.button2.textContent = "Close";
elements.button1.type = "button";
elements.button2.type = "button";
elements.button3.type = "button";
elements.button1.onclick = function () { $('#modal').modal('hide'); }
elements.button2.onclick = function () { $('#modal').modal('hide'); }
elements.header.appendChild(elements.title);
elements.header.appendChild(elements.button1);
elements.body.appendChild(elements.form);
elements.footer.appendChild(elements.button2);
elements.footer.appendChild(elements.button3);
elements.content.appendChild(elements.header);
elements.content.appendChild(elements.body);
elements.content.appendChild(elements.footer);
elements.dialog.appendChild(elements.content);
elements.main.appendChild(elements.dialog);
document.body.appendChild(elements.main);
this.root = document.getElementById('modal');
}
this.title = document.getElementById('modal-title');
this.form = document.getElementById('form-group');
this.subbutton = document.getElementById('form-submit-button');
this.title.textContent = this.config.title;
this.subbutton.textContent = this.config.title;
this.subbutton.style.display = "inline-block";
this.form.innerHTML = "";
if (this.config.inputs){
this.inputs = this.config.inputs;
this.results = {};
for (var i in this.inputs){
var form_group = document.createElement('div');
form_group.className = "form-group";
var label = document.createElement('label');
label.setAttribute('for', this.inputs[i].id);
label.className = "col-form-label";
label.textContent = this.inputs[i].label;
if (this.inputs[i].type == "textarea"){
var input = document.createElement('textarea');
input.className = "form-control";
input.id = this.inputs[i].id;
input.textContent = this.inputs[i].value ?? "";
} else {
var input = document.createElement('input');
input.type = this.inputs[i].type;
input.className = "form-control";
input.id = this.inputs[i].id;
input.value = this.inputs[i].value ?? "";
}
form_group.appendChild(label);
form_group.appendChild(input);
this.form.appendChild(form_group);
this.results[this.inputs[i].id] = "";
}
} else if (this.config.text) {
this.text = this.config.text;
for (var i in this.text){
var form_group = document.createElement('div');
form_group.className = "form-group";
var label = document.createElement('label');
label.innerHTML = this.text[i];
form_group.appendChild(label);
this.form.appendChild(form_group);
}
this.subbutton.style.display = "none";
}
this.subbutton.onclick = function (e) { modal.submit(e) };
$("#modal").modal('show');
}
submit (e){
$("#modal").modal('hide');
if (this.inputs){
for (var i in this.inputs){
this.results[this.inputs[i].id] = document.getElementById(this.inputs[i].id).value;
}
this.config.callback(this.results);
}
return true;
}
}
function createEvent(args, calendar){
modal = new Modal({title: "Add new event", inputs: [{id: "title", label: "Title:", type: "text"}, {id: "description", label: "Description:", type: "text"}], callback: function (res) { handleCreateEvent(res, args, calendar); }});
}
function handleCreateEvent(res, args, calendar){
if (res.title) {
var data = {
start: args.start,
end: args.end,
text: res.title,
description: res.description,
location: "",
allday: args.allDay
};
httpajax({
url: "<?=$url?>api/create_roster.php",
data: data,
success: function(ajax) {
calendar.addEvent({
id: ajax.data.id,
title: res.title,
start: args.start,
end: args.end,
allDay: args.allDay,
description: res.description,
})
}
});
}
calendar.unselect();
}
function editEvent(event){
modal = new Modal({title: "Edit event", inputs: [{id: "title", label: "Title:", type: "text", value: event.title}, {id: "description", label: "Description:", type: "text", value: event.extendedProps.description}], callback: function (res) { handleEditEvent(res, event); }});
}
function handleEditEvent(res, event){
httpajax({
url: "<?=$url?>api/change_roster.php",
data: { id: event.id, newStart: event.startStr, newEnd: event.endStr, newName: res.title, newDescription: res.description },
success: function(ajax) {
console.log("eventChanged");
}
});
}
function showDetails(event){
modal = new Modal({title: "Show Details", text: ["<b>Title: </b>" + event.title, "<b>Details/homework:</b> " + event.extendedProps.description ?? "", "<b>Time:</b> " + event.start + " - " + event.end], callback: function (res) { handleEditEvent(res, event); }});
}
function goToHomework(event){
alert(event.title);
}
function deleteEvent(event){
if (confirm('Are you sure you want to delete this event?')) {
httpajax({
url: "<?=$url?>api/delete_roster.php",
data: {id: event.id},
success: function(ajax) {
event.remove();
}
})
}
}
function contextListener(el, event, calendar, type="event") {
el.addEventListener("contextmenu", function(e) {
e.preventDefault();
if (document.getElementById("contextMenu").style.display == "block") {
hideMenu();
} else {
var menu = document.getElementById("contextMenu");
menu.style.display = 'block';
menu.style.left = e.pageX + "px";
menu.style.top = e.pageY + "px";
var menulist = menu.firstChild.nextSibling;
menulist.innerHTML = "<ul></ul>";
if (type=="event"){
var li = document.createElement("li"); li.textContent = "Details"; li.onclick = function() { showDetails(event); }; menulist.appendChild(li);
var li = document.createElement("li"); li.textContent = "Edit"; li.onclick = function() {
document.getElementsByClassName('btn-success')[1].onclick = function () { editEvent(args.event); };
document.getElementById('newname').value = event.title;
document.getElementById('deleteitem').onclick = function () { deleteEvent(args.event); }; var modal = $("#schedule-edit");modal.modal(); };
menulist.appendChild(li);
var li = document.createElement("li"); li.textContent = "Go to homework"; li.onclick = function() { goToHomework(event); }; menulist.appendChild(li);
var li = document.createElement("li"); li.textContent = ""; menulist.appendChild(li);
var li = document.createElement("li"); li.textContent = "Delete"; li.onclick = function() { deleteEvent(event); }; li.style.background = "red"; menulist.appendChild(li);
}
}
});
}
</script>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment