Initial commit

This commit is contained in:
mmk2410 2015-10-21 10:47:50 +02:00
parent bdecb95b7d
commit 39ff574037
19 changed files with 851 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
res/php/config.php
node_modules/

16
README.md Normal file
View file

@ -0,0 +1,16 @@
# TiTaMa
A time table manager with a beautiful material design.
# How does it work?
TiTaMa uses a MySQL database to store the timetable. For web interface PHP is used.
# What are the features?
- Single page user interface
- Responsive design
# HHVM
This page works also with HHVM

10
gulpfile.coffee Normal file
View file

@ -0,0 +1,10 @@
gulp = require 'gulp'
coffee = require 'gulp-coffee'
gulp.task 'coffee', ->
gulp.src './res/js/*.coffee'
.pipe coffee()
.pipe gulp.dest './res/js/'
gulp.task 'default', ->
gulp.watch './res/js/*.coffee', ['coffee']

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

289
index.php Normal file
View file

@ -0,0 +1,289 @@
<!DOCTYPE html>
<!--
TiTaMa - A TImeTAbleMAnager for the web
MIT LICENSE
2015 (c) Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
-->
<?php
function getFullDay($day) {
if ($day == "Mon") {
return "Monday";
} else if ($day == "Thu") {
return "Thusday";
} else if ($day == "Wed") {
return "Wednesday";
} else if ($day == "Thur") {
return "Thursday";
} else if ($day == "Fri") {
return "Friday";
}
}
?>
<html>
<head>
<meta charset="UTF-8">
<title>TiTaMa</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="description" content="A web time table manager">
<meta name="theme-color" content="#3f51b5">
<link rel="manifest" href="manifest.json">
<meta name="msapplication-TileColor" content="#3f51b5">
<meta name="mobile-web-app-capable" content="yes">
<meta name="application-name" content="TiTaMa">
<meta rel="icon" sizes="192x192" href="images/touch/chrome-touch-icon-192x192.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="TiTaMa">
<link rel="apple-touch-icon" href="images/touch/apple-touch-icon.png">
<meta name="msapplication-TileImage" content="images/touch/ms-touch-icon-144x144.png">
<link href='//fonts.googleapis.com/css?family=Roboto:400,600,300,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="./res/titama.css" />
</head>
<body>
<div class="header">
<span class="title">TiTaMa</span>
</div>
<?php
include './res/php/config.php';
if (isset($_GET['add'])) {
$conn = new mysqli($dbhost, $dbuser, $dbpassword, $dbname);
$name = $_POST['name'];
$kind = $_POST['kind'];
$room = $_POST['room'];
$day = $_POST['day'];
$time = $_POST['time'];
$prof = $_POST['prof'];
if ($conn->error) {
?>
<section class="card">
<div class="headline">Error</div>
<?php
die("Failed to connect to the database: " . $conn->error);
?>
</section>
<?php
}
$sql = "INSERT INTO Titama (name, kind, room, day, time, prof)
VALUES('$name', '$kind', '$room', '$day', '$time', '$prof')";
if ($conn->query($sql) === TRUE) {
?>
<section class="card">
<div class="headline">Success</div>
<?php
echo "The new course was created successfully.";
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
} else {
?>
<section class="card">
<div class="headline">Error</div>
<?php
echo "Error:" . $sql . "<br>" . $conn->error;
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
}
}
if (isset($_GET['change'])) {
$conn = new mysqli($dbhost, $dbuser, $dbpassword, $dbname);
$userid = $_POST['userid'];
$name = $_POST['name'];
$kind = $_POST['kind'];
$room = $_POST['room'];
$day = $_POST['day'];
$time = $_POST['time'];
$prof = $_POST['prof'];
if ($conn->error) {
?>
<section class="card">
<div class="headline">Error</div>
<?php
die("Failed to connect to the database: " . $conn->error);
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
}
$sql = "UPDATE Titama SET name='$name',kind='$kind',room='$room',day='$day',time='$time',prof='$prof' WHERE id=$userid";
if ($conn->query($sql)) {
?>
<section class="card">
<div class="headline">Success</div>
<?php
echo "Course successfully updated";
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
} else {
?>
<section class="card">
<div class="headline">Error</div>
<?php
echo "Some error occured. SQL: " . $sql . "<br> ERROR: " . $conn->error;
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
}
}
if (isset($_GET['del'])) {
$userid = $_POST['userid'];
$conn = new mysqli($conn, $dbuser, $dbpassword, $dbname);
if ($conn->error) {
?>
<section class="card">
<div class="headline">Error</div>
<?php
die("Failed to connect to the database: " . $conn->error);
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
}
$sql = "DELETE FROM Titama WHERE id=$userid";
$results = $conn->query($sql);
if ($conn->query($sql)) {
?>
<section class="card">
<div class="headline">Success</div>
<?php
echo "Course successfully deleted";
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
} else {
?>
<section class="card">
<div class="headline">Error</div>
<?php
echo "Some error occured. SQL: " . $sql . "<br> ERROR: " . $conn->error;
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
}
}
$conn = new mysqli($dbhost, $dbuser, $dbpassword, $dbname);
if ($conn->error) {
?>
<section class="card">
<div class="headline">Error</div>
<?php
die("Failed to connect to the database: " . $conn->error);
?>
<br>
<br>
<span id="remove" class="button">OK</span>
</section>
<?php
}
$days = array("Mon", "Thu", "Wed", "Thur", "Fri");
foreach ($days as $day) {
$sql = "SELECT * FROM Titama WHERE day='$day'";
$res = $conn->query($sql);
if ($res->num_rows > 0) {
?>
<section class="card">
<div class="headline"><?php echo getFullDay($day) ?></div>
<?php
$courses = $res->fetch_all();
usort($courses, function($a, $b) {
return $a[5] - $b[5];
});
foreach ($courses as $course) {
?>
<div class="course">
<div class="c_name" id="c_name_<?php echo $course[0] ?>"><?php echo $course[1]; ?></div>
<div class="c_time"><?php echo $course[5]; ?>:00</div>
<div class="c_id">Id: <?php echo $course[0]; ?></div>
<div class="c_kind">Kind: <?php echo $course[2]; ?></div>
<div class="c_place">Place: <?php echo $course[3]; ?></div>
<div class="c_prof">Prof: <?php echo $course[6]; ?></div>
</div>
<?php
}
}
?>
</section>
<?php
}
include './res/php/closedb.php';
?>
<section class="card">
<div class="headline">Add new course</div>
<form action="?add=1" method="post">
<p>Name:</p><input name="name" class="itextfield"/>
<p>Kind:</p><input name="kind" class="itextfield"/>
<p>Room:</p><input name="room" class="itextfield"/>
<p>Day:</p><input name="day" class="itextfield"/>
<p>Starts at:</p><input name="time" class="itextfield"/>
<p>Prof:</p><input name="prof" class="itextfield"/>
<br>
<br>
<input type="submit" class="button" value="ADD"/>
</form>
</section>
<section class="card">
<div class="headline">Change course</div>
<form action="?change=1" method="post">
<p>Course ID:</p><input name="userid" id="change_id" class="itextfield"/>
<div id="noid"></div>
<p>Name:</p><input name="name" id="change_name" class="itextfield"/>
<p>Kind:</p><input name="kind" id="change_kind" class="itextfield"/>
<p>Room:</p><input name="room" id="change_room" class="itextfield"/>
<p>Day:</p><input name="day" id="change_day" class="itextfield"/>
<p>Starts at:</p><input name="time" id="change_time" class="itextfield"/>
<p>Prof:</p><input name="prof" id="change_prof" class="itextfield"/>
<br>
<br>
<input type="submit" class="button" value="CHANGE" />
</form>
</section>
<section class="card">
<div class="headline">Delete course</div>
<form action="?del=1" method="post">
<p>Course ID:</p><input name="userid" class="itextfield"/>
<br>
<br>
<input type="submit" class="button" value="DELETE" />
</form>
</section>
</section>
<div class="footer">Marcel Kapfer (mmk2410) - 2015</div>
<script src="./res/jquery-2.1.4.min.js"></script>
<script src="./res/js/titama.js"></script>
</body>
</html>

102
init.sh Executable file
View file

@ -0,0 +1,102 @@
#!/bin/bash
# TiTaMa - A web time table manager
# Shell script for initialiying the whole thing
# 2015 (c) Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
# MIT License
echo
echo "Welcome to TiTaMa."
echo
echo "To initialize TiTaMa please enter the following values."
echo
echo -n "Database Host: "
read -r host
echo -n "Database User: "
read -r user
echo -n "Database Name: "
read -r db
echo -n "Database password: "
read -r password
echo
config=$(
cat << EOF
<?php
// TiTaMa - A web time table manager
// 2015 \(c\) Marcel Kapfer \(mmk2410\) <marcelmichaelkapfer@yahoo.co.nz>
// MIT License
\$dbhost = "$host";
\$dbuser = "$user";
\$dbname = "$db";
\$dbpassword = "$password";
EOF
)
data=$(
cat << EOF
Database Host: $host
Database User: $user
Database Name: $db
Database Password: $password
EOF
)
if [[ -s ./res/php/config.php ]]; then
echo -n "File already exists. Do you want to override it? (y/n) "
read -r option
if [[ "$option" == "y" ]]; then
echo
echo "$data"
echo
echo -n "Is the data right? (y/n) "
read -r correct
if [[ "$correct" == "y" ]]; then
echo "$config" > ./res/php/config.php
else
echo "Aborting"
echo
exit
fi
else
echo "Exiting without overriding the existing file."
echo
exit
fi
else
echo
echo "$data"
echo
echo -n "Is the data right? (y/n) "
read -r correct
if [[ "$correct" == "y" ]]; then
echo "$config" > ./res/php/config.php
else
echo "Aborting"
echo
exit
fi
fi
add_info=$(
cat << EOF
Additional Information:
To use TiTaMa you have to initialize the MySQL database of your system. Please follow the instruction of your operating systems.
After that you should create a user. You can do so in the MySQL CLI with this commands:
CREATE USER '$user'@'$host' IDENTIFIED BY '$password';
GRANT ALL PRIVILEGES ON *.* TO '$user'@'$host'
WITH GRANT OPTION;
Then create the database:
CREATE DATABASE $db
and last create the table:
CREATE TABLE $db.Titama( id INT(7) UNSIGNED AUTO_INCREMENT PRIMARY KEY, name TEXT, kind TEXT, room TEXT, day TEXT, time TEXT, prof TEXT);
EOF
)
echo
echo "$add_info"
echo
echo "Have fun using TiTaMa!"
echo

19
manifest.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "TiTaMa",
"short_name": "TiTaMa",
"icons" : [{
"src": "images/touch/icon-128x128.png",
"sizes": "128x128"
}, {
"src": "images/touch/apple-touch-icon.png",
"sizes": "152x152"
}, {
"src": "images/touch/ms-touch-icon-144x144-precomposed.png",
"sizes": "144x144"
}, {
"src": "images/touch/chrome-touch-icon-192x192.png",
"sizes": "192x192"
}],
"start_url": "./",
"display": "standalone"
}

14
package.json Normal file
View file

@ -0,0 +1,14 @@
{
"name": "titama",
"version": "1.0.0",
"description": "A web based time table manager",
"main": "index.php",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "mmk2410",
"license": "MIT",
"devDependencies": {
"gulp-coffee": "^2.3.1"
}
}

4
res/jquery-2.1.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

35
res/js/titama.coffee Normal file
View file

@ -0,0 +1,35 @@
# CoffeeScript for TiTaMa
$('#remove').click ->
window.location = "./"
change_course = (id) ->
httpRequest = new XMLHttpRequest()
httpRequest.onreadystatechange = ->
if httpRequest.readyState == 4 && httpRequest.status == 200
res = httpRequest.responseText
if not res
if $('#change_id').val()
$('#noid').html("<br>Id not available.")
else
$('#noid').html("")
$('#change_name').val("")
$('#change_kind').val("")
$('#change_room').val("")
$('#change_day').val("")
$('#change_time').val("")
$('#change_prof').val("")
else
res = JSON.parse(res)
$('#noid').html("")
$('#change_name').val(res.name)
$('#change_kind').val(res.kind)
$('#change_room').val(res.room)
$('#change_day').val(res.day)
$('#change_time').val(res.time)
$('#change_prof').val(res.prof)
httpRequest.open "GET", "./res/php/get_course.php?id=" + id, true
httpRequest.send()
$('#change_id').keyup ->
arg = $('#change_id').val()
change_course(arg)

49
res/js/titama.js Normal file
View file

@ -0,0 +1,49 @@
(function() {
var change_course;
$('#remove').click(function() {
return window.location = "./";
});
change_course = function(id) {
var httpRequest;
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
var res;
if (httpRequest.readyState === 4 && httpRequest.status === 200) {
res = httpRequest.responseText;
if (!res) {
if ($('#change_id').val()) {
$('#noid').html("<br>Id not available.");
} else {
$('#noid').html("");
}
$('#change_name').val("");
$('#change_kind').val("");
$('#change_room').val("");
$('#change_day').val("");
$('#change_time').val("");
return $('#change_prof').val("");
} else {
res = JSON.parse(res);
$('#noid').html("");
$('#change_name').val(res.name);
$('#change_kind').val(res.kind);
$('#change_room').val(res.room);
$('#change_day').val(res.day);
$('#change_time').val(res.time);
return $('#change_prof').val(res.prof);
}
}
};
httpRequest.open("GET", "./res/php/get_course.php?id=" + id, true);
return httpRequest.send();
};
$('#change_id').keyup(function() {
var arg;
arg = $('#change_id').val();
return change_course(arg);
});
}).call(this);

5
res/php/ajax_get_arg.php Normal file
View file

@ -0,0 +1,5 @@
<?php
echo "<b>Some arg:</b>";
echo "<br>";
echo $_GET['arg'];
?>

11
res/php/closedb.php Normal file
View file

@ -0,0 +1,11 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
if (isset($conn)) {
mysqli_close($conn);
}

19
res/php/get_course.php Normal file
View file

@ -0,0 +1,19 @@
<?php
if (!isset($_GET['id'])) {
echo "No id given!";
return;
}
$id = $_GET['id'];
include './config.php';
$conn = new mysqli($dbhost, $dbuser, $dbpassword, $dbname);
if ($conn->error) {
die("Failed to connect to the database: " . $conn->error);
}
$sql = "SELECT * FROM Titama WHERE id=$id";
$res = $conn->query($sql);
if ($res->num_rows > 0) {
$course = $res->fetch_assoc();
echo json_encode($course);
}
include './closedb.php';
?>

21
res/php/id_exists.php Normal file
View file

@ -0,0 +1,21 @@
<?php
if (!isset($_GET['id'])) {
echo "No id given!";
return;
}
$id = $_GET['id'];
include './config.php';
$conn = new mysqli($dbhost, $dbuser, $dbpassword, $dbname);
if ($conn->error) {
die("Failed to connect to the database: " . $conn->error);
}
$sql = "SELECT * FROM Titama WHERE id=$id";
$res = $conn->query($sql);
$course = $res->fetch_assoc();
if(isset($course)){
echo json_encode(true);
} else {
echo json_encode(false);
}
include './closedb.php';
?>

254
res/titama.css Normal file
View file

@ -0,0 +1,254 @@
/*
The MIT License
Copyright 2015 mmk2410.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/*
Created on : Jun 14, 2015, 6:13:38 PM
Author : mmk2410
*/
/* BODY */
body{
font-family: "Roboto", sans-serif;
background: #f6f6f6;
color: #383838;
margin-top: 94px;
}
.main{
height: 100%;
width: 100%;
margin-left: 0px;
}
/* HEADER */
.header{
background-color: #3F51B5;
position: fixed;
top: 0px;
right: 0px;
left: 0px;
width: 100%;
height: 64px;
box-shadow: 2px 0px 2px 2px rgba(62, 62, 62, 0.45);
}
.title{
color: #fff;
font-size: 23px;
text-decoration: none;
line-height: 64px;
vertical-align: middle;
left: 75px;
position: absolute;
}
/* MAIN */
.card{
margin-right: auto;
margin-left: auto;
width: 75%;
background: #fff;
border-radius: 2px;
padding: 24px;
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
margin-bottom: 40px;
max-width: 1160px;
}
.headline{
font-size: 24px;
color: #383838!important;
text-decoration: none;
display: block;
padding-bottom: 8px;
border-bottom: none!important;
}
.card > p{
font-size: 14px;
line-height: 24px;
}
.table-content{
max-height: 200px;
overflow: auto;
}
/* Course Block */
.c_name {
font-size: 32px;
font-weight: 300;
padding-top: 23px;
}
.c_time {
font-size: 24px;
font-weight: 400;
padding: 15px 0px;
}
.c_id {
font-size: 14px;
padding: 7px 0px;
}
.c_kind, .c_place, .c_prof {
padding: 5px 0px;
}
.c_place {
font-weight: 600;
}
/* FOOTER */
.footer{
font-size: 12px;
text-align: center;
}
.footer a{
color: #383838;
text-decoration: none;
border-bottom: 1px solid transparent;
border-bottom-color: transparent;
transition: border-bottom-color 150ms ease-in-out 100ms;
}
.footer a:hover{
border-bottom-color: #383838;
}
/* BUTTON */
.button {
text-decoration: none;
color: #fff;
background-color: #3F51B5;
line-height: 36px;
min-width: 64px;
text-align: center;
height: 36px;
padding: 8px;
border-width: 1px;
border-style: solid;
border-color: #3F51B5;
box-shadow: 0.4px 1px 1.5px 1px #aaa;
-moz-box-shadow: 0.4px 1px 1.5px 1px #aaa;
-webkit-box-shadow: 0.4px 1px 1.5px 1px #aaa;
border-radius: 2px;
margin-top: 4px;
margin-bottom: 5px;
letter-spacing: 0.4px;
font-weight: 700;
font-size: 14px;
transition-property: box-shadow;
transition-delay: 50ms;
transition-duration: 125ms;
transition-timing-function: ease;
-moz-transition-property: box-shadow;
-moz-transition-delay: 50ms;
-moz-transition-duration: 125ms;
-moz-transition-timing-function: ease;
-webkit-transition-property: box-shadow;
-webkit-transition-delay: 50ms;
-webkit-transition-duration: 125ms;
-webkit-transition-timing-function: ease;
cursor: pointer;
}
.button:hover, .button:hover {
box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa; }
input.button{
padding: 0px 8px;
}
/* INPUT FIELD */
.itextfield{
border-color: transparent;
border-width: 1px;
font-size: 16px;
line-height: 22px;
width: 50%;
border-bottom-color: #aaa;
transition-property: border-bottom-color;
transition-delay: 50ms;
transition-duration: 125ms;
transition-timing-function: ease;
-moz-transition-property: border-bottom-color;
-moz-transition-delay: 50ms;
-moz-transition-duration: 125ms;
-moz-transition-timing-function: ease;
-webkit-transition-property: border-bottom-color;
-webkit-transition-delay: 50ms;
-webkit-transition-duration: 125ms;
-webkit-transition-timing-function: ease;
}
.itextfield:focus{
border-bottom-color: #E91E63;
border-width: 2px;
outline: none;
}
#noid {
font-size: 12px;
color: #F44336;
}
/* FORM */
form{
margin-top: 20px;
}
@media screen and (min-width: 1440px) {
.card{
width: 1160px;
}
}
@media screen and (max-width: 720px){
.card{
width: 82%;
}
.title{
left: 25px;
}
.itextfield{
width: 100%;
}
}