Using SteemSQL to query Steem database in your SteemJS Application

SteemJS is still rudimentary and if you start developing some applications you will know that they will fall short. For a bot that I was working on I wanted to know if the user has already posted earlier with the same tag. The case in questions was I wanted to check if the user is misusing the #introduceyourself tag. So before posting a welcome message to the users I wanted to check if he has created more than two posts with the#introduceyourself tag.

What will you learn?

In this tutorial you will learn

  • How to use SteemSQL in SteemJS code
  • How to use steem.api.streamTransaction function to do something when a user has created a post.
  • Using SteemSQL to identify if the user has already create posts with a similar tag.

Requirements

These are good to have requirements. Even if you don't know these you can still read the tutorial and make sense out of it.

  • Basics of Javascript
  • Basics of SteemJS

Difficulty

  • Advanced. You can take a look at the code even if you are not at an advanced level. It might seem a little complicated but it will start making sense to once you cover your basics. I will be happy to answer any queries you have in the comments section.

Add relevant node packages and settings.

In the below script we are adding relevant node packages and their related settings.

We are adding steem package so that we can use steemJS APIs. We are setting that url to wss://steemd-int.steemit.com which is functioning without any issues for me for last two months. We are settings up variables that will be used across the file.

We are adding mssql package as SteemSQL is a MS-SQL database. You can get your SteemSQL credentials by purchasing the subscription as mentioned in the post

var steem = require('steem');
steem.api.setOptions({ url: 'wss://steemd-int.steemit.com' });


const BASEURL = 'https://steemit.com/'
const ACCOUNT_NAME = 'steemladder'

console.log('SteemLadder app has started');

const sql = require('mssql');
const config = {
    user: 'Steemit-gokulnk',
    password: 'you-will-get-this-once-you-subscribe',
    server: 'vip.steemsql.com',
    database: 'DBSteem',
}

Listem to streamTransaction to identify when a comment is posted.

In the below script we are listening streamOperations. Once the streamOperation is emmitted we are getting the txType and txData from the operation. We are then checking if the txType is comment and it has no parent(comments without parents or posts) and has metadata. If it passes all these conditions they we get the tags of the posts from metadata and see if the tags text contains the tags we are looking for.

steem.api.streamOperations(function (err, operations) {
    var txType = operations[0];
    var txData = operations[1];
    var steemDbquery = '';
    if (txType == 'comment' && txData.parent_author == '' &&  txData.json_metadata){
        var metadata = JSON.parse(txData.json_metadata);
        if (metadata) {
            var tags = metadata.tags || [];
            var parentAuthor = txData.author;
            var parentPermlink = txData.permlink;
            var commentPermlink = steem.formatter.commentPermlink(parentAuthor, parentPermlink);

            if (tags.indexOf("introduceyourself") > -1) {

Once it matches all these we now need to check if the user has already posted earlier with the same tag.

Use SteemSQL before running doSomething function

This is the core of the tutorial and we will see how to use the SteemSQL query in steemJS.

In the code below we are checking that the json_metadata contains the work introduce and depth is 0 to make sure that we are querying only the posts and not the comments. Since node.js is asynchronous we will get the response from the DB and we need to use then to process that output. Within the the then function we are checking if we have got more than 2 rows which satisfies our conditions. Including the current post if the user has posted less than or equal to two posts with #introduce tags then we can perform some action like say up-voting their posts.

                    steemDbquery = `SELECT * FROM [dbo].[Comments] where author = '${parentAuthor}' AND json_metadata like '%introduce%' AND DEPTH = 0`;
                    sql.connect(config).then(pool => {
                        console.log('Connected to SteemSQL');
                        return pool.request()
                            .query(steemDbquery)
                    }).then(result => {
                        console.log(result); // Print SQL results to console for debugging                                                                                           
                        if (result.rowsAffected[0] <=2) {
                            doSomething();
                        }
                        sql.close();
                    })

                    sql.on('error', err => {
                        console.log('Unable to connect to DB');
                    })

Helper Functions

Following Helper functions are used to generate links to the authors and blogs.

  function steemBlogFullurl(author, permlink) {
      return BASEURL + '@' + author + '/' + permlink;
  }
  function steemBlogFullurl(author, permlink) {
      return BASEURL + '@' + author + '/' + permlink;
  }
  function steemAuthorFullurl(author) {
      return BASEURL + '@' + author;
  }
  function steemAuthorLink(author) {
    return getLink('@' + author, steemAuthorFullurl(author));
  }
  function getLink(linkText, targetLink) {
    if (typeof linkText == "undefined" || linkText == ''){
      linkText = targetLink;
    }else if (typeof targetLink === "undefined") {
      targetLink = linkText;
    }
    return `<a href = ${targetLink} target="_blank">${linkText}</a>`;
  }

Final notes.

You can checkout the final code from Github.

Curriculum

If you are a developer and would like to kickcstart your learning you can check the following link to set up your dev environments and tools. As I write further tutorials I will add them to the list.

Originally published on https://steemit.com/utopian-io/@gokulnk/using-steemsql-to-query-steem-d…

Build matrix like Steem Stream with SteemJs

This is going to be the first tutorial in the tutorial series I will be starting. I am working on a couple of Steem projects and I will share my learnings from the project as Tutorial Series. This tutorial intends to be the "Hello World" program of coding on Steem Blockchain. In this tutorial we will create a simple activity stream which shows the latest activity on the blockchain. To make things a little interesting I will format it in the Matrix style. You will know what I mean once you look at the demo. If you just want to take sneak peak at what we will be achieving before starting the tutorial take a look at https://nkgokul.github.io/steem-tutorials/SteemStream.html

matrix.jpg

What will you learn?

In this tutorial you will learn

  • How to use SteemJS
  • How to use steem.api.streamTransaction function to check for transactions from the latest blocks.
  • Create a basic HTML that will display the steem stream in a matrix like fashion.

Requirements

These are good to have requirements. Even if you don't know these you can still read the tutorial and make sense out of it.

  • Basics of HTML
  • Basics of Javascript

Difficulty

  • Basic. You can take a look at the code even if you are not from a development background. I will be happy to answer any queries you have in the comments section.

Create a HTML skeleton

<body>
  <div id="gokul-details">
    <h3>This example was created by <a href="https://www.steemit.com/@gokulnk" target="_blank">@gokulnk</a></h3>
  </div>
  <div id="steem-data-wrapper">
    <h2>Please wait while fetching the data from Steem Blockchian.</h2>
  </div>
</body>

Within the body tag create a div which we will use to populate the contents of our data stream from Steem blockchain.

Add relevant javascript files

In your head tag add the following scripts

  <script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

The first script is the minified version of SteemJS library which will help us interact with the steem blockchain direction from the javascript/browser.

The second script is the jQuery library file which simplifies DOM manipulations and saves time in performing the frequently used actions in javascript. We will use these two files in all the browser based tutorials going forward.

Understanding steem.api.streamTransactions function

The takeaway from this tutorial will be how to use steem.api.streamTransactions function

  console.log('hello, is this working')
  var counter = 1;
  const BASEURL = 'https://steemit.com/'
  const ACCOUNT_NAME = 'gokulnk'
  steem.api.setOptions({ url: 'https://api.steemit.com' });
  steem.api.streamTransactions('head', function(err, result) {
    let txType = result.operations[0][0]
    let txData = result.operations[0][1]
    jQuery('#steem-data-wrapper').prepend('<div class="stream-activity' + counter + '">' + counter++ + ' ' + getMessagefromTransaction(txType, txData) + '</div>');
  }); 

In this code we are doing a couple of things.

  1. setup some variables like counter and BASEURL variables which we will be using erstwhile.
  2. steem.api.setOptions({ url: 'https://api.steemit.com' }); sets the url of the endpoint to https://api.steemit.com. Recently there were some changes made to the endpoints and a couple of witness servers were not working. In case you are getting any errors google for other endpoints and update them accordingly.
  3. Minitor the blockchain with steem.api.streamTransactions function, decorate/process them using the function getMessagefromTransaction(txType, txData)
  4. Using jQuery prepend the output to the div we created earlier in HTML with id "steem-data-wrapper". We will be using jQuery for prepending this value.

The processing function

The processing function uses a switch case to identify the different types of transactions and returns a relevant activity message.

  function getMessagefromTransaction(txType, txData) {
    //console.log(txType, txData) ;
    //console.log(txType, JSON.stringify(txData)) ;
    var custom_json;
    switch (txType) {
      case 'vote':
        return steemAuthorLink(txData.voter) + ' upvoted ' + steemAuthorLink(txData.author) + "'s post " + getLink(txData.title, steemBlogFullurl(txData.author, txData.permlink));
        // statements_1
        break;
      case 'comment':
         if (txData.parent_author == ''){
           return steemAuthorLink(txData.author) + ' created a post ' + getLink(txData.title, steemBlogFullurl(txData.author, txData.permlink));
         }else {
            return steemAuthorLink(txData.author) + ' posted a comment' + ' on '+ getLink(txData.permlink, steemBlogFullurl(txData.author, txData.permlink));
         }
        break;
      case 'transfer':
        return steemAuthorLink(txData.from) + ' transferred ' + txData.amount + ' to '+ steemAuthorLink(txData.to) + ' with the memo "' + txData.memo + '"';
        break;
      case 'claim_reward_balance':
        return steemAuthorLink(txData.account) + ' claimed his remaining rewards balance of ' + txData.reward_steem + ", "+  txData.reward_sbd + " and " + txData.reward_vests;
        console.log(txType, txData) ;
      break;
      case 'custom_json':
          if (txData.id == 'follow') {
            custom_json = JSON.parse(txData.json);
            return steemAuthorLink(custom_json[1].follower) + ' followed ' + steemAuthorLink(custom_json[1].following);
          }
      default:
        return txType + ' ' + JSON.stringify(txData).substring(0,300) + ((txData.length > 300) ? "....." : "");
        break;
    }
  }

Following Helper functions are used to generate links to the authors and blogs.

  function steemBlogFullurl(author, permlink) {
      return BASEURL + '@' + author + '/' + permlink;
  }
  function steemBlogFullurl(author, permlink) {
      return BASEURL + '@' + author + '/' + permlink;
  }
  function steemAuthorFullurl(author) {
      return BASEURL + '@' + author;
  }
  function steemAuthorLink(author) {
    return getLink('@' + author, steemAuthorFullurl(author));
  }
  function getLink(linkText, targetLink) {
    if (typeof linkText == "undefined" || linkText == ''){
      linkText = targetLink;
    }else if (typeof targetLink === "undefined") {
      targetLink = linkText;
    }
    return `<a href = ${targetLink} target="_blank">${linkText}</a>`;
  }

Final notes.

You can checkout the final code and the demo to see what you have created with the help of this tutorial.

 

Originally published on https://steemit.com/utopian-io/@gokulnk/build-matrix-like-steem-stream-…

AngularJS Series: An introduction to Scope

This is the Sixth post in my series on the AngularJS; have a look on my initial posts covering ‘An intro to AngularJS’, ‘Data-binding methods’, ‘Modules & controllers', 'Filters' and ‘Custom services’. 

Before jumping to another component of AngularJS - Scope - let’s make sure you all have seen the term $scope under controller function(). Scope is used to access variable and methods in Angular. 

As the name suggests, $scope means ‘within the range’. In Angular, $scope is a reserved word. As per the name $scope does the same by availing variable/functions () within the range. So the same variable could be rendered in the view. 
 
Technically:  $scope is service for AngularJS. It is an object that refers to a model. It acts as a mediator between the View & the Controller. It allows accessing properties and variable Within the scope. Scope looks to expression in your view and performs the event.

Sample code:

The below source code allows you to print the data directly from the Scope. As you can see our custom app has myCtrl controller and data is bind to the scope using $scope.name & $scope.job. The same variable can be pulled up in view while rendering the data. We have used {{name}} &  {{job}} in our view.
 

Response Result:

Scope output

Another way to create a controller 

You might have come across a situation where you need to develop a huge application of not just 50-100 lines of code but 10X larger than that. In this scenario, it's very difficult to manage each and every controller and get a minified version of JS script. When we talk about the minified version that means it will remove unnecessary blank space, comment and try to look for parameter and transform it to very simple name.  

While compiling new variable ‘b’ will be replaced with $scope.

Sample code :  

Every App has a local & global scope (root scope), where $rootScope never bound with any controller. In other words, $rootScope is a parent controller where are $scope_1 ,$scope_2…..$scope_n are the child of parent controller(---------    ) and can be accessible from anywhere in the application. Here variable has the same name and calls out within the scope and outside of the scope. In this scenario, variable within the local scope gets executed before root scope.

Let me share one small example:

Code Simplification: 

In above codebase, a module has two controllers including run().
run() is one of the phases of code execution order. Only constant and an instance can be taken up and called right after config(). In other words, you can use run() to boost the application.

Back to code: we have two controller myCtrl & yourCtrl. These controllers are called within local scope whereas $rootScope have an object in global scope and rendered the same in the view.

To access the $rootScope property or methods within the controller,  you need to mention $root. Method_name or $root.property_name


 
Global scope within local scope : You are logged in as: {{ $root.name}} & your profession as {{ $root.job}}

In case you need $rootScope inside the local scope of your controller then you need to pass $rootScope as Dependency injection in your local scope of the controller.

In below source code $rootScope.job will take up the value from the global controller and assign back to myCtrl. Using this technique, global data can be passed through multiple controller and local data within the same controller.

 app.controller('myCtrl', function($scope, $rootScope) {
                              $scope.name = "Jaywant Topno";
                              $scope.job = $rootScope.job;
                   });

Sample response:

Scope output with controller

This is what Scope in AngularJS all about. The goal of our series of tutorial on AngularJS is to bring you valuable information to help you gro tow enhance your technical knowledge. We hope you enjoy this post!

Git Source code: https://github.com/xaiwant/AngularJS-Scope

How to integrate Salesforce with Drupal 8 website

Integration of CRM tool with web applications has turned out to be an undaunted task especially when you monitor/manage your contacts, existing clients and leads generated for marketing campaigns. In this post, I would like to walk you through Salesforce integration with Drupal web application. Let’s dive in to the basics of Salesforce.

Salesforce is a cloud-based CRM solution that helps business effectively manage sales, service, marketing, collaboration, analytics, and building custom mobile apps. In order to manage the business effectively, companies need to integrate their Drupal website with Salesforce CRM solution, which is quite configurable. Not to mention Drupal offers various modules that help in synchronizing your application with CRM. Check out how.

Prerequisites

Server requirement: 

SSL is mandatory for using Salesforce on the website.

Creating connected app in Salesforce

Step 1 Login your Salesforce account.

Step 2 Follow the steps:

           Setup->Apps->App manager->New connected App

Follow the steps as shown in the screenshot:

Setup navigation for New connected app

Step 3 Now you can see connected app form, select required fields.

3.1 Basic information: Provide basic information about your app. 

3.2 API (Enable OAuth setting): OAuth (Open Authorization) gives access to resources without revealing user credentials to apps and end user's account information can be used by third-party services. Select setting checkbox. 

Form sections for creating app


Step 4 Check whether the setting is selected or not as it toggles a form with some other required fields. 

Form section for creating app

Step 5 Enter the callback URL “yourdomain.com/salesforce/oauth_callback”.

Step 6 Select other fields as per your requirement and process it. Wait for 2-10 minutes before using your app. Now continue the process. 

New connected app

Here you will get the consumer key and secret key (these keys are required to connect Drupal to Salesforce). Now you can use the connected app on your Drupal website.

App’s final credentials

Salesforce module:

Download Salesforce module and install it on your Drupal website. Also, download and install dependent modules like key & encrypt.

Let’s check out the submodules in Salesforce and what they do: 

  • Salesforce: OAUTH2 authorization, wrapper around REST API.
  • Salesforce Mapping: Maps Drupal entities to Salesforce fields, including field level mapping.
  • Salesforce Push: Pushes Drupal entity updates in to Salesforce.
  • Salesforce Pull: Pulls Salesforce object updates into Drupal on cron run.
  • Salesforce Encrypt: This module is dependent on two other module Encrypt & Key so make sure these are installed. Module required for access and refresh token with security.

Setting up Salesforce on Drupal website: 

Step 1 Go to Configuration->Salesforce->Salesforce Authorization 

Step 2 Add the oAuth configuration setting here

Authorization setting form


Create Salesforce mapping: 

Before Salesforce mapping, make sure what exactly are you looking for. 

Scenario:

Let’s map out basic information, like first name, last name, email of Drupal users to Salesforce and push them to CRM tool. 

Follow this path (admin/structure/salesforce/mappings) to get a form similar to the shown below.

First step of Salesforce Mapping form

Now fill the list of values: 

  • Label: Label of the mapping.
  • Drupal Entity: Select users in both of the fields “Drupal Entity Type” and “User Bundle” in order to map out Drupal users. 
  • Salesforce object: Here the selected value should be contacted only.
  • Action Trigger: Ones you create a user on Drupal site, use that as a contact in Salesforce tool. For this, select all the data push actions, like insert, update, delete.

Now select Upsert key and Mapped fields.

Second step of Salesforce Mapping form


Upsert key: By setting Upsert key on Salesforce, you can prevent data duplicacy.

Mapped fields: Fill the following columns. 

  • Property: Listed Drupal fields
  • Salesforce field: Listed Salesforce fields
  • Direction: There are three directions on the radio button. Here you can see the mapped data that will be updated on Salesforce or on your Drupal site or will synchronize on both. Your mapped field data depends on this setting. 
  • Operations: If you don’t want to map this field then delete it by selecting the ‘delete field option’.

I have added Email as an Upsert key and for direction field, select “Drupal to Salesforce”.

How to test: 

Steps 1 Create a user from admin.

Note: Salesforce module will automatically push the data on CRM with contacts.  

Step 2 Run cron directly to update data with Salesforce contact by using the following path: 

/admin/config/system/cron 

The integration of Salesforce with your Drupal has endless benefits as it helps your sales and marketing to work efficiently and meet the process they perform on a regular basis in a more streamlined way. Further, it also enables you to custom-tailor industry-specific tasks, such as contact status in the Sales pipeline and contact reminders.

Below given is a presentation on "Salesforce integration with Drupal".

AngularJS: Developing custom Services

This is the fifth post in my series on the AngularJS; have a look at my initial posts covering ‘An intro to AngularJS’, ‘data-binding methods’, ‘Modules & controllers' and 'Filters'.

Considering the series is getting a bit longer, but it has immense importance as these tutorials are written in such a way to help you develop the understanding of Angular and its various components. Let’s move towards another important component of AngularJS - Services.

In a layman language, AngularJS Services is a piece of code (either business logic or objects) that can be used by an Angular application. 

Key Points:

  • It keeps your controller lightweight & makes logic that would be independent of the controller. 
  • Services only instantiated once. (the same instance is used during application cycle).
  • Services are not instantiated by default but when a controller refers to services it gets instantiated if it is not instantiated earlier.
  • A Controller can use multiple services and one service can also use another service.

Types of Services in AngularJS

1. Built-in Services: AngularJS by default provide core services, such as  $http, $log, $location angularjs etc.

2. Custom-services: These services are developed by developers to achieve certain business logic in the form of service. 

In this blog cum tutorial, we will build custom services and in the next, I will walk you through built-in services of AngularJS. 

Long story short, there are three different ways to develop custom services.

Factory: While creating services, a developer is responsible to create a service name and register the service factory function for the Angular module. Check out how to create your own custom service and call them directly to your controller. 

Sample code

Using the above source code, we can create a service name and register it to the service factory function.

The above source code has factory service that is created under the module. Where call service object with null value gets initiated and assign that service object for all the service members and return the same object. The returned object can be used directly by the controller. It passes the return object directly to the controller as a parameter. 

Once the value is available in the controller parameter then we can easily access the member function of that service as below code sample.

Service: Service is similar to the factory service. But let me tell you How does it make a difference over a selection of the right service. There is a major difference between AngularJs service vs factory service. In the service factory, we don’t need to create an additional service object and a new member function can be added directly to service definition similar to our controller, where we define member function. Also, member function gets instantiated automatically and sends the response to the controller parameter. 

The only difference between service and factory is that service object declaration. Here you don’t need to create an object and Angular takes care of - how member function gets instantiate and send to the controller as a parameter as well as minor syntax changes.

We can go with any of the service/factory.

Provider:  At this moment you must be thinking of What is a Provider in AngularJS. Let me clear you, In Angular Provider is another way to develop custom services. It is one of the core services in Angular in which services and factory are depended on. The provider has a lot of customization options compared to services and factory. Remember whenever we create custom services using factory/service, it automatically gets called to the provider in the background. 

A provider is really helpful whenever there is a service call. It helps you in initializing the configuration before any service call. In this scenario, Provider is the best option. Use Provider only when you need to instantiate some sort of configuration information or use factory/service.
 

Myapp.config provides configuration for service "TaxServiceProvider". Suffix for a service provider with 'Provider'. App configuration gets registered before the controller and services. So next time when the app controller gets instantiated it looks for service. Service is built with the Provider. While in the Bootstrap process, Provider (service) looks for configuration and executes the service.

Let’s start building a sum of two numbers using Services:

In the below source, we are implementing a simple addition of two numbers and business login using services in AngularJS.

Below we have two sources: 

1. an_page.html: Is a view 
2. an.js: implemented factory service
 

Code Explanation: In the View, we are providing two input boxes with one addition button. By default, the value of a and b will be taken up from hardcoded value, which is written directly on the controller.
 $scope.a =20;
 $scope.b =30;

When someone tries to change the value of any of the input fields the view also gets changed.
 

Service Code output

You could also initialize the same in View using ng-init. Instead of writing business logic or the addition of two numbers function inside the controller, create factory service and implement logic in the same.

As mentioned earlier, the basic rule of creating Factory service is to:
 
1. Create a blank object.
2. Assign method to that object
3. Return object so that the same could be passed over the controller as an argument.

an_page.html an.js

Let’s implement the same services using the service method.

As mentioned earlier, we don’t need to create any new object. We can directly add the member to the service. Note that an instance of service is auto-created by AngularJS.
 

& same could be passed to the controller as an argument.

Below is the source code for an.js

Moving to the next methodology of a service creation - Provider. It’s similar to factory service but allows you to add some additional configuration. Here sumServiceProvider is the provider name followed by service name + postfix(Provider keyword) else Angular will never instantiate your service configuration. As soon as Angular find service as a provider, it starts searching for configuration and instantiate some additional configuration.

MyApp.config(['sumServiceProvider', function (sumServiceProvider) {
    ………
}]);

Let’s build our provider service. This is similar to factory service.
this.$get = function () { 
}

The above function gets executed automatically by AngularJS that allows you to implement a service object as well as methods.
 

Source Code:


So far we have learned about different variants of services as well as ways to create a service and when to use them. This installment will give you an in-depth knowledge of AngularJS Services and will help you build a strong foundation. This post is a follow-up to our previous post Filters in AngularJS. Hope you enjoyed reading.
 

GitHub source code: https://github.com/xaiwant/AngularJS-Services

How to integrate Bynder DAM System with Drupal 8

In order to have a strong online presence, it's significant to offer an amazing digital experience to customers. And for this, offering a seamless experience to content managers is extremely important. To achieve this one of very important aspect is making digital assets available at different web properties to editors while they are creating content. These assets should be searchable with meta information as well as other related information. Bynder is one such digital asset management system that allows easy access to your digital file.

Let’s have a look what Bynder is and how to integrate it with Drupal 8 web application to import digital files into content pieces.

First thing first, Bynder is a cloud-based platform that helps marketers to create, find, and use digital content. Every brand that leverages media, graphics, and documents for marketing or sales efforts is a great fit to use Bynder. It is a digital content library that understands the ways in which marketers need to use the content. 

Further, the integration of Bynder with Drupal eliminates the hassle of logging into a different platform to access digital files to content. With this, content managers can use any assets available in their repository system.

Integrating Bynder into a Drupal 8 Site

First, create a Bynder account on www.bynder.com and create API tokens to access the portal using the Drupal module

Module Dependencies:

  1. Media Entity: Media entity provides a 'base' entity for media.
  2. Entity Browser: This module provides a generic entity browser/selector.
  3. DropzoneJS: An open source library that provides drag-drop file uploads feature with image previews.

Library Dependencies:

  1. DropjoneJS: Download this library and add it inside the libraries folder.
  2. ImagesLoaded: This library detects when images are loaded. Download from https://github.com/desandro/imagesloaded and add it inside the libraries folder.
  3. Masonry: It is a grid layout library. Download from https://github.com/desandro/masonry/releases and add it inside the libraries folder.

Installation:

Step 1 Enable the Bynder module via drush - drush en bynder

Step 2 At this point you should be prompted to update the Composer dependencies.

Step 3 Make sure all the packages are installed correctly in your vendor folder - default path is /vendor

Step 4 Bynder needs the "bynder/bynder-php-sdk": "^1.0" . The directory /vendor/bynder/bynder-php-sdk should be present after the composer update.

Configuration:

Step 1 Go to admin/config/services/bynder

Step 2 Fill the configuration form with your Bynder API token details. The details will include Consumer Key, Consumer Secret, Token, Token Secret and Account domain.

Step 3 Save the form to fetch the derivatives and brand information from the Bynder portal

Step 4 The jQuery version should be set to 1.7 or higher for content add/edit pages.

Step 5 Test the Bynder connection from the configuration page and Reload Derivatives. Every time a new Derivative is created in Bynder side, derivatives reloads on the Drupal site.

Bynder Configuration Page

 

Step 6 Bynder provides a default media entity that can be referred to a Drupal content-type. Select Bynder and image media type as shown in the below       

            screenshot.

Bynder Configuration Page

 

Step 7 Create an entity browser to upload and select Bynder media:

Create an entity browser from “/admin/config/content/entity_browser” and then select the entity browser from Manage Form Display (/admin/structure/types/manage/article/form-display) for the content-type in which you want to select images from Bynder. 

Bynder Form Display Settings

Step 8 Attach Bynder media in a content.

A Bynder media can be added to a content from the node add/edit form. The entity reference field stores the references to Bynder assets. A popup opens by clicking the upload asset button. Go to the Bynder Search Tab and select an image. 

Note: Log in to the Bynder repository to upload an image from node creation form.

Bynder Entity Selection Popup

Step 9  Uploading an image to Bynder

Through Bynder’s uploader widget, you can also upload images from Drupal to the Bynder Repository.

That’s it. This is how Bynder, a data asset management system, is one such tool that eases content management work of any publishing house. I believe after completing this tutorial, you will have a better understanding of how Bynder works? How to install and configure it? Once the setup is completed upload images to your Account Domain and starts using those on the Drupal site.

Componentizing Drupal Front End using Pattern Lab

Componentization has become a growing consideration in most of the web application development firms. The reasons are obvious, instead of reinventing the wheels again and again, why don’t we re-use them. This article will help you to understand the importance of componentizing your Drupal front end and how you can achieve that using Pattern Lab.

So what is Componentization?

In front-end perspective, components are a collection of HTML, CSS, and JS that combines together to form a display element and Component-Driven Development (CDD), a development methodology by which the web pages are built from the bottom up. 'Componentization' is the process of breaking things down into small and easily identifiable pieces, a practice used by developers and designers alike to solve complex problems.

Why should you follow component driven front-end development approach?

  1. Allows for re-use of Components

  2. A component-based UI approach accelerates the development

  3. You can completely decouple the front-end development

  4. Testing becomes easier

  5. Parallelize development

  6. Flexible project workflow

How to use component driven front-end development approach In Drupal?

One of the most popular tools for component driven front-end development is Pattern Lab. What makes Pattern Lab so famous is its flexibility in pairing up with the Atomic Design methodology. Addition of twig templating system in Drupal makes it easier for us to integrate Pattern Lab with Drupal. Although many starter kits for Pattern Lab with Drupal 8 are available, I personally find Emulsify the most useful one. Emulsify is a starter kit for Pattern Lab based theming created by Fourkitchens.

Integrating Emulsify with Drupal

Let me explain how you can use Emulsify for componentizing your Drupal front-end development. Emulsify is a Drupal 8 starter kit theme, which means we install Emulsify and tweak it to meet our needs rather than creating a subtheme out of it.

Before installing Emulsify, there are certain prerequisites which need to be met:

  1. Node

  2. Gulp 

  3. Composer

  4. Components Module

Installing Emulsify:

Step 1: Emulsify can either be installed using composer or you can directly download Emulsify and place it in your themes directory. 
For installation using composer: composer require Fourkitchens/Emulsify.
Step 2: You can rename the downloaded Emulsify theme to suit your project if needed.
Step 3: Move the Unified Twig Extension module from the Emulsify to modules/unified-twig-extensions. 
Step 4: Enable the Emulsify theme, unified-twig-extensions and components module.

Emulsify theme


Step 5: Run ‘npm install’ from the Emulsify theme directory.

 

npm-install


Step 6: Run ‘composer install’ from the Emulsify theme directory.

You will now have a working theme based on Pattern Lab. 

Now, Let’s create a simple component in Emulsify

Step 1: Run npm start from terminal

Your terminal screen would look like this

npm-start

A Pattern Lab instance will be created. Access URL’s are displayed on the screen. This process would take care all of the tasks like compiling the sass to CSS and updating the living style guide. Your Pattern Lab instance would look as below.

Pattern lab

Step 2: Create Component

Certain components are built within Emulsify by default. Let's create a view that will display article teasers. We will be using the card component which is in the Emulsify theme.

card grid


Step 2.1 Create a view which displays the article teasers
Step 2.2 Override node template for article teaser view mode.

node-article-teaser


Here we are including the molecule 01-card.twig.

Step 2.3 Override the view template for our articles-list view

View

Here we are extending the card-grid organism for the necessary wrapper div.

Now clear the cache and view the article list view page. You will be able to see a nice gird card with the contents you added for the article.

article browser view

So now you know how to isolate front-end workflow in Drupal using Pattern Lab. If you have any suggestions or queries please comment down let me try to answer.

Below is the presentation on "Contentization of front-end workflow in Drupal 8 using Pattern Lab".

Everything about Filters in AngularJS

This is the fourth post in my series on the AngularJS; check out my initial piece covering ‘An intro to AngularJS’, ‘Data-binding methods’ and ‘Modules & controllers’.

In Angular, Filters are used to format/search functionality in AngualrJS/transform the data. Angular provides default formatter that allows you to display the data in a formatted way to your view or pass the same for the input of another variable. By default, Angular has a list of Filter component in AngularJS and they can be added to your data by including a pipe (|) with expression.

  • Uppercase
  • Lowercase
  • OrderBy
  • Number
  • Date
  • Currency
  • Filter
  • JSON
  • LimitTo

Let’s explore each of them. 

Uppercase:  Format the data in Uppercase.

Sample code: 

Logged in User Details

  • {{n.name | uppercase}}

Uppercase passed in Controller:

We can pass the Filter to Controller by adding $filter argument in controller function. We already have a javascript function to handle uppercase and the same can be achieved in AngularJS as well. Below source code will let you pass the filter in the Controller.
 

Output:

Hello World
HELLO WORLD
HELLO WORLD


Response: The above source code format the username in uppercase.

Uppercase output

Lowercase:  Run the following code to format the data in lowercase.

Sample code: 

Logged in User Details

  • {{n.name | lowercase}}

Response: The above source code format the username in lowercase. See the screenshot below.
 

Lowercase output

Lowercase passed in Controller:  

You can also pass the filter in a controller by adding $filter argument in controller function. Javascript function handles lowercase. Similar to Uppercase, the same can be achieved in AngularJS.  
 

Output:

SAY HELLO TO NEW WORLD ANGULAR!
say hello to new world angular!
say hello to new world angular!
 

Orderby: Suppose you have a long list of user data: first name, location, job, salary. But when it comes to rendering, how would you like to filter the data in your view? Based on salary/firstname/location. Using orderby, you can achieve this. Have a look at the below code and the result.

Sample code:

  • {{ns.name + ', ' + ns.city}}

Response: In the above source code, I have filtered the user data based on the city so the response would look similar to this.

Orderby output

number: It formats data by returning number value in a string. 

syntax: 

 {{ expression | number : fractionSize}}

Here we have expressions that we are formatting the data into a string. With numbers, we have additional parameter fractionize that tells how many digits you can display decimal numbers.

Sample code: 

Result: 

What if we add price as 707.6758956 and fractionsize: 2

By default, it prints first three digits after decimal point. By adding fractionsize, you can display the number of values of your choice after the decimal.  

Will print till next two digits after decimal places.

Input: 77757.677876543
Output: 77757.67

It also prints infinite value when we have something like. 

input: 77754323467876432456787654356898765432456787654356787654307.677876543
Output: 7.775e+58

Date: This filter transforms a string date into a human-readable format as listed below: 

  • yyyy: 4 digit numeric year representation.  e.g: 1989, 2017
  • MMMM: month name in string format e.g: January, November
  • MMM: first three letter of month e.g: JAN, MAR, FEB, DEC
  • HH:  24 hours time format e.g: 24, 01,17
  • mm: minutes in double-digit format. e.g: 34, 59

Similar to that there are various formatters in AngularJS official documentation. https://docs.angularjs.org/api/ng/filter/date

Syntax:
 {{ DateExpression | date : format : timezone}}

Here DateExpression is a timestamp. 
The format of an optional parameter. String either would be medium, short, full date, long date etc. by default it takes medium Date.
timezone is also an optional parameter that is used for formatting. e.g: +0530, +0430.

Sample:  {{1288323623006 | date:'medium'}}Result: The above codebase is printing medium date format includes MMM d, y h:mm:ss a
 

Date Output


Currency: Add Currency prefix. By default, it takes location currency symbol. 

Syntax:   {{ expression | symbol : fractionSize}}

Expression is the amount that needs to be manipulated.

Symbol: It is an optional parameter. Placeholder for currency symbol e.g: USD, $, ₹
Fractionsize: It shows a number of digits after the decimal. Add 0 if you do not want to display any value after the decimal.

Sample code: {{20000000000 | currency: "₹" }}
result:   ₹20,000,000,000.00

Filter:  Technically, Filter is used to return a new array when an item is found. It is also used to get the matching element from the array.

Syntax:    {{ filter_expression | filter : expression : comparator : anyPropertyKey}}

filter_expression: source array
expression: element that you are looking for whether string, object, function.
anyPropertyKey: Is an optional parameter. Element needs to be searched.

In the below codebase, we have filtered the output data based on name having ‘i’ and gender ‘m’. Passing multiple filter value treat as & operator. Change the filter value to get the desired result.

Sample code: 
 


Output:   
Jani,m
Birgit,m

Demo Dynamic User Filter Codebase:

Json: Converts javascript objects to JSON. Primarily, it is used to debug the applications.

Syntax:  {{ expression | json : spacing}}

expression :  data to be filtered.
spacing: indentation . default is 2.

Sample code: 

The below source code formats the data in JSON format with indentation is set to 8.

Output:

{
        "name": "Alfreds Futterkiste",
        "city": "Berlin",
        "country": "Germany"
}

LimitTo: This filer returns a string or array having a specific number of elements. The counting number of character in the string, array or digits can be taken from either from the beginning or the end.

Syntax:  {{ expression | limitTo : limit : begin}}

expression: containing array,string, number  etc.
Limit: It returns string length. If it’s in –(negative) then it will start from the end or else from the beginning.
Begin: It is an optional parameter and used to offset from the end of input. The default is 0.
 

Sample code: 

Output:

Try to change the beginning and limit value and see the response.

eraser
sharpener
tape

So far we have gone through almost all the filters provided by AngularJS. Hope you must have used them in real time scenario. In case you have any question or suggestion then please comment below.


Codebase: https://github.com/xaiwant/AngularJS-Filters
 

How to make your Drupal site GDPR compliant

Many of the clients we help with developing web applications have been asking about General Data Protection Regulation (GDPR), the European Union’s new suite of data privacy law in 20 years. So we decided to provide information as clear as possible about - How does GDPR relate to a Drupal website? How to make Drupal site GDPR compliant? Are there any modules that will help me with it?  

Unsure about GDPR? Let’s dive in to the basics.

According to EU GDPR, GDPR is “designed to harmonize data privacy laws across Europe, to protect and empower all EU citizens data privacy and to reshape the way organizations across the region approach data privacy.”

The new regulation, which will come into effect on 25 May 2018, applies to data collected about EU citizens from anywhere in the world. As a consequence, a website with any EU visitors or customers must comply with the law. Have a look at the publication of the regulations in the Official Journal of the European Union in order to have a better understanding. The penalty for non-compliance can be 4% of annual global turnover, up to a maximum of €20 million.

So how does GDPR relate to your Drupal website?

Any information, such as name, address, email address, social security number, IP address etc., related to identifying a living person directly or indirectly is classed as personal data. Since most companies gather users information through forms for email marketing or CRM extensions in this case their site will be affected. Further, any form that deals with the commerce of any type is affected.

Steps to make your Drupal site GDPR compliant

  • Data collection and storage: Article 12 of GDPR, Right of access, states that before collection of data places or before a user submits the form, they must be aware of that the form on your Drupal site is collecting their personal information with the intention to store it.

  • Inform the user: Users should be aware of which of their data will be stored and use, how, where, and for what purpose. To make things simple in your form, fully disclose your data collection and storage practices in the privacy policy.

  • Keep user data organized and accessible: According to Article 17 of GDPR, Right to erasure (right to be forgotten), users must have an option to erase personal data, stop further collection and processing of the data that concerns him or her. At the same time, users should be able to download their personal data for which they have earlier given permission. Further, on request, companies should be able to provide a user with a copy of all personal information they have on them, free of cost within 40 days and delete the info on request.

  • An open channel for users request: Your Drupal website must have a simple form for consent withdrawal and/or request to view on your privacy policy page to allow users contact the company in an easy way. Setting up an email action that sends the notification to you each time the form is submitted is the best way to know happenings.

  • Communicate privacy information: Review your current privacy policy and mention clearly for making any necessary changes after the implementation of GDPR. under the new regulation, you need to explain how you process the data, data retention periods and that individuals have a right to complain if they think there is a problem with the way company is handling their data.

  • Individuals’ right: Through Drupal’s GDPR module, we ensure your website includes the following rights - the right to be informed; the right of access; the right to rectification; the right to erasure; the right to restrict processing; the right to data portability; the right to object; and the right not to be subject to automated decision-making including profiling.

  • Breach notification: In case your Drupal website ever experience a data breach of any kind, the information on the same must be communicated to all of your users within 72 hours of becoming aware of a breach.

  • Google Analytics: As per the law, if you are using Google Analytics it means you are data controller, and can decide which data should be sent to Google Analytics and not. In order to be GDPR compliant with Google Analytics, you need to follow certain guidelines, like: 

    Auditing data for personally identifiable information (PII)
    Turning on IP anonymization
    Auditing collection of pseudonymous identifiers (hashed emails, user IDs)
    Updating contract, privacy policy on the website
    Building an opt-in/out capability

  • Modules: While developing a website, we ensure that your site is integrated with different auditing modules, such as for performance, security, or a general review to check the overall status of the site. A security audit on your Drupal site reveals how data is being processed and stored on your servers, and steps that are required to comply with the GDPR.

Are there any Drupal modules that will help the website with EU compliance

In short, Drupal community has come up with General Data Protection Regulation module that gives users visibility to their stored data. As an owner of the site, it's your responsibility to deal with the organization inner workflow of dealing with customers data. Not to mention Drupal’s GDPR module can be a Kickstarter to go through checklist points to maintain the privacy and security of an individual. Further, configuring the site plays an important role.

With the integration of GDPR, users will be able to view what are the information stored about them, can correct all the stored data themselves, opt for “forget me” action from the site, can remove the account (but not the content). In addition, the updated version will have more items and recommendations on the checklist.

Okay, so now you know what GDPR is and how you can make your Drupal website GDPR compliant. Understanding how to adhere to these rules confounds many people, but it's an essential part when your customers are from EU. Our intention here is to inform. We will try our best to keep you updated as the regulation move towards implementation. 

Still worried how you go about making your site GDPR compliant? Drop a mail at info@valuebound.com and let our Drupal 8 experts help you with your queries.

 

 

How to generate PDF of HTML code in Drupal 8

Have you ever been in a situation where you were required to generate PDF of HTML code? Recently, I came across a similar situation. In Drupal 8, there are several PHP libraries that allow you to generate PDF. However, out of curiosity, I thought of finding better alternatives. After some research, I found an interesting library, called mPDF, that converts HTML code to PDF without changing the structure.

mPDF is a smart library that considers the CSS attached to the HTML. Not only CSS, it takes care of almost all the HTML tags like form tags, tables, images, lists etc.

Generating PDF of HTML in custom module

Requirements

mPDF 7.0 requires PHP ^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0. PHP mbstring and gd extensions

Installation

Step 1 Download mPDF via composer and its packageist package mpdf/mpdf.

Step 2 Run the following command in the Drupal root directory: 

$ composer requires mpdf/mpdf

Step 3 Once the mPDF libraries install generate the pdf in the custom module.

Step 4 In custom module, create a controller with routing path(/pdf-download)

Step 5 Now hit the URL (/pdf-download) to download pdf

Whenever you hit the URL, pdf will automatically get downloaded. Further, the HTML which we wish to print can be passed dynamically too. For example, by passing the node contents, we can download the node contents in a pdf file.

Hope you can now generate PDF from encoded HTML in the custom module. If you have any suggestions or queries please comment down let me try to answer.

Download the Drupal Guide
Enter your email address to receive the guide.
get in touch