From eaafd4d811e4561cf93480c72166d58b6c8bd09a Mon Sep 17 00:00:00 2001 From: Marc Billow Date: Sun, 28 May 2017 20:53:07 -0400 Subject: [PATCH 1/3] Endpoints for clearing active group and rooms --- conditional/blueprints/housing.py | 24 +++++++++++++++++++++ conditional/blueprints/member_management.py | 20 +++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/conditional/blueprints/housing.py b/conditional/blueprints/housing.py index 7326309d..763d1d5a 100644 --- a/conditional/blueprints/housing.py +++ b/conditional/blueprints/housing.py @@ -11,6 +11,7 @@ from conditional.util.ldap import ldap_get_member from conditional.util.ldap import ldap_get_roomnumber from conditional.util.ldap import ldap_get_current_students +from conditional.util.ldap import _ldap_add_member_to_group as ldap_add_member_to_group from conditional.util.flask import render_template @@ -118,6 +119,8 @@ def change_room_numbers(rmnumber): account = ldap_get_member(occupant) account.roomNumber = rmnumber log.info('api', action='%s assigned to room %s' % (occupant, rmnumber)) + ldap_add_member_to_group(account, "active") + log.info('api', action='%s marked as active because of room assignment' % occupant) # Delete any old occupants that are no longer in room. for old_occupant in [account for account in current_students if ldap_get_roomnumber(account) == str(rmnumber) @@ -138,3 +141,24 @@ def get_occupants(rmnumber): occupants = [account.uid for account in current_students if ldap_get_roomnumber(account) == str(rmnumber)] return jsonify({"room": rmnumber, "occupants": occupants}), 200 + + +@housing_bp.route('/housing', methods=['DELETE']) +def clear_all_rooms(): + log = logger.new(user_name=request.headers.get("x-webauth-user"), + request_id=str(uuid.uuid4())) + log.info('api', action='clear all room numbers') + + username = request.headers.get('x-webauth-user') + account = ldap_get_member(username) + + if not ldap_is_eval_director(account): + return "must be eval director", 403 + # Get list of current students. + current_students = ldap_get_current_students() + + # Find the current occupants and clear them. + for occupant in current_students: + log.info('api', action='remove room %s from %s' % (occupant.roomNumber, occupant.uid)) + occupant.roomNumber = None + return jsonify({"success": True}), 200 diff --git a/conditional/blueprints/member_management.py b/conditional/blueprints/member_management.py index 161c998e..7fc4d364 100644 --- a/conditional/blueprints/member_management.py +++ b/conditional/blueprints/member_management.py @@ -565,3 +565,23 @@ def get_member(uid): } return jsonify(account_dict), 200 + +@member_management_bp.route('/manage/active', methods=['DELETE']) +def clear_active_members(): + log = logger.new(user_name=request.headers.get("x-webauth-user"), + request_id=str(uuid.uuid4())) + log.info('api', action='clear active group') + + username = request.headers.get('x-webauth-user') + account = ldap_get_member(username) + + if not ldap_is_eval_director(account): + return "must be eval director", 403 + # Get the active group. + members = ldap_get_active_members() + + # Clear the active group. + for account in members: + log.info('api', action='remove %s from active status' % account.uid) + ldap_remove_member_from_group(account, 'active') + return jsonify({"success": True}), 200 From 16bed125b1538ac35e1693894bca714967aaf2c6 Mon Sep 17 00:00:00 2001 From: Marc Billow Date: Sat, 17 Jun 2017 14:50:11 -0400 Subject: [PATCH 2/3] Add new year flow --- conditional/blueprints/member_management.py | 18 ++++++++- conditional/templates/member_management.html | 5 ++- conditional/templates/new_year.html | 33 +++++++++++++++++ frontend/javascript/modules/newYear.js | 39 ++++++++++++++++++++ frontend/stylesheets/pages/_management.scss | 12 +++++- frontend/stylesheets/partials/_global.scss | 4 ++ 6 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 conditional/templates/new_year.html create mode 100644 frontend/javascript/modules/newYear.js diff --git a/conditional/blueprints/member_management.py b/conditional/blueprints/member_management.py index 7fc4d364..4f469d8c 100644 --- a/conditional/blueprints/member_management.py +++ b/conditional/blueprints/member_management.py @@ -549,7 +549,7 @@ def introductory_project_submit(): def get_member(uid): log = logger.new(user_name=request.headers.get("x-webauth-user"), request_id=str(uuid.uuid4())) - log.info('api', action='submit introductory project results') + log.info('api', action="get %s's information" & uid) username = request.headers.get('x-webauth-user') account = ldap_get_member(username) @@ -585,3 +585,19 @@ def clear_active_members(): log.info('api', action='remove %s from active status' % account.uid) ldap_remove_member_from_group(account, 'active') return jsonify({"success": True}), 200 + +@member_management_bp.route('/manage/new', methods=['GET']) +def new_year(): + log = logger.new(user_name=request.headers.get("x-webauth-user"), + request_id=str(uuid.uuid4())) + log.info('api', action='show new year page') + + username = request.headers.get('x-webauth-user') + account = ldap_get_member(username) + + if not ldap_is_eval_director(account): + return "must be eval director", 403 + + return render_template(request, + 'new_year.html', + username=username) diff --git a/conditional/templates/member_management.html b/conditional/templates/member_management.html index 3c7c7135..6235978f 100644 --- a/conditional/templates/member_management.html +++ b/conditional/templates/member_management.html @@ -27,13 +27,16 @@

Administration

Intro Accounts
{% if is_eval_director %} -
+
Site Lockdown
+ {% endif %}
diff --git a/conditional/templates/new_year.html b/conditional/templates/new_year.html new file mode 100644 index 00000000..9271d155 --- /dev/null +++ b/conditional/templates/new_year.html @@ -0,0 +1,33 @@ +{% extends "nav.html" %} +{% block title %} +New Year Guide +{% endblock %} +{% block body %} +
+
+

Welcome!

+

Is it that time of year already? Before we get started, please be careful and ready everything before continuing. Some actions taken on the next few steps can be detrimental if followed in the middle of the year. Once you are ready to proceed, click 'Begin' below.

+ Begin +
+ + +
+ + +{% endblock %} diff --git a/frontend/javascript/modules/newYear.js b/frontend/javascript/modules/newYear.js new file mode 100644 index 00000000..755cc0d0 --- /dev/null +++ b/frontend/javascript/modules/newYear.js @@ -0,0 +1,39 @@ +import FetchUtil from '../utils/fetchUtil'; + +export default class NewYear { + constructor(link) { + this.link = link; + this.step = this.link.dataset.step; + + this.endpoints = { + housing: '/housing', + active: '/manage/active' + }; + + this.render(); + } + render() { + this.link.addEventListener('click', e => { + e.preventDefault(); + + if (this.step === "welcome") { + $('#new-welcome').fadeOut(function() { + $("#new-clear").fadeIn(); + }); + } else if (this.step === "clear") { + FetchUtil.fetchWithWarning(this.endpoints.active, { + method: 'DELETE', + warningText: "This will clear active members and room assignments!", + successText: "Data successfully cleared."}, () => { + fetch(this.endpoints.housing, { + method: 'DELETE' + }) + .then($('#new-clear').fadeOut(function() { + $("#new-housing").fadeIn(); + }) + ); + }); + } + }); + } +} diff --git a/frontend/stylesheets/pages/_management.scss b/frontend/stylesheets/pages/_management.scss index f92d0a9c..23e70bc1 100644 --- a/frontend/stylesheets/pages/_management.scss +++ b/frontend/stylesheets/pages/_management.scss @@ -1,9 +1,17 @@ .switch-label { - display: inline-block; - padding: 40px 10px; + display: block; + padding: 17px 10px 10px; text-align: center; } +.btn-new-year { + margin-top: 30px; +} + +.btn-new-next { + margin: 30px 0; +} + .upload-title { padding-top: 20px; height: 55px; diff --git a/frontend/stylesheets/partials/_global.scss b/frontend/stylesheets/partials/_global.scss index b4d32def..ec9be224 100644 --- a/frontend/stylesheets/partials/_global.scss +++ b/frontend/stylesheets/partials/_global.scss @@ -88,3 +88,7 @@ tr { float: none; vertical-align: middle; } + +.hidden { + display: none; +} From 699958c42152545d4a4f9155455bdfcd18f87081 Mon Sep 17 00:00:00 2001 From: Marc Billow Date: Sat, 17 Jun 2017 17:07:54 -0400 Subject: [PATCH 3/3] Add current student pruning --- conditional/blueprints/housing.py | 4 +- conditional/blueprints/member_management.py | 36 +++++++++++++-- conditional/templates/new_year.html | 38 ++++++++++----- conditional/util/ldap.py | 12 +++++ frontend/javascript/modules/newYear.js | 51 +++++++++++++++++++-- 5 files changed, 120 insertions(+), 21 deletions(-) diff --git a/conditional/blueprints/housing.py b/conditional/blueprints/housing.py index 763d1d5a..f7382ff5 100644 --- a/conditional/blueprints/housing.py +++ b/conditional/blueprints/housing.py @@ -11,7 +11,7 @@ from conditional.util.ldap import ldap_get_member from conditional.util.ldap import ldap_get_roomnumber from conditional.util.ldap import ldap_get_current_students -from conditional.util.ldap import _ldap_add_member_to_group as ldap_add_member_to_group +from conditional.util.ldap import ldap_set_active from conditional.util.flask import render_template @@ -119,7 +119,7 @@ def change_room_numbers(rmnumber): account = ldap_get_member(occupant) account.roomNumber = rmnumber log.info('api', action='%s assigned to room %s' % (occupant, rmnumber)) - ldap_add_member_to_group(account, "active") + ldap_set_active(account) log.info('api', action='%s marked as active because of room assignment' % occupant) # Delete any old occupants that are no longer in room. for old_occupant in [account for account in current_students diff --git a/conditional/blueprints/member_management.py b/conditional/blueprints/member_management.py index 4f469d8c..abb047fb 100644 --- a/conditional/blueprints/member_management.py +++ b/conditional/blueprints/member_management.py @@ -33,8 +33,11 @@ from conditional.util.ldap import ldap_set_active from conditional.util.ldap import ldap_set_inactive from conditional.util.ldap import ldap_set_housingpoints +from conditional.util.ldap import ldap_set_current_student +from conditional.util.ldap import ldap_set_non_current_student from conditional.util.ldap import ldap_get_active_members from conditional.util.ldap import ldap_get_member +from conditional.util.ldap import ldap_get_current_students from conditional.util.ldap import _ldap_add_member_to_group as ldap_add_member_to_group from conditional.util.ldap import _ldap_remove_member_from_group as ldap_remove_member_from_group from conditional.util.ldap import _ldap_is_member_of_group as ldap_is_member_of_group @@ -549,7 +552,7 @@ def introductory_project_submit(): def get_member(uid): log = logger.new(user_name=request.headers.get("x-webauth-user"), request_id=str(uuid.uuid4())) - log.info('api', action="get %s's information" & uid) + log.info('api', action="get {}'s information".format(uid)) username = request.headers.get('x-webauth-user') account = ldap_get_member(username) @@ -583,9 +586,32 @@ def clear_active_members(): # Clear the active group. for account in members: log.info('api', action='remove %s from active status' % account.uid) - ldap_remove_member_from_group(account, 'active') + ldap_set_inactive(account) return jsonify({"success": True}), 200 + +@member_management_bp.route('/manage/current/', methods=['POST', 'DELETE']) +def remove_current_student(uid): + log = logger.new(user_name=request.headers.get("x-webauth-user"), + request_id=str(uuid.uuid4())) + + + username = request.headers.get('x-webauth-user') + account = ldap_get_member(username) + + if not ldap_is_eval_director(account): + return "must be eval director", 403 + + member = ldap_get_member(uid) + if request.method == 'DELETE': + log.info('api', action='remove {} from current_student'.format(uid)) + ldap_set_non_current_student(member) + elif request.method == 'POST': + log.info('api', action='add {} to current_student'.format(uid)) + ldap_set_current_student(member) + return jsonify({"success": True}), 200 + + @member_management_bp.route('/manage/new', methods=['GET']) def new_year(): log = logger.new(user_name=request.headers.get("x-webauth-user"), @@ -598,6 +624,10 @@ def new_year(): if not ldap_is_eval_director(account): return "must be eval director", 403 + current_students = ldap_get_current_students() + + return render_template(request, 'new_year.html', - username=username) + username=username, + current_students=current_students) diff --git a/conditional/templates/new_year.html b/conditional/templates/new_year.html index 9271d155..b8d01273 100644 --- a/conditional/templates/new_year.html +++ b/conditional/templates/new_year.html @@ -7,27 +7,43 @@

Welcome!

Is it that time of year already? Before we get started, please be careful and ready everything before continuing. Some actions taken on the next few steps can be detrimental if followed in the middle of the year. Once you are ready to proceed, click 'Begin' below.

- Begin + Begin
+ - - {% endblock %} diff --git a/conditional/util/ldap.py b/conditional/util/ldap.py index cbe140b1..443c877d 100644 --- a/conditional/util/ldap.py +++ b/conditional/util/ldap.py @@ -121,6 +121,18 @@ def ldap_set_inactive(account): ldap_get_member.cache_clear() +def ldap_set_current_student(account): + _ldap_add_member_to_group(account, 'current_student') + ldap_get_current_students.cache_clear() + ldap_get_member.cache_clear() + + +def ldap_set_non_current_student(account): + _ldap_remove_member_from_group(account, 'current_student') + ldap_get_current_students.cache_clear() + ldap_get_member.cache_clear() + + def ldap_get_roomnumber(account): try: return account.roomNumber diff --git a/frontend/javascript/modules/newYear.js b/frontend/javascript/modules/newYear.js index 755cc0d0..0d8ba6ae 100644 --- a/frontend/javascript/modules/newYear.js +++ b/frontend/javascript/modules/newYear.js @@ -1,13 +1,18 @@ import FetchUtil from '../utils/fetchUtil'; +import Exception from "../exceptions/exception"; +import FetchException from "../exceptions/fetchException"; +import sweetAlert from "../../../node_modules/bootstrap-sweetalert/dev/sweetalert.es6.js"; // eslint-disable-line max-len export default class NewYear { constructor(link) { this.link = link; this.step = this.link.dataset.step; + this.uid = this.link.dataset.uid; this.endpoints = { housing: '/housing', - active: '/manage/active' + active: '/manage/active', + current: '/manage/current/' }; this.render(); @@ -17,7 +22,7 @@ export default class NewYear { e.preventDefault(); if (this.step === "welcome") { - $('#new-welcome').fadeOut(function() { + $('#new-welcome').fadeOut(() => { $("#new-clear").fadeIn(); }); } else if (this.step === "clear") { @@ -28,11 +33,47 @@ export default class NewYear { fetch(this.endpoints.housing, { method: 'DELETE' }) - .then($('#new-clear').fadeOut(function() { - $("#new-housing").fadeIn(); + .then($('#new-clear').fadeOut(() => { + $("#new-current").fadeIn(); }) - ); + ).catch(error => { + sweetAlert("Uh oh...", "We're having trouble submitting that " + + "action right now. Please try again later.", "error"); + throw new Exception(FetchException.REQUEST_FAILED, error); + }); }); + } else if (this.uid) { + if ($('#rem-' + this.uid).is(":visible")) { + fetch(this.endpoints.current + this.uid, { + method: 'DELETE' + }).then(() => { + $('#rem-' + this.uid).hide(); + $('#add-' + this.uid).show(); + var userRow = $('#row-' + this.uid)[0]; + userRow.style.setProperty("text-decoration", "line-through"); + }).catch(error => { + sweetAlert("Uh oh...", "We're having trouble submitting that " + + "action right now. Please try again later.", "error"); + throw new Exception(FetchException.REQUEST_FAILED, error); + }); + } else { + fetch(this.endpoints.current + this.uid, { + method: 'POST' + }).then(() => { + $('#add-' + this.uid).hide(); + $('#rem-' + this.uid).show(); + var lineRow = $('#row-' + this.uid)[0]; + lineRow.style.setProperty("text-decoration", "none"); + }).catch(error => { + sweetAlert("Uh oh...", "We're having trouble submitting that " + + "action right now. Please try again later.", "error"); + throw new Exception(FetchException.REQUEST_FAILED, error); + }); + } + } else if (this.step === "current") { + $('#new-current').fadeOut(function() { + $("#new-housing").fadeIn(); + }); } }); }