38 Commits 934ac2d285 ... 1ecf67acf8

Author SHA1 Message Date
  paul 1ecf67acf8 mustard: notifs: Aggiunto timestamp alle notifiche. 4 years ago
  paul 14200ea5fd mustard: notifs: Aggiunto bottone per invertire la selezione. 4 years ago
  paul df9782ab1e mustard: Aggiunti controlli per gestione in massa delle notifiche. 4 years ago
  paul 1a66024907 mustard: theme: Aggiunte regole per notifs.php. 4 years ago
  paul aefa4ebf54 mustard: notifs: Refactor layout pagina gestione notifiche. 4 years ago
  paul a9e7bfb132 mustard: notifs: Aggiunti controlli per cancellare le notifiche. 4 years ago
  paul 3c7756f76f mustard: notifs.js: Aggiunta funzione per cancellare le notifiche. 4 years ago
  paul 7314ce63d1 mustard: notifsh: Aggiunto endpoint per cancellare le notifiche. 4 years ago
  paul 6778516add mustard: notifs: Aggiunti controlli per la lista delle notifiche. 4 years ago
  paul c44d3b0d6e mustard: theme: Aggiunte regole per i controlli di notifs.php 4 years ago
  paul e04853ce5f mustard: notifs: Aggiunto bottone per leggere le notifiche. 4 years ago
  paul 44db4b4aa2 mustard: theme: Aggiunta regola per le notifiche già lette. 4 years ago
  paul db3fd262dd js: notifs: Se una notifica viene letta aggiornane la classe. 4 years ago
  paul 0198c3b523 Sposta flag mail.add_x_header. 4 years ago
  paul 53b5294fb0 mustard: theme: Aggiunte regole per notifs.php. 4 years ago
  paul 5fd367c26a notifs: Nuova pagina. 4 years ago
  paul 9c1a3f4068 include: notifs: Ritorna un array di notifiche. 4 years ago
  paul a33ac2d130 menu: Aggiunto link a "notifs.php". 4 years ago
  pezcurrel 16e6324051 Aggiunta colonna 'Deleted' alla tabella 'Notifications' 4 years ago
  pezcurrel a7f9306aec Aggiornato. 4 years ago
  pezcurrel 9569802669 Sistemato un bacone. 4 years ago
  pezcurrel 0cdf966ec8 Aggiunta la possibilità di passargli opzioni da riga di comando; sistemato un bacone; eliminata una funzione non utilizzata. 4 years ago
  pezcurrel 8d276bcd94 ... 4 years ago
  paul 934ac2d285 mustard: theme: Aggiunte regole per notifs.php. 4 years ago
  paul 9e05c76d68 mustard: notifs: Refactor layout pagina gestione notifiche. 4 years ago
  paul 81c3fd2722 mustard: notifs: Aggiunti controlli per cancellare le notifiche. 4 years ago
  paul 33e0f335a8 mustard: notifs.js: Aggiunta funzione per cancellare le notifiche. 4 years ago
  paul 888235e5bf mustard: notifsh: Aggiunto endpoint per cancellare le notifiche. 4 years ago
  paul 9e34b1091e mustard: notifs: Aggiunti controlli per la lista delle notifiche. 4 years ago
  paul f9e10f906b mustard: theme: Aggiunte regole per i controlli di notifs.php 4 years ago
  paul 970c8d64c1 mustard: notifs: Aggiunto bottone per leggere le notifiche. 4 years ago
  paul 8a89e2ad96 mustard: theme: Aggiunta regola per le notifiche già lette. 4 years ago
  paul 6bdb2c865b js: notifs: Se una notifica viene letta aggiornane la classe. 4 years ago
  paul 6b459c252b Sposta flag mail.add_x_header. 4 years ago
  paul c20f69895f mustard: theme: Aggiunte regole per notifs.php. 4 years ago
  paul d5ccc9bd20 notifs: Nuova pagina. 4 years ago
  paul 06c208bb71 include: notifs: Ritorna un array di notifiche. 4 years ago
  paul 4c639131a7 menu: Aggiunto link a "notifs.php". 4 years ago

+ 66 - 25
web/mustard/crawler/crawler.php

@@ -61,42 +61,83 @@ $opts=array(
 	'log'=>false,
 	'jsonfp'=>__DIR__.'/instances.json',
 	'jsonwrite'=>false,
-	'peersfp'=>'peers'
+	'peersfp'=>__DIR__.'/peers'
 );
 
-use function mysqli_real_escape_string as myesc;
-
-function tosec($str) {
-	if (preg_match('/^([0-9]+)([smogSMA]?)/',$str,$buf)===1) {
-		switch ($buf[2]) {
-			case '':
-			case 's':
-			return($buf[1]);
+$help='crawler.php
+ DESCRIZIONE
+  Popola/aggiorna il database di mastostart con i dati che riesce
+  a recuperare da una lista di istanze composta da quelle già presenti
+  nel database più quelle di un file specificabile (tipicamente il file
+  di output di peerscrawl.php).
+  È possibile fermarne l’esecuzione per riprenderla in un secondo tempo:
+  il programma genera, durante l’esecuzione, una lista delle istanze che
+  deve controllare («instances.job») e un file in cui viene salvata l’ultima
+  istanza controllata e altri dati; per riprendere l’esecuzione là dove
+  era stata lasciata basta lanciare nuovamente il programma; per evitare
+  che il programma riprenda da dove era arrivato durante l’esecuzione
+  precedente basta cancellare i due file di cui sopra.
+ SYNOPSIS
+  peerscrawl.php [options]
+ OPTIONS
+  -p, --peersfp <file>
+   Definisce il file da cui caricare la lista delle istanze di cui cercare
+   di recuperare i dati. Nota: questa opzione è ininfluente se il programma
+   viene lanciato per riprendere un’esecuzione precedente interrotta.
+   DEFAULT: «'.$opts['peersfp'].'»
+  -t, --timeout <secondi>
+   Definisce il timeout in secondi di ogni tentativo di connessione.
+   DEFAULT: «'.$opts['timeout'].'»
+  -l, --log
+   Attiva il logging dell’output nel file «crawler.php» nella stessa
+   directory di crawler.php.
+  -j, --jsonwrite
+   Attiva la scrittura di un file «instances.json» nella stessa directory
+   di crawler.php, contenente tutti i dati recuperati da tutte le istanze.
+
+  This program comes with ABSOLUTELY NO WARRANTY; for details see the source.
+  This is free software, and you are welcome to redistribute it under
+  certain conditions; see <http://www.gnu.org/licenses/> for details.'.N;
+
+for ($i=1; $i<$argc; $i++) {
+	if (substr($argv[$i],0,1)=='-') {
+		switch($argv[$i]) {
+			case '-p':
+			case '--peersfp':
+			if ($i+1>=$argc || !file_exists($argv[$i+1]) || !is_file($argv[$i+1]) || !is_readable($argv[$i+1]))
+				mexit('L’opzione «'.$argv[$i].'» richiede come parametro un file esistente e leggibile (usa «-h» per vedere la guida).'.N,1);
+			$i++;
+			$opts['peersfp']=$argv[$i];
 			break;
-			case 'm':
-			return($buf[1]*60);
+			case '-t':
+			case '--timeout':
+			if ($i+1>=$argc || preg_match('/[0-9]+/',$argv[$i+1])!==1)
+				mexit('L’opzione «'.$argv[$i].'» richiede un parametro numerico (usa «-h» per vedere la guida).'.N,1);
+			$i++;
+			$opts['timeout']=$argv[$i]+0;
 			break;
-			case 'o':
-			return($buf[1]*60*60);
+			case '-l':
+			case '--log':
+			$opts['log']=true;
+			$i++;
 			break;
-			case 'g':
-			return($buf[1]*60*60*24);
+			case '-j':
+			case '--jsonwrite':
+			$opts['jsonwrite']=true;
 			break;
-			case 'S':
-			return($buf[1]*60*60*24*7);
+			case '-h':
+			case '--help':
+			mexit($help,0);
 			break;
-			case 'M':
-			return($buf[1]*60*60*24*30);
-			break;
-			case 'A':
-			return($buf[1]*60*60*24*365);
+			default:
+			mexit('L’opzione «'.$argv[$i].'» è sconosciuta (usa «-h» per vedere la guida).'.N,1);
 			break;
 		}
-	} else {
-		return(false);
 	}
 }
 
+use function mysqli_real_escape_string as myesc;
+
 function mexit($msg,$code) {
 	global $link, $jsonf, $logf;
 	lecho($msg);
@@ -113,7 +154,7 @@ function lecho($msg,$logonly=false) {
 	global $opts, $logf;
 	if (!$logonly)
 		echo($msg);
-	if ($opts['log'])
+	if ($opts['log'] && $logf!==false)
 		fwrite($logf,$msg);
 }
 

+ 1 - 1
web/mustard/crawler/peerscrawl.php

@@ -22,7 +22,7 @@ define('N',"\n");
 
 $opts=array(
 	'startinst'=>'mastodon.social',
-	'peersfp'=>'peers',
+	'peersfp'=>__DIR__.'/peers',
 	'restore'=>false,
 	'excludefp'=>null
 );

+ 3 - 1
web/mustard/dafa.txt

@@ -13,12 +13,14 @@
 * niente virtualhost, spostare mastostart nella docroot di default di apache, così che per vederlo basti andare su 172.17.0.2, senza dover toccare /etc/hosts dell'host
 * aggiornare update.sh così che rifletta il cambiamento al punto precedente
 
+- transazioni, dove appropriato
+- dispinst.php: setlocale: il nome della locale è sempre quello su tutti i sistemi?
 ! invite.php: una modalità di test che non manda le mail ma crea gli account "guest"
 - "stabilizzare" $cjrand in glob.php a una versione
 ? tutto: ristrutturare il layout directory?
 * vedere un po' se è possibile determinare quanta ram sugge il crawler, in modo da poter dare indicazioni più precise in INSTALL --- usare memory_get_peak_usage(true) --- fatto per ora con altro metodo
 * in attesa dei template di Ca_Gi, nei template per le mail dichiarare comunque già che un requisito è moderazione attiva contro contenuti fascisti-razzisti-sessisti
-- crawler.php: possibilità di passargli le opzioni da riga di comando
+* crawler.php: possibilità di passargli le opzioni da riga di comando
 - peerscrawl.php: rendere opzionale il check su google.com, spiegare però bene a cosa serve
 * viewinst.php
 - pagina gestione accounts

+ 64 - 9
web/mustard/js/notifs.js.php

@@ -47,7 +47,7 @@ function markdeleted(notif) {
     xhr.send();
     xhr.onload = function () {
         if (xhr.response['deleted']) {
-            notif.remove();
+            notif.classList.add("deleted");
         } else {
             alert("Il server non ha potuto cancellare la notifica '" + notif.text + "'");
         }
@@ -57,16 +57,71 @@ function markdeleted(notif) {
     };
 }
 
-function applyAllSelected(fun) {
-    let notifs = document.querySelectorAll("div#notifs-list > div");
-    notifs.forEach(function (notif) {
-        let checkbox = notif.querySelector("input.seen-checkbox");
-        if (checkbox.checked) {
-            fun(notif);
-        }});
+function getAliveNotifs(){
+    let notifs = Array.from(document.querySelectorAll("div.notif"));
+    return notifs.filter(n => !(Array.from(n.classList).includes("deleted")))
 }
 
-lmt=<?php echo($notifs['lastmicrotime']); ?>;
+function getAliveCheckboxes() {
+    let notifs = getAliveNotifs();
+    return notifs.map(n => n.querySelector("input.seen-checkbox"))
+}
+
+function readSelected() {
+    let selected = getSelectedNotifs()
+    let request = {
+        "act": "massread",
+        "ids": selected.map(div => div.id.replace(/^notif-([0-9]+)$/, '$1'))
+    }
+    let xhr = new XMLHttpRequest();
+    xhr.open('POST', 'notifs.php');
+    xhr.setRequestHeader('Content-type','application/json');
+    xhr.responseType = 'json';
+    xhr.send(JSON.stringify(request));
+    xhr.onload = function () {
+        if (xhr.response['done']) {
+            selected.forEach(notif => {
+                        notif.classList.remove("unseen");
+                        notif.classList.add("seen");
+                    })
+        } else {
+            alert("Il server non ha potuto completare la richiesta:\n" + xhr.response["error"]);
+        }
+    };
+    xhr.onerror = function () {
+        alert('La richiesta è fallita.');
+    };
+}
+
+function deleteSelected() {
+    let selected = getSelectedNotifs()
+    let request = {
+        "act": "massdelete",
+        "ids": selected.map(div => div.id.replace(/^notif-([0-9]+)$/, '$1'))
+    }
+    let xhr = new XMLHttpRequest();
+    xhr.open('POST', 'notifs.php');
+    xhr.setRequestHeader('Content-type','application/json');
+    xhr.responseType = 'json';
+    xhr.send(JSON.stringify(request));
+    xhr.onload = function () {
+        if (xhr.response['done']) {
+            selected.forEach(notif => notif.classList.add("deleted"));
+        } else {
+            alert("Il server non ha potuto completare la richiesta:\n" + xhr.response["error"]);
+        }
+    };
+    xhr.onerror = function () {
+        alert('La richiesta è fallita.');
+    };
+}
+
+function getSelectedNotifs() {
+    let notifs = getAliveNotifs();
+    return notifs.filter(notif => notif.querySelector("input.seen-checkbox").checked)
+}
+
+lmt =<?php echo($notifs['lastmicrotime']); ?>;
 chunk=0;
 end=false;
 loading=false;

+ 86 - 19
web/mustard/notifs.php

@@ -20,6 +20,51 @@ function hspech($str)
     return (htmlspecialchars($str, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
 }
 
+function are_valid_ids($ids)
+{
+    if (count($ids) <= 0) return false;
+    foreach ($ids as $id) {
+        if (!(preg_match('/^[0-9]+$/', $id) === 1)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER["CONTENT_TYPE"] === "application/json") {
+    $response = array(
+        "done" => true,
+        "error" => ""
+    );
+    $body = json_decode(file_get_contents('php://input'), true);
+    if (array_key_exists('act', $body) &&
+        array_key_exists('ids', $body) &&
+        are_valid_ids($body["ids"])) {
+        switch ($body['act']) {
+            case "massread":
+                mysqli_query($link, 'UPDATE Notifications SET Seen=1 WHERE ID in (' . implode(", ", $body["ids"]) . ')')
+                or muoribene(mysqli_error($link), true);
+                break;
+            case "massdelete":
+                mysqli_query($link, 'UPDATE Notifications SET Deleted=1 WHERE ID in (' . implode(", ", $body["ids"]) . ')')
+                or muoribene(mysqli_error($link), true);
+                break;
+            default:
+                http_response_code(400);
+                $response["done"] = false;
+                $response["error"] = "Unknown act.";
+        }
+    } else {
+        http_response_code(400);
+        $response["done"] = false;
+        $response["error"] = "Bad request.";
+    }
+    echo(json_encode($response));
+    mysqli_close($link);
+    exit(0);
+}
+
+
 $dbg .= $dlang . '<br>' . N;
 $dbg .= '<pre>' . print_r($_GET, 1) . '</pre>';
 
@@ -61,8 +106,26 @@ if ($filtordon) {
         <!--
         <?php if ($account['Level'] != 'guest') require('js/notifs.js.php'); ?>
 
+        function reverseSelection() {
+            let checkboxes = getAliveCheckboxes()
+            checkboxes.forEach(function (box) {
+                box.checked = !box.checked;
+            })
+            let n_selected = getSelectedNotifs().length;
+            if (n_selected > 0) {
+                setBtnsVisibility("visible");
+            } else if (n_selected === 0) {
+                setBtnsVisibility("hidden");
+                document.getElementById("global-selector").checked = false;
+            }
+            if (n_selected === checkboxes.length) {
+                document.getElementById("global-selector").checked = true;
+            }
+        }
+
         function setBtnsVisibility(state) {
-            let btns = document.querySelectorAll("#notifs-list-controls .control-btn");
+            let controls = document.querySelector("#notifs-list-controls");
+            let btns = Array(controls.querySelector("#read-btn"), controls.querySelector("#delete-btn"));
             btns.forEach(function (btn) {
                 btn.style.visibility = state;
             });
@@ -74,14 +137,14 @@ if ($filtordon) {
             } else {
                 setBtnsVisibility("hidden")
             }
-            let checkboxes = document.querySelectorAll("div.notif > input.seen-checkbox");
+            let checkboxes = getAliveCheckboxes()
             checkboxes.forEach(function (box) {
                 box.checked = check.checked;
             });
         }
 
         function notifSelect(check) {
-            let checkboxes = Array.from(document.querySelectorAll("div.notif > input.seen-checkbox"));
+            let checkboxes = getAliveCheckboxes()
             if (check.checked) {
                 setBtnsVisibility("visible");
             } else if (checkboxes.every(box => !box.checked)) {
@@ -113,22 +176,9 @@ if ($filtordon) {
 <?php echo($notifs['div']); ?>
 
 <div id="notifs-grid">
-    <div id="notifs-list-controls">
-        <input id="global-selector" type="checkbox" onclick="toggleState(this)">
-        <button class="control-btn" onclick="applyAllSelected(markread)"><i class="fa fa-envelope-open-o"
-                                                                            aria-hidden="true"></i>
-        </button>
-        <button class="control-btn" onclick="applyAllSelected(markdeleted)"><i class="fa fa-trash-o"
-                                                                               aria-hidden="true"></i>
-        </button>
-    </div>
-    <h1 class="control-btn">CIAONEE</h1>
     <div id="notifs-list">
         <?php
         if ($account['Level'] != 'guest') {
-            // Questi valori sono un po' a (n|c)aso,
-            // dovrebbero avere senso ma non ho
-            // indagato troppo
             $sev_classes = array(
                 1 => "sev-normal",
                 2 => "sev-warning",
@@ -138,18 +188,35 @@ if ($filtordon) {
                 0 => "unseen",
                 1 => "seen"
             );
+            $deleted = array(
+                0 => "",
+                1 => "deleted"
+            );
             foreach ($notifs['notifs'] as $n) {
-                echo("<div id=\"notif-" . $n["ID"] .
-                    "\" class=\"" . "notif " . $sev_classes[$n["Severity"]] . " " . $seen_class[$n["Seen"]] . "\">" .
+                echo("<div id=\"notif-" . $n["ID"] . "\" class=\"" . "notif " . $deleted[$n["Deleted"]] . " " . $sev_classes[$n["Severity"]] . " " . $seen_class[$n["Seen"]] . "\">" .
                     "<input type=\"checkbox\" class=\"seen-checkbox\" onclick='notifSelect(this)'>" .
                     "<button type='button' onclick='markread(this.parentElement)'><i class=\"fa fa-envelope-open-o\" aria-hidden=\"true\"></i></button>" .
                     "<button type='button' onclick='markdeleted(this.parentElement)'><i class=\"fa fa-trash-o\" aria-hidden=\"true\"></i></button>" .
-                    "<p>" . $n["Notification"] . "</p>" .
+                    "<p id='notif-text'>" . strftime('%d/%m/%y %T', $n['Microtime']) . ": " . $n["Notification"] . "</p>" .
                     "</div>\n");
             }
         } ?>
     </div>
 
+    <div id="footer">
+        <div id="notifs-list-controls">
+            <input id="global-selector" type="checkbox" onclick="toggleState(this)">
+            <button id='reverse-btn' type='button' class="control-btn" onclick="reverseSelection()">
+                Inverti selezione
+            </button>
+            <button id='read-btn' type='button' class="control-btn" onclick="readSelected()">
+                <i class="fa fa-envelope-open-o" aria-hidden="true"></i>
+            </button>
+            <button id='delete-btn' type='button' class="control-btn" onclick="deleteSelected()">
+                <i class="fa fa-trash-o" aria-hidden="true"></i>
+            </button>
+        </div>
+    </div>
 </div>
 </body>
 </html>

+ 1 - 1
web/mustard/notifsh.php

@@ -19,7 +19,7 @@ if (array_key_exists('act', $_GET) && $_GET['act'] == 'markread' && array_key_ex
 	echo('{"hmunseen":' . mysqli_num_rows($res) . '}' . N);
 } elseif (array_key_exists('act', $_GET) && $_GET['act'] == 'delete' && array_key_exists('id', $_GET) && preg_match('/^[0-9]+$/', $_GET['id']) === 1) {
 	$_GET['id'] += 0;
-	mysqli_query($link, 'DELETE FROM Notifications WHERE ID=' . $_GET['id'])
+	mysqli_query($link, 'UPDATE Notifications SET Deleted=1 WHERE ID=' . $_GET['id'])
 	or muoribene(mysqli_error($link), true);
 	echo('{"deleted":' . true . '}' . N);
 } elseif (array_key_exists('act', $_GET) && $_GET['act'] == 'loadchunk' && array_key_exists('chunk', $_GET) && preg_match('/^[0-9]+$/', $_GET['chunk']) === 1) {

+ 30 - 9
web/mustard/theme.css

@@ -823,29 +823,46 @@ input {
 	display: grid;
 	grid-template-columns: repeat(3, 1fr);
 	grid-gap: 10px;
+	margin-top: 32px;
 }
 
 #notifs-list-controls {
 	display: inline-block;
-	overflow: auto;
-	margin-top: 32px;
-	margin-left: 10px;
-	margin-right: 10px;
-	grid-column: 2;
-	border-radius: 5px;
-	padding: 3px;
-	background-color: #FFEEAA;
+	position: absolute;
+	left: 50%;
+	transform: translateX(-50%);
+	margin-top: 5px;
 }
 
 #global-selector {
 	width: auto;
+	margin: 2px 1px 2px 2px;
 }
 
 .control-btn {
+	margin-top: 2px;
+	margin-bottom: 2px;
+}
+
+#read-btn {
+	margin-left: 1px;
+	margin-right: 2px;
 	float: right;
 	visibility: hidden;
 }
 
+#delete-btn {
+	margin-left: 1px;
+	margin-right: 1px;
+	float: right;
+	visibility: hidden;
+}
+
+#reverse-btn {
+	margin-left: 1px;
+	margin-right: 1px;
+}
+
 #notifs-list {
 	grid-column: 2;
 }
@@ -860,10 +877,10 @@ div.notif {
 
 div.notif p {
 	text-align: center;
+	margin: 2px;
 	padding: 3px;
 }
 
-
 div.notif input {
 	width: auto;
 }
@@ -872,6 +889,10 @@ div.notif button {
 	float: right;
 }
 
+div.deleted {
+	display: none;
+}
+
 div.sev-warning {
 	background-color: #FFEEAA;
 }

BIN
web/mustard/zzz-materiali/mastostart_non_popolato.sql.gz


BIN
web/mustard/zzz-materiali/mastostart_popolato.sql.gz