Commit 16815a3805fc895501269ffeadeaec239e376687

Authored by Galileo Sanchez
1 parent 8a54ad09

al fin terminamos

Showing 38 changed files with 663 additions and 117 deletions
@@ -30,9 +30,6 @@ moment.locale('es-ES') @@ -30,9 +30,6 @@ moment.locale('es-ES')
30 30
31 export default class App extends Component { 31 export default class App extends Component {
32 32
33 - componentWillMount() {  
34 - }  
35 -  
36 render() { 33 render() {
37 // buscar solicitudes 34 // buscar solicitudes
38 // estadisticas 35 // estadisticas
@@ -57,6 +54,9 @@ export default class App extends Component { @@ -57,6 +54,9 @@ export default class App extends Component {
57 BuscarSolicitudes: { screen: BuscarSolicitudes }, 54 BuscarSolicitudes: { screen: BuscarSolicitudes },
58 DetalleSolicitud: { screen: DetalleSolicitud } 55 DetalleSolicitud: { screen: DetalleSolicitud }
59 }) 56 })
  57 + const AyudaNavigator = createStackNavigator({
  58 + Ayuda: { screen: Ayuda },
  59 + })
60 60
61 const DrawerNavigator = createDrawerNavigator({ 61 const DrawerNavigator = createDrawerNavigator({
62 MisSolicitudes: { 62 MisSolicitudes: {
@@ -84,7 +84,12 @@ export default class App extends Component { @@ -84,7 +84,12 @@ export default class App extends Component {
84 }), 84 }),
85 }, 85 },
86 Estadisticas: { screen: Estadisticas }, 86 Estadisticas: { screen: Estadisticas },
87 - Ayuda: { screen: Ayuda }, 87 + AyudaNavigator: {
  88 + screen: AyudaNavigator,
  89 + navigationOptions: () => ({
  90 + title: 'Ayuda',
  91 + })
  92 + }
88 }, { 93 }, {
89 contentComponent: CustomDrawerContentComponent 94 contentComponent: CustomDrawerContentComponent
90 }) 95 })
  1 +import React, { Component } from 'react'
  2 +import {
  3 + View,
  4 +} from 'react-native'
  5 +import { connect } from 'react-redux'
  6 +import { Button } from 'react-native-elements'
  7 +
  8 +import { postValoracion } from '../../redux/actions/valoraciones'
  9 +import { postReporte } from '../../redux/actions/reportes'
  10 +
  11 +import css from './style'
  12 +
  13 +const SATISFECHO = 'SATISFECHO'
  14 +const NO_SATISFECHO = 'NO SATISFECHO'
  15 +const INFORMACION_NO_PUBLICADA = 'CONFIDENCIAL'
  16 +class BotonValoracion extends Component {
  17 +
  18 + render() {
  19 + if (this.props.mostrar) {
  20 + const solicitudId = this.props.solicitud.id
  21 + const usuario = this.props.usuario
  22 + const likeName = this.props.valoracion.data === SATISFECHO
  23 + ? 'ios-thumbs-up'
  24 + : 'ios-thumbs-up-outline'
  25 +
  26 + const dislikeName = this.props.valoracion.data === NO_SATISFECHO
  27 + ? 'ios-thumbs-down'
  28 + : 'ios-thumbs-down-outline'
  29 +
  30 + const reportName = this.props.reporte.data === INFORMACION_NO_PUBLICADA
  31 + ? 'ios-megaphone'
  32 + : 'ios-megaphone-outline'
  33 +
  34 + return (
  35 + <View style={[css.buttonFooter]}>
  36 + <Button
  37 + onPress={() => this.props.postReporte(solicitudId, usuario, INFORMACION_NO_PUBLICADA)}
  38 + backgroundColor="white"
  39 + icon={{
  40 + name: reportName,
  41 + size: 27,
  42 + color: 'red',
  43 + type: 'ionicon'
  44 + }}
  45 + />
  46 + <Button
  47 + backgroundColor="white"
  48 + onPress={() => this.props.postValoracion(solicitudId, usuario, SATISFECHO)}
  49 + icon={{
  50 + name: likeName,
  51 + size: 27,
  52 + color: 'red',
  53 + type: 'ionicon'
  54 + }}
  55 + />
  56 + <Button
  57 + onPress={() => this.props.postValoracion(solicitudId, usuario, NO_SATISFECHO)}
  58 + backgroundColor="white"
  59 + icon={{
  60 + name: dislikeName,
  61 + size: 27,
  62 + color: 'red',
  63 + type: 'ionicon'
  64 + }}
  65 + />
  66 + </View>
  67 + )
  68 + }
  69 + return <View />
  70 + }
  71 +}
  72 +
  73 +const mapStateToProps = (state) => ({
  74 + solicitud: state.solicitudes.current,
  75 + usuario: state.usuario.datos,
  76 + valoracion: state.valoracion,
  77 + reporte: state.reporte,
  78 +})
  79 +
  80 +const mapDispatchToProps = (dispatch) => ({
  81 + postValoracion: (solicitud, usuario, valoracion) =>
  82 + dispatch(postValoracion(solicitud, usuario, valoracion)),
  83 + postReporte: (solicitud, usuario, valoracion) =>
  84 + dispatch(postReporte(solicitud, usuario, valoracion))
  85 +})
  86 +export default connect(mapStateToProps, mapDispatchToProps)(BotonValoracion)
  1 +import { StyleSheet } from 'react-native'
  2 +import { merge } from 'ramda'
  3 +
  4 +import styles from '../../common/styles'
  5 +
  6 +export default merge(StyleSheet.create({
  7 + buttonFooter: {
  8 + flexDirection: 'row',
  9 + justifyContent: 'space-evenly'
  10 + }
  11 +}), styles)
@@ -3,10 +3,12 @@ import { View, Image, Linking, TouchableOpacity } from 'react-native' @@ -3,10 +3,12 @@ import { View, Image, Linking, TouchableOpacity } from 'react-native'
3 3
4 import css from './style' 4 import css from './style'
5 5
  6 +const innovandoImg = require('../../assets/logos/innovando.png')
  7 +const senaticsImg = require('../../assets/logos/senatics.png')
  8 +
6 class FooterSenatics extends Component { 9 class FooterSenatics extends Component {
7 10
8 myHandlePress = (link) => () => { 11 myHandlePress = (link) => () => {
9 - console.log('pressed link')  
10 Linking.openURL(link) 12 Linking.openURL(link)
11 } 13 }
12 14
@@ -15,12 +17,12 @@ class FooterSenatics extends Component { @@ -15,12 +17,12 @@ class FooterSenatics extends Component {
15 <View style={css.container}> 17 <View style={css.container}>
16 <View style={css.card} > 18 <View style={css.card} >
17 <TouchableOpacity onPress={this.myHandlePress('http://www.innovando.gov.py')}> 19 <TouchableOpacity onPress={this.myHandlePress('http://www.innovando.gov.py')}>
18 - <Image style={css.img} source={require('../../assets/logos/innovando.png')} /> 20 + <Image style={css.img} source={innovandoImg} />
19 </TouchableOpacity> 21 </TouchableOpacity>
20 </View> 22 </View>
21 <View style={css.card} > 23 <View style={css.card} >
22 <TouchableOpacity onPress={this.myHandlePress('https://www.senatics.gov.py')}> 24 <TouchableOpacity onPress={this.myHandlePress('https://www.senatics.gov.py')}>
23 - <Image style={css.img} source={require('../../assets/logos/senatics.png')} /> 25 + <Image style={css.img} source={senaticsImg} />
24 </TouchableOpacity> 26 </TouchableOpacity>
25 </View> 27 </View>
26 </View>) 28 </View>)
@@ -8,7 +8,6 @@ const imgSrc = require('../../assets/logos/jaikuaamina.png') @@ -8,7 +8,6 @@ const imgSrc = require('../../assets/logos/jaikuaamina.png')
8 class FooterSenatics extends Component { 8 class FooterSenatics extends Component {
9 9
10 myHandlePress = (link) => () => { 10 myHandlePress = (link) => () => {
11 - console.log('pressed link')  
12 Linking.openURL(link) 11 Linking.openURL(link)
13 } 12 }
14 resizeMode='center' 13 resizeMode='center'
@@ -3,19 +3,16 @@ import { Constants } from 'expo' @@ -3,19 +3,16 @@ import { Constants } from 'expo'
3 export const STATUS_BAR_HEIGHT = Constants.statusBarHeight 3 export const STATUS_BAR_HEIGHT = Constants.statusBarHeight
4 4
5 // PROD 5 // PROD
6 -export const AUTH_TOKEN = '730e9175-c76c-418a-a051-7e2834ed7fd7'  
7 -export const CLIENT_SECRET = 'deb7aa26038d0f44a35cd3e1d2f60b5c0e11192ddd0f9430c0d64a1101daa11f'  
8 -export const SENATICS_URL = 'https://informacionpublica.paraguay.gov.py:443/portal-core/rest/api'  
9 - 6 +// export const SENATICS_URL = 'https://informacionpublica.paraguay.gov.py:443/portal-core/rest/api'
10 // DEV 7 // DEV
11 -// export const AUTH_TOKEN = '0496164f-8de1-449c-9ce9-af0e0a6ce9fe'  
12 -// export const CLIENT_SECRET = 'a66a1a98eb7059a5c3b446183e214cc2661326c2994b811cb06dd9d3d873a9e9'  
13 -// export const SENATICS_URL = 'http://192.168.0.26:2128/api'  
14 -export const BACKEND_URL = 'http://192.168.0.26:3000/api'  
15 -export const RENEW_INTERVAL = 1 * 1000 * 60  
16 -export const TOKEN_EXPIRATION = 15 * 1000 * 60 8 +export const SENATICS_URL = 'http://192.168.0.26:2128/api'
  9 +
  10 +export const BACKEND_URL = 'http://192.168.0.26:3000'
17 export const NOTIFICATION_ICON = 'http://ayuda.tesis-jmgo.cnc.una.py/img/jaikuaamina.icon.png' 11 export const NOTIFICATION_ICON = 'http://ayuda.tesis-jmgo.cnc.una.py/img/jaikuaamina.icon.png'
18 export const INFO_PY_URL = 'https://informacionpublica.paraguay.gov.py/portal/' 12 export const INFO_PY_URL = 'https://informacionpublica.paraguay.gov.py/portal/'
  13 +export const PORTAL_DENUNCIAS_URL = 'http://www.denuncias.gov.py'
  14 +export const TUTORIAL_AIF_URL = 'https://youtu.be/W8jG3md7YFg'
  15 +export const TUTORIAL_APP = `${BACKEND_URL}/index.html`
19 16
20 export const ESTADOS_SOLICITUDES = { 17 export const ESTADOS_SOLICITUDES = {
21 finalizados: [ 18 finalizados: [
@@ -2629,13 +2629,12 @@ @@ -2629,13 +2629,12 @@
2629 } 2629 }
2630 }, 2630 },
2631 "buffer": { 2631 "buffer": {
2632 - "version": "4.9.1",  
2633 - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",  
2634 - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", 2632 + "version": "5.1.0",
  2633 + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz",
  2634 + "integrity": "sha512-YkIRgwsZwJWTnyQrsBTWefizHh+8GYj3kbL1BTiAQ/9pwpino0G7B2gp5tx/FUBqUlvtxV85KNR3mwfAtv15Yw==",
2635 "requires": { 2635 "requires": {
2636 "base64-js": "^1.0.2", 2636 "base64-js": "^1.0.2",
2637 - "ieee754": "^1.1.4",  
2638 - "isarray": "^1.0.0" 2637 + "ieee754": "^1.1.4"
2639 } 2638 }
2640 }, 2639 },
2641 "buffer-alloc": { 2640 "buffer-alloc": {
@@ -5157,8 +5156,7 @@ @@ -5157,8 +5156,7 @@
5157 }, 5156 },
5158 "safe-buffer": { 5157 "safe-buffer": {
5159 "version": "5.1.1", 5158 "version": "5.1.1",
5160 - "bundled": true,  
5161 - "optional": true 5159 + "bundled": true
5162 }, 5160 },
5163 "safer-buffer": { 5161 "safer-buffer": {
5164 "version": "2.1.2", 5162 "version": "2.1.2",
@@ -5250,8 +5248,7 @@ @@ -5250,8 +5248,7 @@
5250 }, 5248 },
5251 "yallist": { 5249 "yallist": {
5252 "version": "3.0.2", 5250 "version": "3.0.2",
5253 - "bundled": true,  
5254 - "optional": true 5251 + "bundled": true
5255 } 5252 }
5256 } 5253 }
5257 }, 5254 },
@@ -9890,6 +9887,18 @@ @@ -9890,6 +9887,18 @@
9890 "html-entities": "^1.2.0", 9887 "html-entities": "^1.2.0",
9891 "htmlparser2": "^3.9.0", 9888 "htmlparser2": "^3.9.0",
9892 "stream": "0.0.2" 9889 "stream": "0.0.2"
  9890 + },
  9891 + "dependencies": {
  9892 + "buffer": {
  9893 + "version": "4.9.1",
  9894 + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
  9895 + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
  9896 + "requires": {
  9897 + "base64-js": "^1.0.2",
  9898 + "ieee754": "^1.1.4",
  9899 + "isarray": "^1.0.0"
  9900 + }
  9901 + }
9893 } 9902 }
9894 }, 9903 },
9895 "react-native-safe-area-view": { 9904 "react-native-safe-area-view": {
@@ -12613,9 +12622,9 @@ @@ -12613,9 +12622,9 @@
12613 "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 12622 "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
12614 }, 12623 },
12615 "uuid": { 12624 "uuid": {
12616 - "version": "3.0.1",  
12617 - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",  
12618 - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" 12625 + "version": "3.2.1",
  12626 + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
  12627 + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
12619 }, 12628 },
12620 "uuid-js": { 12629 "uuid-js": {
12621 "version": "0.7.5", 12630 "version": "0.7.5",
@@ -12833,6 +12842,13 @@ @@ -12833,6 +12842,13 @@
12833 "pegjs": "^0.10.0", 12842 "pegjs": "^0.10.0",
12834 "simple-plist": "^0.2.1", 12843 "simple-plist": "^0.2.1",
12835 "uuid": "3.0.1" 12844 "uuid": "3.0.1"
  12845 + },
  12846 + "dependencies": {
  12847 + "uuid": {
  12848 + "version": "3.0.1",
  12849 + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
  12850 + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE="
  12851 + }
12836 } 12852 }
12837 }, 12853 },
12838 "xdl": { 12854 "xdl": {
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 "preset": "jest-expo" 20 "preset": "jest-expo"
21 }, 21 },
22 "dependencies": { 22 "dependencies": {
  23 + "buffer": "^5.1.0",
23 "elliptic": "^6.4.0", 24 "elliptic": "^6.4.0",
24 "expo": "^27.0.1", 25 "expo": "^27.0.1",
25 "moment": "^2.22.2", 26 "moment": "^2.22.2",
@@ -35,6 +36,7 @@ @@ -35,6 +36,7 @@
35 "redux": "^4.0.0", 36 "redux": "^4.0.0",
36 "redux-observable": "^0.19.0", 37 "redux-observable": "^0.19.0",
37 "redux-thunk": "^2.3.0", 38 "redux-thunk": "^2.3.0",
38 - "rxjs": "^5.0.0" 39 + "rxjs": "^5.0.0",
  40 + "uuid": "^3.2.1"
39 } 41 }
40 } 42 }
  1 +import EC from 'elliptic'
1 import { tap } from 'ramda' 2 import { tap } from 'ramda'
2 -import { SENATICS_URL } from '../../constants' 3 +import uuid from 'uuid/v1'
  4 +import { Buffer } from 'buffer/'
  5 +import { ownPrivate } from '../../constants/keys'
  6 +import { BACKEND_URL } from '../../constants'
  7 +
  8 +const ec = new EC.ec('secp256k1')
  9 +const clientPriv = ec.keyFromPrivate(ownPrivate)
3 10
4 export const ACCESS_TOKEN_REQUESTED = 'ACCESS_TOKEN_REQUESTED' 11 export const ACCESS_TOKEN_REQUESTED = 'ACCESS_TOKEN_REQUESTED'
5 export const accessTokenRequested = () => ({ 12 export const accessTokenRequested = () => ({
@@ -17,24 +24,19 @@ export const accessTokenReceived = (accessToken) => ({ @@ -17,24 +24,19 @@ export const accessTokenReceived = (accessToken) => ({
17 }) 24 })
18 25
19 26
20 -const ACCESS_TOKEN_URL = `${SENATICS_URL}/auth/token`  
21 -export const fetchToken = (token, secret) => (dispatch) => { 27 +export const fetchToken = () => (dispatch) => {
22 dispatch(accessTokenRequested()) 28 dispatch(accessTokenRequested())
23 -  
24 - const payload = {  
25 - clientSecret: secret  
26 - }  
27 - 29 + const nonce = uuid()
  30 + const firma = new Buffer(clientPriv.sign(nonce).toDER()).toString('hex')
28 const options = { 31 const options = {
29 - method: 'POST',  
30 - body: JSON.stringify(payload), 32 + method: 'GET',
31 headers: { 33 headers: {
32 Accept: 'application/json', 34 Accept: 'application/json',
33 'Content-Type': 'application/json', 35 'Content-Type': 'application/json',
34 - Authorization: `Basic ${token}`  
35 }, 36 },
36 } 37 }
37 38
  39 + const ACCESS_TOKEN_URL = `${BACKEND_URL}/token/${nonce}/${firma}`
38 const internal = () => fetch(ACCESS_TOKEN_URL, options) 40 const internal = () => fetch(ACCESS_TOKEN_URL, options)
39 .then(response => response.text()) 41 .then(response => response.text())
40 .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) 42 .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
@@ -6,9 +6,9 @@ import { fetchTipoRespuestas } from './tipoRespuestas' @@ -6,9 +6,9 @@ import { fetchTipoRespuestas } from './tipoRespuestas'
6 import { comprobarExistenciaUsuarioLocal } from './usuario' 6 import { comprobarExistenciaUsuarioLocal } from './usuario'
7 7
8 export const INICIALIZAR_DATOS = 'INICIALIZAR_DATOS' 8 export const INICIALIZAR_DATOS = 'INICIALIZAR_DATOS'
9 -export const inicializarDatos = (authToken, secret) => 9 +export const inicializarDatos = () =>
10 (dispatch, getState) => 10 (dispatch, getState) =>
11 - dispatch(fetchToken(authToken, secret)) 11 + dispatch(fetchToken())
12 .then(() => { 12 .then(() => {
13 const accessToken = getState().autenticacion.token 13 const accessToken = getState().autenticacion.token
14 return Promise.all([ 14 return Promise.all([
  1 +import EC from 'elliptic'
1 import { Permissions, Location } from 'expo' 2 import { Permissions, Location } from 'expo'
  3 +import { tap } from 'ramda'
  4 +import { Buffer } from 'buffer/'
  5 +import { ownPrivate } from '../../constants/keys'
  6 +import { BACKEND_URL } from '../../constants'
  7 +
  8 +const ec = new EC.ec('secp256k1')
  9 +const clientPriv = ec.keyFromPrivate(ownPrivate)
2 10
3 export const LOCATION_PERMISSION_REQUESTED = 'LOCATION_PERMISSION_REQUESTED' 11 export const LOCATION_PERMISSION_REQUESTED = 'LOCATION_PERMISSION_REQUESTED'
4 export const locationPermissionRequested = () => ({ 12 export const locationPermissionRequested = () => ({
@@ -6,8 +14,9 @@ export const locationPermissionRequested = () => ({ @@ -6,8 +14,9 @@ export const locationPermissionRequested = () => ({
6 }) 14 })
7 15
8 export const LOCATION_PERMISSION_GRANTED = 'LOCATION_PERMISSION_GRANTED' 16 export const LOCATION_PERMISSION_GRANTED = 'LOCATION_PERMISSION_GRANTED'
9 -export const locationPermissionGranted = () => ({  
10 - type: LOCATION_PERMISSION_GRANTED 17 +export const locationPermissionGranted = (solicitud) => ({
  18 + type: LOCATION_PERMISSION_GRANTED,
  19 + solicitud
11 }) 20 })
12 21
13 export const LOCATION_PERMISSION_DENIED = 'LOCATION_PERMISSION_DENIED' 22 export const LOCATION_PERMISSION_DENIED = 'LOCATION_PERMISSION_DENIED'
@@ -21,12 +30,12 @@ export const locationPermissionFailed = (error) => ({ @@ -21,12 +30,12 @@ export const locationPermissionFailed = (error) => ({
21 error 30 error
22 }) 31 })
23 32
24 -export const requestLocationPermission = () => (dispatch) => { 33 +export const requestLocationPermission = (solicitud) => (dispatch) => {
25 dispatch(locationPermissionRequested()) 34 dispatch(locationPermissionRequested())
26 return Permissions.askAsync(Permissions.LOCATION) 35 return Permissions.askAsync(Permissions.LOCATION)
27 .then(({ status }) => { 36 .then(({ status }) => {
28 if (status === 'granted') { 37 if (status === 'granted') {
29 - return dispatch(locationPermissionGranted()) 38 + return dispatch(locationPermissionGranted(solicitud))
30 } 39 }
31 return dispatch(locationPermissionDenied()) 40 return dispatch(locationPermissionDenied())
32 }) 41 })
@@ -40,9 +49,10 @@ export const locationRequested = () => ({ @@ -40,9 +49,10 @@ export const locationRequested = () => ({
40 }) 49 })
41 50
42 export const LOCATION_RECEIVED = 'LOCATION_RECEIVED' 51 export const LOCATION_RECEIVED = 'LOCATION_RECEIVED'
43 -export const locationReceived = (location) => ({ 52 +export const locationReceived = ({ location, solicitud }) => ({
44 type: LOCATION_RECEIVED, 53 type: LOCATION_RECEIVED,
45 - location 54 + location,
  55 + solicitud
46 }) 56 })
47 57
48 export const LOCATION_FAILED = 'LOCATION_FAILED' 58 export const LOCATION_FAILED = 'LOCATION_FAILED'
@@ -51,9 +61,53 @@ export const locationFailed = (error) => ({ @@ -51,9 +61,53 @@ export const locationFailed = (error) => ({
51 error 61 error
52 }) 62 })
53 63
54 -export const requestLocation = () => (dispatch) => { 64 +export const requestLocation = (solicitud) => (dispatch) => {
55 dispatch(locationRequested()) 65 dispatch(locationRequested())
56 Location.getCurrentPositionAsync({}) 66 Location.getCurrentPositionAsync({})
57 - .then(location => dispatch(locationReceived(location))) 67 + .then(location => dispatch(locationReceived({ location, solicitud })))
58 .catch(error => dispatch(locationFailed(error))) 68 .catch(error => dispatch(locationFailed(error)))
59 } 69 }
  70 +
  71 +
  72 +export const LOCATION_POSTED = 'LOCATION_POSTED'
  73 +export const locationPosted = () => ({
  74 + type: LOCATION_POSTED
  75 +})
  76 +export const LOCATION_POST_FAILED = 'LOCATION_POST_FAILED'
  77 +export const locationPostFailed = (error) => ({
  78 + type: LOCATION_POST_FAILED,
  79 + error
  80 +})
  81 +export const LOCATION_POST_SUCCESS = 'LOCATION_POST_SUCCESS'
  82 +export const locationPostSuccess = (result) => ({
  83 + type: LOCATION_POST_SUCCESS,
  84 + result
  85 +})
  86 +
  87 +
  88 +export const postLocation = (location, solicitud) => (dispatch) => {
  89 + dispatch(locationPosted())
  90 + const message = JSON.stringify({ location, solicitud })
  91 + const firma = new Buffer(clientPriv.sign(message).toDER()).toString('hex')
  92 + const options = {
  93 + method: 'POST',
  94 + body: message,
  95 + headers: {
  96 + Accept: 'application/json',
  97 + 'Content-Type': 'application/json',
  98 + },
  99 + }
  100 +
  101 + const url = `${BACKEND_URL}/solicitudes/ubicacion/${firma}`
  102 +
  103 + const internal = () => fetch(url, options)
  104 + .then(response => response.text())
  105 + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
  106 + .then(JSON.parse)
  107 + .then(json => {
  108 + if (json.error) return dispatch(locationPostFailed(json.error))
  109 + return dispatch(locationPostSuccess(json))
  110 + })
  111 + .catch(error => dispatch(locationPostFailed(error)))
  112 + return internal()
  113 +}
  1 +import EC from 'elliptic'
  2 +import { tap } from 'ramda'
  3 +import { Buffer } from 'buffer/'
  4 +import { BACKEND_URL } from '../../constants'
  5 +import { ownPrivate } from '../../constants/keys'
  6 +
  7 +const ec = new EC.ec('secp256k1')
  8 +const clientPriv = ec.keyFromPrivate(ownPrivate)
  9 +
  10 +export const REPORTE_REQUESTED = 'REPORTE_REQUESTED'
  11 +export const reporteRequested = () => ({
  12 + type: REPORTE_REQUESTED
  13 +})
  14 +
  15 +export const REPORTE_RECEIVED = 'REPORTE_RECEIVED'
  16 +export const reporteReceived = ({ reporte }) => ({
  17 + type: REPORTE_RECEIVED,
  18 + reporte,
  19 +})
  20 +
  21 +export const REPORTE_FAILED = 'REPORTE_FAILED'
  22 +export const reporteFailed = (error) => ({
  23 + type: REPORTE_FAILED,
  24 + error
  25 +})
  26 +
  27 +export const requestReporte = (id, email) => (dispatch) => {
  28 + dispatch(reporteRequested())
  29 + const url = `${BACKEND_URL}/reportes/solicitud/${id}/usuario/${email}/`
  30 + const options = {
  31 + method: 'GET',
  32 + headers: {
  33 + Accept: 'application/json',
  34 + },
  35 + }
  36 +
  37 + return fetch(url, options)
  38 + .then(response => response.text())
  39 + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
  40 + .then(JSON.parse)
  41 + .then(json => dispatch(reporteReceived(json)))
  42 + .catch(error => dispatch(reporteFailed(error)))
  43 +}
  44 +
  45 +
  46 +export const REPORTE_POSTED = 'REPORTE_POSTED'
  47 +export const reportePosted = (reporte) => ({
  48 + type: REPORTE_POSTED,
  49 + reporte
  50 +})
  51 +export const REPORTE_POST_FAILED = 'REPORTE_POST_FAILED'
  52 +export const reportePostFailed = () => ({
  53 + type: REPORTE_POST_FAILED
  54 +})
  55 +export const REPORTE_POST_SUCCESS = 'REPORTE_POST_SUCCESS'
  56 +export const reportePostSuccess = (result) => ({
  57 + type: REPORTE_POST_SUCCESS,
  58 + result
  59 +})
  60 +
  61 +
  62 +export const postReporte = (solicitudId, usuario, reporte) => (dispatch) => {
  63 + dispatch(reportePosted(reporte))
  64 + const message = JSON.stringify({ reporte, usuario })
  65 + const firma = new Buffer(clientPriv.sign(message).toDER()).toString('hex')
  66 +
  67 + const options = {
  68 + method: 'POST',
  69 + body: message,
  70 + headers: {
  71 + Accept: 'application/json',
  72 + 'Content-Type': 'application/json',
  73 + },
  74 + }
  75 +
  76 +
  77 + const url = `${BACKEND_URL}/solicitudes/${solicitudId}/reporte/${firma}`
  78 +
  79 + const internal = () => fetch(url, options)
  80 + .then(response => response.text())
  81 + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
  82 + .then(JSON.parse)
  83 + .then(json => {
  84 + if (json.error) return dispatch(reportePostFailed(json.error))
  85 + return dispatch(reportePostSuccess(json))
  86 + })
  87 + .catch(error => dispatch(reportePostFailed(error)))
  88 + return internal()
  89 +}
@@ -100,8 +100,9 @@ export const fetchFlujo = (token, solicitudId) => ( @@ -100,8 +100,9 @@ export const fetchFlujo = (token, solicitudId) => (
100 100
101 101
102 export const SOLICITUD_POSTED = 'SOLICITUD_POSTED' 102 export const SOLICITUD_POSTED = 'SOLICITUD_POSTED'
103 -export const solicitudPosted = () => ({  
104 - type: SOLICITUD_POSTED 103 +export const solicitudPosted = (solicitud) => ({
  104 + type: SOLICITUD_POSTED,
  105 + solicitud
105 }) 106 })
106 export const SOLICITUD_POST_FAILED = 'SOLICITUD_POST_FAILED' 107 export const SOLICITUD_POST_FAILED = 'SOLICITUD_POST_FAILED'
107 export const solicitudPostFailed = () => ({ 108 export const solicitudPostFailed = () => ({
@@ -124,7 +125,7 @@ export const notifySolicitud = ({ titulo, institucion }) => () => @@ -124,7 +125,7 @@ export const notifySolicitud = ({ titulo, institucion }) => () =>
124 }) 125 })
125 126
126 export const postSolicitud = (token, solicitud) => (dispatch) => { 127 export const postSolicitud = (token, solicitud) => (dispatch) => {
127 - dispatch(solicitudPosted()) 128 + dispatch(solicitudPosted(solicitud))
128 const options = { 129 const options = {
129 method: 'POST', 130 method: 'POST',
130 body: JSON.stringify(solicitud), 131 body: JSON.stringify(solicitud),
@@ -142,7 +143,10 @@ export const postSolicitud = (token, solicitud) => (dispatch) => { @@ -142,7 +143,10 @@ export const postSolicitud = (token, solicitud) => (dispatch) => {
142 .then(response => response.text()) 143 .then(response => response.text())
143 .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text }))) 144 .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
144 .then(JSON.parse) 145 .then(JSON.parse)
145 - .then(json => dispatch(solicitudPostSuccess(json))) 146 + .then(json => {
  147 + if (json.error) return dispatch(solicitudPostFailed(json.error))
  148 + return dispatch(solicitudPostSuccess(json))
  149 + })
146 .catch(error => dispatch(solicitudPostFailed(error))) 150 .catch(error => dispatch(solicitudPostFailed(error)))
147 return internal() 151 return internal()
148 } 152 }
  1 +import EC from 'elliptic'
  2 +import { tap } from 'ramda'
  3 +import { Buffer } from 'buffer/'
  4 +import { BACKEND_URL } from '../../constants'
  5 +import { ownPrivate } from '../../constants/keys'
  6 +
  7 +const ec = new EC.ec('secp256k1')
  8 +const clientPriv = ec.keyFromPrivate(ownPrivate)
  9 +
  10 +export const VALORACION_REQUESTED = 'VALORACION_REQUESTED'
  11 +export const valoracionRequested = () => ({
  12 + type: VALORACION_REQUESTED
  13 +})
  14 +
  15 +export const VALORACION_RECEIVED = 'VALORACION_RECEIVED'
  16 +export const valoracionReceived = ({ valoracion }) => ({
  17 + type: VALORACION_RECEIVED,
  18 + valoracion,
  19 +})
  20 +
  21 +export const VALORACION_FAILED = 'VALORACION_FAILED'
  22 +export const valoracionFailed = (error) => ({
  23 + type: VALORACION_FAILED,
  24 + error
  25 +})
  26 +
  27 +export const requestValoracion = (id, email) => (dispatch) => {
  28 + dispatch(valoracionRequested())
  29 + const url = `${BACKEND_URL}/valoraciones/solicitud/${id}/usuario/${email}/`
  30 + const options = {
  31 + method: 'GET',
  32 + headers: {
  33 + Accept: 'application/json',
  34 + },
  35 + }
  36 +
  37 + return fetch(url, options)
  38 + .then(response => response.text())
  39 + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
  40 + .then(JSON.parse)
  41 + .then(json => dispatch(valoracionReceived(json)))
  42 + .catch(error => dispatch(valoracionFailed(error)))
  43 +}
  44 +
  45 +
  46 +export const VALORACION_POSTED = 'VALORACION_POSTED'
  47 +export const valoracionPosted = (valoracion) => ({
  48 + type: VALORACION_POSTED,
  49 + valoracion
  50 +})
  51 +export const VALORACION_POST_FAILED = 'VALORACION_POST_FAILED'
  52 +export const valoracionPostFailed = () => ({
  53 + type: VALORACION_POST_FAILED
  54 +})
  55 +export const VALORACION_POST_SUCCESS = 'VALORACION_POST_SUCCESS'
  56 +export const valoracionPostSuccess = (result) => ({
  57 + type: VALORACION_POST_SUCCESS,
  58 + result
  59 +})
  60 +
  61 +
  62 +export const postValoracion = (solicitudId, usuario, valoracion) => (dispatch) => {
  63 + dispatch(valoracionPosted(valoracion))
  64 + const message = JSON.stringify({ valoracion, usuario })
  65 + const firma = new Buffer(clientPriv.sign(message).toDER()).toString('hex')
  66 +
  67 + const options = {
  68 + method: 'POST',
  69 + body: message,
  70 + headers: {
  71 + Accept: 'application/json',
  72 + 'Content-Type': 'application/json',
  73 + },
  74 + }
  75 +
  76 +
  77 + const url = `${BACKEND_URL}/solicitudes/${solicitudId}/valoracion/${firma}`
  78 +
  79 + const internal = () => fetch(url, options)
  80 + .then(response => response.text())
  81 + .then(tap(text => dispatch({ type: 'TEXT_RECEIVED', text })))
  82 + .then(JSON.parse)
  83 + .then(json => {
  84 + if (json.error) return dispatch(valoracionPostFailed(json.error))
  85 + return dispatch(valoracionPostSuccess(json))
  86 + })
  87 + .catch(error => dispatch(valoracionPostFailed(error)))
  88 + return internal()
  89 +}
  1 +import {
  2 + ACCESS_TOKEN_RECEIVED,
  3 + fetchToken
  4 +} from '../actions/autenticacion'
  5 +
  6 +export const renewToken = (action$) =>
  7 + action$.ofType(ACCESS_TOKEN_RECEIVED)
  8 + .delay(60000)
  9 + .map(fetchToken)
@@ -11,6 +11,10 @@ import { @@ -11,6 +11,10 @@ import {
11 } from './logger' 11 } from './logger'
12 12
13 import { 13 import {
  14 + renewToken
  15 +} from './autenticacion'
  16 +
  17 +import {
14 askLocationOnPost, 18 askLocationOnPost,
15 getLocationOnGrant, 19 getLocationOnGrant,
16 postLocationOnReceive, 20 postLocationOnReceive,
@@ -28,5 +32,6 @@ export default combineEpics( @@ -28,5 +32,6 @@ export default combineEpics(
28 postLocationOnReceive, 32 postLocationOnReceive,
29 searchDebounce, 33 searchDebounce,
30 changePage, 34 changePage,
31 - getUserIfExists 35 + getUserIfExists,
  36 + renewToken
32 ) 37 )
@@ -5,19 +5,19 @@ import { @@ -5,19 +5,19 @@ import {
5 import { 5 import {
6 requestLocation, 6 requestLocation,
7 requestLocationPermission, 7 requestLocationPermission,
  8 + postLocation,
8 LOCATION_PERMISSION_GRANTED, 9 LOCATION_PERMISSION_GRANTED,
9 LOCATION_RECEIVED 10 LOCATION_RECEIVED
10 } from '../actions/location' 11 } from '../actions/location'
11 12
12 export const askLocationOnPost = (action$) => 13 export const askLocationOnPost = (action$) =>
13 action$.ofType(SOLICITUD_POSTED) 14 action$.ofType(SOLICITUD_POSTED)
14 - .map(requestLocationPermission) 15 + .map(action => requestLocationPermission(action.solicitud))
15 16
16 export const getLocationOnGrant = (action$) => 17 export const getLocationOnGrant = (action$) =>
17 action$.ofType(LOCATION_PERMISSION_GRANTED) 18 action$.ofType(LOCATION_PERMISSION_GRANTED)
18 - .map(requestLocation) 19 + .map(action => requestLocation(action.solicitud))
19 20
20 export const postLocationOnReceive = (action$) => 21 export const postLocationOnReceive = (action$) =>
21 action$.ofType(LOCATION_RECEIVED) 22 action$.ofType(LOCATION_RECEIVED)
22 - .do(console.log)  
23 - .ignoreElements() 23 + .map(action => postLocation(action.location, action.solicitud))
@@ -29,8 +29,3 @@ export const searchDebounce = (action$, store) => @@ -29,8 +29,3 @@ export const searchDebounce = (action$, store) =>
29 export const changePage = (action$, store) => 29 export const changePage = (action$, store) =>
30 action$.ofType(CAMBIAR_PAGINA_SOLICITUD) 30 action$.ofType(CAMBIAR_PAGINA_SOLICITUD)
31 .map(() => fetchSolicitudes(getToken(store), getBusqueda(store))) 31 .map(() => fetchSolicitudes(getToken(store), getBusqueda(store)))
32 -  
33 -export const logAll = (action$) =>  
34 - action$  
35 - .do(console.log)  
36 - .ignoreElements()  
@@ -78,4 +78,3 @@ export const getUserIfExists = (action$, store) => @@ -78,4 +78,3 @@ export const getUserIfExists = (action$, store) =>
78 seleccionarDepartamento(distrito.departamento.id) 78 seleccionarDepartamento(distrito.departamento.id)
79 ]) 79 ])
80 }) 80 })
81 - .do(console.log)  
@@ -3,6 +3,7 @@ import { merge } from 'ramda' @@ -3,6 +3,7 @@ import { merge } from 'ramda'
3 import { 3 import {
4 REQUEST_FORMATOS, 4 REQUEST_FORMATOS,
5 RECEIVE_FORMATOS, 5 RECEIVE_FORMATOS,
  6 + ERROR_FORMATOS
6 } from '../actions/formatos' 7 } from '../actions/formatos'
7 8
8 9
@@ -22,6 +23,10 @@ export default (state, action) => { @@ -22,6 +23,10 @@ export default (state, action) => {
22 return merge( 23 return merge(
23 state, 24 state,
24 { loading: false, data: action.formatos, pages: action.pages }) 25 { loading: false, data: action.formatos, pages: action.pages })
  26 + case ERROR_FORMATOS:
  27 + return merge(
  28 + state,
  29 + { loading: false, data: [], pages: null })
25 default: 30 default:
26 return state || formatos 31 return state || formatos
27 } 32 }
@@ -9,6 +9,8 @@ import tipoRespuestas from './tipoRespuestas' @@ -9,6 +9,8 @@ import tipoRespuestas from './tipoRespuestas'
9 import usuario from './usuario' 9 import usuario from './usuario'
10 import events from './events' 10 import events from './events'
11 import auxiliares from './auxiliares' 11 import auxiliares from './auxiliares'
  12 +import valoracion from './valoraciones'
  13 +import reporte from './reportes'
12 14
13 15
14 export default combineReducers({ 16 export default combineReducers({
@@ -21,5 +23,7 @@ export default combineReducers({ @@ -21,5 +23,7 @@ export default combineReducers({
21 tipoRespuestas, 23 tipoRespuestas,
22 usuario, 24 usuario,
23 events, 25 events,
24 - auxiliares 26 + auxiliares,
  27 + reporte,
  28 + valoracion
25 }) 29 })
  1 +import { merge } from 'ramda'
  2 +
  3 +import {
  4 + REPORTE_REQUESTED,
  5 + REPORTE_RECEIVED,
  6 + REPORTE_FAILED,
  7 + REPORTE_POST_SUCCESS,
  8 + REPORTE_POSTED,
  9 +} from '../actions/reportes'
  10 +
  11 +
  12 +const reporte = {
  13 + data: [],
  14 + loading: true,
  15 + error: null
  16 +}
  17 +
  18 +export default (state, action) => {
  19 + switch (action.type) {
  20 + case REPORTE_REQUESTED:
  21 + return merge(state, reporte)
  22 + case REPORTE_RECEIVED:
  23 + return merge(state, { loading: false, error: null, data: action.reporte })
  24 + case REPORTE_POSTED:
  25 + return merge(state, { data: action.reporte })
  26 + case REPORTE_POST_SUCCESS:
  27 + return merge(state, { data: action.result.reporte })
  28 + case REPORTE_FAILED:
  29 + return merge(state, { loading: false, data: null, error: action.error })
  30 + default:
  31 + return state || reporte
  32 + }
  33 +}
1 -import { merge, mergeAll, filter, contains, mergeDeepRight } from 'ramda' 1 +import {
  2 + contains,
  3 + filter,
  4 + merge,
  5 + mergeDeepRight,
  6 + mergeAll,
  7 +} from 'ramda'
2 8
3 import { 9 import {
4 SOLICITUDES_REQUESTED, 10 SOLICITUDES_REQUESTED,
5 SOLICITUDES_RECEIVED, 11 SOLICITUDES_RECEIVED,
6 SOLICITUDES_FAILED, 12 SOLICITUDES_FAILED,
7 VER_DETALLE_SOLICITUD, 13 VER_DETALLE_SOLICITUD,
8 - FLUJOS_RECEIVED, FLUJOS_REQUESTED, 14 + FLUJOS_RECEIVED, FLUJOS_REQUESTED, FLUJOS_FAILED,
9 SOLICITUD_POST_SUCCESS, 15 SOLICITUD_POST_SUCCESS,
10 SOLICITUD_POST_FAILED, 16 SOLICITUD_POST_FAILED,
11 SOLICITUD_POSTED, 17 SOLICITUD_POSTED,
@@ -84,6 +90,9 @@ export default (state, action) => { @@ -84,6 +90,9 @@ export default (state, action) => {
84 case FLUJOS_RECEIVED: 90 case FLUJOS_RECEIVED:
85 return merge(state, { flujos: { loading: false, datos: action.flujos } }) 91 return merge(state, { flujos: { loading: false, datos: action.flujos } })
86 92
  93 + case FLUJOS_FAILED:
  94 + return merge(state, { flujos: { loading: false, datos: [], error: action.error } })
  95 +
87 case SOLICITUD_POST_SUCCESS: 96 case SOLICITUD_POST_SUCCESS:
88 return merge(state, { post: { loading: false, error: null, result: action.result } }) 97 return merge(state, { post: { loading: false, error: null, result: action.result } })
89 98
@@ -3,6 +3,7 @@ import { merge } from 'ramda' @@ -3,6 +3,7 @@ import { merge } from 'ramda'
3 import { 3 import {
4 REQUEST_SOPORTES, 4 REQUEST_SOPORTES,
5 RECEIVE_SOPORTES, 5 RECEIVE_SOPORTES,
  6 + ERROR_SOPORTES
6 } from '../actions/soportes' 7 } from '../actions/soportes'
7 8
8 9
@@ -22,6 +23,10 @@ export default (state, action) => { @@ -22,6 +23,10 @@ export default (state, action) => {
22 return merge( 23 return merge(
23 state, 24 state,
24 { loading: false, data: action.soportes, pages: action.pages }) 25 { loading: false, data: action.soportes, pages: action.pages })
  26 + case ERROR_SOPORTES:
  27 + return merge(
  28 + state,
  29 + { loading: false, data: [], pages: null })
25 default: 30 default:
26 return state || soportes 31 return state || soportes
27 } 32 }
@@ -3,6 +3,7 @@ import { merge } from 'ramda' @@ -3,6 +3,7 @@ import { merge } from 'ramda'
3 import { 3 import {
4 REQUEST_TIPO_RESPUESTAS, 4 REQUEST_TIPO_RESPUESTAS,
5 RECEIVE_TIPO_RESPUESTAS, 5 RECEIVE_TIPO_RESPUESTAS,
  6 + ERROR_TIPO_RESPUESTAS,
6 } from '../actions/tipoRespuestas' 7 } from '../actions/tipoRespuestas'
7 8
8 9
@@ -22,6 +23,10 @@ export default (state, action) => { @@ -22,6 +23,10 @@ export default (state, action) => {
22 return merge( 23 return merge(
23 state, 24 state,
24 { loading: false, data: action.tipoRespuestas, pages: action.pages }) 25 { loading: false, data: action.tipoRespuestas, pages: action.pages })
  26 + case ERROR_TIPO_RESPUESTAS:
  27 + return merge(
  28 + state,
  29 + { loading: false, data: [], pages: null })
25 default: 30 default:
26 return state || tipoRespuestas 31 return state || tipoRespuestas
27 } 32 }
  1 +import { merge } from 'ramda'
  2 +
  3 +import {
  4 + VALORACION_REQUESTED,
  5 + VALORACION_RECEIVED,
  6 + VALORACION_FAILED,
  7 + VALORACION_POSTED,
  8 + VALORACION_POST_SUCCESS
  9 +} from '../actions/valoraciones'
  10 +
  11 +
  12 +const valoracion = {
  13 + data: null,
  14 + loading: true,
  15 + error: null
  16 +}
  17 +
  18 +const toggle = (state, val) => {
  19 + if (state.valoracion === val) {
  20 + return null
  21 + }
  22 + return val
  23 +}
  24 +
  25 +export default (state, action) => {
  26 + switch (action.type) {
  27 + case VALORACION_REQUESTED:
  28 + return merge(state, valoracion)
  29 + case VALORACION_POSTED:
  30 + return merge(state, { data: toggle(state, action.valoracion) })
  31 + case VALORACION_POST_SUCCESS:
  32 + return merge(state, { data: action.result.valoracion })
  33 + case VALORACION_RECEIVED:
  34 + return merge(state, { loading: false, error: null, data: action.valoracion })
  35 + case VALORACION_FAILED:
  36 + return merge(state, { loading: false, data: null, error: action.error })
  37 + default:
  38 + return state || valoracion
  39 + }
  40 +}
1 -import 'moment/locale/es'  
2 import React, { Component } from 'react' 1 import React, { Component } from 'react'
3 -import { View, Text } from 'react-native' 2 +import { Button } from 'react-native-elements'
  3 +import { View, Text, Linking } from 'react-native'
4 import { connect } from 'react-redux' 4 import { connect } from 'react-redux'
  5 +
  6 +import {
  7 + PORTAL_DENUNCIAS_URL,
  8 + TUTORIAL_AIF_URL,
  9 + TUTORIAL_APP
  10 +} from '../../constants'
  11 +
5 import css from './style' 12 import css from './style'
6 // AIP Movil 13 // AIP Movil
7 14
8 -class Estadistica extends Component {  
9 - static navigationOptions = () => ({ 15 +class Ayuda extends Component {
  16 + static navigationOptions = ({ navigation }) => ({
10 title: 'Ayuda', 17 title: 'Ayuda',
11 headerStyle: css.headerStyle, 18 headerStyle: css.headerStyle,
12 - headerTitleStyle: css.headerTitleStyle 19 + headerTitleStyle: css.headerTitleStyle,
  20 + headerLeft:
  21 + <Button
  22 + icon={{ name: 'menu', size: 27, color: 'white' }}
  23 + buttonStyle={{ backgroundColor: 'transparent' }}
  24 + onPress={() => navigation.toggleDrawer()}
  25 + />
13 }); 26 });
  27 + myHandlePress = (link) => () => {
  28 + Linking.openURL(link)
  29 + }
14 30
15 31
16 render() { 32 render() {
17 return ( 33 return (
18 - <View style={[css.pane, css.fixStatusBar]}>  
19 - <Text> AYUDA </Text> 34 + <View style={[css.pane, css.distribute]}>
  35 + <View>
  36 + <Text style={css.label}>
  37 + ¿Quieres saber más?
  38 + </Text>
  39 + <Button
  40 + buttonStyle={css.btn}
  41 + onPress={this.myHandlePress(TUTORIAL_AIF_URL)}
  42 + title="Ver Tutorial de Información Pública"
  43 + />
  44 + </View>
  45 + <View>
  46 + <Text style={css.label}>
  47 + Aun no sé como usar la App
  48 + </Text>
  49 + <Button
  50 + buttonStyle={css.btn}
  51 + onPress={this.myHandlePress(TUTORIAL_APP)}
  52 + title="¿Cómo usar la App?"
  53 + />
  54 + </View>
  55 + <View>
  56 + <Text style={css.label}>
  57 + No quiero información... Quiero Denunciar!
  58 + </Text>
  59 + <Button
  60 + buttonStyle={css.btn}
  61 + onPress={this.myHandlePress(PORTAL_DENUNCIAS_URL)}
  62 + title="Ir al Portal de Denuncias"
  63 + />
  64 + </View>
20 </View> 65 </View>
21 ) 66 )
22 } 67 }
@@ -28,4 +73,4 @@ const mapStateToProps = () => ({ @@ -28,4 +73,4 @@ const mapStateToProps = () => ({
28 const mapDispatchToProps = () => ({ 73 const mapDispatchToProps = () => ({
29 }) 74 })
30 75
31 -export default connect(mapStateToProps, mapDispatchToProps)(Estadistica) 76 +export default connect(mapStateToProps, mapDispatchToProps)(Ayuda)
1 import { StyleSheet } from 'react-native' 1 import { StyleSheet } from 'react-native'
2 import { merge } from 'ramda' 2 import { merge } from 'ramda'
3 3
4 -import styles from '../../common/styles' 4 +import styles, { colors } from '../../common/styles'
5 5
6 export default merge(StyleSheet.create({ 6 export default merge(StyleSheet.create({
7 - 7 + distribute: {
  8 + justifyContent: 'space-evenly',
  9 + },
  10 + btn: {
  11 + backgroundColor: colors.primary,
  12 + margin: 10,
  13 + },
8 }), styles) 14 }), styles)
@@ -29,8 +29,6 @@ const navegarSiguiente = (self, texto) => { @@ -29,8 +29,6 @@ const navegarSiguiente = (self, texto) => {
29 29
30 if (validateEmail(texto)) { 30 if (validateEmail(texto)) {
31 self.props.navigation.dispatch(pushAction) 31 self.props.navigation.dispatch(pushAction)
32 - } else {  
33 - console.log('no pasar')  
34 } 32 }
35 } 33 }
36 34
@@ -35,8 +35,6 @@ const navegarSiguiente = (self, requeridos) => { @@ -35,8 +35,6 @@ const navegarSiguiente = (self, requeridos) => {
35 if (validateNext(requeridos)) { 35 if (validateNext(requeridos)) {
36 self.props.navigation.dispatch(resetAction) 36 self.props.navigation.dispatch(resetAction)
37 self.props.guardarUsuarioLocal(self.props.usuario) 37 self.props.guardarUsuarioLocal(self.props.usuario)
38 - } else {  
39 - console.log('escribir mensajes de validacion')  
40 } 38 }
41 } 39 }
42 40
@@ -7,18 +7,25 @@ import { @@ -7,18 +7,25 @@ import {
7 } from 'react-native' 7 } from 'react-native'
8 import { connect } from 'react-redux' 8 import { connect } from 'react-redux'
9 import { HeaderBackButton } from 'react-navigation' 9 import { HeaderBackButton } from 'react-navigation'
10 -import { map } from 'ramda'  
11 - 10 +import { map, contains } from 'ramda'
12 import { Card, Divider, Text, Button } from 'react-native-elements' 11 import { Card, Divider, Text, Button } from 'react-native-elements'
13 import HTML from 'react-native-render-html' 12 import HTML from 'react-native-render-html'
14 13
15 -import { INFO_PY_URL } from '../../constants' 14 +import { INFO_PY_URL, ESTADOS_SOLICITUDES } from '../../constants'
16 import { fetchFlujo } from '../../redux/actions/solicitudes' 15 import { fetchFlujo } from '../../redux/actions/solicitudes'
  16 +import { requestValoracion } from '../../redux/actions/valoraciones'
  17 +import { requestReporte } from '../../redux/actions/reportes'
  18 +
17 import css from './style' 19 import css from './style'
18 import DefaultIndicator from '../../components/DefaultIndicator' 20 import DefaultIndicator from '../../components/DefaultIndicator'
  21 +import BotonValoracion from '../../components/BotonValoracion'
19 22
20 const makeSolicitudURL = (solicitud) => `${INFO_PY_URL}/#!/ciudadano/solicitud/${solicitud.id}` 23 const makeSolicitudURL = (solicitud) => `${INFO_PY_URL}/#!/ciudadano/solicitud/${solicitud.id}`
21 24
  25 +const esFinal = (solicitud) => contains(
  26 + solicitud.estado.nombre,
  27 + ESTADOS_SOLICITUDES.finalizados)
  28 +
22 class PaginaDetalle extends Component { 29 class PaginaDetalle extends Component {
23 static navigationOptions = ({ navigation }) => ({ 30 static navigationOptions = ({ navigation }) => ({
24 title: 'Detalles de solicitud', 31 title: 'Detalles de solicitud',
@@ -37,6 +44,8 @@ class PaginaDetalle extends Component { @@ -37,6 +44,8 @@ class PaginaDetalle extends Component {
37 44
38 componentDidMount() { 45 componentDidMount() {
39 this.props.fetchFlujo(this.props.token, this.props.solicitud.id) 46 this.props.fetchFlujo(this.props.token, this.props.solicitud.id)
  47 + this.props.requestValoracion(this.props.solicitud.id, this.props.miUsuario.mail)
  48 + this.props.requestReporte(this.props.solicitud.id, this.props.miUsuario.mail)
40 } 49 }
41 50
42 render() { 51 render() {
@@ -84,6 +93,11 @@ class PaginaDetalle extends Component { @@ -84,6 +93,11 @@ class PaginaDetalle extends Component {
84 </Card> 93 </Card>
85 {props.flujos.loading ? spinner : flujos(props.flujos.datos)} 94 {props.flujos.loading ? spinner : flujos(props.flujos.datos)}
86 </ScrollView> 95 </ScrollView>
  96 + <BotonValoracion
  97 + mostrar={esFinal(props.solicitud)}
  98 + reporte={props.reporte}
  99 + valoracion={props.valoracion}
  100 + />
87 </View> 101 </View>
88 ) 102 )
89 } 103 }
@@ -94,10 +108,15 @@ const mapStateToProps = (state) => ({ @@ -94,10 +108,15 @@ const mapStateToProps = (state) => ({
94 token: state.autenticacion.token, 108 token: state.autenticacion.token,
95 flujos: state.solicitudes.flujos, 109 flujos: state.solicitudes.flujos,
96 usuario: state.solicitudes.current.usuario, 110 usuario: state.solicitudes.current.usuario,
  111 + miUsuario: state.usuario.datos,
  112 + valoracion: state.valoracion,
  113 + repote: state.reporte
97 }) 114 })
98 115
99 const mapDispatchToProps = dispatch => ({ 116 const mapDispatchToProps = dispatch => ({
100 - fetchFlujo: (token, solicitudId) => dispatch(fetchFlujo(token, solicitudId)) 117 + fetchFlujo: (token, solicitudId) => dispatch(fetchFlujo(token, solicitudId)),
  118 + requestValoracion: (solicitud, usuario) => dispatch(requestValoracion(solicitud, usuario)),
  119 + requestReporte: (solicitud, usuario) => dispatch(requestReporte(solicitud, usuario))
101 }) 120 })
102 121
103 export default connect(mapStateToProps, mapDispatchToProps)(PaginaDetalle) 122 export default connect(mapStateToProps, mapDispatchToProps)(PaginaDetalle)
@@ -22,8 +22,6 @@ const navegarSiguiente = (self, requeridos) => { @@ -22,8 +22,6 @@ const navegarSiguiente = (self, requeridos) => {
22 22
23 if (validateNext(requeridos)) { 23 if (validateNext(requeridos)) {
24 self.props.navigation.dispatch(pushAction) 24 self.props.navigation.dispatch(pushAction)
25 - } else {  
26 - console.log('no pasar')  
27 } 25 }
28 } 26 }
29 27
@@ -33,12 +33,10 @@ const makePicker = (onChange, dato, current) => ( @@ -33,12 +33,10 @@ const makePicker = (onChange, dato, current) => (
33 const validateNext = none(either(isNil, isEmpty)) 33 const validateNext = none(either(isNil, isEmpty))
34 const navigateNext = (self, requeridos) => { 34 const navigateNext = (self, requeridos) => {
35 if (validateNext(requeridos)) { 35 if (validateNext(requeridos)) {
36 - const pushAction = StackActions.push({  
37 - routeName: 'ConfirmarSolicitud'  
38 - })  
39 - self.props.navigation.dispatch(pushAction)  
40 - } else {  
41 - console.log('no pasar') 36 + const pushAction = StackActions.push({
  37 + routeName: 'ConfirmarSolicitud'
  38 + })
  39 + self.props.navigation.dispatch(pushAction)
42 } 40 }
43 } 41 }
44 42
@@ -7,9 +7,6 @@ import { connect } from 'react-redux' @@ -7,9 +7,6 @@ import { connect } from 'react-redux'
7 import { NavigationActions, StackActions } from 'react-navigation' 7 import { NavigationActions, StackActions } from 'react-navigation'
8 import { all, not, identity } from 'ramda' 8 import { all, not, identity } from 'ramda'
9 9
10 -  
11 -import { AUTH_TOKEN, CLIENT_SECRET } from '../../constants'  
12 -  
13 import DefaultIndicator from '../../components/DefaultIndicator' 10 import DefaultIndicator from '../../components/DefaultIndicator'
14 11
15 import { inicializarDatos } from '../../redux/actions/inicio' 12 import { inicializarDatos } from '../../redux/actions/inicio'
@@ -34,7 +31,7 @@ const goToUserDetails = StackActions.reset({ @@ -34,7 +31,7 @@ const goToUserDetails = StackActions.reset({
34 class Splash extends Component { 31 class Splash extends Component {
35 32
36 componentWillMount() { 33 componentWillMount() {
37 - this.props.inicializarDatos(AUTH_TOKEN, CLIENT_SECRET) 34 + this.props.inicializarDatos()
38 } 35 }
39 36
40 37
@@ -81,7 +78,7 @@ const mapStateToProps = (state) => ({ @@ -81,7 +78,7 @@ const mapStateToProps = (state) => ({
81 }) 78 })
82 79
83 const mapDispatchToProps = (dispatch) => ({ 80 const mapDispatchToProps = (dispatch) => ({
84 - inicializarDatos: (token, secret) => dispatch(inicializarDatos(token, secret)), 81 + inicializarDatos: () => dispatch(inicializarDatos()),
85 }) 82 })
86 83
87 export default connect(mapStateToProps, mapDispatchToProps)(Splash) 84 export default connect(mapStateToProps, mapDispatchToProps)(Splash)
@@ -1258,12 +1258,14 @@ @@ -1258,12 +1258,14 @@
1258 "balanced-match": { 1258 "balanced-match": {
1259 "version": "1.0.0", 1259 "version": "1.0.0",
1260 "bundled": true, 1260 "bundled": true,
1261 - "dev": true 1261 + "dev": true,
  1262 + "optional": true
1262 }, 1263 },
1263 "brace-expansion": { 1264 "brace-expansion": {
1264 "version": "1.1.11", 1265 "version": "1.1.11",
1265 "bundled": true, 1266 "bundled": true,
1266 "dev": true, 1267 "dev": true,
  1268 + "optional": true,
1267 "requires": { 1269 "requires": {
1268 "balanced-match": "^1.0.0", 1270 "balanced-match": "^1.0.0",
1269 "concat-map": "0.0.1" 1271 "concat-map": "0.0.1"
@@ -1278,17 +1280,20 @@ @@ -1278,17 +1280,20 @@
1278 "code-point-at": { 1280 "code-point-at": {
1279 "version": "1.1.0", 1281 "version": "1.1.0",
1280 "bundled": true, 1282 "bundled": true,
1281 - "dev": true 1283 + "dev": true,
  1284 + "optional": true
1282 }, 1285 },
1283 "concat-map": { 1286 "concat-map": {
1284 "version": "0.0.1", 1287 "version": "0.0.1",
1285 "bundled": true, 1288 "bundled": true,
1286 - "dev": true 1289 + "dev": true,
  1290 + "optional": true
1287 }, 1291 },
1288 "console-control-strings": { 1292 "console-control-strings": {
1289 "version": "1.1.0", 1293 "version": "1.1.0",
1290 "bundled": true, 1294 "bundled": true,
1291 - "dev": true 1295 + "dev": true,
  1296 + "optional": true
1292 }, 1297 },
1293 "core-util-is": { 1298 "core-util-is": {
1294 "version": "1.0.2", 1299 "version": "1.0.2",
@@ -1405,7 +1410,8 @@ @@ -1405,7 +1410,8 @@
1405 "inherits": { 1410 "inherits": {
1406 "version": "2.0.3", 1411 "version": "2.0.3",
1407 "bundled": true, 1412 "bundled": true,
1408 - "dev": true 1413 + "dev": true,
  1414 + "optional": true
1409 }, 1415 },
1410 "ini": { 1416 "ini": {
1411 "version": "1.3.5", 1417 "version": "1.3.5",
@@ -1417,6 +1423,7 @@ @@ -1417,6 +1423,7 @@
1417 "version": "1.0.0", 1423 "version": "1.0.0",
1418 "bundled": true, 1424 "bundled": true,
1419 "dev": true, 1425 "dev": true,
  1426 + "optional": true,
1420 "requires": { 1427 "requires": {
1421 "number-is-nan": "^1.0.0" 1428 "number-is-nan": "^1.0.0"
1422 } 1429 }
@@ -1431,6 +1438,7 @@ @@ -1431,6 +1438,7 @@
1431 "version": "3.0.4", 1438 "version": "3.0.4",
1432 "bundled": true, 1439 "bundled": true,
1433 "dev": true, 1440 "dev": true,
  1441 + "optional": true,
1434 "requires": { 1442 "requires": {
1435 "brace-expansion": "^1.1.7" 1443 "brace-expansion": "^1.1.7"
1436 } 1444 }
@@ -1438,12 +1446,14 @@ @@ -1438,12 +1446,14 @@
1438 "minimist": { 1446 "minimist": {
1439 "version": "0.0.8", 1447 "version": "0.0.8",
1440 "bundled": true, 1448 "bundled": true,
1441 - "dev": true 1449 + "dev": true,
  1450 + "optional": true
1442 }, 1451 },
1443 "minipass": { 1452 "minipass": {
1444 "version": "2.2.4", 1453 "version": "2.2.4",
1445 "bundled": true, 1454 "bundled": true,
1446 "dev": true, 1455 "dev": true,
  1456 + "optional": true,
1447 "requires": { 1457 "requires": {
1448 "safe-buffer": "^5.1.1", 1458 "safe-buffer": "^5.1.1",
1449 "yallist": "^3.0.0" 1459 "yallist": "^3.0.0"
@@ -1462,6 +1472,7 @@ @@ -1462,6 +1472,7 @@
1462 "version": "0.5.1", 1472 "version": "0.5.1",
1463 "bundled": true, 1473 "bundled": true,
1464 "dev": true, 1474 "dev": true,
  1475 + "optional": true,
1465 "requires": { 1476 "requires": {
1466 "minimist": "0.0.8" 1477 "minimist": "0.0.8"
1467 } 1478 }
@@ -1542,7 +1553,8 @@ @@ -1542,7 +1553,8 @@
1542 "number-is-nan": { 1553 "number-is-nan": {
1543 "version": "1.0.1", 1554 "version": "1.0.1",
1544 "bundled": true, 1555 "bundled": true,
1545 - "dev": true 1556 + "dev": true,
  1557 + "optional": true
1546 }, 1558 },
1547 "object-assign": { 1559 "object-assign": {
1548 "version": "4.1.1", 1560 "version": "4.1.1",
@@ -1554,6 +1566,7 @@ @@ -1554,6 +1566,7 @@
1554 "version": "1.4.0", 1566 "version": "1.4.0",
1555 "bundled": true, 1567 "bundled": true,
1556 "dev": true, 1568 "dev": true,
  1569 + "optional": true,
1557 "requires": { 1570 "requires": {
1558 "wrappy": "1" 1571 "wrappy": "1"
1559 } 1572 }
@@ -1675,6 +1688,7 @@ @@ -1675,6 +1688,7 @@
1675 "version": "1.0.2", 1688 "version": "1.0.2",
1676 "bundled": true, 1689 "bundled": true,
1677 "dev": true, 1690 "dev": true,
  1691 + "optional": true,
1678 "requires": { 1692 "requires": {
1679 "code-point-at": "^1.0.0", 1693 "code-point-at": "^1.0.0",
1680 "is-fullwidth-code-point": "^1.0.0", 1694 "is-fullwidth-code-point": "^1.0.0",
  1 +<!doctype html>
  2 +<html class="no-js" lang="">
  3 +
  4 +<head>
  5 + <meta charset="utf-8">
  6 + <meta http-equiv="x-ua-compatible" content="ie=edge">
  7 + <title></title>
  8 + <meta name="description" content="">
  9 + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  10 +
  11 +</head>
  12 +
  13 +<body>
  14 + <p>Hello world! This is HTML5 Boilerplate.</p>
  15 +</body>
  16 +
  17 +</html>
1 -body {  
2 - padding: 50px;  
3 - font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;  
4 -}  
5 -  
6 -a {  
7 - color: #00B7FF;  
8 -}  
Please register or login to post a comment