Friday, April 17, 2020

Firebase Authentication for Web - Sign-in Method Email/Password Implementation

First go to https://firebase.google.com/docs/web/setup and create a project step by step by following https://console.firebase.google.com/.

Step 2: Register your app with Firebase

Go to https://console.firebase.google.com/u/0/project/test-firebase-auth-1/authentication/providers for enable signin method.

I enabled Email/Password authentication type for this example.

To initialize Firebase in your app, you need to provide your app's Firebase project configuration.

Go to Project Settings page for configure app and get API Key.



Step 3: Add Firebase SDKs and initialize Firebase, we will use CDN to load all necessary resources

<script src="//www.gstatic.com/firebasejs/7.14.0/firebase-app.js"></script>
<script src="//www.gstatic.com/firebasejs/7.8.1/firebase-auth.js"></script>

<script type="text/javascript">
    $(document).ready(function () {
        // Your web app's Firebase configuration
        var firebaseConfig = {
            apiKey: "AIzaSyA9XqTsdfsdfsdf0w9TSlYSlUlpCLcNjeM",
            authDomain: "test-firebase-auth-1.firebaseapp.com",
            databaseURL: "https://test-firebase-auth-1.firebaseio.com",
            projectId: "test-firebase-auth-1",
            storageBucket: "test-firebase-auth-1.appspot.com",
            messagingSenderId: "514502059460",
            appId: "1:51450324232059460:web:70b12cd2342345ee4287f932f091"
        };
        // Initialize Firebase
        var defaultProject = firebase.initializeApp(firebaseConfig);

        console.log(defaultProject.auth());
    });
</script>
You can restrict your API Key to specific domain using below steps:

1. Visit https://console.developers.google.com/apis
2. Go to your firebase project
3. Go to Credentials
4. Under API keys, select the Browser key associated with your firebase project (should have the same key as the API key you use to initialize your firebase app.)
5. Under "Accept requests from these HTTP referrers (web sites), simply add the URL of your app.



We are done from configure Firebase.

Now we will build our registration/login page.

Request Sample When User State Changed (Login,Logout,Registration)


defaultProject.auth().onAuthStateChanged(function(user) {
    if (user) {
        console.log("Logged in user details");
        console.log(user);

        console.log(user.displayName);
        console.log(user.email);
    }
    else {
        window.location.href = "/";
    }
});

Request Sample to Register User With Email/Password


defaultProject.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
    console.log(error);
    if (error.message) {
        alert(error.message);
    }
});

Request Sample to Login Action


defaultProject.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
    console.log(error);
    if (error.message) {
        alert(error.message);
    }
});

Password Reset Email Send Request

defaultProject.auth().sendPasswordResetEmail(email).then(function() {
    alert('Password Reset Email Sent!');
}).catch(function(error) {
    console.log(error);
    if (error.message) {
        alert(error.message);
    }
});

You can configure password reset URL



You can reset your password using below code snippet

const queryString = window.location.search;

const urlParams = new URLSearchParams(queryString);

const code = urlParams.get('oobCode');

defaultProject.auth().confirmPasswordReset(code, "Password-123456").then(function() {
    alert('Password Reset Completed');
}).catch(function(error) {
    console.log(error);
    if (error.message) {
        alert(error.message);
    }
});
Finally GibHUB link to the sample project


Saturday, March 14, 2020

Laravel-mix Webpack Public Path | Set custom path for chunk files | Using Laravel Mix with webpack for All Your Assets

Laravel Mix allows you to use a single line to describe what you want and it'll use it's preconfigured settings to process it properly.
Most of our time will be spent in the webpack.mix.js file. In the file, we can configure all we need to do to set public path and we can also set js file location for chunk js files when we use Suspense and lazy for dynamic js loading for per route.
There are several more Mix methods and you can set all of them in the default webpack.mix.js file.
// Full API
    // mix.js(src, output);
    // mix.react(src, output); <-- Identical to mix.js(), but registers React Babel compilation.
    // mix.extract(vendorLibs);
    // mix.sass(src, output);
    // mix.standaloneSass('src', output); <-- Faster, but isolated from Webpack.
    // mix.fastSass('src', output); <-- Alias for mix.standaloneSass().
    // mix.less(src, output);
    // mix.stylus(src, output);
    // mix.postCss(src, output, [require('postcss-some-plugin')()]);
    // mix.browserSync('my-site.dev');
    // mix.combine(files, destination);
    // mix.babel(files, destination); <-- Identical to mix.combine(), but also includes Babel compilation.
    // mix.copy(from, to);
    // mix.copyDirectory(fromDir, toDir);
    // mix.minify(file);
    // mix.sourceMaps(); // Enable sourcemaps
    // mix.version(); // Enable versioning.
    // mix.disableNotifications();
    // mix.setPublicPath('path/to/public');
    // mix.setResourceRoot('prefix/for/resource/locators');
    // mix.autoload({}); <-- Will be passed to Webpack's ProvidePlugin.
    // mix.webpackConfig({}); <-- Override webpack.config.js, without editing the file directly.
    // mix.then(function () {}) <-- Will be triggered each time Webpack finishes building.
    // mix.options({
    //   extractVueStyles: false, // Extract .vue component styling to file, rather than inline.
    //   processCssUrls: true, // Process/optimize relative stylesheet url()'s. Set to false, if you don't want them touched.
    //   purifyCss: false, // Remove unused CSS selectors.
    //   uglify: {}, // Uglify-specific options. https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
    //   postCss: [] // Post-CSS options: https://github.com/postcss/postcss/blob/master/docs/plugins.md
    // });
Below is the code snippet which will define js file location for chunk js files:
const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.react('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

mix.webpackConfig({
    output: {
        // Directory for junk files to {ROOT_DIR}/public/js
        chunkFilename: 'js/[name].js',
    },
});

Thursday, March 12, 2020

React Component on Window Resize Event

React doesn't have a resize event integrated into it, but we can listen to the native browser window resize event from within our React component. We will attach window resize event into componentDidMount method.
Under normal conditions, React will re-render a component when its props or state changes. To trigger a re-render of Component in the example, we'll set internal state on the component when the event is fired. So we can set/update state variable to tell React Component to update. We can implement method componentDidUpdate to acknoledged something changed.
When adding an event listener, such as we are for the resize event, we should make sure to clean up after ourselves. We will clean up any type of listener we added into method componentWillUnmount.
Example code given below:
import React from "react";
import "./styles.css";

class App extends React.Component {
  constructor() {
    super();

    // we will update below state variables to tell react component
    // to update, only state or props change can update react component
    this.state = {
      width: 0,
      height: 0
    };

    // we will use this timer to less fire resize event
    // practially we will fire resize event 500 miliseconds after
    this.timer = null;

    // we will catch windows resize event into below function
    this.windowResized = this.windowResized.bind(this);

    // we will handle resize event so resize event will
    // be in some time interval, less freequent 
    this.updateWindowWidth = this.updateWindowWidth.bind(this);
  }

  componentDidMount() {
    window.addEventListener("resize", this.windowResized);
    this.updateWindowWidth();
  }

  componentDidUpdate() {
    console.log(
      `Window width/height changed to ${this.state.width}X${this.state.height}`
    );
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.windowResized);
  }

  updateWindowWidth() {
    let _this = this;
    setTimeout(function() {
      _this.setState({
        width: window.innerWidth,
        height: window.innerHeight
      });
    });
  }

  windowResized() {
    let _this = this;
    if (this.timer) {
      clearTimeout(this.timer);
    }
    this.timer = setTimeout(function() {
      _this.updateWindowWidth();
    }, 500);
  }

  render() {
    return (
      <div className="App">
        <h1>
          WIDTH={this.state.width} HEIGHT={this.state.height}
        </h1>
      </div>
    );
  }
}

export default App;
Sample Image:

Live Example:

https://codesandbox.io/s/react-component-on-window-resize-event-3b29u

Saturday, March 7, 2020

Lazy Loading React Components (with react.lazy and suspense)

Our first step is to create an React application using below command:

npm init react-app react-lazy-loading-component

Navigate to project folder and type npm start to start project on browser.

Make sure you execute command npm run build to prepare build script which will be deployed on server

Route-based code splitting

You have to install react-router-dom using npm install --save react-router-dom to use this functionality.

Deciding where in your app to introduce code splitting can be a bit tricky. You want to make sure you choose places that will split bundles evenly, but won’t disrupt the user experience.

A good place to start is with routes. Most people on the web are used to page transitions taking some amount of time to load. You also tend to be re-rendering the entire page at once so your users are unlikely to be interacting with other elements on the page at the same time.
Sample App.js

import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import React, {Suspense, lazy} from 'react';
import './App.css';

import Header from './Header';

const Home = lazy(() => import('./Home'));
const AnotherHome = lazy(() => import('./AnotherHome'));

function App() {
    return (
        <div>
            <Router>
                <Header/>
                <div className="container">
                    <Suspense fallback={<div>Loading...</div>}>
                        <Switch>
                            <Route exact path="/" component={Home}/>
                            <Route exact path="/another-home" component={AnotherHome}/>
                        </Switch>
                    </Suspense>
                </div>
            </Router>
        </div>
    );
}

export default App;
Actually use of Suspense and Lazy will load components chunk by chunk when they needed, and once a component loaded into browser will not load second time.
GitHub Link https://github.com/pritomkucse/react-lazy-loading-component
Live Example at codesandbox.io

https://codesandbox.io/s/lazy-loading-react-components-with-reactlazy-and-suspense-2hx75

Make sure you see console to ensure that suspense callback working as expected:


Saturday, February 29, 2020

Laravel Migrations with MySQL 8.0.x - How to resolve the error: SQL authentication method unknown in Laravel-MySql

By default and for some reason, mysql 8 default plugin is auth_socket. Applications will most times expect to log in to your database using a password.
If you have not yet already changed your mysql default authentication plugin, you can do so by:

1. Log in as root to mysql
2. Run this sql command:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
Replace 'password' with your root password. In case your application does not log in to your database with the root user, replace the 'root' user in the above command with the user that your application uses.

Windows Command Prompt - Change the default Command Prompt directory

The change requires you to modify a value in the Registry. To do so press the Windows and R key at the same time to open up the run box on the system. Type in regedit and tap on the enter key on the keyboard to load the Registry Editor. You may receive an UAC prompt on newer versions of the operating system which you need to accept before the Registry Editor opens up.
Navigate to the key HKEY_CURRENT_USER\Software\Microsoft\Command Processor and search for the String Autorun in the right window.If you can't find the parameter there right-click on Command Processor and select New > String. Name the string Autorun and click ok. Now double-click the new Autorun entry that you find on the right and enter the following string (as example).

C:\Users\PRITOM\Desktop\MINE

MySQL Installation With Error: Microsoft Visual C++ 2019 Redistributable Package (x64) is not installed. Latest binary compatible version will be installed if agreed to resolve this requirement.

Microsoft Visual C++ 2019 Redistributable Package (x64) is not installed. Latest binary compatible version will be installed if agreed to resolve this requirement.
You need to download latest Microsoft Visual C++ Redistributable Package to resolve the problem.
You can download latest one from https://www.microsoft.com/en-us/download/details.aspx?id=48145