Browse Source

Merge branch 'master' of github.com:nisstyre56/TextbookEngine

master
wes 9 years ago
parent
commit
ce963b4d4b
  1. 6
      Makefile
  2. 5
      src/goasearch.py
  3. 13
      src/mcmaster/classes.py
  4. 2
      src/scripts/book.tag
  5. 4
      src/scripts/class.tag
  6. 11
      src/scripts/results.tag
  7. 26
      src/scripts/search.js
  8. 80
      src/scripts/search.tag
  9. 7
      src/search.py
  10. 85
      src/styles/search.scss
  11. 22
      src/templates/search.html

6
Makefile

@ -21,8 +21,8 @@ clean:
install: install:
$(MAKE) clean; $(MAKE) clean;
$(MAKE); $(MAKE);
rm -rf ${SRV_ROOT}build/; rm -rf /srv/http/build/;
cp -rT ./build ${SRV_ROOT}build/; cp -rT ./build /srv/http/build/;
cp -rT ./build/scripts/ ${SRV_ROOT}scripts/; cp -rT ./build/scripts/ ${SRV_ROOT}scripts/;
cp -rT ./build/styles/ ${SRV_ROOT}styles/; cp -rT ./build/styles/ ${SRV_ROOT}styles/;
cp search.ini ${SRV_ROOT}build/; cp search.ini /srv/http/build/;

5
src/goasearch.py

@ -1,7 +1,8 @@
#! /usr/bin/python2 #! /usr/bin/python2
from search import indexListing from search import indexListing
from textbookExceptions import UnIndexable from textbookExceptions import UnIndexable
from mcmaster.classes import allCourses, classToJSON, indexListing from mcmaster.classes import allCourses
from search import indexListing, createIndex
from itertools import imap from itertools import imap
try: try:
@ -11,7 +12,7 @@ except Exception as e:
print e print e
print "Downloading course info" print "Downloading course info"
for c in imap(classToJSON, allCourses()): for c in allCourses():
try: try:
print indexListing(c) print indexListing(c)
except UnIndexable as e: except UnIndexable as e:

13
src/mcmaster/classes.py

@ -118,10 +118,19 @@ class Section(dict):
self.time = time.encode("UTF-8") self.time = time.encode("UTF-8")
self.loc = loc.encode("UTF-8") self.loc = loc.encode("UTF-8")
self.prof = prof.encode("UTF-8") self.prof = prof.encode("UTF-8")
self.sem = sem.encode("UTF-8") self._sem = sem.encode("UTF-8")
self._date = False self._date = False
self._day = False self._day = False
@property
def sem(self):
if self._sem == fall:
return "Fall"
elif self._sem == winter:
return "Winter"
else:
return "Spring/Summer"
@property @property
def date(self): def date(self):
if self.time != "TBA": if self.time != "TBA":
@ -341,7 +350,7 @@ def getCourses(semester, threadcount=10):
def allCourses(): def allCourses():
return chain.from_iterable( return chain.from_iterable(
(getCourses(sem, threadcount=10) (getCourses(sem, threadcount=25)
for sem in (fall, winter, spring_summer))) for sem in (fall, winter, spring_summer)))
if __name__ == "__main__": if __name__ == "__main__":

2
src/scripts/book.tag

@ -23,7 +23,7 @@
</button> </button>
</a> </a>
</p> </p>
<p class="centered" if={ noResources }> <p class="centered wraptext" if={ noResources }>
Couldn't find anything, sorry :( Couldn't find anything, sorry :(
</p> </p>
</dd> </dd>

4
src/scripts/class.tag

@ -21,8 +21,8 @@
</div> </div>
</div> </div>
<div class="toast" if={ !books }> <div class="toast" if={ !books }>
<p>No books at this time</p> <p class="wraptext">No books at this time</p>
<p>Check back later, or verify the course has books</p> <p class="wraptext">Check back later, or verify the course has books</p>
</div> </div>
</class> </class>

11
src/scripts/results.tag

@ -1,13 +1,22 @@
<results> <results>
<div class="courses container"> <div if={notLoading} class="courses container">
<row class="course-row columns" each={ rows } data="{ this }" classrow={ row }></row> <row class="course-row columns" each={ rows } data="{ this }" classrow={ row }></row>
</div> </div>
this.rows = []; this.rows = [];
var self = this; var self = this;
results_passer.on("loading",
function() {
self.notLoading = false;
self.update();
});
results_passer.on("new_results", results_passer.on("new_results",
function(data) { function(data) {
console.log("new search results detected"); console.log("new search results detected");
console.log(data);
self.rows = data; self.rows = data;
self.notLoading = true;
self.update(); self.update();
}); });
</results> </results>

26
src/scripts/search.js

@ -8,11 +8,9 @@ function makeResourceGetter(self) {
"author" : this.bookauthor "author" : this.bookauthor
}; };
var url = "/search/resources"; var url = "/search/resources";
console.log(params);
$.getJSON(url, { $.getJSON(url, {
data : JSON.stringify(params) data : JSON.stringify(params)
}).done(function(results) { }).done(function(results) {
if (results.iarchive) { if (results.iarchive) {
self.iarchive = results.iarchive[0]; self.iarchive = results.iarchive[0];
} }
@ -50,8 +48,11 @@ function ResultsPasser() {
var results_passer = new ResultsPasser(); var results_passer = new ResultsPasser();
riot.mount("search"); riot.mount("search", {
riot.mount("results"); showHelp : false,
booksLoading : false
});
riot.mount("results", {notLoading : true});
function autocomplete(element, endpoint) { function autocomplete(element, endpoint) {
// The element should be an input class // The element should be an input class
@ -65,7 +66,24 @@ function autocomplete(element, endpoint) {
}); });
} }
function realBook(book) {
var noAdoption = book.booktitle.indexOf("No Adoption");
var noBooks = book.booktitle.indexOf("No Textbooks");
return ((noAdoption == -1) &&
(noBooks == -1));
}
function filterCourses(courses) { function filterCourses(courses) {
var books;
for (var i in courses) {
books = courses[i].books;
if ((books.length > 0) &&
(!realBook(books[0]))) {
courses[i].books = "";
}
}
return courses.filter( return courses.filter(
function (c) { function (c) {
return c.prof != "Staff"; return c.prof != "Staff";

80
src/scripts/search.tag

@ -1,30 +1,84 @@
<search> <search>
<form class="form-horizontal search-form" onsubmit={ submit } type="submit"method="get"> <form class="form-horizontal search-form" onsubmit={ submit.bind(this) } type="submit"method="get">
<div class="form-group"> <div class="form-group">
<div class="col-sm-8 form-item"> <div class="container">
<input class="form-input" placeholder="Description" type="text" name="title"/> <div class="columns">
</div> <div class="col-sm-8 form-item">
<div class="col-sm-2 form-item"> <input onfocus={ showHelp }
<select class="form-select" aria-labelledby="dLabel" name="sem"> class="form-input"
placeholder="Description"
type="text"
name="title"/>
</div>
<div class="col-sm-2 form-item">
<select class="form-select" aria-labelledby="dLabel" name="sem">
<option value="Fall">Fall</option> <option value="Fall">Fall</option>
<option value="Winter" selected>Winter</option> <option value="Winter" selected>Winter</option>
<option value="Summer">Summer</option> <option value="Spring/Summer">Spring/Summer</option>
</select> </select>
</div> </div>
<div class="col-sm-2 form-item"> <div class="col-sm-2 form-item">
<button class="btn btn-primary" type="submit">Search</button> <button class="btn btn-primary" type="submit">Search</button>
</div>
</div>
</div> </div>
</div> </div>
</form> </form>
<div if={ opts.showHelp }
class="help-toast toast toast-primary">
<button onclick={ clearHelp }
class="btn btn-clear float-right">
</button>
Type keywords of your course's name or the course code (e.g. PSYCH 2B03)
</div>
<div if={ opts.booksLoading } class="search-load">
</div>
</search> </search>
this.showedHelp = false;
this.waiting = false;
function showHelp() {
if (!this.showedHelp) {
this.opts.showHelp = true;
this.update();
if (!waiting) {
waiting = true;
window.setTimeout(
(function() {
this.waiting = false;
clearHelpTemp.bind(this)();
}).bind(this), 10000);
}
}
}
function clearHelp() {
this.showedHelp = true;
this.opts.showHelp = false;
this.update();
}
function clearHelpTemp() {
this.opts.showHelp = false;
this.update();
}
function submit(ev) { function submit(ev) {
ev.preventDefault();
this.showedHelp = true;
this.opts.showHelp = false;
console.log("submitted"); console.log("submitted");
this.opts.booksLoading = true;
this.update();
results_passer.trigger("loading");
var params = $(ev.currentTarget).serialize(); var params = $(ev.currentTarget).serialize();
$.getJSON("/search/fc?"+params, $.getJSON("/search/fc?"+params,
function(courses) { (function(courses) {
var fcourses = filterCourses(courses); var fcourses = filterCourses(courses);
var cgroups = groupsof(3, fcourses); var cgroups = groupsof(3, fcourses);
results_passer.trigger("new_results", cgroups); results_passer.trigger("new_results", cgroups);
}); this.opts.booksLoading = false;
this.update();
}).bind(this));
} }

7
src/search.py

@ -9,6 +9,7 @@ from json import dumps, loads
from itertools import chain, imap from itertools import chain, imap
from hashlib import sha1 from hashlib import sha1
from syslog import syslog
from textbookExceptions import UnIndexable from textbookExceptions import UnIndexable
@ -106,11 +107,12 @@ def indexListing(course):
} }
""" """
courseID = hashsec(course) json_course = classToJSON(course)
courseID = hashsec(json_course)
print es.index(index="oersearch", print es.index(index="oersearch",
doc_type="course", doc_type="course",
id=courseID, id=courseID,
body=course) body=json_course)
# For every course we index, we also create a resource for it # For every course we index, we also create a resource for it
# This should be an idempotent operation because we're putting it in couchdb # This should be an idempotent operation because we're putting it in couchdb
@ -169,6 +171,7 @@ def searchTerms(terms):
""" """
Run a search for courses Run a search for courses
""" """
syslog(repr(terms))
# A list of all the queries we want to run # A list of all the queries we want to run
qs = [searchers[field](term) for qs = [searchers[field](term) for

85
src/styles/search.scss

@ -6,6 +6,31 @@ header {
white-space: pre-wrap !important; white-space: pre-wrap !important;
} }
.search-load {
color: transparent !important;
min-height: 1.6rem;
pointer-events: none;
position: relative;
}
.search-load::after {
-webkit-animation: loading 500ms infinite linear;
animation: loading 500ms infinite linear;
border: .2rem solid #5764c6;
border-radius: 2.9rem;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: block;
height: 2.8rem;
left: 50%;
margin-left: -.8rem;
margin-top: -.8rem;
position: absolute;
top: 50%;
width: 3rem;
}
.body { .body {
color: #1c75bc; color: #1c75bc;
} }
@ -18,9 +43,18 @@ a {
background-color: #1c75bc !important; background-color: #1c75bc !important;
} }
.courses { @media (min-width: 1335px) {
.courses {
margin-top: 100px; margin-top: 100px;
max-width: 75%; max-width: 75%;
}
}
@media (max-width: 1366px) {
.courses {
margin-top: 100px;
max-width: 85%;
}
} }
.course { .course {
@ -34,7 +68,7 @@ a {
} }
.search-form { .search-form {
margin-top: 9%; margin-top: 6%;
-webkit-appearance: none !important; -webkit-appearance: none !important;
} }
@ -43,8 +77,9 @@ a {
} }
.form-item { .form-item {
padding-left: 15px; padding-left: 5px;
padding-right: 15px; padding-right: 5px;
margin-right: -15px;
} }
#title { #title {
@ -95,22 +130,28 @@ a {
background-image: none; background-image: none;
} }
.logo-div { @media (min-width: 480px) {
height:67px; .logo {
width:150px; margin-top: 20px;
margin-right:1%; margin-left: -175px;
margin-bottom: 0%; }
margin-top:1%; }
margin-left:2%;
background-size: 100%; @media (min-width: 480px) {
background-size: cover; .title {
-webkit-background-size: cover; margin-left: 80px;
-o-background-size: cover; }
background-size: cover; }
background-position: center center;
/*background-image: url('https://mgoal.ca/goal_transp.png');*/ .page-top {
} font-size: 15px;
width: 50% !important;
.title-div { }
font-size: 25px;
.help-toast {
background-color: rgba(28,117,188, 0.7) !important;
font-size: 0.8em;
max-width: 55%;
margin-top: -10px;
border: none;
} }

22
src/templates/search.html

@ -3,16 +3,26 @@
{{super()}} {{super()}}
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<header class="text-center nav navbar"> <header class="text-center nav navbar">
<section class="navbar-section"> <section class="centered page-top navbar-section">
<div class="title-div"> <div class="container">
<h1>TextBook Commons</h1> <div class="columns">
<h5>Type in the name of your course and start saving money on your books</h5> <div class="title column col-md-9"><h1>TextBook Commons</h1></div>
<div class="logo column col-md-3">
<figure class="avatar avatar-xl">
<img src="https://mgoal.ca/goal_small.png" />
</figure>
</div> </div>
<search class="search-form"></search> </div>
</section> </div>
<h5>Search for your course and start saving money on your books</h5>
<search></search>
</section>
</header> </header>
{% endblock %} {% endblock %}
<html> <html>
<figure class="avatar avatar-xl">
<img src="https://mgoal.ca/goal_small.png" />
</figure>
<body> <body>
{% block content %} {% block content %}

Loading…
Cancel
Save