Skip to content

New Year Flow #143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 18, 2017
Merged
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
24 changes: 24 additions & 0 deletions conditional/blueprints/housing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_set_active

from conditional.util.flask import render_template

Expand Down Expand Up @@ -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_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
if ldap_get_roomnumber(account) == str(rmnumber)
Expand All @@ -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
68 changes: 67 additions & 1 deletion conditional/blueprints/member_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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='submit introductory project results')
log.info('api', action="get {}'s information".format(uid))

username = request.headers.get('x-webauth-user')
account = ldap_get_member(username)
Expand All @@ -565,3 +568,66 @@ 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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, please use Python 3 string formatting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once this is merged I am going to be re-doing all of our logging...

ldap_set_inactive(account)
return jsonify({"success": True}), 200


@member_management_bp.route('/manage/current/<uid>', 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"),
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

current_students = ldap_get_current_students()


return render_template(request,
'new_year.html',
username=username,
current_students=current_students)
5 changes: 4 additions & 1 deletion conditional/templates/member_management.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ <h3 class="panel-title">Administration</h3>
<div class="stat-title">Intro Accounts</div>
</div>
{% if is_eval_director %}
<div class="col-xs-12 col-sm-4 align-center">
<div class="col-xs-6 col-sm-2 align-center">
<div class="material-switch">
<div class="switch-label">Site Lockdown</div>
<input type="checkbox" id="siteLockdownSwitch" name="siteLockdownSwitch" data-module="siteSettings" data-setting="siteLockdown"{% if site_lockdown %} checked{% endif %}>
<label for="siteLockdownSwitch" class="label-primary"></label>
</div>
</div>
<div class="col-xs-6 col-sm-2 align-center">
<a href="/manage/new" class="btn btn-danger btn-sm btn-new-year"><span class="glyphicon glyphicon-repeat"></span> New Year</a>
</div>
{% endif %}
</div>
</div>
Expand Down
49 changes: 49 additions & 0 deletions conditional/templates/new_year.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{% extends "nav.html" %}
{% block title %}
New Year Guide
{% endblock %}
{% block body %}
<div class="container main">
<div id="new-welcome">
<h3 class="page-title">Welcome!</h3>
<p>Is it that time of year already? Before we get started, please <strong>be careful and ready everything before continuing</strong>. 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.</p>
<a href="#" data-module="newYear" data-step="welcome" class="btn btn-primary btn-new-next center-block"><span class="glyphicon glyphicon-ok"></span> Begin</a>
</div>
<div id="new-clear" style="display: none;">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you added a .hidden class, please use that instead of inline style here.

<h3 class="page-title">Clear Active Members and Floor Roster</h3>
<p>This is the scary part. In order to get everything ready for next year, we need to clear everyone from Active status and then clear the housing board. Once we get a fresh start, we will forward you onto the housing page to fill out the new housing board.</p>
<a href="#" data-module="newYear" data-step="clear" class="btn btn-primary btn-new-next center-block"><span class="glyphicon glyphicon-erase"></span> Clear Active Group and Housing Board</a>
</div>
<div id="new-current" style="display: none;">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

<h3 class="page-title">Prune Current Students Group</h3>
<p>Take a second and scroll down the list, remove anyone who has graduated. Anyone in this list who is in good standing can become active, so it is important it is correct.</p>
<table class="table table-striped no-bottom-margin" data-module="table" data-searchable="true" data-sort-column="0" data-sort-order="asc" data-length-changable="true">
<thead>
<tr>
<th>Name</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
{% for student in current_students %}
<tr>
<td id="row-{{student.uid}}">{{student.displayName}}</td>
<td width=100px>
<a href="#" data-module="newYear" data-uid="{{student.uid}}">
<span id="rem-{{student.uid}}" class="glyphicon glyphicon-remove red align-center" style="width: 100%"></span>
<span id="add-{{student.uid}}" class="glyphicon glyphicon-plus green align-center" style="width: 100%; display: none;"></span>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="#" data-module="newYear" data-step="current" class="btn btn-primary btn-new-next center-block"><span class="glyphicon glyphicon-ok"></span> Next Step</a>
</div>
<div id="new-housing" style="display: none;">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

<h3 class="page-title">That was easy!</h3>
<p>The next and final step is to go through and populate the housing board, the button below will even take you there. Just a note: adding people will automatically mark them as active, since they will be charged dues.</p>
<a href="/housing" class="btn btn-primary btn-new-next center-block"><span class="glyphicon glyphicon-ok"></span> Onward and Upward!</a>
</div>
</div>
{% endblock %}
12 changes: 12 additions & 0 deletions conditional/util/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
80 changes: 80 additions & 0 deletions frontend/javascript/modules/newYear.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
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',
current: '/manage/current/'
};

this.render();
}
render() {
this.link.addEventListener('click', e => {
e.preventDefault();

if (this.step === "welcome") {
$('#new-welcome').fadeOut(() => {
$("#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, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should have a .catch() attached to the promise to handle failure cases. Take a look at FetchUtil for an example.

method: 'DELETE'
})
.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();
});
}
});
}
}
12 changes: 10 additions & 2 deletions frontend/stylesheets/pages/_management.scss
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
4 changes: 4 additions & 0 deletions frontend/stylesheets/partials/_global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ tr {
float: none;
vertical-align: middle;
}

.hidden {
display: none;
}