Skip to content
This repository was archived by the owner on Sep 7, 2020. It is now read-only.
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
46 changes: 46 additions & 0 deletions oh_queue/estimatedTime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import csv

def finding_file():
fname = input('Enter file name: ')
try:
fhand = open(fname)
return fhand
except:
print('Failed to find file', fname + '. Please try again.')
return finding_file()

def estimatedTimeCalculation(file):
sum = 0
count = 0
for line in file:
#print(line)
line_modified = line.rstrip()
list = line.split(",")
if list[4] == "resolved":
if (list[2].split("T")[0].split("-")[0] == "2019"):
if (list[2].split("T")[0] == list[5].split("T")[0]):
startTime = list[2].split("T")[1].split(".")[0].split(":")
#print(startTime)
resolvedTime = list[5].split("T")[1].split(".")[0].split(":")
#print(resolvedTime)
waitTime = (int(resolvedTime[0]) * 3600 + int(resolvedTime[1]) * 60 + int(resolvedTime[2]) - (int(startTime[0]) * 3600 + int(startTime[1]) * 60 + int(startTime[2])))
if ((waitTime / 60) < 60):
print(waitTime/60)
sum += waitTime/60
count += 1


return sum / count


handle = finding_file()
print(estimatedTimeCalculation(handle))





#The current wait time is a 75% confidence interval with a hardcoded expected avgHelpTime = 10 (minutes)
#divided by the number of staff available. Empirically we've found that this causes the interval to fluctuate a little too much.
#To see this, try varying the number of online assistants. We should develop a better way of calculating this
#and perhaps estimating parameters based on data instead of magic numbers.
10 changes: 10 additions & 0 deletions oh_queue/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ class Location(db.Model):
name = db.Column(db.String(255), nullable=False, unique=True)
visible = db.Column(db.Boolean, default=False)

class Tag(db.Model):
"""Represents a ticket's tag."""
__tablename__ = 'tag'
id = db.Column(db.Integer, primary_key=True)
created = db.Column(db.DateTime, default=db.func.now())
name = db.Column(db.String(255), nullable=False, unique=True)
visible = db.Column(db.Boolean, default=False)

TicketStatus = enum.Enum('TicketStatus', 'pending assigned resolved deleted')

class Ticket(db.Model):
Expand All @@ -75,6 +83,7 @@ class Ticket(db.Model):

assignment_id = db.Column(db.ForeignKey('assignment.id'), nullable=False, index=True)
location_id = db.Column(db.ForeignKey('location.id'), nullable=False, index=True)
tag_id = db.Column(db.ForeignKey('tag.id'), nullable=False, index=True)
question = db.Column(db.String(255), nullable=False)

description = db.Column(db.Text)
Expand All @@ -83,6 +92,7 @@ class Ticket(db.Model):
helper = db.relationship(User, foreign_keys=[helper_id])
assignment = db.relationship(Assignment, foreign_keys=[assignment_id])
location = db.relationship(Location, foreign_keys=[location_id])
tag = db.relationship(Tag, foreign_keys=[tag_id])

@classmethod
def for_user(cls, user):
Expand Down
49,935 changes: 49,935 additions & 0 deletions oh_queue/query_result.csv

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions oh_queue/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@ h1.truncate, h2.truncate, h3.truncate, h4.truncate, h5.truncate, h6.truncate {
min-width: 0;
}
}
.btn-group {
display: inline-flex;
width: 100%
}

.route-transition-group {
position: relative;
Expand Down
2 changes: 1 addition & 1 deletion oh_queue/static/js/components/admin_home.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class AdminHome extends React.Component {
<div className="row">
<div className="col-md-12">
<h1>{window.courseName} Admin Panel</h1>
<h2>Edit assignments, locations, and more!</h2>
<h2>Edit assignments, locations, tags, and more!</h2>
<p>Found a bug? Want to change something? Talk to us at <a href="https://github.com/Cal-CS-61A-Staff/oh-queue">our GitHub repo</a>!</p>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions oh_queue/static/js/components/admin_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AdminLayout extends React.Component {
<Switch location={location}>
<Route exact path={match.path} render={(props) => (<AdminHome state={state} {...props} />)} />
<Route path={`${match.path}/assignments`} render={(props) => (<AdminAssignmentsManager state={state} {...props} />)} />
<Route path={`${match.path}/tags`} render={(props) => (<AdminAssignmentsManager state={state} {...props} />)} />
<Route path={`${match.path}/locations`} render={(props) => (<AdminLocationsManager state={state} {...props} />)} />
</Switch>
</CSSTransition>
Expand Down
1 change: 1 addition & 0 deletions oh_queue/static/js/components/admin_navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class AdminNavbar extends React.Component {
if(user) {
links.push(<li key="assignments"><Link to="/admin/assignments">Assignments</Link></li>);
links.push(<li key="locations"><Link to="/admin/locations">Locations</Link></li>);
links.push(<li key="tags"><Link to="/admin/tags">Tags</Link></li>);
}

return (
Expand Down
10 changes: 10 additions & 0 deletions oh_queue/static/js/components/admin_tags_manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class AdminTagManager extends React.Component {
render() {
var {tags} = this.props.state;
return (
<div className="container">
<AdminItemsManager itemName="tag" items={tags} />
</div>
);
}
}
7 changes: 7 additions & 0 deletions oh_queue/static/js/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ class App extends React.Component {
this.state.locations[location.id] = location;
}
}
if(Array.isArray(data.tags)) {
this.state.tags = {};
for(var location of data.tags) {
this.state.tags[tag.id] = tag;
}
}
if(Array.isArray(data.tickets)) {
for (var ticket of data.tickets) {
setTicket(this.state, ticket);
Expand Down Expand Up @@ -106,6 +112,7 @@ class App extends React.Component {
case 'update_location':
if(isStaff(this.state) && ticket.status === 'pending') {
var assignment = ticketAssignment(this.state, ticket);
var tag = ticketTag(this.state, ticket);
var location = ticketLocation(this.state, ticket);
var question = ticketQuestion(this.state, ticket);
notifyUser('New request for ' + assignment.name + ' ' + question,
Expand Down
13 changes: 9 additions & 4 deletions oh_queue/static/js/components/filter_controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,31 @@ class FilterControls extends React.Component {
assignment_id: $('#assignment').val(),
location_id: $('#location').val(),
question: $('#question').val(),
tag_id: $('#tag').val(),
});
}

render() {
let {filter, state} = this.props;
let {assignments, locations} = state;
let {assignments, locations, tags} = state;

let filteredAssignments = Object.values(assignments).sort((a, b) => a.name.localeCompare(b.name));
let filteredLocations = Object.values(locations).sort((a, b) => a.name.localeCompare(b.name));

let filteredTags = Object.values(tags).sort((a, b) => a.name.localeCompare(b.name));

return (
<div className="row form-group form-group-lg">
<div className="col-xs-12 col-sm-4 filter-field">
<SelectPicker options={filteredAssignments} emptyOption="Any Assignment" className="selectpicker form-control" data-live-search="true" data-size="8" data-width="100%" data-style="btn-lg btn-default" id="assignment" name="assignment" title="Assignment" onChange={this.updateFilter}/>
<SelectPicker options={filteredAssignments} emptyOption="Any Assignment" className="selectpicker form-control" data-live-search="true" data-size="8" data-width="75%" data-style="btn-lg btn-default" id="assignment" name="assignment" title="Assignment" onChange={this.updateFilter}/>
</div>
<div className="col-xs-12 col-sm-4 filter-field">
<input className="form-control" type="text" id="question" name="question" title="Question" placeholder="Question" onChange={this.updateFilter}/>
</div>
<div className="col-xs-12 col-sm-4 filter-field">
<SelectPicker options={filteredLocations} emptyOption="Any Location" className="selectpicker form-control" id="location" data-width="100%" data-style="btn-lg btn-default" name="location" title="Location" onChange={this.updateFilter}/>
<SelectPicker options={filteredLocations} emptyOption="Any Location" className="selectpicker form-control" id="location" data-width="75%" data-style="btn-lg btn-default" name="location" title="Location" onChange={this.updateFilter}/>
</div>
<div className="col-xs-12 col-sm-4 filter-field">
<SelectPicker options={filteredTags} emptyOption="Any Tag" className="selectpicker form-control" data-live-search="true" data-size="8" data-width="75%" data-style="btn-lg btn-default" id="tag" name="tag" title="Tag" onChange={this.updateFilter}/>
</div>
<hr></hr>
</div>
Expand Down
17 changes: 16 additions & 1 deletion oh_queue/static/js/components/request_form.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
function initializeToggle(toggle) {
if(!toggle) return;
$(toggle).bootstrapToggle();
}

let RequestForm = ({state}) => {
let submit = (e) => {
e.preventDefault();
Expand All @@ -13,10 +18,11 @@ let RequestForm = ({state}) => {
app.makeRequest('create', formData, true);
};

let {assignments, locations} = state;
let {assignments, locations, tag} = state;

let filteredAssignments = Object.values(assignments).filter((assignment) => assignment.visible).sort((a, b) => a.name.localeCompare(b.name));
let filteredLocations = Object.values(locations).filter((location) => location.visible).sort((a, b) => a.name.localeCompare(b.name));
let filteredTags = Object.values(tags).filter((tag) => location.visible).sort((a, b) => a.name.localeCompare(b.name));

return (
<form id="request-form">
Expand All @@ -34,6 +40,15 @@ let RequestForm = ({state}) => {
</div>
</div>
</div>
<div className="form-group form-group-lg">
<div className="input-group">
<div className="btn-group btn-group-lg" role="group" aria-label="Basic example">
<button type="button" className="btn btn-primary">Debugging</button>
<button type="button" className="btn btn-default">Content Help</button>
</div>
</div>

</div>
</form>
);
};
1 change: 1 addition & 0 deletions oh_queue/static/js/components/ticket.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
let Ticket = ({state, ticket}) => {
let assignment = ticketAssignment(app.state, ticket);
let location = ticketLocation(app.state, ticket);
let tag = ticketTag(app.state, ticket);

var status;
if (ticket.status === 'pending') {
Expand Down
1 change: 1 addition & 0 deletions oh_queue/static/js/components/ticket_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class TicketLayout extends React.Component {

let assignment = ticketAssignment(state, ticket);
let location = ticketLocation(state, ticket);
let tag = ticketTag(state, ticket);
let question = ticketQuestion(state, ticket);

return (
Expand Down
20 changes: 20 additions & 0 deletions oh_queue/static/js/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Ticket = {
updated: ?string,
location_id: number,
assignment_id: number,
tag_id: number,
question: string,
description: ?string,
helper: ?User,
Expand All @@ -36,10 +37,17 @@ type TicketLocation = {
name: string
};

/* added */
type TicketTag = {
id: number,
name: string
}

type Filter = {
/* Selected options. null means do not filter by an attribute. */
assignment_id: ?number,
location_id: ?number,
tag_id: ?number,
question: ?string,
};

Expand All @@ -61,6 +69,8 @@ type State = {
assignments: Map<number, TicketAssignment>,
/* Ticket locations */
locations: Map<number, TicketLocation>,
/* Ticket tags */
tags: Map<number, TicketTag>,
/* All known tickets, including ones that have been resolved or deleted.
* We may have to load past tickets asynchronously though.
* This is an ES6 Map from ticket ID to the ticket data.
Expand All @@ -83,11 +93,13 @@ let initialState: State = {
offline: true,
assignments: {},
locations: {},
tags: {},
tickets: new Map(),
loadingTickets: new Set(),
filter: {
location_id: null,
assignment_id: null,
tag_id: null,
question: null,
},
queueTabIndex: 0,
Expand Down Expand Up @@ -126,6 +138,10 @@ function ticketLocation(state: State, ticket: Ticket): TicketLocation {
return state.locations[ticket.location_id];
}

function ticketTag(state: State, ticket: Ticket): TicketTag {
return state.tags[ticket.tag_id];
}

function ticketQuestion(state: State, ticket: Ticket): string {
var question = ticket.question;
if(!isNaN(question)) {
Expand Down Expand Up @@ -220,6 +236,10 @@ function applyFilter(filter: Filter, tickets: Array<Ticket>): Array<Ticket> {
if (!isNaN(locationId)) {
tickets = tickets.filter((ticket) => ticket.location_id === locationId);
}
let tagId = parseInt(filter.tag_id);
if (!isNaN(locationID)) {
tickets = tickets.filter((ticket) => ticket.tag_id === tagId);
}
if (filter.question) {
tickets = tickets.filter((ticket) => ticket.question === filter.question);
}
Expand Down
Loading