Skip to content
This repository has been archived by the owner on Sep 7, 2020. It is now read-only.

Piazza search (WiP) #126

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions oh_queue/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,13 @@ hr {
margin-bottom: 10px;
}

/* Piazza Search Experiment */

.piazza-vote {
margin-top: -5px;
}


/* Mostly stolen from offline.js */

.offline {
Expand Down
70 changes: 68 additions & 2 deletions oh_queue/static/js/components/description_box.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ class DescriptionBox extends React.Component {
super(props);
this.handleChange = this.handleChange.bind(this);
this.submit = this.submit.bind(this);

this.piazzaFeedback = this.piazzaFeedback.bind(this);
this.searchPiazza = this.searchPiazza.bind(this);

this.searchPiazza()
}

handleChange(event) {
Expand All @@ -14,18 +19,75 @@ class DescriptionBox extends React.Component {
submit() {
let ticket = this.props.ticket;
app.makeRequest('describe', {'id': ticket.id, 'description': this.newDescription} );
// Search Piazza if available
this.searchPiazza(this.newDescription);
this.newDescription = null;
this.setState(this.props.state); // force a render
}

piazzaFeedback(e, postId, semester, vote) {
let {state, ticket} = this.props;
e.persist() // Use the event in the async callback.
axios.post(`https://oh-help.cs61a.org/api/v1/algolia/vote`, {
user: this.state.currentUser.hash,
post: postId,
semester: semester,
assignment: ticket.assignment,
isStaff: isStaff(state),
question: ticket.question,
ticketTime: ticket.created,
ticketStatus: ticket.status,
location: ticket.location,
description: ticket.description,
vote: vote
}).then(res => {
app.addMessage("Thanks for your feedback!", 'success');
});
}

searchPiazza(description) {
let ticket = this.props.ticket;
let assgn = ticket.assignment.replace('Project', 'Proj').replace('Homework', 'HW');
let assignment = assgn + " Q" + ticket.question
let query = encodeURIComponent(assignment)
let user = encodeURIComponent(this.props.state.currentUser.hash)

if (description) {
query += encodeURIComponent(' ' + description);
}

axios.get(`https://oh-help.cs61a.org/api/v1/algolia/search?query=` + query + '&user=' + user)
.then(res => {
this.piazzaResults = []
var post;
for (var i in res.data['results']) {
if (i <= 4) {
post = res.data['results'][i];
this.piazzaResults.push(<div>
<a href={post.url}> {post.subject} </a>
<small>({post.semester})</small>
<div className="btn-toolbar btn-group pull-right piazza-vote" role="toolbar" aria-label="Rating">
<div className="btn btn-default btn-small" onClick={(e) => this.piazzaFeedback(e, post.qid, post.semester, 'up')} role="group" aria-label="Thumbs Up">👍</div>
<div className="btn btn-default btn-small" onClick={(e) => this.piazzaFeedback(e, post.qid, post.semester, 'down')} role="group" aria-label="Thumbs Down">👎</div>
</div>
<hr></hr>
</div>)
}
}
this.setState(this.props.state); // force a render
});
}

render() {
let {state, ticket} = this.props;
let staff = isStaff(state);


if (staff) {
return (
<p className="ticket-view-desc">{ticket.description ? ticket.description : <i>No description</i>}</p>
<div>
<p className="ticket-view-desc">{ticket.description ? ticket.description : <i>No description</i>}</p>
{ this.piazzaResults }
</div>
);
} else {
return (
Expand All @@ -34,6 +96,10 @@ class DescriptionBox extends React.Component {
<textarea className="description-box" defaultValue={ticket.description} onChange={this.handleChange}
rows="5" placeholder="It would be helpful if you could describe your issue. For example, &quot;I have a SyntaxError in my ___ function. I've tried using ____ and ____.&quot;" />
{this.newDescription ? <button onClick={this.submit} className="description-button btn btn-default btn-lg btn-block"> Save Description </button> : null}
{this.piazzaResults ? <div>
<p> While you are waiting - check out these resources: </p>
{ this.piazzaResults }
</div> : null}
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions oh_queue/static/js/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type User = {
name: string,
shortName: string,
isStaff: boolean,
hash: string
};

type Ticket = {
Expand Down
6 changes: 4 additions & 2 deletions oh_queue/templates/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
</script>
</head>
<body>
{% block header %}{% endblock %}
{% block body %}{% endblock %}

{% block header %}{% endblock %}
{% block body %}{% endblock %}


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
Expand All @@ -38,6 +39,7 @@
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/push.js/0.0.12/push.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.min.js"></script>

<!-- Should be loaded before common.js -->
Expand Down
5 changes: 4 additions & 1 deletion oh_queue/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import functools
import collections
import pytz
from hashlib import md5

from flask import render_template, url_for
from flask_login import current_user
Expand All @@ -11,12 +12,14 @@
from oh_queue.models import Ticket, TicketStatus, TicketEvent, TicketEventType

def user_json(user):
email = user.email.encode('utf-8')
return {
'id': user.id,
'email': user.email,
'email': email,
'name': user.name,
'shortName': user.short_name,
'isStaff': user.is_staff,
'hash': md5(email).hexdigest()
}

def student_json(user):
Expand Down