def _search_series(conference=False): info = to_dict(request.args, search_array=SeriesSearchArray(conference=conference)) if "search_type" not in info: info["seminar_online"] = True info["daterange"] = info.get("daterange", datetime.now(current_user.tz).strftime("%B %d, %Y -")) try: seminar_count = int(info["seminar_count"]) seminar_start = int(info["seminar_start"]) if seminar_start < 0: seminar_start += (1 - (seminar_start + 1) // seminar_count) * seminar_count except (KeyError, ValueError): seminar_count = info["seminar_count"] = 50 seminar_start = info["seminar_start"] = 0 seminar_query, org_query = {"is_conference": conference}, {} seminars_parser(info, seminar_query, org_query, conference=conference) res = [s for s in seminars_search(seminar_query, organizer_dict=all_organizers(org_query))] # process query again with keywords applied to seminar_organizers rather than seminars if "keywords" in info: seminar_query, org_query = {"is_conference": conference}, {} seminars_parser(info, seminar_query, org_query, org_keywords=True, conference=conference) res += list(seminars_search(seminar_query, organizer_dict=all_organizers(org_query))) info["results"] = date_sorted(res) if conference else next_talk_sorted(res) subsection = "conferences" if conference else "seminars" title = "Search " + ("conferences" if conference else "seminar series") return render_template( "search_seminars.html", title=title, info=info, section="Search", subsection=subsection, bread=None, is_conference=conference, )
def _series_index(query, sort=None, subsection=None, conference=True, past=False, keywords=""): search_array = SeriesSearchArray(conference=conference, past=past) info = to_dict(read_search_cookie(search_array), search_array=search_array) info.update(request.args) if keywords: info["keywords"] = keywords query = dict(query) if conference: # Be permissive on end-date since we don't want to miss ongoing conferences, and we could have time zone differences. # Ignore the possibility that the user/conference is in Kiribati. recent = datetime.now().date() - timedelta(days=1) query["end_date"] = {"$lt" if past else "$gte": recent} query["visibility"] = 2 # only show public talks query[ "display"] = True # don't show talks created by users who have not been endorsed kw_query = query.copy() parse_substring(info, kw_query, "keywords", series_keyword_columns()) org_query, more = {}, {} # we will be selecting talks satsifying the query and recording whether they satisfy the "more" query seminars_parser(info, more, org_query) results = list( seminars_search(kw_query, organizer_dict=all_organizers(org_query), more=more)) if info.get("keywords", ""): parse_substring(info, org_query, "keywords", organizers_keyword_columns()) results += list( seminars_search(query, organizer_dict=all_organizers(org_query), more=more)) unique = {s.shortname: s for s in results} results = [unique[key] for key in unique] series = series_sorted(results, conference=conference, reverse=past) counters = _get_counters(series) row_attributes = _get_row_attributes(series) response = make_response( render_template("browse_series.html", title="Browse " + ("past " if past else "") + ("conferences" if conference else "seminar series"), section="Browse", subsection=subsection, info=info, series_row_attributes=zip(series, row_attributes), is_conference=conference, past=past, **counters)) if request.cookies.get("topics", ""): # TODO: when we move cookie data to server with ajax calls, this will need to get updated again # For now we set the max_age to 30 years response.set_cookie("topics_dict", topic_dag.port_cookie(), max_age=60 * 60 * 24 * 365 * 30) response.set_cookie("topics", "", max_age=0) return response
def show_institution(shortname): institution = db.institutions.lookup(shortname) if institution is None: return abort(404, "Institution not found") institution = WebInstitution(shortname, data=institution) section = "Manage" if current_user.is_creator else None query = {"institutions": {"$contains": shortname}} if not current_user.is_admin: query["display"] = True # Find other institutions that are joint with seminars here others = list(set(sum(seminars_search(query, "institutions"), []))) idict = all_institutions({"shortname": {"$in": others}}) events = next_talk_sorted( list( seminars_search(query, organizer_dict=all_organizers(), institution_dict=idict))) seminars = [S for S in events if not S.is_conference] conferences = [S for S in events if S.is_conference] conferences.sort(key=lambda S: (S.start_date, S.name)) return render_template( "institution.html", seminars=seminars, conferences=conferences, title="View institution", institution=institution, section=section, subsection="viewinst", )
def _series_index(query, sort=None, subsection=None, conference=True, past=False): search_array = SeriesSearchArray(conference=conference, past=past) info = to_dict(read_search_cookie(search_array), search_array=search_array) info.update(request.args) query = dict(query) parse_substring(info, query, "keywords", ["name", "description", "homepage", "shortname", "comments"]) more = {} # we will be selecting talks satsifying the query and recording whether they satisfy the "more" query seminars_parser(info, more) query["visibility"] = 2 print(info, more) if conference: # Be permissive on end-date since we don't want to miss ongoing conferences, and we could have time zone differences. Ignore the possibility that the user/conference is in Kiribati. recent = datetime.now().date() - timedelta(days=1) if past: query["end_date"] = {"$lt": recent} else: query["end_date"] = {"$gte": recent} if sort is None: if past: sort = [("end_date", -1), ("start_date", -1), "name"] else: sort = ["start_date", "end_date", "name"] if sort is None: # not conferences # We don't currently call this case in the past, but if we add it we probably # need a last_talk_sorted that sorts by end time of last talk in reverse order series = next_talk_sorted(seminars_search(query, organizer_dict=all_organizers(), more=more)) else: series = list(seminars_search(query, sort=sort, organizer_dict=all_organizers(), more=more)) counters = _get_counters(series) row_attributes = _get_row_attributes(series) title = "Browse conferences" if conference else "Browse seminar series" response = make_response(render_template( "browse_series.html", title=title, section="Browse", subsection=subsection, info=info, series_row_attributes=zip(series, row_attributes), is_conference=conference, past=past, **counters )) if request.cookies.get("topics", ""): # TODO: when we move cookie data to server with ajax calls, this will need to get updated again # For now we set the max_age to 30 years response.set_cookie("topics_dict", topic_dag.port_cookie(), max_age=60*60*24*365*30) response.set_cookie("topics", "", max_age=0) return response
def search_talks(version=0): if version != 0: raise version_error(version) if request.method == "POST": raw_data = get_request_json() query = raw_data.pop("query", {}) projection = raw_data.pop("projection", 1) # FIXME # tz = raw_data.pop("timezone", "UTC") else: query = get_request_args_json() projection = 1 raw_data = {} query["hidden"] = False visible_series = set(seminars_search({"visibility": 2}, "shortname")) # TODO: Need to check visibility on the seminar try: results = talks_search(query, projection, objects=False, **raw_data) except Exception as err: raise APIError({ "code": "search_error", "description": "error in executing search", "error": str(err) }) results = [rec for rec in results if rec["seminar_id"] in visible_series] ans = {"code": "success", "results": results} callback = raw_data.get("callback", False) return str_jsonify(ans, callback)
def show_institution(shortname): institution = db.institutions.lookup(shortname) if institution is None: return abort(404, "Institution not found") institution = WebInstitution(shortname, data=institution) section = "Manage" if current_user.is_creator else None query = {"institutions": {"$contains": shortname}} if not current_user.is_admin: query["display"] = True events = list( seminars_search( query, sort=["weekday", "start_time", "name"], organizer_dict=all_organizers(), ) ) seminars = [S for S in events if not S.is_conference] conferences = [S for S in events if S.is_conference] conferences.sort(key=lambda S: (S.start_date, S.name)) return render_template( "institution.html", seminars=seminars, conferences=conferences, title="View institution", institution=institution, section=section, subsection="viewinst", )
def search_series(version=0): if version != 0: raise version_error(version) if request.method == "POST": raw_data = get_request_json() query = raw_data.pop("query", {}) # FIXME # projection = raw_data.pop("projection", 1) tz = raw_data.pop("timezone", "UTC") else: query = get_request_args_json() tz = current_user.tz # Is this the right choice? for col, val in query.items(): if col in db.seminars.col_type: query[col] = process_user_input(val, col, db.seminars.col_type[col], tz) else: raise APIError({"code": "unknown_column", "col": col, "description": "%s not a column of seminars" % col}) raw_data = {} query["visibility"] = 2 # TODO: encode the times.... try: results = list(seminars_search(query, objects=False, sanitized=True, **raw_data)) except Exception as err: raise APIError({"code": "search_error", "description": "error in executing search", "error": str(err)}) ans = {"code": "success", "results": results} callback = raw_data.get("callback", False) return str_jsonify(ans, callback)
def ams(): seminars = next_talk_sorted( seminars_search( query={"topics": { '$contains': "math" }}, organizer_dict=all_organizers(), )) from collections import defaultdict math_topics = { rec["topic_id"]: rec["name"].capitalize() for rec in db.new_topics.search({ "topic_id": { "$in": list(db.new_topics.lookup("math", "children")) } }) } seminars_dict = defaultdict(list) for sem in seminars: for topic in sem.topics: if topic in math_topics: seminars_dict[topic].append(sem) return render_template("ams.html", title="AMS example", math_topics=sorted(math_topics.items(), key=lambda x: x[1]), seminars_dict=seminars_dict)
def _search_series(conference): info = to_dict(request.args, search_array=SemSearchArray()) if "search_type" not in info: info["seminar_online"] = True try: seminar_count = int(info["seminar_count"]) seminar_start = int(info["seminar_start"]) if seminar_start < 0: seminar_start += ( 1 - (seminar_start + 1) // seminar_count) * seminar_count except (KeyError, ValueError): seminar_count = info["seminar_count"] = 50 seminar_start = info["seminar_start"] = 0 seminar_query = {"is_conference": conference} seminars_parser(info, seminar_query) # Ideally we would do the following with a single join query, but the backend doesn't support joins yet. # Instead, we use a function that returns a dictionary of all next talks as a function of seminar id. # One downside of this approach is that we have to retrieve ALL seminars, which we're currently doing anyway. # The second downside is that we need to do two queries. print(seminar_query) info["results"] = next_talk_sorted( seminars_search(seminar_query, organizer_dict=all_organizers())) print(len(info["results"])) return render_template("search_seminars.html", title="Search seminars", info=info, section="Search", subsection="seminars", bread=None, is_conference=conference)
def parse_institution_talk(info, query): if info.get("institution"): sub_query = {} # one day we will do joins parse_institution_sem(info, sub_query) sem_shortnames = list(seminars_search(sub_query, "shortname")) query["seminar_id"] = {"$in": sem_shortnames}
def make_creator(self, email, endorser): with DelayCommit(self): db.users.update({"email": ilike_query(email)}, {"creator": True, "endorser": endorser}, restat=False) # Update all of this user's created seminars and talks db.seminars.update({"owner": ilike_query(email)}, {"display": True}) # Could do this with a join... for sem in seminars_search({"owner": ilike_query(email)}, "shortname"): db.talks.update({"seminar_id": sem}, {"display": True}, restat=False)
def review_api(): decision = request.form.get("submit") series = set() for series_id in db.seminar_organizers.search( {"email": ilike_query(current_user.email)}, "seminar_id"): series.add(series_id) for series_id in seminars_search( {"owner": ilike_query(current_user.email)}, "shortname", include_pending=True): series.add(series_id) series = list(series) if decision == "approve": db.seminars.update( { "shortname": { "$in": series }, "by_api": True, "display": False }, {"display": True}, restat=False) db.talks.update( { "seminar_id": { "$in": series }, "by_api": True, "display": False }, {"display": True}, restat=False) else: db.seminars.delete( { "shortname": { "$in": series }, "by_api": True, "display": False }, restat=False) db.talks.delete( { "seminar_id": { "$in": series }, "by_api": True, "display": False }, restat=False) # Need to check whether new seminars might have been completely deleted for series_id in series: if db.seminars.lookup(series_id) is None: db.seminar_organizers.delete({"seminar_id": series_id}) return redirect(url_for("create.index"))
def make_creator(self, email, endorser): with DelayCommit(self): db.users.update({"email": email}, {"creator": True, "endorser": endorser}) # Update all of this user's created seminars and talks db.seminars.update({"owner": email}, {"display": True}) # Could do this with a join... from seminars.seminar import seminars_search for sem in seminars_search({"owner": email}, "shortname"): db.talks.update({"seminar_id": sem}, {"display": True})
def export_dev_db(folder, users, sep="\t"): db.copy_to(['new_topics'], folder, sep=sep) # We only export the most recent version in case people removed information they didn't want public def approve_all(by_col): return True def approve_none(by_col): return False # Seminars table write_content_table(folder, db.seminars, " WHERE visibility=2 AND deleted=false", seminar_selecter, approve_all, users, sep) visible_seminars = set(seminars_search({"visibility": 2}, "shortname")) # Talks table def approve_row(by_col): return by_col["seminar_id"] in visible_seminars write_content_table(folder, db.talks, " WHERE hidden=false AND deleted=false", talk_selecter, approve_row, users, sep) user_selecter = basic_selecter(db.users) def approve_row(by_col): return by_col["email"] in users write_content_table(folder, db.users, "", user_selecter, approve_row, users, sep) institutions_selecter = basic_selecter(db.institutions) write_content_table(folder, db.institutions, "", institutions_selecter, approve_all, users, sep) new_topics_selecter = basic_selecter(db.new_topics) write_content_table(folder, db.new_topics, "", new_topics_selecter, approve_all, users, sep) preendorsed_selecter = basic_selecter(db.preendorsed_users) write_content_table(folder, db.preendorsed_users, "", preendorsed_selecter, approve_none, users, sep) organizers_selecter = basic_selecter(db.seminar_organizers, SQL(" WHERE display=true")) write_content_table(folder, db.seminar_organizers, "", organizers_selecter, approve_all, users, sep) registrations_selecter = basic_selecter(db.talk_registrations) write_content_table(folder, db.talk_registrations, "", registrations_selecter, approve_none, users, sep)
def _series_index(query, sort=None, subsection=None, conference=True, past=False): query = dict(query) query["display"] = True query["visibility"] = 2 if conference: # Be permissive on end-date since we don't want to miss ongoing conferences, and we could have time zone differences. Ignore the possibility that the user/conference is in Kiribati. recent = datetime.now().date() - timedelta(days=1) if past: query["end_date"] = {"$lt": recent} else: query["end_date"] = {"$gte": recent} if conference and sort is None: if past: sort = [("end_date", -1), ("start_date", -1), "name"] else: sort = ["start_date", "end_date", "name"] if sort is None: # not conferences # We don't currently call this case in the past, but if we add it we probably # need a last_talk_sorted that sorts by end time of last talk in reverse order series = next_talk_sorted( seminars_search(query, organizer_dict=all_organizers())) else: series = list( seminars_search(query, sort=sort, organizer_dict=all_organizers())) counters = _get_counters(series) row_attributes = _get_row_attributes(series) title = "Browse conferences" if conference else "Browse seminar series" return render_template("browse_series.html", title=title, hide_filters=[], subjects=subject_pairs(), section="Browse", subsection=subsection, series_row_attributes=zip(series, row_attributes), is_conference=conference, **counters)
def ams(): seminars = next_talk_sorted( seminars_search(query={"subjects": { '$contains': "math" }}, organizer_dict=all_organizers())) from collections import defaultdict math_topics = { elt['subject'] + '_' + elt['abbreviation']: elt['name'].capitalize() for elt in db.topics.search() if elt['subject'] == 'math' } seminars_dict = defaultdict(list) for sem in seminars: for topic in sem.topics: if topic in math_topics: seminars_dict[topic].append(sem) return render_template("ams.html", title="AMS example", math_topics=sorted(math_topics.items(), key=lambda x: x[1]), seminars_dict=seminars_dict)
def try_to_endorse(self): if self.email_confirmed and not self.is_creator: preendorsed = db.preendorsed_users.lucky( {"email": ilike_query(self.email)}) if preendorsed: self.endorser = preendorsed[ "endorser"] # must set endorser first self.creator = True # it already saves db.preendorsed_users.delete({"email": ilike_query(self.email)}) return True # try to endorse if the user is the organizer of some seminar if self._organizer: shortname = db.seminar_organizers.lucky( {"email": ilike_query(self.email)}, "seminar_id") for owner in seminars_search({"shortname": shortname}, "owner"): owner = userdb.lookup(owner, ["creator", "id"]) if owner and owner.get("creator"): self.endorser = owner["id"] # must set endorser first self.creator = True # it already saves return True return False
def index(): # TODO: use a join for the following query seminars = {} conferences = {} deleted_seminars = [] deleted_talks = [] def key(elt): role_key = {"organizer": 0, "curator": 1, "creator": 3} return (role_key[elt[1]], elt[0].name) for rec in db.seminar_organizers.search( {"email": ilike_query(current_user.email)}, ["seminar_id", "curator"]): semid = rec["seminar_id"] role = "curator" if rec["curator"] else "organizer" seminar = WebSeminar(semid) pair = (seminar, role) if seminar.is_conference: conferences[semid] = pair else: seminars[semid] = pair role = "creator" for semid in seminars_search({"owner": ilike_query(current_user.email)}, "shortname", include_deleted=True): if semid not in seminars and semid not in conferences: seminar = WebSeminar(semid, deleted=True) # allow deleted pair = (seminar, role) if seminar.deleted: deleted_seminars.append(seminar) elif seminar.is_conference: conferences[semid] = pair else: seminars[semid] = pair seminars = sorted(seminars.values(), key=key) conferences = sorted(conferences.values(), key=key) deleted_seminars.sort(key=lambda sem: sem.name) for semid, semctr in db._execute( # ~~* is case insensitive amtch SQL(""" SELECT DISTINCT ON ({Ttalks}.{Csemid}, {Ttalks}.{Csemctr}) {Ttalks}.{Csemid}, {Ttalks}.{Csemctr} FROM {Ttalks} INNER JOIN {Tsems} ON {Ttalks}.{Csemid} = {Tsems}.{Csname} WHERE {Tsems}.{Cowner} ~~* %s AND {Ttalks}.{Cdel} = %s AND {Tsems}.{Cdel} = %s """).format( Ttalks=IdentifierWrapper("talks"), Tsems=IdentifierWrapper("seminars"), Csemid=IdentifierWrapper("seminar_id"), Csemctr=IdentifierWrapper("seminar_ctr"), Csname=IdentifierWrapper("shortname"), Cowner=IdentifierWrapper("owner"), Cdel=IdentifierWrapper("deleted"), ), [ilike_escape(current_user.email), True, False], ): talk = WebTalk(semid, semctr, deleted=True) deleted_talks.append(talk) deleted_talks.sort(key=lambda talk: (talk.seminar.name, talk.start_time)) manage = "Manage" if current_user.is_organizer else "Create" return render_template( "create_index.html", seminars=seminars, conferences=conferences, deleted_seminars=deleted_seminars, deleted_talks=deleted_talks, institution_known=institution_known, institutions=institutions(), section=manage, subsection="home", title=manage, user_is_creator=current_user.is_creator, )