Friday, December 27, 2019

Laravel 5 | Start Session Manually | Dynamically Set Session Id on Creating Session | Extending the StartSession Middleware | Session Handler Extending

Its really easy using the middleware in Laravel 5, I needed any request with an API key not to have a session and I simply did :
For this case you can create a StartSession middleware for your application that extends the Illuminate and need to override few methods to manage as you want.

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession as BaseStartSession;

class StartSession extends BaseStartSession
{

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return parent::handle($request, $next);
    }

    /**
     * Get the session implementation from the manager.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Contracts\Session\Session
     */
    public function getSession(Request $request)
    {
        return tap($this->manager->driver(), function (\Illuminate\Contracts\Session\Session $session) use ($request) {
            // getting session id from request
            // then using the same id for session
            $token = request()->header("token", null);
            if (is_null($token)) {
                $token = "custom" . \Str::random(34);
            }

            $session->setId($token);
        });
    }

    /**
     * Start the session for the given request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Contracts\Session\Session
     */
    protected function startSession(Request $request)
    {
        return tap($this->getSession($request), function (\Illuminate\Contracts\Session\Session $session) use ($request) {
            $session->setRequestOnHandler($request);

            $session->start();
        });
    }
}
Now need to replace session middleware in kernel file: app\Http\Kernel.php as below:

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \App\Http\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            \App\Http\Middleware\StartSession::class,
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];

    /**
     * The priority-sorted list of middleware.
     *
     * This forces non-global middleware to always be in the given order.
     *
     * @var array
     */
    protected $middlewarePriority = [
        \App\Http\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\Authenticate::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];
}

Thursday, December 19, 2019

ReactJS - Multiple Layout In React Using React Router | Using multiple layouts for react-router components

React Router is a standard routing library for React.
In the first step, we will create two different layout files (named CommonLayout and DashboardLayout) and their respective routes to implement multiple layouts in React.

CommonLayout


import React, { Component } from 'react';
import {Route} from 'react-router-dom';

class CommonLayoutComponent extends React.Component{
    constructor(props){
        super(props);
        this.createRef = this.createRef.bind(this);
    }

    createRef(element) {
        console.log(element);
    }

    render() {
        return (
            <div key="dashboard">
                <div className="Content" ref={this.createRef}>
                    {this.props.children}
                </div>
            </div>
        );
    }
}

const CommonLayoutRoute = ({component: Component, ...rest}) => {
    return (
        <Route {...rest} render={matchProps => (
            <CommonLayoutComponent {...matchProps}>
                <Component {...matchProps} />
            </CommonLayoutComponent>
        )} />
    )
};

export default CommonLayoutRoute;

DashboardLayout


import React, { Component } from 'react';
import { Route } from 'react-router-dom';

const DashboardLayoutRoute = ({component: Component, ...rest}) => {
    return (
        <Route {...rest} render={matchProps => (
            <div>
                <h3>Dashboard Layout</h3>
                <Component {...matchProps} />
            </div>
        )} />
    )
};

export default DashboardLayoutRoute;
Now, update your App.js file to use both - the layout and the component - as below.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';

/** Layouts **/
import CommonLayoutRoute from "./CommonLayoutRoute";
import DashboardLayoutRoute from "./DashboardLayout";

/** Components **/
import LayoutPage1 from './LayoutPage1';
import LayoutPage2 from './LayoutPage2'

/*
   App
 */
class App extends Component {
    render() {
        return (
            <Router>
                <Switch>
                    <Route exact path="/">
                        <Redirect to="/layout1" />
                    </Route>
                    <CommonLayoutRoute path="/layout1" component={LayoutPage1} />
                    <DashboardRoute path="/layout2" component={LayoutPage2} />
                </Switch>
            </Router>
        );
    }
}

export default App;
Here, we have updated the App.js file as defined in the route. When we route to /layout1, then CommonLayoutRoute (our first layout) will be used as the master page for the component LayoutPage1. On the other hand, when we route to /layout2, then our second layout, i.e., DashbaordLayoutRoute will be used as the master page for the component LayoutPage2.

Wednesday, December 18, 2019

ReactJS - Preventing Form Submission

I've been experimenting with React. In my experiement, I'm using the React framework. When I click a button, I've noticed that the HTML form submits. Is there a way to prevent form submission when a button is clicked? Just need to add the following attribute to the form.

<form onSubmit={(e) => e.preventDefault()}>


</form>

Laravel Custom Data Validation | Validate Request Data And Return Appropriate Error Message

Now we are ready to fill in our store method with the logic to validate the new blog post. To do this, we will use the validate method provided by the Illuminate\Http\Request object. If the validation rules pass, your code will keep executing normally; however, if validation fails, an exception will be thrown and the proper error response will automatically be sent back to the user. In the case of a traditional HTTP request, a redirect response will be generated, while a JSON response will be sent for AJAX requests.
<?php
namespace App\Http\Controllers;

use Validator;
use App\Models\Users;
use Illuminate\Support\Facades\Log;

class RegistrationController extends ControllerBase {
    /**
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function register() {
        if ($this->isLoggedIn()) {
            $this->setErrorMessage("Already logged in");
            throw new \Exception("Already logged in");
        }

        // if data is json formatted
        if (true) {
            $data = json_decode(request()->getContent(), true);

            request()->merge($data);
        }

        // custom messaged will show when validation fail
        // for example if name is missing will return 'The Name field is required'
        // we can define full message without using :attribute like 'email.unique'
        $customMessages = [
            'required' => 'The :attribute field is required.',
            'in' => 'The :attribute field has invalid data',
            'password.required' => 'Password required',
            'email.unique' => 'Email address must be unique'
        ];

        // used to set display name against key
        // for example if email is required then 'The Email Address field is required'
        $attributes = [
            'name' => 'Name',
            'email' => 'Email Address',
            'password' => 'Password',
            'status' => 'Status'
        ];

        $validator = Validator::make(request()->all(), [
            'name' => 'required|max:70',
            'email' => 'required|email|max:70|unique:users',
            'password' => 'required|min:6|max:70',
            'status' => 'required|in:pending',
        ],  $customMessages, $attributes);

        $validator->after(function($validator) {
            // If some validation failed
            if (true) {
                $validator->errors()->add('field', 'The field has invalid data');
            }
        });

        if ($validator->fails()) {
            Log::error($validator->errors());
            return response()->json(["success" => 0, "error" => $validator->errors()->first()], 200);
        }

        $user = Users::create(request([
            'name',  'email', 'password', 'status'
        ]));

        return response()->json(["success" => 1, "user_id" => $user->id]);
    }
}

Monday, December 2, 2019

How to access a DOM element in React? What is the equilvalent of document.getElementById() in React | ReactJS access HTML Element Node Reference

React supports a good way to set refs called “callback refs”, which gives more fine-grain control over when refs are set and unset.
Instead of passing a ref attribute created by createRef(), you pass a function. The function receives the React component instance or HTML DOM element as its argument, which can be stored and accessed elsewhere.
The example below implements a common pattern: using the ref callback to store a reference to a DOM node in an instance property.
class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;

    this.setTextInputRef = element => {
      this.textInput = element;
    };

    this.focusTextInput = () => {
      // Focus the text input using the raw DOM API
      if (this.textInput) this.textInput.focus();
    };
  }

  componentDidMount() {
    // autofocus the input on mount
    this.focusTextInput();
  }

  render() {
    // Use the `ref` callback to store a reference to the text input DOM
    // element in an instance field (for example, this.textInput).
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

Wednesday, November 27, 2019

Git Bash | Changing a remote's URL | How to Change a Git Remote's URL | How Save Username/Password/Credentials For Git Repository in Git Bash

Got to the directory where the repository is located using Git Bash:

cd /path/to/repository
Run git remote to list the existing remotes and see their names and URLs:

git remote -v

The output will look something like this:

origin https://pritomkucse@bitbucket.org/pritomkucse/demo_project.git (fetch)
origin https://pritomkucse@bitbucket.org/pritomkucse/demo_project.git (push)
For example, to change the URL of the origin to some other repo you would type:

git remote set-url origin https://pritomkucse:your_password@bitbucket.org/pritomkucse/demo_project_2.git
Verify that the remote URL has changed using the same command git remote -v

Sunday, November 24, 2019

ReactJS Render HTML string as real HTML in a React component

First need to install react-html-parser to render html as html element in react js.
Run below command to add the dependency:

npm add react-html-parser
Then use as below:

import ReactHtmlParser from 'react-html-parser';

import axios from 'axios'
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import MainActivity from "./MainActivity";
import ReactHtmlParser from 'react-html-parser';

class ProjectsList extends MainActivity {
    constructor () {
        super();
        this.state = {
            projects: [],
            loading: true,
            html: ""
        };
    }

    componentDidMount () {
        axios.get(`${this.APP_URL}/api/projects`).then( response => {
            console.log(response);
            this.setState({
                projects: response.data,
                loading: false,
                html: response.data.html
            })
        })
    }

    render () {
        if (this.state.loading) {
            return this.loader()
        }
        if (this.state.html) {
            return <div>{ ReactHtmlParser(this.state.html) }</div>;
        }
        const { projects } = this.state;
        return (
            <div className='container py-4'>
                <div className='row justify-content-center'>
                    <div className='col-md-8'>
                        <div className='card'>
                            <div className='card-header'>All Projects</div>
                            <div className='card-body'>
                                <Link className='btn btn-primary btn-sm mb-3' to='/project/create'>
                                    + Create New Project
                                </Link>
                                <ul className='list-group list-group-flush'>
                                    {projects.map(project => (
                                        <Link
                                            className='list-group-item list-group-item-action d-flex justify-content-between align-items-center'
                                            to={`/project/${project.id}`}
                                            key={project.id}>
                                            {project.name}
                                            <span className='badge badge-primary badge-pill'>{project.tasks_count}</span>
                                        </Link>
                                    ))}
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default ProjectsList