Skip to content

Commit 9bae979

Browse files
authored
Merge pull request #2560 from StoDevX/dictionary-report-issue
Report dictionary issue
2 parents 992de91 + 7c01bdc commit 9bae979

File tree

11 files changed

+334
-5
lines changed

11 files changed

+334
-5
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@
142142
"timers": "0.1.1",
143143
"titlecase": "1.1.2",
144144
"url": "0.11.0",
145+
"wordwrap": "1.0.0",
145146
"xml2js": "0.4.19"
146147
},
147148
"devDependencies": {

source/navigation.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import * as c from './views/components/colors'
66

77
import CalendarView, {EventDetail as EventDetailView} from './views/calendar'
88
import {ContactsView, ContactsDetailView} from './views/contacts'
9-
import {DictionaryView, DictionaryDetailView} from './views/dictionary'
9+
import {
10+
DictionaryView,
11+
DictionaryDetailView,
12+
DictionaryEditorView,
13+
} from './views/dictionary'
1014
import {HomeView, EditHomeView} from './views/home'
1115
import StreamingView, {
1216
KSTOScheduleView,
@@ -72,6 +76,7 @@ export const AppNavigator = StackNavigator(
7276
CreditsView: {screen: CreditsView},
7377
DictionaryDetailView: {screen: DictionaryDetailView},
7478
DictionaryView: {screen: DictionaryView},
79+
DictionaryEditorView: {screen: DictionaryEditorView},
7580
EditHomeView: {screen: EditHomeView},
7681
EventDetailView: {screen: EventDetailView},
7782
FaqView: {screen: FaqView},

source/views/components/cells/textfield.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@ const styles = StyleSheet.create({
1717
customTextInput: {
1818
flex: 1,
1919
},
20-
loginCell: {
20+
singlelineCell: {
2121
height: Platform.OS === 'android' ? 65 : 44,
2222
alignItems: 'stretch',
2323
paddingTop: 0,
2424
paddingBottom: 0,
2525
},
26+
multilineCell: {
27+
alignItems: 'stretch',
28+
paddingTop: 10,
29+
paddingBottom: 10,
30+
},
2631
})
2732

2833
type Props = {
2934
label?: string,
3035
_ref: any => any,
3136
disabled: boolean,
37+
multiline?: boolean,
3238
onChangeText: string => any,
3339
onSubmitEditing: string => any,
3440
placeholder: string,
@@ -84,6 +90,7 @@ export class CellTextField extends React.Component<Props> {
8490
autoCorrect={false}
8591
clearButtonMode="while-editing"
8692
disabled={this.props.disabled}
93+
multiline={this.props.multiline || false}
8794
onChangeText={this.props.onChangeText}
8895
onSubmitEditing={this.onSubmit}
8996
placeholder={this.props.placeholder}
@@ -95,7 +102,9 @@ export class CellTextField extends React.Component<Props> {
95102
/>
96103
}
97104
cellContentView={label}
98-
contentContainerStyle={styles.loginCell}
105+
contentContainerStyle={
106+
this.props.multiline ? styles.multilineCell : styles.singlelineCell
107+
}
99108
/>
100109
)
101110
}

source/views/dictionary/detail.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import * as React from 'react'
33
import {StyleSheet} from 'react-native'
44
import {Markdown} from '../components/markdown'
55
import {ListFooter} from '../components/list'
6+
import {Button} from '../components/button'
67
import glamorous from 'glamorous-native'
78
import type {WordType} from './types'
9+
import type {TopLevelViewPropsType} from '../types'
810
import {GH_NEW_ISSUE_URL} from '../../globals'
911

1012
// TODO: This doesn't point at the SA dictionary because they don't have an
@@ -29,7 +31,7 @@ const styles = StyleSheet.create({
2931
},
3032
})
3133

32-
type Props = {
34+
type Props = TopLevelViewPropsType & {
3335
navigation: {state: {params: {item: WordType}}},
3436
}
3537

@@ -40,6 +42,13 @@ export class DictionaryDetailView extends React.PureComponent<Props> {
4042
}
4143
}
4244

45+
handleEditButtonPress = () => {
46+
const item = this.props.navigation.state.params.item
47+
this.props.navigation.navigate('DictionaryEditorView', {
48+
word: item,
49+
})
50+
}
51+
4352
render() {
4453
const item = this.props.navigation.state.params.item
4554
return (
@@ -50,6 +59,8 @@ export class DictionaryDetailView extends React.PureComponent<Props> {
5059
styles={{Paragraph: styles.paragraph}}
5160
/>
5261

62+
<Button onPress={this.handleEditButtonPress} title="Suggest an Edit" />
63+
5364
<ListFooter
5465
href={STO_SA_DICT_URL}
5566
title={

source/views/dictionary/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
// @flow
22
export {DictionaryView} from './list'
33
export {DictionaryDetailView} from './detail'
4+
export {DictionaryEditorView} from './report'
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`handles a basic term 1`] = `
4+
"word: A Word
5+
definition: |
6+
My Long-ish Definition
7+
"
8+
`;
9+
10+
exports[`handles long definitions 1`] = `
11+
"word: ACE
12+
definition: |
13+
Academic Civic Engagement. These are courses that include a component of
14+
learning in the community with non-profit or governmental partners.
15+
"
16+
`;
17+
18+
exports[`handles long words 1`] = `
19+
"word: >-
20+
Academic Civic Engagement. These are courses that include a component of
21+
learning in the community with non-profit or governmental partners.
22+
definition: |
23+
foo
24+
"
25+
`;
26+
27+
exports[`handles newlines in the definition 1`] = `
28+
"word: ACE
29+
definition: |
30+
Academic Civic Engagement.
31+
32+
These are courses that include
33+
34+
a component of learning in the
35+
36+
community with non-profit or
37+
38+
governmental partners.
39+
"
40+
`;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* eslint-env jest */
2+
// @flow
3+
4+
import {stringifyDictionaryEntry} from '../submit'
5+
6+
test('handles a basic term', () => {
7+
expect(
8+
stringifyDictionaryEntry({
9+
word: 'A Word',
10+
definition: 'My Long-ish Definition',
11+
}),
12+
).toMatchSnapshot()
13+
})
14+
15+
test('handles long definitions', () => {
16+
let def = {
17+
word: 'ACE',
18+
definition:
19+
'Academic Civic Engagement. These are courses that include a component of learning in the community with non-profit or governmental partners.',
20+
}
21+
expect(stringifyDictionaryEntry(def)).toMatchSnapshot()
22+
})
23+
24+
test('handles long words', () => {
25+
let def = {
26+
word:
27+
'Academic Civic Engagement. These are courses that include a component of learning in the community with non-profit or governmental partners.',
28+
definition: 'foo',
29+
}
30+
expect(stringifyDictionaryEntry(def)).toMatchSnapshot()
31+
})
32+
33+
test('handles newlines in the definition', () => {
34+
let def = {
35+
word: 'ACE',
36+
definition:
37+
'Academic Civic Engagement.\n\nThese are courses that include\n\na component of learning in the\n\ncommunity with non-profit or\n\ngovernmental partners.',
38+
}
39+
expect(stringifyDictionaryEntry(def)).toMatchSnapshot()
40+
})
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// @flow
2+
import * as React from 'react'
3+
import {ScrollView, View, Text, StyleSheet} from 'react-native'
4+
import {CellTextField} from '../../components/cells/textfield'
5+
import {ButtonCell} from '../../components/cells/button'
6+
import {TableView, Section} from 'react-native-tableview-simple'
7+
import {submitReport} from './submit'
8+
import type {WordType} from '../types'
9+
import * as c from '../../components/colors'
10+
import type {TopLevelViewPropsType} from '../../types'
11+
12+
type Props = TopLevelViewPropsType & {
13+
navigation: {state: {params: {item: WordType}}},
14+
}
15+
16+
type State = {
17+
term: string,
18+
definition: string,
19+
}
20+
21+
export class DictionaryEditorView extends React.PureComponent<Props, State> {
22+
static navigationOptions = () => {
23+
return {
24+
title: 'Suggest an Edit',
25+
}
26+
}
27+
28+
static getDerivedStateFromProps(nextProps: Props) {
29+
let entry = nextProps.navigation.state.params.word
30+
return {
31+
term: entry.word,
32+
definition: entry.definition,
33+
}
34+
}
35+
36+
state = {
37+
term: this.props.navigation.state.params.word.word,
38+
definition: this.props.navigation.state.params.word.definition,
39+
}
40+
41+
submit = () => {
42+
submitReport(this.props.navigation.state.params.word, {
43+
word: this.state.term,
44+
definition: this.state.definition,
45+
})
46+
}
47+
48+
onChangeTitle = (newTitle: string) => {
49+
this.setState(() => ({term: newTitle}))
50+
}
51+
52+
onChangeDefinition = (newDefinition: string) => {
53+
this.setState(() => ({definition: newDefinition}))
54+
}
55+
56+
render() {
57+
let term = this.state.term ? this.state.term.trim() : ''
58+
let definition = this.state.definition ? this.state.definition.trim() : ''
59+
60+
return (
61+
<ScrollView
62+
keyboardDismissMode="on-drag"
63+
keyboardShouldPersistTaps="always"
64+
>
65+
<View style={styles.helpWrapper}>
66+
<Text style={styles.helpTitle}>Thanks for spotting a problem!</Text>
67+
<Text style={styles.helpDescription}>
68+
If you could tell us what the word and definition should be,
69+
we&rsquo;d greatly appreciate it.
70+
</Text>
71+
</View>
72+
73+
<TableView>
74+
<Section header="WORD">
75+
<TitleCell onChange={this.onChangeTitle} text={term} />
76+
</Section>
77+
78+
<Section header="DEFINITION">
79+
<DefinitionCell
80+
onChange={this.onChangeDefinition}
81+
text={definition}
82+
/>
83+
</Section>
84+
85+
<Section footer="Thanks for reporting!">
86+
<ButtonCell onPress={this.submit} title="Submit Report" />
87+
</Section>
88+
</TableView>
89+
</ScrollView>
90+
)
91+
}
92+
}
93+
94+
type TextFieldProps = {text: string, onChange: string => any}
95+
96+
const TitleCell = ({text, onChange = () => {}}: TextFieldProps) => (
97+
<CellTextField
98+
autoCapitalize="words"
99+
hideLabel={true}
100+
onChangeText={onChange}
101+
onSubmitEditing={onChange}
102+
placeholder="Title"
103+
returnKeyType="done"
104+
value={text}
105+
/>
106+
)
107+
108+
const DefinitionCell = ({text, onChange = () => {}}: TextFieldProps) => (
109+
<CellTextField
110+
autoCapitalize="sentences"
111+
hideLabel={true}
112+
multiline={true}
113+
onChangeText={onChange}
114+
onSubmitEditing={onChange}
115+
placeholder="Definition"
116+
returnKeyType="default"
117+
value={text}
118+
/>
119+
)
120+
121+
const styles = StyleSheet.create({
122+
helpWrapper: {
123+
backgroundColor: c.white,
124+
borderWidth: StyleSheet.hairlineWidth,
125+
borderTopColor: c.iosHeaderTopBorder,
126+
borderBottomColor: c.iosHeaderBottomBorder,
127+
marginBottom: 10,
128+
},
129+
helpTitle: {
130+
fontSize: 16,
131+
fontWeight: 'bold',
132+
paddingTop: 15,
133+
paddingHorizontal: 15,
134+
},
135+
helpDescription: {
136+
fontSize: 14,
137+
paddingTop: 5,
138+
paddingBottom: 15,
139+
paddingHorizontal: 15,
140+
},
141+
})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @flow
2+
3+
export {DictionaryEditorView} from './editor'

0 commit comments

Comments
 (0)