Finalizada la conexion con la BBDD y la funcionalidad. Todo: Crear los datos en la base de datos.

master
Fernando 2018-11-21 12:58:16 -05:00
parent ee5c3a3e9f
commit 110819d8a3
15 changed files with 302 additions and 99 deletions

6
app.ts
View File

@ -3,6 +3,12 @@ let app = express();
app.use(express.static('dist'));
app.use(express.urlencoded());
app.use(express.json());
app.get("/");
app.post('/links', require('./srv/LinksAnimes/obtenerLinks').obtenerLinks);
app.put('/links', require('./srv/LinksAnimes/modificarLink').modificarLinks);
app.listen(8080);

11
package-lock.json generated
View File

@ -103,6 +103,12 @@
"integrity": "sha512-5Th3OsZ4gTRdr9Mho83BQ23cex4sRhOR4XTG+m+cJc0FhtUBK9Vn62hBJ+pnQYnSxoPOsKoAPOx6FcphxBC8ng==",
"dev": true
},
"@types/yaml": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.0.1.tgz",
"integrity": "sha512-Bq8/v5jtk4TsPY4qSmlEM2hucw5vgA7jWaDV6NFNv6ZjSoqxicRB5RH8Cc1eMEr0VcbgnysGIujg6hR3nZ14sw==",
"dev": true
},
"@vue/cli-overlay": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-3.0.5.tgz",
@ -10058,6 +10064,11 @@
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
},
"yaml": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.0.2.tgz",
"integrity": "sha512-vPmXtExk6AV7F5l2N5jW4LhbhZZPPN+xOK8x/+EgSXsXoawuo19Iqa+9nYMwrltsi6nl0rMKiROA/SAfG2OgUw=="
},
"yargs": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz",

View File

@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"start": "node app.js",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"express": "vue-cli-service express:watch",
@ -16,9 +17,11 @@
"vue": "^2.5.17",
"vue-class-component": "^6.0.0",
"vue-property-decorator": "^7.0.0",
"vue-router": "^3.0.1"
"vue-router": "^3.0.1",
"yaml": "^1.0.2"
},
"devDependencies": {
"@types/yaml": "^1.0.1",
"@vue/cli-plugin-typescript": "^3.0.5",
"@vue/cli-service": "^3.0.5",
"node-sass": "^4.9.0",

View File

@ -24,5 +24,6 @@
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</body>
</html>

View File

@ -1,79 +1,103 @@
<template>
<div>
<div class="caja contenido">
<div v-if="render">
<div class="contenido--titulo">
{{ datos.titulo }}
</div>
<br>
<div class="contenido--contenedor-imagen">
<img :src="datos.imgUrl" :alt="datos.titulo" class="responsive-img">
</div>
<br>
<div class="contenido--descripcion">
{{ datos.descripcion }}
</div>
<div class="contenido--datos">
<div class="contenido--datos--titulo">
Especificaciones tecnicas
</div>
<div class="contenido--datos--descripcion">
Capitulos: {{ datos.data.eps }} <br>
Al Aire: {{ datos.data.alAire }} <br>
Temporada: {{ datos.data.temporada }} <br>
Estudio: {{ datos.data.estudio }} <br>
Fuente: {{ datos.data.fuente }} <br>
Generos: {{ datos.data.generos }} <br>
<br>
Openings:<br>
<template v-for="(op, index) in datos.data.OP">
<div class="espaciado">{{ index }} : {{ op }}</div>
</template>
Endings:<br>
<template v-for="(op, index) in datos.data.ED">
<div class="espaciado">{{ index }} : {{ op }}</div>
</template>
</div>
<br>
<ayuda-mini :color="color" :nombre-anime="datos.titulo" />
<br>
<proximo-episodio :color="color" />
<br>
<anuncio-global />
<anuncio-local />
<br>
<panel-de-descarga :color="color" :nombre="datos.titulo"/>
<div class="contenido--titulo">
{{ datos.titulo }}
</div>
<br>
<div class="contenido--contenedor-imagen">
<img :src="datos.imgUrl" :alt="datos.titulo" class="responsive-img">
</div>
<br>
<div class="contenido--descripcion">
{{ datos.descripcion }}
</div>
<div class="contenido--datos">
<div class="contenido--datos--titulo">
Especificaciones tecnicas
</div>
<div class="contenido--datos--descripcion">
Capitulos: {{ datos.data.eps }} <br>
Al Aire: {{ datos.data.alAire }} <br>
Temporada: {{ datos.data.temporada }} <br>
Estudio: {{ datos.data.estudio }} <br>
Fuente: {{ datos.data.fuente }} <br>
Generos: {{ datos.data.generos }} <br>
<br>
Openings:<br>
<template v-for="(op, index) in datos.data.OP">
<div class="espaciado">{{ index }} : {{ op }}</div>
</template>
Endings:<br>
<template v-for="(op, index) in datos.data.ED">
<div class="espaciado">{{ index }} : {{ op }}</div>
</template>
</div>
<br>
<ayuda-mini :color="color" :nombre-anime="datos.titulo" />
<br>
<proximo-episodio :color="color" />
<br>
<anuncio-global />
<anuncio-local :mensaje="datosAnime.aviso"/>
<br>
<panel-de-descarga :color="color" :nombre="datos.titulo" :datos="datosAnime"/>
</div>
<div v-else>
No pudimos encontrar {{ nombre }} en nuestra base de datos :c
</div>
</div>
</div>
</template>
<script lang="ts">
<script>
import AnuncioGlobal from '../anuncio-global.vue'
import AyudaMini from './ayudaMini.vue'
import ProximoEpisodio from './proximoEpisodio.vue'
import AnuncioLocal from './anuncioLocal.vue'
import PanelDeDescarga from './panelDeDescarga.vue'
import ComponenteCarga from '../comp-cargando.vue'
export default {
name: "Contenido",
data: function () {
return {
datosAnime: {}
}
},
props: {
nombre: String,
datos: Object,
render: Boolean,
color: String
color: String,
},
components: {
'anuncio-global': AnuncioGlobal,
'ayuda-mini': AyudaMini,
'proximo-episodio': ProximoEpisodio,
'anuncio-local': AnuncioLocal,
'panel-de-descarga': PanelDeDescarga
'panel-de-descarga': () => ({
component: import('./panelDeDescarga.vue'),
loading: ComponenteCarga,
delay: 200,
timeout: 5000
})
},
created: function () {
const xhr = new XMLHttpRequest();
xhr.open("POST","/links");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
const vm = this;
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
if (data.exito) {
vm.datosAnime = data.payload;
}
};
console.log("Este es el query: " + `nombre=${ this.datos.titulo }`);
xhr.send(`nombre=${ this.datos.titulo }`);
}
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<div class="anuncio">
<div class="anuncio" v-html="mensaje">
Mirame we este es el anuncio local. <br>
Por ahora será solo esto...
</div>
@ -9,7 +9,13 @@
/* TODO: Hacer que el anuncio este basado en los datos de la BBDD */
export default {
name: "anuncioLocal"
name: "anuncioLocal",
props: {
mensaje: {
type: String,
default: "Anuncio local...<br>Anuncio local x2 ..."
}
}
}
</script>

View File

@ -7,6 +7,7 @@
"res": "@60fps",
"servidor": "MEGA",
"color": "red",
"key": 1,
"eps": {
"1": [0, "162 MB", "https://mega.nz/#!0kpQnCzB!vt_b9n5I-YZ5TiFoqKyE5anuU_RFIzaYkEBChD-SwaA"]
}
@ -16,6 +17,7 @@
"res": "720p@60fps",
"servidor": "OneDrive",
"color": "#0d3ed5",
"key": 2,
"eps": {
"1": [0, "246 MB", "https://unsaedupe-my.sharepoint.com/:v:/g/personal/faraoz_unsa_edu_pe/EY0ddAEU0OdMo09arH62F3kBrQdFvNIv6zCCfalEND3KJg?e=sdoOiD"]
}

View File

@ -7,7 +7,8 @@
<template v-for="(opcion, indice) in datos.opciones">
<div class="panel__titulo__variantes__variante hoverable"
:style="indice === 0? `background-color: ${opcion.color}` : ''"
v-on:click="cambiarDescripcionDescarga(indice)" >
v-on:click="cambiarDescripcionDescarga(indice)" :color-min="opcion.color"
:id="`opcion${indice}`">
{{ opcion.formato }} {{ opcion.res }}<br>{{ opcion.servidor }}
</div>
</template>
@ -19,9 +20,21 @@
<template v-for="(opcion, indice) in datos.opciones">
<div class="panel__descripcion__titulo" :id="`tarjeta${indice}`"
:style="'color: ' + color + ((indice !== 0)? '; display: none' : '')">
Links (Elem num {{ indice }})
<div :id="`tarjeta${indice}`" :style="indice !== 0? 'display: none' : ''">
<div class="panel__descripcion__titulo" :style="'color: ' + color">
Links<br>
</div>
<span v-for="(ep, num) in opcion.eps" class="panel__descripcion__link">
Todos los links se abren en una pestaña nueva.<br>
<br>
Episodio {{ num }} ->
<a :href="ep[2]" target="_blank" :style="'color: ' + color"
@mousedown.stop="incrementarContador(opcion.key, num, $event)">
{{ ep[1] }}
</a>
</span>
</div>
</template>
@ -30,13 +43,12 @@
</div>
</template>
<script lang="ts">
<script>
export default {
name: "panelDeDescarga",
data: function () {
return {
datos: {},
posActual: '0'
}
},
@ -48,45 +60,52 @@
nombre: {
type: String,
required: true
}
},
datos: Object
},
methods: {
cambiarDescripcionDescarga (idDestino: string) {
cambiarDescripcionDescarga (idDestino) {
const elemAnterior = document.getElementById(`tarjeta${this.posActual}`);
const elemNuevo = document.getElementById(`tarjeta${idDestino}`);
if (elemNuevo && elemAnterior) {
const opcionAnterior = document.getElementById(`opcion${this.posActual}`);
const opcionNueva = document.getElementById(`opcion${idDestino}`);
if (elemNuevo && elemAnterior && opcionAnterior && opcionNueva) {
this.posActual = idDestino;
elemAnterior.style.display = "none";
elemNuevo.style.display = "block";
opcionAnterior.style.backgroundColor = "transparent";
elemNuevo.style.display = "block";
opcionNueva.style.backgroundColor = opcionNueva.getAttribute("color-min");
console.log(":3 " + idDestino);
} else {
console.log(":c");
}
},
incrementarContador (variante, episodio, evento) {
const xhr = new XMLHttpRequest();
xhr.open("PUT","/links");
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.onload = () => {
console.log(xhr.responseText);
};
xhr.send(`nombre=${ this.nombre }&variante=${ variante }&episodio=${ episodio }`);
}
},
created: function () {
const xhr = new XMLHttpRequest();
xhr.open("POST","/links");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
const vm = this;
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
if (data.exito) {
vm.datos = data.payload;
}
};
xhr.send(`nombre=${ this.nombre }`);
}
}
</script>
<style scoped lang="sass">
.icono-pequeno
font-size: 15px
padding: 0 5px
cursor: default
.panel__titulo
font:
family: Muli, "Open Sans", sans-serif
@ -118,5 +137,10 @@
size: x-large
weight: bold
.panel__descripcion__link
a
font-weight: bold
.panel
</style>

View File

@ -0,0 +1,56 @@
<template>
<div class="cargando">
<div class="preloader-wrapper big active">
<div class="spinner-layer spinner-blue">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer spinner-red">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer spinner-yellow">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer spinner-green">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "comp-cargando"
}
</script>
<style scoped lang="sass">
.cargando
text-align: center
</style>

View File

@ -6,7 +6,7 @@ import AnimeView from './views/AnimeView.vue'
Vue.use(Router);
export default new Router({
const rutas = {
mode: 'history',
base: process.env.BASE_URL,
routes: [
@ -26,8 +26,11 @@ export default new Router({
component: AnimeView
}
],
scrollBehavior (to, from, savedPosition) {
scrollBehavior (to: any, from: any, savedPosition: any) {
// return desired position
return { x: 0, y: 0 }
}
});
};
// @ts-ignore
export default new Router(rutas);

View File

@ -10,8 +10,12 @@
<div class="container row">
<div class="col l8 m12 s12">
<contenido :nombre="this.$route.params.anime" :datos="this.datos" :render="this.existe"
:color="color"/>
<template v-if="this.existe">
<contenido :nombre="this.$route.params.anime" :datos="this.datos" :color="color"/>
</template>
<template v-else>
Este anime no está en nuestra base de datos.
</template>
</div>
<div class="col l4 hide-on-med-and-down">
@ -25,16 +29,23 @@
</template>
<script>
import NavBar from '../components/AnimeView/NavBar'
import Contenido from '../components/AnimeView/Contenido'
import Footer from '../components/mi-footer';
import ComponenteCarga from '../components/comp-cargando.vue';
export default {
name: "AnimeView",
components: {
'nav-bar': NavBar,
'contenido': Contenido,
'mi-footer': Footer,
'nav-bar': () => ({
component: import('../components/AnimeView/NavBar'),
loading: ComponenteCarga,
delay: 500,
timeout: 5000
}),
'contenido': () => ({
component: import('../components/AnimeView/Contenido')
}),
'mi-footer': () => ({
component: import('../components/mi-footer')
}),
},
data: function () {
return {
@ -44,27 +55,29 @@
}
},
created: function () {
const vm = this;
const exec = () => {
const link = `/Anime/${this.$route.params.anio}/${this.$route.params.temp}/${this.$route.params.anime}`;
console.log(`El link es ${link}`);
for (const animeI in window.indiceAnimes) {
const anime = window.indiceAnimes[animeI];
if (anime.link === link) {
this.datos = anime;
this.existe = true;
this.color = anime.data.color;
vm.datos = anime;
vm.existe = true;
vm.color = anime.data.color;
break;
}
}
};
/* Se asegura que la lista de animes exista. */
if (window.indiceAnimes[0]) {
exec();
} else {
let vm = this;
// Obtener los animes desde una API v:
// TODO: Obtener los animes desde una API v:
fetch('/animes.json')
.then( response => response.json())
.then(function (myJson) {
@ -73,6 +86,7 @@
})
}
}
}
</script>

View File

@ -0,0 +1,50 @@
const modificarLink = (req: any, res: any) => {
const nombre = req.body.nombre;
const variante = parseInt(req.body.variante);
const episodio = req.body.episodio;
const con = require('../mysql').obtenerConexionMySql();
con.connect((err: any) => {
if (!err) {
con.query(
`SELECT data FROM links WHERE nombre='${nombre}'`,
(err: any, respuesta: any) => {
if (!err) {
const data = JSON.parse(respuesta[0]["data"]);
for (const opcion of data["opciones"]) {
if (opcion.key === variante) {
opcion["eps"][episodio][0]++;
}
}
con.query(
`UPDATE links SET data='${JSON.stringify(data)}' WHERE nombre='${nombre}'`,
(err:any) => {
if (err)
console.log("Error al actualizar la tabla :c");
con.end();
}
);
} else {
console.log("Eror al ejecutar query.");
con.end();
}
}
);
} else {
console.log("Error al conectarse a base de datos.");
con.end();
}
});
};
module.exports.modificarLinks = modificarLink;

View File

@ -14,8 +14,10 @@ const obtenerLinks = (req: any, res: any) => {
res.send(`{ "exito": true, "payload": ${JSON.stringify(objecto)} }`);
} else if (!err) {
console.log("Error: La consulta no dio ningun resultado en obtenerLinks");
} else {
console.log("Error al ejecutar Query.\n" + err);
console.log("Error al ejecutar Query en obtenerLinks.\n" + err);
res.send(`{ "exito": false }`);
}

View File

@ -16,5 +16,6 @@ export default (app:any) => {
app.get("/");
app.post('/links', require('./LinksAnimes/obtenerLinks').obtenerLinks);
app.put('/links', require('./LinksAnimes/modificarLink').modificarLinks);
}

View File

@ -3,7 +3,7 @@ const obtenerConexionMySql = () => {
const mysql = require('mysql');
const SQL_CONNECT_DATA:object = {
// Solo para produccion habilitar socketPath
// socketPath: '/cloudsql/pseudosubs:us-central1:base-principal',
socketPath: '/cloudsql/pseudosubs:us-central1:base-principal',
user: 'root',
password: 'GgwTo5GryvDhAr06wk5opKhd',
database: 'animes_links',