From 7c7fc83c905519131d29e71c438901b71b41e730 Mon Sep 17 00:00:00 2001 From: NYABUTOA Date: Mon, 3 Aug 2026 16:07:25 -0400 Subject: [PATCH 1/6] Created the revise position page bones i still need to figure out how its going to work because its not going to be active its going to be pending so i need to work my way around it --- app/static/css/reviseposition.css | 12 +++ app/static/js/reviseposition.js | 14 ++++ app/templates/main/reviseposition.html | 105 +++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 app/static/css/reviseposition.css create mode 100644 app/static/js/reviseposition.js create mode 100644 app/templates/main/reviseposition.html diff --git a/app/static/css/reviseposition.css b/app/static/css/reviseposition.css new file mode 100644 index 00000000..1d642d2d --- /dev/null +++ b/app/static/css/reviseposition.css @@ -0,0 +1,12 @@ +/* Revise position form - styles not covered by Bootstrap */ +.description-section-row { + background: #fff; + border: 1px solid #e6e6e6; + padding: 1rem; + border-radius: 6px; + margin-bottom: 1rem; +} + +.revise-actions { + margin-top: 1.5rem; +} diff --git a/app/static/js/reviseposition.js b/app/static/js/reviseposition.js new file mode 100644 index 00000000..7ec65ffb --- /dev/null +++ b/app/static/js/reviseposition.js @@ -0,0 +1,14 @@ +$(document).ready(function () { + var sectionsContainer = document.getElementById('sectionsContainer'); + var sectionRowTemplate = document.getElementById('sectionRowTemplate'); + + document.getElementById('addSectionBtn').addEventListener('click', function () { + sectionsContainer.appendChild(sectionRowTemplate.content.cloneNode(true)); + }); + + sectionsContainer.addEventListener('click', function (event) { + if (event.target.classList.contains('remove-section-btn')) { + event.target.closest('.description-section-row').remove(); + } + }); +}); diff --git a/app/templates/main/reviseposition.html b/app/templates/main/reviseposition.html new file mode 100644 index 00000000..8c8906b4 --- /dev/null +++ b/app/templates/main/reviseposition.html @@ -0,0 +1,105 @@ +{% extends "base.html" %} + +{% block scripts %} + {{ super() }} + + + +{% endblock %} + +{% block app_content %} +
+

Revise {{ position.positionTitle }}

+
+ +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+

{{ position.positionCode }}

+
+
+ +
+ +
+ +
+
+ +
+ +
+

{{ position.revisionDate }}

+
+
+ +
+ +
+

{{ position.revisedBy }}

+
+
+
+ +

Description

+
+ {%- for section in sections %} +
+
+ + +
+
+ + +
+ +
+ {%- endfor %} +
+ + + +
+
+ + Cancel + + +
+
+ +
+ +
+
+
+ + +{% endblock %} From 1f7f42211a77868bbc9ab4dddb7a2f92c6cc357e Mon Sep 17 00:00:00 2001 From: NYABUTOA Date: Tue, 4 Aug 2026 10:13:57 -0400 Subject: [PATCH 2/6] added a connection so that we are able to press the button and see the revise page --- app/templates/main/managePositions.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/main/managePositions.html b/app/templates/main/managePositions.html index 1d6dd8c6..98d86629 100644 --- a/app/templates/main/managePositions.html +++ b/app/templates/main/managePositions.html @@ -33,8 +33,8 @@

{{ department_name }} Positions

{{ position.wls }} {{ position.revisionDate }} - - + View + Revise Position {% endfor %} From 48e83ecc5d19604158ad9c6a6b248c020de01f5d Mon Sep 17 00:00:00 2001 From: NYABUTOA Date: Tue, 4 Aug 2026 10:45:20 -0400 Subject: [PATCH 3/6] This is the revise position page where one should be able to edit position and make changes.these are the bones, html,css,and js --- app/static/css/revisepositionpage.css | 12 +++ app/static/js/revisepositionpage.js | 14 +++ app/templates/main/revisepositionpage.html | 105 +++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 app/static/css/revisepositionpage.css create mode 100644 app/static/js/revisepositionpage.js create mode 100644 app/templates/main/revisepositionpage.html diff --git a/app/static/css/revisepositionpage.css b/app/static/css/revisepositionpage.css new file mode 100644 index 00000000..1d642d2d --- /dev/null +++ b/app/static/css/revisepositionpage.css @@ -0,0 +1,12 @@ +/* Revise position form - styles not covered by Bootstrap */ +.description-section-row { + background: #fff; + border: 1px solid #e6e6e6; + padding: 1rem; + border-radius: 6px; + margin-bottom: 1rem; +} + +.revise-actions { + margin-top: 1.5rem; +} diff --git a/app/static/js/revisepositionpage.js b/app/static/js/revisepositionpage.js new file mode 100644 index 00000000..7ec65ffb --- /dev/null +++ b/app/static/js/revisepositionpage.js @@ -0,0 +1,14 @@ +$(document).ready(function () { + var sectionsContainer = document.getElementById('sectionsContainer'); + var sectionRowTemplate = document.getElementById('sectionRowTemplate'); + + document.getElementById('addSectionBtn').addEventListener('click', function () { + sectionsContainer.appendChild(sectionRowTemplate.content.cloneNode(true)); + }); + + sectionsContainer.addEventListener('click', function (event) { + if (event.target.classList.contains('remove-section-btn')) { + event.target.closest('.description-section-row').remove(); + } + }); +}); diff --git a/app/templates/main/revisepositionpage.html b/app/templates/main/revisepositionpage.html new file mode 100644 index 00000000..fa1f2751 --- /dev/null +++ b/app/templates/main/revisepositionpage.html @@ -0,0 +1,105 @@ +{% extends "base.html" %} + +{% block scripts %} + {{ super() }} + + + +{% endblock %} + +{% block app_content %} +
+

Revise {{ position.positionTitle }}

+
+ +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+

{{ position.positionCode }}

+
+
+ +
+ +
+ +
+
+ +
+ +
+

{{ position.revisionDate }}

+
+
+ +
+ +
+

{{ position.revisedBy }}

+
+
+
+ +

Description

+
+ {%- for section in sections %} +
+
+ + +
+
+ + +
+ +
+ {%- endfor %} +
+ + + +
+
+ + Cancel + + +
+
+ +
+ +
+
+
+ + +{% endblock %} From 496a93f4e04c59a0401c1f18cf9cb4df4178b401 Mon Sep 17 00:00:00 2001 From: NYABUTOA Date: Tue, 4 Aug 2026 11:29:00 -0400 Subject: [PATCH 4/6] DETELETD THIS DUPLICATE FILES --- app/static/css/reviseposition.css | 12 --- app/static/js/reviseposition.js | 14 ---- app/templates/main/reviseposition.html | 105 ------------------------- 3 files changed, 131 deletions(-) delete mode 100644 app/static/css/reviseposition.css delete mode 100644 app/static/js/reviseposition.js delete mode 100644 app/templates/main/reviseposition.html diff --git a/app/static/css/reviseposition.css b/app/static/css/reviseposition.css deleted file mode 100644 index 1d642d2d..00000000 --- a/app/static/css/reviseposition.css +++ /dev/null @@ -1,12 +0,0 @@ -/* Revise position form - styles not covered by Bootstrap */ -.description-section-row { - background: #fff; - border: 1px solid #e6e6e6; - padding: 1rem; - border-radius: 6px; - margin-bottom: 1rem; -} - -.revise-actions { - margin-top: 1.5rem; -} diff --git a/app/static/js/reviseposition.js b/app/static/js/reviseposition.js deleted file mode 100644 index 7ec65ffb..00000000 --- a/app/static/js/reviseposition.js +++ /dev/null @@ -1,14 +0,0 @@ -$(document).ready(function () { - var sectionsContainer = document.getElementById('sectionsContainer'); - var sectionRowTemplate = document.getElementById('sectionRowTemplate'); - - document.getElementById('addSectionBtn').addEventListener('click', function () { - sectionsContainer.appendChild(sectionRowTemplate.content.cloneNode(true)); - }); - - sectionsContainer.addEventListener('click', function (event) { - if (event.target.classList.contains('remove-section-btn')) { - event.target.closest('.description-section-row').remove(); - } - }); -}); diff --git a/app/templates/main/reviseposition.html b/app/templates/main/reviseposition.html deleted file mode 100644 index 8c8906b4..00000000 --- a/app/templates/main/reviseposition.html +++ /dev/null @@ -1,105 +0,0 @@ -{% extends "base.html" %} - -{% block scripts %} - {{ super() }} - - - -{% endblock %} - -{% block app_content %} -
-

Revise {{ position.positionTitle }}

-
- -
-
-
- -
- -
-
- -
- -
-
- -
- -
-

{{ position.positionCode }}

-
-
- -
- -
- -
-
- -
- -
-

{{ position.revisionDate }}

-
-
- -
- -
-

{{ position.revisedBy }}

-
-
-
- -

Description

-
- {%- for section in sections %} -
-
- - -
-
- - -
- -
- {%- endfor %} -
- - - -
-
- - Cancel - - -
-
- -
- -
-
-
- - -{% endblock %} From 557e211f3a7b55c7820fdd797b2970c06b83b11c Mon Sep 17 00:00:00 2001 From: NYABUTOA Date: Tue, 4 Aug 2026 13:37:54 -0400 Subject: [PATCH 5/6] Implemented the revisePosition route and createPositionRevision function so the revise position page actually works. Submitting the form now creates a new pending (Requested) revision of the position with updated title, WLS, and description sections. --- .../main_routes/departmentPortal.py | 40 +++++++++++++++++-- app/logic/getPositions.py | 28 ++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index 5d69fdd7..3984750b 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -1,11 +1,11 @@ from datetime import datetime -from flask import g, render_template, request, send_file +from flask import flash, g, redirect, render_template, request, send_file, url_for from peewee import DoesNotExist from app.controllers.main_routes import main_bp from app.logic.download import makePositionDescriptionPDF -from app.logic.getPositions import getPosition, getPositions, getPositionDescriptionSections +from app.logic.getPositions import createPositionRevision, getPosition, getPositions, getPositionDescriptionSections from app.models.department import Department from app.models.positionHistory import PositionHistory from app.models.supervisorDepartment import SupervisorDepartment @@ -67,6 +67,40 @@ def downloadPositionDescription(org, account, positionCode): +@main_bp.route('/department///positions//revise', methods=['GET', 'POST']) +def revisePosition(org, account, positionCode): + try: + dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) + except (NameError, DoesNotExist): + return render_template('errors/404.html'), 404 + + position = getPosition(dept, positionCode) + + if not position: + return render_template('errors/404.html'), 404 + + if request.method == 'POST': + createPositionRevision( + position, + g.currentUser.fullName, + request.form.get('positionTitle'), + request.form.get('wls'), + request.form.getlist('sectionTitle[]'), + request.form.getlist('sectionContent[]') + ) + flash('Position revision saved.', 'success') + return redirect(url_for('main.managePositions', org=org, account=account)) + + sections = getPositionDescriptionSections(position) + + return render_template( + 'main/revisepositionpage.html', + department=dept, + position=position, + sections=sections + ) + + @main_bp.route('/department///positions', methods=['GET']) def managePositions(org, account): try: @@ -87,4 +121,4 @@ def managePositions(org, account): department = dept, department_name = dept.DEPT_NAME, positions = positions - ) + ) \ No newline at end of file diff --git a/app/logic/getPositions.py b/app/logic/getPositions.py index 7410d7f7..3d3bcd67 100644 --- a/app/logic/getPositions.py +++ b/app/logic/getPositions.py @@ -1,5 +1,6 @@ from app.models.positionHistory import PositionHistory from app.models.positionDescriptionSection import PositionDescriptionSection +from datetime import date def getActivePositions(dept): """ @@ -52,7 +53,32 @@ def getPositionDescriptionSections(position): positionDescriptionSections = list(PositionDescriptionSection.select() .where(PositionDescriptionSection.position == position) .order_by(PositionDescriptionSection.order.asc())) - + return positionDescriptionSections +def createPositionRevision(position, revisedBy, positionTitle, wls, sectionTitles, sectionContents): + """ + Creates a new pending (Requested) revision of a position, copying forward its + department and position code, and replaces its description sections with the + given titles/contents. Returns the newly created PositionHistory row. + """ + newPosition = PositionHistory.create( + positionTitle=positionTitle, + positionCode=position.positionCode, + department=position.department, + status="Requested", + wls=wls, + revisionDate=date.today(), + revisedBy=revisedBy + ) + + for order, (sectionTitle, sectionContent) in enumerate(zip(sectionTitles, sectionContents)): + PositionDescriptionSection.create( + position=newPosition, + sectionTitle=sectionTitle, + sectionContent=sectionContent, + order=order + ) + + return newPosition From 8cddd37c1f164303ddfe25a1988fad107e9789b9 Mon Sep 17 00:00:00 2001 From: NYABUTOA Date: Tue, 4 Aug 2026 14:00:25 -0400 Subject: [PATCH 6/6] Make revise position stay on the page after saving so the new pending revision is immediately visible instead of redirecting back to a list that only shows Active positions. --- app/controllers/main_routes/departmentPortal.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index 3984750b..65d27443 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -1,6 +1,6 @@ from datetime import datetime -from flask import flash, g, redirect, render_template, request, send_file, url_for +from flask import flash, g, render_template, request, send_file from peewee import DoesNotExist from app.controllers.main_routes import main_bp @@ -80,7 +80,7 @@ def revisePosition(org, account, positionCode): return render_template('errors/404.html'), 404 if request.method == 'POST': - createPositionRevision( + position = createPositionRevision( position, g.currentUser.fullName, request.form.get('positionTitle'), @@ -89,7 +89,6 @@ def revisePosition(org, account, positionCode): request.form.getlist('sectionContent[]') ) flash('Position revision saved.', 'success') - return redirect(url_for('main.managePositions', org=org, account=account)) sections = getPositionDescriptionSections(position)