sábado, 12 de diciembre de 2020

Angular - Formulario

  // 12-12-2020

//* Functions Experiencia laboral
  //* experiencias_trabajador: fb.array([]),

get experiencias_trabajador() {
return this.formulario.get("experiencias_trabajador") as FormArray;
}
addExp( val ){
this.experiencias_trabajador.push(this.fb.group( val ));
}

removeExp( pos:number ) {
this.experiencias_trabajador.removeAt(pos);
};

editExp( objExp:{ newExp: ExperienciaTrab, index:number } ){
this.experiencias_trabajador.removeAt( objExp.index );
this.experiencias_trabajador.insert( objExp.index, this.fb.group( objExp.newExp ) );
}


jueves, 3 de diciembre de 2020

New Project Angular

> ng new nameApp
> npm install @angular/service-worker
> cambiar la version de service worker
    "@angular/service-worker": "~8.1.2",
    "dexie-cloud-addon": "^1.0.0-alpha.7",
    "moment": "^2.18.1",
    "ng2-filter-pipe": "^0.1.10",
    "sweetalert2": "^8.16.2",

> npm install
> ng add @angular/pwa --project nameApp /* (ir a ->angular.js ->defaultProject:'nameApp')*

>Agregar bootstrap al index.html
    <!--En Head-->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">        <!--Al final del Body-->
      <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" ></script>
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"></script>

Configurar las rutas MAIN

> const routes: Routes = [
  { path: '', redirectTo: 'puntosgeo', pathMatch: 'full' },
  { path: 'puntosgeo',  loadChildren: () => import('./puntosgeo/puntosgeo.module').then( m => m.PuntosgeoModule) },  
];

Crear Modulo y Componente
> ng g m nameModule
> ng g c nameModule
> ng g c nameModule/namePage
> ng g c nameModule/namePage

Config route SubModule

// Rutas
const routes: Routes = [
{ path: '', component: A2odevComponent, },
{ path: 'register', component: Problem1Component, },
{ path: 'update', component: Problem2Component, },
];









miércoles, 2 de diciembre de 2020

Laravel - Guide

 Crear Proyecto Nuevo

# Encender Vagrant

> cd /Homestead

      vagrant up

      vagrant ssh


# Crear proyecto

> cd code/

> composer create-project --prefer-dist laravel/laravel a2odev "6.*"

> salir de vagrant ssh


# Habilitar dominio

> sudo nano /Homestead/Homestead.yaml

--add

      map: a2odev.test

      to: /home/vagrant/code/a2odev/public


# Agregar al Host local

> sudo nano /etc/hosts

add: 192.168.10.10  a2odev.test 


# Reiniciar Vagrant

> vagrant reload --provision      



-- vagrant up

-- vagrant reload --provision

-- vagrant suspend

-- vagrant ssh

-- vagrant halt

-- vagrant destroy


<!-- composer create-project laravel/laravel NameProyect 5.3.x (crea con version laravel) -->



















lunes, 30 de noviembre de 2020

Cómo procesar páginas web PHP con Nginx

Por defecto Nginx no es capaz de procesar páginas web dinámicas con PHP, por lo que requiere el uso de complementos adicionales específicos para dicho fin. Uno de estos complementos es FPM (FastCGI Process Manager), una implementación alternativa a FastCGI con varias características adicionales útiles para sitios web con mucho tráfico.

 ========= seccion 9 (instalacion y configuracion de PHP en el VPS)

> sudo apt install php-fpm

> sudo nano /etc/php/7.2/fpm/php.ini

> Ctrl + w  buscar : cgi.fix_pathinfo=1 (cambiar a 0)

> cgi.fix_pathinfo=0 

> sudo systemctl reload php7.2-fpm.service


** Habilitar php para todos los sitios web

> sudo nano /etc/nginx/sites-available/*

> add: index index.php index.html

       location ~ \.php$ {

                include snippets/fastcgi-php.conf;


                # With php-fpm (or other unix sockets):

                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;

        }


** Probar archivos php

> cd /var/www/

> sudo nano <dir_domain>/index.php

<?php 

echo "Hola con PHP desde {$_SERVER['HTTP_HOST']}";

?>


> sudo nginx -t

> sudo systemctl reload nginx.service


-----

> config gral

> /etc/php/7.2/fpm$ sudo nano php.ini

ver los errores

>/var/log$ sudo nano php7.2-fpm.log

----


ACME.SH

Renovar certificado:

sudo acme.sh list ó acme.sh --list
sudo acme.sh --renew -d example.com --force









zsfsf

sábado, 14 de noviembre de 2020

Convert PWA - Project angular/ionic

     "@ionic/storage": "2.2.0",

    "@angular/animations": "~7.2.8",

    "angular2-moment": "^1.9.0",

    "angular2-json2csv": "^1.1.2",

    "base64-img": "^1.0.4",

    "chart.js": "^2.7.3",

    "dom-to-image": "^2.5.2", 

    "jquery": "^3.2.1",

    "jquery-mask-plugin": "^1.14.15",

    "jspdf": "^1.4.1",

    "lodash": "^4.17.10",

    "moment": "^2.18.1",

    "ng-socket-io": "^0.2.4",

    "ng2-filter-pipe": "^0.1.10",

    "ng2-order-pipe": "^0.1.5",

    "ngx-device-detector": "^1.3.5",

    "ngx-infinite-scroll": "^6.0.1",

    "ngx-mask": "^7.3.5",

    "ngx-paginate": "^1.0.5",

    "ngx-pagination": "^3.0.1",

    "ngx-papaparse": "^4.0.4",

    "ngx-socket-io": "^3.0.1",

    "ngx-spinner": "^6.1.2",

    "pickerjs": "^1.2.0",

    "html2canvas": "^0.5.0-beta4",

    "rxjs-compat": "^6.2.2",

    "socket.io": "^2.1.1",

    "socket.io-client": "^2.1.1",

    "sweetalert": "^2.1.2",

    "sweetalert2": "^8.16.2",

    "uuid": "^3.3.2",


    "@ng-select/ng-select": "^2.11.2",

    "angular-in-memory-web-api": "^0.3.2",

    "pdfmake": "^0.1.63",

    "@angular/http": "~7.2.8",

    "http-server": "^0.11.1"               



//install  para el map

> npm install @ionic-native/geolocation

> npm install @ionic-native/camera


// ionic cordova plugin add cordova-plugin-geolocation

// npm install @ionic-native/geolocation

// ionic cordova plugin add cordova-plugin-camera

// npm install @ionic-native/camera

//ionicframework.com/docs/native/geolocation

//ionicframework.com/docs/native/camera

=====


//config socket


src>polyfills.ts

import 'zone.js/dist/zone';  // Included with Angular CLI.

(window as any).global = window;


//prepare push

npm install @angular/service-worker


//cambiar el nombre de angular.js

{

  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",

  "version": 1,

  "defaultProject": "app",

  "newProjectRoot": "projects",

  "projects": {

    "app": {

 


ng add @angular/pwa --project app /* (el nombre que configuro en angular.js)*/


=======/

luego para cambiar el nombre pwa es en

ngsw-config.json

>  "$schema": "./node_modules/@angular/service-worker/config/schema.json",

  "index": "/index.html",

  "assetGroups": [

    {

      "name": "app",<--cambiar este nombre que sale en pwa al instalar


>tambien en manifest.webmanifest


martes, 6 de octubre de 2020

MySQL o MariaDB en el VPS

 seccion 8 (instalacion o configuracion de MySQL o MariaDB en el VPS)

instalr mariadb

>sudo apt install mariadb-serve

>mysql --version


iteractuar por cmd

>sudo mysql -u root -p

crear base de datos

create database snewapp_com;

create database api_snewapp_com;

...

show databases;

exit


asegurar instalación 9:30

sudo mysql_secure_installation

>Enter current password for root (enter for none): 

>Set root password? [Y/n] : Y

>New password: 12345678

>Remove anonymous users? [Y/n] : Y

>Disallow root login remotely? [Y/n] : Y

>Remove test database and access to it? [Y/n] : Y

>Reload privilege tables now? [Y/n]  : Y


* crear usuarios para las bases de datos

>sudo mysql -u root -p

>create user snewapp_com@localhost identified by 'AquiContraseña';

>create user api_snewapp_com@localhost identified by 'AquiContraseña';


>select user from mysql.user;

asignar usuario a una base de datos

>grant all privileges on snewapp_com.* to snewapp_com@localhost;

>grant all privileges on api_snewapp_com.* to api_snewapp_com@localhost;

>flush privileges;


example ========================================================

use u759233740_crio;

show tables;


** Crear usuarios para las bases de datos

> sudo mysql -u root -p

> select user from mysql.user;

> create user eco@localhost identified by 'AquiContraseña';


** Asignar usuario a una base de datos

> select user from mysql.user;

> GRANT ALL PRIVILEGES ON <database_name>.* TO <username>@localhost;

GRANT ALL PRIVILEGES ON ecommerce2.* TO eco@localhost;

> flush privileges;


===============================================


BACKUP

> sudo mysql -u <user> -p<pass> <name_bd> < <name_archivo.sql>

> sudo mysql -u eco -p1234 ecommerce2 < ecommerce.sql




lunes, 17 de agosto de 2020

 1. instalar : ngx-socket-io

https://www.npmjs.com/package/ngx-socket-io

2 .- Import and configure SocketIoModule

import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
const config: SocketIoConfig = { url: appConfig.api , options: {} };
    SocketIoModule.forRoot(config), 

crear servicio de websocket:
import { Injectable } from '@angular/core';
import { Socket } from 'ngx-socket-io';
import Swal from 'sweetalert2';


@Injectable({ providedIn: 'root' })
export class WebsocketService {

  public socketStatus = false;

  constructor(
    private socket: Socket
  ) {

    this.checkStatus();

    // Metodo para recibir
    this.listen('suggested-aviso').subscribe( ( payload ) => {              
      console.log('Aviso Sugerido', payload);
    });    

  }

  // 17-08-2020 ( Funcion para syncronizar socket )
    checkStatus() {
        this.socket.on('connect', () => { console.log('conexion socket');  this.socketStatus = true; })
        this.socket.on('disconnect', () => { console.log('desconexion socket'); this.socketStatus = false; });
    };

  // 17-08-2020 ( Funcion para EMITIR un evento )
    emit( evento: string, payload?: any, callback?: Function ) {      
      this.socket.emit( evento, payload, callback );
    }

  // 17-08-2020 ( Funcion para RECIBIR un evento )
    listen( evento: string ) {
      return this.socket.fromEvent( evento );
    }



}

=== Emitir eventos desde el servidor 
SERVER.io.emit('create-product', data);


==== ahora el uso en componentes
import { WebsocketService } from 'src/app/api/websocket.service';

  constructor(
public menuCtrl: MenuController,
    private route : Router,
    public _posts: ProductService,
    public socketIO : WebsocketService,
    
  ) {
      //** Socket **//
        this.socketIO.listen('create-product').subscribe( (payload ) => { console.log('create-product'); this.loadData(); });
        this.socketIO.listen('update-product').subscribe( (payload ) => { console.log('update-product'); this.loadData(); });
        this.socketIO.listen('delete-product').subscribe( (payload ) => { console.log('delete-product'); this.loadData(); });
      //** Socket **//

jueves, 9 de julio de 2020

Backup MongoDB

======================================
# Habilitar images
  sudo cp -r <ruta_del_backend/avatars> <ruta_path_del_servidor/nombre_del_directorio>
======================================
# vps
sudo cp -r /home/dev/Desktop/code/nutribo_backend/avatars /root/img_nutribo_db3

# local
sudo cp -r /home/dev/Desktop/code/nutribo_backend/avatars /home/dev/img_dev_nutribo_db3

======================================



=====================================
# Backup a base de datos
  mongorestore --drop -d <nombre-base-datos> <dirección-donde-está-el-respaldo>
===================================

# Crear backup del Servidor VPS
mongodump --db nutribo_db3 --out /var/www/root/api/nutribo_backend/db

# Restaurar backup al Servidor Local
mongorestore --drop -d dev_nutribo_db3 /home/dev/Desktop/code/nutribo_backend/db/nutribo_db3

===
# Crear backup del Servidor LOCAL
mongodump --db dev_nutribo_db3 --out /home/dev/Desktop/code/nutribo_backend/db

# Restaurar backup al Local
mongorestore --drop -d nutribo_db3 /var/www/root/api/nutribo_backend/db/dev_nutribo_db3



# https://sebmaldo.com/2015/07/24/restaurar-una-base-mongodb/
# https://parzibyte.me/blog/2018/03/07/respaldar-base-datos-mongodb/

En caso de que no este por comando mongo si no por ejecutable hacer esto:
Para restaurar bd
> </c/'programs files'/mongo/serv/bin/mongorestore> --drop -d dev_nutribo_db3 /home/dev/Desktop/code/nutribo_backend/db/nutribo_db3



Domain + SSL - Ya con servidor

============ HABILITAR DOMINIO BASICO (SIN SSL)
--- Config del servidor web

> cd /etc/nginx/sites-available/
> sudo cp default ecommerce.snew-app.com
> sudo nano ecommerce.snew-app.com
        < cambiar el root: del directorio del proyecto 
            añadir el server_name:  dominio.com  >

> Ctrl+O + Enter + Ctrl+X ---gurardar
> cd /var/www/
NOTA: SE DEBE CREAR LA CARPETA DE LA WEB CON EL MISMO NOMBRE DEL DOMINIO PARA NO TENER PROBLEMAS EN RENOVAR CERTIFICADO
> sudo mkdir ecommerce.snew-app.com
> sudo nano ecommerce.snew-app.com/index.html
                < Hello world !!! >
> Ctrl+O + Enter + Ctrl+X ---gurardar

> sudo nginx -t
> sudo ln -s /etc/nginx/sites-available/ecommerce.snew-app.com /etc/nginx/sites-enabled/
> sudo nginx -t
> sudo  systemctl reload nginx.service 

============== Agregar dominios y subdominios al VPS
seccion(s1-s3) min:35
6. agregar dominios al VPS
a. ir a networking >> add domain
b. Create new record de tipo A
HOSTNAME = @
WILL DIRECT TO = seleccionar tu droplet
TTL (SECONDS) = 3600
y create record

6.1 crear subdominios al vps
(api,blog,assets)
a. Create new record de tipo CNAME
HOSTNAME = api (nombre subdominio)
IS AN ALIAS OF = @
TTL (SECONDS) = 3600
y create record

6.2 configurar los DNS de los dominios
en namecheap ir a Custom DNS
ns1.digitalocean.com
ns2.digitalocean.com
        ns3.digitalocean.com
        ns4.digitalocean.com


========================== Let'sEncrypt SSL
"SOLO REEMPLAZAR EL DOMINIO, en este caso: ecommerce.snew-app.com"
el path:/var/www/ecommerce.snew-app.com/www/ <- debe ser donde esta el index.html (caso ionic)

sudo acme.sh --issue -d ecommerce.snew-app.com -w /var/www/ecommerce.snew-app.com/ --force

sudo mkdir /etc/nginx/certs/ecommerce.snew-app.com

sudo acme.sh --install-cert -d ecommerce.snew-app.com --key-file /etc/nginx/certs/ecommerce.snew-app.com/key.pem --fullchain-file /etc/nginx/certs/ecommerce.snew-app.com/fullchain.pem --ca-file /etc/nginx/certs/ecommerce.snew-app.com/ca.pem --reloadcmd "systemctl force-reload nginx.service" --force



======================== CONFIGURACION SITES-AVAILABLED DE NGINX
"SOLO REEMPLAZAR EL DOMINIO, en este caso: ecommerce.snew-app.com"
contrl + k : para borrar una linea en la terminal

server {
        listen 80;
        listen [::]:80;

        server_name ecommerce.snew-app.com;
        return 301 https://ecommerce.snew-app.com$request_uri;
       # return 404;
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        ssl_certificate /etc/nginx/certs/ecommerce.snew-app.com/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/ecommerce.snew-app.com/key.pem;
        ssl_session_timeout 1d;
        ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
        ssl_session_tickets off;

        # modern configuration
        ssl_protocols TLSv1.3;
        ssl_prefer_server_ciphers off;

        ##
        # Security setting
        ##

        # Avoiding iFrames from other origins
        add_header X-Frame-Options SAMEORIGIN;

        # Avoiding MIME type sniffing
        add_header X-Content-Type-Options nosniff;

        # Avoiding XSS attacks
        add_header X-XSS-Protection "1;mode=block";

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)
        add_header Strict-Transport-Security "max-age=63072000" always;

        # OCSP stapling
        ssl_stapling on;
        ssl_stapling_verify on;

        # verify chain of trust of OCSP response using Root CA and Intermediate certs
        ssl_trusted_certificate /etc/nginx/certs/ecommerce.snew-app.com/ca.pem;
        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/ecommerce.snew-app.com;

        # Add index.php to the list if you are using PHP
        index index.php index.html;

        server_name ecommerce.snew-app.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ /index.html;
                # try_files $uri $uri/ /index.php?$query_string; (para php)
        }

        # pass PHP scripts to FastCGI server
        #
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        location ~ /\.ht {
                deny all;
        }

        # deny access to .git files
        #
        location ~ /\.git {
                deny all;
        }
}



========== OK - REINICIAR SERVIDOR WEB

> sudo nginx -t
> sudo  systemctl reload nginx.service 

NOTA: SE DEBE CREAR LA CARPETA DE LA WEB CON EL MISMO NOMBRE DEL DOMINIO PARA NO TENER PROBLEMAS EN RENOVAR CERTIFICADO
sudo ln -s ~/code/fullpizzas_com/* /var/www/fullpizzas.sandwichescriollos.com






CMD - LINUX

-------- Agregar o eliminar un usario
> sudo adduser prueba
> sudo deluser prueba --remove-home --remove-all-file

-- Agregar usuario al grupo de administradores
> adduser snewapp sudo

--- Dar permiso a una carpeta
> sudo chown -R prueba:<grupoOpcional> blog.snew-app.com/

--- Eliminar todos los archivos de una carpeta
> sudo rm *



> sudo rm -r vendor/  -- Eliminar carpeta
> sudo mkdir nmCarpeta --crear carpeta

miércoles, 8 de julio de 2020

CMD FIREWAL - UFW

INSTALACIÓN:
--- Firewall para desactivar los puertos
> permitir conexiones ssh
> ssh snewapp_snew_vps
> sudo ufw status
> sudo ufw app list
> sudo ufw allow "OpenSSH"

> sudo ufw enable
> sudo ufw status verbose
> sudo ufw --help



habilitar puertos: 
> sudo ufw allow 27017/tcp (mongodb)
> sudo ufw allow 3306/tcp (mysql)
> sudo ufw allow 9000:9999/tcp (rango)
> sudo ufw status verbose


viernes, 3 de julio de 2020

CSS - Centrar contenido





#container {
text-align: center;

position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}

#container strong {
font-size: 34px;
line-height: 60px;
}

#container p {
font-size: 20px;
line-height: 35px;

color: #8c8c8c;

margin: 0;
}

#container a {
text-decoration: none;
}

--------------------------------------

<div id="container">
<strong>Project</strong>
<p>1. <a target="_blank" rel="noopener noreferrer"
href="https://nutribol.snew-app.com">Nutriboliva.com</a> Ionic 5 </p>
</div>

lunes, 15 de junio de 2020

Versionamiento semantico

X, Y Z -> v0.0.0

Major -> X = PRODUCCIÓN       (Terminado y en producción)
Minor -> Y = MEJORAS               (Nuevas funcionalidades o arreglos privados)
Path    -> Z = ARREGLOS    (Arreglos de bug solo errores)

Nombre de un proyecto en su version inicial  seria 
-> v0.1.0

Nombre de un proyecto en su version en producción
-> v1.0.0


COMO HACER CAMBIOS EN UN PROYECTO 
EJ.

    v0.1.0 -> inicio (Sprint 1, "objetivo estructura de proyecto")
    v0.2.0 -> Add login, home, etc. (Sprint 2, "Objetivo páginas del cliente")
    v0.2.1 -> Fix valid login
    v0.2.2 -> Fix preload login
    v0.3.0 -> Add Dashboard (Sprint 3, "Objetivo páginas del admin")
    v0.3.1 -> Fix search not reload
    v1.0.0 -> Deployment proyect functional
    ...
    ... 

Aún falta más...

sábado, 6 de junio de 2020

Manipulación de Fechas

con libreria momentjs


Convertir fecha de tipo utf que se guarda en base de dato como new Date() default

Para combertir en el frontend se debe hacer como 

        //* Totales por Dia
        this.follows = JSON.parse(JSON.stringify(this.follows)).map(item=>{                                                                     item.created_at = moment.parseZone(item.created_at).utc().format('DD-MM-YYYY');                               return item;
        });





viernes, 29 de mayo de 2020

Push Notification - ONESIGNAL

1. instalar:

ionic cordova plugin add onesignal-cordova-pluginnpm install @ionic-native/onesignal
2. Importar el servicio en los privders MODULO PRINCIPAL (app.module.ts)
import { OneSignal } from '@ionic-native/onesignal/ngx';
    
providers: [
StatusBar,
SplashScreen,
OneSignal,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],


3. KEY EN VARIABLES DE ENTORNO    ONESIGNAL APP IDEJM-f799-4ced-b221-84c8297adca3    FIREBASE_SENDER_ID: ej3523024246

4. Crear servicio PushService
import { OneSignal, OSNotification } from '@ionic-native/onesignal/ngx';
import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class PushService {

constructor(private oneSignal: OneSignal) { }

mensajes:any[] = [
{
title: 'Titulo de la push',
body: 'Este es el body de la push',
date: new Date()
}
];

configuracionInicial(){

this.oneSignal.startInit(ONESIGNAL_APP_ID, FIREBASE_SENDER_ID);

this.oneSignal.inFocusDisplaying(this.oneSignal.OSInFocusDisplayOption.Notification );

this.oneSignal.handleNotificationReceived().subscribe((noti) => {
// do something when notification is received
console.log('Notificación recibida', noti);
this.notificacionRecibida( noti );
});

this.oneSignal.handleNotificationOpened().subscribe((noti) => {
// do something when a notification is opened
console.log('Notificación abierta', noti)
});

this.oneSignal.endInit();

};

notificacionRecibida( noti: OSNotification ){

const payload = noti.payload;
const existePush = this.mensajes.find( mensaje=> mensaje.notificationID === payload.notificationID );

if( existePush ){
return;
}

this.mensajes.unshift( payload );

};

}


5. INYECTAR EN APP.COMPONENT.TS
private pushService: PushService

initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
this.pushService.configuracionInicial();
});
}




































Crear Servicio de 0 - Angular

1.- crear archivo .service

2. crear clase del servicio

import { Injectable } from '@angular/core';
import { HttpClient , HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { LoadingController } from '@ionic/angular';

import { appConfig } from 'src/app/global/app.config';
const URL = appConfig.api;

@Injectable({ providedIn:'root' })

export class PushPatient {
constructor(private http: HttpClient, public loadingController: LoadingController){ }

};


3. crear funciones para optimizar
    3.1 suscripcion
    3.2 cabezera
    3.3 menejador de errores
    3.4 preload (only ionic)

3.1 
private subscribe( request:any ){
return new Promise((resolve, reject )=>{
request.subscribe(res=>resolve(res), err=> reject(err));
});
};


3.2 (si solo valida token x storage , si va manejar otro tipo de cabezera modificar codigo)
private _httpOption( current_user:string ){
let token = "";
if( current_user ) token = localStorage.getItem( current_user );
return { headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': token })
};
};

3.3
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code, The response body may contain clues as to what went wrong,
console.error( `Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError( error.error.message );
};

3.4
async loading() {
const loading = await this.loadingController.create({
duration: 3000,
message: 'Please wait...',
});
return await loading.present();
}


===================== EJEMPLO COMPLETO =====================



import { Injectable } from '@angular/core';
import { HttpClient , HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { LoadingController } from '@ionic/angular';

import { appConfig } from 'src/app/global/app.config';
const URL = appConfig.api;

@Injectable({ providedIn:'root' })

export class PushPatient {
constructor(private http: HttpClient, public loadingController: LoadingController){ }

// Envia notificación push
async _sendPush(data: any) {
const api = "https://onesignal.com/api/v1/notifications";
const resp = await this._post(data, api, appConfig.REST_API_KEY );
return resp;
};

//========== CUSTOM FUNCTIONS ============//
async _post( data: any, _router:string, _options?:any ){
await this.loading();
let url = _router;
_options = this._httpOption( _options );
let req = await this.http.post( url, data, _options ).pipe( catchError(this.handleError) );
let resp = await this.subscribe( req );
return resp;
};

private subscribe( request:any ){
return new Promise((resolve, reject )=>{
request.subscribe(res=>resolve(res), err=> reject(err));
});
};

private _httpOption( key:string ){
return { headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': key })
};
};

private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code, The response body may contain clues as to what went wrong,
console.error( `Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError( error.error.message );
};

async loading() {
const loading = await this.loadingController.create({
duration: 3000,
message: 'Please wait...',
});
return await loading.present();
};

};