git remote update origin --prune
comparar 2 branchs git
To compare the current branch against
master
branch:$ git diff --name-status master
To compare any two branches:
$ git diff --name-status firstbranch..yourBranchName
elasticsearch eliminar todos los registros de un indice por query
POST http://10.10.16.90:9200/prod-man.access/v1/_delete_by_query
{ "query": { "match_all": {} } }
{ "query": { "match_all": {} } }
elasticsearch modificar un registro
por id
http://10.10.16.90:9200/prod-man.access/v1/Gxc_HW4BAXIIB-1uKgC0
{ "route": "product_delete_content_filter", "clients": [ "adm-cv", "adm-cm", "adm-netflex" ] }
hay que enviar todos los campos
http://10.10.16.90:9200/prod-man.access/v1/Gxc_HW4BAXIIB-1uKgC0
{ "route": "product_delete_content_filter", "clients": [ "adm-cv", "adm-cm", "adm-netflex" ] }
hay que enviar todos los campos
elasticsearch insertar varios registros a la vez
post http://10.10.16.90:9200/prod-man.access/_bulk
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_get", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_store", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_update", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_add_content_filter", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_delete_content_filter", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_delete", "clients":["adm-cv","adm-cm","adm-netflex"]}
al final dejar una linea en blanco
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_get", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_store", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_update", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_add_content_filter", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_delete_content_filter", "clients":["adm-cv","adm-cm","adm-netflex"]}
{ "index": { "_index": "prod-man.access", "_type": "v1" } }
{ "route":"product_delete", "clients":["adm-cv","adm-cm","adm-netflex"]}
al final dejar una linea en blanco
POST: ENDPOINT/shirts/_bulk
{ "index": { "_index": "shirts", "_type": "shirt" } }
{ "name": "tshirt", "size": "M", "color": "black", "fabric": "cotton", price": 1000 }
{ "index": { "_index": "shirts", "_type": "shirt" } }
{ "name": "tshirt", "size": "L", "color": "black", "fabric": "cotton", "price": 1000 }
...
Observations:
- Each row is a complete JSON entry; cannot be multi-line
- Each row (including the last one) needs to be terminated with a new line.
elasticsearch listar todos los registros
GET http://10.10.16.90:9200/prod-man.access/v1/_search
{ "query": { "match_all": {} } }
{ "query": { "match_all": {} } }
elasticsearch agregar registro
para agregar registro
{
"route":"product_get_all",
"clients":["adm-cv","adm-cm"," adm-netflex"]
}
"route":"product_get_all",
"clients":["adm-cv","adm-cm","
}
el _id, lo genera aleatoriamente.
si se quiere enviar tambien el ID, se lo debe agregar al final de la URL
elasticsearch obtener por id
GET url:9200/indice/tipo_doc/id
para borrar un registro:
DELETE url:9200/indice/tipo_doc/i
para borrar un registro:
DELETE url:9200/indice/tipo_doc/i
elasticsearch busqueda
por default devuelve solo 10 registros
GET http://10.10.16.90:9200/xxx.indice/_search
{ "from" : 0, "size" : 100, "query": { "bool": { "filter": [ } } }
--------------
{ "query": { "term": { "route": "regions_get_all" } } }
GET http://10.10.16.90:9200/xxx.indice/_search
{ "from" : 0, "size" : 100, "query": { "bool": { "filter": [ } } }
--------------
{ "query": { "term": { "route": "regions_get_all" } } }
web push notification
para el client que recibira las notificaciones
https://www.blog.plint-sites.nl/progressive-web-app-using-vue-cli-3/
hay que crear un archivo en la raiz del proyecto llamado .env
con las sgts variables:
VUE_APP_VAPID_PUBLIC_KEY=la que se haya generado en el backend
VUE_APP_API_PATH=http://127.0.0.1:8000/api
recordar que para que funcione se debe levantar la version en produccion, es decir
1) para generar la carpeta dist
npm run build
2) para levantar el servidor (previamente instalar globalmente el comando serve:
npm install -g serve )
aunque se puede abrir la pagina a traves de http://localhost:5000 cuando se envien las push notifications no las lee.
en el backend:
https://www.blog.plint-sites.nl/how-to-add-push-notifications-to-a-progressive-web-app/?fbclid=IwAR0Ts7ydULV0DairqZaSxoeBA5cl-husEXtx2HwTfnj3B-WRWPUxJywY5iw
instalar Cors
https://github.com/barryvdh/laravel-cors
y crear la tabla de notifications
php artisan make:migration create_notifications_table
y el controller
php artisan make:controller NotificationController
https://www.blog.plint-sites.nl/progressive-web-app-using-vue-cli-3/
hay que crear un archivo en la raiz del proyecto llamado .env
con las sgts variables:
VUE_APP_VAPID_PUBLIC_KEY=la que se haya generado en el backend
VUE_APP_API_PATH=http://127.0.0.1:8000/api
recordar que para que funcione se debe levantar la version en produccion, es decir
1) para generar la carpeta dist
npm run build
2) para levantar el servidor (previamente instalar globalmente el comando serve:
npm install -g serve )
serve -s dist3) en el navegador ingresar http://127.0.0.1:5000/
aunque se puede abrir la pagina a traves de http://localhost:5000 cuando se envien las push notifications no las lee.
en el backend:
https://www.blog.plint-sites.nl/how-to-add-push-notifications-to-a-progressive-web-app/?fbclid=IwAR0Ts7ydULV0DairqZaSxoeBA5cl-husEXtx2HwTfnj3B-WRWPUxJywY5iw
instalar Cors
https://github.com/barryvdh/laravel-cors
y crear la tabla de notifications
php artisan make:migration create_notifications_table
$table->uuid('id')->primary();
$table->string('type');
$table->morphs('notifiable');
$table->text('data');
$table->timestamp('read_at')->nullable();
$table->timestamps();
y el controller
php artisan make:controller NotificationController
permisos en linux para proyectos laravel
sudo chown -R www-data:www-data /var/www/html/MyProject/ sudo chmod -R 755 /var/www/html/MyProject/
laravel5.8 authentication jwt
fuente original:
https://blog.ezteven.com/tech/2019/05/30/utiliza-jwt-con-laravel-para-apis.html
creamos el proyecto:
composer create-project --prefer-dist laravel/laravel webpage "5.8.*"
en la carpeta del proyecto creado:
composer require tymon/jwt-auth:1.0.*
actualizar las librerias:
composer update
[para linux] cambiar el owner de la carpeta del proyecto:
desde la carpeta superior a la del proyecto...
sudo chown -R ibazan:ibazan webpage
generar la key para jwt:
php artisan jwt:secret
publicar el servicio:
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
el modelo de user:
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject {
use Notifiable;
protected $fillable = [
'name', 'surname', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function getJWTIdentifier() {
return $this->getKey();
}
public function getJWTCustomClaims() {
return [];
}
}
editamos config/auth.php
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
creamos el AuthController:
php artisan make:controller AuthController
editamos el AuthController.php:
use App\Http\Requests\RegisterAuthRequest;
use App\User;
use Illuminate\Http\Request;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class AuthController extends Controller {
public $loginAfterSignUp = true;
public function register(Request $request) {
$user = new User();
$user->name = $request->name;
$user->surname = $request->surname;
$user->email = $request->email;
$user->password = bcrypt($request->password);
$user->save();
if ($this->loginAfterSignUp) {
return $this->login($request);
}
return response()->json([
'status' => 'ok',
'data' => $user
], 200);
}
public function login(Request $request) {
$input = $request->only('email', 'password');
$jwt_token = null;
if (!$jwt_token = JWTAuth::attempt($input)) {
return response()->json([
'status' => 'invalid_credentials',
'message' => 'Correo o contraseña no válidos.',
], 401);
}
return response()->json([
'status' => 'ok',
'token' => $jwt_token,
]);
}
public function logout(Request $request) {
$this->validate($request, [
'token' => 'required'
]);
try {
JWTAuth::invalidate($request->token);
return response()->json([
'status' => 'ok',
'message' => 'Cierre de sesión exitoso.'
]);
} catch (JWTException $exception) {
return response()->json([
'status' => 'unknown_error',
'message' => 'Al usuario no se le pudo cerrar la sesión.'
], 500);
}
}
public function getAuthUser(Request $request) {
$this->validate($request, [
'token' => 'required'
]);
$user = JWTAuth::authenticate($request->token);
return response()->json(['user' => $user]);
}
}
creamos las rutas a las apis:
use Illuminate\Http\Request;
// estas rutas se pueden acceder sin proveer de un token válido.
Route::post('/login', 'AuthController@login');
Route::post('/register', 'AuthController@register');
// estas rutas requiren de un token válido para poder accederse.
Route::group(['middleware' => 'jwt.auth'], function () {
Route::post('/logout', 'AuthController@logout');
});
editar en Http/Kernel.php:
protected $routeMiddleware = [
...
'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
];
Adicionalmente podemos añadir al comienzo del public\index.php el siguiente código para evitar error de CORS durante nuestras pruebas:
// permite peticiones desde cualquier origen
header('Access-Control-Allow-Origin: *');
// permite peticiones con métodos GET, PUT, POST, DELETE y OPTIONS
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
// permite los headers Content-Type y Authorization
header('Access-Control-Allow-Headers: Content-Type, Authorization');
..y eso es todo!
ya podemos probar el registro:
post: http://127.0.0.1:8000/api/register
{
"name":"juan",
"surname":"perez",
"email":"jperez@mail.com",
"password":"123456",
}
lo que devolvera
{
"status":"ok",
"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjE6ODAwMFwvYXBpXC9yZWdpc3RlciIsImlhdCI6MTU2ODA1MDI2MywiZXhwIjoxNTY4MDUzODYzLCJuYmYiOjE1NjgwNTAyNjMsImp0aSI6ImtnOElmbmxJQ2w3TXJPUWoiLCJzdWIiOjIsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.6rMzjaqKneDgMtr0DVlCQGoFZVUhi7ZSOjH3EoF0HWU"
}
para desloguearnos debemos enviar el token, por ejemplo como parametro
post: http://127.0.0.1:8000/api/logout
{
"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjE6ODAwMFwvYXBpXC9yZWdpc3RlciIsImlhdCI6MTU2ODA1MDI2MywiZXhwIjoxNTY4MDUzODYzLCJuYmYiOjE1NjgwNTAyNjMsImp0aSI6ImtnOElmbmxJQ2w3TXJPUWoiLCJzdWIiOjIsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.6rMzjaqKneDgMtr0DVlCQGoFZVUhi7ZSOjH3EoF0HWU"
}
lo que devolvera
{
"status": "ok",
"message": "Cierre de sesión exitoso."
}
crear proyecto laravel para una version especifica
composer create-project laravel/laravel="5.5.*" myApp
actualiza npm en linux
1
2
3
|
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
|
cerrar la terminal y abrirla nuevamente
para comprobar la version instalada
npm -v
laravel 5.8 crud con vue spa
fuente original:
https://appdividend.com/2018/11/17/vue-laravel-crud-example-tutorial-from-scratch
parte 1
creamos la aplicacion
laravel new vue_laravel_crud
(ya te crea el .env con la key)
en linux dar permisos a la carpeta del proyecto
chmod -R 777 vue_laravel_crud
vamos a la carpeta creada vue_laravel_crud
e instalamos las dependencias del frontend.
npm install
(en linux usar sudo npm install)
se puede ahora ejecutar npm run dev para compilar los assets y guardarlos
o ejecutar npm run watch para que los compile mientras se cree codigo nuevo o se modifique el existente
Parte 2
instalar vue-router y vue-axios
router para manejar el direccionamiento
axios para manejar las peticiones al servidor
npm install vue-router vue-axios --save
y configuramos estas librerias en
rosurces/js/app.js
y ahora en resources/views/ creamos post.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">
<link href="{{ mix('css/app.css') }}" type="text/css" rel="stylesheet" />
<meta name="csrf-token" value="{{ csrf_token() }}" />
</head>
<body>
<div id="app">
</div>
<script src="{{ mix('js/app.js') }}" type="text/javascript"></script>
</body>
</html>
ahora editamos routes/web.php
<?php
Route::get('/{any}', function () {
return view('post');
})->where('any', '.*');
para poder capturar cualquier ruta que se escriba en el browser
en el sector de id="app" vamos a cargar el component App.vue que contendra nuestro
router-view
si existe el router lo renderizara sino no. y quedara vacio.
resources/js/App.vue
editaremos app.js para crear las routes de los componentes importados y asignarselo a nuestro
objeto Vue de la aplicacion
los componentes
hay que crearlos en resources/js/components/
por ejemplo el CreateComponent.vue seria
al App.vue
le vamos a agregar una cabecera para navegar
Parte 3: Crear el Backend
Vamos a crear el modelo Post, el controlador y una collection de Post como resorce.
php artisan make:model Post -mc
-mc : crea el archivo de migracion y el controlador de un saque
para crear la collection PostCollection
php artisan make:resource PostCollection
editar en el archivo de migracion:
en el modelo Post.php, indicar los campos que se pueden llenar masivamente:
implementamos los metodos del controlador PostController.php
Parte 4: Definir las routes en la api
en routes/api.php:
Parte 5: Implementar los componentes de Creacion, Listado y actualizacion
notar el uso de axios para los request a nuestra api
CreateComponent.vue
we have used the push() method to change the route programmatically.
IndexComponent.vue
en el listado se colocará acciones por cada item: link de editar y boton de eliminar
si se elimina un item el listado se modifica sin que se recargue la pagina
EditComponent.vue
por un tema de organizacion de codigo, las routes se pueden definir en un arhivo e importarlo luego
en app.js.
entonces creamos en resorces/js/routes.js
y en app.js
https://appdividend.com/2018/11/17/vue-laravel-crud-example-tutorial-from-scratch
parte 1
creamos la aplicacion
laravel new vue_laravel_crud
(ya te crea el .env con la key)
en linux dar permisos a la carpeta del proyecto
chmod -R 777 vue_laravel_crud
vamos a la carpeta creada vue_laravel_crud
e instalamos las dependencias del frontend.
npm install
(en linux usar sudo npm install)
se puede ahora ejecutar npm run dev para compilar los assets y guardarlos
o ejecutar npm run watch para que los compile mientras se cree codigo nuevo o se modifique el existente
Parte 2
instalar vue-router y vue-axios
router para manejar el direccionamiento
axios para manejar las peticiones al servidor
npm install vue-router vue-axios --save
y configuramos estas librerias en
rosurces/js/app.js
import VueRouter from 'vue-router'; Vue.use(VueRouter); import VueAxios from 'vue-axios'; import axios from 'axios'; Vue.use(VueAxios, axios); const router = new VueRouter({ mode: 'history'}); const app = new Vue(Vue.util.extend({ router })).$mount('#app');
y ahora en resources/views/ creamos post.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">
<link href="{{ mix('css/app.css') }}" type="text/css" rel="stylesheet" />
<meta name="csrf-token" value="{{ csrf_token() }}" />
</head>
<body>
<div id="app">
</div>
<script src="{{ mix('js/app.js') }}" type="text/javascript"></script>
</body>
</html>
ahora editamos routes/web.php
<?php
Route::get('/{any}', function () {
return view('post');
})->where('any', '.*');
para poder capturar cualquier ruta que se escriba en el browser
en el sector de id="app" vamos a cargar el component App.vue que contendra nuestro
router-view
si existe el router lo renderizara sino no. y quedara vacio.
resources/js/App.vue
<template>
<div class="container">
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-active {
opacity: 0
}
</style>
<script>
export default{
mounted() {
console.log('App.vue mounted.')
}
}
</script>
editaremos app.js para crear las routes de los componentes importados y asignarselo a nuestro
objeto Vue de la aplicacion
import HomeComponent from './components/HomeComponent.vue';
import CreateComponent from './components/CreateComponent.vue';
import IndexComponent from './components/IndexComponent.vue';
import EditComponent from './components/EditComponent.vue';
const routes = [
{
name: 'home',
path: '/home',
component: HomeComponent
},
{
name: 'create',
path: '/create',
component: CreateComponent
},
{
name: 'posts',
path: '/posts',
component: IndexComponent
},
{
name: 'edit',
path: '/edit/:id',
component: EditComponent
}
];
import App from './App.vue';
const router = new VueRouter({ mode: 'history', routes: routes});
const app = new Vue(
Vue.util.extend({ router }, App)
).$mount('#app');
los componentes
hay que crearlos en resources/js/components/
por ejemplo el CreateComponent.vue seria
<template>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">Create Component</div>
<div class="card-body">
I'm the Create Component component.
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('CreateComponent mounted.')
}
}
</script>
al App.vue
le vamos a agregar una cabecera para navegar
<template>
<div class="container">
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
<ul class="navbar-nav">
<li class="nav-item">
<router-link to="/home" class="nav-link">Home</router-link>
</li>
<li class="nav-item">
<router-link to="/create" class="nav-link">Create Post</router-link>
</li>
<li class="nav-item">
<router-link to="/posts" class="nav-link">Posts</router-link>
</li>
</ul>
</nav><br />
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</template>
Parte 3: Crear el Backend
Vamos a crear el modelo Post, el controlador y una collection de Post como resorce.
php artisan make:model Post -mc
-mc : crea el archivo de migracion y el controlador de un saque
para crear la collection PostCollection
php artisan make:resource PostCollection
editar en el archivo de migracion:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
en el modelo Post.php, indicar los campos que se pueden llenar masivamente:
protected $fillable = ['title', 'body'];
implementamos los metodos del controlador PostController.php
use Illuminate\Http\Request;
use App\Http\Resources\PostCollection;
use App\Post;
class PostController extends Controller
{
public function store(Request $request)
{
$post = new Post([
'title' => $request->get('title'),
'body' => $request->get('body')
]);
$post->save();
return response()->json('successfully added');
}
public function index()
{
return new PostCollection(Post::all());
}
public function edit($id)
{
$post = Post::find($id);
return response()->json($post);
}
public function update($id, Request $request)
{
$post = Post::find($id);
$post->update($request->all());
return response()->json('successfully updated');
}
public function delete($id)
{
$post = Post::find($id);
$post->delete();
return response()->json('successfully deleted');
}
}
Parte 4: Definir las routes en la api
en routes/api.php:
use Illuminate\Http\Request;
Route::post('/post/create', 'PostController@store');
Route::get('/post/edit/{id}', 'PostController@edit');
Route::post('/post/update/{id}', 'PostController@update');
Route::delete('/post/delete/{id}', 'PostController@delete');
Route::get('/posts', 'PostController@index');
Parte 5: Implementar los componentes de Creacion, Listado y actualizacion
notar el uso de axios para los request a nuestra api
CreateComponent.vue
<template>
<div>
<h1>Create A Post</h1>
<form @submit.prevent="addPost">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Title:</label>
<input type="text" class="form-control" v-model="post.title">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Body:</label>
<textarea class="form-control" v-model="post.body" rows="5"></textarea>
</div>
</div>
</div><br />
<div class="form-group">
<button class="btn btn-primary">Create</button>
</div>
</form>
</div>
</template>
<script>
export default {
mounted() {
console.log('CreateComponent mounted.')
},
data(){
return {
post:{}
}
},
methods: {
addPost(){
console.log(this.post);
let server = 'http://127.0.0.1:8001';
let uri = server + '/api/post/create';
this.axios.post(uri, this.post).then((response) => {
this.$router.push({name: 'posts'});
});
}
}
}
</script>
we have used the push() method to change the route programmatically.
IndexComponent.vue
<template>
<div>
<h1>Posts</h1>
<div class="row">
<div class="col-md-10"></div>
<div class="col-md-2">
<router-link :to="{ name: 'create' }" class="btn btn-primary">Create Post</router-link>
</div>
</div><br />
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Item Name</th>
<th>Item Body</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts" :key="post.id">
<td>{{ post.id }}</td>
<td>{{ post.title }}</td>
<td>{{ post.body }}</td>
<td><router-link :to="{name: 'edit', params: { id: post.id }}" class="btn btn-primary">Edit</router-link></td>
<td><button class="btn btn-danger" @click.prevent="deletePost(post.id)">Delete</button></td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
mounted() {
console.log('IndexComponent mounted.')
},
data() {
return {
posts: []
}
},
created() {
let server = 'http://127.0.0.1:8001';
let uri = server + '/api/posts';
this.axios.get(uri).then(response => {
this.posts = response.data.data;
});
},
methods: {
deletePost(id)
{
let server = 'http://127.0.0.1:8001';
let uri = `${server}/api/post/delete/${id}`;
this.axios.delete(uri).then(response => {
let i = this.posts.map(item => item.id).indexOf(id); // find index of your object
this.posts.splice(i, 1)
});
}
}
}
</script>
si se elimina un item el listado se modifica sin que se recargue la pagina
EditComponent.vue
<template>
<div>
<h1>Edit Post</h1>
<form @submit.prevent="updatePost">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Title:</label>
<input type="text" class="form-control" v-model="post.title">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Body:</label>
<textarea class="form-control" v-model="post.body" rows="5"></textarea>
</div>
</div>
</div><br />
<div class="form-group">
<button class="btn btn-primary">Update</button>
</div>
</form>
</div>
</template>
<script>
export default {
mounted() {
console.log('EditComponent mounted.')
},
data() {
return {
post: {}
}
},
created() {
let server = 'http://127.0.0.1:8001';
let uri = `${server}/api/post/edit/${this.$route.params.id}`;
this.axios.get(uri).then((response) => {
this.post = response.data;
});
},
methods: {
updatePost() {
let server = 'http://127.0.0.1:8001';
let uri = `${server}/api/post/update/${this.$route.params.id}`;
this.axios.post(uri, this.post).then((response) => {
this.$router.push({name: 'posts'});
});
}
}
}
</script>
por un tema de organizacion de codigo, las routes se pueden definir en un arhivo e importarlo luego
en app.js.
entonces creamos en resorces/js/routes.js
import HomeComponent from './components/HomeComponent.vue';
import CreateComponent from './components/CreateComponent.vue';
import IndexComponent from './components/IndexComponent.vue';
import EditComponent from './components/EditComponent.vue';
const routes = [
{
name: 'home',
path: '/home',
component: HomeComponent
},
{
name: 'create',
path: '/create',
component: CreateComponent
},
{
name: 'posts',
path: '/posts',
component: IndexComponent
},
{
name: 'edit',
path: '/edit/:id',
component: EditComponent
}
];
export default routes;
y en app.js
import routes_file from './routes';
const router = new VueRouter({ mode: 'history', routes: routes_file});
extraer un archivo rar en linux
1 instalar winrar
2 extraer el archivo
asi se extraeran los archivos comprimidos en la ubicacion actual. Si se quiere enviar los archivos extraidos a una carpeta
unrar e mis_archivos.rar mi_carpeta/
sudo apt-get install unrar
2 extraer el archivo
unrar e mis_archivos.rar
asi se extraeran los archivos comprimidos en la ubicacion actual. Si se quiere enviar los archivos extraidos a una carpeta
unrar e mis_archivos.rar mi_carpeta/
graphql client apollo vue
crearemos bajo la carpeta src
una llamada graphql y dentro otra llamada queries
donde guardaremos nuestras queries.
Crearemos ahi el archivo categories.gql
query{
categories{
id
name
}
}
luego en Home.vue
si recargamos la pagina podremos ver el listado de categories
sin embargo aunque la carga no sea inmediata, el mensaje de "loading..." no aparece.
para que funcione vamos a modificar las sgts lineas:
ahora queremos que al clickear sobre una categoria nos liste los libros que tenga esa categoria.
para eso primero creamos el archivo category.gql
luego en nuestro codigo agregamos
el bloque para mostrar los libros
notar que inicialmente se cargaran los libros de la categoria 1
para lo cual
en la seccion de script
y para hacer dinamica la pagina creamos el metodo que le asigna un valor a la variable "selectedCategory" segun la categoria que clickeemos
en la misma seccion de script, y debajo de data, escribimos:
y en la seccion de categorias implementamos el evento click para que llame a ese metodo
nota:
posiblemente aunque la aplicacion funcione en la terminal el Eslint de errores o warnings
que no tengan sentido
para evitarlos
crear en la raiz del proyecto un archivo llamado
.eslintignore
y adentro escribir la sgt linea
*/*.gql
una llamada graphql y dentro otra llamada queries
donde guardaremos nuestras queries.
Crearemos ahi el archivo categories.gql
query{
categories{
id
name
}
}
luego en Home.vue
<template>
<div class="home">
<ApolloQuery :query="require('../graphql/queries/categories.gql')">
<template slot-scope="{ result: { data, loading } }">
<div v-if="loading">Loading...</div>
<ul v-else>
<li v-for="category of data.categories" :key="category.id" class="user">
{{ category.name }}
</li>
</ul>
</template>
</ApolloQuery>
</div>
</template>
si recargamos la pagina podremos ver el listado de categories
sin embargo aunque la carga no sea inmediata, el mensaje de "loading..." no aparece.
para que funcione vamos a modificar las sgts lineas:
<template slot-scope="{ result: { data, loading } }">
<!-- Some content -->
<div v-if="loading">Loading...</div>
ahora queremos que al clickear sobre una categoria nos liste los libros que tenga esa categoria.
para eso primero creamos el archivo category.gql
query($id: ID!){
category(id: $id){
id
name
books{
id
title
author
image
}
}
}
luego en nuestro codigo agregamos
el bloque para mostrar los libros
<ApolloQuery :query="require('../graphql/queries/category.gql')" :variables="{id: selectedCategory}">
<template slot-scope="{ result: { data, loading }, isLoading }">
<div v-if="isLoading">Loading...</div>
<div v-else>
<div v-for="book of data.category.books" :key="book.id" class="link-margin">
{{ book.title }}.{{ book.title }}
</div>
</div>
</template>
</ApolloQuery>
notar que inicialmente se cargaran los libros de la categoria 1
para lo cual
en la seccion de script
<script>
// @ is an alias to /src
export default{
data(){
return {
selectedCategory : 1
}
},
y para hacer dinamica la pagina creamos el metodo que le asigna un valor a la variable "selectedCategory" segun la categoria que clickeemos
en la misma seccion de script, y debajo de data, escribimos:
methods: {
selectCategory(category){
this.selectedCategory = category
}
}
y en la seccion de categorias implementamos el evento click para que llame a ese metodo
<a href="#" v-for="category of data.categories" :key="category.id" class="link-margin"
@click="selectCategory(category.id)">
{{ category.name }}
</a>
nota:
posiblemente aunque la aplicacion funcione en la terminal el Eslint de errores o warnings
que no tengan sentido
para evitarlos
crear en la raiz del proyecto un archivo llamado
.eslintignore
y adentro escribir la sgt linea
*/*.gql
Suscribirse a:
Entradas (Atom)
linux ubuntu mint actualizar chrome
desde una terminal: $ sudo apt update $ sudo apt install google-chrome-stable
-
por consola y desde la raiz de tu proyecto php artisan --version
-
en nuestro proyecto creamos una carpeta llamada donde estaran todas nuestras clases, por ejemplo una llamada: MiApp adentro de esta irian b...
-
Integridad al nivel de la base de datos Oracle Oracle valida la integridad de la base de datos y presenta los siguientes mensajes de erro...