Wednesday, August 21, 2019

NodeJs MySQL Observer

Hello,

In this blog we are going to learn how to use NodeJs to observe changes in MySql databases. This is useful when you want to track MySQL changes and based on that want to send some events to frontends or want to do any other actions.

For this first of all you have to enable binary logging in you database. Binary logging is very much useful for real time MySQL replication. In Amazon RDS, it's by default available and you can switch on it from configurations. For your local database if you are using MAMP, you can do following trick.

Create a file with name my.cnf and add following content to it.

[mysqld]
server-id = 1
default-storage-engine = InnoDB
log-bin=bin.log
log-bin-index=bin-log.index
max_binlog_size=100M
expire_logs_days = 10
binlog_format=row
socket=mysql.sock

Add this file to conf folder of your MAMP directory and restart MySQL server. This will enable binary logging in your database.

Now to observe this changes we use npm package called zongji . Install it with NPM.

Add following code to your NodeJs script.

var ZongJi = require('zongji');
var _underScore = require('underscore');

var zongji = new ZongJi({
    user : 'YOUR_USERNAME',
    password : "YOUR_PASSWORD",
    database: 'YOUR_DATABASE',
    socketPath : '/Applications/MAMP/tmp/mysql/mysql.sock'
});

Now add event on binlog.

zongji.on('binlog', function(evt) {

});

This event is triggered whenever there is a change in any of your database tables.

Inside this event you can have logic of checking new rows, updates rows, deleted rows.
zongji.on('binlog', function(evt) {
if (evt.getEventName() === 'writerows' || evt.getEventName() === 'updaterows' || evt.getEventName() === 'deleterows') {
var database = evt.tableMap[evt.tableId].parentSchema; 
        var table =  evt.tableMap[evt.tableId].tableName; 
        var columns = evt.tableMap[evt.tableId].columns; 
        _underScore.each(evt.rows, function(row) {
        });
}
});

At last start the process and pass the events you want to watch.
zongji.start({
  includeEvents: ['tablemap', 'writerows', 'updaterows', 'deleterows']
});

Tuesday, August 20, 2019

ReactJs Material UI Table Infinite Scroll

Hello,

Recently in one of my ReactJs project, I faced a challenge in implementing infinite scroll in Material UI table. In this blog I am going to mention trick I have used.

First of all I was really surprised to see that Material UI table does not have infinite scroll function out of the box. It's very much needed. Sometimes something can not be achieved with frameworks, can be achieved via basics of JavaScript. In this I have done something similar.

I tried adding on scroll events on Table, Table Body but it didn't work. I also tried adding refs to body and then bind the Scroll event but that also did not work. After struggling for couple of hours, I finally decided to it with Pure JavaScript.

Step 1 : Wrap material UI table inside the container with fixed height and set overflow = scroll to container.


import styled from "styled-components";

export const Table = props => (
  <TableWrapper id={props.id}>
    <MuiTable {...props}/>
  </TableWrapper>

);

const TableWrapper = styled.div`
  max-height: 500px;
  overflow: scroll;

  ::-webkit-scrollbar {
    width: 3px;
    height: 3px;
  }
`;

As you can see I created a wrapper of table and set max height to it. You can make it dynamic as well depending on window height.

Step 2: Import Table to your component

import {
  Table

 } from './components/Table';

return (
          <>         
             <Table id={"tableID"}/>
          </>
        );

Step 3: Bind scroll event to wrapper

let me = this;
document.getElementById('tableID').onscroll = function(event){
   if(this.scrollTop == (this.scrollHeight - this.clientHeight)){
         //User reached bottom of table after scroll
         //Logic to call web services to get next set of data
   }
};

Hope this helps you.

Monday, August 19, 2019

Accessing Data From Redis Using NodeJs

Hello,

When you are working with business applications, it's sometimes need to cache the data. At this point Redis can be very useful, it can be used as database or cache database. You can store any kind of data like strings, JSON objects etc. in Redis.

Problem we face while working with NodeJs and Redis, get data operation from Redis is Asynchronous operations so it gives you callback and your code execution will continue. This may create a problem when you want to handle it in Synchronous way. For example you may have loops inside that you are trying to access data from Redis.

In this blog I am going to explain how you can have Synchronous operations. In nutshell we got to promisify the redis module.

There is a library called bluebird, that can be used for this. Lets go step by step.

Step 1

Install bluebird and redis in your NodeJs app.

npm install bluebird
npm install redis

Step 2

Import it in NodeJs app.

var redis = require('redis');
var bluebird = require("bluebird");

Step 3

Promisify Redis.

bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);

Step 4

Connect to Redis client.

var client = redis.createClient();
    client.on('connect', function() {
    console.log('Redis client connected');
});

Step 5

Use Async version of get function to get data.

client.getAsync("MY_KEY").then(function(res) {
      //Access Data
});

This is how you can have Sync operations with Redis. 

Thursday, August 15, 2019

ReactJs / Angular - Override Material UI Theme

Hello,

While working with React or Angular Applications we normally uses Material UI themes and components and it's great choice because it has nice set of themes and colors and ready to use components. That makes our life easy.

One challenge we face is, in case if we want to change or override the theme. For example Material ui has dark blue theme. What if you want to change colors or dark blue theme with your own color. One option is you can declare the class with same name and give your own property. However the better solution is to use theme override. In this blog I am going to mention how to this.

Please note the method I am going to mention here is specific to React application.

First of all create theme.js file in your app and add following code to it.

import React from "react";
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import blueGrey from "@material-ui/core/colors/blueGrey";
import lightBlue from "@material-ui/core/colors/lightBlue";
import "typeface-roboto";

import { ThemeProvider as ScThemeProvider } from "styled-components";

export default props => (
  <ScThemeProvider theme={muiTheme}>
    <MuiThemeProvider theme={muiTheme}>
      <CssBaseline>{props.children}</CssBaseline>
    </MuiThemeProvider>
  </ScThemeProvider>
);

const theme = {
  overrides: {
  },
  palette: {
    primary: { 
      main: '#MAIN_COLOR' 
    }, 
    secondary: { 
      main: '#SECONDARY_COLOR' 
    },
    background: {
      default: '#BACKGROUND_COLOR'
    }
  },
  type: "dark"
};

const muiTheme = createMuiTheme(theme);

Now here in overrides you can add code to override. For example if you want to change panel header. If you inspect html element you will find it has a class MuiPaper-root

Here is how you can override base CSS of it.

   overrides: {
    MuiPaper: {
      root: {
        background: '#YOUR_COLOR'
      },
      rounded: {
        background: '#YOUR_COLOR'
      }
    }

Same way for any other components you can do it. Inspect the HTML structure, find out Class Name and override it.

Wednesday, August 14, 2019

NodeJs , MySql Wait For Query Result

Hello,

One major issue we face while working with NodeJs and MySql is waiting for query result. When you have nested queries or you have to use for loop inside query result and wait for it's output. Because NodeJs MySql uses async function to give you query result and by the time you get the result the script finish execution.

In this blog I am going to mention one of the method I have used in one of my project. There can be various other ways for it.

First of all we have to import async plugin in your node app and add it to your script.

var async = require('async');

Now, lets assume here is your first query.

const result = connection.query('SELECT * FROM TABLE1', async function(err, rows, fields) {

});

Now this query result you have to do loop and have more queries.

let resultRows = Array();
const result = connection.query('SELECT * FROM TABLE1', async function(err, rows, fields) {
     async.each(rows, function (row, callback) {
          connection.query('SELECT * FROM TABLE 2', function(err, innerRow){
                 resultRows.push(innerRow);
                 callback(null);
          });
     }, async function () {
            //This is the final function which get executed when loop is done.
            const response = {
                statusCode: 200,
                headers: {
                "Access-Control-Allow-Origin" : "*" // Required for CORS support to work
              },
                body: JSON.stringify({
                  success: true,
                  data: resultRows
                })
              };
              callback(null, response);
    });
});

As you can see in above code, after first query is executed we are using async each for the loop.
In second query result function we are returning null callback. Once the loop is executed and all the null call backs are return it will call the final function where you will get your result rows. There you can process the result.

Tuesday, August 13, 2019

ReactJs - Convert JSON Data using loadash

Hello,

Finally now I am going to post few blogs on React and ReactJs. In this blog we are going to learn how we can modify, manipulate or edit JSON data received from API according to your need.

This will be very useful when your backend developer refused to change API response. So not to worry, let it be as it is and convert data on your side before you use it.

For this we are going to use Lodash library, so first of all add it your ReactJs project using npm and import it in your class file.

import _ from "lodash";

Now create function for converting data.

const convertData = (data, key) =>{
  let result = _.chain(data)
    .get(key)
    .map(d => ({
      modified_key1: _.get(d, "original_key1"),
      modified_key2: _.get(d, "original_key2"),
      modified_key3: _.get(d, "original_key3"),
      modified_key4: _.get(d, "original_key4")
    }))
    .value();
    return result;
}

Now call this function in your API response.

let modifiedData = convertData(response.body, "data");

Here data is the root key of your JSON response. Change it according to your JSON response. That's it now you have modified data according to your requirements.

Saturday, July 13, 2019

Swift - Notify ViewController from AppDelegate On FCM / APN

Hello,

Recently I tried  my hands on iOS app after long time as I had to convert one of our hybrid app to native app on urgent basis. There I had webview where I was loading my html app. On FCM message receieved we need to send URL received in FCM to webview and load the URL.

So here in this blog I will mention the procedure for it.

First of all in AppDelegate we have didReceiveRemoteNotification method. There we will create notification for it. Here is the code.


let url = dict
serverURL = url;
let notificationName = Notification.Name("updateWebView")
NotificationCenter.default.post(name: notificationName, object: nil)

Now in the ViewController where you want to make updates, subscribe to this notification in viewDidLoad function.

override func viewDidLoad() {
  let notificationName = Notification.Name("updateWebView")
  NotificationCenter.default.addObserver(self, selector:            #selector(ViewController.updateWebView), name: notificationName, object: nil)
}

And then add function in ViewController.

@objc func updateWebView() {
  let appDelegate = UIApplication.shared.delegate as! AppDelegate
  let serverURL = appDelegate.serverURL
        
  guard let url = URL(string: serverURL!) else {
     print("Invalid URL")
     return
  }
        
  let request = URLRequest(url: url)
  webView.load(request)
}

That's it and now you will have data passed from AppDelegate to ViewController. This method you can pass any kind of data from FCM to respective ViewController.

Hope this helps you.



Sunday, May 5, 2019

Laravel Mail Queue Get Receiver User

Hello,

Recently in one my Laravel project faced an issue where in Mail we have to change content dynamically based on receiver. As we know that when we use Mailable class and mail queue, mail will not sent immediately but it will be processed with Mail Queue. Here we don't have Auth Session or any other information to get receiver user.

To solve this I used following trick.

In mailable class if you check $this variable it will give all such information like this.

from-> => "norply@xyz.com"
address-> : Array[
    0 => Array[
          "address" => "hdave10@gmail.com"
    ]
]

From here you can access email address like this

$emailOfReceiver = $this->to[0]["address"];

And using this you can find user object from Auth\User model or your own model which you used for user information in your laravel project. For my case I was using EmployeeMaster model to get additional information.

Following line I have used in one my Mailable class.

$employee = EmployeeMaster::where("emp_email",$this->to[0]["address"])->first();

Now with this I can write my logic to dynamically change the content of mail.

Hope this helps you.

Wednesday, February 13, 2019

Laravel - Connect With Multiple Database

Hello,

In this blog post I am going to mention how we can connect multiple databases with Laravel applications. First add multiple connections in config/database.php For this copy paste mysql connection and change configurations as following.

'mysql1' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE_1',''),
            'username' => env('DB_DATABASE_1_USERNAME',''),
            'password' => env('DB_DATABASE_1_PASSWORD',''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => false,
            'engine' => null,
        ],

Now add these values in .env file

DB_DATABASE_1=YOUR_DB_NAME
DB_DATABASE_1_USERNAME =YOUR_USER_NAME
DB_DATABASE_1_PASSWORD = YOUR_PASSWORD

Now laravel give you two ways to switch database connection.

1) Set connection property in Eloquent Model

protected $connection = 'mysql1';

So here when you use this model to get data it will use the connection specified in the mysql1. You don't need to manually change it. 

2) use DB:connection 

If you are using raw queries and using DB facade so to get query the data. You have to use following logic.

DB::connection('mysql1')->table(env('DB_DATABASE_1','')).'.TABLE_NAME')


So here first you have specified connection and then used table by appending db name in front of it. 

So this is how you can manage multiple databases.