commit 177812e32e0e64b888ace44b8e6907d4d6c8b750
parent 41c9c44abf69a64b598de5d639021b2c0e595ce8
Author: Youth Employment Program Production <youthemployment22@gmail.com>
Date: Sun, 17 Mar 2024 21:47:25 -0600
Cleanup after website work.
Diffstat:
8 files changed, 253 insertions(+), 21 deletions(-)
diff --git a/app/routes.py b/app/routes.py
@@ -707,6 +707,93 @@ def admin():
#def vehicle_report():
# return render_template ('admin/reports/vehicle_report.html', ORGNAME=OrganizationName)
+#############################
+###### DEV HOURS ROUTE ######
+#############################
+@app.route('/hoursd/<username>', methods=['GET','POST'])
+@login_required
+def hoursd(username):#userid goes into call to db to get user[] -> then returns formatted table (punchclock/index.html
+
+ availableProjects = []
+
+ for project in mongo.db.projects_collection.find(): #TODO TO RESOLVE BELOW ISSUE, JUST USE aggregator QUERY, WILL ALLOW SORTING AS WELL AS PROPER SUMMATION OF HOURS
+ availableProjects.append((project['_id'],project['project_name']))#TODO FIND OUT WHY THIS RETURNS THE OBJECTID VALUE .str THROWS AttributeError: 'ObjectId' object has no attribute 'str'
+ #'completed':{'$exists':False}
+ dbhours = mongo.db.time_collection.find({'modified_by.0':user['username']})
+ hours = []
+ deltas=[]
+ for hour in dbhours: # Currenty acts wrong with longer than 1 day
+ for x, y in availableProjects:
+ if x is ObjectId(hour['project']):
+ hour['projectName'] = y
+ if 'clock_out' not in hour:
+ hour['clock_out']=[datetime.datetime.now()]
+ time = hour['clock_out'][-1] - hour['clock_in'][-1]
+ hour['total_time'] = time
+ hours.append(hour)
+ deltas.append(time)
+
+ form = NewHoursForm()
+ form.dateSel.data = datetime.datetime.today()
+ form.projectSel.choices = availableProjects
+ form.startTime.data = datetime.datetime.now()
+ total_hours = sum(deltas,datetime.timedelta())
+ statement_hours = "{} Hours, {} Minutes".format(total_hours.seconds//3600,(total_hours.seconds//60)%60)
+
+ if form.validate_on_submit(): # Possible bug iff user clocks in between page load and form submit... will create additional time_collection entry
+ indt = datetime.combine(form.dateSel.data,form.startTime.data)
+ outdt = datetime.combine(form.dateSel.data,form.endTime.data)
+ if user['username'] is current_user.username and not form.perDiemSel.data and not form.lunchSel.data:
+ mongo.db.time_collection.insert_one({'clock_in' : [indt],
+ 'modified_by' : [current_user.username],
+ 'date' : datetime.datetime.today(),
+ 'project' : ObjectId(form.projectSel.data),
+ 'clock_out':[outdt]})
+ return redirect(url_for('hours',username=user['username']))
+
+ if user['username'] is not current_user.username and not form.perDiemSel.data and not form.lunchSel.data:
+ mongo.db.time_collection.insert_one({'clock_in' : [indt],
+ 'modified_by' : [user['username'], current_user.username],
+ 'date' : datetime.datetime.today(),
+ 'project' : ObjectId(form.projectSel.data),
+ 'clock_out':[outdt]})
+
+ return redirect(url_for('hours',username=user['username']))
+
+ #hours = mongo.db.time_collection.find({'modified_by.0':user.username})
+
+
+ tspp = mongo.db.time_collection.aggregate( [
+ {
+ "$lookup":{
+ 'from':'projects_collection',
+ 'localField':'project',
+ 'foreignField':'_id',
+ 'as':'project_data'
+ }
+ },
+ {
+ "$group": {
+ "_id":"$project_data",
+ "laborHoursWorked": { "$sum": { "$subtract": [{"$last":"$clock_out"}, {"$last":"$clock_in"}] } },
+ "lunchCount": { "$sum" : { '$cond':["$lunch",1,0] } },
+ "perdiemCount": { "$sum" :{'$cond':["$per_diem",1,0] } }
+ }
+ },
+ {
+ "$addFields": {
+ "totalHoursWorked": {"$subtract":[ "$laborHoursWorked", {"$multiply":["$lunchCount", 30 * 60 * 1000]}] }
+ }
+ },
+ {
+ "$sort": { "_id": -1 }
+ }
+ ] )# Time Spent Per Project (filter entries by username, then group and sum hours by project)
+
+
+ return render_template ('dashboard/punchclock/index.dev.html',form=form,hours=hours,availableProjects=availableProjects,total_hours=total_hours,statement_hours=statement_hours,user=user,tspp=tspp,ORGNAME=OrganizationName)
+
+
#### ####
####### Hours Route #######
@@ -1305,6 +1392,36 @@ def project_report():
return render_template('admin/reports/project.html',by_project=by_project,tspp=tspp,projectlookup=ptl,ORGNAME=OrganizationName)
+@app.route('/admin/rename/agreement/<agreement_id>',methods=["GET","POST"])
+@login_required
+def rename_agreement(agreement_id):
+ form = RenameAgreementForm()
+ if form.validate_on_submit():
+ try:
+ project = mongo.db.projects_collection.find_one({'_id':project_id})
+ except:
+ flash("Issue finding Project with id {}".format(project_id))
+ else:
+ try:
+ mongo.db.projects_collection.update_one({'_id':ObjectId(project_id)},{'$set':{'project_name':form.newName.data}})
+ except:
+ flash("Issue setting {} as project name for {}".format(form.newName.data,project_id))
+ finally:
+ return redirect(url_for('project', project_id=project_id))
+ return render_template('admin/agreements/projects/update/rename.html',form=form,ORGNAME=OrganizationName)
+
+@app.route("/admin/remove/agreement/<agreement_id>",methods=["GET","POST"])
+@login_required
+def remove_agreement(agreement_id):
+ #TODO
+ return render_template('admin/agreements/projects/update/move.html',form=form,ORGNAME=OrganizationName)#TODO FIX
+
+@app.route('/admin/change/agreement/dates',methods=["GET","POST"])
+@login_required
+def change_agreement_dates():
+ #TODO
+ return render_template('admin/agreements/projects/update/move.html',form=form,ORGNAME=OrganizationName)#TODO FIX
+
# Payperiod Routes
#TODO marked 06.29,23
###### TESTING START #######
diff --git a/app/static/css/main.css b/app/static/css/main.css
@@ -7,7 +7,6 @@
--progressfill:var(--maincolor);
--totalprogressfill:var(--accent);
--progressbg:var(--zoning);
- font-family: 'Courier New';
/* --zoning:#dcd;
--maincolor:#dff;
--accent:#f3f;
@@ -141,6 +140,17 @@ dl {
box-shadow: 0 3px 6px 0 rgba(0,0,0,0.2);
/* &:hover { transform: translateY(-10px); box-shadow: 0 6px 6px 0 rgba(0,0,0,0.2); };*/
}
+.action-button {
+ border: none;
+ background: var(--accent);
+ cursor: pointer;
+ border-radius: 3px;
+ padding: 6px;
+ width:150px;
+ height:1.2em;
+ color: white;
+ box-shadow: 0 3px 6px 0 rgba(0,0,0,0.2);
+}
/********** NAVIGATION **********/
header {
font-size:1.5em;
diff --git a/app/templates/admin/agreements/index.html b/app/templates/admin/agreements/index.html
@@ -11,17 +11,23 @@
{% endif %}
{% endwith %}
<section class="agreement-grid">
- <h3>{{ agreement['agreement_name'] }}</h3>
-
- {%- for element in agreement['signing_agency'] %}
- {{ agreement[element] }}
- {%- endfor %}
- {{ agreement['start_date'] }} - {{ agreement['end_date'] }}
- {% if agreement['contacts'] %}
- {% for contact in agreement['contacts'] %}
- {{ contact }}
- {% endfor %}
- {% endif %}
+ <dl>
+ <dt>{{ agreement['agreement_name'] }}<a href="{{url_for('rename_agreement',agreement_id=agreement['_id'])}}" style="color:var(--accent)"> change</a></dt>
+ <dd>
+ {%- for element in agreement['signing_agency'] %}
+ {{ agreement[element] }}
+ {%- endfor %}
+ </dd>
+ <dd>{{ agreement['start_date'] }} - {{ agreement['end_date'] }}<a href="{{url_for('change_agreement_dates')}}" style="color:var(--accent);"> change</a></dd>
+ <dd>
+ {% if agreement['contacts'] %}
+ {% for contact in agreement['contacts'] %}
+ {{ contact }}
+ {% endfor %}
+ {% endif %}
+ </dd>
+ <dd><a href="{{url_for('remove_agreement',agreement_id=agreement['_id'])}}" style="color:var(--accent)">remove</a></dd>
+ </dl>
<h5>Projects</h5>
diff --git a/app/templates/admin/agreements/projects/index.html b/app/templates/admin/agreements/projects/index.html
@@ -13,12 +13,12 @@
<section class="project-grid">
<dl>
- <dt>{{ project['project_name'] }}<a href="{{url_for('rename_project', project_id=project['_id'])}}"> change</a></dt>
+ <dt>{{ project['project_name'] }}<a href="{{url_for('rename_project', project_id=project['_id'])}}"style="color:var(--accent);"> change</a></dt>
<dd>ID: {{ project['_id'] }}</dd>
- <dd>A_ID:{{ project['agreement']}}<a href="{{url_for('move_project',project_id=project['_id'])}}"> change</a></dd>
+ <dd>A_ID:{{ project['agreement']}}<a href="{{url_for('move_project',project_id=project['_id'])}}"style="color:var(--accent);"> change</a></dd>
<dd>Budget:{{ project['budget']}}</dd>
<dd>Costs:{{ project['costs']}}</dd>
- <dd><a href="{{url_for('remove_project',project_id=project['_id'])}}"style="color:red;">remove</a></dd>
+ <dd><a href="{{url_for('remove_project',project_id=project['_id'])}}" style="color:var(--accent);">REMOVE</a></dd>
</dl>
<div class="current-pay-period">
diff --git a/app/templates/admin/agreements/update/rename.html b/app/templates/admin/agreements/update/rename.html
@@ -0,0 +1,27 @@
+{% extends 'base.html' %}
+
+{% block title %}Update Project Name {% endblock %}
+
+{% block content %}
+<section class="new-agreement-grid">
+ <h3>Update Project Name</h3>
+ <form action="" method="POST" novalidate>
+ {{ form.hidden_tag() }}
+ {% for error in form.errors %}
+ <span style="color:red;">[{{ error }}]</span>
+ {% endfor %}
+ {% for ferror in form.form_errors %}
+ <span style="color:yellow;">[{{ ferror }}]</span>
+ {% endfor %}
+ {% with messages = get_flashed_messages() %}
+ {% if messages %}
+ {% for message in messages %}
+ <p style='color:red'>{{ message }}</p>
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
+ {{ form.newName.label }}{{ form.newName() }}<br>
+ {{ form.renameProject() }}
+ </form>
+</section>
+{% endblock %}
diff --git a/app/templates/dashboard/activeusers/widget.html b/app/templates/dashboard/activeusers/widget.html
@@ -10,7 +10,7 @@
<table><!-- replace w/ function getUserHours(username) -->
{% for user in clocked_in_users %}
<tr>
- <td><button><a href="{{ url_for('hours',username=user.modified_by.0) }}">{{ user.modified_by.0 }}</a></button></td>
+ <td><a href="{{ url_for('hours',username=user.modified_by.0) }}" class="action-button">{{ user.modified_by.0 }}</a></td>
<td><a href="{{ url_for('toggle_lunch',timeid=user._id) }}">
{% if user.lunch %}
<input type="checkbox" name="lunch" checked><label for="lunch">Lunch</label>
@@ -25,14 +25,14 @@
<input type="checkbox" name="per_diem"><label for="per_diem">Per Diem</label>
{% endif %}
</a></td>
- <td><button><a href="{{ url_for('hours',username=user.modified_by.0) }}">{{ user.clock_in.0.isoformat(timespec='minutes') }}</a></button></td><!-- can format/display non-military time with format %I:%M%p removed.time() after index to try and show date value-->
- <td><button><a href="{{ url_for('clockout_by_id',modusernm=current_user.username,timeid=user._id) }}">Clock Out</a></button></td>
+ <td><a href="{{ url_for('hours',username=user.modified_by.0) }}" class="action-button">{{ user.clock_in.0.isoformat(timespec='minutes') }}</a></td><!-- can format/display non-military time with format %I:%M%p removed.time() after index to try and show date value-->
+ <td><a href="{{ url_for('clockout_by_id',modusernm=current_user.username,timeid=user._id) }}" class="action-button">Clock Out</a></td>
</tr>
{% endfor %}
</table>
</form>
- <a href="{{ url_for('clockin_new_user') }}"><button>Clock in User</button></a>
- <a href="{{ url_for('new_user_time') }}"><button>New User Entry</button></a>
+ <a href="{{ url_for('clockin_new_user') }}" class="action-button">Clock in User</a>
+ <a href="{{ url_for('new_user_time') }}" class="action-button">New User Entry</a>
<!-- clock in clocked out user MIGHT NEED TO COMMENT OUT... DOES NOT GET DATA FROM FORMS ON SUBMIT... ONLY USES DEFAULT.data -->
<!-- <form>
<table>
diff --git a/app/templates/dashboard/punchclock/index.dev.html b/app/templates/dashboard/punchclock/index.dev.html
@@ -0,0 +1,72 @@
+{% extends 'base.html' %}
+
+{% block title %}Hours{% endblock %}
+
+{% block content %}
+ <section class="hours-grid">
+ <h3>{{ user.fname }} {{ user.lname }}</h3><!-- IF logged in user has permission allow this username section to be a dropdown for modifying user time sheets. -->
+ <h1 id="clock"></h1>
+ <div><!-- abstract to payPeriod() -->
+ <h6>$payperiod range</h6>
+ <!--<h5>Total:{# {{ statement_hours }} #}</h5> -->
+ {{availableProjects}}
+ </div>
+ <a href="{{url_for('new_time',usernm=user.username)}}" style=" border: none;
+ background: var(--accent);
+ cursor: pointer;
+ border-radius: 3px;
+ padding: 6px;
+ width: 200px;
+ color: white;
+ margin-left: 25px;
+ box-shadow: 0 3px 6px 0 rgba(0,0,0,0.2);">New Time</a>
+ <form action="" method="POST" novalidate>
+ <table><tr>
+ {% for field in form %}{% if field.widget.input_type != 'hidden' and field.widget.input_type != 'submit' %}
+ <th>{{ field.label }}</th>
+ {% endif %}{% endfor %}</tr>
+ <!--{# <tr>
+ <td>{{ form.dateSel() }}</td>
+ <td>{{ form.projectSel() }}</td>
+ <td>{{ form.startTime() }}</td>
+ <td>{{ form.endTime() }}</td>
+ <td>{{ form.lunchSel() }}</td>
+ <td>{{ form.perDiemSel() }}</td>
+ <td>{{ form.note() }}</td>
+ <td>{{ form.submitEntr() }}</td>
+ </tr> #}-->
+
+ {% for entry in hours %}
+ <tr>
+ <td><a href="{{url_for('updateDate',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.date.date().isoformat() }}</a></td>
+ <td>{{ entry.projectName }}</td>
+ <td><a href="{{url_for('updateStartTime',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.clock_in[-1].time().isoformat(timespec='minutes') }}</a></td>
+ <td><a href="{{url_for('updateEndTime',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.clock_out[-1].time().isoformat(timespec='minutes') }}</a></td>
+ {% if entry.lunch %}
+ <td><a href="{{url_for('toggle_lunch',timeid=entry._id)}}">Yes</a></td>
+ {% else %}
+ <td><a href="{{url_for('toggle_lunch',timeid=entry._id)}}">No</a></td>
+ {% endif %}
+ {% if entry.per_diem %}
+ <td><a href="{{url_for('toggle_per_diem',timeid=entry._id)}}">Yes</a></td>
+ {% else %}
+ <td><a href="{{url_for('toggle_per_diem',timeid=entry._id)}}">No</a></td>
+ {% endif %}
+ {% if entry.note %}
+ <td><a href="{{url_for('updateNote',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.note }}</a></td>
+ {% else %}
+ <td><a href="{{url_for('updateNote',mod_username=current_user.username,timeid=entry._id)}}">Add Note</a></td>
+ {% endif %}
+ <td><a href="{{url_for( 'removetime',timeid=entry._id) }}" class="action-button">Remove</a></td>
+ {#{{ form.hidden_tag() }}#}
+ </tr>
+ {# {{entry}} #}
+ {% endfor %}
+ </table>
+ </form>
+ </section>
+ {% for time in tspp %}
+ {{ time }}
+ </br>
+ {% endfor %}
+{% endblock %}
diff --git a/app/templates/dashboard/punchclock/index.html b/app/templates/dashboard/punchclock/index.html
@@ -57,7 +57,7 @@
{% else %}
<td><a href="{{url_for('updateNote',mod_username=current_user.username,timeid=entry._id)}}">Add Note</a></td>
{% endif %}
- <td><button><a href="{{url_for( 'removetime',timeid=entry._id) }}">Remove</a></button></td>
+ <td><a href="{{url_for( 'removetime',timeid=entry._id) }}" class="action-button">Remove</a></td>
{#{{ form.hidden_tag() }}#}
</tr>
{# {{entry}} #}