1
- import React from 'react'
1
+ import React , { useEffect , useState } from 'react'
2
2
import { connect } from 'react-redux'
3
3
import AceEditor from 'react-ace'
4
4
import { WithContext as Tags } from 'react-tag-input'
@@ -7,166 +7,150 @@ import 'brace/theme/textmate'
7
7
8
8
import Notification from './common/Notification'
9
9
import ListBoxWithSearch from './ListBoxWithSearch'
10
+
10
11
import { fetchSyntaxes , postSnippet } from '../actions'
11
12
12
- import { validateSnippet } from '../entries/snippetValidation'
13
- import { getCurrentModeName , getModesByName } from '../misc/modes'
14
13
import { onEditorLoad } from '../misc/editor'
15
- import { recalcLangHeaderHeight } from '../misc/dom '
14
+ import { getCurrentModeName , getModesByName } from '../misc/modes '
16
15
16
+ import { validateSnippet } from '../entries/snippetValidation'
17
17
import { delimeterKeys } from '../entries/keyboardKeys'
18
18
import { defaultOptions } from '../entries/aceEditorOptions'
19
19
20
20
import '../styles/NewSnippet.styl'
21
21
22
- class NewSnippet extends React . Component {
23
- constructor ( props ) {
24
- super ( props )
22
+ const recalcLangHeaderHeight = ( ) => {
23
+ const mainHeader = 'new-snippet-code-header'
24
+ const langHeader = 'new-snippet-lang-header'
25
25
26
- this . state = {
27
- content : '' ,
28
- title : '' ,
29
- tags : [ ] ,
30
- syntax : '' ,
31
- validationError : null ,
32
- }
33
- }
26
+ const height = document . getElementsByClassName ( mainHeader ) [ 0 ] . offsetHeight
34
27
35
- componentDidMount ( ) {
36
- const { dispatch } = this . props
28
+ document . getElementsByClassName ( langHeader ) [ 0 ] . setAttribute ( 'style' , `height:${ height } px` )
29
+ }
30
+
31
+ const NewSnippet = props => {
32
+ const { dispatch, history } = props
33
+
34
+ const [ syntax , setSyntax ] = useState ( '' )
35
+ const [ content , setContent ] = useState ( '' )
36
+ const [ title , setTitle ] = useState ( '' )
37
+ const [ tags , setTags ] = useState ( [ ] )
38
+ const [ validationError , setValidationError ] = useState ( null )
39
+
40
+ useEffect ( ( ) => {
37
41
dispatch ( fetchSyntaxes )
38
- }
42
+ } , [ ] )
43
+
44
+ useEffect ( ( ) => {
45
+ recalcLangHeaderHeight ( )
46
+ } , [ tags ] )
39
47
40
- onTagAdded = tag => {
48
+ const onTagAdded = tag => {
41
49
if ( tag && tag . text ) {
42
- this . setState ( { tags : [ ...this . state . tags , tag ] } , ( ) => {
43
- recalcLangHeaderHeight ( )
44
- } )
50
+ setTags ( [ ...tags , tag ] )
45
51
}
46
52
}
47
53
48
- onTagRemoved = i => {
49
- const { tags } = this . state
50
-
51
- this . setState ( { tags : tags . filter ( ( tag , index ) => index !== i ) } , ( ) => {
52
- recalcLangHeaderHeight ( )
53
- } )
54
+ const onTagRemoved = i => {
55
+ setTags ( tags . filter ( ( tag , index ) => index !== i ) )
54
56
}
55
57
56
- onTagBlur = tag => {
57
- this . onTagAdded ( { id : tag , text : tag } )
58
+ const onTagBlur = tag => {
59
+ onTagAdded ( { id : tag , text : tag } )
58
60
}
59
61
60
- onSyntaxClick = syntax => {
61
- this . setState ( { syntax } )
62
+ const onSyntaxClick = syntax => {
63
+ setSyntax ( syntax )
62
64
}
63
65
64
- onInputChange = e => {
65
- const { name , value } = e . target
66
+ const onTitleChange = e => {
67
+ const { value } = e . target
66
68
67
- this . setState ( { [ name ] : value } )
69
+ setTitle ( value )
68
70
}
69
71
70
- validate = ( ) => {
71
- const { content } = this . state
72
-
73
- return validateSnippet ( { content : content . trim ( ) } )
74
- }
72
+ const validate = ( ) => validateSnippet ( { content : content . trim ( ) } )
75
73
76
- post = e => {
74
+ const post = e => {
77
75
e . preventDefault ( )
78
- const { dispatch, history } = this . props
79
- const { error } = this . validate ( )
76
+ const { error } = validate ( )
80
77
81
- this . setState ( { validationError : error } )
78
+ setValidationError ( error )
82
79
83
80
if ( ! error ) {
84
- const {
85
- content, title, tags, syntax,
86
- } = this . state
87
-
88
81
dispatch ( postSnippet ( {
89
82
content, title, tags : tags . map ( tag => tag . text ) , syntax,
90
83
} , json => history . push ( `/${ json . id } ` ) ) )
91
84
}
92
85
}
93
86
94
- getSyntaxes = ( ) => {
87
+ const getSyntaxes = ( ) => {
95
88
const { modesByName } = getModesByName ( )
96
89
97
- return this . props . syntaxes . map ( item => ( {
90
+ return props . syntaxes . map ( item => ( {
98
91
name : modesByName [ item ] . caption ,
99
92
value : item ,
100
93
} ) )
101
94
}
102
95
103
- renderValidationError = ( ) => {
104
- const { validationError } = this . state
105
-
106
- return validationError && < Notification
107
- message = "Content is required :("
108
- show = { ! ! validationError }
109
- />
110
- }
111
-
112
- render ( ) {
113
- const { syntax, content, title, tags } = this . state
114
-
115
- return (
116
- < form
117
- className = "new-snippet"
118
- key = "New Snippet"
119
- onSubmit = { this . post }
120
- role = "presentation"
121
- >
122
- < div className = "new-snippet-code-wrapper" >
123
- < div className = "new-snippet-code-header" >
124
- < input
125
- className = "input"
126
- placeholder = "Title"
127
- name = "title"
128
- type = "text"
129
- value = { title }
130
- onChange = { this . onInputChange }
131
- />
132
- < Tags
133
- placeholder = "Tags"
134
- tags = { tags }
135
- handleDelete = { this . onTagRemoved }
136
- handleAddition = { this . onTagAdded }
137
- handleInputBlur = { this . onTagBlur }
138
- delimiters = { delimeterKeys }
139
- />
140
- </ div >
141
- < div className = "new-snippet-code" >
142
- < AceEditor
143
- mode = { getCurrentModeName ( syntax ) }
144
- width = "100%"
145
- height = "100%"
146
- focus
147
- theme = "textmate"
148
- onLoad = { onEditorLoad }
149
- setOptions = { defaultOptions }
150
- editorProps = { { $blockScrolling : Infinity } }
151
- value = { content }
152
- onChange = { ( content ) => { this . setState ( { content } ) } }
153
- />
154
-
155
- < div className = "new-snippet-code-bottom-bar" >
156
- { this . renderValidationError ( ) }
157
- < input type = "submit" value = "POST SNIPPET" />
158
- </ div >
159
- </ div >
96
+ const renderValidationError = ( ) => ( validationError && < Notification
97
+ message = "Content is required :("
98
+ show = { ! ! validationError }
99
+ /> )
100
+
101
+ return (
102
+ < form
103
+ className = "new-snippet"
104
+ key = "New Snippet"
105
+ onSubmit = { post }
106
+ role = "presentation"
107
+ >
108
+ < div className = "new-snippet-code-wrapper" >
109
+ < div className = "new-snippet-code-header" >
110
+ < input
111
+ className = "input"
112
+ placeholder = "Title"
113
+ name = "title"
114
+ type = "text"
115
+ value = { title }
116
+ onChange = { onTitleChange }
117
+ />
118
+ < Tags
119
+ placeholder = "Tags"
120
+ tags = { tags }
121
+ handleDelete = { onTagRemoved }
122
+ handleAddition = { onTagAdded }
123
+ handleInputBlur = { onTagBlur }
124
+ delimiters = { delimeterKeys }
125
+ />
160
126
</ div >
161
- < div className = "new-snippet-lang-wrapper" >
162
- < ListBoxWithSearch
163
- items = { this . getSyntaxes ( ) }
164
- onClick = { this . onSyntaxClick }
127
+ < div className = "new-snippet-code" >
128
+ < AceEditor
129
+ mode = { getCurrentModeName ( syntax ) }
130
+ width = "100%"
131
+ height = "100%"
132
+ focus
133
+ theme = "textmate"
134
+ onLoad = { onEditorLoad }
135
+ setOptions = { defaultOptions }
136
+ editorProps = { { $blockScrolling : Infinity } }
137
+ value = { content }
138
+ onChange = { ( value ) => setContent ( value ) }
165
139
/>
140
+ < div className = "new-snippet-code-bottom-bar" >
141
+ { renderValidationError ( ) }
142
+ < input type = "submit" value = "POST SNIPPET" />
143
+ </ div >
166
144
</ div >
167
- </ form >
168
- )
169
- }
145
+ </ div >
146
+ < div className = "new-snippet-lang-wrapper" >
147
+ < ListBoxWithSearch
148
+ items = { getSyntaxes ( ) }
149
+ onClick = { onSyntaxClick }
150
+ />
151
+ </ div >
152
+ </ form >
153
+ )
170
154
}
171
155
172
156
export default connect ( state => ( {
0 commit comments