pezcurrel 4 years ago
parent
commit
352466bba8

+ 5 - 1
web/admin/dafa.txt

@@ -3,10 +3,14 @@
 * fatto
 # in corso
 
+* edinsth.php: su edit e add, nel js, selezionare solo il valore editato/aggiunto, perché nella finestrella elenco valori mostra il primo selezionato
+- nei vari helper, sarebbe meglio morisse in json, alla bisogna
+- sanificazione input: edinsth.php: su edit e add controllare sempre che il valore "nuovo" non ci sia già
+- aggiungere colonna NameCA a Languages e Localities, e relativi pimpumpam nel codice
 - troncare tabella languages e far rigirare tools/popudb.php per ricrearla: my_ucfirst metteva in minuscolo tutta la stringa, a parte il primo carattere maiuscolo
 # edinst.php: su languages se account "Level" è "guest", "lock this list" dev'essere checkato per default *se "guest" non ha ancora mai modificato i dati dell'istanza*
 - index.php: lunghezza automatica di username
-- tutto: notifiche
+# tutto: notifiche; fatto, completo, in instances.php; da riportare anche in edinst.php, e poi in qualsiasi altra pagina; serve un "notifs.php" per la gestione accurata delle notifiche (possibilità di marcarle tutte o "precedenti a" come lette, possibilità di cancellarle tutte o "precedenti a")
 - crawler.php: ricorsivizzarlo?
 - crawler.php: deve controllare se nella tabella Instances OurAdmID è definito; se è definito deve aggiornare l'account "guest" corrispettivo in Admins con la mail e il nome utente attuali
 - instances.php: tradurre tutto in inglese

+ 6 - 0
web/admin/edinst.php

@@ -151,6 +151,12 @@ function selbot(selid) {
 			seldown(selid);
 	}
 }
+function selonebyval(refarr,val) {
+	var len=refarr.length, i;
+	for (i=len-1; i>-1; i--)
+		(refarr[i][1]==val) ? refarr[i][2]=true : refarr[i][2]=false;
+	return refarr;
+}
 function rmelbyval(refarr,val) {
 	var len=refarr.length, i;
 	for (i=len-1; i>-1; i--) {

+ 98 - 56
web/admin/edinsth.php

@@ -57,6 +57,7 @@ function edaddrem($id,$table,$column,$dispselarr,$lntable,$lncolumn,$searchid,$d
 		}
 		$morejs.='parent.'.$dispselarr.'=parent.cheltxtbyval(parent.'.$dispselarr.','.$id.',"'.jsencode($_POST['v']).'");'.N;
 		$morejs.='parent.'.$dispselarr.'=parent.sortByKey(parent.'.$dispselarr.',0);'.N;
+		$morejs.='parent.'.$dispselarr.'=parent.selonebyval(parent.'.$dispselarr.','.$id.');'.N;
 	} elseif ($_POST['m']=='add') {
 		if ($table!='Languages') {
 			mysqli_query($link,'INSERT INTO '.$table.' (ID, '.$column.', AddedBy) VALUES (NULL, \''.myesc($link,$_POST['v']).'\', \''.$account['ID'].'\')')
@@ -68,7 +69,7 @@ function edaddrem($id,$table,$column,$dispselarr,$lntable,$lncolumn,$searchid,$d
 						'NameES'=>mb_ucfirst(locale_get_display_name($_POST['v'],'es')),
 						'NameFR'=>mb_ucfirst(locale_get_display_name($_POST['v'],'fr')),
 						'NameIT'=>mb_ucfirst(locale_get_display_name($_POST['v'],'it')));
-			if ($_POST['v']==$langs['NameOrig']) {
+			if (strtolower($_POST['v'])==strtolower($langs['NameOrig'])) {
 				muoribene('«'.$_POST['v'].'»: unknown language identifier.',true);
 			} else {
 				mysqli_query($link,'INSERT INTO '.$table.' (ID, Code, NameOrig, NameEN, NameES, NameFR, NameIT, AddedBy) VALUES (NULL, \''.myesc($link,$_POST['v']).'\', \''.myesc($link,$langs['NameOrig']).'\', \''.myesc($link,$langs['NameEN']).'\', \''.myesc($link,$langs['NameES']).'\', \''.myesc($link,$langs['NameFR']).'\', \''.myesc($link,$langs['NameIT']).'\', '.$account['ID'].')')
@@ -79,6 +80,7 @@ function edaddrem($id,$table,$column,$dispselarr,$lntable,$lncolumn,$searchid,$d
 		}
 		$morejs.='parent.'.$dispselarr.'.push(["'.jsencode($_POST['v']).'",'.$newid.',true]);'.N;
 		$morejs.='parent.'.$dispselarr.'=parent.sortByKey(parent.'.$dispselarr.',0);'.N;
+		$morejs.='parent.'.$dispselarr.'=parent.selonebyval(parent.'.$dispselarr.','.$newid.');'.N;
 	} elseif ($_POST['m']=='remove') {
 		if (!array_key_exists('subst',$_POST) || preg_match('/^[0-9]+$/',$_POST['subst'])!==1)
 			muoribene(__LINE__.': Malformed input.',true);
@@ -122,6 +124,7 @@ function edaddrem($id,$table,$column,$dispselarr,$lntable,$lncolumn,$searchid,$d
 		$morejs.='parent.'.$dispselarr.'=parent.rmelbyval(parent.'.$dispselarr.','.$id.');'.N;
 	}
 	$morejs.='parent.filtsel (parent.'.$dispselarr.', parent.document.getElementById("'.$searchid.'").value, "'.$dispselid.'", "'.$recbid.'", "'.$searchid.'", "white", "#ff8080");'.N;
+	$morejs.='parent.closeinpup();'.N;
 }
 
 if (array_key_exists('w',$_GET) && array_key_exists('i',$_GET) && preg_match('/^[0-9]+$/',$_GET['i'])===1 && array_key_exists('m',$_GET) && in_array($_GET['m'],array('edit','add','remove'))) {
@@ -152,68 +155,88 @@ if (array_key_exists('w',$_GET) && array_key_exists('i',$_GET) && preg_match('/^
 		break;
 	}
 } elseif (array_key_exists('m',$_POST) && in_array($_POST['m'],array('edit','add','remove')) && array_key_exists('t',$_POST) && in_array($_POST['t'],array('Localities','Languages','Financing','Policies','Tags')) && array_key_exists('i',$_POST) && preg_match('/^[0-9]+$/',$_POST['i'])===1) {
+	$id=$_POST['i']+0;
 	if (array_key_exists('v',$_POST)) {
 		$out='';
-		$id=$_POST['i']+0;
 		if ($_POST['t']=='Localities') {
+			if ($_POST['m']!='remove') {
 //https://nominatim.openstreetmap.org/search?q=bresso,+milano&format=json&accept-language=fr&email=pezcurrel@tiscali.it
 //https://nominatim.openstreetmap.org/lookup?osm_ids=R45266&format=json&accept-language=fr&addressdetails=1&email=pezcurrel@tiscali.it
-			$url='https://nominatim.openstreetmap.org/search?q='.urlencode($_POST['v']).'&format=json&email='.$email;
-			$osmd=@file_get_contents($url,false,$context);
-			if ($osmd!==false) {
-				$out.='<form action="edinsth.php" method="post" id="f">'.N;
-				$addrkeys=array('suburb','city','county','state','country');
-				$osmd=json_decode($osmd,true);
-				if (count($osmd)>0) {
-					$some=false;
-					$out.='<p><strong>Please choose the most detailed appropriate entry</strong></p>'.N;
-					foreach ($osmd as $loc) {
-						if (array_key_exists('osm_id',$loc) && array_key_exists('osm_type',$loc) && $loc['osm_type']=='relation') {
-							$out.='<div class="hifloc" onclick="subosmd(\''.$loc['osm_id'].'\');">'.N;
-							$out.='<ul class="hiful">'.N;
-							foreach ($langs as $code=>$lang) {
-								$url='https://nominatim.openstreetmap.org/lookup?osm_ids=R'.$loc['osm_id'].'&format=json&accept-language='.$code.'&addressdetails=1&email='.$email;
-								$osmdil=@file_get_contents($url,false,$context);
-								if ($osmdil!==false) {
-									$some=true; //+++
-									$osmdil=json_decode($osmdil,true);
-									if (array_key_exists(0,$osmdil) && array_key_exists('address',$osmdil[0])) {
-										$dispname='';
-										foreach ($addrkeys as $addrkey)
-											if (array_key_exists($addrkey,$osmdil[0]['address']))
-												$dispname.=$osmdil[0]['address'][$addrkey].', ';
-										$dispname=substr($dispname,0,-2);
-										$out.='<li><strong>'.$lang.':</strong> '.hspech($dispname).'</li>'.N;
-										$out.='<input type="hidden" id="Loc'.ucfirst($code).'-'.$loc['osm_id'].'" value="'.jsencode($dispname).'">'.N;
+				$url='https://nominatim.openstreetmap.org/search?q='.urlencode($_POST['v']).'&format=json&email='.$email;
+				$osmd=@file_get_contents($url,false,$context);
+				if ($osmd!==false) {
+					$out.='<form action="edinsth.php" method="post" id="f">'.N;
+					$addrkeys=array('suburb','city','county','state','country');
+					$osmd=json_decode($osmd,true);
+					if (count($osmd)>0) {
+						$some=false;
+						$out.='<p><strong>Please choose the most detailed appropriate entry</strong></p>'.N;
+						foreach ($osmd as $loc) {
+							if (array_key_exists('osm_id',$loc) && array_key_exists('osm_type',$loc) && $loc['osm_type']=='relation') {
+								$out.='<div class="hifloc" onclick="subosmd(\''.$loc['osm_id'].'\');">'.N;
+								$out.='<ul class="hiful">'.N;
+								foreach ($langs as $code=>$lang) {
+									$url='https://nominatim.openstreetmap.org/lookup?osm_ids=R'.$loc['osm_id'].'&format=json&accept-language='.$code.'&addressdetails=1&email='.$email;
+									$osmdil=@file_get_contents($url,false,$context);
+									if ($osmdil!==false) {
+										$some=true; //+++
+										$osmdil=json_decode($osmdil,true);
+										if (array_key_exists(0,$osmdil) && array_key_exists('address',$osmdil[0])) {
+											$dispname='';
+											foreach ($addrkeys as $addrkey)
+												if (array_key_exists($addrkey,$osmdil[0]['address']))
+													$dispname.=$osmdil[0]['address'][$addrkey].', ';
+											$dispname=substr($dispname,0,-2);
+											$out.='<li><strong>'.$lang.':</strong> '.hspech($dispname).'</li>'.N;
+											$out.='<input type="hidden" id="Loc'.strtoupper($code).'-'.$loc['osm_id'].'" value="'.jsencode($dispname).'">'.N;
+										} else {
+											$out.='<li class="hiferr"><strong>'.$lang.':</strong> Couldn’t parse OpenStreetMap lookup data.</li>'.N;
+											$out.='<input type="hidden" id="Loc'.strtoupper($code).'-'.$loc['osm_id'].'" value="">'.N;
+										}
 									} else {
-										$out.='<li class="hiferr"><strong>'.$lang.':</strong> Couldn’t parse OpenStreetMap lookup data.</li>'.N;
-										$out.='<input type="hidden" id="Loc'.ucfirst($code).'-'.$loc['osm_id'].'" value="">'.N;
+										$out.='<li class="hiferr"><strong>'.$lang.':</strong> Couldn’t fetch OpenStreetMap lookup data.</li>'.N;
 									}
-								} else {
-									$out.='<li class="hiferr"><strong>'.$lang.':</strong> Couldn’t fetch OpenStreetMap lookup data.</li>'.N;
 								}
+								$out.='</ul>'.N.'</div>'.N;
 							}
-							$out.='</ul>'.N.'</div>'.N;
 						}
-					}
-					if ($some) {
-						$out.='<input type="hidden" id="i" name="i" value="'.$_POST['i'].'">'.N;
-						$out.='<input type="hidden" id="t" name="t" value="'.$_POST['t'].'">'.N;
-						$out.='<input type="hidden" id="m" name="m" value="'.$_POST['m'].'">'.N;
-						$out.='<input type="hidden" id="LocXx" name="LocXx" value="">'.N;
-						$out.='<input type="hidden" id="LocEn" name="LocEn" value="">'.N;
-						$out.='<input type="hidden" id="LocEs" name="LocEs" value="">'.N;
-						$out.='<input type="hidden" id="LocFr" name="LocFr" value="">'.N;
-						$out.='<input type="hidden" id="LocIt" name="LocIt" value="">'.N;
-						$out.='</form>'.N;
+						if ($some) {
+							$out.='<input type="hidden" id="i" name="i" value="'.$_POST['i'].'">'.N;
+							$out.='<input type="hidden" id="t" name="t" value="'.$_POST['t'].'">'.N;
+							$out.='<input type="hidden" id="m" name="m" value="'.$_POST['m'].'">'.N;
+							$out.='<input type="hidden" id="LocXX" name="LocXX" value="">'.N;
+							$out.='<input type="hidden" id="LocEN" name="LocEN" value="">'.N;
+							$out.='<input type="hidden" id="LocES" name="LocES" value="">'.N;
+							$out.='<input type="hidden" id="LocFR" name="LocFR" value="">'.N;
+							$out.='<input type="hidden" id="LocIT" name="LocIT" value="">'.N;
+							$out.='</form>'.N;
+						} else {
+							$out='<p class="hiferr">Couldn’t find localized OpenStreetMap data for «'.hspech($_POST['v']).'».</p>';
+						}
 					} else {
-						$out='<p class="hiferr">Couldn’t find localized OpenStreetMap data for «'.hspech($_POST['v']).'».</p>';
+						$out='<p class="hiferr">Couldn’t find OpenStreetMap data for «'.hspech($_POST['v']).'».</p>';
 					}
 				} else {
-					$out='<p class="hiferr">Couldn’t find OpenStreetMap data for «'.hspech($_POST['v']).'».</p>';
+					$out='<p class="hiferr">Couldn’t fetch OpenStreetMap search data.</p>'.N;
 				}
 			} else {
-				$out='<p class="hiferr">Couldn’t fetch OpenStreetMap search data.</p>'.N;
+				// locality remove
+				$out='CANCELLO!';
+				if (!array_key_exists('subst',$_POST) || preg_match('/^[0-9]+$/',$_POST['subst'])!==1)
+					muoribene(__LINE__.': Malformed input.',true);
+				$_POST['subst']+=0;
+				if ($_POST['subst']==0) {
+					mysqli_query($link,'UPDATE Instances SET LocalityID=NULL WHERE LocalityID='.$id)
+						or muoribene(__LINE__.': '.mysqli_error($link),true);
+				} else {
+					mysqli_query($link,'UPDATE Instances SET LocalityID='.$_POST['subst'].' WHERE LocalityID='.$id)
+						or muoribene(__LINE__.': '.mysqli_error($link),true);
+				}
+				mysqli_query($link,'DELETE FROM Localities WHERE ID='.$id)
+					or muoribene(__LINE__.': '.mysqli_error($link),true);
+				$morejs.='parent.locselarr=parent.rmelbyval(parent.locselarr,'.$id.');'.N;
+				$morejs.='parent.filtsel (parent.locselarr, parent.document.getElementById("locsearch").value, "LocalityID", "locselre", "locsearch", "white", "#ff8080");'.N;
+				$morejs.='parent.closeinpup();'.N;
 			}
 		} elseif ($_POST['t']=='Languages') {
 			edaddrem($id,'Languages','Name'.$dlang,'langselarr','InstOurLangs','OurLangID','langsearch','DispLangs','langselre');
@@ -227,8 +250,24 @@ if (array_key_exists('w',$_GET) && array_key_exists('i',$_GET) && preg_match('/^
 			// questo è ridondante ma fa niente
 			muoribene(__LINE__.': Malformed input.',true);
 		}
-	} elseif (array_key_exists('LocEn',$_POST) && array_key_exists('LocEs',$_POST) && array_key_exists('LocFr',$_POST) && array_key_exists('LocIt',$_POST)) {
-		$out='CIAO!';
+	} elseif (array_key_exists('LocXX',$_POST) && array_key_exists('LocEN',$_POST) && array_key_exists('LocES',$_POST) && array_key_exists('LocFR',$_POST) && array_key_exists('LocIT',$_POST)) {
+		// locality edit/add
+		$out='EDITO/AGGIUNGO!';
+		// qui, sia su add sia su edit, serve check che non esista già +++
+		if ($_POST['m']=='add') {
+			mysqli_query($link,'INSERT INTO Localities (ID, NameOrig, NameEN, NameES, NameFR, NameIT, AddedBy) VALUES (NULL, \''.myesc($link,$_POST['LocXX']).'\', \''.myesc($link,$_POST['LocEN']).'\', \''.myesc($link,$_POST['LocES']).'\', \''.myesc($link,$_POST['LocFR']).'\', \''.myesc($link,$_POST['LocIT']).'\', \''.$account['ID'].'\')')
+				or muoribene(__LINE__.': '.mysqli_error($link),true);
+			$id=mysqli_insert_id($link);
+			$morejs.='parent.locselarr.push(["'.jsencode($_POST['Loc'.$dlang]).'",'.$id.',true]);'.N;
+		} elseif ($_POST['m']=='edit') {
+			mysqli_query($link,'UPDATE Localities SET NameOrig=\''.myesc($link,$_POST['LocXX']).'\', NameEN=\''.myesc($link,$_POST['LocEN']).'\', NameES=\''.myesc($link,$_POST['LocES']).'\', NameFR=\''.myesc($link,$_POST['LocFR']).'\', NameIT=\''.myesc($link,$_POST['LocIT']).'\' WHERE ID='.$id)
+				or muoribene(__LINE__.': '.mysqli_error($link),true);
+			$morejs.='parent.locselarr=parent.cheltxtbyval(parent.locselarr,'.$id.',"'.jsencode($_POST['Loc'.$dlang]).'");'.N;
+		}
+		$morejs.='parent.locselarr=parent.sortByKey(parent.locselarr,0);'.N;
+		$morejs.='parent.locselarr=parent.selonebyval(parent.locselarr,'.$id.');'.N;
+		$morejs.='parent.filtsel (parent.locselarr, parent.document.getElementById("locsearch").value, "LocalityID", "locselre", "locsearch", "white", "#ff8080");'.N;
+		$morejs.='parent.closeinpup();'.N;
 	} else {
 		muoribene(__LINE__.': Malformed input.',true);
 	}
@@ -363,7 +402,7 @@ function ckf(mode,table) {
 	}
 	if (ok) {
 		var wdiv=document.getElementById('wait');
-		if (table=='Localities')
+		if (table=='Localities' && mode!='remove')
 			wdiv.innerHTML='Fetching data from OpenStreetMap.org ...';
 		else
 			wdiv.innerHTML='Sending data ...';
@@ -375,11 +414,12 @@ function ckf(mode,table) {
 }
 
 function subosmd(osmid) {
-	document.getElementById('LocEn').value=document.getElementById('LocEn-'+osmid).value;
-	document.getElementById('LocEs').value=document.getElementById('LocEs-'+osmid).value;
-	document.getElementById('LocFr').value=document.getElementById('LocFr-'+osmid).value;
-	document.getElementById('LocIt').value=document.getElementById('LocIt-'+osmid).value;
-	if (document.getElementById('LocEn').value=='' || document.getElementById('LocEs').value=='' || document.getElementById('LocFr').value=='' || document.getElementById('LocIt').value=='') {
+	document.getElementById('LocXX').value=document.getElementById('LocXX-'+osmid).value;
+	document.getElementById('LocEN').value=document.getElementById('LocEN-'+osmid).value;
+	document.getElementById('LocES').value=document.getElementById('LocES-'+osmid).value;
+	document.getElementById('LocFR').value=document.getElementById('LocFR-'+osmid).value;
+	document.getElementById('LocIT').value=document.getElementById('LocIT-'+osmid).value;
+	if (document.getElementById('LocXX').value=='' || document.getElementById('LocEN').value=='' || document.getElementById('LocES').value=='' || document.getElementById('LocFR').value=='' || document.getElementById('LocIT').value=='') {
 		alert('NO GOOD!');
 	} else {
 		document.getElementById('f').submit();
@@ -397,7 +437,9 @@ function subosmd(osmid) {
 <?php echo($out); ?>
 </div>
 </div>
+<div id="debugh">
 <?php echo($dbg); ?>
+</div>
 <div id="wait">
 ...
 </div>

+ 76 - 0
web/admin/imgs/bell_act_off.svg

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg11"
+   sodipodi:docname="bell_act_off.svg"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14">
+  <metadata
+     id="metadata17">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>notification</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs15" />
+  <sodipodi:namedview
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="3840"
+     inkscape:window-height="2037"
+     id="namedview13"
+     showgrid="false"
+     inkscape:zoom="20.85965"
+     inkscape:cx="9.9715326"
+     inkscape:cy="9.4838728"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg11"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:pagecheckerboard="false" />
+  <!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
+  <title
+     id="title2">notification</title>
+  <desc
+     id="desc4">Created with Sketch.</desc>
+  <g
+     id="g1494"
+     transform="translate(3.9322038,-2.1355933)"
+     style="fill:#800000">
+    <path
+       style="fill:#78b1e2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1"
+       d="m 12.068431,4.9334213 c -1.27045,0 -2.304267,1.0338166 -2.304267,2.3042676 V 9.3037713 C 6.437807,10.29779 4.004397,13.381325 4.004397,17.026765 v 2.888906 c 0,1.773751 -0.482607,3.514625 -1.394831,5.036188 l -1.97766495,3.296709 c -0.107117,0.178546 -0.107941,0.400215 -0.0054,0.581028 0.102528,0.180815 0.292506,0.292319 0.49982895,0.292319 h 7.365718 c 0.666788,1.307642 2.010598,2.21585 3.576396,2.21585 1.565856,0 2.90963,-0.908131 3.576396,-2.21585 h 7.365717 c 0.207324,0 0.397302,-0.112639 0.499829,-0.292319 0.102528,-0.179734 0.09878,-0.40367 -0.0072,-0.581028 l -1.975877,-3.294906 c -0.913358,-1.521507 -1.396636,-3.26424 -1.396636,-5.037991 v -2.888906 c 0,-3.64544 -2.433356,-6.728975 -5.759767,-7.7229937 V 7.2376889 c 0,-1.270451 -1.032011,-2.3042676 -2.302462,-2.3042676 z"
+       id="Path"
+       inkscape:connector-curvature="0" />
+  </g>
+  <circle
+     style="opacity:1;vector-effect:none;fill:#ff2a2a;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
+     id="path4522"
+     cx="26.402098"
+     cy="5.4348607"
+     r="2.7500005" />
+</svg>

+ 76 - 0
web/admin/imgs/bell_act_on.svg

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg11"
+   sodipodi:docname="bell_act_on.svg"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14">
+  <metadata
+     id="metadata17">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>notification</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs15" />
+  <sodipodi:namedview
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="3840"
+     inkscape:window-height="2037"
+     id="namedview13"
+     showgrid="false"
+     inkscape:zoom="14.75"
+     inkscape:cx="11.535553"
+     inkscape:cy="1.7984075"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg11"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:pagecheckerboard="false" />
+  <!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
+  <title
+     id="title2">notification</title>
+  <desc
+     id="desc4">Created with Sketch.</desc>
+  <g
+     id="g1494"
+     transform="translate(3.9322038,-2.1355933)"
+     style="fill:#ffffff">
+    <path
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1"
+       d="m 12.068431,4.9334213 c -1.27045,0 -2.304267,1.0338166 -2.304267,2.3042676 V 9.3037713 C 6.437807,10.29779 4.004397,13.381325 4.004397,17.026765 v 2.888906 c 0,1.773751 -0.482607,3.514625 -1.394831,5.036188 l -1.97766495,3.296709 c -0.107117,0.178546 -0.107941,0.400215 -0.0054,0.581028 0.102528,0.180815 0.292506,0.292319 0.49982895,0.292319 h 7.365718 c 0.666788,1.307642 2.010598,2.21585 3.576396,2.21585 1.565856,0 2.90963,-0.908131 3.576396,-2.21585 h 7.365717 c 0.207324,0 0.397302,-0.112639 0.499829,-0.292319 0.102528,-0.179734 0.09878,-0.40367 -0.0072,-0.581028 l -1.975877,-3.294906 c -0.913358,-1.521507 -1.396636,-3.26424 -1.396636,-5.037991 v -2.888906 c 0,-3.64544 -2.433356,-6.728975 -5.759767,-7.7229937 V 7.2376889 c 0,-1.270451 -1.032011,-2.3042676 -2.302462,-2.3042676 z"
+       id="Path"
+       inkscape:connector-curvature="0" />
+  </g>
+  <circle
+     style="opacity:1;vector-effect:none;fill:#ff2a2a;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
+     id="path4522"
+     cx="26.402098"
+     cy="5.4348607"
+     r="2.7500005" />
+</svg>

+ 70 - 0
web/admin/imgs/bell_off.svg

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg11"
+   sodipodi:docname="bell_off.svg"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14">
+  <metadata
+     id="metadata17">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>notification</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs15" />
+  <sodipodi:namedview
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="3840"
+     inkscape:window-height="2037"
+     id="namedview13"
+     showgrid="false"
+     inkscape:zoom="20.85965"
+     inkscape:cx="9.9715326"
+     inkscape:cy="9.4838728"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg11"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:pagecheckerboard="false" />
+  <!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
+  <title
+     id="title2">notification</title>
+  <desc
+     id="desc4">Created with Sketch.</desc>
+  <g
+     id="g1494"
+     transform="translate(3.9322038,-2.1355933)"
+     style="fill:#800000">
+    <path
+       style="fill:#78b1e2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1"
+       d="m 12.068431,4.9334213 c -1.27045,0 -2.304267,1.0338166 -2.304267,2.3042676 V 9.3037713 C 6.437807,10.29779 4.004397,13.381325 4.004397,17.026765 v 2.888906 c 0,1.773751 -0.482607,3.514625 -1.394831,5.036188 l -1.97766495,3.296709 c -0.107117,0.178546 -0.107941,0.400215 -0.0054,0.581028 0.102528,0.180815 0.292506,0.292319 0.49982895,0.292319 h 7.365718 c 0.666788,1.307642 2.010598,2.21585 3.576396,2.21585 1.565856,0 2.90963,-0.908131 3.576396,-2.21585 h 7.365717 c 0.207324,0 0.397302,-0.112639 0.499829,-0.292319 0.102528,-0.179734 0.09878,-0.40367 -0.0072,-0.581028 l -1.975877,-3.294906 c -0.913358,-1.521507 -1.396636,-3.26424 -1.396636,-5.037991 v -2.888906 c 0,-3.64544 -2.433356,-6.728975 -5.759767,-7.7229937 V 7.2376889 c 0,-1.270451 -1.032011,-2.3042676 -2.302462,-2.3042676 z"
+       id="Path"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>

+ 70 - 0
web/admin/imgs/bell_on.svg

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg11"
+   sodipodi:docname="bell_on.svg"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14">
+  <metadata
+     id="metadata17">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>notification</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs15" />
+  <sodipodi:namedview
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="3840"
+     inkscape:window-height="2037"
+     id="namedview13"
+     showgrid="false"
+     inkscape:zoom="20.85965"
+     inkscape:cx="9.9715326"
+     inkscape:cy="9.4838728"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg11"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:pagecheckerboard="false" />
+  <!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
+  <title
+     id="title2">notification</title>
+  <desc
+     id="desc4">Created with Sketch.</desc>
+  <g
+     id="g1494"
+     transform="translate(3.9322038,-2.1355933)"
+     style="fill:#ffffff">
+    <path
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1"
+       d="m 12.068431,4.9334213 c -1.27045,0 -2.304267,1.0338166 -2.304267,2.3042676 V 9.3037713 C 6.437807,10.29779 4.004397,13.381325 4.004397,17.026765 v 2.888906 c 0,1.773751 -0.482607,3.514625 -1.394831,5.036188 l -1.97766495,3.296709 c -0.107117,0.178546 -0.107941,0.400215 -0.0054,0.581028 0.102528,0.180815 0.292506,0.292319 0.49982895,0.292319 h 7.365718 c 0.666788,1.307642 2.010598,2.21585 3.576396,2.21585 1.565856,0 2.90963,-0.908131 3.576396,-2.21585 h 7.365717 c 0.207324,0 0.397302,-0.112639 0.499829,-0.292319 0.102528,-0.179734 0.09878,-0.40367 -0.0072,-0.581028 l -1.975877,-3.294906 c -0.913358,-1.521507 -1.396636,-3.26424 -1.396636,-5.037991 v -2.888906 c 0,-3.64544 -2.433356,-6.728975 -5.759767,-7.7229937 V 7.2376889 c 0,-1.270451 -1.032011,-2.3042676 -2.302462,-2.3042676 z"
+       id="Path"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>

+ 11 - 11
web/admin/include/columns.php

@@ -18,7 +18,7 @@ $cols=array(
 
 //--------------------------------
 
-	'Instances.LocalityID'=>array('field'=>'Instances.LocalityID','name'=>'[Località] ','type'=>'join','join'=>array(),'ord'=>false),
+	'Instances.LocalityID'=>array('field'=>'Instances.LocalityID','name'=>'[Località] ','type'=>'join','join'=>array(),'ord'=>false),
 	'Localities.Name'=>array('field'=>'Localities.Name'.$dlang,'name'=>'[Località]','type'=>'joini','join'=>array('Localities ON Localities.ID=Instances.LocalityID'),'subtype'=>'text'),
 
 //--------------------------------
@@ -46,11 +46,11 @@ $cols=array(
 
 	'InstLangs'=>array('name'=>'Lingue dichiarate','search'=>false,'ord'=>false),
 
-	'InstLangs.LangID'=>array('field'=>'InstLangs%.LangID','name'=>'Una lingua dichiarata ','type'=>'join','join'=>array('InstLangs AS InstLangs% ON InstLangs%.InstID=Instances.ID'),'ord'=>false),
+	'InstLangs.LangID'=>array('field'=>'InstLangs%.LangID','name'=>'Una lingua dichiarata ','type'=>'join','join'=>array('InstLangs AS InstLangs% ON InstLangs%.InstID=Instances.ID'),'ord'=>false),
 
 	'Languages.NameXX'=>array('field'=>'Languages%.Name'.$dlang,'name'=>'Una lingua dichiarata','type'=>'joini','join'=>array('InstLangs AS InstLangs% ON InstLangs%.InstID=Instances.ID','Languages AS Languages% ON Languages%.ID=InstLangs%.LangID'),'subtype'=>'text','ord'=>true,'ordname'=>'Lingue dichiarate','ordjoin'=>array('InstLangs AS OrdInstLangs ON OrdInstLangs.InstID=Instances.ID','Languages AS OrdLanguages ON OrdLanguages.ID=OrdInstLangs.LangID'),'ordselmore'=>'GROUP_CONCAT(OrdLanguages.Name'.$dlang.' ORDER BY OrdInstLangs.Pos ASC SEPARATOR \'\') AS xOrdLangs','ordby'=>'xOrdLangs'),
 
-	'InstLangs.LangID.First'=>array('field'=>'InstLangs.LangID','name'=>'Lingua primaria dichiarata ','type'=>'join','join'=>array('InstLangs AS InstLangs ON InstLangs.InstID=Instances.ID AND InstLangs.Pos=1'),'ord'=>false),
+	'InstLangs.LangID.First'=>array('field'=>'InstLangs.LangID','name'=>'Lingua primaria dichiarata ','type'=>'join','join'=>array('InstLangs AS InstLangs ON InstLangs.InstID=Instances.ID AND InstLangs.Pos=1'),'ord'=>false),
 
 	'Languages.NameXX.First'=>array('field'=>'Languages.Name'.$dlang,'name'=>'Lingua primaria dichiarata','type'=>'joini','join'=>array('InstLangs AS InstLangs ON InstLangs.InstID=Instances.ID AND InstLangs.Pos=1','Languages AS Languages ON Languages.ID=InstLangs.LangID'),'subtype'=>'text','ord'=>false),
 
@@ -58,11 +58,11 @@ $cols=array(
 
 	'InstOurLangs'=>array('name'=>'[Lingue impostate da noi]','search'=>false,'ord'=>false),
 
-	'InstOurLangs.OurLangID'=>array('field'=>'InstOurLangs%.OurLangID','name'=>'[Una lingua impostata da noi] ','type'=>'join','join'=>array('InstOurLangs AS InstOurLangs% ON InstOurLangs%.InstID=Instances.ID'),'ord'=>false),
+	'InstOurLangs.OurLangID'=>array('field'=>'InstOurLangs%.OurLangID','name'=>'[Una lingua impostata da noi] ','type'=>'join','join'=>array('InstOurLangs AS InstOurLangs% ON InstOurLangs%.InstID=Instances.ID'),'ord'=>false),
 
 	'OurLanguages.NameXX'=>array('field'=>'OurLanguages%.Name'.$dlang,'name'=>'[Una lingua impostata da noi]','type'=>'joini','join'=>array('InstOurLangs AS InstOurLangs% ON InstOurLangs%.InstID=Instances.ID','Languages AS OurLanguages% ON OurLanguages%.ID=InstOurLangs%.OurLangID'),'subtype'=>'text','ord'=>true,'ordname'=>'Lingue impostate da noi','ordjoin'=>array('InstOurLangs AS OrdInstOurLangs ON OrdInstOurLangs.InstID=Instances.ID','Languages AS OrdOurLanguages ON OrdOurLanguages.ID=OrdInstOurLangs.OurLangID'),'ordselmore'=>'GROUP_CONCAT(OrdOurLanguages.Name'.$dlang.' ORDER BY OrdInstOurLangs.Pos ASC SEPARATOR \'\') AS xOrdOurLangs','ordby'=>'xOrdOurLangs'),
 
-	'InstOurLangs.OurLangID.First'=>array('field'=>'InstOurLangs.OurLangID','name'=>'[Lingua primaria impostata da noi] ','type'=>'join','join'=>array('InstOurLangs AS InstOurLangs ON InstOurLangs.InstID=Instances.ID AND InstOurLangs.Pos=1'),'ord'=>false),
+	'InstOurLangs.OurLangID.First'=>array('field'=>'InstOurLangs.OurLangID','name'=>'[Lingua primaria impostata da noi] ','type'=>'join','join'=>array('InstOurLangs AS InstOurLangs ON InstOurLangs.InstID=Instances.ID AND InstOurLangs.Pos=1'),'ord'=>false),
 
 	'OurLanguages.NameXX.First'=>array('field'=>'OurLanguages.Name'.$dlang,'name'=>'[Lingua primaria impostata da noi]','type'=>'joini','join'=>array('InstOurLangs AS InstOurLangs ON InstOurLangs.InstID=Instances.ID AND InstOurLangs.Pos=1','Languages AS OurLanguages ON OurLanguages.ID=InstOurLangs.OurLangID'),'subtype'=>'text','ord'=>false),
 
@@ -70,11 +70,11 @@ $cols=array(
 
 	'InstFinancing'=>array('name'=>'[Modalità di finanziamento]','search'=>false,'ord'=>false),
 
-	'InstFinancing.FinID'=>array('field'=>'InstFinancing%.FinID','name'=>'[Una modalità di finanziamento] ','type'=>'join','join'=>array('InstFinancing AS InstFinancing% ON InstFinancing%.InstID=Instances.ID'),'ord'=>false),
+	'InstFinancing.FinID'=>array('field'=>'InstFinancing%.FinID','name'=>'[Una modalità di finanziamento] ','type'=>'join','join'=>array('InstFinancing AS InstFinancing% ON InstFinancing%.InstID=Instances.ID'),'ord'=>false),
 
 	'Financing.Type'=>array('field'=>'Financing%.Type','name'=>'[Una modalità di finanziamento]','type'=>'joini','join'=>array('InstFinancing AS InstFinancing% ON InstFinancing%.InstID=Instances.ID','Financing AS Financing% ON Financing%.ID=InstFinancing%.FinID'),'subtype'=>'text','ord'=>true,'ordname'=>'Modalità di finanziamento','ordjoin'=>array('InstFinancing AS OrdInstFinancing ON OrdInstFinancing.InstID=Instances.ID','Financing AS OrdFinancing ON OrdFinancing.ID=OrdInstFinancing.FinID'),'ordselmore'=>'GROUP_CONCAT(OrdFinancing.Type ORDER BY OrdInstFinancing.Pos ASC SEPARATOR \'\') AS xOrdFinancing','ordby'=>'xOrdFinancing'),
 
-	'InstFinancing.FinID.First'=>array('field'=>'InstFinancing.FinID','name'=>'[Modalità di finanziamento primaria] ','type'=>'join','join'=>array('InstFinancing AS InstFinancing ON InstFinancing.InstID=Instances.ID AND InstFinancing.Pos=1'),'ord'=>false),
+	'InstFinancing.FinID.First'=>array('field'=>'InstFinancing.FinID','name'=>'[Modalità di finanziamento primaria] ','type'=>'join','join'=>array('InstFinancing AS InstFinancing ON InstFinancing.InstID=Instances.ID AND InstFinancing.Pos=1'),'ord'=>false),
 
 	'Financing.Type.First'=>array('field'=>'Financing.Type','name'=>'[Modalità di finanziamento primaria]','type'=>'joini','join'=>array('InstFinancing AS InstFinancing ON InstFinancing.InstID=Instances.ID AND InstFinancing.Pos=1','Financing AS Financing ON Financing.ID=InstFinancing.FinID'),'subtype'=>'text','ord'=>false),
 
@@ -82,12 +82,12 @@ $cols=array(
 
 	'InstPolicies'=>array('name'=>'[Policies]','search'=>false,'ord'=>false),
 
-	'InstPolicies.PolID'=>array('field'=>'InstPolicies%.PolID','name'=>'[Una policy] ','type'=>'join','join'=>array('InstPolicies AS InstPolicies% ON InstPolicies%.InstID=Instances.ID'),'ord'=>false),
+	'InstPolicies.PolID'=>array('field'=>'InstPolicies%.PolID','name'=>'[Una policy] ','type'=>'join','join'=>array('InstPolicies AS InstPolicies% ON InstPolicies%.InstID=Instances.ID'),'ord'=>false),
 
 	'Policies.Name'=>array('field'=>'Policies%.Name','name'=>'[Una policy]','type'=>'joini','join'=>array('InstPolicies AS InstPolicies% ON InstPolicies%.InstID=Instances.ID','Policies AS Policies% ON Policies%.ID=InstPolicies%.PolID'),'subtype'=>'text','ord'=>true,'ordname'=>'Policies','ordjoin'=>array('InstPolicies AS OrdInstPolicies ON OrdInstPolicies.InstID=Instances.ID','Policies AS OrdPolicies ON OrdPolicies.ID=OrdInstPolicies.PolID'),'ordselmore'=>'GROUP_CONCAT(OrdPolicies.Name ORDER BY OrdInstPolicies.Pos ASC SEPARATOR \'\') AS xOrdPolicies','ordby'=>'xOrdPolicies'),
 
 // Questi qui sotto sono disabilitati perché le policy non sono "pesate"
-	/*'InstPolicies.PolID.First'=>array('field'=>'InstPolicies.PolID','name'=>'[Policy primaria] ','type'=>'join','join'=>array('InstPolicies AS InstPolicies ON InstPolicies.InstID=Instances.ID AND InstPolicies.Pos=1'),'ord'=>false),
+	/*'InstPolicies.PolID.First'=>array('field'=>'InstPolicies.PolID','name'=>'[Policy primaria] ','type'=>'join','join'=>array('InstPolicies AS InstPolicies ON InstPolicies.InstID=Instances.ID AND InstPolicies.Pos=1'),'ord'=>false),
 
 	'Policies.Name.First'=>array('field'=>'Policies.Name','name'=>'[Policy primaria]','type'=>'joini','join'=>array('InstPolicies AS InstPolicies ON InstPolicies.InstID=Instances.ID AND InstPolicies.Pos=1','Policies AS Policies ON Policies.ID=InstPolicies.PolID'),'subtype'=>'text','ord'=>false),*/
 
@@ -95,11 +95,11 @@ $cols=array(
 
 	'InstTags'=>array('name'=>'[Tags]','search'=>false,'ord'=>false),
 
-	'InstTags.TagID'=>array('field'=>'InstTags%.TagID','name'=>'[Una tag] ','type'=>'join','join'=>array('InstTags AS InstTags% ON InstTags%.InstID=Instances.ID'),'ord'=>false),
+	'InstTags.TagID'=>array('field'=>'InstTags%.TagID','name'=>'[Una tag] ','type'=>'join','join'=>array('InstTags AS InstTags% ON InstTags%.InstID=Instances.ID'),'ord'=>false),
 
 	'Tags.Name'=>array('field'=>'Tags%.Name','name'=>'[Una tag]','type'=>'joini','join'=>array('InstTags AS InstTags% ON InstTags%.InstID=Instances.ID','Tags AS Tags% ON Tags%.ID=InstTags%.TagID'),'subtype'=>'text','ord'=>true,'ordname'=>'Tags','ordjoin'=>array('InstTags AS OrdInstTags ON OrdInstTags.InstID=Instances.ID','Tags AS OrdTags ON OrdTags.ID=OrdInstTags.TagID'),'ordselmore'=>'GROUP_CONCAT(OrdTags.Name ORDER BY OrdInstTags.Pos ASC SEPARATOR \'\') AS xOrdTags','ordby'=>'xOrdTags'),
 
-	'InstTags.TagID.First'=>array('field'=>'InstTags.TagID','name'=>'[Tag primaria] ','type'=>'join','join'=>array('InstTags AS InstTags ON InstTags.InstID=Instances.ID AND InstTags.Pos=1'),'ord'=>false),
+	'InstTags.TagID.First'=>array('field'=>'InstTags.TagID','name'=>'[Tag primaria] ','type'=>'join','join'=>array('InstTags AS InstTags ON InstTags.InstID=Instances.ID AND InstTags.Pos=1'),'ord'=>false),
 
 	'Tags.Name.First'=>array('field'=>'Tags.Name','name'=>'[Tag primaria]','type'=>'joini','join'=>array('InstTags AS InstTags ON InstTags.InstID=Instances.ID AND InstTags.Pos=1','Tags AS Tags ON Tags.ID=InstTags.TagID'),'subtype'=>'text','ord'=>false),
 

+ 131 - 5
web/admin/instances.php

@@ -344,6 +344,37 @@ while ($row=mysqli_fetch_assoc($res)) {
 		$presopts.='<option value="'.$row['ID'].'" selected>'.hspech($row['Name']).'</option>'.N;
 }
 
+$chunksize=20; // questo deve essere settato paro-paro in notifsh.php
+$i=0;
+$notifs='<div id="notifc">'.N;
+$notifs.='<div id="notifs" onscroll="morenotifs();">'.N;
+$unreadnotifs=false;
+$res=mysqli_query($link,'SELECT * FROM Notifications ORDER BY Microtime DESC')
+	or muoribene(mysqli_error($link),true);
+while ($row=mysqli_fetch_assoc($res)) {
+	if ($row['Seen']==0) {
+		$unreadnotifs=true;
+		$notifclass='notifunseen';
+	} else {
+		$notifclass='notifseen';
+	}
+	$i++;
+	if ($i<=$chunksize) {
+		if ($i==1) $fntime=$row['Microtime'];
+		$notifs.='<div id="notif-'.$row['ID'].'" class="'.$notifclass.'" onclick="markread(this)">'.strftime('%d/%m/%y %T',$row['Microtime']).': '.$row['Notification'].'</div>'.N;
+	}
+}
+$notifs.='</div>'.N;
+$notifs.='<div id="notifa"><a href="notifs.php">Vedi tutte le notifiche</a></div>'.N;
+$notifs.='</div>'.N;
+if ($unreadnotifs) {
+	$notifimgoff='imgs/bell_act_off.svg';
+	$notifimgon='imgs/bell_act_on.svg';
+} else {
+	$notifimgoff='imgs/bell_off.svg';
+	$notifimgon='imgs/bell_on.svg';
+}
+
 mysqli_close($link);
 
 if ($filtordon) {
@@ -377,14 +408,106 @@ function shideplancia() {
 	var plctrl=document.getElementById('lente');
 	if (plancia.style.display=='block') {
 		plancia.style.display='none';
-		lente.src='<?php echo($filtordimgoff); ?>';
-		lente.title='Mostra il pannello di ricerca e ordinamento';
+		plctrl.src='<?php echo($filtordimgoff); ?>';
+		plctrl.title='Mostra il pannello di ricerca e ordinamento';
 	} else {
 		plancia.style.display='block';
-		lente.src='<?php echo($filtordimgon); ?>';
-		lente.title='Nascondi il pannello di ricerca e ordinamento';
+		plctrl.src='<?php echo($filtordimgon); ?>';
+		plctrl.title='Nascondi il pannello di ricerca e ordinamento';
+	}
+}
+notifimgon='<?php echo($notifimgon); ?>';
+notifimgoff='<?php echo($notifimgoff); ?>';
+function shidenotifs() {
+	var notifc=document.getElementById('notifc');
+	var ctrli=document.getElementById('bell');
+	if (notifc.style.display=='block') {
+		notifc.style.display='none';
+		ctrli.src=notifimgoff;
+		ctrli.title='Mostra le notifiche';
+	} else {
+		notifc.style.display='block';
+		ctrli.src=notifimgon;
+		ctrli.title='Nascondi le notifiche';
 	}
 }
+function markread(notif) {
+	let xhr=new XMLHttpRequest();
+	xhr.open('GET','notifsh.php?act=markread&id='+notif.id.replace(/^notif-([0-9]+)$/,'$1'));
+	xhr.responseType='json';
+	xhr.send();
+	xhr.onload=function() {
+		notif.className='notifseen';
+		let jarr=xhr.response;
+		if (jarr['hmunseen']==0) {
+			notifimgon='imgs/bell_on.svg';
+			notifimgoff='imgs/bell_off.svg';
+			bell.src=notifimgon;
+		}
+	};
+	xhr.onerror=function() {
+		alert('La richiesta è fallita.');
+	};
+}
+lmt=<?php echo($fntime); ?>;
+chunk=0;
+end=false;
+loading=false;
+function morenotifs() {
+	if (!loading && !end && notifs.scrollHeight-notifs.clientHeight-notifs.scrollTop<20) {
+		loading=true;
+		chunk++;
+		let xhr=new XMLHttpRequest();
+		xhr.open('GET','notifsh.php?act=loadchunk&chunk='+chunk);
+		xhr.responseType='json';
+		xhr.send();
+		xhr.onload=function() {
+			let jarr=xhr.response;
+			//console.log(jarr);
+			let i=0, html='';
+			for (i=0; i<jarr.length; i++)
+				html+=jarr[i];
+			notifs.innerHTML+=html;
+			if (jarr.length<<?php echo($chunksize); ?>)
+				end=true;
+			loading=false;
+		};
+		xhr.onerror=function() {
+			alert('La richiesta è fallita.');
+		};
+	}
+}
+loadingupd=false;
+function updnotifs() {
+	if (!loadingupd) {
+		loadingupd=true;
+		let xhr=new XMLHttpRequest();
+		xhr.open('GET','notifsh.php?act=loadnew&lmt='+lmt);
+		xhr.responseType='json';
+		xhr.send();
+		xhr.onload=function() {
+			let jarr=xhr.response;
+			//console.log(jarr);
+			let i=0, html='';
+			for (i=0; i<jarr['buf'].length; i++)
+				html+=jarr['buf'][i];
+			notifs.innerHTML=html+notifs.innerHTML;
+			lmt=jarr['newlmt'];
+			if (jarr['newunread']) {
+				notifimgoff='imgs/bell_act_on.svg';
+				notifimgon='imgs/bell_act_off.svg';
+				(notifc.style.display=='block') ? bell.src=notifimgoff : bell.src=notifimgon;
+			}
+			loadingupd=false;
+		};
+		xhr.onerror=function() {
+			alert('La richiesta è fallita.');
+		};
+	} else {
+		console.log('Già sto caricando...');
+	}
+}
+updint=setInterval(updnotifs,3000);
 function hent(str) {
 	return str.replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;').replace(/"/g,'&quot;');
 }
@@ -932,11 +1055,14 @@ function pupoff() {
 <div class="mtit">Elenco istanze</div>
 <div id="rightdiv">
 	<img src="<?php echo($filtordimgoff); ?>" id="lente" class="rlinks" title="Mostra il pannello di ricerca e ordinamento" onclick="shideplancia();">
-	<a href="logout.php" class="rlinks"><img src="imgs/esci.svg" title="Esci"></a>
+	<img src="<?php echo($notifimgoff); ?>" id="bell" class="rlinks" title="Show notifications" onclick="shidenotifs();">
+	<img src="imgs/esci.svg" class="rlinks" title="Esci" onclick="document.location.href='logout.php';">
 </div>
 </div>
 </nav>
 
+<?php echo($notifs); ?>
+
 <div id="popup">
 <div id="inpopup">
 <div id="popupcont">

+ 55 - 0
web/admin/notifsh.php

@@ -0,0 +1,55 @@
+<?php
+
+header('Content-Type: application/json; charset=utf-8');
+
+require('include/glob.php');
+require('include/muoribene.php');
+require('include/sessionstart.php');
+
+if (array_key_exists('act',$_GET) && $_GET['act']=='markread' && array_key_exists('id',$_GET) && preg_match('/^[0-9]+$/',$_GET['id'])===1) {
+	$_GET['id']+=0;
+	require('include/myconn.php');
+	mysqli_query($link,'UPDATE Notifications SET Seen=1 WHERE ID='.$_GET['id'])
+		or muoribene(mysqli_error($link),true);
+	$res=mysqli_query($link,'SELECT ID FROM Notifications WHERE Seen=0')
+		or muoribene(mysqli_error($link),true);
+	echo('{"hmunseen":'.mysqli_num_rows($res).'}'.N);
+	mysqli_close($link);
+} elseif (array_key_exists('act',$_GET) && $_GET['act']=='loadchunk' && array_key_exists('chunk',$_GET) && preg_match('/^[0-9]+$/',$_GET['chunk'])===1) {
+	$_GET['chunk']+=0;
+	$chunksize=20; // questo dev'essere uguale in instances.php
+	require('include/myconn.php');
+	$res=mysqli_query($link,'SELECT * FROM Notifications ORDER BY Microtime DESC LIMIT '.($_GET['chunk']*$chunksize).','.$chunksize)
+		or muoribene(mysqli_error($link),true);
+	mysqli_close($link);
+	$buf=array();
+	while ($row=mysqli_fetch_assoc($res)) {
+		($row['Seen']==0) ? $notifclass='notifunseen' : $notifclass='notifseen';
+		$buf[]='<div id="notif-'.$row['ID'].'" class="'.$notifclass.'" onclick="markread(this)">'.strftime('%d/%m/%y %T',$row['Microtime']).': '.$row['Notification'].'</div>';
+	}
+	echo(json_encode($buf));
+} elseif (array_key_exists('act',$_GET) && $_GET['act']=='loadnew' && array_key_exists('lmt',$_GET) && preg_match('/^[0-9]+(\.[0-9]+)?$/',$_GET['lmt'])===1) {
+	$_GET['lmt']+=0;
+	$newlmt=$_GET['lmt'];
+	$newunread=false;
+	require('include/myconn.php');
+	$res=mysqli_query($link,'SELECT * FROM Notifications WHERE Microtime > '.$_GET['lmt'].' ORDER BY Microtime DESC')
+		or muoribene(mysqli_error($link),true);
+	mysqli_close($link);
+	$buf=array();
+	while ($row=mysqli_fetch_assoc($res)) {
+		if ($row['Seen']==0) {
+			$notifclass='notifunseen';
+			$newunread=true;
+		} else {
+			$notifclass='notifseen';
+		}
+		$buf[]='<div id="notif-'.$row['ID'].'" class="'.$notifclass.'" onclick="markread(this)">'.strftime('%d/%m/%y %T',$row['Microtime']).': '.$row['Notification'].'</div>';
+		if ($row['Microtime']+0>$newlmt) $newlmt=$row['Microtime'];
+	}
+	$buf=array('newlmt'=>$newlmt,'newunread'=>$newunread,'buf'=>$buf);
+	echo(json_encode($buf));
+}
+exit(0);
+
+?>

+ 42 - 0
web/admin/theme.css

@@ -701,6 +701,43 @@ input {
 	margin-top: 5px;
 }
 
+#notifc {
+	position: fixed;
+	top: 32px;
+	right: 0;
+	width: 200px;
+	height: 80%;
+	font-size: 9pt;
+	color: white;
+	background-color: rgba(0,0,0,0);
+	border-left: 3px solid rgba(0,0,0,0.85);
+	border-bottom:  3px solid rgba(0,0,0,0.85);
+	border-radius: 0 0 0 3px;
+	display: none;
+}
+#notifc a {
+	color: #ffeeaa;
+}
+#notifs {
+	height: calc(100% - 30px);
+	overflow-y: auto;
+}
+#notifa {
+	height: 30px;
+	line-height: 30px;
+	background-color: rgba(0,0,0,0.85);
+	text-align: center;
+}
+.notifseen, .notifunseen {
+	border-bottom: 1px solid white;
+	background-color: rgba(0,0,0,0.85);
+	padding: 2px;
+	cursor: pointer;
+}
+.notifunseen {
+	background-color: rgba(85,0,0,0.85);
+}
+
 #debug {
 	position: fixed;
 	left: 0;
@@ -712,6 +749,11 @@ input {
 	/*display: none;*/
 }
 
+#debugh {
+	font-size: 8pt;
+	/*display: none;*/
+}
+
 #intro {
 	width:720px;
 	margin-left:auto;

+ 4 - 4
web/home_fr.php

@@ -180,7 +180,7 @@ Fondamentalement, chaque instance peut interagir avec toutes les autres et déci
 <!-- Needs translation -->
 <section>
 <h3><a name="CopyRights" id="CopyRights" class="anchor"></a>Copy rights</h3>
-<p>{Needs translation} Every Instance is completely indipendent and has its own policy and terms of service. Therefore, when you publish something on Mastodon, your content is saved on your Instance’s server and every Istance will manage it in a different way, depending by its own rules.</p>
+<p>Every Instance is completely indipendent and has its own policy and terms of service. Therefore, when you publish something on Mastodon, your content is saved on your Instance’s server and every Istance will manage it in a different way, depending by its own rules.</p>
 <p>If you want to use Mastodon to promote your art or, for other reasons, you want to have certain specific guarantees for your content, you should choose an Instance specialized in that.</p>
 <p>Anyway, due the federated nature of Mastodon, your content could be boosted also on other Instances that could manage it in different ways.</p>
 <p>For the same reason if your Instance admin removes one of your posts, a copy of it can still be present on other Instances.</p>
@@ -233,7 +233,7 @@ Fondamentalement, chaque instance peut interagir avec toutes les autres et déci
 <!-- Needs translation -->
 <section>
 <h3><a name="LingoAndTranslations" id="LingoAndTranslations" class="anchor"></a>Lingo and translations</h3>
-<p>{Needs translation}Like every digital platform, Mastodon too renames functionalities that other platforms call differently.</p>
+<p>Like every digital platform, Mastodon too renames functionalities that other platforms call differently.</p>
 <p>For example the posts, or messages, that on Twitter are called “tweets”, on Mastodon are called “toots”. A shared post on certain platforms is called “repost” or “retweet” while here it’s called “boost”.</p>
 <p>Since you can access Mastodon with different Apps and frontends developed by different people it’s also possible that certain functionalities are called or translated differently. For example what is called “direct messages” on an App, on a different one is called “private messages”.</p>
 </section>
@@ -329,7 +329,7 @@ Mais alors, comment avec Mastodon découvrir et suivre de nouvelles personnes sa
 <!-- Needs translation -->
 <section>
 <h3><a name="ContentWarning" id="ContentWarning" class="anchor"></a>Content Warning</h3>
-<p>{Needs translation}Mastodon features a Content Warning system. It’s an optional mask that covers the content of a post with an editable warning message.</p>
+<p>Mastodon features a Content Warning system. It’s an optional mask that covers the content of a post with an editable warning message.</p>
 <p>It’s used to cover content that is admitted by your Instance policy but may still hurt people, like spoilers, nudity, depiction of violence or threads about sensitive topics.</p>
 <p>For example, if you want to start a thread about the ending of a fresh new movie, you can do it using a CW like “Spoiler about the ending of...”</p>
 <p>Every Instance has its own rules about CWs and therefore it’s common to see them used in different ways, like on selfies or depictions of food. That is because what on an Instance is considered a sensitive topic on another may be something commonly accepted. It’s possible that an Instance is blocked by others because of its misuse of CWs on certain kinds of topics.</p>
@@ -462,7 +462,7 @@ Si vous trouvez une vidéo PeerTube que vous voulez partager sur Mastodon, vous
 <p>Ce bouton ouvrira une fenêtre popup à partir de laquelle vous pourrez facilement copier l’URL d’une vidéo en cliquant sur le bouton “copier”:</p>
 <p><img src="<?php echo($prepath); ?>imgs/Peer2.png" class="image" alt="Capture d’écran montrant le dialogue de partage."></p>
 <!-- Needs translation -->
-<p>{Needs translation}Go to your Instance and paste the URL in the search box. The video appears in Mastodon and here you can like, comment or boost it. You can also decide to follow the user that posted the video. Everything as it was a Mastodon user.</p>
+<p>Go to your Instance and paste the URL in the search box. The video appears in Mastodon and here you can like, comment or boost it. You can also decide to follow the user that posted the video. Everything as it was a Mastodon user.</p>
 <p><img src="<?php echo($prepath); ?>imgs/Peer3.png" class="image" alt="Capture d’écran montrant la boite de recherche de Mastodon avec l’adresse de Peertube."></p>
 <p>Sinon, au cas où vous voudriez suivre seulement cet utilisateur, avec PeerTube vous pouvez cliquer sur le bouton “S’abonner”:</p>
 <p>

+ 1 - 1
web/home_it.php

@@ -405,7 +405,7 @@ Si tratta di una maschera che, quando impostata, copre il contenuto di un post e
 <li><a href="https://pixelfed.org/join">PixelFed</a> è simile a Instagram;</li>
 <li><a href="https://joinpeertube.org">PeerTube</a> è simile a Youtube;</li>
 <li><a href="https://friendi.ca">Friendica</a> è simile a Facebook;</li>
-<li><a href="https://funkwhale.audio">FunkWhale</a> è simile a to Soundcloud;</li>
+<li><a href="https://funkwhale.audio">FunkWhale</a> è simile a Soundcloud;</li>
 <li><a href="https://writefreely.org/instances">Write.as</a> e <a href="https://joinplu.me">Plume</a> sono piattaforme di blogging;</li>
 <li><a href="https://hubzilla.eu">Hubzilla</a> è una potente piattaforma multi-funzionale.</li>
 </ul>

+ 1 - 1
web/index.php

@@ -21,8 +21,8 @@ if (preg_match('#/('.implode('|',$supplangs).')$#',$path,$lang)===1) {
 	$path=substr($path,0,-3);
 } else {
 	$dlang=substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2);
+	$dlang=in_array($dlang,$supplangs) ? $dlang : 'en';
 }
-$dlang=in_array($dlang,$supplangs) ? $dlang : 'en';
 
 $menu=array(
 	'guide'=>array('liadd'=>null, 'href'=>$instpath.'/'.$dlang, 'title'=>'Guide', 'selected'=>false, 'submenu'=>null),

+ 1 - 1
web/theme.css

@@ -32,12 +32,12 @@ html {
 	scroll-behavior: smooth;
 }
 body {
+  	background-color: #eeeeee;
 	background-image: url('imgs/mascotte_left_mod.png'), url('imgs/mascotte_right.png'), linear-gradient(#eeeeee, #3088d4);
 	background-repeat: no-repeat;
 	background-attachment: fixed;
 	background-position: bottom left, bottom right, top left;
 	background-size: 338px, 372px, auto;
-  	background-color: #eeeeee;
 	color: black;
 /*	font-family: Roboto-slab, serif;*/
 	font-family: Titillium, sans;