1
- import React from 'react'
1
+ import React , { Component } from 'react'
2
2
import Skeleton from 'react-loading-skeleton'
3
3
import PropTypes from 'prop-types'
4
- import { Query } from 'react-apollo'
4
+ import { Query , Mutation } from 'react-apollo'
5
5
import gql from 'graphql-tag'
6
6
import { withRouter } from 'react-router'
7
7
import get from 'lodash/get'
8
8
9
9
import { deslugify } from '../lib/helpers'
10
10
11
- const Section = ( { loading, section, chapter } ) => {
12
- let headerContent = null ,
13
- sectionContent = null
11
+ class Section extends Component {
12
+ lastSectionId = null
14
13
15
- if ( loading ) {
16
- headerContent = (
17
- < h1 >
18
- < Skeleton />
19
- </ h1 >
20
- )
21
- sectionContent = < Skeleton count = { 7 } />
22
- } else if ( ! section ) {
23
- headerContent = (
24
- < h1 >
25
- < span role = "img" aria-label = "magnifying glass" >
26
- 🔍
27
- </ span > { ' ' }
28
- 404 page not found
29
- </ h1 >
30
- )
31
- } else {
32
- if ( chapter . number !== null ) {
14
+ componentWillReceiveProps ( props ) {
15
+ if ( ! props . section ) {
16
+ return
17
+ }
18
+
19
+ const sectionChanged = props . section . id !== this . lastSectionId
20
+
21
+ if ( sectionChanged ) {
22
+ setTimeout ( ( ) => {
23
+ props . viewedSection ( {
24
+ variables : { id : props . section . id }
25
+ } )
26
+ } , 2000 )
27
+ this . lastSectionId = props . section . id
28
+ }
29
+ }
30
+
31
+ render ( ) {
32
+ const { loading, section, chapter } = this . props
33
+ let headerContent = null ,
34
+ sectionContent = null ,
35
+ footerContent = null
36
+
37
+ if ( loading ) {
33
38
headerContent = (
34
- < div >
35
- < h1 > { section . title } </ h1 >
36
- < h2 >
37
- { 'Chapter ' + chapter . number }
38
- < span className = "Section-number-divider" />
39
- { 'Section ' + section . number }
40
- </ h2 >
41
- </ div >
39
+ < h1 >
40
+ < Skeleton />
41
+ </ h1 >
42
+ )
43
+ sectionContent = < Skeleton count = { 7 } />
44
+ } else if ( ! section ) {
45
+ headerContent = (
46
+ < h1 >
47
+ < span role = "img" aria-label = "magnifying glass" >
48
+ 🔍
49
+ </ span > { ' ' }
50
+ 404 page not found
51
+ </ h1 >
42
52
)
43
53
} else {
44
- headerContent = < h1 > { chapter . title } </ h1 >
54
+ if ( chapter . number !== null ) {
55
+ headerContent = (
56
+ < div >
57
+ < h1 > { section . title } </ h1 >
58
+ < h2 >
59
+ { 'Chapter ' + chapter . number }
60
+ < span className = "Section-number-divider" />
61
+ { 'Section ' + section . number }
62
+ </ h2 >
63
+ </ div >
64
+ )
65
+ } else {
66
+ headerContent = < h1 > { chapter . title } </ h1 >
67
+ }
68
+
69
+ sectionContent = section . content
70
+ footerContent = `Viewed ${ section . views . toLocaleString ( ) } times`
45
71
}
46
72
47
- sectionContent = section . content
73
+ return (
74
+ < section className = "Section" >
75
+ < div className = "Section-header-wrapper" >
76
+ < header className = "Section-header" > { headerContent } </ header >
77
+ </ div >
78
+ < div className = "Section-content" > { sectionContent } </ div >
79
+ < footer > { footerContent } </ footer >
80
+ </ section >
81
+ )
48
82
}
49
-
50
- return (
51
- < section className = "Section" >
52
- < div className = "Section-header-wrapper" >
53
- < header className = "Section-header" > { headerContent } </ header >
54
- </ div >
55
- < div className = "Section-content" > { sectionContent } </ div >
56
- </ section >
57
- )
58
83
}
59
84
60
85
Section . propTypes = {
61
86
section : PropTypes . shape ( {
62
87
title : PropTypes . string ,
63
88
number : PropTypes . number ,
64
- content : PropTypes . string
89
+ content : PropTypes . string ,
90
+ views : PropTypes . number
65
91
} ) ,
66
92
chapter : PropTypes . shape ( {
67
93
title : PropTypes . string ,
68
94
number : PropTypes . number
69
95
} ) ,
70
- loading : PropTypes . bool . isRequired
96
+ loading : PropTypes . bool . isRequired ,
97
+ viewedSection : PropTypes . func . isRequired
71
98
}
72
99
73
100
const SECTION_BY_ID_QUERY = gql `
74
101
query SectionContent($id: String!) {
75
102
section(id: $id) {
103
+ id
76
104
content
105
+ views
77
106
}
78
107
}
79
108
`
@@ -83,7 +112,9 @@ const SECTION_BY_CHAPTER_TITLE_QUERY = gql`
83
112
chapterByTitle(title: $title) {
84
113
title
85
114
section(number: 1) {
115
+ id
86
116
content
117
+ views
87
118
}
88
119
}
89
120
}
@@ -94,14 +125,25 @@ const SECTION_BY_NUMBER_QUERY = gql`
94
125
chapterByNumber(number: $chapterNumber) {
95
126
number
96
127
section(number: $sectionNumber) {
128
+ id
97
129
number
98
130
title
99
131
content
132
+ views
100
133
}
101
134
}
102
135
}
103
136
`
104
137
138
+ const VIEWED_SECTION_MUTATION = gql `
139
+ mutation ViewedSection($id: String!) {
140
+ viewedSection(id: $id) {
141
+ id
142
+ views
143
+ }
144
+ }
145
+ `
146
+
105
147
const SectionWithData = ( { location : { state, pathname } } ) => {
106
148
const page = deslugify ( pathname )
107
149
@@ -113,7 +155,8 @@ const SectionWithData = ({ location: { state, pathname } }) => {
113
155
createProps = ( { data, loading } ) => ( {
114
156
section : {
115
157
...state . section ,
116
- content : get ( data , 'section.content' )
158
+ content : get ( data , 'section.content' ) ,
159
+ views : get ( data , 'section.views' )
117
160
} ,
118
161
chapter : state . chapter ,
119
162
loading
@@ -141,7 +184,16 @@ const SectionWithData = ({ location: { state, pathname } }) => {
141
184
142
185
return (
143
186
< Query query = { query } variables = { variables } >
144
- { queryInfo => < Section { ...createProps ( queryInfo ) } /> }
187
+ { queryInfo => (
188
+ < Mutation mutation = { VIEWED_SECTION_MUTATION } >
189
+ { viewedSection => (
190
+ < Section
191
+ { ...createProps ( queryInfo ) }
192
+ viewedSection = { viewedSection }
193
+ />
194
+ ) }
195
+ </ Mutation >
196
+ ) }
145
197
</ Query >
146
198
)
147
199
}
0 commit comments