Skip to content

Commit 051de5e

Browse files
committed
Merge branch 'main' of github.com:DocNow/docnow into main
2 parents b315297 + 6d066e4 commit 051de5e

File tree

10 files changed

+172
-61
lines changed

10 files changed

+172
-61
lines changed

src/archive/app/Archive.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import WebpagesBody from '../../client/components/Insights/WebpagesBody'
1212
import styles from '../../client/containers/App.css'
1313

1414
const search = window.searchData
15+
console.log(search)
1516

1617
class App extends MediaQueryComponent {
1718
constructor(props) {
@@ -122,7 +123,7 @@ class App extends MediaQueryComponent {
122123
title={search.title}
123124
desc={search.description}
124125
creator={search.creator}
125-
searchQuery={search.query.map(q => q.value).join(' ')}
126+
searchQuery={search.query.map(q => q.value.or.map(t => t.value).join(' ')).join(' ')}
126127
startDate={search.startDate}
127128
endDate={search.endDate}
128129
isHome={this.state.isHome} />

src/client/actions/search.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ export const getTweets = (id, includeRetweets = false, offset = 0) => {
241241
}
242242
}
243243

244-
export const getUsers = (id) => {
244+
export const getUsers = (id, offset = 0) => {
245245
return (dispatch) => {
246-
fetch('/api/v1/search/' + id + '/users', {credentials: 'same-origin'})
246+
fetch(`/api/v1/search/${id}/users?offset=${offset}`, {credentials: 'same-origin'})
247247
.then((resp) => resp.json())
248248
.then((result) => {
249249
dispatch(setTwitterSearchUsers(result))

src/client/components/Collections/Collection.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
.CardHolder {
2+
max-width: 1500px;
3+
}
4+
5+
.Card {
6+
width: 400px !important;
7+
height: 550px !important;
8+
overflow-y: scroll !important;
9+
}
10+
111
.CardTitle {
212
text-align: center;
313
padding-bottom: 1em;
@@ -10,4 +20,31 @@
1020
.Options {
1121
text-align: center;
1222
font-size: 5.5pt !important;
23+
}
24+
25+
.UserImg {
26+
max-width: 48px;
27+
max-height: 48px;
28+
overflow: hidden;
29+
overflow-wrap: anywhere;
30+
padding: 1px;
31+
font-size: 14px;
32+
}
33+
34+
.ButtonText {
35+
text-decoration: underline;
36+
}
37+
38+
.Search {
39+
display: flex;
40+
align-items: center;
41+
padding: 2px 10px;
42+
}
43+
44+
.SearchInput {
45+
width: 100%;
46+
}
47+
48+
.FoundUser {
49+
text-align: center
1350
}

src/client/components/Collections/Collection.js

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import FormControl from '@material-ui/core/FormControl'
1616
import Button from '@material-ui/core/Button'
1717
import TextField from '@material-ui/core/TextField'
1818
import Paper from '@material-ui/core/Paper'
19-
import InputAdornment from '@material-ui/core/InputAdornment'
19+
import IconButton from '@material-ui/core/IconButton'
2020

2121
import listStyle from './CollectionList.css'
2222
import style from './Collection.css'
@@ -26,9 +26,12 @@ export default class CollectionList extends Component {
2626
constructor(props) {
2727
super(props)
2828
this.state = {
29-
filteredUsers: [],
30-
filtered: false
29+
checkedTweets: [],
30+
findUser: '',
31+
findingUser: false,
32+
lastUserLookup: ''
3133
}
34+
this.randomTweet = Math.floor(Math.random() * (98))
3235
}
3336

3437
componentDidMount() {
@@ -47,26 +50,42 @@ export default class CollectionList extends Component {
4750
tick() {
4851
this.props.getSearch(this.props.searchId)
4952
this.props.getFoundInSearches()
50-
if (!this.state.filtered && this.props.search.userCount) {
53+
54+
const foundTweets = this.props.user.foundInSearches[this.props.searchId] || []
55+
if (this.state.checkedTweets.length === 0 && foundTweets.length > 0) {
5156
this.setState({
52-
filteredUsers: [...Array(this.props.search.userCount).keys()]
57+
checkedTweets: foundTweets.map(() => false)
5358
})
5459
}
5560
}
5661

57-
filterUser(term) {
58-
if (term === '') {
62+
handleFindUserInput(user) {
63+
const findingUser = user === '' ? false : this.state.findingUser
64+
this.setState({
65+
findUser: user,
66+
findingUser
67+
})
68+
}
69+
70+
findUser() {
71+
if (this.state.findUser !== '') {
5972
this.setState({
60-
filteredUsers: [...Array(this.props.search.userCount).keys()],
61-
filtered: true
62-
})
73+
findingUser: true,
74+
lastUserLookup: this.state.findUser
75+
})
76+
this.props.getTweetsForUser(this.props.searchId, this.state.findUser)
6377
}
78+
}
79+
80+
setAllTweets(checked) {
6481
this.setState({
65-
filteredUsers: this.props.search.users.reduce((acc, u, i) => {
66-
if (u.screenName.includes(term)) { acc.push(i) }
67-
return acc
68-
}, []),
69-
filtered: true
82+
checkedTweets: this.state.checkedTweets.map(() => checked)
83+
})
84+
}
85+
86+
toggleOneTweet(i) {
87+
this.setState({
88+
checkedTweets: this.state.checkedTweets.map((v, tIdx) => {return (i === tIdx ? !v : v)})
7089
})
7190
}
7291

@@ -82,8 +101,8 @@ export default class CollectionList extends Component {
82101
? <a href={`mailto:${this.props.search.creator.email}`}>{this.props.search.creator.email}</a>
83102
: 'No contact provided.'
84103
let tweets = 'Loading tweets...'
85-
if (this.props.search.tweets.length > 0) {
86-
tweets = this.props.search.tweets.slice(0, 2).map((t, i) => {
104+
if (this.props.search.tweets.length > 0) {
105+
tweets = this.props.search.tweets.slice(this.randomTweet, this.randomTweet + 2).map((t, i) => {
87106
return <TweetEmbed key={`t${i}`} id={t.id} />
88107
})
89108
}
@@ -103,21 +122,19 @@ export default class CollectionList extends Component {
103122
<FormGroup row>
104123
<FormControlLabel
105124
value="all"
106-
control={<Checkbox color="primary" />}
125+
control={<Checkbox color="primary"
126+
onChange={t => this.setAllTweets(t.target.checked)}
127+
checked={this.state.checkedTweets.indexOf(false) === -1} />}
107128
label={`Select all ${foundTweets.length} tweets`}
108129
/>
109130
</FormGroup>
110131
</FormControl>
111-
<Grid container spacing={0}>
112-
<Grid item xs={4}><Button className={style.Options}>specify consent</Button></Grid>
113-
<Grid item xs={4}><Button className={style.Options}>request removal</Button></Grid>
114-
<Grid item xs={4}><Button className={style.Options}>talk with us</Button></Grid>
115-
</Grid>
132+
<Button size="small"><span className={style.ButtonText}>Specify/Adjust Consent</span></Button>
116133
<hr/>
117134
{foundTweets.map((tweetId, i) => {
118135
return (
119136
<Grid container spacing={0} key={`ut${i}`}>
120-
<Grid item xs={2}><Checkbox color="primary" /></Grid>
137+
<Grid item xs={2}><Checkbox color="primary" checked={this.state.checkedTweets[i] || false} onChange={() => this.toggleOneTweet(i)} /></Grid>
121138
<Grid item xs={10}><TweetEmbed id={tweetId} /></Grid>
122139
</Grid>
123140
)
@@ -128,6 +145,28 @@ export default class CollectionList extends Component {
128145
}
129146
}
130147

148+
let usersInfo = (<div>
149+
<Typography variant="body2">Showing {this.props.search.users.length} of {this.props.search.userCount} users.</Typography>
150+
{this.props.search.users.map((u, i) => {
151+
return <img className={style.UserImg}
152+
src={u.avatarUrl}
153+
alt={u.screenName}
154+
title={u.screenName} key={`u${i}`} />
155+
})}
156+
</div>)
157+
158+
if (this.state.findingUser) {
159+
if (this.props.foundUserTweets > 0) {
160+
usersInfo = (
161+
<Typography variant="body2">
162+
Found {this.props.foundUserTweets} tweet{this.props.foundUserTweets > 1 ? 's' : ''} by &nbsp;
163+
<a href={`https://twitter.com/${this.state.lastUserLookup}`}>@{this.state.lastUserLookup}</a>.
164+
</Typography>)
165+
} else {
166+
usersInfo = <Typography variant="body2">Could not find user &quot;{this.state.lastUserLookup}&quot;.</Typography>
167+
}
168+
}
169+
131170
return (
132171
<>
133172
<Grid container spacing={3} className={listStyle.Header}>
@@ -154,47 +193,35 @@ export default class CollectionList extends Component {
154193
</Grid>
155194
</Grid>
156195

157-
<div className={card.CardHolder}>
158-
<Card raised className={card.Card} >
196+
<div className={`${card.CardHolder} ${style.CardHolder}`}>
197+
<Card raised className={`${card.Card} ${style.Card}`} >
159198
<CardContent>
160199
<div className={style.CardTitle}>
161200
<FindMe user={this.props.user} dest={`/collection/${this.props.searchId}`}/>
162201
</div>
163202
{userTweets}
164203
</CardContent>
165204
</Card>
166-
<Card raised className={card.Card} >
167-
<CardContent className={card.Scroll}>
205+
<Card raised className={`${card.Card} ${style.Card}`} >
206+
<CardContent>
168207
<div className={style.CardTitle}>
169-
<Paper id="box" elevation={4}>
170-
<TextField name="usersearch"
171-
onChange={t => this.filterUser(t.target.value)}
172-
InputProps={{
173-
startAdornment: (
174-
<InputAdornment position="start">
175-
<ion-icon name="search"></ion-icon>
176-
</InputAdornment>
177-
),
178-
}}/>
208+
<Paper id="box" elevation={4} className={style.Search}>
209+
<TextField name="usersearch" className={style.SearchInput}
210+
onChange={(e) => this.handleFindUserInput(e.target.value)} />
211+
<IconButton color="primary" onClick={() => this.findUser()}>
212+
<ion-icon name="search"></ion-icon>
213+
</IconButton>
179214
</Paper>
180215
</div>
181-
<div>
182-
{this.state.filteredUsers.map((i) => {
183-
if (this.props.search.users[i]) {
184-
return <img
185-
src={this.props.search.users[i].avatarUrl}
186-
alt={this.props.search.users[i].screenName}
187-
title={this.props.search.users[i].screenName} key={`u${i}`} />
188-
}
189-
})}
190-
</div>
216+
{usersInfo}
191217
</CardContent>
192218
</Card>
193-
<Card raised className={card.Card} >
194-
<CardContent className={card.Scroll}>
219+
<Card raised className={`${card.Card} ${style.Card}`} >
220+
<CardContent>
195221
<Typography variant="h2" className={style.CardTitle}>
196222
{tweetCount} tweets (all users)
197223
</Typography>
224+
<Typography variant="body2">Showing 2 random tweets from the collection.</Typography>
198225
{tweets}
199226
</CardContent>
200227
</Card>
@@ -212,4 +239,6 @@ CollectionList.propTypes = {
212239
getTweets: PropTypes.func,
213240
getUsers: PropTypes.func,
214241
getFoundInSearches: PropTypes.func,
242+
getTweetsForUser: PropTypes.func,
243+
foundUserTweets: PropTypes.bool
215244
}

src/client/components/Insights/Users.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ export default class Users extends Component {
4949

5050
<UsersBody
5151
searchId={this.props.searchId}
52-
search={this.props.search}
5352
getTweetsForUser={this.props.getTweetsForUser}
5453
resetTweets={this.props.resetTweets}
5554
tweets={this.props.tweets}
55+
userCount={this.props.search.userCount}
56+
users={this.props.search.users}
57+
getUsers={this.props.getUsers}
5658
/>
5759

5860
</div>

src/client/components/Insights/UsersBody.js

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,46 @@ export default class UsersBody extends Component {
1010
constructor(props) {
1111
super(props)
1212
this.modalOpen = true
13+
this.users = this.props.users
14+
this.offset = 0
1315
}
1416

1517
closeModal() {
1618
this.props.resetTweets()
1719
}
1820

21+
componentDidMount() {
22+
window.addEventListener(`scroll`, () => this.handleScroll())
23+
}
24+
25+
componentDidUpdate() {
26+
if (this.users && this.props.users.length > 0) {
27+
if (this.users[this.users.length - 1].id !== this.props.users[this.props.users.length - 1].id) {
28+
this.users = this.users.concat(this.props.users)
29+
}
30+
}
31+
}
32+
33+
update() {
34+
const distanceToBottom =
35+
document.documentElement.offsetHeight -
36+
(window.scrollY + window.innerHeight)
37+
if (distanceToBottom < 150) {
38+
this.offset = this.offset + 100
39+
if (this.offset <= this.props.userCount) {
40+
this.props.getUsers(this.props.searchId, this.offset)
41+
}
42+
}
43+
this.ticking = false
44+
}
45+
46+
handleScroll() {
47+
if (!this.ticking) {
48+
this.ticking = true
49+
requestAnimationFrame(() => this.update())
50+
}
51+
}
52+
1953
render() {
2054
const modalOpen = this.props.tweets.length > 0
2155

@@ -28,7 +62,7 @@ export default class UsersBody extends Component {
2862
tweets={this.props.tweets} />
2963

3064
<div className={cardStyle.CardHolder}>
31-
{this.props.search.users.map((i) => {
65+
{this.users.map((i) => {
3266
return (
3367
<User
3468
key={i.id}
@@ -54,8 +88,10 @@ export default class UsersBody extends Component {
5488

5589
UsersBody.propTypes = {
5690
searchId: PropTypes.string,
57-
search: PropTypes.object,
91+
users: PropTypes.array,
92+
userCount: PropTypes.int,
5893
getTweetsForUser: PropTypes.func,
94+
getUsers: PropTypes.func,
5995
resetTweets: PropTypes.func,
6096
tweets: PropTypes.array,
6197
}

src/client/containers/CollectionPage.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { bindActionCreators } from 'redux'
22
import { connect } from 'react-redux'
33
import { getSearch, getTweets, getUsers } from '../actions/search'
44
import { getFoundInSearches } from '../actions/user'
5+
import { getTweetsForUser } from '../actions/tweets'
56

67
import Collection from '../components/Collections/Collection'
78

89
const mapStateToProps = (state, ownProps) => {
910
return {
11+
foundUserTweets: state.tweets.length,
1012
user: state.user,
1113
searchId: ownProps.match.params.searchId,
1214
search: state.search,
@@ -17,7 +19,8 @@ const actions = {
1719
getSearch,
1820
getTweets,
1921
getUsers,
20-
getFoundInSearches
22+
getFoundInSearches,
23+
getTweetsForUser
2124
}
2225

2326
const mapDispatchToProps = (dispatch) => bindActionCreators(actions, dispatch)

0 commit comments

Comments
 (0)