Forráskód Böngészése

Added Label management, Mailaccount management

Moritz Schmidt 10 éve
szülő
commit
fc57dbe012

+ 71 - 0
ajax.php

@@ -0,0 +1,71 @@
+<?php
+// AJAX handling
+
+// Includes
+include('includes/config.inc.php');
+include('includes/database.inc.php');
+include('includes/functions.inc.php');
+include('includes/document.inc.php');
+include('includes/label.inc.php');
+include('includes/imap.inc.php');
+include('includes/mailboxfolder.inc.php');
+
+$db = new Database($CONFIG['dbHost'], $CONFIG['dbUser'], $CONFIG['dbPassword'], $CONFIG['dbDatabase']);
+
+switch($_POST['action']) {
+    case 'updateMailaccounts':
+        switch($_POST['name']) {
+            case 'hostname':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `server`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            case 'port':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `port`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            case 'protocol':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `protocol`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            case 'use-ssl':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `use_ssl`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            case 'no-valid-cert':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `valid_ssl`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            case 'username':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `username`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            case 'password':
+                header("Status: 200 OK");
+                $db->updateQuery("UPDATE `mailboxes` SET `password`='" . $_POST['value'] . "' WHERE id=" . $_POST['pk'] . ";");
+                break;
+            default:
+                header("Status: 400 Wrong Field");
+                echo 'error';
+                break;
+
+        }
+        //$db->updateQuery("UPDATE `mailboxes` SET x=y WHERE id=;")
+        echo 'updateMailaccounts';
+        break;
+    case 'addDefaultMailaccount':
+        header("Status: 200 OK");
+        $db->insertQuery("INSERT INTO `mailboxes` (`user_id`) VALUES (" . $_POST['user-id'] . ");");
+        break;
+    case 'removeMailaccount':
+        header("Status: 200 OK");
+        $db->removeQuery("DELETE FROM `mailboxes` WHERE `id` = " . $_POST['id'] . ";");
+        break;
+    default:
+        header("Status: 400 No Action Defined");
+        echo 'error';
+        break;
+}
+
+pa($_POST); // Debug
+
+?>

BIN
fonts/FontAwesome.otf


BIN
fonts/fontawesome-webfont.eot


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 196 - 0
fonts/fontawesome-webfont.svg


BIN
fonts/fontawesome-webfont.ttf


BIN
fonts/fontawesome-webfont.woff


BIN
fonts/fontawesome-webfont.woff2


BIN
images/clear.png


BIN
images/loading.gif


BIN
images/logo.png


+ 1 - 0
img

@@ -0,0 +1 @@
+images/

+ 13 - 11
includes/controller.inc.php

@@ -22,7 +22,6 @@ class Controller {
 		$this->template = !empty($request['action']) ? $request['action'] : 'default';
 
 		if(isset($request['action']) && $request['action'] === "login" && isset($request['username'])) {
-			echo "jo";
 			$user->login($request['username'], $request['password']);
 		}
 
@@ -56,16 +55,6 @@ class Controller {
 					$innerView->assign('title', $entry['title']);
 					$innerView->assign('content', $entry['content']);
 					break;
-				case 'profile':
-					$innerView->setTemplate('profile');
-					$openvpn = new OpenVPNStatus("/home/moritz/www/openvpn-status.log");
-					$clientName = $user->getClients();
-					$hostname = searchForHostname($clientName, $openvpn->logfile);
-					$innerView->assign('openvpn', $openvpn->logfile[$hostname]);
-					break;
-				case 'download':
-					$innerView->setTemplate('download');
-					break;
 				case 'label':
 					$innerView->setTemplate('label');
 					$innerView->assign('label', getLabelById($this->request['labelId']));
@@ -74,6 +63,19 @@ class Controller {
 					$documentView->assign('labelId', $this->request['labelId']);
 					$innerView->assign('documentlist', $documentView->loadTemplate());
 					break;
+				case 'manage-labels':
+					$innerView->setTemplate('manage-labels');
+					$innerView->assign('labels', getLabels());
+					break;
+				case 'manage-label':
+					$innerView->setTemplate('manage-label');
+					$innerView->assign('label', getLabelById($this->request['labelId']));
+					$innerView->assign('mailboxFolders', getMailboxFolderByLabelId($this->request['labelId']));
+					break;
+				case 'settings':
+					$innerView->setTemplate('settings');
+					$innerView->assign('user', $user);
+					break;
 				case 'default':
 				default:
 					$entries = Model::getEntries();

+ 20 - 0
includes/database.inc.php

@@ -43,6 +43,26 @@ class Database {
 		$stmt->execute();
 		$stmt->close();
 	}
+
+	public function updateQuery($query) {
+		$stmt = $this->handle->prepare($query);
+		if(!$stmt) {
+			pa($this->handle);
+		} else {
+			$stmt->execute();
+			$stmt->close();
+		}
+	}
+
+	public function removeQuery($query) {
+		$stmt = $this->handle->prepare($query);
+		if(!$stmt) {
+			pa($this->handle);
+		} else {
+			$stmt->execute();
+			$stmt->close();
+		}
+	}
 }
 
 ?>

+ 47 - 3
includes/functions.inc.php

@@ -107,7 +107,7 @@ function getMailboxes() {
 		if(!$mailbox->valid_ssl) {
 			$noValidCert = '/novalidate-cert';
 		}
-		$return[] = new Imap('{' . $mailbox->server . ':' . $mailbox->port . '/' . $mailbox->protocol . $useSsl . $noValidCert . '}', $mailbox->username, $mailbox->password); // TODO: Encrypt password
+		$return[] = new Imap($mailbox->id, $mailbox->server, $mailbox->port, $mailbox->protocol, $useSsl, $noValidCert, $mailbox->username, $mailbox->password); // TODO: Encrypt password
 	}
 
 	return $return;
@@ -130,7 +130,8 @@ function getMailboxesByUserId($userId) {
 		if(!$mailbox->valid_ssl) {
 			$noValidCert = '/novalidate-cert';
 		}
-		$return[] = new Imap('{' . $mailbox->server . ':' . $mailbox->port . '/' . $mailbox->protocol . $useSsl . $noValidCert . '}', $mailbox->username, $mailbox->password); // TODO: Encrypt password
+		//$return[] = new Imap('{' . $mailbox->server . ':' . $mailbox->port . '/' . $mailbox->protocol . $useSsl . $noValidCert . '}', $mailbox->username, $mailbox->password); // TODO: Encrypt password
+		$return[] = new Imap($mailbox->id, $mailbox->server, $mailbox->port, $mailbox->protocol, $useSsl, $noValidCert, $mailbox->username, $mailbox->password); // TODO: Encrypt password
 	}
 
 	return $return;
@@ -154,6 +155,24 @@ function getMailboxFolderByName($folderName) {
 
 }
 
+function getMailboxFolderByLabelId($labelId) {
+	global $db;
+
+	$return = array();
+	$folders = $db->selectQuery("SELECT * FROM `mailbox-folders` WHERE `label_id` = '" . $labelId . "';");
+
+	if(!$folders) {
+		return false;
+	}
+
+	foreach($folders as $folder) {
+		$return[] = new MailboxFolder($folder->folder_name, $folder->mailbox_id, $folder->label_id);
+	}
+
+	return $return;
+
+}
+
 function addDocument($type, $fileName, $path, $labelId, $draft, $created, $lastChange, $mailUid) {
 	global $db;
 	$query = "INSERT INTO `documents`(`type`, `filename`, `path`, `label_id`, `draft`, `created`, `last_change`, `mail_uid`) VALUES ('" . $type . "', '" . $fileName . "', '" . $path . "', " . $labelId . ", '" . $draft . "', " . $created . ", " . $lastChange . ", " . $mailUid . ");";
@@ -211,7 +230,7 @@ function searchMails() {
 
 				for($i = 1; $i <= $messageCount; ++$i) {
 				    $headers = imap_header($mailbox->getMailbox(), $i);
-					$uid = imap_uid($mailbox->getMailbox(), $i);
+					$uid = imap_uid($mailbox->getMailbox(), $i); // TODO: Get really unique ID, not folder-id
 
 					$documents = getDocumentsByMailUidLabelId($uid, $mbFolder[0]->getLabelId());
 
@@ -223,4 +242,29 @@ function searchMails() {
 		}
 	}
 }
+
+
+function getEditableLink($elementId, $type, $pk, $title, $value) {
+	if($type == 'text' || $type == 'password') {
+		$class = 'editable-element-text';
+	} else if($type == 'select' && $elementId == 'protocol') {
+		$class = 'editable-element-select-protocol';
+	} else if($type == 'select' && $elementId == 'use-ssl') {
+		$class = 'editable-element-select-use-ssl';
+		if($value == '/ssl') {
+			$value = 'On';
+		} else {
+			$value = 'Off';
+		}
+	} else if($type == 'select' && $elementId == 'no-valid-cert') {
+		$class = 'editable-element-select-no-valid-cert';
+		if($value == '/novalidate-cert') {
+			$value = 'On';
+		} else {
+			$value = 'Off';
+		}
+	}
+	$link = '<a href="#" id="' . $elementId . '" class="' . $class . '" data-type="' . $type . '" data-pk="' . $pk . '" data-url="ajax.php" data-title="' . $title . '">' . $value . '</a>';
+	return $link;
+}
 ?>

+ 51 - 10
includes/imap.inc.php

@@ -1,18 +1,31 @@
 <?php
 
 class Imap {
-    private $server     = NULL;
-    private $username   = NULL;
-    private $password   = NULL;
-    private $mailbox    = NULL;
-    private $folders    = NULL;
+    private $id             = NULL;
+    private $server         = NULL;
+    private $hostname       = NULL;
+    private $port           = NULL;
+    private $protocol       = NULL;
+    private $useSsl         = NULL;
+    private $noValidCert    = NULL;
+    private $username       = NULL;
+    private $password       = NULL;
+    private $mailbox        = NULL;
+    private $folders        = NULL;
 
-    public function __construct($server, $username, $password) {
-        $this->server   = $server;
-        $this->username = $username;
-        $this->password = $password;
+    public function __construct($id, $hostname, $port, $protocol, $useSsl, $noValidCert, $username, $password) {
+        $this->id           = $id;
+        $this->hostname     = $hostname;
+        $this->port         = $port;
+        $this->protocol     = $protocol;
+        $this->useSsl       = $useSsl;
+        $this->noValidCert  = $noValidCert;
+        $this->username     = $username;
+        $this->password     = $password;
+        // '{' . $mailbox->server . ':' . $mailbox->port . '/' . $mailbox->protocol . $useSsl . $noValidCert . '}'
+        $this->server   = '{' . $this->hostname . ':' . $this->port . '/' . $this->protocol . $this->useSsl . $this->noValidCert . '}';
 
-        $this->mailbox = imap_open($this->server . 'INBOX', $this->username, $this->password) or error('Failed to connect to IMAP');
+        $this->mailbox = imap_open($this->server . 'INBOX', $this->username, $this->password) or error('Failed to connect to IMAP: ' . $this->username . '@' . $this->hostname);
     }
 
     public function changeFolder($folder) {
@@ -30,6 +43,10 @@ class Imap {
         $this->folders = $newFolders;
     }
 
+    public function getId() {
+        return $this->id;
+    }
+
     public function getFolders() {
         return $this->folders;
     }
@@ -42,5 +59,29 @@ class Imap {
         return $this->mailbox;
     }
 
+    public function getHostname() {
+        return $this->hostname;
+    }
+
+    public function getPort() {
+        return $this->port;
+    }
+
+    public function getProtocol() {
+        return $this->protocol;
+    }
+
+    public function getUseSsl() {
+        return $this->useSsl;
+    }
+
+    public function getNoValidCert() {
+        return $this->noValidCert;
+    }
+
+    public function getUsername() {
+        return $this->username;
+    }
+
 
 }

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 4 - 0
scripts/bootstrap-editable.min.js


+ 117 - 0
scripts/custom.js

@@ -0,0 +1,117 @@
+$(document).ready(function() {
+    $.fn.editable.defaults.mode = 'inline';
+    $.fn.editableform.buttons =
+  '<button type="submit" class="btn btn-primary btn-sm editable-submit">'+
+    '<i class="fa fa-fw fa-check"></i>'+
+  '</button>'+
+  '<button type="button" class="btn btn-default btn-sm editable-cancel">'+
+    '<i class="fa fa-fw fa-times"></i>'+
+  '</button>';
+
+    $('.editable-element-text').editable({
+        escape: false,
+        success: function(response, newValue) {
+            console.log(response); // Debug output from ajax.php
+            if(response.status == 'error') return response.msg; //msg will be shown in editable form
+        },
+        error: function (xhr, status, error) {
+            //var err = eval("(" + xhr.responseText + ")");
+            return xhr.statusText;
+        },
+        params: function(params) {
+            params.action = 'updateMailaccounts';
+            return params;
+        }
+    });
+
+    $('.editable-element-select-protocol').editable({
+        defaultValue: 'imap',
+        source: [
+            {value: 'imap', text: 'IMAP'},
+            {value: 'pop3', text: 'POP3'}
+        ],
+        success: function(response, newValue) {
+            console.log(response); // Debug output from ajax.php
+            if(response.status == 'error') return response.msg; //msg will be shown in editable form
+        },
+        error: function (xhr, status, error) {
+            //var err = eval("(" + xhr.responseText + ")");
+            return xhr.statusText;
+        },
+        params: function(params) {
+            params.action = 'updateMailaccounts';
+            return params;
+        }
+    });
+
+
+    $('.editable-element-select-use-ssl').editable({
+        defaultValue: '1',
+        source: [
+            {value: '1', text: 'On'},
+            {value: '0', text: 'Off'}
+        ],
+        success: function(response, newValue) {
+            console.log(response); // Debug output from ajax.php
+            if(response.status == 'error') return response.msg; //msg will be shown in editable form
+        },
+        error: function (xhr, status, error) {
+            //var err = eval("(" + xhr.responseText + ")");
+            return xhr.statusText;
+        },
+        params: function(params) {
+            params.action = 'updateMailaccounts';
+            return params;
+        }
+    });
+
+
+    $('.editable-element-select-no-valid-cert').editable({
+        defaultValue: '0',
+        source: [
+            {value: '0', text: 'On'},
+            {value: '1', text: 'Off'}
+        ],
+        success: function(response, newValue) {
+            console.log(response); // Debug output from ajax.php
+            if(response.status == 'error') return response.msg; //msg will be shown in editable form
+        },
+        error: function (xhr, status, error) {
+            //var err = eval("(" + xhr.responseText + ")");
+            return xhr.statusText;
+        },
+        params: function(params) {
+            params.action = 'updateMailaccounts';
+            return params;
+        }
+    });
+
+
+    $('#add-mailaccount').on('click', function(e) {
+        e.preventDefault();
+        var uId = $(this).attr('data-uid');
+        $.ajax({
+                url: 'ajax.php',
+                type: 'POST',
+                data: {'action': 'addDefaultMailaccount', 'user-id': uId},
+                success: function (result) {
+                    console.log(result);
+                    location.reload();
+                }
+            });
+    });
+
+    $('.remove-mailaccount').on('click', function(e) {
+        e.preventDefault();
+        var id = $(this).attr('data-id');
+        $.ajax({
+                url: 'ajax.php',
+                type: 'POST',
+                data: {'action': 'removeMailaccount', 'id': id},
+                success: function (result) {
+                    console.log(result);
+                    location.reload();
+                }
+            });
+    });
+});

+ 663 - 0
styles/bootstrap-editable.css

@@ -0,0 +1,663 @@
+/*! X-editable - v1.5.1 
+* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
+* http://github.com/vitalets/x-editable
+* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
+.editableform {
+    margin-bottom: 0; /* overwrites bootstrap margin */
+}
+
+.editableform .control-group {
+    margin-bottom: 0; /* overwrites bootstrap margin */
+    white-space: nowrap; /* prevent wrapping buttons on new line */
+    line-height: 20px; /* overwriting bootstrap line-height. See #133 */
+}
+
+/* 
+  BS3 width:1005 for inputs breaks editable form in popup 
+  See: https://github.com/vitalets/x-editable/issues/393
+*/
+.editableform .form-control {
+    width: auto;
+}
+
+.editable-buttons {
+   display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
+   vertical-align: top;
+   margin-left: 7px;
+   /* inline-block emulation for IE7*/
+   zoom: 1; 
+   *display: inline;
+}
+
+.editable-buttons.editable-buttons-bottom {
+   display: block; 
+   margin-top: 7px;
+   margin-left: 0;
+}
+
+.editable-input {
+    vertical-align: top; 
+    display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
+    width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
+    white-space: normal; /* reset white-space decalred in parent*/
+   /* display-inline emulation for IE7*/
+   zoom: 1; 
+   *display: inline;   
+}
+
+.editable-buttons .editable-cancel {
+   margin-left: 7px; 
+}
+
+/*for jquery-ui buttons need set height to look more pretty*/
+.editable-buttons button.ui-button-icon-only {
+   height: 24px; 
+   width: 30px;
+}
+
+.editableform-loading {
+    background: url('../img/loading.gif') center center no-repeat;  
+    height: 25px;
+    width: auto; 
+    min-width: 25px; 
+}
+
+.editable-inline .editableform-loading {
+    background-position: left 5px;      
+}
+
+ .editable-error-block {
+    max-width: 300px;
+    margin: 5px 0 0 0;
+    width: auto;
+    white-space: normal;
+}
+
+/*add padding for jquery ui*/
+.editable-error-block.ui-state-error {
+    padding: 3px;  
+}  
+
+.editable-error {
+   color: red;  
+}
+
+/* ---- For specific types ---- */
+
+.editableform .editable-date {
+    padding: 0; 
+    margin: 0;
+    float: left;
+}
+
+/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
+.editable-inline .add-on .icon-th {
+   margin-top: 3px;
+   margin-left: 1px; 
+}
+
+
+/* checklist vertical alignment */
+.editable-checklist label input[type="checkbox"], 
+.editable-checklist label span {
+    vertical-align: middle;
+    margin: 0;
+}
+
+.editable-checklist label {
+    white-space: nowrap; 
+}
+
+/* set exact width of textarea to fit buttons toolbar */
+.editable-wysihtml5 {
+    width: 566px; 
+    height: 250px; 
+}
+
+/* clear button shown as link in date inputs */
+.editable-clear {
+   clear: both;
+   font-size: 0.9em;
+   text-decoration: none;
+   text-align: right;
+}
+
+/* IOS-style clear button for text inputs */
+.editable-clear-x {
+   background: url('../img/clear.png') center center no-repeat;
+   display: block;
+   width: 13px;    
+   height: 13px;
+   position: absolute;
+   opacity: 0.6;
+   z-index: 100;
+   
+   top: 50%;
+   right: 6px;
+   margin-top: -6px;
+   
+}
+
+.editable-clear-x:hover {
+   opacity: 1;
+}
+
+.editable-pre-wrapped {
+   white-space: pre-wrap;
+}
+.editable-container.editable-popup {
+    max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
+}  
+
+.editable-container.popover {
+    width: auto; /* without this rule popover does not stretch */
+}
+
+.editable-container.editable-inline {
+    display: inline-block; 
+    vertical-align: middle;
+    width: auto;
+    /* inline-block emulation for IE7*/
+    zoom: 1; 
+    *display: inline;    
+}
+
+.editable-container.ui-widget {
+   font-size: inherit;  /* jqueryui widget font 1.1em too big, overwrite it */
+   z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
+}
+.editable-click, 
+a.editable-click, 
+a.editable-click:hover {
+    text-decoration: none;
+    border-bottom: dashed 1px #0088cc;
+}
+
+.editable-click.editable-disabled, 
+a.editable-click.editable-disabled, 
+a.editable-click.editable-disabled:hover {
+   color: #585858;  
+   cursor: default;
+   border-bottom: none;
+}
+
+.editable-empty, .editable-empty:hover, .editable-empty:focus{
+  font-style: italic; 
+  color: #DD1144;  
+  /* border-bottom: none; */
+  text-decoration: none;
+}
+
+.editable-unsaved {
+  font-weight: bold; 
+}
+
+.editable-unsaved:after {
+/*    content: '*'*/
+}
+
+.editable-bg-transition {
+  -webkit-transition: background-color 1400ms ease-out;
+  -moz-transition: background-color 1400ms ease-out;
+  -o-transition: background-color 1400ms ease-out;
+  -ms-transition: background-color 1400ms ease-out;
+  transition: background-color 1400ms ease-out;  
+}
+
+/*see https://github.com/vitalets/x-editable/issues/139 */
+.form-horizontal .editable
+{ 
+    padding-top: 5px;
+    display:inline-block;
+}
+
+
+/*!
+ * Datepicker for Bootstrap
+ *
+ * Copyright 2012 Stefan Petre
+ * Improvements by Andrew Rowls
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+.datepicker {
+  padding: 4px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+  direction: ltr;
+  /*.dow {
+		border-top: 1px solid #ddd !important;
+	}*/
+
+}
+.datepicker-inline {
+  width: 220px;
+}
+.datepicker.datepicker-rtl {
+  direction: rtl;
+}
+.datepicker.datepicker-rtl table tr td span {
+  float: right;
+}
+.datepicker-dropdown {
+  top: 0;
+  left: 0;
+}
+.datepicker-dropdown:before {
+  content: '';
+  display: inline-block;
+  border-left: 7px solid transparent;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid #ccc;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  position: absolute;
+  top: -7px;
+  left: 6px;
+}
+.datepicker-dropdown:after {
+  content: '';
+  display: inline-block;
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid #ffffff;
+  position: absolute;
+  top: -6px;
+  left: 7px;
+}
+.datepicker > div {
+  display: none;
+}
+.datepicker.days div.datepicker-days {
+  display: block;
+}
+.datepicker.months div.datepicker-months {
+  display: block;
+}
+.datepicker.years div.datepicker-years {
+  display: block;
+}
+.datepicker table {
+  margin: 0;
+}
+.datepicker td,
+.datepicker th {
+  text-align: center;
+  width: 20px;
+  height: 20px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+  border: none;
+}
+.table-striped .datepicker table tr td,
+.table-striped .datepicker table tr th {
+  background-color: transparent;
+}
+.datepicker table tr td.day:hover {
+  background: #eeeeee;
+  cursor: pointer;
+}
+.datepicker table tr td.old,
+.datepicker table tr td.new {
+  color: #999999;
+}
+.datepicker table tr td.disabled,
+.datepicker table tr td.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: default;
+}
+.datepicker table tr td.today,
+.datepicker table tr td.today:hover,
+.datepicker table tr td.today.disabled,
+.datepicker table tr td.today.disabled:hover {
+  background-color: #fde19a;
+  background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
+  background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
+  background-image: linear-gradient(top, #fdd49a, #fdf59a);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
+  border-color: #fdf59a #fdf59a #fbed50;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #000;
+}
+.datepicker table tr td.today:hover,
+.datepicker table tr td.today:hover:hover,
+.datepicker table tr td.today.disabled:hover,
+.datepicker table tr td.today.disabled:hover:hover,
+.datepicker table tr td.today:active,
+.datepicker table tr td.today:hover:active,
+.datepicker table tr td.today.disabled:active,
+.datepicker table tr td.today.disabled:hover:active,
+.datepicker table tr td.today.active,
+.datepicker table tr td.today:hover.active,
+.datepicker table tr td.today.disabled.active,
+.datepicker table tr td.today.disabled:hover.active,
+.datepicker table tr td.today.disabled,
+.datepicker table tr td.today:hover.disabled,
+.datepicker table tr td.today.disabled.disabled,
+.datepicker table tr td.today.disabled:hover.disabled,
+.datepicker table tr td.today[disabled],
+.datepicker table tr td.today:hover[disabled],
+.datepicker table tr td.today.disabled[disabled],
+.datepicker table tr td.today.disabled:hover[disabled] {
+  background-color: #fdf59a;
+}
+.datepicker table tr td.today:active,
+.datepicker table tr td.today:hover:active,
+.datepicker table tr td.today.disabled:active,
+.datepicker table tr td.today.disabled:hover:active,
+.datepicker table tr td.today.active,
+.datepicker table tr td.today:hover.active,
+.datepicker table tr td.today.disabled.active,
+.datepicker table tr td.today.disabled:hover.active {
+  background-color: #fbf069 \9;
+}
+.datepicker table tr td.today:hover:hover {
+  color: #000;
+}
+.datepicker table tr td.today.active:hover {
+  color: #fff;
+}
+.datepicker table tr td.range,
+.datepicker table tr td.range:hover,
+.datepicker table tr td.range.disabled,
+.datepicker table tr td.range.disabled:hover {
+  background: #eeeeee;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+}
+.datepicker table tr td.range.today,
+.datepicker table tr td.range.today:hover,
+.datepicker table tr td.range.today.disabled,
+.datepicker table tr td.range.today.disabled:hover {
+  background-color: #f3d17a;
+  background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
+  background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
+  background-image: linear-gradient(top, #f3c17a, #f3e97a);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
+  border-color: #f3e97a #f3e97a #edde34;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+}
+.datepicker table tr td.range.today:hover,
+.datepicker table tr td.range.today:hover:hover,
+.datepicker table tr td.range.today.disabled:hover,
+.datepicker table tr td.range.today.disabled:hover:hover,
+.datepicker table tr td.range.today:active,
+.datepicker table tr td.range.today:hover:active,
+.datepicker table tr td.range.today.disabled:active,
+.datepicker table tr td.range.today.disabled:hover:active,
+.datepicker table tr td.range.today.active,
+.datepicker table tr td.range.today:hover.active,
+.datepicker table tr td.range.today.disabled.active,
+.datepicker table tr td.range.today.disabled:hover.active,
+.datepicker table tr td.range.today.disabled,
+.datepicker table tr td.range.today:hover.disabled,
+.datepicker table tr td.range.today.disabled.disabled,
+.datepicker table tr td.range.today.disabled:hover.disabled,
+.datepicker table tr td.range.today[disabled],
+.datepicker table tr td.range.today:hover[disabled],
+.datepicker table tr td.range.today.disabled[disabled],
+.datepicker table tr td.range.today.disabled:hover[disabled] {
+  background-color: #f3e97a;
+}
+.datepicker table tr td.range.today:active,
+.datepicker table tr td.range.today:hover:active,
+.datepicker table tr td.range.today.disabled:active,
+.datepicker table tr td.range.today.disabled:hover:active,
+.datepicker table tr td.range.today.active,
+.datepicker table tr td.range.today:hover.active,
+.datepicker table tr td.range.today.disabled.active,
+.datepicker table tr td.range.today.disabled:hover.active {
+  background-color: #efe24b \9;
+}
+.datepicker table tr td.selected,
+.datepicker table tr td.selected:hover,
+.datepicker table tr td.selected.disabled,
+.datepicker table tr td.selected.disabled:hover {
+  background-color: #9e9e9e;
+  background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
+  background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
+  background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
+  background-image: -o-linear-gradient(top, #b3b3b3, #808080);
+  background-image: linear-gradient(top, #b3b3b3, #808080);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
+  border-color: #808080 #808080 #595959;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker table tr td.selected:hover,
+.datepicker table tr td.selected:hover:hover,
+.datepicker table tr td.selected.disabled:hover,
+.datepicker table tr td.selected.disabled:hover:hover,
+.datepicker table tr td.selected:active,
+.datepicker table tr td.selected:hover:active,
+.datepicker table tr td.selected.disabled:active,
+.datepicker table tr td.selected.disabled:hover:active,
+.datepicker table tr td.selected.active,
+.datepicker table tr td.selected:hover.active,
+.datepicker table tr td.selected.disabled.active,
+.datepicker table tr td.selected.disabled:hover.active,
+.datepicker table tr td.selected.disabled,
+.datepicker table tr td.selected:hover.disabled,
+.datepicker table tr td.selected.disabled.disabled,
+.datepicker table tr td.selected.disabled:hover.disabled,
+.datepicker table tr td.selected[disabled],
+.datepicker table tr td.selected:hover[disabled],
+.datepicker table tr td.selected.disabled[disabled],
+.datepicker table tr td.selected.disabled:hover[disabled] {
+  background-color: #808080;
+}
+.datepicker table tr td.selected:active,
+.datepicker table tr td.selected:hover:active,
+.datepicker table tr td.selected.disabled:active,
+.datepicker table tr td.selected.disabled:hover:active,
+.datepicker table tr td.selected.active,
+.datepicker table tr td.selected:hover.active,
+.datepicker table tr td.selected.disabled.active,
+.datepicker table tr td.selected.disabled:hover.active {
+  background-color: #666666 \9;
+}
+.datepicker table tr td.active,
+.datepicker table tr td.active:hover,
+.datepicker table tr td.active.disabled,
+.datepicker table tr td.active.disabled:hover {
+  background-color: #006dcc;
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(top, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker table tr td.active:hover,
+.datepicker table tr td.active:hover:hover,
+.datepicker table tr td.active.disabled:hover,
+.datepicker table tr td.active.disabled:hover:hover,
+.datepicker table tr td.active:active,
+.datepicker table tr td.active:hover:active,
+.datepicker table tr td.active.disabled:active,
+.datepicker table tr td.active.disabled:hover:active,
+.datepicker table tr td.active.active,
+.datepicker table tr td.active:hover.active,
+.datepicker table tr td.active.disabled.active,
+.datepicker table tr td.active.disabled:hover.active,
+.datepicker table tr td.active.disabled,
+.datepicker table tr td.active:hover.disabled,
+.datepicker table tr td.active.disabled.disabled,
+.datepicker table tr td.active.disabled:hover.disabled,
+.datepicker table tr td.active[disabled],
+.datepicker table tr td.active:hover[disabled],
+.datepicker table tr td.active.disabled[disabled],
+.datepicker table tr td.active.disabled:hover[disabled] {
+  background-color: #0044cc;
+}
+.datepicker table tr td.active:active,
+.datepicker table tr td.active:hover:active,
+.datepicker table tr td.active.disabled:active,
+.datepicker table tr td.active.disabled:hover:active,
+.datepicker table tr td.active.active,
+.datepicker table tr td.active:hover.active,
+.datepicker table tr td.active.disabled.active,
+.datepicker table tr td.active.disabled:hover.active {
+  background-color: #003399 \9;
+}
+.datepicker table tr td span {
+  display: block;
+  width: 23%;
+  height: 54px;
+  line-height: 54px;
+  float: left;
+  margin: 1%;
+  cursor: pointer;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+}
+.datepicker table tr td span:hover {
+  background: #eeeeee;
+}
+.datepicker table tr td span.disabled,
+.datepicker table tr td span.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: default;
+}
+.datepicker table tr td span.active,
+.datepicker table tr td span.active:hover,
+.datepicker table tr td span.active.disabled,
+.datepicker table tr td span.active.disabled:hover {
+  background-color: #006dcc;
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(top, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker table tr td span.active:hover,
+.datepicker table tr td span.active:hover:hover,
+.datepicker table tr td span.active.disabled:hover,
+.datepicker table tr td span.active.disabled:hover:hover,
+.datepicker table tr td span.active:active,
+.datepicker table tr td span.active:hover:active,
+.datepicker table tr td span.active.disabled:active,
+.datepicker table tr td span.active.disabled:hover:active,
+.datepicker table tr td span.active.active,
+.datepicker table tr td span.active:hover.active,
+.datepicker table tr td span.active.disabled.active,
+.datepicker table tr td span.active.disabled:hover.active,
+.datepicker table tr td span.active.disabled,
+.datepicker table tr td span.active:hover.disabled,
+.datepicker table tr td span.active.disabled.disabled,
+.datepicker table tr td span.active.disabled:hover.disabled,
+.datepicker table tr td span.active[disabled],
+.datepicker table tr td span.active:hover[disabled],
+.datepicker table tr td span.active.disabled[disabled],
+.datepicker table tr td span.active.disabled:hover[disabled] {
+  background-color: #0044cc;
+}
+.datepicker table tr td span.active:active,
+.datepicker table tr td span.active:hover:active,
+.datepicker table tr td span.active.disabled:active,
+.datepicker table tr td span.active.disabled:hover:active,
+.datepicker table tr td span.active.active,
+.datepicker table tr td span.active:hover.active,
+.datepicker table tr td span.active.disabled.active,
+.datepicker table tr td span.active.disabled:hover.active {
+  background-color: #003399 \9;
+}
+.datepicker table tr td span.old,
+.datepicker table tr td span.new {
+  color: #999999;
+}
+.datepicker th.datepicker-switch {
+  width: 145px;
+}
+.datepicker thead tr:first-child th,
+.datepicker tfoot tr th {
+  cursor: pointer;
+}
+.datepicker thead tr:first-child th:hover,
+.datepicker tfoot tr th:hover {
+  background: #eeeeee;
+}
+.datepicker .cw {
+  font-size: 10px;
+  width: 12px;
+  padding: 0 2px 0 5px;
+  vertical-align: middle;
+}
+.datepicker thead tr:first-child th.cw {
+  cursor: default;
+  background-color: transparent;
+}
+.input-append.date .add-on i,
+.input-prepend.date .add-on i {
+  display: block;
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+}
+.input-daterange input {
+  text-align: center;
+}
+.input-daterange input:first-child {
+  -webkit-border-radius: 3px 0 0 3px;
+  -moz-border-radius: 3px 0 0 3px;
+  border-radius: 3px 0 0 3px;
+}
+.input-daterange input:last-child {
+  -webkit-border-radius: 0 3px 3px 0;
+  -moz-border-radius: 0 3px 3px 0;
+  border-radius: 0 3px 3px 0;
+}
+.input-daterange .add-on {
+  display: inline-block;
+  width: auto;
+  min-width: 16px;
+  height: 18px;
+  padding: 4px 5px;
+  font-weight: normal;
+  line-height: 18px;
+  text-align: center;
+  text-shadow: 0 1px 0 #ffffff;
+  vertical-align: middle;
+  background-color: #eeeeee;
+  border: 1px solid #ccc;
+  margin-left: -5px;
+  margin-right: -5px;
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 0
styles/font-awesome.min.css


+ 8 - 0
styles/style.css

@@ -45,6 +45,14 @@ table tr > td:last-of-type {
 	font-weight: 600;
 }
 
+table td {
+	vertical-align: middle !important;
+}
+
+#protocol.editable-element-select-protocol {
+	text-transform: uppercase;
+}
+
 /*.footer {
 	position: absolute;
 	bottom: 0;

+ 2 - 0
templates/footer.php

@@ -7,6 +7,8 @@
 	<script src="scripts/jquery-2.1.3.min.js"></script>
 	<script src="scripts/bootstrap.min.js"></script>
 	<script src="scripts/docs.min.js"></script>
+	<script src="scripts/bootstrap-editable.min.js"></script>
+	<script src="scripts/custom.js"></script>
 	<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
 	<!--<script src="./Dashboard Template for Bootstrap_files/ie10-viewport-bug-workaround.js"></script>-->
 	</body>

+ 4 - 2
templates/header.php

@@ -15,6 +15,8 @@
 	<!-- Custom styles for this template -->
 	<link href="styles/dashboard.css" rel="stylesheet">
 	<link href="styles/style.css" rel="stylesheet">
+	<link href="styles/bootstrap-editable.css" rel="stylesheet">
+	<link href="styles/font-awesome.min.css" rel="stylesheet">
 
 	<!--<script src="./Dashboard Template for Bootstrap_files/ie-emulation-modes-warning.js"></script><style type="text/css"></style>-->
 
@@ -41,7 +43,7 @@
 		<div id="navbar" class="navbar-collapse collapse">
 		<ul class="nav navbar-nav navbar-right">
 			<li><a href="">Dashboard</a></li>
-			<li><a href="">Einstellungen</a></li>
+			<li><a href="?action=settings">Einstellungen</a></li>
 			<li><a href="">Profil</a></li>
 			<li><a href="">Hilfe</a></li>
 			<li><a href="?action=logout">Logout</a></li>
@@ -60,7 +62,7 @@
 			<li class="active"><a href="?">Übersicht <span class="sr-only">(current)</span></a></li>
 		</ul>
 		<ul class="nav nav-sidebar">
-			<li class="navbar-label-header"><a href="?action=manage-labels">Labels</a></li>
+			<li class="navbar-label-header<?php if(isset($this->_['request']['action']) && $this->_['request']['action'] == 'manage-labels') { echo ' active'; } ?>"><a href="?action=manage-labels">Labels</a></li>
 			<?php
 			foreach($this->_['labels'] as $label) {
 				if(isset($this->_['request']['action']) && $this->_['request']['action'] == 'label' && $_REQUEST['labelId'] == $label->getId()) {

+ 1 - 1
templates/label.php

@@ -20,7 +20,7 @@ foreach($this->_['entries'] as $entry){
                 <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">Profile</a></li>
                 <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">Messages</a></li>
                 <li role="presentation"><a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">Settings</a></li>
-            </ul>
+            </ul> <!-- TODO: Add manual file-scan button -->
 
             <!-- Tab panes -->
             <div class="tab-content">

+ 38 - 0
templates/manage-label.php

@@ -0,0 +1,38 @@
+<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
+    <h1 class="page-header">Label verwalten</h1>
+
+    <div class="row">
+        <form action="" method="POST">
+            <input type="hidden" name="labelId" value="<?php echo $this->_['label'][0]->getId(); ?>">
+            <div class="form-group">
+                <label for="labelName">Name</label>
+                <input type="text" class="form-control" id="labelName" name="labelName" value="<?php echo $this->_['label'][0]->getName(); ?>">
+            </div>
+            <div class="form-group">
+                <label>Zugewiesene Mailaccounts</label>
+                <table class="table table-striped">
+                    <thead>
+                        <tr>
+                            <th>#</th>
+                            <th>Name</th>
+                            <th>Manage</th>
+                            <th>Remove</th>
+                        </tr>
+                        <?php
+                            foreach($this->_['mailboxFolders'] as $mailboxFolder) {
+                                echo '<tr>';
+                                echo '<td>' . $mailboxFolder->getMailboxId() . '</td>';
+                                echo '<td>' . $mailboxFolder->getFolderName() . '</td>';
+                                echo '<td><a href="" role="button" class="btn btn-primary">Manage</a></td>';
+                                echo '<td><a href="" role="button" class="btn btn-danger">Remove</a></td>';
+                                echo '</tr>';
+                            }
+                        ?>
+                    </thead>
+                    <a href="" role="button" class="btn btn-primary pull-right">Add</a> <!-- TODO: Add this, manage and remove (fancybox!) -->
+                </table>
+            </div>
+            <button type="submit" class="btn btn-default">Submit</button>
+        </form>
+    </div>
+</div>

+ 27 - 0
templates/manage-labels.php

@@ -0,0 +1,27 @@
+<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
+    <h1 class="page-header">Label verwalten</h1>
+
+    <div class="row">
+        <?php
+            //pa($this->_['labels']);
+        ?>
+        <table class="table table-striped">
+            <thead>
+                <tr>
+                    <th>#</th>
+                    <th>Name</th>
+                    <th>Manage</th>
+                </tr>
+            </thead>
+            <?php
+                foreach($this->_['labels'] as $label) {
+                    echo '<tr>';
+                    echo '<td>' . $label->getId() . '</td>';
+                    echo '<td>' . $label->getName() . '</td>';
+                    echo '<td><a href="?action=manage-label&labelId=' . $label->getId() . '" role="button" class="btn btn-primary">Manage</a></td>';
+                    echo '</tr>';
+                }
+            ?>
+        </table>
+    </div>
+</div>

+ 50 - 0
templates/settings.php

@@ -0,0 +1,50 @@
+<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
+    <h1 class="page-header">Settings</h1>
+
+    <div class="row">
+        <h3>Mailaccounts</h3>
+        <?php
+            $user = $this->_['user'];
+            $mailboxes = getMailboxesByUserId($user->getUserId()); // TODO: MVC
+        ?>
+
+        <table class="table table-striped">
+            <thead>
+                <tr>
+                    <th>Hostname</th>
+                    <th>Port</th>
+                    <th>Protocol</th>
+                    <th>SSL</th>
+                    <th>Allow invalid cert</th>
+                    <th>Username</th>
+                    <th>Password</th>
+                    <th></th>
+                </tr>
+            </thead>
+            <?php
+            foreach($mailboxes as $mailbox) {
+                echo '<tr>';
+                echo '<td>' . getEditableLink('hostname', 'text', $mailbox->getId(), 'Click to edit', $mailbox->getHostname()) . '</td>';
+                echo '<td>' . getEditableLink('port', 'text', $mailbox->getId(), 'Click to edit', $mailbox->getPort()) . '</td>'; // TODO: alternative inputs
+                echo '<td>' . getEditableLink('protocol', 'select', $mailbox->getId(), 'Click to edit', $mailbox->getProtocol()) . '</td>';
+                echo '<td>' . getEditableLink('use-ssl', 'select', $mailbox->getId(), 'Click to edit', $mailbox->getUseSsl()) . '</td>';
+                echo '<td>' . getEditableLink('no-valid-cert', 'select', $mailbox->getId(), 'Click to edit', $mailbox->getNoValidCert()) . '</td>';
+                echo '<td>' . getEditableLink('username', 'text', $mailbox->getId(), 'Click to edit', $mailbox->getUsername()) . '</td>';
+                echo '<td>' . getEditableLink('password', 'password', $mailbox->getId(), 'Click to edit', 'Click to change') . '</td>';
+                echo '<td><a class="remove-mailaccount" href="#" data-id="' . $mailbox->getId() . '"><i class="fa fa-minus-circle"></i></a></td>';
+                echo '</tr>';
+            }
+            ?>
+            <tr>
+                <td><a id="add-mailaccount" href="#" data-uid="<?php echo $user->getUserId(); ?>"><i class="fa fa-plus-circle"></i></a></td>
+                <td></td>
+                <td></td>
+                <td></td>
+                <td></td>
+                <td></td>
+                <td></td>
+                <td></td>
+            </tr>
+        </table>
+    </div>
+</div>

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott