Просмотр исходного кода

Project management page improved. Blog management page created.

Iñigo Valentin 8 лет назад
Родитель
Сommit
e145329705

+ 17 - 2
www-admin/blog/delete.php

@@ -8,9 +8,24 @@
     $server = $proto . $http_host;
     $pserver = substr($server, 0, strpos($http_host, ':')); // public server
     if (!check_session($con)){
-        header("Location: /authentication.php");
-        exit(-1);
+        http_response_code(401); // Not logged in: Forbidden.
     }
     else{
+        $id = intval(mysqli_real_escape_string($con, $_GET["p"]));
+        if (strlen($id) < 1){
+            http_response_code(400); // No or bad ID: Bad request.
+        }
+        else{
+            if (mysqli_num_rows(mysqli_query($con, "SELECT id FROM post WHERE id = $id;")) == 0){
+                http_response_code(404); // Unexistent id: Not found.
+            }
+            else{
+                mysqli_query($con, "DELETE FROM post_tag WHERE project = $id;");
+                mysqli_query($con, "DELETE FROM post_image WHERE project = $id;");
+                mysqli_query($con, "DELETE FROM post_comment WHERE project = $id;");
+                mysqli_query($con, "DELETE FROM post WHERE id = $id;");
+                http_response_code(200); //OK.
+            }
+        }
     }
 ?>

+ 28 - 0
www-admin/blog/deletecomment.php

@@ -0,0 +1,28 @@
+<?php
+    session_start();
+    $http_host = $_SERVER["HTTP_HOST"];
+    $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
+    include $doc_root . "functions.php";
+    $proto = get_protocol();
+    $con = start_db();
+    $server = $proto . $http_host;
+    $pserver = substr($server, 0, strpos($http_host, ':')); // public server
+    if (!check_session($con)){
+        http_response_code(401); // Not logged in: Forbidden.
+    }
+    else{
+        $id = intval(mysqli_real_escape_string($con, $_GET["i"]));
+        if (strlen($id) < 1){
+            http_response_code(400); // No or bad ID: Bad request.
+        }
+        else{
+            if (mysqli_num_rows(mysqli_query($con, "SELECT id FROM post_comment WHERE id = $id;")) == 0){
+                http_response_code(404); // Unexistent id: Not found.
+            }
+            else{
+                mysqli_query($con, "DELETE FROM post_comment WHERE id = $id;");
+                http_response_code(200); //OK.
+            }
+        }
+    }
+?>

+ 241 - 5
www-admin/blog/edit.php

@@ -4,49 +4,285 @@
     $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
     include $doc_root . "functions.php";
     $proto = get_protocol();
+    $lang = "en";
     $con = start_db();
     $server = $proto . $http_host;
-    $pserver = substr($server, 0, strpos($http_host, ':')); // public server
+    $pserver = $proto . substr($http_host, 0, strpos($http_host, ':')); // public server
     if (!check_session($con)){
+        http_response_code(401);
         header("Location: /authentication.php");
-        exit(-1);
     }
     else{
+        $id = intval(mysqli_real_escape_string($con, $_GET["p"]));
+        if (strlen($id) < 1){
+            http_response_code(400); // No or bad ID: Bad request.
+            header("Location: /blog/");
+        }
+        else{
+            $q_post = mysqli_query($con, "SELECT * FROM post WHERE id = $id;");
+            if (mysqli_num_rows($q_post) == 0){
+                http_response_code(404); // Unexistent id: Not found.
+                header("Location: /blog/");
+            }
+            else{
+                $r_post = mysqli_fetch_array($q_post);
+                $id = $r_post["id"];
+                $title = text($con, $r_post["title"], $lang);
+                $q_lang = mysqli_query($con, "SELECT * FROM lang;");
 ?>
 <html>
     <head>
         <meta content='text/html; charset=windows-1252' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'>
         <link rel='shortcut icon' href='<?=$pserver?>/img/logo/x2/favicon.ico'/>
-        <title>I&ntilde;igo Valentin - Administration Panel</title>
+        <title><?=$title?>I&ntilde;igo Valentin - Administration Panel</title>
         <style>
 <?php
             include $doc_root . "css/ui.css";
-            include $doc_root . "css/home.css";
+            include $doc_root . "css/blog.css";
 ?>
         </style>
         <!-- CSS for mobile version -->
         <style media='(max-width : 990px)'>
 <?php
             include $doc_root . "css/m/ui.css";
-            include $doc_root . "css/m/home.css";
+            include $doc_root . "css/m/blog.css";
 ?>
         </style>
         <!-- Script files -->
         <script type='text/javascript'>
 <?php
             include $doc_root . "script/ui.js";
+            include $doc_root . "script/blog.js";
 ?>
         </script>
+         <script src='/script/ckeditor/ckeditor.js'></script>
     </head>
     <body>
 <?php
         include $doc_root . "header.php";
 ?>
         <div id='content'>
+            <div class='section' id='post_edit'>
+                <h3 class='section_title'><?=$title?></h3>
+                <div class='entry'>
+                    <div id='lang_tabs'>
+                        <table>
+                            <tr>
+<?php
+                                mysqli_data_seek($q_lang, 0);
+                                $active = 'lang_tabs_active';
+                                while ($r_lang = mysqli_fetch_array($q_lang)){
+?>
+                                    <td class='pointer <?=$active?>' id='lang_tab_<?=$r_lang["code"]?>' onclick='showLanguage("<?=$r_lang["code"]?>");'>
+                                        <?=$r_lang["name"]?>
+                                    </td>
+<?php
+                                    $active = '';
+                                }
+?>
+                            </tr>
+                        </table>
+                    </div> <!-- #lang_tabs -->
+                    <span class='bold'>URL:</span>
+                    <?=$pserver?>/blog/
+                    <span class='editable'>
+                        <span class='field_result'><?=$r_post["permalink"]?></span>
+                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                        <input class='field_editable' type='text' value='<?=$r_post["permalink"]?>'/>
+                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "post", "permalink", <?=$id?>);'/>
+                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                    </span>
+                    <hr class='separator'/>
+<?php
+                    mysqli_data_seek($q_lang, 0);
+                    $active = "content_lang_active";
+                    while ($r_lang = mysqli_fetch_array($q_lang)){
+?>
+                        <div class='content_lang_<?=$r_lang["code"]?> content_lang <?=$active?>'>
+                            <div class='editable'>
+                                <span class='bold'>Title (<?=$r_lang["name"]?>):</span>
+                                <span class='field_result'><?=text($con, $r_post["title"], $r_lang["code"])?></span>
+                                <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                <input class='field_editable' type='text' value='<?=text($con, $r_post["title"], $r_lang["code"])?>'/>
+                                <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_post["title"]?>");'/>
+                                <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                            </div>
+                            <hr class='separator'/>
+                            <div class='editable'>
+                                <span class='bold'>Text (<?=$r_lang["name"]?>):</span>
+                                <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_post["text"]?>");'/>
+                                <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                <br/>
+                                <p class='field_result'><?=text($con, $r_post["text"], $r_lang["code"])?></p>
+                                <textarea id='text_<?=$r_lang["code"]?>' class='field_editable'><?=text($con, $r_post["text"], $r_lang["code"])?></textarea>
+                                <script>CKEDITOR.replace('text_<?=$r_lang["code"]?>');</script>
+                            </div>
+                        </div> <!-- .content_lang_<?=$r_lang["code"]?> -->
+<?php
+                        $active = '';
+                    }
+?>
+                    <hr class='separator'/>
+                    <h4>Images</h4>
+                    <div id='image_reel' class='horizontal_scroll'>
+<?php
+                        $q_image = mysqli_query($con, "SELECT id, image FROM post_image WHERE post = $id;");
+                        while ($r_image = mysqli_fetch_array($q_image)){
+?>
+                            <span id='post_image_<?=$r_image["id"]?>'>
+                                <img alt='<?=$title?>' title='<?=$title?>' src='<?=$pserver?>/imgblog/x3/<?=$r_image["image"]?>' />
+                                <img class='pointer' onClick='deleteImage(<?=$r_image["id"]?>)' alt='Delete image' title='Delete image' src='<?=$server?>/img/icon/cancel.png' />
+                            </span>
+<?php
+                        }
+?>
+                        <span id='post_image_add'>
+                            <img onClick='addImage(<?=$id?>)' alt='Add image' title='Add image' src='<?=$server?>/img/icon/addimage.png' />
+                        </span> <!-- #image_reel -->
+                    </div>
+                    <hr class='separator'/>
+                    <h4>Tags</h4>
+                    TODO
+                    <hr class='separator'/>
+                    <h4>Settings</h4>
+<?php
+                    if ($r_post["visible"] == 1){
+                        $v = "Yes";
+                        $selected1 = "selected";
+                        $selected0 = "";
+                    }
+                    else{
+                        $v = "No";
+                        $selected1 = "";
+                        $selected0 = "selected";
+                    }
+?>
+                    <div class='editable'>
+                        <span class='bold'>Visible:</span>
+                        <span class='field_result'><?=$v?></span>
+                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                        <select class='field_editable'>
+                            <option value='1' <?=$selected1?>>Yes</option>
+                            <option value='0' <?=$selected0?>>No</option>
+                        </select>
+                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "post", "visible", "<?=$id?>");'/>
+                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                    </div>
+<?php
+                    if ($r_post["comments"] == 1){
+                        $v = "Yes";
+                        $selected1 = "selected";
+                        $selected0 = "";
+                    }
+                    else{
+                        $v = "No";
+                        $selected1 = "";
+                        $selected0 = "selected";
+                    }
+?>
+                    <div class='editable'>
+                        <span class='bold'>Comments enabled:</span>
+                        <span class='field_result'><?=$v?></span>
+                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                        <select class='field_editable'>
+                            <option value='1' <?=$selected1?>>Yes</option>
+                            <option value='0' <?=$selected0?>>No</option>
+                        </select>
+                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "post", "comments", "<?=$id?>");'/>
+                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                    </div>
+                    <input type='button' onclick='deletePost(<?=$id?>, "<?=$title?>");' value='Delete post'/>
+                    <h4>Comments</h4>
+<?php
+                        $q_comment = mysqli_query($con, "SELECT post_comment.id AS id, text, dtime, user, username, lang, (SELECT name FROM lang WHERE code = post_comment.lang) AS lang_name, approved, ip, browser, os, uagent FROM post_comment, stat_visit WHERE stat_visit.id = visit AND post = $id;");
+                        if (mysqli_num_rows($q_comment) == 0){
+?>
+                            <span>No comments yet</span>
+<?php
+                        }
+                        else{
+?>
+                            <table id='comments'>
+<?php
+                            while ($r_comment = mysqli_fetch_array($q_comment)){
+?>
+                                <tr>
+                                    <td class='text'>
+                                        <p><?=$r_comment["text"]?></p>
+                                    </td>
+                                    <td class='details'>
+                                        On <?=format_date($r_comment["dtime"], $lang, true)?>
+                                        <br/>
+<?php
+                                        if (strlen($r_comment["user"]) > 0){
+                                            $q_user = mysqli_query($con, "SELECT concat(fname, concat(' ', lname)) AS name, username FROM user WHERE id = $r_comment[user];");
+                                            $r_user = mysqli_fetch_array($q_user);
+?>
+                                            By <?=$r_user["name"]?> (<span class='bold'><?=$r_user["username"]?></span>)
+<?php
+                                        }
+                                        else{
+?>
+                                            By <?=$r_comment["username"]?>
+<?php
+                                        }
+                                        if (strlen($r_comment["lang_name"]) > 0){
+                                            $strlang = $r_comment["lang_name"];
+                                        }
+                                        else{
+                                            $strlang = $r_comment["lang"];
+                                        }
+                                        if (file_exists($doc_root . "img/lang/" . $r_comment["lang"] . ".gif")){
+                                            $imgpath = $doc_root . "img/lang/" . $r_comment["lang"] . ".gif";
+                                            $strlang = $strlang . " <img class='lang' title='$r_comment[lang]' alt='$r_comment[lang]' src='$server/$imgpath' />";
+                                        }
+?>
+                                        <br/>
+                                        Language: <?=$strlang?>
+<?php
+                                        if ($r_post["visible"] == 1){
+                                            $v = "Yes";
+                                            $selected1 = "selected";
+                                            $selected0 = "";
+                                        }
+                                        else{
+                                            $v = "No";
+                                            $selected1 = "";
+                                            $selected0 = "selected";
+                                        }
+?>
+                                        <div class='editable'>
+                                            Approved:
+                                            <span class='field_result'><?=$v?></span>
+                                            <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                            <select class='field_editable'>
+                                                <option value='1' <?=$selected1?>>Yes</option>
+                                                <option value='0' <?=$selected0?>>No</option>
+                                            </select>
+                                            <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "post_comment", "approved", "<?=$r_comment["id"]?>");'/>
+                                            <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                        </div>
+                                    </td>
+                                    <td class='actions'>
+                                        <input type='button' onclick='deletePostComment(<?=$id?>);' value='Delete'/>
+                                    </td>
+                                </tr>
+<?php
+                            }
+?>
+                            </table>
+<?php
+                        }
+?>
+                </div> <!-- .entry -->
+            </div> <!-- .section -->
         </div> <!-- #content -->
     </body>
 </html>
 <?php
+            }
+        }
     }
 ?>

+ 87 - 5
www-admin/blog/index.php

@@ -7,6 +7,7 @@
     $con = start_db();
     $server = $proto . $http_host;
     $pserver = substr($server, 0, strpos($http_host, ':')); // public server
+    $lang = "en";
     if (!check_session($con)){
         header("Location: /authentication.php");
         exit(-1);
@@ -22,20 +23,21 @@
         <style>
 <?php
             include $doc_root . "css/ui.css";
-            include $doc_root . "css/home.css";
+            include $doc_root . "css/blog.css";
 ?>
         </style>
         <!-- CSS for mobile version -->
         <style media='(max-width : 990px)'>
 <?php
             include $doc_root . "css/m/ui.css";
-            include $doc_root . "css/m/home.css";
+            include $doc_root . "css/m/blog.css";
 ?>
         </style>
         <!-- Script files -->
         <script type='text/javascript'>
 <?php
             include $doc_root . "script/ui.js";
+            include $doc_root . "script/blog.js";
 ?>
         </script>
     </head>
@@ -45,16 +47,96 @@
 ?>
         <div id='content'>
             <div class='section'>
+                <h3 class='section_title'>Post list</h3>
                 <div class='entry'>
-                    <table>
+                    <table id='post_list'>
                         <tr>
                             <th>Post</th>
                             <th>Detalles</th>
                             <th>Acciones</th>
                         </tr>
 <?php
-                        // TODO: Chaneg for blog
-                        $q_post = mysqli_query($con, "SELECT project.id, permalink, project_type.title AS type, project.title AS title, project.logo AS logo, header, text, license.id AS license, concat(fname, concat(' ', lname)) AS user, visible, comments, (SELECT version_name FROM project_version v, project_version_type WHERE type = id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version, (SELECT title FROM project_version v, project_version_type WHERE type = id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version_type, (SELECT color FROM project_version v, project_version_type WHERE type = id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version_color, (SELECT image FROM project_image WHERE project = project.id) AS image, (SELECT count(image) FROM project_image WHERE project = project.id) AS image_count FROM project, project_type, license, user WHERE project.type = project_type.id AND project.license = license.id AND project.user = user.id;")
+                        $q_post = mysqli_query($con, "SELECT post.id AS id, permalink, title, text, dtime, comments, (SELECT count(id) FROM post_comment WHERE post = post.id) AS comment_count, concat(fname, concat(' ', lname)) AS user, visible, comments, (SELECT image FROM post_image WHERE post = post.id ORDER BY idx LIMIT 1) AS image, (SELECT count(image) FROM post_image WHERE post = post.id) AS image_count FROM post, user WHERE user = user.id");
+                        while ($r_post = mysqli_fetch_array($q_post)){
+                            $title = text($con, $r_post["title"], $lang);
+?>
+                            <tr>
+                                <td class='td_post'>
+                                    <h4>
+                                        <a title='View <?=$title?> on a new tab' target='_blank' href='<?=$pserver?>/blog/<?=$r_post["permalink"]?>'>
+                                            <?=$title?>
+                                        </a>
+                                    </h4>
+                                    <p><?=cut_text(text($con, $r_post["text"], $lang), 200)?></p>
+<?php
+                                    if ($r_post["image_count"] > 0){
+?>
+                                        <img class='post_image' alt='<?=$title?>' title='<?=$title?>' src='<?=$pserver?>/img/blog/x2/<?=$r_post["image"]?>' />
+<?php
+                                        if ($r_post["image_count"] == 2){
+?>
+                                            + other image.
+<?php
+                                        }
+                                        elseif ($r_post["image_count"] > 2){
+                                            $pl = $r_post["image_count"] - 1;
+?>
+                                            + <?=$pl?> other images.
+<?php
+                                        }
+                                    }
+?>
+                                </td>
+                                <td class='td_details'>
+                                    By <?=$r_post["user"]?>.<br/>
+                                    Posted <?=format_date($r_post["dtime"], $lang, true)?>.<br/>
+                                    Visible:
+<?php
+                                    if ($r_post["visible"] == 1){
+?>
+                                        Yes
+<?php
+                                    }
+                                    else{
+?>
+                                        No
+<?php
+                                    }
+?>
+                                    <br/>Comments: <?=$r_post["comment_count"]?><br/>
+                                    Comments allowed:
+<?php
+                                    if ($r_post["comments"] == 1){
+?>
+                                        Yes
+<?php
+                                    }
+                                    else{
+?>
+                                        No
+<?php
+                                    }
+?>
+                                </td>
+                                <td class='td_actions'>
+                                    <input type='button' onclick='managePost(<?=$r_post["id"]?>);' value='Manage / Translate'/>
+                                    <input type='button' onclick='deletePost(<?=$r_post["id"]?>, "<?=$title?>");' value='Delete'/>
+                                    <?php
+                                    if ($r_post["visible"] == 1){
+?>
+                                        <input type='button' onclick='visiblePost(<?=$r_post["id"]?>, "<?=$title?>", 0);' value='Unpublish'/>
+<?php
+                                    }
+                                    else{
+?>
+                                        <input type='button' onclick='visiblePost(<?=$r_post["id"]?>, "<?=$title?>", 1);' value='Publish'/>
+<?php
+                                    }
+?>
+                                </td>
+                            </tr>
+<?php
+                        }
 ?>
                     </table>
                 </div> <!-- .entry -->

+ 5 - 1
www-admin/blog/new.php

@@ -8,9 +8,13 @@
     $server = $proto . $http_host;
     $pserver = substr($server, 0, strpos($http_host, ':')); // public server
     if (!check_session($con)){
+        http_response_code(401);
         header("Location: /authentication.php");
-        exit(-1);
     }
     else{
+        $user = mysqli_real_escape_string($_SESSION['id']);
+        mysqli_query($con, "INSERT INTO post (id, permalink, title, text, user, dtime, visible) VALUES ((SELECT max(id) +1 FROM post p), concat((SELECT max(id) +1 FROM post p), ''), '', '', $user, now(), 0);");
+        $id = mysqli_fetch_array(mysqli_query($con, "SELECT max(id) AS id FROM project;"))["id"];
+        header("Location: /blog/edit.php?p=" + $id);
     }
 ?>

+ 28 - 0
www-admin/blog/uploadimage.php

@@ -0,0 +1,28 @@
+<?php
+    session_start();
+    $http_host = $_SERVER["HTTP_HOST"];
+    $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
+    include $doc_root . "functions.php";
+    $proto = get_protocol();
+    $lang = "en";
+    $con = start_db();
+    $server = $proto . $http_host;
+    $pserver = $proto . substr($http_host, 0, strpos($http_host, ':')); // public server
+    if (!check_session($con)){
+        http_response_code(401);
+        header("Location: /authentication.php");
+    }
+    else{
+        foreach ($_POST as $key => $value){
+            error_log("{$key} = {$value}");
+        }
+        $name = mysqli_real_escape_string($con, $_GET["name"]);
+        $base64string = $_POST["image"];
+        error_log("FILENAME: $name");
+        error_log("PATH: $doc_root../www/img/blog/DEBUG_$name");
+        error_log("B64: $base64string");
+        file_put_contents("$doc_root../www/img/blog/DEBUG_$name", base64_decode($base64string));
+
+        echo("OK");
+    }
+?>

+ 29 - 0
www-admin/blog/visible.php

@@ -0,0 +1,29 @@
+<?php
+    session_start();
+    $http_host = $_SERVER["HTTP_HOST"];
+    $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
+    include $doc_root . "functions.php";
+    $proto = get_protocol();
+    $con = start_db();
+    $server = $proto . $http_host;
+    $pserver = substr($server, 0, strpos($http_host, ':')); // public server
+    if (!check_session($con)){
+        http_response_code(401); // Not logged in: Forbidden.
+    }
+    else{
+        $id = intval(mysqli_real_escape_string($con, $_GET["p"]));
+        $visible = intval(mysqli_real_escape_string($con, $_GET["v"]));
+        if (strlen($id) < 1 || ($visible != 1 && $visible != 0)){
+            http_response_code(400); // No or bad ID, visible not 1 or 0: Bad request.
+        }
+        else{
+            if (mysqli_num_rows(mysqli_query($con, "SELECT id FROM post WHERE id = $id;")) == 0){
+                http_response_code(404); // Unexistent id: Not found.
+            }
+            else{
+                mysqli_query($con, "UPDATE post SET visible = $visible WHERE id = $id;");
+                http_response_code(200); //OK.
+            }
+        }
+    }
+?>

+ 116 - 0
www-admin/css/blog.css

@@ -0,0 +1,116 @@
+/* /blog/index.php */
+
+table#post_list{
+    width: 100%;
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table#post_list th{
+    font-weight: bold;
+    background: linear-gradient(to bottom, #4e9987 0%,#69d8b9 89%,#60caac 97%,#ade8f9 100%);
+    border: 0.1em solid #335533;
+}
+
+table#post_list td{
+    border: 0.1em solid #335533;
+    padding: 0.2em;
+}
+
+table#post_list td.td_post{
+    width: 30%;
+}
+
+table#post_list td.td_post h4{
+    margin: 0.2em;
+}
+
+table#post_list td.td_post h4 img{
+    max-height: 2em;
+    max-width: 2em;
+    vertical-align: middle;
+}
+
+table#post_list td.td_post img.post_image{
+    border: 0.2em solid #335533;
+    border-radius: 0.4em;
+    max-height: 3em;
+    max-width: 3em;
+}
+
+table#post_list td.td_post{
+    width: 50%;
+    font-size: 80%;
+}
+
+table#post_list td.td_actions{
+    width: 20%;
+    text-align: center;
+}
+
+table#post_list td.td_actions input{
+    padding: 0.1em;
+    display: block;
+    margin: auto;
+    width: 90%;
+}
+
+
+/* /blog/edit.php */
+
+div#post_edit hr.separator{
+    margin: 1.5em 20% 1.5em 20%;
+    opacity: 0.5;
+}
+
+div#post_edit div#image_reel{
+    overflow-x: scroll;
+    border: 0.1em solid #003400;
+    border-radius: 0.3em;
+    height: 7em;
+    background-color: #334433;
+    padding: 0.5em;
+}
+
+div#post_edit div#image_reel img{
+    vertical-align: middle;
+    max-height: 5em;
+    max-width: 7em;
+    border: 0.2em solid #003400;
+    border-radius: 0.1em;
+    margin: 0.5em;
+    background-color: #ffffff;
+}
+
+div#post_edit table#comments{
+    border-collapse: collapse;
+    width: 100%;
+}
+
+div#post_edit table#comments td{
+    border-right: 0.1em solid #334433;
+    border-left: 0.1em solid #334433;
+    border-bottom: 0.2em solid #334433;
+    border-top: 0.2em solid #334433;
+}
+
+div#post_edit table#comments td.text{
+    width: 35%;
+}
+
+div#post_edit table#comments td.details{
+    width: 50%;
+    line-height: 2
+}
+
+div#post_edit table#comments td.actions{
+    width: 15%;
+    text-align: center;
+}
+
+div#post_edit table#comments td.actions input{
+    width: 90%;
+    margin: auto;
+    padding: 0.2em;
+    display: block;
+}

+ 114 - 0
www-admin/css/projects.css

@@ -1,3 +1,5 @@
+/* /projects/index.php */
+
 table#project_list{
     width: 100%;
     border-spacing: 0;
@@ -53,3 +55,115 @@ table#project_list td.td_actions input{
     width: 90%;
 }
 
+
+/* /projects/edit.php */
+
+div#project_edit hr.separator{
+    margin: 1.5em 20% 1.5em 20%;
+    opacity: 0.5;
+}
+
+div#project_edit img#icon{
+    vertical-align: middle;
+    width: 4em;
+    height: 4em;
+    border: 0.3em solid #003400;
+    border-radius: 1em;
+}
+
+div#project_edit input#icon_file{
+    width: 0;
+    height: 0;
+    opacity: 0;
+}
+
+div#project_edit div#image_reel{
+    overflow-x: scroll;
+    border: 0.1em solid #003400;
+    border-radius: 0.3em;
+    height: 7em;
+    background-color: #334433;
+    padding: 0.5em;
+}
+
+div#project_edit div#image_reel img{
+    vertical-align: middle;
+    max-height: 5em;
+    max-width: 7em;
+    border: 0.2em solid #003400;
+    border-radius: 0.1em;
+    margin: 0.5em;
+    background-color: #ffffff;
+}
+
+div#project_edit input#new_version{
+    width: 16em;
+    margin: 0.5em auto 2em auto;
+    display: block;
+}
+
+div#project_edit table#versions{
+    border-collapse: collapse;
+    width: 100%;
+}
+
+div#project_edit table#versions td{
+    border-right: 0.1em solid #334433;
+    border-left: 0.1em solid #334433;
+    border-bottom: 0.2em solid #334433;
+    border-top: 0.2em solid #334433;
+}
+
+div#project_edit table#versions td.version_name{
+    width: 15%;
+}
+
+div#project_edit table#versions td.version_details{
+    width: 70%;
+    line-height: 2
+}
+
+div#project_edit table#versions td.version_actions{
+    width: 15%;
+    text-align: center;
+}
+
+div#project_edit table#versions td.version_actions input{
+    width: 90%;
+    margin: auto;
+    padding: 0.2em;
+    display: block;
+}
+
+div#project_edit table#comments{
+    border-collapse: collapse;
+    width: 100%;
+}
+
+div#project_edit table#comments td{
+    border-right: 0.1em solid #334433;
+    border-left: 0.1em solid #334433;
+    border-bottom: 0.2em solid #334433;
+    border-top: 0.2em solid #334433;
+}
+
+div#project_edit table#comments td.text{
+    width: 35%;
+}
+
+div#project_edit table#comments td.details{
+    width: 50%;
+    line-height: 2
+}
+
+div#project_edit table#comments td.actions{
+    width: 15%;
+    text-align: center;
+}
+
+div#project_edit table#comments td.actions input{
+    width: 90%;
+    margin: auto;
+    padding: 0.2em;
+    display: block;
+}

+ 15 - 6
www-admin/css/ui.css

@@ -409,6 +409,7 @@ a.a_button{
     cursor: pointer;
     max-width: 1.2em;
     vertical-align: middle;
+    opacity: 0.5;
 }
 
 /* Field value, editing. */
@@ -444,27 +445,35 @@ a.a_button{
 div#lang_tabs{
     margin-top: 2em;
     margin-bottom: 2em;
+    text-align: center;
 }
 
 div#lang_tabs table{
-    width: 100%;
+    border-collapse: collapse;
+    border: 0.2em solid #1e9957;
+    border-radius: 0.2em;
+    margin: 0.5em auto 1em auto;
 }
 
 div#lang_tabs td{
-    color: #555555;
+    background-color: #ffffff;
+    color: #29d889;
     font-weight: bold;
-    width: 33%;
-    border: 0.1em solid black;
+    width: 7em;
     margin: 0;
+    padding: 0.2em;
+    border: 0.05em solid #1e9957;
 }
 
 div#lang_tabs td.lang_tabs_active{
-    color: #0078ff;
-    border-bottom: 0.1em solid #ffffff;
+    background-color: #29d889;
+    color: #ffffff;
 }
 
 div.content_lang{
     display: none;
+    margin: 0;
+    padding: 0;
 }
 
 div.content_lang_active{

+ 1 - 1
www-admin/functions.php

@@ -208,7 +208,7 @@
             return $text;
         }
         $cut = substr($text, 0, strpos($text, " ", $length));
-        $cut = closeTags($cut);
+        $cut = close_tags($cut);
         if (strlen($cut) == 0){
             $cut = $text;
         }

+ 28 - 0
www-admin/projects/deletecomment.php

@@ -0,0 +1,28 @@
+<?php
+    session_start();
+    $http_host = $_SERVER["HTTP_HOST"];
+    $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
+    include $doc_root . "functions.php";
+    $proto = get_protocol();
+    $con = start_db();
+    $server = $proto . $http_host;
+    $pserver = substr($server, 0, strpos($http_host, ':')); // public server
+    if (!check_session($con)){
+        http_response_code(401); // Not logged in: Forbidden.
+    }
+    else{
+        $id = intval(mysqli_real_escape_string($con, $_GET["i"]));
+        if (strlen($id) < 1){
+            http_response_code(400); // No or bad ID: Bad request.
+        }
+        else{
+            if (mysqli_num_rows(mysqli_query($con, "SELECT id FROM project_comment WHERE id = $id;")) == 0){
+                http_response_code(404); // Unexistent id: Not found.
+            }
+            else{
+                mysqli_query($con, "DELETE FROM project_comment WHERE id = $id;");
+                http_response_code(200); //OK.
+            }
+        }
+    }
+?>

+ 28 - 0
www-admin/projects/deleteversion.php

@@ -0,0 +1,28 @@
+<?php
+    session_start();
+    $http_host = $_SERVER["HTTP_HOST"];
+    $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
+    include $doc_root . "functions.php";
+    $proto = get_protocol();
+    $con = start_db();
+    $server = $proto . $http_host;
+    $pserver = substr($server, 0, strpos($http_host, ':')); // public server
+    if (!check_session($con)){
+        http_response_code(401); // Not logged in: Forbidden.
+    }
+    else{
+        $id = intval(mysqli_real_escape_string($con, $_GET["v"]));
+        if (strlen($id) < 1){
+            http_response_code(400); // No or bad ID: Bad request.
+        }
+        else{
+            if (mysqli_num_rows(mysqli_query($con, "SELECT id FROM project_version WHERE id = $id;")) == 0){
+                http_response_code(404); // Unexistent id: Not found.
+            }
+            else{
+                mysqli_query($con, "DELETE FROM project_version WHERE id = $id;");
+                http_response_code(200); //OK.
+            }
+        }
+    }
+?>

+ 298 - 22
www-admin/projects/edit.php

@@ -4,7 +4,7 @@
     $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
     include $doc_root . "functions.php";
     $proto = get_protocol();
-    $lang = "es";
+    $lang = "en";
     $con = start_db();
     $server = $proto . $http_host;
     $pserver = $proto . substr($http_host, 0, strpos($http_host, ':')); // public server
@@ -39,20 +39,21 @@
         <style>
 <?php
             include $doc_root . "css/ui.css";
-            include $doc_root . "css/home.css";
+            include $doc_root . "css/projects.css";
 ?>
         </style>
         <!-- CSS for mobile version -->
         <style media='(max-width : 990px)'>
 <?php
             include $doc_root . "css/m/ui.css";
-            include $doc_root . "css/m/home.css";
+            include $doc_root . "css/m/projects.css";
 ?>
         </style>
         <!-- Script files -->
         <script type='text/javascript'>
 <?php
             include $doc_root . "script/ui.js";
+            include $doc_root . "script/projects.js";
 ?>
         </script>
          <script src='/script/ckeditor/ckeditor.js'></script>
@@ -62,18 +63,9 @@
         include $doc_root . "header.php";
 ?>
         <div id='content'>
-            <div class='section'>
+            <div class='section' id='project_edit'>
                 <h3 class='section_title'><?=$title?></h3>
                 <div class='entry'>
-                    <span class='bold'>URL:</span>
-                    <?=$pserver?>/
-                    <span class='editable'>
-                        <span class='field_result'><?=$r_project["permalink"]?></span>
-                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
-                        <input class='field_editable' type='text' value='<?=$r_project["permalink"]?>'/>
-                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project", "permalink", <?=$id?>);'/>
-                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
-                    </span>
                     <div id='lang_tabs'>
                         <table>
                             <tr>
@@ -91,33 +83,55 @@
 ?>
                             </tr>
                         </table>
-                    </div>
+                    </div> <!-- #lang_tabs -->
+                    <span class='bold'>URL:</span>
+                    <?=$pserver?>/projects/
+                    <span class='editable'>
+                        <span class='field_result'><?=$r_project["permalink"]?></span>
+                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                        <input class='field_editable' type='text' value='<?=$r_project["permalink"]?>'/>
+                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project", "permalink", <?=$id?>);'/>
+                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                    </span>
+                    <hr class='separator'/>
+                    <span class='bold'>Icon:</span>
+<?php
+                    if (strlen($r_project["icon"]) > 0){
+                        $src = "$pserver/img/projects/x3/$r_image[image]";
+                    }
+                    else{
+                        $src = "$server/img/icon/addimage.png";
+                    }
+?>
+                    <img class='pointer' onClick='selectIcon();' id='icon' src='<?=$src?>' />
+                    <input id='icon_file' type='file' accept='image/*' onchange='changeIcon(event, "<?=$title?>");'>
+                    <hr class='separator'/>
 <?php
                     mysqli_data_seek($q_lang, 0);
-                    $active = 'content_lang_active';
+                    $active = "content_lang_active";
                     while ($r_lang = mysqli_fetch_array($q_lang)){
 ?>
-                        <div id='content_lang_<?=$r_lang["code"]?>' class='content_lang <?=$active?>'>
+                        <div class='content_lang_<?=$r_lang["code"]?> content_lang <?=$active?>'>
                             <div class='editable'>
-                                Title:
+                                <span class='bold'>Title (<?=$r_lang["name"]?>):</span>
                                 <span class='field_result'><?=text($con, $r_project["title"], $r_lang["code"])?></span>
                                 <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
                                 <input class='field_editable' type='text' value='<?=text($con, $r_project["title"], $r_lang["code"])?>'/>
                                 <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_project["title"]?>");'/>
                                 <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
                             </div>
-                            <hr/>
+                            <hr class='separator'/>
                             <div class='editable'>
-                                Summary: 
+                                <span class='bold'>Summary (<?=$r_lang["name"]?>):</span>
                                 <span class='field_result'><?=text($con, $r_project["summary"], $r_lang["code"])?></span>
                                 <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
                                 <input class='field_editable' type='text' value='<?=text($con, $r_project["summary"], $r_lang["code"])?>'/>
                                 <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_project["summary"]?>");'/>
                                 <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
                             </div>
-                            <hr/>
+                            <hr class='separator'/>
                             <div class='editable'>
-                                Text:
+                                <span class='bold'>Text (<?=$r_lang["name"]?>):</span>
                                 <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
                                 <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_project["text"]?>");'/>
                                 <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
@@ -131,8 +145,270 @@
                         $active = '';
                     }
 ?>
-                    </div> <!-- #lang_tabs -->
+                    <hr class='separator'/>
+                    <h4>Images</h4>
+                    <div id='image_reel' class='horizontal_scroll'>
+<?php
+                        $q_image = mysqli_query($con, "SELECT id, image FROM project_image WHERE project = $id;");
+                        while ($r_image = mysqli_fetch_array($q_image)){
+?>
+                            <span id='project_image_<?=$r_image["id"]?>'>
+                                <img alt='<?=$title?>' title='<?=$title?>' src='<?=$pserver?>/img/projects/x3/<?=$r_image["image"]?>' />
+                                <img class='pointer' onClick='deleteImage(<?=$r_image["id"]?>)' alt='Delete image' title='Delete image' src='<?=$server?>/img/icon/cancel.png' />
+                            </span>
+<?php
+                        }
+?>
+                        <span id='project_image_add'>
+                            <img onClick='addImage(<?=$id?>)' alt='Add image' title='Add image' src='<?=$server?>/img/icon/addimage.png' />
+                        </span> <!-- #image_reel -->
+                    </div>
+                    <hr class='separator'/>
+                    <h4>Tags</h4>
+                    TODO
+                    <hr class='separator'/>
+                    <h4>Versions</h4>
+                    <div id='versions'>
+                        <input id='new_version' type='button' value='New version' onClick='newVersion(<?=$id?>);' />
+<?php
+                        // TODO replace id -> project_version: id
+                        $q_version = mysqli_query($con, "SELECT project_version.id AS version, version_code, version_name, type, (SELECT text FROM text WHERE id = project_version_type.title AND lang = '$lang') AS type_name, color AS type_color, project_version.summary AS summary, changelog FROM project_version, project_version_type WHERE type = project_version_type.id AND project = $id ORDER BY version_code;");
+                        while ($r_version = mysqli_fetch_array($q_version)){
+?>
+                            <div class='entry list_enty'>
+                                <table id='versions'>
+                                    <tr>
+                                        <td class='version_name'>
+                                            <span class='editable'>
+                                                <span class='field_result'><?=$r_version["version_name"]?></span>
+                                                <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                                <input class='field_editable' type='text' value='<?=$r_version["version_name"]?>'/>
+                                                <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project_version", "version", "<?=$r_version["id"]?>");'/>
+                                                <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                            </span>
+                                        </td>
+                                        <td class='version_details'>
+                                            <span class='bold'>Version code (fixed):</span> <?=$r_version["version_code"]?>
+                                            <br/>
+                                            <span class='editable'>
+                                                <span class='bold'>Version type:</span>
+                                                <span class='field_result'><?=$r_version["type_name"]?></span>
+                                                <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                                <select class='field_editable' value='<?=$r_version["type"]?>'>
+<?php
+                                                    $q_version_type = mysqli_query($con, "SELECT id, title, color, (SELECT text FROM text WHERE id = project_version_type.title AND lang = '$lang') AS title FROM project_version_type;");
+                                                    while ($r_version_type = mysqli_fetch_array($q_version_type)){
+                                                        if ($r_version_type["id"] == $r_version["type"]){
+                                                            $selected = "selected";
+                                                        }
+                                                        else{
+                                                            $selected = "";
+                                                        }
+                                                        // TODO: Ignoring default 'selected'. It's because display: none?
+?>
+                                                        <option value='<?=$r_version_type["id"]?>' <?=$selected?>><?=$r_version_type["title"]?></option>
+<?php
+                                                    }
+?>
+                                                </select>
+                                                <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project_version", "type", "<?=$r_version["id"]?>");'/>
+                                                <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                            </span>
+<?php
+                                            mysqli_data_seek($q_lang, 0);
+                                            $active = "content_lang_active";
+                                            while ($r_lang = mysqli_fetch_array($q_lang)){
+?>
+                                                <div class='content_lang_<?=$r_lang["code"]?> content_lang <?=$active?>'>
+                                                    <div class='editable'>
+                                                        <span class='bold'>Summary (<?=$r_lang["name"]?>):</span>
+                                                        <span class='field_result'><?=text($con, $r_version["summary"], $r_lang["code"])?></span>
+                                                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                                        <input class='field_editable' type='text' value='<?=text($con, $r_project["summary"], $r_lang["code"])?>'/>
+                                                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_version["summary"]?>");'/>
+                                                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                                    </div>
+                                                </div>
+                                                <div class='content_lang_<?=$r_lang["code"]?> content_lang <?=$active?>'>
+                                                    <div class='editable'>
+                                                        <span class='bold'>Changelog (<?=$r_lang["name"]?>):</span>
+                                                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "text", "<?=$r_lang["code"]?>", "<?=$r_version["changelog"]?>");'/>
+                                                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                                        <p class='field_result'><?=text($con, $r_version["changelog"], $r_lang["code"])?></p>
+                                                        <textarea class='field_editable'><?=text($con, $r_project["summary"], $r_lang["code"])?></textarea>
+                                                    </div>
+                                                </div>
+<?php
+                                                $active = "";
+                                            }
+                                            if ($r_project["visible"] == 1){
+                                                $v = "Yes";
+                                                $selected1 = "selected";
+                                                $selected0 = "";
+                                            }
+                                            else{
+                                                $v = "No";
+                                                $selected1 = "";
+                                                $selected0 = "selected";
+                                            }
+?>
+                                            <div class='editable'>
+                                                <span class='bold'>Visible:</span>
+                                                <span class='field_result'><?=$v?></span>
+                                                <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                                <select class='field_editable'>
+                                                    <option value='1' <?=$selected1?>>Yes</option>
+                                                    <option value='0' <?=$selected0?>>No</option>
+                                                </select>
+                                                <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project_version", "visible", "<?=$r_version["id"]?>");'/>
+                                                <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                            </div>
 
+                                        </td>
+                                        <td class='version_actions'>
+                                            <input type='button' onclick='deleteVersion(<?=$r_version["id"]?>, "<?=$title?>");' value='Delete'/>
+                                        </td>
+                                    </tr>
+                                </table>
+                            </div> <!-- .entry -->
+<?php
+                        }
+?>
+                    </div> <!-- #versions -->
+                    <hr class='separator'/>
+                    <h4>Settings</h4>
+<?php
+                    if ($r_project["visible"] == 1){
+                        $v = "Yes";
+                        $selected1 = "selected";
+                        $selected0 = "";
+                    }
+                    else{
+                        $v = "No";
+                        $selected1 = "";
+                        $selected0 = "selected";
+                    }
+?>
+                    <div class='editable'>
+                        <span class='bold'>Visible:</span>
+                        <span class='field_result'><?=$v?></span>
+                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                        <select class='field_editable'>
+                            <option value='1' <?=$selected1?>>Yes</option>
+                            <option value='0' <?=$selected0?>>No</option>
+                        </select>
+                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project", "visible", "<?=$id?>");'/>
+                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                    </div>
+<?php
+                    if ($r_project["comments"] == 1){
+                        $v = "Yes";
+                        $selected1 = "selected";
+                        $selected0 = "";
+                    }
+                    else{
+                        $v = "No";
+                        $selected1 = "";
+                        $selected0 = "selected";
+                    }
+?>
+                    <div class='editable'>
+                        <span class='bold'>Comments enabled:</span>
+                        <span class='field_result'><?=$v?></span>
+                        <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                        <select class='field_editable'>
+                            <option value='1' <?=$selected1?>>Yes</option>
+                            <option value='0' <?=$selected0?>>No</option>
+                        </select>
+                        <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project", "comments", "<?=$id?>");'/>
+                        <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                    </div>
+                    <input type='button' onclick='deleteProject(<?=$id?>, "<?=$title?>");' value='Delete project'/>
+                    <h4>Comments</h4>
+<?php
+                        $q_comment = mysqli_query($con, "SELECT project_comment.id AS id, (SELECT version_name FROM project_version WHERE id = project_comment.version) AS version, text, dtime, user, username, lang, (SELECT name FROM lang WHERE code = project_comment.lang) AS lang_name, approved, ip, browser, os, uagent FROM project_comment, stat_visit WHERE stat_visit.id = visit AND project = $id;");
+                        if (mysqli_num_rows($q_comment) == 0){
+?>
+                            <span>No comments yet</span>
+<?php
+                        }
+                        else{
+?>
+                            <table id='comments'>
+<?php
+                            while ($r_comment = mysqli_fetch_array($q_comment)){
+?>
+                                <tr>
+                                    <td class='text'>
+                                        <p><?=$r_comment["text"]?></p>
+                                    </td>
+                                    <td class='details'>
+                                        On <?=format_date($r_comment["dtime"], $lang, true)?>
+                                        <br/>
+                                        For version <?=$r_comment["version"]?>
+                                        <br/>
+<?php
+                                        if (strlen($r_comment["user"]) > 0){
+                                            $q_user = mysqli_query($con, "SELECT concat(fname, concat(' ', lname)) AS name, username FROM user WHERE id = $r_comment[user];");
+                                            $r_user = mysqli_fetch_array($q_user);
+?>
+                                            By <?=$r_user["name"]?> (<span class='bold'><?=$r_user["username"]?></span>)
+<?php
+                                        }
+                                        else{
+?>
+                                            By <?=$r_comment["username"]?>
+<?php
+                                        }
+                                        if (strlen($r_comment["lang_name"]) > 0){
+                                            $strlang = $r_comment["lang_name"];
+                                        }
+                                        else{
+                                            $strlang = $r_comment["lang"];
+                                        }
+                                        if (file_exists($doc_root . "img/lang/" . $r_comment["lang"] . ".gif")){
+                                            $imgpath = $doc_root . "img/lang/" . $r_comment["lang"] . ".gif";
+                                            $strlang = $strlang . " <img class='lang' title='$r_comment[lang]' alt='$r_comment[lang]' src='$server/$imgpath' />";
+                                        }
+?>
+                                        <br/>
+                                        Language: <?=$strlang?>
+<?php
+                                        if ($r_project["visible"] == 1){
+                                            $v = "Yes";
+                                            $selected1 = "selected";
+                                            $selected0 = "";
+                                        }
+                                        else{
+                                            $v = "No";
+                                            $selected1 = "";
+                                            $selected0 = "selected";
+                                        }
+?>
+                                        <div class='editable'>
+                                            Approved:
+                                            <span class='field_result'><?=$v?></span>
+                                            <img class='button_edit' src='<?=$server?>/img/icon/edit.png' onclick='enableEdit(this);'/>
+                                            <select class='field_editable'>
+                                                <option value='1' <?=$selected1?>>Yes</option>
+                                                <option value='0' <?=$selected0?>>No</option>
+                                            </select>
+                                            <img class='button_save' src='<?=$server?>/img/icon/save.png' onclick='saveEdit(this, "project_comment", "approved", "<?=$r_comment["id"]?>");'/>
+                                            <img class='button_cancel' src='<?=$server?>/img/icon/cancel.png' onclick='cancelEdit(this);'/>
+                                        </div>
+                                    </td>
+                                    <td class='actions'>
+                                        <input type='button' onclick='deleteProjectComment(<?=$id?>);' value='Delete'/>
+                                    </td>
+                                </tr>
+<?php
+                            }
+?>
+                            </table>
+<?php
+                        }
+?>
                 </div> <!-- .entry -->
             </div> <!-- .section -->
         </div> <!-- #content -->

+ 2 - 3
www-admin/projects/index.php

@@ -56,9 +56,9 @@
                             <th>Actions</th>
                         </tr>
 <?php
-                        $q_project = mysqli_query($con, "SELECT project.id, permalink, project_type.title AS type, project.title AS title, project.logo AS logo, header, text, license.id AS license, concat(fname, concat(' ', lname)) AS user, visible, comments, (SELECT count(id) FROM project_comment WHERE project = project.id) AS comment_count, (SELECT version_name FROM project_version v, project_version_type WHERE type = id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version, (SELECT dtime FROM project_version v WHERE  v.project = project.id ORDER BY version_code DESC LIMIT 1) AS dtime, (SELECT title FROM project_version v, project_version_type WHERE type = id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version_type, (SELECT color FROM project_version v, project_version_type WHERE type = id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version_color, (SELECT image FROM project_image WHERE project = project.id) AS image, (SELECT count(image) FROM project_image WHERE project = project.id) AS image_count FROM project, project_type, license, user WHERE project.type = project_type.id AND project.license = license.id AND project.user = user.id;");
+                        $q_project = mysqli_query($con, "SELECT project.id, permalink, project_type.title AS type, project.title AS title, project.logo AS logo, header, text, license.id AS license, concat(fname, concat(' ', lname)) AS user, visible, comments, (SELECT count(id) FROM project_comment WHERE project = project.id) AS comment_count, (SELECT version_name FROM project_version v, project_version_type WHERE type = v.id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version, (SELECT dtime FROM project_version v WHERE  v.project = project.id ORDER BY version_code DESC LIMIT 1) AS dtime, (SELECT title FROM project_version v, project_version_type WHERE type = v.id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version_type, (SELECT color FROM project_version v, project_version_type WHERE type = v.id AND v.project = project.id ORDER BY version_code DESC LIMIT 1) AS version_color, (SELECT image FROM project_image WHERE project = project.id) AS image, (SELECT count(image) FROM project_image WHERE project = project.id ORDER BY idx LIMIT 1) AS image_count FROM project, project_type, license, user WHERE project.type = project_type.id AND project.license = license.id AND project.user = user.id;");
                         while ($r_project = mysqli_fetch_array($q_project)){
-                            $title = text($con, $r_project["title"],$lang);
+                            $title = text($con, $r_project["title"], $lang);
 ?>
                             <tr>
                                 <td class='td_project'>
@@ -133,7 +133,6 @@
                                 <td class='td_actions'>
                                     <input type='button' onclick='manageProject(<?=$r_project["id"]?>);' value='Manage / Translate'/>
                                     <input type='button' onclick='deleteProject(<?=$r_project["id"]?>, "<?=$title?>");' value='Delete'/>
-                                    <input type='button' onclick='TODO' value='Moderate comments'/>
                                     <?php
                                     if ($r_project["visible"] == 1){
 ?>

+ 5 - 1
www-admin/projects/new.php

@@ -8,9 +8,13 @@
     $server = $proto . $http_host;
     $pserver = substr($server, 0, strpos($http_host, ':')); // public server
     if (!check_session($con)){
+        http_response_code(401);
         header("Location: /authentication.php");
-        exit(-1);
     }
     else{
+        $user = mysqli_real_escape_string($_SESSION['id']);
+        mysqli_query($con, "INSERT INTO project (id, permalink, type, title, user, visible) VALUES ((SELECT max(id) +1 FROM project p), concat((SELECT max(id) +1 FROM project p), ''), 'M', 'NULL', $user, 0);");
+        $id = mysqli_fetch_array(mysqli_query($con, "SELECT max(id) AS id FROM project;"))["id"];
+        header("Location: /projects/edit.php?p=" + $id);
     }
 ?>

+ 28 - 0
www-admin/projects/uploadimage.php

@@ -0,0 +1,28 @@
+<?php
+    session_start();
+    $http_host = $_SERVER["HTTP_HOST"];
+    $doc_root = $_SERVER["DOCUMENT_ROOT"] . "/";
+    include $doc_root . "functions.php";
+    $proto = get_protocol();
+    $lang = "en";
+    $con = start_db();
+    $server = $proto . $http_host;
+    $pserver = $proto . substr($http_host, 0, strpos($http_host, ':')); // public server
+    if (!check_session($con)){
+        http_response_code(401);
+        header("Location: /authentication.php");
+    }
+    else{
+        foreach ($_POST as $key => $value){
+            error_log("{$key} = {$value}");
+        }
+        $name = mysqli_real_escape_string($con, $_GET["name"]);
+        $base64string = $_POST["image"];
+        error_log("FILENAME: $name");
+        error_log("PATH: $doc_root../www/img/projects/DEBUG_$name");
+        error_log("B64: $base64string");
+        file_put_contents("$doc_root../www/img/projects/DEBUG_$name", base64_decode($base64string));
+
+        echo("OK");
+    }
+?>

+ 69 - 0
www-admin/script/blog.js

@@ -0,0 +1,69 @@
+function managePost(id){
+    window.location.href = "/blog/edit.php?p=" + id;
+}
+
+function deletePost(id, title){
+    dialog("confirm", "Delete post", "Do you really want to delete the post '" + title + "'?<br/><br/>There is no way to undo this action. You can also unpublish the post instead of deleting it.", function (confirmed) {
+        if (confirmed) {
+            var xmlhttp;
+            if (window.XMLHttpRequest){
+                xmlhttp = new XMLHttpRequest();
+            }
+            xmlhttp.onreadystatechange=function(){
+                if (xmlhttp.readyState == 4){
+                    if (xmlhttp.status == 200){
+                        location.reload();
+                    }
+                    else{
+                        dialog("alert", "ERROR", "Error deleting the post '" + title + "'.", null);
+                    }
+                }
+            }
+            xmlhttp.open("GET","/blog/delete.php?p=" + id, true);
+            xmlhttp.send();
+        }
+    });
+}
+
+
+function deleteComment(id){
+    dialog("confirm", "Delete version", "Do you really want to delete this comment?<br/><br/>There is no way to undo this action. You can also disapprove the comment instead of deleting it.", function (confirmed) {
+        if (confirmed) {
+            var xmlhttp;
+            if (window.XMLHttpRequest){
+                xmlhttp = new XMLHttpRequest();
+            }
+            xmlhttp.onreadystatechange=function(){
+                if (xmlhttp.readyState == 4){
+                    if (xmlhttp.status == 200){
+                        location.reload();
+                    }
+                    else{
+                        dialog("alert", "ERROR", "Error deleting the comment.", null);
+                    }
+                }
+            }
+            xmlhttp.open("GET","/blog/deletecomment.php?i=" + id, true);
+            xmlhttp.send();
+        }
+    });
+}
+
+function visiblePost(id, title, visible){
+    var xmlhttp;
+    if (window.XMLHttpRequest){
+        xmlhttp = new XMLHttpRequest();
+    }
+    xmlhttp.onreadystatechange=function(){
+        if (xmlhttp.readyState == 4){
+            if (xmlhttp.status == 200){
+                location.reload();
+            }
+            else{
+                dialog("alert", "ERROR", "Error changing visibility of the post '" + title + "'.", null);
+            }
+        }
+    }
+    xmlhttp.open("GET","/post/visible.php?p=" + id + "&v=" + visible, true);
+    xmlhttp.send();
+}

+ 91 - 0
www-admin/script/projects.js

@@ -25,6 +25,52 @@ function deleteProject(id, title){
     });
 }
 
+function deleteVersion(id, title){
+    dialog("confirm", "Delete version", "Do you really want to delete the version '" + title + "'?<br/><br/>There is no way to undo this action. You can also unpublish the version instead of deleting it.", function (confirmed) {
+        if (confirmed) {
+            var xmlhttp;
+            if (window.XMLHttpRequest){
+                xmlhttp = new XMLHttpRequest();
+            }
+            xmlhttp.onreadystatechange=function(){
+                if (xmlhttp.readyState == 4){
+                    if (xmlhttp.status == 200){
+                        location.reload();
+                    }
+                    else{
+                        dialog("alert", "ERROR", "Error deleting the version '" + title + "'.", null);
+                    }
+                }
+            }
+            xmlhttp.open("GET","/projects/deleteversion.php?v=" + id, true);
+            xmlhttp.send();
+        }
+    });
+}
+
+function deleteComment(id){
+    dialog("confirm", "Delete version", "Do you really want to delete this comment?<br/><br/>There is no way to undo this action. You can also disapprove the comment instead of deleting it.", function (confirmed) {
+        if (confirmed) {
+            var xmlhttp;
+            if (window.XMLHttpRequest){
+                xmlhttp = new XMLHttpRequest();
+            }
+            xmlhttp.onreadystatechange=function(){
+                if (xmlhttp.readyState == 4){
+                    if (xmlhttp.status == 200){
+                        location.reload();
+                    }
+                    else{
+                        dialog("alert", "ERROR", "Error deleting the comment.", null);
+                    }
+                }
+            }
+            xmlhttp.open("GET","/projects/deletecomment.php?i=" + id, true);
+            xmlhttp.send();
+        }
+    });
+}
+
 function visibleProject(id, title, visible){
     var xmlhttp;
     if (window.XMLHttpRequest){
@@ -43,3 +89,48 @@ function visibleProject(id, title, visible){
     xmlhttp.open("GET","/projects/visible.php?p=" + id + "&v=" + visible, true);
     xmlhttp.send();
 }
+
+function selectIcon(){
+    document.getElementById("icon_file").click();
+}
+
+function changeIcon(event, title){
+    console.log("changeIcon 1");
+    var frame = document.getElementById("icon");
+    var file = event.target.files[0];
+    var reader = new FileReader();
+    var httpPost = new XMLHttpRequest();
+    console.log("changeIcon 2");
+    reader.onloadend = function() {
+        console.log("changeIcon LOADEND 1");
+        console.log('RESULT', reader.result);
+        var data = "image=IVV" + reader.result;
+        var path = "/projects/uploadimage.php?name=" + title + "-icon.png";
+        console.log("changeIcon LOADEND 2");
+        httpPost.open("POST", path, true);
+        console.log("changeIcon LOADEND 3");
+        httpPost.setRequestHeader('Content-Type', 'x-www-form-urlencoded');
+        httpPost.setRequestHeader("Content-length", data.length);
+        console.log("changeIcon LOADEND 4");
+        httpPost.send(data);
+        console.log("changeIcon LOADEND 5 - END");
+    }
+    console.log("changeIcon 3");
+    var b64 = reader.readAsDataURL(file);
+    //var b64 = reader.result;
+    console.log("changeIcon 4");
+    httpPost.onreadystatechange = function(err) {
+        console.log("changeIcon REQCHANGE");
+        if (httpPost.readyState == 4 && httpPost.status == 200){
+            console.log("changeIcon REQOK");
+            frame.src = window.URL.createObjectURL(event.target.files[0]);
+            console.log(httpPost.responseText);
+        }
+        else {
+            console.log("changeIcon REQ-ERROR");
+            console.log(err);
+        }
+    };
+    console.log("changeIcon 5 - END");
+    
+}

+ 18 - 9
www-admin/script/ui.js

@@ -29,27 +29,36 @@ function showHeader(header, from){
  * @param lang Two letter language code. 'es', 'en' or 'eu'.
  */
 function showLanguage(lang){
+    var en = document.getElementsByClassName('content_lang_en');
+    var es = document.getElementsByClassName('content_lang_es');
+    var eu = document.getElementsByClassName('content_lang_eu');
     switch (lang){
         case 'es':
-            document.getElementById('content_lang_es').style.display = 'block';
-            document.getElementById('content_lang_eu').style.display = 'none';
-            document.getElementById('content_lang_en').style.display = 'none';
+            for (var i = 0; i < en.length; ++i) {
+                en[i].style.display = 'none';
+                es[i].style.display = 'block';
+                eu[i].style.display = 'none';
+            }
             document.getElementById('lang_tab_es').classList.add("lang_tabs_active");
             document.getElementById('lang_tab_eu').classList.remove("lang_tabs_active");
             document.getElementById('lang_tab_en').classList.remove("lang_tabs_active");
             break;
         case 'eu':
-            document.getElementById('content_lang_es').style.display = 'none';
-            document.getElementById('content_lang_eu').style.display = 'block';
-            document.getElementById('content_lang_en').style.display = 'none';
+            for (var i = 0; i < en.length; ++i) {
+                en[i].style.display = 'none';
+                es[i].style.display = 'none';
+                eu[i].style.display = 'block';
+            }
             document.getElementById('lang_tab_es').classList.remove("lang_tabs_active");
             document.getElementById('lang_tab_eu').classList.add("lang_tabs_active");
             document.getElementById('lang_tab_en').classList.remove("lang_tabs_active");
             break;
         case 'en':
-            document.getElementById('content_lang_es').style.display = 'none';
-            document.getElementById('content_lang_eu').style.display = 'none';
-            document.getElementById('content_lang_en').style.display = 'block';
+            for (var i = 0; i < en.length; ++i) {
+                en[i].style.display = 'block';
+                es[i].style.display = 'none';
+                eu[i].style.display = 'none';
+            }
             document.getElementById('lang_tab_es').classList.remove("lang_tabs_active");
             document.getElementById('lang_tab_eu').classList.remove("lang_tabs_active");
             document.getElementById('lang_tab_en').classList.add("lang_tabs_active");

+ 1 - 1
www/functions.php

@@ -297,7 +297,7 @@
             return $text;
         }
         $cut = substr($text, 0, strpos($text, " ", $length));
-        $cut = closeTags($cut);
+        $cut = close_tags($cut);
         if (strlen($cut) == 0){
             $cut = $text;
         }