Browse Source

Basic implementation for tags
- Edit Tags
- Delete Tags
- Search Tags

Multiselect:
- Only when logged in

Tobias Reich 10 years ago
parent
commit
be404366bc

+ 6 - 1
assets/css/modules/infobox.css

@@ -131,10 +131,15 @@
 
 	/* Tags ------------------------------------------------*/
 	#infobox #tags {
-		margin: 20px 20px 15px 20px;
+		width: calc(100% - 40px);
+		margin: 16px 20px 12px 20px;
 		color: #fff;
 		display: inline-block;
 	}
+	#infobox #tags .empty {
+		font-size: 14px;
+		margin-bottom: 8px;
+	}
 	#infobox .tag {
 		float: left;
 		padding: 4px 7px;

+ 33 - 9
assets/js/modules/build.js

@@ -18,11 +18,11 @@ build = {
 		return "<div id='" + id + "' class='edit'><a class='icon-pencil'></a></div>";
 
 	},
-		
+
 	multiselect: function(top, left) {
-	
+
 		return "<div id='multiselect' style='top: " + top + "px; left: " + left + "px;'></div>";
-	
+
 	},
 
 	album: function(albumJSON) {
@@ -37,7 +37,7 @@ build = {
 			title = albumJSON.title.substr(0, 18) + "...";
 			longTitle = albumJSON.title;
 		}
-		
+
 		typeThumb0 = albumJSON.thumb0.split('.').pop();
 		typeThumb1 = albumJSON.thumb1.split('.').pop();
 		typeThumb2 = albumJSON.thumb2.split('.').pop();
@@ -241,6 +241,32 @@ build = {
 
 	},
 
+	tags: function(tags, forView) {
+
+		var html = "",
+			editTagsHTML;
+
+		if (tags!=="") {
+
+			tags = tags.split(",");
+
+			tags.forEach(function(tag, index, array) {
+
+				html += "<a class='tag'>" + tag + "<span class='icon-remove' data-index='" + index + "'></span></a>";
+
+			});
+
+		} else {
+
+			editTagsHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_tags");
+			html = "<div class='empty'>No Tags" + editTagsHTML + "</div>";
+
+		}
+
+		return html;
+
+	},
+
 	infoboxPhoto: function(photoJSON, forView) {
 
 		if (!photoJSON) return "";
@@ -272,7 +298,6 @@ build = {
 		editTitleHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_title");
 		editDescriptionHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_description");
 
-		//["Tags", "<a class='tag'>Abstract<span class='icon-remove'></span></a><a class='tag'>Colors<span class='icon-remove'></span></a><a class='tag'>Photoshop<span class='icon-remove'></span></a><a class='tag'>Something<span class='icon-remove'></span></a><a class='tag'>Lychee<span class='icon-remove'></span></a><a class='tag'>Tags<span class='icon-remove'></span></a><a class='tag icon-plus'></a>"]
 		infos = [
 			["", "Basics"],
 			["Name", photoJSON.title + editTitleHTML],
@@ -281,7 +306,8 @@ build = {
 			["", "Image"],
 			["Size", photoJSON.size],
 			["Format", photoJSON.type],
-			["Resolution", photoJSON.width + " x " + photoJSON.height]
+			["Resolution", photoJSON.width + " x " + photoJSON.height],
+			["Tags", build.tags(photoJSON.tags, forView)]
 		];
 
 		if ((photoJSON.takedate+photoJSON.make+photoJSON.model+photoJSON.shutter+photoJSON.aperture+photoJSON.focal+photoJSON.iso)!="") {
@@ -319,9 +345,7 @@ build = {
 				case "Tags":	// Tags
 								infobox += "</table>";
 								infobox += "<div class='separator'><h1>" + infos[index][0] + "</h1></div>";
-								infobox += "<tr>";
-								infobox +=		"<div id='tags'>" + infos[index][1] + "</div>";
-								infobox += "</tr>";
+								infobox += "<div id='tags'>" + infos[index][1] + "</div>";
 								break;
 
 				default:		// Item

+ 2 - 2
assets/js/modules/contextMenu.js

@@ -110,8 +110,8 @@ contextMenu = {
 		if (albumID==="0"||albumID==="f"||albumID==="s") return false;	
 
 		contextMenu.fns = [
-			function() { album.setTitle(albumID) },
-			function() { album.delete(albumID) }
+			function() { album.setTitle([albumID]) },
+			function() { album.delete([albumID]) }
 		];
 
 		items = [

+ 6 - 4
assets/js/modules/init.js

@@ -35,7 +35,7 @@ $(document).ready(function(){
 		else modal.show("Share Album", "All photos inside this album will be public and visible for everyone. Existing public photos will have the same sharing permission as this album. Are your sure you want to share this album? <input class='text' type='password' placeholder='password (optional)' value=''>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]]);
 	});
 	$("#button_download").on(event_name, function() { photo.getArchive(photo.getID()) });
-	$("#button_trash_album").on(event_name, function() { album.delete(album.getID()) });
+	$("#button_trash_album").on(event_name, function() { album.delete([album.getID()]) });
 	$("#button_move").on(event_name, function(e) { contextMenu.move([photo.getID()], e) });
 	$("#button_trash").on(event_name, function() { photo.delete([photo.getID()]) });
 	$("#button_info_album").on(event_name, function() { view.infobox.show() });
@@ -68,10 +68,12 @@ $(document).ready(function(){
 	/* Infobox */
 	$("#infobox")
 		.on(event_name, ".header a", function() { view.infobox.hide() })
-		.on(event_name, "#edit_title_album", function() { album.setTitle(album.getID()) })
+		.on(event_name, "#edit_title_album", function() { album.setTitle([album.getID()]) })
 		.on(event_name, "#edit_description_album", function() { album.setDescription(album.getID()) })
 		.on(event_name, "#edit_title", function() { photo.setTitle([photo.getID()]) })
-		.on(event_name, "#edit_description", function() { photo.setDescription(photo.getID()) });
+		.on(event_name, "#edit_description", function() { photo.setDescription(photo.getID()) })
+		.on(event_name, "#edit_tags", function() { photo.editTags([photo.getID()]) })
+		.on(event_name, "#tags .tag span", function() { photo.deleteTag(photo.getID(), $(this).data('index')) });
 
 	/* Keyboard */
 	Mousetrap
@@ -108,7 +110,7 @@ $(document).ready(function(){
 		/* Header */
 		.on(event_name, "#title.editable", function() {
 			if (visible.photo()) photo.setTitle([photo.getID()]);
-			else album.setTitle(album.getID());
+			else album.setTitle([album.getID()]);
 		})
 
 		/* Navigation */

+ 3 - 2
assets/js/modules/multiselect.js

@@ -19,6 +19,7 @@ multiselect = {
 	show: function(e) {
 	
 		if (mobileBrowser()) return false;
+		if (lychee.publicMode) return false;
 		if ($('.album:hover, .photo:hover').length!=0) return false;
 		if (visible.multiselect()) $('#multiselect').remove();
 	
@@ -133,7 +134,7 @@ multiselect = {
 				
 					id = $(this).data('id');
 					
-					if (id!=="0"&&id!==0&&id!=="f"&&id!=="s"&&id!==null&id!==undefined) {
+					if (id!=='0'&&id!==0&&id!=='f'&&id!=='s'&&id!==null&id!==undefined) {
 				
 						ids.push(id);
 						$(this).addClass('active');
@@ -159,7 +160,7 @@ multiselect = {
 		multiselect.position.bottom = null;
 		multiselect.position.left = null;
 		
-		lychee.animate('#multiselect', "fadeOut");
+		lychee.animate('#multiselect', 'fadeOut');
 		setTimeout(function() {
 			$('#multiselect').remove();
 		}, 300);

+ 62 - 0
assets/js/modules/photo.js

@@ -302,7 +302,69 @@ photo = {
 		modal.show("Set Description", "Please enter a description for this photo: <input class='text' type='text' placeholder='Description' value='" + oldDescription + "'>", buttons);
 
 	},
+	
+	editTags: function(photoIDs) {
+	
+		var oldTags = "";
+	
+		if (!photoIDs) return false;
+		if (photoIDs instanceof Array===false) photoIDs = [photoIDs];
+		if (visible.photo()) oldTags = photo.json.tags;
+	
+		buttons = [
+			["Set Tags", function() {
+
+				tags = $(".message input.text").val();
 
+				if (tags.length<800) {
+
+					if (visible.photo()) {
+						photo.json.tags = tags;
+						view.photo.tags();
+					}
+
+					photo.setTags(photoIDs, tags)
+
+				} else loadingBar.show("error", "Description too long. Please try again!");
+
+			}],
+			["Cancel", function() {}]
+		];
+		modal.show("Set Tags", "Please enter your tags for this photo. You can add multiple tags by separating them with a comma: <input class='text' type='text' placeholder='Tags' value='" + oldTags + "'>", buttons);
+	
+	},
+	
+	setTags: function(photoIDs, tags) {
+		
+		var params;
+	
+		if (!photoIDs) return false;
+		if (photoIDs instanceof Array===false) photoIDs = [photoIDs];
+		
+		params = "setTags&photoIDs=" + photoIDs + "&tags=" + tags;
+		lychee.api(params, function(data) {
+
+			if (data!==true) lychee.error(null, params, data);
+
+		});
+	
+	},
+		
+	deleteTag: function(photoID, index) {
+		
+		var tags;
+	
+		// Remove
+		tags = photo.json.tags.split(',');
+		tags.splice(index, 1);
+				
+		// Save
+		photo.json.tags = tags.toString();
+		view.photo.tags();
+		photo.setTags([photoID], photo.json.tags);
+	
+	},
+		
 	share: function(photoID, service) {
 
 		var link = "",

+ 6 - 0
assets/js/modules/view.js

@@ -447,6 +447,12 @@ view = {
 			}
 
 		},
+		
+		tags: function() {
+		
+			$("#infobox #tags").html(build.tags(photo.json.tags));
+		
+		},
 
 		photo: function() {
 

+ 11 - 0
php/api.php

@@ -24,6 +24,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
 	require('modules/upload.php');
 	require('modules/album.php');
 	require('modules/photo.php');
+	require('modules/tags.php');
 	require('modules/misc.php');
 
 	if (file_exists('config.php')) require('config.php');
@@ -157,6 +158,16 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
 			case 'search':			if (isset($_POST['term']))
 										echo json_encode(search($_POST['term']));
 									break;
+									
+			// Tag Functions
+			
+			case 'getTags':			if (isset($_POST['photoID']))
+										echo json_encode(getTags($_POST['photoID']));
+									break;
+			
+			case 'setTags':			if (isset($_POST['photoIDs'])&&isset($_POST['tags']))
+										echo setTags($_POST['photoIDs'], $_POST['tags']);
+									break;
 
 			// Session Function
 

+ 1 - 1
php/modules/album.php

@@ -16,8 +16,8 @@ function addAlbum($title) {
     if (strlen($title)<1||strlen($title)>30) return false;
     $sysdate = date("d.m.Y");
     $result = $database->query("INSERT INTO lychee_albums (title, sysdate) VALUES ('$title', '$sysdate');");
+    
     if (!$result) return false;
-
     return $database->insert_id;
 
 }

+ 1 - 0
php/modules/db.php

@@ -152,6 +152,7 @@ function createTables($database) {
 				`title` varchar(50) NOT NULL,
 				`description` varchar(1000) NOT NULL DEFAULT '',
 				`url` varchar(100) NOT NULL,
+				`tags` varchar(1000) NOT NULL DEFAULT '',
 				`public` tinyint(1) NOT NULL,
 				`type` varchar(10) NOT NULL,
 				`width` int(11) NOT NULL,

+ 3 - 3
php/modules/misc.php

@@ -44,13 +44,13 @@ function search($term) {
 
 	$return["albums"] = "";
 
-    $result = $database->query("SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%';");
+    $result = $database->query("SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%' OR tags like '%$term%';");
     while($row = $result->fetch_array()) {
         $return['photos'][$row['id']] = $row;
         $return['photos'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate']));
     }
 
-    $result = $database->query("SELECT * FROM lychee_albums WHERE title like '%$term%';");
+    $result = $database->query("SELECT * FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';");
     $i=0;
     while($row = $result->fetch_object()) {
 
@@ -85,7 +85,7 @@ function update() {
 	if($database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE  `lychee_albums` CHANGE  `password` `password` VARCHAR( 100 ) NULL DEFAULT ''");
 
 	if($database->query("SELECT `description` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE  `lychee_photos` CHANGE  `description` `description` VARCHAR( 1000 ) NULL DEFAULT ''");
-	if($database->query("SELECT `shortlink` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE  `lychee_photos` DROP  `shortlink`");
+	if(!$database->query("SELECT `tags` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE  `lychee_photos` ADD  `tags` VARCHAR( 1000 ) NULL DEFAULT ''");
 	$database->query("UPDATE `lychee_photos` SET url = replace(url, 'uploads/big/', ''), thumbUrl = replace(thumbUrl, 'uploads/thumb/', '')");
 	
 	$result = $database->query("SELECT `value` FROM `lychee_settings` WHERE `key` = 'importFilename' LIMIT 1;");

+ 38 - 0
php/modules/tags.php

@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @name        Album Module
+ * @author      Tobias Reich
+ * @copyright   2014 by Philipp Maurer, Tobias Reich
+ */
+
+if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
+
+function getTags($photoID) {
+
+	global $database;
+
+	$result = $database->query("SELECT tags FROM lychee_photos WHERE id = '$photoID';");
+	$return = $result->fetch_array();
+
+	if (!$result) return false;
+	return $return;
+
+}
+
+function setTags($photoIDs, $tags) {
+
+	global $database;
+
+	if (substr($tags, strlen($tags)-1)===',') $tags = substr($tags, 0, strlen($tags)-1);
+	$tags = str_replace(' , ', ',', $tags);
+	$tags = str_replace(', ', ',', $tags);
+	$tags = str_replace(' ,', ',', $tags);
+	$tags = str_replace(',,', ',', $tags);
+
+	$result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);");
+
+	if (!$result) return false;
+	return true;
+
+}