Skip to content
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
3 changes: 3 additions & 0 deletions app/config/contributors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,7 @@ contributors:
- name: "Oluwagbayi Makinde"
username: "makindeo"
year: 2024
- name: "Bhushan Sah "
username: "sahb"
year: 2029

10 changes: 8 additions & 2 deletions app/controllers/main_routes/main_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
from app.login_manager import require_login, logout
from app.logic.getTableData import getDatatableData
from app.logic.banner import Banner
from app.models.positionHistory import PositionHistory
from app.logic.getPositions import getActivePositions


@main_bp.route('/logout', methods=['GET'])
def triggerLogout():
Expand Down Expand Up @@ -57,15 +60,18 @@ def departmentPortal(org=None,account=None):
dept = None



if g.currentUser.isLaborAdmin:
departments = list(Department.select().order_by(Department.isActive.desc(), Department.DEPT_NAME.asc()))
else:
departments = list(getDepartmentsForSupervisor(g.currentUser).order_by(Department.isActive.desc(), Department.DEPT_NAME.asc()))

positionsList, posURL = getActivePositions(dept)

return render_template('main/departmentPortal.html',
departments = departments,
department = dept)
department = dept,
positions = positionsList,
posURL = posURL)

@main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST'])
def addUserToDept():
Expand Down
45 changes: 45 additions & 0 deletions app/logic/getPositions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from app.models.positionHistory import PositionHistory

def getActivePositions(dept):
"""
Returns a list of active positions for a given department, along with their corresponding position codes.
The function filters out duplicate position codes within the same department and ensures that a position code can only be Active in ONE place at a time.
"""
if not dept:
return [], []

positions = list(PositionHistory.select()
.where(PositionHistory.department == dept, PositionHistory.status == "Active")
.order_by(PositionHistory.positionTitle.asc()))

positionsList = []
posURL = []
seenCodes = set()
# Iterate through the positions and filter out duplicates based on positionCode and department
for pos in positions:
code = pos.positionCode

# Same dept returned two Active rows with the same code (shouldn't normally happen, but guards against bad data) -> skip the duplicate
if code in seenCodes:
continue

# Enforces: A positionCode can only be Active in ONE place at a time, regardless of department or revisionDate.
# If an earlier-created Active row with this code exists in a DIFFERENT department, this one loses.
claimedElsewhere = (PositionHistory
.select()
.where(
PositionHistory.positionCode == code,
PositionHistory.status == "Active",
PositionHistory.department != dept,
PositionHistory.id < pos.id # Uses PeeWee's auto-incrementing ID to determine which row was created first.
)
.exists())

if claimedElsewhere:
continue

seenCodes.add(code) # Mark this code as seen for the current department to avoid duplicates
positionsList.append(pos.positionTitle + ": " + "(WLS " + str(pos.wls) + ")")
posURL.append(str(pos.positionCode))

return positionsList, posURL
3 changes: 2 additions & 1 deletion app/models/positionHistory.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from app.models.department import Department

class PositionHistory(baseModel):
positionTitle = CharField()
positionCode = CharField()
department = ForeignKeyField(Department)
status = CharField()
Expand All @@ -10,5 +11,5 @@ class PositionHistory(baseModel):
description = TextField(default=None)

class Meta:
indexes = ( (('positionCode', 'revisionDate', 'status'), True), )
indexes = ( (('positionCode', 'revisionDate', 'status'), False), )

27 changes: 27 additions & 0 deletions app/static/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ a {
padding: 0.5rem 1rem;
background-color: rgba(0, 0, 0, 0.03);
border-top: 1px solid rgba(0, 0, 0, 0.125);
margin-top: auto;
}

.card-footer:last-child {
Expand All @@ -264,3 +265,29 @@ a {
border-top-left-radius: calc(0.25rem - 1px);
border-top-right-radius: calc(0.25rem - 1px);
}
.site-footer {
position: fixed;
left: 280px;
right: 0;
bottom: 0;

background-color: #e9ebec;
color: #1e2433;

padding: 8px 15px;
line-height: 1.4;
box-sizing: border-box;
z-index: 101;

}

.sidebar-push {
padding-bottom: 85px;
}

@media (max-width: 991px) {
.site-footer {
left: 0;
width: 100%;
}
}
1 change: 0 additions & 1 deletion app/static/css/contributors.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
color: #ffffff;
padding: 7px 30px;
margin-top: 100px;
margin-right: 250px;
}
.container {
top: -75px;
Expand Down
31 changes: 31 additions & 0 deletions app/static/css/departmentPortal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.card {
border-radius: 1rem;
overflow: hidden;
width: 100%;
height: 100%;
min-width: 100%;
box-shadow: 2px 2px 4px rgba(100, 100, 100, 0.26);
}
.bi-suitcase-lg-fill { /* Bootstrap Icon */
border: 1px solid #c0c0c0;
border-radius: 8px;
padding: 3px 3.5px 1.5px 3.5px;
font-size: 3rem;
color:#6e6e6e;
}
.card-group {
gap: 1rem;
}
.form-group {
width: 50%;
margin-left: auto ;
margin-right:auto;
}
.card-body {
padding: 1rem 1rem;
min-width: 100%
}
.row {
display: flex;
flex-wrap: wrap;
}
20 changes: 15 additions & 5 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,20 @@
<div class="row bottom-buffer"></div>

{% block footer %}
<div class="footer">
<span><strong>Issues? Contact: </strong><a href="mailto:support@bereacollege.onmicrosoft.com" class="footerlink">Systems Support </a>
<strong>Created & Designed by the </strong><a href="/contributors" id = "contribLink" class="footerlink">Student Software Development Team</a></span>
</div>
{% endblock %}
<footer class="site-footer text-center d-print-none">
<div>
<strong>Issues? Contact: </strong>
<a href="mailto:support@bereacollege.onmicrosoft.com" class="footerlink">
Systems Support
</a>
</div>

<div>
<strong>Created &amp; Designed by the </strong>
<a href="/contributors" id="contribLink" class="footerlink">
Student Software Development Team
</a>
</div>
</footer>
{% endblock %}
{% endblock %}
6 changes: 3 additions & 3 deletions app/templates/main/contributors.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ <h2> Contributors </h2>
{% endfor %}
</table>

<div class= "btn-holder pull-left col-lg-6">
<button type='button' class='btn btn-lg btn-newcolor' id='backButton' onclick ="history.back()">Back</button>
</div>
<div class="row">
<div class="col-xs-12 text-center">
<button type="button" class="btn btn-lg btn-newcolor" id="backButton" onclick="history.back()"> Back </button> </div> </div>

</div>
</div>
Expand Down
67 changes: 67 additions & 0 deletions app/templates/main/departmentPortal.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{% block scripts %}
{{super()}}
<script type="text/javascript" src="{{url_for('static', filename='js/departmentPortal.js') }}?u={{lastStaticUpdate}}"></script>
<link rel="stylesheet" type="text/css" href="/static/css/departmentPortal.css?u={{lastStaticUpdate}}"/>
{% endblock %}

{% block app_content %}
Expand All @@ -24,4 +25,70 @@ <h2 class="text-center">{% if department %} {{department.DEPT_NAME}} Portal {% e
</select>

</div>

{% if department %}
<div class="row g-3">
<div class="col-12 col-lg-4 ">

<section class="card" aria-labelledby="current_allocation-title">
<p> Insert Allocations Card Here </p>
<div class="card-footer text-center">
<a href="/department/{{ department.ORG }}/{{ department.ACCOUNT }}/REPLACEME" class="btn btn-primary">View Alloations<span class="glyphicon glyphicon-chevron-right"></span></a>
</div>
</section>

</div>

<div class="col-12 col-lg-4">
<section class="card" aria-labelledby="members-title">

<p> Insert Members Card Here </p>
<div class="card-footer text-center">
<a href="/department/{{ department.ORG }}/{{ department.ACCOUNT }}/REPLACEME" class="btn btn-primary">View All Members<span class="glyphicon glyphicon-chevron-right"></span></a>
</div>
</section>

</div>

<div class=" col-12 col-lg-4">
<section class="card" aria-labelledby="positions-title">
<div class="card-body">
<div class="media">
<div class="media-left media-middle">
<span aria-hidden="true" style="color: #424242; font-size: 24px;">
<i class="bi bi-suitcase-lg-fill"></i>
</span>
</div>
<div class="media-body media-middle">
<h3>Positions</h3>
</div>

</div>
<ul style="line-height:2;">
{% if positions == [] %}
<li class="card-text">
<p> No active positions in this department </p>
</li>
{% else %}
{% for p in positions[:7] %}
<li class="card-text">
<a href= "/department/{{ department.ORG }}/{{ department.ACCOUNT }}/positions/{{posURL[loop.index0]}}">{{ p }}</a>
</li>
{% endfor %}
{% if (positions | length) > 7 %}
</ul><p class="card-text">and {{ (positions | length) - 7}} more ...</p>
{% endif %}
{% endif %}
</ul>

</div>
<div class="card-footer text-center">
<a href="/department/{{ department.ORG }}/{{ department.ACCOUNT }}/positions" class="btn btn-primary">View All Positions<span class="glyphicon glyphicon-chevron-right"></span></a>
</div>
</section>
</div>
</div>

{% endif %}

{% endblock %}
Loading