Share Youtube Videos on Chatter Using Lightning Components (YouTube2Chatter)

Screenshot_2015-09-17-21-00-31

Hi Everyone
I am here with some cool stuff. As you know that YouTube is very popular for videos. Many of salesforce videos on YouTube as well. After reading this post, you can search videos in salesforce1 and also you can share to chatter as well.

Chatter feeds

We will learn following things in this post :
1. Lightning Components
2. Lightning Design System with lightning Components
3. YouTube Integration
4. Wrapper Classes in lightning
5. Nested Components
6. Passing values from child to parent Component
7. Creating app on google console

First of all we need a google API key to fetch data for YouTube. For getting API key we need to create a App on google console.

A. Get a API key from Google :
1. Go to https://console.developers.google.com
2. Create a new project here.
Create Project
3. A pop-up will open, fill all project’s info here, Then click on Create button.
Fill Info Of Project
4. Now navigate to left panel and select APIs & Auth –> APIs
5. Then click on YouTube Data API under YouTube APIs section.
Youtube APis
6. Then press Enable API button to enable YouTube’s API.
Enable Api
7. After that Go to Credentials then click on Add Credential –> Api Key
Cred
8. A popup will open, select Server Key option here.
Server Key
9. Now give Server Api Key name here and click on create. now you have your Api Key. Please do secure your API key.

B. Building Lighting Components and Apex Classes:
1. YouTubeFeedCtrl.cls
2. YouTubeWrraper.cls
3. YouTubeJSON.cls
4. YouTubeToFeed.cmp
5. YouTubeToFeedContoller.js
6. YouTubeViewPort.cmp
7. YouTubeViewPortContoller.js

1.YouTubeFeedCtrl.cls
This class used for fetching data from google API and sharing feeds on chatter. We are making request on http://www.googleapis.com and filling wrapper class list from response of http request.

public with sharing class YouTubeFeedCtrl{
    private static final String SEARCH_URL = 'https://www.googleapis.com/youtube/v3/search';
    private static final String API_KEY = 'AIzaSyC60-a9ziN9zLIcb9ueYv2-IwS03CnYgI4'; //API_KEY
    
    //Fetching youtube data by given search string
    @AuraEnabled
    public static List fetchVideos(string searchString){
        //If no search keywords found then it will search for salesforce keyword
        searchString = searchString == null ? 'salesforce' : searchString ;
        
        //Making Http request to google apis
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        HttpResponse res = null;
        String endpoint = SEARCH_URL +
            '?part=snippet' +
            '&maxResults=20' +
            '&type=video' +
            '&q=' + EncodingUtil.urlEncode(searchString, 'UTF-8') +
            '&key=' + API_KEY;
            
        req.setEndPoint(endpoint);
        req.setMethod('GET');
        res = http.send(req);
        
        //Deserializing json data
        YouTubeJSON.Response response = (YouTubeJSON.Response)JSON.deserialize(res.getBody(), YouTubeJSON.Response.class);
        List items = response.items;
        
        //Filling Wrapper Data for lightning component
        List LstYTWrapper = new List();
        For( YouTubeJSON.Item itemObj : items ){
            YouTubeWrapper YuTuWr = new YouTubeWrapper();
            YuTuWr.videoId = itemObj.id.videoId;
            YuTuWr.title = itemObj.snippet.title;
            YuTuWr.Description = itemObj.snippet.description;
            YuTuWr.thumbnails = itemObj.snippet.thumbnails.medium.url;            
            YuTuWr.channelTitle = itemObj.snippet.channelTitle ;
            YuTuWr.publishedAt = itemObj.snippet.publishedAt+'';
            LstYTWrapper.add(YuTuWr);
        }
        return LstYTWrapper;
    }    
    
    //Function for share youtube link to chatter
    @AuraEnabled
    public static boolean shareOnChatter(string chatterText,String youTubeUrl){
        chatterText  = chatterText == null ? '' : chatterText ;
        FeedItem post = new FeedItem();
        post.ParentId = userinfo.getUserId();
        post.Body = chatterText;
        post.LinkUrl = youTubeUrl;
        insert post;
        return true;
    }
}

2. YouTubeWrraper.cls
Lightning wrapper classes different from salesforce wrapper classes. We can’t access inner classes in lightning so we are not creating wrapper class as inner class here. In wrapper classes each variable should be @AuraEnabled.

public class YouTubeWrapper{
    @AuraEnabled
    public String videoId { get; set; }
    @AuraEnabled
    public String Description { get; set; }
    @AuraEnabled
    public String thumbnails{ get; set; }
    @AuraEnabled
    public String title { get; set; }
    @AuraEnabled
    public String channelTitle { get; set; }
    @AuraEnabled
    public String publishedAt  { get; set; }
}

3. YouTubeJSON.cls
This class contains wrapper classes for json de-serialization.

public class YouTubeJSON{
    public List items { get; set; }    
    public class Response {
        public String kind { get; set; }
        public String etag { get; set; }
        public String nextPageToken { get; set; }
        public String prevPageToken { get; set; }
        public YouTubeJSON.PageInfo pageInfo { get; set; }
        public List items { get; set; }
    }
    
    public class PageInfo {
        public Integer totalResults { get; set; }
        public Integer resultsPerPage { get; set; }
    }
    
    public class Item {
        public String kind { get; set; }
        public String etag { get; set; }
        public YouTubeJSON.Id id { get; set; }
        public YouTubeJSON.Snippet snippet { get; set; }
    }
    
    public class Id {
        public String kind { get; set; }
        public String videoId { get; set; }
    }
    
    public class Snippet {
        public Datetime publishedAt { get; set; }
        public String channelId { get; set; }
        public String title { get; set; }
        public String description { get; set; }
        public YouTubeJSON.Thumbnails thumbnails { get; set; }
        public String channelTitle { get; set; }
        public String liveBroadcastContent { get; set; }
    }
    
    public class Thumbnails {
        public YouTubeJSON.Thumbnail medium { get; set; }
        public YouTubeJSON.Thumbnail high { get; set; }
    }
    
    public class Thumbnail {
        public String url { get; set; }
    }
}

4. YouTubeFeed.cmp
From here we are going to develop lightning part for this app. This is our main component, we will use this component to show our app in salesforce1. In this component we are defining success message, iframe for YouTube videos, searching of videos on YouTube and share videos link on chatter.


	<!--Describing Youtube video id for Parent Component(YouTubeFeed.cmp)-->
	
	
	<!--Describing attribut of YouTubeWrapper class-->
	
	
	<!--Including Lightninh Design System resource-->
	
	
	<!--Calling doSearch function on loading of component-->
	
	
	<div class="slds" style="background-color:#F4F6F9;">
	  <!--Success Message Start Here-->
	  <div id="ChatterSuccessMessage" class="slds-notify-container" style="display:none;">
		 <div class="slds-notify slds-notify--toast slds-theme--success" role="alert" style="min-width:0;">
			<span class="slds-assistive-text">Info</span>
			<div class="notify__content">
			   <h2 class="slds-text-heading--small">Feed succefully posted...</h2>
			</div>
		 </div>
	  </div>
	  <!--Success Message End Here-->
	  
	  <!--Header Start Here-->
	  <div class="slds-page-header" role="banner">
		 <div class="slds-grid">
			<div class="slds-col slds-has-flexi-truncate">
			   <div class="slds-media">
				  <div class="slds-media__figure">
					 <b style="color:red;">Youtube</b><b style="font-size:45px;">2</b><b style="color:blue;">Chatter</b>
				  </div>
			   </div>
			</div>
		 </div>
		 <div class="slds-grid">
			<div class="slds-col--padded slds-size--3-of-4">
			   <!--Input box for taking search string for videos-->
			   
			</div>
			<div class="slds-col--padded slds-size--1-of-4">    
			   <!--Search Button-->
			   Search                	
			</div>
		 </div>
	  </div>
	  <!--Header End Here-->
	  
	  <!--Container Start Here-->
	  <div class="slds-container--fluid  slds-container--center">	 
		  <div class="slds-grid" id="youtubeframe" style="display:none;">
			 <div class="slds-card slds-card--empty" style="width:100%;">
				<div class="slds-card__body" style="padding:0;">
				   
				</div>
				<div class="slds-grid slds-m-top--medium slds-m-bottom--medium">
				   <div class="slds-col slds-size--1-of-2">
					  <!--Chatter Feed Message-->
					  
				   </div>
				   <div class="slds-col slds-size--1-of-2">                            
					  <!--Share on chatter button-->
					  Share to Chatter
				   </div>
				</div>
			 </div>
		  </div>
		  <div class="slds-grid slds-m-top--medium">
			 <div class="slds-col">
				<ul class="slds-timeline" style="background-color:#F4F6F9;">
				   <!--Passing youtube records in YouTubeViewPort Component using Iteration-->
				   
					  
				   
				</ul>
			 </div>
		  </div>
	  </div>
	  <!--Container Start Here-->
	</div>

5. YouTubeToFeedContoller.js
This is the controller of YouTubeToFeed.cmp. Here are two methods first one is used for fetch data and set data to wrapper attribute on YouTubeToFeed.cmp and second one is used to share feed on chatter.

({
    //Searching and getting data from apex class
    doSearch: function(cmp, event, helper) {
        var fetchVideo = cmp.get("c.fetchVideos");
        fetchVideo.setParams({
            searchString: cmp.find("searchstr").get("v.value")
        });
        fetchVideo.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.set("v.YouTubeVideos", response.getReturnValue());
            } else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] &amp;amp;&amp;amp; errors[0].message) {
                        $A.error("Error message: " + errors[0].message);
                    }
                } else {
                    $A.error("Unknown error");
                }
            }
        });
        $A.enqueueAction(fetchVideo);
    },

    //Posting feeds to chatter
    shareOnChatterClient: function(cmp, event, helper) {
        var myVar;
        var shareOnChatterAuraFun = cmp.get("c.shareOnChatter");
        //Passing params to apex shareOnChatter function
        shareOnChatterAuraFun.setParams({
            "chatterText": cmp.find("chatterStr").get("v.value"),
            "youTubeUrl": cmp.get("v.ParentviewIt")
        });

        shareOnChatterAuraFun.setCallback(this, function(response) {
            var state = response.getState();
            //If result is successfull then notification will apears for 5 second
            if (state === "SUCCESS") {
                document.getElementById("ChatterSuccessMessage").style.display = 'block';
                //Run a interval and call eraseSuccessMessage in 5 second to hide notification
                myVar = setInterval(function() {
                    eraseSuccessMessage();
                }, 5000);
            }
        });
        $A.enqueueAction(shareOnChatterAuraFun);

        //Function for hide notification
        function eraseSuccessMessage() {
            document.getElementById("ChatterSuccessMessage").style.display = 'none';
            clearInterval(myVar);
        }
    }
})

6. YouTubeViewPort.cmp
In this component, I am implementing nested components concept in lightning. This is child component of YouTubeToFeed.cmp. Here we are filing data of for each

  • of Lighting Design System’s timeline. See more here about Lightning Design System Timeline component.
    
        
    	<!--Describing Youtube video id for Child Component(YouViePort.cmp)-->
        
    	
    	<!--Describing attribut of YouTubeWrapper Variable-->
    	 
    	
        <li class="slds-timeline__item">
        <span class="slds-assistive-text">Event</span>
        <div class="slds-media slds-media--reverse">
          <div class="slds-media__body">
            <div class="slds-media slds-media--timeline slds-timeline__media--event">
              <div class="slds-media__figure">
                <img id="{!v.YTVVar.videoId}" style="width:100px;height:100px;border-radius:9px;" src="{!v.YTVVar.thumbnails}" />
              </div>
              <div class="slds-media__body">
                <p><a>{!v.YTVVar.title}</a></p>
                <p class="slds-truncate">{!v.YTVVar.Description }</p>
                <ul class="slds-list--horizontal slds-text-body--small">
                  <li class="slds-list__item slds-m-right--large">
                    <dl class="slds-dl--inline">
                      <dt class="slds-dl--inline__label">By:</dt>
                      <dd class="slds-dl--inline__detail">{!v.YTVVar.channelTitle }</dd>
                    </dl>
                  </li>
                  <li class="slds-list__item">
                    <dl class="slds-dl--inline">
                      <dt class="slds-dl--inline__label">Date:</dt>
                      <dd class="slds-dl--inline__detail">{!v.YTVVar.publishedAt }</dd>
                    </dl>
                  </li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </li> 
    
    

    7. YouTubeViewPortContoller.js
    This is controller of YouTubeViewPort.cmp. In this, we will learn how can we pass values from child component to parent component. Whenever YouTube video’s link is clicked that time it will set value in “ChildViewIt” attribute and using this attribute, value will pass to “ParentviewIt” and after this iframe will be shown up with video.

    ({
    	//Use for set value src of iframe
    	seeVideo : function(cmp, event, helper) {  
            cmp.set("v.ChildViewIt", "https://www.youtube.com/embed/"+cmp.get("v.YTVVar.videoId") ) ;
            document.getElementById("youtubeframe").style.display = 'block';        
    	}        
    })
    

    We have almost done our functionality. Now we are going to setup for salesfroce1 app.

    C. Create a lightning component tab for salesforce1 :
    1. Go to setup menu
    2. Go to Create –> Tab –> Create Lightning Component Tabs
    3. Fill Values here :
    Tab creating

    4. After creating tab Go to Mobile Administration –> Mobile Navigation
    5. Here move YouTube tab to selected list.
    Mob Nav

    All Setup ???

    Happy Coding…

  • 4 thoughts on “Share Youtube Videos on Chatter Using Lightning Components (YouTube2Chatter)

    Leave a comment