Merge branch '17-Export-Import-Option' into 'develop'

Resolve "Export/Import-Option"

See merge request bluekay/shopping-list!5
This commit is contained in:
Tim Krehan 2018-12-17 10:26:40 +00:00
commit dfde633df5
29 changed files with 519 additions and 82 deletions

25
bin/adduser.js Normal file
View file

@ -0,0 +1,25 @@
$(document).ready(function(){
$("#button_newuser").click(function(){
$.post("/php/edit-user.php",
{
function: "new-user",
username: $("#text_user").val(),
passwd: $("#text_passwd").val()
},
function(data){
if(data==0){
infoPopUp("Benutzer erfolgreich erstellt!", 100);
$("#text_user").val("");
$("#text_passwd").val("");
$("#adduser-button-done").removeClass("button-disabled");
}
else {
infoPopUp("Fehler bei der Benutzeranlage!", 100);
}
}
);
});
$("#adduser-button-done").click(function(){
window.location.href = "/";
});
});

5
bin/index.js Normal file
View file

@ -0,0 +1,5 @@
function infoPopUp(infotext, timeout){
$("#info-popup-text").text(infotext);
$("#info-popup-text").css("animation", "none");
setTimeout(function(){$("#info-popup-text").css("animation", "fade 4s linear");}, timeout);
}

View file

@ -9,14 +9,8 @@ $(document).ready(function(){
id: dataId,
status: $(this).prop("checked")
},
success: function(){
$("#saved font").css("animation", "none");
setTimeout(function(){$("#saved font").css("animation", "fade 4s linear");}, 100);
},
error: function(){
$("#error font").css("animation", "none");
setTimeout(function(){$("#error font").css("animation", "fade 6s linear");}, 100);
}
success: function(){infoPopUp("SAVED!", 100);},
error: function(){infoPopUp("Netzwerkfehler! Bitte aktualisieren.", 100);}
});
if($(this).prop("checked")){$("[data-id='"+dataId+"']").addClass("checked");}
else{$("[data-id='"+dataId+"']").removeClass("checked");}

View file

@ -15,4 +15,7 @@ $(document).ready(function(){
$("#logout").click(function(){
window.location.href = "/php/logout.php";
});
$("#settings").click(function(){
window.location.href = "/settings";
});
});

107
bin/settings.js Normal file
View file

@ -0,0 +1,107 @@
function downloadObjectAsJson(exportObj, exportName){
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", exportName + ".json");
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
$(document).ready(function(){
$("#username-input").focus(function(){$(this).css("color", "black");});
$("#mail-input").focus(function(){$(this).css("color", "black");});
// change password
$("#old-password-input").focus(function(){$(this).css("color", "black");});
$("#new-password-input").focus(function(){$(this).css("color", "black");});
$("#check-password-input").focus(function(){$(this).css("color", "black");});
$(".password-input").on("input", function(){
if(
(($("#old-password-input").val()).length>0) &&
(($("#new-password-input").val()).length>0) &&
(($("#check-password-input").val()).length>0) &&
($("#new-password-input").val()==$("#check-password-input").val())
){
$("#passwordSaveButton").prop("disabled", false);
$("#passwordSaveButton").removeClass("button-disabled");
}
else{
$("#passwordSaveButton").prop("disabled", true);
$("#passwordSaveButton").addClass("button-disabled");
}
});
$("#passwordSaveButton").click(function(){
$.post("/php/edit-user.php",
{
function: "change-pw",
current: $("#old-password-input").val(),
new: $("#new-password-input").val()
},
function(data){
if(data==0){
$("#old-password-input").val("");
$("#new-password-input").val("");
$("#check-password-input").val("");
infoPopUp("Passwort erfolgreich geändert!", 100);
}
else {
infoPopUp("Altes Passwort Falsch!", 100);
}
}
);
});
$("#export-recipe-button").click(function(){
$.post("/php/edit-recipes.php", {function:"export"}, function(data){
downloadObjectAsJson(JSON.parse(data), "recipes");
});
});
$("#export-list-button").click(function(){
$.post("/php/edit-list.php", {function:"export"}, function(data){
downloadObjectAsJson(JSON.parse(data), "list");
});
});
$("#import-button").click(function(){
$('<input type="file" accept=".json">').on('change', function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(){
var content = JSON.parse(reader.result);
if(content.sites!=null){
$.post("/php/edit-recipes.php",
{
function: "import",
content: reader.result
},
function(data){
if(data==0){
infoPopUp("Alle Rezepte erfolgreich Importiert!", 200);
}
else{
infoPopUp("Nicht alle Rezepte konnten Importiert werden!", 1000);
downloadObjectAsJson(JSON.parse(data), "failed_recipe_import");
}
}
);
}
else if(content.list!=null){
$.post("/php/edit-list.php",
{
function: "import",
content: reader.result
},
function(data){
console.log(data);
if(data==0){
infoPopUp("Alle Listeneinträge erfolgreich Importiert!", 200);
}
}
);
}
};
reader.readAsText(file);
}).click();
});
});

View file

@ -1 +1,4 @@
Require all denied
# prevent access to these files while not logged in
<files "*.php">
Require all denied
</files>

View file

@ -1,4 +1,4 @@
# prevent access to these files while not logged in
<files "adduser.php">
Require all denied
<files "*.php">
Require all denied
</files>

View file

@ -1,12 +1,11 @@
<?php ?>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/master.css">
<link rel="stylesheet" href="/style/adduser.css">
<script src="/bin/adduser.js" charset="utf-8"></script>
</head>
<h1>Benutzer hinzufügen</h1>
<form class="adduser" action="/php/adduser_action.php" method="post">
<label for="text_user">Benutzername</label><input id="text_user" type="text" name="username" value="" placeholder="user1" required>
<label for="text_passwd">Passwort</label><input id="text_passwd" type="Password" name="passwd" value="" placeholder="********" required>
<div class="adduser">
<label for="text_user">Benutzername</label><input id="text_user" type="text" name="username" placeholder="user" required>
<label for="text_passwd">Passwort</label><input id="text_passwd" type="password" name="passwd" placeholder="********" required>
<input id="button_newuser" class="button" type="submit" name="" value="Neuer Benutzer">
</form>
</div>
<button class="button button-disabled" id="adduser-button-done">Fertig</button>

View file

@ -35,5 +35,3 @@
?>
</div>
</form>
<div id="saved"><font>SAVED!</font></div>
<div id="error"><font>Netzwerkfehler!<br /> Bitte aktualisieren.</font></div>

View file

@ -2,6 +2,7 @@
<script src="/bin/nav.js" charset="utf-8"></script>
<div id="navigation" data-open="false">
<img src="/pic/logout.png" id="logout" alt="">
<img src="/pic/settings.svg" id="settings" alt="">
<nav>
<font class="hover even" data-url="list">Einkaufsliste</font>
<font class="hover odd" data-url="recipes">Rezepte</font>

View file

@ -3,7 +3,7 @@
<script src="/bin/recipe.js" charset="utf-8"></script>
<?php
include $_SESSION["docroot"].'/php/classes.recipe.php';
include $_SESSION["docroot"].'/php/classes.parsedown.php';
include $_SESSION["docroot"].'/php/classes.parsedown.php';
$book = new cookbook;
$book->getRecipe($_GET["number"]);
$recipe = $book->sites[0];

35
cont/settings.php Normal file
View file

@ -0,0 +1,35 @@
<script src="/bin/settings.js" charset="utf-8"></script>
<link rel="stylesheet" href="/style/settings.css">
<h1>Settings</h1>
<?php
include $_SESSION["docroot"].'/php/classes.user.php';
$user = new user;
$user->get_info($_COOKIE["token"]);
?>
<div class="settings">
<h2>User</h2>
<div class="userprofile-pane pane">
<div class="userprofile">
<span><font class="attribute">Benutzername</font><input class="change-attribute-input" id="username-input" type="text" name="username" placeholder="<?php echo $user->username; ?>"></span>
<span><font class="attribute">Email</font><input class="change-attribute-input" id="mail-input" type="email" name="username" placeholder="<?php echo $user->email; ?>"></span>
<span><font class="attribute">Letzter Login</font><font><?php echo $user->last_login; ?></font></span>
</div>
<button class="button" id="userSaveButton">Speichern</button>
</div>
<div class="userpassword-pane pane">
<div class="userpassword">
<span><font class="attribute">Altes Passwort</font><input class="change-attribute-input password-input" id="old-password-input" type="password" name="username" placeholder="********"></span>
<span><font class="attribute">Neues Passwort</font><input class="change-attribute-input password-input" id="new-password-input" type="password" name="username" placeholder="********"></span>
<span><font class="attribute">Passwort bestätigen</font><input class="change-attribute-input password-input" id="check-password-input" type="password" name="username" placeholder="********"></span>
</div>
<button class="button button-disabled" id="passwordSaveButton" disabled>Speichern</button>
</div>
<div class="import-export-pane">
<h2>Import / Export</h2>
<p>Hiermit werden alle Rezepte und sich zurzeit auf der Shoppingliste befindlichen Einträge als Download zur Verfügung gestellt. Diese Datei kann dann an anderer Stelle wieder Importiert werden, oder als Backup abgespeichert werden.</p>
<button type="button" id="export-recipe-button" class="button">Export Rezepte</button>
<button type="button" id="export-list-button" class="button">Export Shoppingliste</button>
<p>Der Import kann benutzt werden, um alle Daten von einer exportierten Datei in diese Datenbank einzupflegen. Hierbei werden nur die Einträge in der Shoppingliste, sowie die Rezepte beachtet. Die Benutzer bleiben unberührt!</p>
<button type="button" id="import-button" class="button">Import ...</button>
</div>
</div>

View file

@ -23,6 +23,7 @@
<link rel="shortcut icon" type="image/png" href="/pic/fav.ico"/>
<link rel="stylesheet" href="/style/master.css">
<script src="/bin/jquery.js"></script>
<script src="/bin/index.js" charset="utf-8"></script>
<title>Einkaufsliste</title>
</head>
<body>
@ -44,6 +45,10 @@
include $_SESSION["docroot"].'/cont/list.php';
break;
case "settings":
include $_SESSION["docroot"].'/cont/settings.php';
break;
case "recipes":
include $_SESSION["docroot"].'/cont/recipes.php';
break;
@ -76,5 +81,6 @@
echo "</div>";
if($site && ($site!="login")){include $_SESSION["docroot"].'/cont/nav.php';}
?>
<div id="info-popup"><font id="info-popup-text"></font></div>
</body>
</html>

View file

@ -1,12 +1,18 @@
<?php ?>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/master.css">
<link rel="stylesheet" href="/style/adduser.css">
<script src="/bin/jquery.js" charset="utf-8"></script>
<script src="/bin/index.js" charset="utf-8"></script>
<script src="/bin/adduser.js" charset="utf-8"></script>
</head>
<h1>Benutzer hinzufügen</h1>
<form class="adduser" action="/php/adduser_action.php" method="post">
<label for="text_user">Benutzername</label><input id="text_user" type="text" name="username" value="" placeholder="user1" required>
<label for="text_passwd">Passwort</label><input id="text_passwd" type="Password" name="passwd" value="" placeholder="********" required>
<div class="adduser">
<label for="text_user">Benutzername</label><input id="text_user" type="text" name="username" placeholder="user" required>
<label for="text_passwd">Passwort</label><input id="text_passwd" type="password" name="passwd" placeholder="********" required>
<input id="button_newuser" class="button" type="submit" name="" value="Neuer Benutzer">
</form>
</div>
<button class="button button-disabled" id="adduser-button-done">Fertig</button>
<!-- Only here in install/adduser -->
<div id="info-popup"><font id="info-popup-text"></font></div>

View file

@ -1,9 +1,9 @@
<?php
session_start();
if (!($_SESSION["docroot"]))
{
$_SESSION["docroot"] = str_replace("/install", "", __DIR__);
}
session_start();
if (!($_SESSION["docroot"]))
{
$_SESSION["docroot"] = str_replace("/install", "", __DIR__);
}
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
header("Pragma: no-cache"); // HTTP 1.0.
@ -12,14 +12,19 @@ if (!($_SESSION["docroot"]))
$mods_enabled = array("mod_rewrite");
$missing_mods = array();
foreach($mods_enabled as $mod){
if(!(in_array($mod, apache_get_modules()))){
array_push($missing_mods, $mod);
if(function_exists("apache_get_modules")){
$apache_mods = apache_get_modules();
foreach($mods_enabled as $mod){
if(!(in_array($mod, $apache_mods))){
array_push($missing_mods, $mod);
}
}
}
if(!(class_exists('mysqli'))){ #php-mysql not installed
array_push($missing_mods, "mysql");
}
if(sizeof($missing_mods)>0){
header("Location: /cont/error.php?id=php_modules&missing_mods=".serialize($missing_mods));
}
@ -28,7 +33,7 @@ if (!($_SESSION["docroot"]))
header("Location: /");
exit;
}
?>
?>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/master.css">

16
php/.htaccess Normal file
View file

@ -0,0 +1,16 @@
# prevent access to these files while not logged in
<files "classes.*.php">
Require all denied
</files>
<files "auth.php">
Require all denied
</files>
<files "connect.php">
Require all denied
</files>
<files "hash.php">
Require all denied
</files>

View file

@ -1,15 +0,0 @@
<?php
session_start();
include $_SESSION["docroot"].'/php/connect.php';
include $_SESSION["docroot"].'/php/hash.php';
$salt = create_salt();
$password = hash_password($_POST["passwd"], $salt);
$result = $mysqli->query("INSERT INTO `users` (`username`, `password`, `salt`, `last_login`) VALUES ('".$_POST["username"]."', '".$password."', '".$salt."', CURRENT_TIMESTAMP);");
$mysqli->close();
unset($salt);
unset($password);
header("Location: /");
?>

View file

@ -60,6 +60,15 @@
$mysqli->query("UPDATE `Einkauf` SET `Erledigt` = $status WHERE `Einkauf`.`ID` = $id");
$mysqli->close();
}
function import(){
$import = json_decode($_POST["content"]);
$units = new units();
foreach($import->list as $item){
$this->newItem($item->Anzahl, $units->getID($item->Einheit), $item->Name);
}
print_f("0");
}
}
class unit {
@ -86,5 +95,13 @@
}
$mysqli->close();
}
function getID($Name){
foreach($this->list as $units){
if($units->Name==$Name){
return $units->ID;
}
}
}
}
?>

View file

@ -20,6 +20,12 @@
}
$mysqli->close();
}
function getID($Name){
include $_SESSION["docroot"].'/php/connect.php';
$result = $mysqli->query("SELECT `ID` FROM `Einheit` WHERE `Name` = '$Name'");
$ID = $result->fetch_assoc();
return $ID["ID"];
}
}
class ingredient {
@ -89,15 +95,51 @@
$mysqli->close();
}
function importCookbook(){
include $_SESSION["docroot"].'/php/connect.php';
$units = new unitList();
$failed_sites = array();
$succeeded_sites = array();
$import = json_decode($_POST["content"]);
if($import->sites!=null){
foreach ($import->sites as $site) {
$result = $mysqli->query("SELECT * FROM `Rezept` WHERE `Name`='$site->Name'");
if($result->num_rows>0){
array_push($failed_sites, $site);
}
else{
array_push($succeeded_sites, $site);
$Zutaten = array();
foreach($site->Zutaten as $Zutat) {
$nZutat = null;
$nZutat["ID"] = $Zutat->ID;
$nZutat["Amount"] = $Zutat->Menge;
$nZutat["Unit"] = $units->getID($Zutat->Einheit);
$nZutat["Name"] = $Zutat->Name;
array_push($Zutaten, $nZutat);
}
$this->newRecipe($site->Name, $site->Dauer, $site->Beschreibung, $Zutaten);
}
}
if(sizeof($failed_sites)==0){
print_r("0");
}
else{
print_r(json_encode($failed_sites));
}
}
}
function newRecipe($Name, $Dauer, $Beschreibung, $Zutaten){
include $_SESSION["docroot"].'/php/connect.php';
$mysqli->query("INSERT INTO Rezept (Name, Dauer, Beschreibung) VALUES ('$Name', '$Dauer', '$Beschreibung')");
$mysqli->query("INSERT INTO `Rezept` (`Name`, `Dauer`, `Beschreibung`) VALUES ('$Name', '$Dauer', '$Beschreibung')");
$RezeptID = $mysqli->insert_id;
foreach ($Zutaten as $Zutat) {
$ZutatID = null;
$result = $mysqli->query("SELECT ID FROM `Zutat` WHERE `Name` LIKE '".$Zutat["Name"]."'");
if($result->num_rows>0){
while($item = $result->fetch_assoc()){$ZutatID = $item["ID"];}
$item = $result->fetch_assoc();
$ZutatID = $item["ID"];
}
else{
$mysqli->query("INSERT INTO `Zutat` (`Name`) VALUES ('".ucwords($Zutat["Name"])."')");

56
php/classes.user.php Normal file
View file

@ -0,0 +1,56 @@
<?php
Class user {
public $uid, $username, $email, $last_login;
private $salt;
function get_info($session_id) {
include $_SESSION["docroot"].'/php/connect.php';
$query = "SELECT uid, username, email, last_login, salt FROM `users` WHERE `uid` = (SELECT user FROM `sessions` WHERE `session_id` = \"$session_id\")";
$result = $mysqli->query($query);
$user = $result->fetch_assoc();
$this->uid = $user["uid"];
$this->username = $user["username"];
$this->email = $user["email"];
$this->last_login = $user["last_login"];
$this->salt = $user["salt"];
$mysqli->close();
}
function change_password($current, $new){
include $_SESSION["docroot"].'/php/hash.php';
include $_SESSION["docroot"].'/php/connect.php';
$current_pwhash = hash_password($current, $this->salt);
$query = "SELECT `uid` FROM `users` WHERE `uid` = $this->uid AND `password` = '$current_pwhash'";
$result = $mysqli->query($query);
if($result->num_rows===1){
$new_pwdhash = hash_password($new, $this->salt);
$mysqli->query("UPDATE `users` SET `password` = '$new_pwdhash' WHERE `users`.`uid` = $this->uid;");
$mysqli->close();
print_r("0");
}
else{
print_r("1");
}
}
function new($uname, $password){
session_start();
include $_SESSION["docroot"].'/php/connect.php';
include $_SESSION["docroot"].'/php/hash.php';
$query = "SELECT `uid` FROM `users` WHERE `username` = '$uname'";
$result = $mysqli->query($query);
if($result->num_rows==0){
$salt = create_salt();
$passhash = hash_password($password, $salt);
$query = "INSERT INTO `users` (`username`, `password`, `salt`, `last_login`) VALUES ('$uname', '$passhash', '$salt', CURRENT_TIMESTAMP);";
$result = $mysqli->query($query);
unset($salt);
unset($password);
print_r(0);
}
else{print_r(1);}
$mysqli->close();
}
}
?>

View file

@ -19,6 +19,15 @@
case 'check':
$shopping->check($_POST["id"], $_POST["status"]);
break;
case 'export':
echo json_encode($shopping);
break;
case 'import':
$shopping->import();
break;
default:
// code...

View file

@ -27,6 +27,15 @@
header(("Location: /recipe/".$_POST["id"]));
break;
case 'export':
$book->fillCookbook();
echo json_encode($book);
break;
case 'import':
$book->importCookbook();
break;
default:
// code...
break;

22
php/edit-user.php Normal file
View file

@ -0,0 +1,22 @@
<?php
session_start();
include $_SESSION["docroot"].'/php/classes.user.php';
$user = new user;
if($_POST["function"]!="new-user"){
$user->get_info($_COOKIE["token"]);
}
switch ($_POST["function"]) {
case 'change-pw':
$user->change_password($_POST["current"], $_POST["new"]);
break;
case 'new-user':
$user->new($_POST["username"], $_POST["passwd"]);
break;
default:
// code...
break;
}
?>

1
pic/settings.svg Normal file
View file

@ -0,0 +1 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="cogs" class="svg-inline--fa fa-cogs fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M512.1 191l-8.2 14.3c-3 5.3-9.4 7.5-15.1 5.4-11.8-4.4-22.6-10.7-32.1-18.6-4.6-3.8-5.8-10.5-2.8-15.7l8.2-14.3c-6.9-8-12.3-17.3-15.9-27.4h-16.5c-6 0-11.2-4.3-12.2-10.3-2-12-2.1-24.6 0-37.1 1-6 6.2-10.4 12.2-10.4h16.5c3.6-10.1 9-19.4 15.9-27.4l-8.2-14.3c-3-5.2-1.9-11.9 2.8-15.7 9.5-7.9 20.4-14.2 32.1-18.6 5.7-2.1 12.1.1 15.1 5.4l8.2 14.3c10.5-1.9 21.2-1.9 31.7 0L552 6.3c3-5.3 9.4-7.5 15.1-5.4 11.8 4.4 22.6 10.7 32.1 18.6 4.6 3.8 5.8 10.5 2.8 15.7l-8.2 14.3c6.9 8 12.3 17.3 15.9 27.4h16.5c6 0 11.2 4.3 12.2 10.3 2 12 2.1 24.6 0 37.1-1 6-6.2 10.4-12.2 10.4h-16.5c-3.6 10.1-9 19.4-15.9 27.4l8.2 14.3c3 5.2 1.9 11.9-2.8 15.7-9.5 7.9-20.4 14.2-32.1 18.6-5.7 2.1-12.1-.1-15.1-5.4l-8.2-14.3c-10.4 1.9-21.2 1.9-31.7 0zm-10.5-58.8c38.5 29.6 82.4-14.3 52.8-52.8-38.5-29.7-82.4 14.3-52.8 52.8zM386.3 286.1l33.7 16.8c10.1 5.8 14.5 18.1 10.5 29.1-8.9 24.2-26.4 46.4-42.6 65.8-7.4 8.9-20.2 11.1-30.3 5.3l-29.1-16.8c-16 13.7-34.6 24.6-54.9 31.7v33.6c0 11.6-8.3 21.6-19.7 23.6-24.6 4.2-50.4 4.4-75.9 0-11.5-2-20-11.9-20-23.6V418c-20.3-7.2-38.9-18-54.9-31.7L74 403c-10 5.8-22.9 3.6-30.3-5.3-16.2-19.4-33.3-41.6-42.2-65.7-4-10.9.4-23.2 10.5-29.1l33.3-16.8c-3.9-20.9-3.9-42.4 0-63.4L12 205.8c-10.1-5.8-14.6-18.1-10.5-29 8.9-24.2 26-46.4 42.2-65.8 7.4-8.9 20.2-11.1 30.3-5.3l29.1 16.8c16-13.7 34.6-24.6 54.9-31.7V57.1c0-11.5 8.2-21.5 19.6-23.5 24.6-4.2 50.5-4.4 76-.1 11.5 2 20 11.9 20 23.6v33.6c20.3 7.2 38.9 18 54.9 31.7l29.1-16.8c10-5.8 22.9-3.6 30.3 5.3 16.2 19.4 33.2 41.6 42.1 65.8 4 10.9.1 23.2-10 29.1l-33.7 16.8c3.9 21 3.9 42.5 0 63.5zm-117.6 21.1c59.2-77-28.7-164.9-105.7-105.7-59.2 77 28.7 164.9 105.7 105.7zm243.4 182.7l-8.2 14.3c-3 5.3-9.4 7.5-15.1 5.4-11.8-4.4-22.6-10.7-32.1-18.6-4.6-3.8-5.8-10.5-2.8-15.7l8.2-14.3c-6.9-8-12.3-17.3-15.9-27.4h-16.5c-6 0-11.2-4.3-12.2-10.3-2-12-2.1-24.6 0-37.1 1-6 6.2-10.4 12.2-10.4h16.5c3.6-10.1 9-19.4 15.9-27.4l-8.2-14.3c-3-5.2-1.9-11.9 2.8-15.7 9.5-7.9 20.4-14.2 32.1-18.6 5.7-2.1 12.1.1 15.1 5.4l8.2 14.3c10.5-1.9 21.2-1.9 31.7 0l8.2-14.3c3-5.3 9.4-7.5 15.1-5.4 11.8 4.4 22.6 10.7 32.1 18.6 4.6 3.8 5.8 10.5 2.8 15.7l-8.2 14.3c6.9 8 12.3 17.3 15.9 27.4h16.5c6 0 11.2 4.3 12.2 10.3 2 12 2.1 24.6 0 37.1-1 6-6.2 10.4-12.2 10.4h-16.5c-3.6 10.1-9 19.4-15.9 27.4l8.2 14.3c3 5.2 1.9 11.9-2.8 15.7-9.5 7.9-20.4 14.2-32.1 18.6-5.7 2.1-12.1-.1-15.1-5.4l-8.2-14.3c-10.4 1.9-21.2 1.9-31.7 0zM501.6 431c38.5 29.6 82.4-14.3 52.8-52.8-38.5-29.6-82.4 14.3-52.8 52.8z"></path></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -13,3 +13,8 @@ label {
flex-direction: column;
width: 50%;
}
#adduser-button-done {
position: absolute;
bottom: 2em;
right: 2em;
}

View file

@ -92,33 +92,3 @@ border-left: none;
.list_row.odd.checked {
border-left: 3px solid #888;
}
#saved, #error {
pointer-events: none;
position: fixed;
display: flex;
justify-content: center;
bottom: 2%;
margin: 0;
left: 0;
width: 100%;
}
#saved font, #error font {
color: #ffffff;
background-color: #000000;
padding: .1em .5em .2em;
border-radius: 50px;
opacity: 0;
}
#error font {
padding: .1em 1em .2em;
}
@keyframes fade {
0% {
opacity: 0;
}
10% {
opacity: 1;
}
}

View file

@ -26,6 +26,15 @@ h2 {
width: 80%;
}
h3 {
font-size: 1.5em;
text-align: left;
margin-top: .5em;
padding-bottom: .5em;
border-bottom: 1px solid grey;
width: 75%;
}
.even {
background-color: #565656;
}
@ -53,9 +62,50 @@ h2 {
font-weight: 800;
background-color: #4CAF50;
color: white;
cursor: pointer;
}
.button:hover {
background-color: #4CAFFF;
}
.button-disabled {
background-color: grey;
cursor: not-allowed;
}
.button-disabled:hover {
background-color: grey;
}
.hover:hover {
background-color: #4CAF50;
cursor: pointer;
}
#info-popup {
pointer-events: none;
position: fixed;
display: flex;
justify-content: center;
bottom: 2%;
margin: 0;
left: 0;
width: 100%;
}
#info-popup-text {
color: #ffffff;
background-color: #000000;
padding: .1em .5em .2em;
border-radius: 50px;
opacity: 0;
}
@keyframes fade {
0% {
opacity: 0;
}
10% {
opacity: 1;
}
}

View file

@ -31,6 +31,13 @@
height: 45px;
cursor: pointer;
}
#settings {
position: absolute;
top: calc(.5em + 5px);
right: calc(2em + 45px);
height: 35px;
cursor: pointer;
}
#burgerMenue {
width: 60px;
height: 45px;

61
style/settings.css Normal file
View file

@ -0,0 +1,61 @@
.settings {
display: flex;
justify-content: flex-start;
flex-direction: row;
flex-wrap: wrap;
}
.pane {
border: 1px solid grey;
border-radius: 5px;
background-color: #ddd;
margin: 1%;
width: auto;
min-width: max-content;
max-width: 45%;
height: max-content;
}
.userprofile-pane {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.userprofile {
width: 22em;
display: flex;
flex-direction: column;
}
.userpassword-pane {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.userpassword {
width: 22em;
display: flex;
flex-direction: column;
}
.userprofile span {
display: flex;
flex-direction: row;
align-items: center;
}
.userpassword span {
display: flex;
flex-direction: row;
align-items: center;
}
.attribute {
width: 6em;
padding: 1em;
}
.change-attribute-input {
text-indent: 1em;
color: grey;
}
.value {
padding: 1em;
}
#passwordSaveButton, #userSaveButton {
align-self: flex-end;
margin: 1em;
}