diff --git a/api/flag_add.php b/api/flag_add.php new file mode 100644 index 0000000..9ba53e6 --- /dev/null +++ b/api/flag_add.php @@ -0,0 +1,18 @@ +getClipID() == 0) + exit; + + $flag = new Flag(); + $flag->setUserID(User::$currentUser->getUserID()); + $flag->setSourceID($clip->getSourceID()); + $flag->setTime($clip->getStart() + (isset($_POST['time'])?$_POST['time']:0)); + $flag->setType((isset($_POST['type'])?$_POST['type']:"")); + $flag->save(); +?> \ No newline at end of file diff --git a/datarake.php b/datarake.php index 4a45669..e3f4310 100644 --- a/datarake.php +++ b/datarake.php @@ -15,6 +15,8 @@ $mysqli->query("delete from clips"); $mysqli->query("delete from users_interests"); $mysqli->query("delete from sources"); +$mysqli->query("delete from contexts"); +$mysqli->query("delete from flags"); $regionUSA = new Interest(); $regionUSA->setName("United States of America"); diff --git a/head.php b/head.php index 5002b9b..9a41ecf 100644 --- a/head.php +++ b/head.php @@ -1,7 +1,6 @@ + query("DELETE from appinfo") or print($mysqli->error); $mysqli->query("INSERT into appinfo (version) values ('11');") or print($mysqli->error); + case 11: + echo("Creating context table\n"); + $mysqli->query("CREATE table contexts (id int auto_increment primary key, + source_id int, + time int, + title int, + url varchar(255), + description text, + creation_date datetime)") or print($mysqli->error); + echo("Updating clips table\n"); + $mysqli->query("ALTER table clips + change column start start int, + change column end end int") or print($mysqli->error); + + echo("Updating app version\n"); + $mysqli->query("DELETE from appinfo") or print($mysqli->error); + $mysqli->query("INSERT into appinfo (version) values ('12');") or print($mysqli->error); + + case 12: + echo("Creating flags table\n"); + $mysqli->query("CREATE table flags (id int auto_increment primary key, + source_id int, + user_id int, + time int, + type varchar(16), + creation_date datetime)") or print($mysqli->error); + + echo("Updating app version\n"); + $mysqli->query("DELETE from appinfo") or print($mysqli->error); + $mysqli->query("INSERT into appinfo (version) values ('13');") or print($mysqli->error); + default: echo("Finished updating the schema\n"); } diff --git a/models/Clip.php b/models/Clip.php index 2cd8619..3389709 100644 --- a/models/Clip.php +++ b/models/Clip.php @@ -1,5 +1,6 @@ clipOrder = 0; $this->feedURL = ""; $this->contextURL = ""; - $this->start = ""; - $this->end = ""; + $this->start = 0; + $this->end = 0; $this->description = ""; $this->title = ""; $this->thumbnail = ""; @@ -65,8 +66,8 @@ public function save() { clips.clip_order = ".$this->getClipOrder().", clips.contextURL = '".DBConn::clean_for_mysql($this->getContextURL())."', clips.feedURL = '".DBConn::clean_for_mysql($this->getFeedURL())."', - clips.start = '".DBConn::clean_for_mysql($this->getStart())."', - clips.end = '".DBConn::clean_for_mysql($this->getEnd())."', + clips.start = ".DBConn::clean_for_mysql($this->getStart()).", + clips.end = ".DBConn::clean_for_mysql($this->getEnd()).", clips.description = '".DBConn::clean_for_mysql($this->getDescription())."', clips.title = '".DBConn::clean_for_mysql($this->getTitle())."', clips.thumbnail = '".DBConn::clean_for_mysql($this->getThumbnail())."' @@ -85,8 +86,8 @@ public function save() { ".$this->getClipOrder().", '".DBConn::clean_for_mysql($this->getContextURL())."', '".DBConn::clean_for_mysql($this->getFeedURL())."', - '".DBConn::clean_for_mysql($this->getStart())."', - '".DBConn::clean_for_mysql($this->getEnd())."', + ".DBConn::clean_for_mysql($this->getStart()).", + ".DBConn::clean_for_mysql($this->getEnd()).", '".DBConn::clean_for_mysql($this->getDescription())."', '".DBConn::clean_for_mysql($this->getTitle())."', '".DBConn::clean_for_mysql($this->getThumbnail())."')"; @@ -123,7 +124,25 @@ public function getDescription() { return $this->description; } public function getTitle() { return $this->title; } public function getThumbnail() { return $this->thumbnail; } + + public function getFlags() { + $mysqli = DBConn::mysqli_connect(); + $queryString = "select flags.id as flagID + from flags + where flags.source_id = ".$this->getSourceID()." + and flags.time >= ".$this->getStart()." + and flags.time <= ".$this->getEnd(); + + $result = $mysqli->query($queryString) + or print($mysqli->error); + + $flagIDs = array(); + while($resultArray = $result->fetch_assoc()) + $flagIDs[] = $resultArray['flagID']; + return FlagFactory::getObjects($flagIDs); + } + # Setters public function setEpisodeID($int) { $this->episodeID = $int;} @@ -136,11 +155,11 @@ public function setFeedURL($str) { $this->feedURL = $str;} public function setContextURL($str) { $this->contextURL = $str;} - public function setStart($str) { $this->start = $str;} + public function setStart($int) { $this->start = $int;} public function setClipOrder($int) { $this->clipOrder = $int;} - public function setEnd($str) { $this->end = $str;} + public function setEnd($int) { $this->end = $int;} public function setDescription($str) { $this->description = $str;} diff --git a/models/Context.php b/models/Context.php new file mode 100644 index 0000000..6e2b368 --- /dev/null +++ b/models/Context.php @@ -0,0 +1,103 @@ +contextID = 0; + $this->sourceID = 0; + $this->time = ""; + $this->title = ""; + $this->url = ""; + $this->description = ""; + $this->dateCreated = 0; + } + + public function load($dataArray) { + $this->contextID = $dataArray['contextID']; + $this->sourceID = $dataArray['sourceID']; + $this->time = $dataArray['time']; + $this->title = $dataArray['title']; + $this->url = $dataArray['url']; + $this->description = $dataArray['description']; + $this->dateCreated = $dataArray['dateCreated']; + } + + public function validate() { + return true; + } + + public function save() { + if(!$this->validate()) + return false; + + $mysqli = DBConn::mysqli_connect(); + if($this->getContextID() != 0) { + // Update an existing context + $queryString = "UPDATE contexts + set contexts.sourceID = '".$this->getSourceID()."', + contexts.time = ".$this->getTime()."', + contexts.title = '".DBConn::clean_for_mysql($this->getTitle())."', + contexts.url = '".DBConn::clean_for_mysql($this->getURL())."', + contexts.description = '".DBConn::clean_for_mysql($this->getDescription())."' + where contexts.id = ".$this->getContextID(); + + $mysqli->query($queryString) + or print($mysqli->error); + } + else { + // Create a new context + $queryString = "INSERT into contexts + values (0, + ".$this->getSourceID().", + ".$this->getTime().", + '".DBConn::clean_for_mysql($this->getTitle())."', + '".DBConn::clean_for_mysql($this->getURL())."', + '".DBConn::clean_for_mysql($getDescription)."', + NOW())"; + + $mysqli->query($queryString) + or print($mysqli->error); + + $this->userID = $mysqli->insert_id; + } + } + + + # Getters + public function getContextID() { return $this->contextID; } + + public function getSourceID() { return $this->sourceID; } + + public function getTime() { return $this->time; } + + public function getTitle() { return $this->title; } + + public function getURL() { return $this->url; } + + public function getDescription() { return $this->description; } + + public function getDateCreated() { return $this->dateCreated; } + + + # Setters + public function setSourceID($int) { $this->sourceID = $int; } + + public function setTime($int) { $this->time = $int; } + + public function setTitle($str) { $this->title = $str;} + + public function setURL($str) { $this->url = $str;} + + public function setDescription($str) { $this->description = $str;} +} + +?> \ No newline at end of file diff --git a/models/ContextFactory.php b/models/ContextFactory.php new file mode 100644 index 0000000..44e9f54 --- /dev/null +++ b/models/ContextFactory.php @@ -0,0 +1,101 @@ +contextID = $dataArray['contextID']; + $this->sourceID = $dataArray['sourceID']; + $this->time = $dataArray['time']; + $this->title = $dataArray['title']; + $this->url = $dataArray['url']; + $this->description = $dataArray['description']; + $this->dateCreated = $dataArray['dateCreated']; + // Load the object data + $queryString = "select contexts.id as contextID, + contexts.source_id as sourceID, + contexts.time as time, + contexts.title as title, + contexts.url as url, + contexts.description as description, + contexts.creation_date as dateCreated + from contexts + where contexts.id = ".$objectID; + + $result = $mysqli->query($queryString) + or print($mysqli->error); + + if($result->num_rows == 0) { + $result->free(); + return new Clip(); + } + + $resultArray = $result->fetch_assoc(); + $result->free(); + + $dataArray['contextID'] = $resultArray['contextID']; + $dataArray['sourceID'] = $resultArray['sourceID']; + $dataArray['time'] = $resultArray['time']; + $dataArray['title'] = $resultArray['title']; + $dataArray['url'] = $resultArray['url']; + $dataArray['description'] = $resultArray['description']; + $dataArray['dateCreated'] = $resultArray['dateCreated']; + + $newObject = new Context(); + $newObject->load($dataArray); + return $newObject; + } + + public static function getObjects($objects) { + $objectIDs = array(); + foreach($objects as $object) + $objectIDs[] = (int)$object; + + // If there are no objects being request, return an empty array + if(sizeof($objectIDs) == 0) + return array(); + + $objectIDString = implode(",",$objectIDs); + $mysqli = DBConn::mysqli_connect(); + $dataArrays = array(); + + // Load the object data + $queryString = "select contexts.id as contextID, + contexts.source_id as sourceID, + contexts.time as time, + contexts.title as title, + contexts.url as url, + contexts.description as description, + contexts.creation_date as dateCreated + from contexts + where contexts.id IN (".$objectIDString.") + order by contexts.time"; + + $result = $mysqli->query($queryString) + or print($mysqli->error); + while($resultArray = $result->fetch_assoc()) { + $dataArray = array(); + $dataArray['contextID'] = $resultArray['contextID']; + $dataArray['sourceID'] = $resultArray['sourceID']; + $dataArray['time'] = $resultArray['time']; + $dataArray['title'] = $resultArray['title']; + $dataArray['url'] = $resultArray['url']; + $dataArray['description'] = $resultArray['description']; + $dataArray['dateCreated'] = $resultArray['dateCreated']; + $dataArrays[] = $dataArray; + } + + // Create the objects + $objectArray = array(); + foreach($dataArrays as $dataArray) { + $newObject = new Context(); + $newObject->load($dataArray); + $objectArray[] = $newObject; + } + return $objectArray; + } +} +?> \ No newline at end of file diff --git a/models/Flag.php b/models/Flag.php new file mode 100644 index 0000000..d28f64f --- /dev/null +++ b/models/Flag.php @@ -0,0 +1,94 @@ +flagID = 0; + $this->sourceID = 0; + $this->userID = 0; + $this->time = 0; + $this->type = ""; + $this->dateCreated = 0; + } + + public function load($dataArray) { + $this->flagID = $dataArray['flagID']; + $this->sourceID = $dataArray['sourceID']; + $this->userID = $dataArray['userID']; + $this->time = $dataArray['time']; + $this->type = $dataArray['type']; + $this->dateCreated = $dataArray['dateCreated']; + } + + public function validate() { + return true; + } + + public function save() { + if(!$this->validate()) + return false; + + $mysqli = DBConn::mysqli_connect(); + if($this->getFlagID() != 0) { + // Update an existing flag + $queryString = "UPDATE flags + set flags.source_id = ".$this->getSourceID().", + flags.user_id = ".$this->getUserID().", + flags.time = ".$this->getTime().", + flags.type = '".DBConn::clean_for_mysql($this->getType())."' + where flags.id = ".$this->getFlagID(); + + $mysqli->query($queryString) + or print($mysqli->error); + } + else { + // Create a new flag + $queryString = "INSERT into flags + values (0, + ".$this->getSourceID().", + ".$this->getUserID().", + ".$this->getTime().", + '".DBConn::clean_for_mysql($this->getType())."', + NOW())"; + + $mysqli->query($queryString) + or print($mysqli->error); + + $this->clipID = $mysqli->insert_id; + } + } + + + # Getters + public function getFlagID() { return $this->flagID; } + + public function getSourceID() { return $this->sourceID; } + + public function getUserID() { return $this->userID; } + + public function getTime() { return $this->time; } + + public function getType() { return $this->type; } + + public function getDateCreated() { return $this->dateCreated; } + + + # Setters + public function setSourceID($int) { $this->sourceID = $int;} + + public function setUserID($int) { $this->userID = $int;} + + public function setTime($int) { $this->time = $int;} + + public function setType($str) { $this->type = $str;} +} + +?> \ No newline at end of file diff --git a/models/FlagFactory.php b/models/FlagFactory.php new file mode 100644 index 0000000..ed95b0b --- /dev/null +++ b/models/FlagFactory.php @@ -0,0 +1,89 @@ +query($queryString) + or print($mysqli->error); + + if($result->num_rows == 0) { + $result->free(); + return new Episode(); + } + + $resultArray = $result->fetch_assoc(); + $result->free(); + + $dataArray['flagID'] = $resultArray['flagID']; + $dataArray['sourceID'] = $resultArray['sourceID']; + $dataArray['userID'] = $resultArray['userID']; + $dataArray['time'] = $resultArray['time']; + $dataArray['type'] = $resultArray['type']; + $dataArray['dateCreated'] = $resultArray['dateCreated']; + + $newObject = new Flag(); + $newObject->load($dataArray); + return $newObject; + } + + public static function getObjects($objects) { + $objectIDs = array(); + foreach($objects as $object) + $objectIDs[] = (int)$object; + + // If there are no objects being request, return an empty array + if(sizeof($objectIDs) == 0) + return array(); + + $objectIDString = implode(",",$objectIDs); + $mysqli = DBConn::mysqli_connect(); + $dataArrays = array(); + + // Load the object data + $queryString = "select flags.id as flagID, + flags.source_id as sourceID, + flags.user_id as userID, + flags.time as time, + flags.type as type, + unix_timestamp(flags.creation_date) as dateCreated + from flags + where flags.id IN (".$objectIDString.")"; + + $result = $mysqli->query($queryString) + or print($mysqli->error); + while($resultArray = $result->fetch_assoc()) { + $dataArray = array(); + $dataArray['flagID'] = $resultArray['flagID']; + $dataArray['sourceID'] = $resultArray['sourceID']; + $dataArray['userID'] = $resultArray['userID']; + $dataArray['time'] = $resultArray['time']; + $dataArray['type'] = $resultArray['type']; + $dataArray['dateCreated'] = $resultArray['dateCreated']; + $dataArrays[] = $dataArray; + } + + // Create the objects + $objectArray = array(); + foreach($dataArrays as $dataArray) { + $newObject = new Flag(); + $newObject->load($dataArray); + $objectArray[] = $newObject; + } + return $objectArray; + } +} +?> \ No newline at end of file diff --git a/pages/episode/view/view.css b/pages/episode/view/view.css index 68f33aa..0d50f94 100644 --- a/pages/episode/view/view.css +++ b/pages/episode/view/view.css @@ -14,14 +14,26 @@ video { border: 4px solid #000000;} .attn-timeline { width: 350px; } -.attn-timeline-clip { display: inline-block; border: 3px solid #660000; margin: 10px; height:30px; cursor: pointer;} +.attn-timeline-clip { display: inline-block; border: 3px solid #000000; margin: 10px; height:30px; cursor: pointer;} .attn-timeline-clip img {height: 100%;} .attn-timeline-clip.loaded { height: 40px; margin: 5px;} .attn-timeline-clip.active { border: 3px solid #aacc00; height: 40px; margin: 5px;} .attn-timeline-clip.viewed { border: 3px solid #006600; } -.attn-information {float: left; width: 350px; height: 300px; margin-left: 10px;} +.attn-information {float: left; width: 350px; height: 200px; margin-left: 10px;} .attn-information-title {} .attn-information-description {} -.attn-information-context {} \ No newline at end of file +.attn-information-context {} + +.attn-social {float: left; height: 100px; width: 350px; margin-left: 10px;} +.attn-social-good {float: left; height: 20px; width: 100px; margin-left: 50px; text-align: center; + border-radius: 15px; + background: #008800; + cursor: pointer; +} +.attn-social-bad {float: left; height: 20px; width: 100px; margin-left: 50px; text-align: center; + border-radius: 15px; + background: #880000; + cursor: pointer; +} \ No newline at end of file diff --git a/pages/episode/view/view.js b/pages/episode/view/view.js index 674ead6..f5ca06a 100644 --- a/pages/episode/view/view.js +++ b/pages/episode/view/view.js @@ -14,10 +14,21 @@ var CLASS_INFORMATION_DESCRIPTION = "attn-information-description"; var CLASS_INFORMATION_CONTEXT = "attn-information-context"; + var CLASS_SOCIAL = "attn-social"; + var CLASS_SOCIAL_GOOD = "attn-social-good"; + var CLASS_SOCIAL_BAD = "attn-social-bad"; + var FLAG_GOOD = "good"; + var FLAG_BAD = "bad"; + + var API_FLAG_ADD = "api/flag_add.php"; + + var goodCount = 0; + var badCount = 0; var methods = { init: function() { + var attnPlayer = this; this.addClass(CLASS_PLAYER); // Video Container @@ -42,14 +53,54 @@ $information.append($description); $information.append($context); + // Social Layer + $social = $("
"); + $social.addClass(CLASS_SOCIAL); + + $good = $("
"); + $good.html("Yay!"); + $good.bind("click", function() { + attnPlayer.attnPlayer("flagMoment", FLAG_GOOD); + }); + $good.addClass(CLASS_SOCIAL_GOOD); + + $bad = $("
"); + $bad.html("Boo!"); + $bad.bind("click", function() { + attnPlayer.attnPlayer("flagMoment", FLAG_BAD); + }); + $bad.addClass(CLASS_SOCIAL_BAD); + + $social.append($good); + $social.append($bad); + // Append them all this.append($videoContainer); this.append($information); + this.append($social); this.append($timeline); return this; }, + flagMoment: function(flagType) { + var clipList = this.data(DATA_CLIPS); + var currentClip = this.data(DATA_CURRENT_CLIP); + var $clip = $("#clip" + currentClip); + var timeOffset = $clip[0].currentTime; + + var flagData = { + type: flagType, + clipID: clipList[currentClip].clipID, + time: timeOffset + }; + + $.ajax(API_FLAG_ADD, { + data: flagData, + type: "POST" + }); + }, + load: function(clipList) { this.data(DATA_CLIPS, clipList); this.data(DATA_CURRENT_CLIP, 0); @@ -96,6 +147,36 @@ $videoEl = $("