Tuesday, July 22, 2014

Umbraco + TweetInvi + JQuery Social Stream Wall

I just spent days to figure out the best Twitter library using OAuth that we can use on our Umbraco websites and a JQuery plugin that could display various social media widgets on a "wall".

Here's the major problem:






  • We don't want to do any custom codes and recompile an Umbraco installation  nor create a package / plugin because we are new to Umbraco and we don't have the time yet to learn how to create Umbraco packages.

  • By searching through the internet forums and doing some code testings, we found out that TweetInvi and JQuery Social Stream could help us achieve our goals. These two libraries are just awesome and it did saved our day!

    But here are more problems:

    • JQuery Social Stream is using a PHP class for the Twitter OAuth as an example and we are using Umbraco (C#)
    • We don't want to create another site just to host the PHP class.
    • TweetInvi returns an IEnumerable rather than a JSON object that can be easily passed to any Javascript library, which means we might have to use another library to convert these objects to JSON
    • I couldn't find any samples on the web that have used both TweetInvi and JQuery Social Stream under an Umbraco website.

    These are all simple problems but not for me as I am not an expert in any of these libraries and Umbraco. So I have to deal with this especially that my company have already purchased a license for JQuery Social Stream.

    Fortunately, Lee Chestnutt (JQuery Social Stream) and Linvi (TweetInvi) have quickly responded to my queries and Linvi's source code is available on GitHub for download in which I could just browse and check if there's any functions available that I could use.

    So far, here are the solutions to these simple problems:

    1. Copy all TweetInvi dlls into the Umbraco installation bin folder
    2. Create a new template under Umbraco
    3. Create a new macro (partial view macro)
    4. Use TweetInvi to authenticate your site to Twitter. You can include this on the Umbraco template or on a macro
    5. Use TweetInvi's function "Tweetinvi.Json.TimelineJson.GetUserTimeline" to retrieve the twitter timeline as json
    6. Render the result as JSON on the Umbraco template
    7. Create a page with the template we just created above
    8. Use JQuery Social Stream on the macro and pass the url (generated from #7) to the twitter option

    Simple isn't it?

    To help other beginners just like me, here's how it was done (through codes):

    Umbraco Template:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @using System
    @using System.Collections.Generic
    @using System.Diagnostics
    @using System.IO
    @using System.Linq
    @using Tweetinvi
    @using Tweetinvi.Core.Enum
    @using Tweetinvi.Core.Extensions
    @using Tweetinvi.Core.Interfaces
    @using Tweetinvi.Core.Interfaces.Controllers
    @using Tweetinvi.Core.Interfaces.DTO
    @using Tweetinvi.Core.Interfaces.Models
    @using Tweetinvi.Core.Interfaces.Models.Parameters
    @using Tweetinvi.Core.Interfaces.oAuth
    @using Tweetinvi.Core.Interfaces.Streaminvi
    @using Tweetinvi.Json
    @using Stream = Tweetinvi.Stream
     
    @{
        Layout = null;
     
     string accessToken = (string)CurrentPage.twitterAccessToken;
     string accessTokenSecret = (string)CurrentPage.twitterAccessTokenSecret;
     string consumerKey = (string)CurrentPage.twitterConsumerKey;
     string consumerSecret = (string)CurrentPage.twitterConsumerSecret;
     string screenName = (string)CurrentPage.twitterScreenName;
     int maxTweets;
     Tweetinvi.Core.Interfaces.IUser user;
     
     //authenticate your site to twitter OAuth
     TwitterCredentials.SetCredentials(accessToken, accessTokenSecret, consumerKey, consumerSecret);
        
     if(!Int32.TryParse(CurrentPage.twitterMaxLimit.ToString(),out maxTweets))
     {
      maxTweets = 20;
     }
     
     if(String.IsNullOrEmpty(screenName))
     {
      //get user
      user = Tweetinvi.User.GetLoggedUser();
     }
     else
     {
      //get user from screen name
      user = Tweetinvi.User.GetUserFromScreenName(screenName);
     }
     
     //retrieve the timeline as json
     var tweets = Tweetinvi.Json.TimelineJson.GetUserTimeline(user,maxTweets);
     
     //convert template to return as json
     Response.ContentType = "application/json";
     
     //write result as json
     @Html.Raw(tweets); 
     
    }

    Umbraco Macro:

    @inherits Umbraco.Web.Macros.PartialViewMacroPage
    @using ClientDependency.Core.Mvc
    @using ClientDependency.Core
    @{
     Html.RequiresJs("~/scripts/jquery/plugins/socialstream/js/jquery.social.stream.1.5.4.min.js", 3);
     Html.RequiresJs("~/scripts/jquery/plugins/socialstream/js/jquery.social.stream.wall.1.3.js", 4);
     Html.RequiresCss("~/scripts/jquery/plugins/socialstream/css/dcsns_wall.css");
     
     var startNodeId = (string)Model.MacroParameters["startNodeId"];
     var iconPath = (string)Model.MacroParameters["iconPath"];
     var imagePath = (string)Model.MacroParameters["imagePath"];
     var htmlId = (string)Model.MacroParameters["htmlId"];
     
     var node = Umbraco.Content(startNodeId);
     
     if(node.DocumentTypeAlias == "SocialWall")
     {
      List<string> feeds = new List<string>();
      List<string> options = new List<string>();
      
      if(String.IsNullOrEmpty(htmlId) || htmlId == "null")
      {
       htmlId = "social-stream";
      }
      if(String.IsNullOrEmpty(iconPath) || iconPath == "null")
      {
       iconPath = "/scripts/jquery/plugins/socialstream/images/dcsns-dark-1/";
      }
      if(String.IsNullOrEmpty(imagePath) || imagePath == "null")
      {
       imagePath = "/scripts/jquery/plugins/socialstream/images/dcsns-dark-1/";
      }
      
      //this is where you have to insert the template url
      if(!String.IsNullOrEmpty(node.socialWallTwitter.ToString()))
      {
       var twitterNode = Umbraco.Content(node.socialWallTwitter.ToString());
       
       if(twitterNode != null && !String.IsNullOrEmpty(twitterNode.Name))
       {
        feeds.Add("twitter: { id: '" + twitterNode.twitterScreenName + "', url: '" + twitterNode.Url + "' }");
       }
       
      }
      
       
      if(!String.IsNullOrEmpty(node.socialWallFacebook))
      {
       feeds.Add("facebook: { id: '" + node.socialWallFacebook +"' }");
      }
      
      //do your other stuffs here...
      
      //render the social stream
      <div id="@htmlId"></div>
      <script type="text/javascript">
       $(document).ready(function($){
       $('#@htmlId').dcSocialStream({
         @Html.Raw(String.Join(",",options.ToArray()))
        });
       });
      </script>
     }
    }
    
    
    

    I know this isn't the best solution, but so far this was the fastest and easiest way for us to implement. So if you have a better solution or suggestions, please don't hesitate to comment below or send me an email. Would be really glad if you could help us out. :)



    Tuesday, December 4, 2012

    Delete files / folders older than X days on windows (bat file)

    This script will delete all MS SQL database backups (*.bak files) older than 30 days on the current directory and all its subdirectories:

    forfiles /s /m *.bak /d -30 /c "cmd /c del @path"
    


    This script will delete all MS SQL database backups (*.bak files) older than 30 days on a specified directory and all its subdirectories:

    forfiles /p "c:\database\backups" /s /m *.bak /d -30 /c "cmd /c del @path"



    This script will delete all folders older than 30 days on a specified directory:


    forfiles /p "C:\todelete" /m * /d -30 /c "cmd /c rd /s /q @path"  
    


    More from here: ForFiles

    If you don't have the forfiles.exe, you can download it from here: ForFiles.zip

    Tuesday, November 13, 2012

    The untold origin and history of jeepney

    The Known Story (Extracted from Wikipedia)

    When American troops began to leave the Philippines at the end of WWII, hundreds of surplus jeeps were sold or given to the Filipinos. They were stripped down and altered; metal roofs were added for shade; and decorated the vehicles with vibrant colors and chrome-plated hood and other ornaments. They reconfigured the jeeps to accommodate more passengers and classified them as passenger-type jeeps. Its size, length and passenger capacity had increased as it evolved though the years. The non-extended, original-seat configuration jeeps were labeled owners, short for owner-type jeep, and used non-commercially.
    The jeepney rapidly emerged as a popular and creative way to re-establish inexpensive public transportation, which had been virtually destroyed during WWII. 

    The Untold Story

    After World War II, a foreign journalist went to Cebu, Philippines. He saw one of the colorful jeepneys and was dazzled by the sight of it. It was the first time that the jeepney reflected into a foreigner's eyes. Out of excitement, he approached one of the drivers and asked:

    Journalist: How do you call this vehicle?
    Driver (bisaya): ha?
    Interpreter (bisaya): ingon siya unsa daw tawag aning imong sakyanan?
    Driver: ahhh... kani? Jeep ni..
    Journalist: Jeepney? Cool!

    Bisaya - English Transalation:
    kani = this
    ni = shortcut for "kani"
    Jeep ni = This is Jeep

    history has written its name... JEEPNEY!

    Sunday, September 9, 2012

    Fight Starts at 40! - The Manny Pacquiao vs Floyd Mayweather Jr. controversy

    If Manny Pacquiao vs Floyd Mayweather Jr. should happen, it should be 7 years from now to have a sensible caption for the long-delayed fight.

    "Fight Starts at 40!"

    or

    "Life Fights at 40!"

    or

    "40-Fight Degrees"

    Book now and watch later!!!




    Sunday, August 12, 2012

    Rich in GOLD.. but never got GOLD


    The Philippine Government should not have any reasons not to join / support the Olympic games...... but these are few reasons why we should join:

    1. Because we have plenty of water

    "Because the rower from Niger was competing in the Olympics despite the fact that he only took up the sport three months ago, his home country doesn't have a single rowing boat and is mostly desert. Yes, he came in last. But he also got one of the biggest cheers of the day."

    2. Because we are 92 million in population

    Montenegro secure first Olympic medal

    "It's amazing this success for a country of 600,000 people. It's historic, something we'll never forget," 

    3. Because we have plenty of physically capable athletes

    "if Pistorius can compete in the Olympics with no legs, then I should be able to overcome the adversity that I have."

    4. Because we have plenty of female athletes

    "Because in spite of the fact she pulled up injured within the first few steps of her 100m preliminary round, Qatar's first ever female Olympic athlete broke down barriers - as did Sarah Attar and Wojdan Shaherkani, Saudi Arabia's first ever female Olympians. They may not have won, but they made history."

    5. Because we are a nation

    All they know about Filipinos is about domestic helpers and monkeys. Isn't this a chance to tell them that we are not?



    sources:

    http://news.ph.msn.com/olympic-game/pictures-of-the-day/images.aspx?cp-documentid=250605046#image=1
    http://uk.eurosport.yahoo.com/news/norway-reach-olympic-handball-final-175326595.html
    http://en.wikipedia.org/wiki/Montenegro
    http://www.ourmidland.com/sports/article_85c02a93-e196-51ac-bd80-9b82863fb9f6.html
    http://en.wikipedia.org/wiki/Philippines
    http://en.wikipedia.org/wiki/Philippines_at_the_Olympics

    Thursday, May 31, 2012

    MSSQL Random Rows

    SELECT TOP 100 * FROM Company_Products p
    ORDER BY (CAST(CHECKSUM(NEWID(),p.id) & 0x7fffffff AS float)
    / CAST (0x7fffffff AS int))

    Tuesday, April 3, 2012

    Custom JQuery Validation with MVC.Net Ajax.BeginForm

    <% using (Ajax.BeginForm("Save", "Setup", new AjaxOptions { OnSuccess = "saveComplete", OnBegin = "validateForm", OnComplete = "ScreenManager.Complete" }, new { id = "setup-edit-form" }))
    {%>

    <%= Html.Label("Name") %><%= Html.TextBox("Name",Model.Name) %>

    <%}% >

    <script type="text/javascript">
    $(document).ready(function () {
    $("#setup-edit-form").validate({
    rules: {
    Name: "required"
    }

    });
    });

    function validateForm()
    {
    var validated = $('#setup-gateways-edit-form').valid();
    if (validated) {
    alert('this is validated');
    }
    return validated;
    }
    <script>