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.static('dist'));
app.use(express.urlencoded());
app.use(express.json());
app.get("/"); app.get("/");
app.post('/links', require('./srv/LinksAnimes/obtenerLinks').obtenerLinks);
app.put('/links', require('./srv/LinksAnimes/modificarLink').modificarLinks);
app.listen(8080); app.listen(8080);

11
package-lock.json generated
View File

@ -103,6 +103,12 @@
"integrity": "sha512-5Th3OsZ4gTRdr9Mho83BQ23cex4sRhOR4XTG+m+cJc0FhtUBK9Vn62hBJ+pnQYnSxoPOsKoAPOx6FcphxBC8ng==", "integrity": "sha512-5Th3OsZ4gTRdr9Mho83BQ23cex4sRhOR4XTG+m+cJc0FhtUBK9Vn62hBJ+pnQYnSxoPOsKoAPOx6FcphxBC8ng==",
"dev": true "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": { "@vue/cli-overlay": {
"version": "3.0.5", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-3.0.5.tgz",
@ -10058,6 +10064,11 @@
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true "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": { "yargs": {
"version": "12.0.2", "version": "12.0.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz",

View File

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

View File

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

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div class="caja contenido"> <div class="caja contenido">
<div v-if="render">
<div class="contenido--titulo"> <div class="contenido--titulo">
{{ datos.titulo }} {{ datos.titulo }}
</div> </div>
@ -40,40 +40,64 @@
<proximo-episodio :color="color" /> <proximo-episodio :color="color" />
<br> <br>
<anuncio-global /> <anuncio-global />
<anuncio-local /> <anuncio-local :mensaje="datosAnime.aviso"/>
<br> <br>
<panel-de-descarga :color="color" :nombre="datos.titulo"/> <panel-de-descarga :color="color" :nombre="datos.titulo" :datos="datosAnime"/>
</div> </div>
</div>
<div v-else>
No pudimos encontrar {{ nombre }} en nuestra base de datos :c
</div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script>
import AnuncioGlobal from '../anuncio-global.vue' import AnuncioGlobal from '../anuncio-global.vue'
import AyudaMini from './ayudaMini.vue' import AyudaMini from './ayudaMini.vue'
import ProximoEpisodio from './proximoEpisodio.vue' import ProximoEpisodio from './proximoEpisodio.vue'
import AnuncioLocal from './anuncioLocal.vue' import AnuncioLocal from './anuncioLocal.vue'
import PanelDeDescarga from './panelDeDescarga.vue' import ComponenteCarga from '../comp-cargando.vue'
export default { export default {
name: "Contenido", name: "Contenido",
data: function () {
return {
datosAnime: {}
}
},
props: { props: {
nombre: String, nombre: String,
datos: Object, datos: Object,
render: Boolean, color: String,
color: String
}, },
components: { components: {
'anuncio-global': AnuncioGlobal, 'anuncio-global': AnuncioGlobal,
'ayuda-mini': AyudaMini, 'ayuda-mini': AyudaMini,
'proximo-episodio': ProximoEpisodio, 'proximo-episodio': ProximoEpisodio,
'anuncio-local': AnuncioLocal, '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> </script>

View File

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

View File

@ -7,6 +7,7 @@
"res": "@60fps", "res": "@60fps",
"servidor": "MEGA", "servidor": "MEGA",
"color": "red", "color": "red",
"key": 1,
"eps": { "eps": {
"1": [0, "162 MB", "https://mega.nz/#!0kpQnCzB!vt_b9n5I-YZ5TiFoqKyE5anuU_RFIzaYkEBChD-SwaA"] "1": [0, "162 MB", "https://mega.nz/#!0kpQnCzB!vt_b9n5I-YZ5TiFoqKyE5anuU_RFIzaYkEBChD-SwaA"]
} }
@ -16,6 +17,7 @@
"res": "720p@60fps", "res": "720p@60fps",
"servidor": "OneDrive", "servidor": "OneDrive",
"color": "#0d3ed5", "color": "#0d3ed5",
"key": 2,
"eps": { "eps": {
"1": [0, "246 MB", "https://unsaedupe-my.sharepoint.com/:v:/g/personal/faraoz_unsa_edu_pe/EY0ddAEU0OdMo09arH62F3kBrQdFvNIv6zCCfalEND3KJg?e=sdoOiD"] "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"> <template v-for="(opcion, indice) in datos.opciones">
<div class="panel__titulo__variantes__variante hoverable" <div class="panel__titulo__variantes__variante hoverable"
:style="indice === 0? `background-color: ${opcion.color}` : ''" :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 }} {{ opcion.formato }} {{ opcion.res }}<br>{{ opcion.servidor }}
</div> </div>
</template> </template>
@ -19,9 +20,21 @@
<template v-for="(opcion, indice) in datos.opciones"> <template v-for="(opcion, indice) in datos.opciones">
<div class="panel__descripcion__titulo" :id="`tarjeta${indice}`" <div :id="`tarjeta${indice}`" :style="indice !== 0? 'display: none' : ''">
:style="'color: ' + color + ((indice !== 0)? '; display: none' : '')">
Links (Elem num {{ indice }}) <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> </div>
</template> </template>
@ -30,13 +43,12 @@
</div> </div>
</template> </template>
<script lang="ts"> <script>
export default { export default {
name: "panelDeDescarga", name: "panelDeDescarga",
data: function () { data: function () {
return { return {
datos: {},
posActual: '0' posActual: '0'
} }
}, },
@ -48,45 +60,52 @@
nombre: { nombre: {
type: String, type: String,
required: true required: true
} },
datos: Object
}, },
methods: { methods: {
cambiarDescripcionDescarga (idDestino: string) { cambiarDescripcionDescarga (idDestino) {
const elemAnterior = document.getElementById(`tarjeta${this.posActual}`); const elemAnterior = document.getElementById(`tarjeta${this.posActual}`);
const elemNuevo = document.getElementById(`tarjeta${idDestino}`); 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; this.posActual = idDestino;
elemAnterior.style.display = "none"; 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 { } else {
console.log(":c"); console.log(":c");
} }
}
}, },
created: function () { incrementarContador (variante, episodio, evento) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("PUT","/links");
xhr.open("POST","/links");
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
const vm = this;
xhr.onload = () => { xhr.onload = () => {
console.log(xhr.responseText);
const data = JSON.parse(xhr.responseText);
if (data.exito) {
vm.datos = data.payload;
}
}; };
xhr.send(`nombre=${ this.nombre }`); xhr.send(`nombre=${ this.nombre }&variante=${ variante }&episodio=${ episodio }`);
}
} }
} }
</script> </script>
<style scoped lang="sass"> <style scoped lang="sass">
.icono-pequeno
font-size: 15px
padding: 0 5px
cursor: default
.panel__titulo .panel__titulo
font: font:
family: Muli, "Open Sans", sans-serif family: Muli, "Open Sans", sans-serif
@ -118,5 +137,10 @@
size: x-large size: x-large
weight: bold weight: bold
.panel__descripcion__link
a
font-weight: bold
.panel .panel
</style> </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); Vue.use(Router);
export default new Router({ const rutas = {
mode: 'history', mode: 'history',
base: process.env.BASE_URL, base: process.env.BASE_URL,
routes: [ routes: [
@ -26,8 +26,11 @@ export default new Router({
component: AnimeView component: AnimeView
} }
], ],
scrollBehavior (to, from, savedPosition) { scrollBehavior (to: any, from: any, savedPosition: any) {
// return desired position // return desired position
return { x: 0, y: 0 } return { x: 0, y: 0 }
} }
}); };
// @ts-ignore
export default new Router(rutas);

View File

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

View File

@ -16,5 +16,6 @@ export default (app:any) => {
app.get("/"); app.get("/");
app.post('/links', require('./LinksAnimes/obtenerLinks').obtenerLinks); 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 mysql = require('mysql');
const SQL_CONNECT_DATA:object = { const SQL_CONNECT_DATA:object = {
// Solo para produccion habilitar socketPath // Solo para produccion habilitar socketPath
// socketPath: '/cloudsql/pseudosubs:us-central1:base-principal', socketPath: '/cloudsql/pseudosubs:us-central1:base-principal',
user: 'root', user: 'root',
password: 'GgwTo5GryvDhAr06wk5opKhd', password: 'GgwTo5GryvDhAr06wk5opKhd',
database: 'animes_links', database: 'animes_links',