React Todo List with Undo Timer on Delete

Goodmorning, 
it’s more time that not write, i spent some time to study ReactJS, so i think that Angular is better, but so ReactJS has its “why”.
Today i want to show how create a simple React TodoList Example in which i have implemented a system to delete an item, but whit a “undo” (possibilities of recovery the deleted item), the undo has a timer (like gmail) to recover the deleted item.

So Let’s start!

Structure of our Component

We must to think as “React”, so we define our component composition:
– TodoList
— TodoListForm
— TodoListElement
— TodoListElementDelete

At first we must to create the class, and define it in src/components/TodoList.js

Attach all the code below, you can find the entire example on CodeSandBox

import React from "react";
import Header from "./Header";

class TodoListElementDelete extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      index: 0,
      timer: 0,
      _timeoutRef: null
    };

    this.onClickUndoDelete = this.onClickUndoDelete.bind(this);
  }

  componentDidMount() {
    this.setState({
      index: this.props.index,
      timer: this.props.timer
    });
  }

  componentDidUpdate() {
    if (this.props.enable) {
      this.state._timeoutRef = setTimeout(() => {
        if (this.state.timer > 0) {
          this.setState({
            timer: this.state.timer - 1
          });
        } else {
          this.props.onEndTimerAction();
        }
      }, 1000);
    }
  }

  componentWillUnmount() {
    console.log("componentWillUnmount");
    clearTimeout(this.state._timeoutRef);
  }

  onClickUndoDelete() {
    clearTimeout(this.state._timeoutRef);
    this.setState({
      timer: this.props.timer
    });
    this.props.onClickUndoDelete();
  }

  render() {
    let classHideItem = this.props.enable ? "" : "hidden";
    return (
      <div className={"alert alert-danger " + classHideItem}>
        You want to undo the action? {this.state.timer}
        <button
          type="button"
          className="btn btn-warning"
          onClick={this.onClickUndoDelete}
        >
          Undo
        </button>
      </div>
    );
  }
}

class TodoListElement extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isDeleted: this.props.item.isDeleted
    };
    this.onClickDelete = this.onClickDelete.bind(this);
    this.onClickUndoDelete = this.onClickUndoDelete.bind(this);
    this.onClickPermanentDelete = this.onClickPermanentDelete.bind(this);
    this.onClickComplete = this.onClickComplete.bind(this);
  }

  onClickDelete() {
    let index = parseInt(this.props.item.index);
    this.props.removeItem(index);
  }

  onClickUndoDelete() {
    let item = this.props.item;
    this.props.undoRemoveItem(item);
  }

  onClickPermanentDelete() {
    this.setState({
      isDeleted: true
    });
    //this.props.definitiveRemoveItem(index);
  }

  onClickComplete() {
    let index = parseInt(this.props.item.index);
    this.props.completeItem(index);
  }

  render() {
    let isCompletedClass = this.props.item.isCompleted
      ? "list-group-item-success"
      : "";

    const btnActionComplete = this.props.item.isCompleted ? (
      ""
    ) : (
      <button
        type="button"
        className="btn btn-success btn-sm"
        onClick={this.onClickComplete}
      >
        Complete
      </button>
    );

    const btnActionDelete = (
      <button
        type="button"
        className="btn btn-danger btn-sm"
        onClick={this.onClickDelete}
      >
        Delete
      </button>
    );

    isCompletedClass = this.state.isDeleted ? "hidden" : isCompletedClass;

    return (
      <li className={"list-group-item " + isCompletedClass}>
        <div className="clarfix">
          {this.props.item.value}
          <span className="float-right">
            {btnActionComplete}
            {btnActionDelete}
          </span>
        </div>
        <TodoListElementDelete
          index={this.props.item.index}
          timer={this.props.timer}
          enable={this.props.item.isBeingDeleted}
          onClickUndoDelete={this.onClickUndoDelete}
          onEndTimerAction={this.onClickPermanentDelete}
        />
      </li>
    );
  }
}

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

  onSubmit(event) {
    event.preventDefault();
    var newItemValue = this.refs.itemName.value;

    if (newItemValue) {
      this.props.addItem({ newItemValue });
      this.refs.form.reset();
    }
  }

  render() {
    return (
      <form ref="form" onSubmit={this.onSubmit} className="form-inline">
        <div className="input-group mb-3">
          <input
            type="text"
            className="form-control"
            ref="itemName"
            placeholder="Write todo item"
          />
          <div className="input-group-append">
            <button className="btn btn-success" type="submit">
              Add
            </button>
          </div>
        </div>
      </form>
    );
  }
}

export default class TodoList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      _lastIndex: 0,
      todoItems: [],
      undoRemoveItems: [],
      timer: 10
    };

    this.addItem = this.addItem.bind(this);
    this.removeItem = this.removeItem.bind(this);
    this.undoRemoveItem = this.undoRemoveItem.bind(this);
    this.definitiveRemoveItem = this.definitiveRemoveItem.bind(this);
    this.completeItem = this.completeItem.bind(this);
  }

  getNewIndex() {
    return this.state._lastIndex + 1;
  }

  addItem(todoItem) {
    const newTodoItem = {
      index: this.getNewIndex(),
      value: todoItem.newItemValue,
      isBeingDeleted: false,
      isDeleted: false,
      isCompleted: false
    };

    this.setState({
      todoItems: [...this.state.todoItems, newTodoItem],
      _lastIndex: newTodoItem.index
    });
  }

  removeItem(itemIndex) {
    let itemToBeDeleted = this.state.todoItems.find(x => x.index === itemIndex);
    if (itemToBeDeleted) {
      itemToBeDeleted.isBeingDeleted = true;
    }
    this.setState({ todoItems: this.state.todoItems });
  }

  definitiveRemoveItem(itemIndex) {
    console.log("definitiveRemoveItem", itemIndex);

    let todoItems = this.state.todoItems;
    let undoTodoItem = this.state.undoRemoveItems;
    let itemToBeDeleted = todoItems.find(
      x => x.index === itemIndex &amp;&amp; x.isBeingDeleted
    );
    let itemInUndo = undoTodoItem.find(x => x.index === itemIndex);
    if (itemToBeDeleted &amp;&amp; itemInUndo == null) {
      todoItems = todoItems.filter(x => x.index !== itemIndex);
    } else {
      undoTodoItem = undoTodoItem.filter(x => x.index !== itemIndex);
    }
    this.setState({
      todoItems: todoItems,
      undoRemoveItems: undoTodoItem
    });
  }

  undoRemoveItem(item) {
    let todoItems = this.state.todoItems;
    let itemToBeDeleted = todoItems.find(x => x.index === item.index);
    itemToBeDeleted.isBeingDeleted = false;
    this.setState({
      todoItems: todoItems
    });
  }

  completeItem(itemIndex) {
    let todoItems = this.state.todoItems;
    let itemComplete = todoItems.find(x => x.index === itemIndex);
    itemComplete.isCompleted = true;
    this.setState({
      todoItems: todoItems
    });
  }

  render() {
    let items = this.state.todoItems.map((item, index) => {
      return (
        <TodoListElement
          key={index}
          item={item}
          timer={this.state.timer}
          completeItem={this.completeItem}
          removeItem={this.removeItem}
          undoRemoveItem={this.undoRemoveItem}
          definitiveRemoveItem={this.definitiveRemoveItem}
        />
      );
    });

    return (
      <div>
        <Header />
        <div className="container">
          <TodoListForm addItem={this.addItem} />
          <ul className="list-group"> {items} </ul>
        </div>
      </div>
    );
  }
}

Do you have some suggestion about React programming? Thank you!

Drawing App with Nodejs, Socket.io and Expressjs

This is my first nodejs app created with express.js 4 and socket.io 1.
Download it on GitHub

A demo is to: drawing.francescopantisano.it

The app permit to draw on a map in real time with other people in a specified “room”, so only who know the name of the room can access.

DrawingAppFirstScreen

You can choose to show/hide the write on the map of the other member, with a “layer system” applied on the canvas.
The canvas is managed with the library jcanvas is very useful.

The room are managed with socket.io, the client connected to are managed by a caching system (node-cache) and a linq library node-linq.

If someone enter on the room after that someone have drawn, the system recover all the written and update the last client connected.

All the drawing action where saved on a buffer to server.

DrawingAppSecondScreen

 

Basic version on github => Download it

Nodemcu Light Control using Nodejs SSDP

LightControl con Nodejs SSDP

questo pacchetto ha una parte di script Arduino da poter lanciare su tutte le vostre NodeMcu e una parte applicativa realizzata con nodejs che gestisce le periferiche ed interagisce con loro utilizzando il protocollo SSDP che trovo veramente interessante per l’aspetto iot, evita di utilizzare/conoscere gli ip delle schede, ogni device connessione in rete espone una propria scheda identificativa, tramite le quale potete riconoscerlo e quindi interagirci:

SSDP.setSchemaURL("description.xml"); 
SSDP.setHTTPPort(80); 
SSDP.setName("NodemcuLightOne"); 
SSDP.setSerialNumber("0001"); 
SSDP.setURL("index.html"); 
SSDP.setModelName("nodemcu"); 
SSDP.setModelNumber("0001"); 
SSDP.setDeviceType("upnp:nodemculight"); 
SSDP.begin();

Il client nodejs è in ascolto sulla porta 3000.
Il device nodemcu viene interrogato sulla porta 80.

##NodeMCU
per configurarlo bisogna prima scaricare i driver https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers e poi, per comodita’, abbiamo utilizzato l’ide di Arduino, debitamente onfigurato così come indicato nelle numerose guide on line. Per installare il mio script su nodemcu ho utilizzato Arduino IDE, se avete bisogno di maggiori informazioni contattatemi pure.

##Node.js
va installato su una macchina e messo in ascolto sulla porta 3000, così come indicato nel pacchetto. 

##INSTALLAZIONE per avviare il server bisogna procedere nel seguente modo:

  1. Scaricare e installare la versione idonea di node ed npm: https://nodejs.org/it/download/
  2. installare il framework express tramite il gestore dei pacchetti: npm intall express

è possibile anche configurare tutto tramite npm install, a patto che il file package.json sia aggiornato nelle dipendenze necessarie. a questo punto si potrà avviare il server:

node app.js

Da notare che su sistemi Debian Node viene avviato con nodejs app.js, in quanto node è un altro applicativo presente sui repository.

 

Come configurare NodeJs SSDP

SSDP la cui definizione è Simple Service Discovery Protocol, viene utilizzato per la ricerca dei device connessi nella rete locale, ho utilizzato la libreria node-ssdp-js semplice da installare e da utilizzare. Bisogna definire una firma nei nostri device da poter successivamente “cercare”.

#JAVASCRIPT NODEJS

var Client = require('node-ssdp-js').Client, client = new Client();

client.on('response', function (response) {
    console.log('Response ssdp device:', response);
    var ipNodeMcuLight = response.referrer.address;
    console.log('IP:', ipNodeMcuLight);
});

client.browse('upnp:nodemculight');

#ARDUINO SCRIPT

SSDP.setDeviceType("upnp:nodemculight");

Progetto “LightControl” di Francesco Pantisano realizzato utilizzando come progetto di base “Plant” di Diomede Mazzone con la collaborazione di Fabio Z Tessitore (@FabioZTessitore) che ringrazio per la pazienza avuta a rispondere alle mie domande.

Tag: NodeJS, ExpressJS, HTML 5, client/server, Simple Service Discovery Protocol (SSDP)

Licenza: GPL 3.0 o successive

Javascript Global Error Handler

Today i’have created a simple class to log in the backend the javascript error, so i can have a real time monitoring of how error appear to the users.

We can use a window.onerror and the addEventListener rewrite.

Window.onerror has been available in most browser, but the argument that are passed on each browser are different:

BrowserMessageURLlineNocolNoerrorObj
Firefox
Chrome
Edge
IE 11
IE 10
IE 9, 8
Safari 10 and up
Safari 9
Android Browser 4.4

This is my class with a _wrap function, and a SendError that trasmit the data on the backend

class ErrorHandler {

	constructor() {
		let $this = this;
		$this._prototypeInit();

		window.onerror = function (message, file, line, col, error) {
			let data = message+" from "+error.stack;
			$this.SendError(data);
		};
	}

	_prototypeInit() {
		let $this = this;
		var addEventListener = window.EventTarget.prototype.addEventListener;
		window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
			addEventListener.call(this, event, $this._wrap(callback), bubble);
		}
		var removeEventListener = window.EventTarget.prototype.removeEventListener;
		window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
			removeEventListener.call(this, event, callback._wrapped || callback, bubble);
		}
	}

	_wrap(func) {
		let $this = this;
		if (!func._wrapped) {
			func._wrapped = function () {
				try {
					func.apply(this, arguments);
				} catch (e) {
					let data = e.message+" from "+e.stack;
					$this.SendError(data);
					throw e;
				}
			}
		}
		return func._wrapped;
	}

	SendError(message) {
		let $this = this;
		fetch('/ErrorHandler/WriteLog', {
			method: 'POST',
			body: JSON.stringify({ message: message }),
			headers: {
				'Content-Type': 'application/json'
			}
		}).then(res => res.json()).catch(error => console.error('Error:', error));
	}
}

In the message we put the stacktrace.
To use it at the init of your application:
let handlerError = new HandlerError();

Write to me if you have some suggestion to improve it.

WordPress Plugin Creation Tutorial – Simplest way

Today I asked myself how to explain to a junior, how to create a wordpress plugin, the simplest way. Without the inclusion of complex structures with public folder, includes, ….., but something very very simple.

Below I will explain how to create a plugin to manage some date, in this example is a Sport Race:
– Create Sport Race
– Insert members of a Sport Race
– Show table with Sport Race, and manage data (bulk delete)
– Show table with Sport Race, and manage data (bulk delete)
– Upload media using WordPress System (media manager of wordpress)

You can download it on: GITHUB

The structure of the project in the Plugin name directory is:

As you can see, a simple list of file with no directory

My project as two section: Sport Race and Members
Each section is composed by two file: _page.php and _table.php
And a file of system: plugin_activation.php

For example now analyze two file: sportrace_page.php and sportrace_table.php

For the sportrace_table.php will explain in the next article how to create a table, now take a look at file, is very simple.
For now i will explain how to use it in the sportrace_page.php

At top of page we put

<?php 
global $wpdb;

// jQuery
wp_enqueue_script('jquery');
// This will enqueue the Media Uploader script
wp_enqueue_media();
?>

For the inclusion of table put:

<?php 
echo '<form method="post">';
require_once 'sportrace_table.php';
$class = new Sportrace_Table();
$class->prepare_items();
$class->display();
echo '</form>';
?>

In the plugin_activation.php you can find the mysql create query and the menu inclusion!

Let’s start to create your wordpress plugin! Simple and Fast!

Ebay OAuth 2 Generate Token and Refresh – PHP

Today i will show to you how to use a OAuth 2 on Ebay, so how you can take your token, and then use it.

At first you must to register on https://developer.ebay.com

Then you must to set your Application on (Sandbox/Test or Production, in this guide i show to you Production procedure) https://developer.ebay.com/my/keys

After you must to have a situation like this:

Now we have:
– Client ID
– Dev ID
– Client Secret

We need:
– Authorization Code
– Access Token
– Refresh Token

Authorization Code

At first we must to generate the Authorization Code, and for this procedure we must to paste an url on the browser and copy the query string “code”.
So click on the “User token link”

Click on “Get a Token from eBay via Your Application”

Then you must to “Add eBay Redirect URL”
So you generate your app details, you can see the
“Your branded eBay Production Sign In (OAuth)” or if sandbox (test)
“Your branded eBay SandboxSign In (OAuth)”

Copy the link, that is like:

https://auth.ebay.com/oauth2/authorize?client_id=App-PRD-hhhhhf72-3hhb&response_type=code&redirect_uri=YourName-App–okllp&scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly

Put this link on your browser, and login with your ebay account, so then you must to redirect on another page that sayd to you that the application has grant, and in the url bar you find your authorization code.

https://signin.ebay.com/ws/eBayISAPI.dll?ThirdPartyAuthSucessFailure&isAuthSuccessful=true&code=v%5K1.1HH%…..w&expires_in=299

Access Token and Refresh Token

Now with our authorization code, we call this url to take our access and refresh token.
For this call we need the authorization header, and create a base64 encode with clientID and certID.
And then in the parameter set Authorization code and RuName

$link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode(':');
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        curl_setopt($ch, CURLHEADER_SEPARATE, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=authorization_code&amp;code==&amp;redirect_uri=");
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
            $this->refreshToken = $json["refresh_token"];
        }

Why we have access token and refresh token?

We use Access Token for all the api request on eBay service.
We use Refresh Token to regenerate a Access Token.

Access token is valid 2 hour, but Refresh Token is valid 18 months.

How can i refresh my access token?

You must to take a call to this service, passing your refresh code, and the service return to you your new access token

$link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode(':');
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        curl_setopt($ch, CURLHEADER_SEPARATE, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=refresh_token&amp;refresh_token&amp;scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly");
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
        }

I suggest to save your Access Token and Refresh Token on Database.

At the end my eBay API Simple Class

<?php

class EbayAPI
{
    protected $devID;
    protected $appID;
    protected $certID;
    protected $clientID;
    protected $serverUrl;
    public $userToken;
    protected $paypalEmailAddress;
    protected $ruName;


    public function __construct()
    {
        $this->devID = '<your-dev-id>'; // these prod keys are different from sandbox keys
        $this->appID = '<your-app-id>';
        $this->certID = '<your-cert-id>';
        $this->clientID = '<your-client-id>';
        //set the Server to use (Sandbox or Production)
        $this->serverUrl = 'https://api.ebay.com/ws/api.dll';      // server URL different for prod and sandbox
        //the token representing the eBay user to assign the call with

        $this->authCode = '<paste here your authorization code>'; 
        $this->authToken ="";
        $this->refreshToken ="";
        $this->ruName= "";

        $this->paypalEmailAddress= 'PAYPAL_EMAIL_ADDRESS';
        
    }

    public function firstAuthAppToken() {
        $url = "https://auth.ebay.com/oauth2/authorize?client_id=".$this->clientID."&amp;response_type=code&amp;redirect_uri=".$this->ruName."&amp;scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly"; 
return $url;      
    }

    public function authorizationToken()
    {
        $link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode($this->clientID.':'.$this->certID);
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        curl_setopt($ch, CURLHEADER_SEPARATE, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=authorization_code&amp;code=".$this->authCode."&amp;redirect_uri=".$this->ruName);
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
            $this->refreshToken = $json["refresh_token"]; 
        } 
    }

    public function refreshToken()
    {
        $link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode($this->clientID.':'.$this->certID);
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        echo $this->refreshToken;
        curl_setopt($ch, CURLHEADER_SEPARATE, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=refresh_token&amp;refresh_token=".$this->refreshToken."&amp;scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly");
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
        } 
    }
}

Yii 2 Framework Configure on Plesk 17 – Nginx

Hi,
today i want to explain how to configure a app with framework Yii 2 on your hosting Plesk.
In my case i have Plesk 17.8, the problem is how to configure the subdirectory and so how to convert the htaccess of Yii 2 app.

On Plesk 17 you must to configure the site, on run PHP-FPM un on nginx.
So go in the Hosting Setting of the domain:

Hosting Setting

So go in the Hosting Setting of the domain:

Apache & nginx Settings

You must to disable Proxy mode

Than we must to configure the Additional nginx directives
So go in the Apache & nginx Settings of the domain
Than into Additional nginx directives copy this code (change YOURDOMAIN with the domain that you want to configure):

set $base_root /var/www/vhosts/YOURDOMAIN/httpdocs;

charset UTF-8;
index index.php index.html;

location / {
	root $base_root/frontend/web;
	try_files $uri $uri/ /frontend/web/index.php$is_args$args;

	location ~ ^/assets/.+\.php(/|$) {
		deny all;
	}
}

location /admin {
	alias $base_root/backend/web/;

	# prevent the directory redirect to the URL with a trailing slash
	location = /admin {
		# if your location is "/backend", try use "/backend/backend/web/index.php$is_args$args"
		# bug ticket: https://trac.nginx.org/nginx/ticket/97
		try_files $uri /backend/web/index.php$is_args$args;
	}

	try_files $uri $uri/ /backend/web/index.php$is_args$args;

	location ~ ^/admin/assets/.+\.php(/|$) {
		deny all;
	}
}

location ~ ^/.+\.php(/|$) {
	rewrite (?!^/((frontend|backend)/web|admin))^ /frontend/web$uri break;
	rewrite (?!^/backend/web)^/admin(/.+)$ /backend/web$1 break;

	fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
	fastcgi_param PATH_INFO $fastcgi_path_info;
	fastcgi_pass "unix:///var/www/vhosts/system/YOURDOMAIN/php-fpm.sock";
	include /etc/nginx/fastcgi.conf;
}

location ~ /\. {
	deny all;
}

If you want you can enable nginx caching

Press “OK” and enjoy

Angular 6 – ADAL Dynamic Parameter initialization

We have seen in the previous article, how to implement the ADAL Authentication in Angular 6.

Now we can see, how to do, for init the ADAL Module with dynamic parameter, for example we can take them from database, or json file configuration.

We must to open the app.module.ts
Search the “imports” line, where we have write:

@NgModule({
declarations: [
  AppComponent
],
imports: [
  MsAdalAngular6Module.forRoot({
  instance: 'https://adal.resource.com/',
  tenant: '',
  clientId: '',
  redirectUri: window.location.origin,
  navigateToLoginRequestUrl: false,
  cacheLocation: 'localStorage'
}),
RouterModule.forRoot(
 appRoutes,
 { enableTracing: true }
),
 BrowserModule,
],
providers: [
 AuthenticationGuard
]
});

As we can see, the parameter are static, now we want to take them from a web service.

We must to change the “forRoot” function, and pass a function that return the object with parameter configuration

@NgModule({
declarations: [
AppComponent
],
imports: [
    MsAdalAngular6Module.forRoot(function () {
      var request = new XMLHttpRequest();
      request.open('GET', '/api/getParameterADAL', false);
      request.send(null);

      if (request.status === 200) {
        console.log(request.responseText);
        var parameter = JSON.parse(request.responseText);
        return {
          instance: parameter.adfs_instance,
          tenant: parameter.adfs_tenant,
          clientId: parameter.adfs_client_id,
          redirectUri: parameter.adfs_redirect_uri,
          navigateToLoginRequestUrl: false,
          cacheLocation: 'localStorage',
        }
      }
    }()),
RouterModule.forRoot(
appRoutes,
{ enableTracing: true }
),
BrowserModule,
],
providers: [
AuthenticationGuard
]
});

If you have compile error build for example:
Function expressions are not supported in decorators in ‘ɵ0’

Build with:

ng build --optimization=true --outputHashing=a

Enjoy!

Angular 6 – ADAL Authentication

Today i want to talk to you about Microsoft ADAL (Azure Active Directory Authentication Library).
ADAL allows users to authenticate in Active Directory (AD) local or in the cloud and take token to protect the API.

How can i do to integrate it in a Angular 6 app?

1) Install the js library microsoft-adal-angular6

npm i microsoft-adal-angular6

2) Open app.component.ts
2.1) Import the microsoft adal

import { MsAdalAngular6Service } from 'microsoft-adal-angular6';

2.2) In the export class AppComponent change the constructor

export class AppComponent {
title = 'APP Title';
constructor(private adalSvc: MsAdalAngular6Service) {
console.log(this.adalSvc.userInfo);
var token = this.adalSvc.acquireToken('http://adal.resource.com').subscribe((token: string) => {
console.log(token);
});
}
}

3) Open app.module.ts
3.1) Import the microsoft adal

import { MsAdalAngular6Module, AuthenticationGuard } from 'microsoft-adal-angular6';

3.2) We must to change our routes

const appRoutes: Routes = [
{ path: '', component: AppComponent, pathMatch: 'full', canActivate: [AuthenticationGuard] }
];

3.3) In NgModule import library

@NgModule({
declarations: [
AppComponent
],
imports: [
MsAdalAngular6Module.forRoot({
instance: 'https://adal.resource.com/',
tenant: '',
clientId: '',
redirectUri: window.location.origin,
navigateToLoginRequestUrl: false,
cacheLocation: 'localStorage'
}),
RouterModule.forRoot(
appRoutes,
{ enableTracing: true }
),
BrowserModule,
],
providers: [
AuthenticationGuard
]
});

If you want an example Angular 6 ADAL App click here.

Angular 6 Material – MatDatePicker italian format dd/MM/yyyy

Material Angular is very very useful library to generate beautiful app with material design and use all the power of angular.
Today we can see how to set the format for the MatDatePicker with dd/MM/yyyy so how to customize it, then you can change it.

In our Angular 6 project we must to install moment.
So execute in our project directory:

npm i @angular/material-moment-adapter 
npm add moment

Then we must to open our
app.module.ts

//Some import before, add this 
import {
    DateAdapter,
    MAT_DATE_FORMATS,
    MAT_DATE_LOCALE
} from '@angular/material';
import {
    MomentDateModule,
    MomentDateAdapter
} from '@angular/material-moment-adapter';
//create our cost var with the information about the format that we want 
export const MY_FORMATS = {
    parse: {
        dateInput: 'DD/MM/YYYY',
    },
    display: {
        dateInput: 'DD/MM/YYYY',
        monthYearLabel: 'MM YYYY',
        dateA11yLabel: 'DD/MM/YYYY',
        monthYearA11yLabel: 'MM YYYY',
    },
};
//in our ngmodule providers add the provide for the date 
@NgModule({
    imports: [............],
    providers: [{
            provide: MAT_DATE_LOCALE,
            useValue: 'it'
        },
        //you can change
        useValue {
            provide: DateAdapter,
            useClass: MomentDateAdapter,
            deps: [MAT_DATE_LOCALE]
        }, {
            provide: MAT_DATE_FORMATS,
            useValue: MY_FORMATS
        }
    ],
    bootstrap: [AppComponent]
});
export class AppModule {}

At the end all the date in our project became with the format dd/mm/yyyy!!
Some question contact me.