stc

a simple time card webapp
git clone _git@git.brennen.work:stc.git
Log | Files | Refs | README

commit cae362e4b891f50c4efd036f97760b2e56896b71
parent 691f5951f0b5e85df7dbaea342e864406d9c55c9
Author: Brennen T. Mazur <brennen@madis.cool>
Date:   Mon,  3 Apr 2023 08:34:00 -0600

some last minute changes

Diffstat:
Mapp/forms.py | 7++++++-
Mapp/routes.py | 64++++++++++++++++++++++++++++++++++++++++------------------------
Mapp/static/imgs/logo.svg | 4++--
Mapp/templates/admin/agreements/widget.html | 4++--
Mapp/templates/dashboard/punchclock/index.html | 14+++++---------
5 files changed, 55 insertions(+), 38 deletions(-)

diff --git a/app/forms.py b/app/forms.py @@ -1,6 +1,6 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, PasswordField, BooleanField, SelectField, DateField, TelField, EmailField, FloatField, IntegerField, TimeField -from wtforms.validators import DataRequired, optional, length +from wtforms.validators import DataRequired, optional, length, InputRequired, EqualTo # Login class currently assumes mongodb collection(Users) with structure # { @@ -42,6 +42,11 @@ class NewUserForm(FlaskForm): setActive = BooleanField('Active',default="checked")# Require some sort of validator for check... createNewUser = SubmitField('Create New User') +class ChangePasswordForm(FlaskForm): + newpass = PasswordField('Password',[InputRequired(),EqualTo('confpass',message='Passwords must match')]) + confpass = PasswordField('Confirm',validators=[DataRequired()]) + changePassword = SubmitField('Change Password') + class NewRoleForm(FlaskForm): rolename = StringField('Role Name', validators=[DataRequired()]) diff --git a/app/routes.py b/app/routes.py @@ -4,7 +4,7 @@ from app import app from flask_pymongo import PyMongo from flask_login import LoginManager from flask import render_template, url_for, request, flash, redirect -from app.forms import LoginForm, PunchclockinWidget, PunchclockoutWidget, FleetCheckoutForm, FleetCheckinForm, NewUserForm, AdmnPermissionsForm, DashPermissionsForm, ChangeHoursForm, NewAgreementForm, NewProjectForm, CrewClockinWidget +from app.forms import LoginForm, PunchclockinWidget, PunchclockoutWidget, FleetCheckoutForm, FleetCheckinForm, NewUserForm, AdmnPermissionsForm, DashPermissionsForm, ChangeHoursForm, NewAgreementForm, NewProjectForm, CrewClockinWidget, ChangePasswordForm from flask import request from werkzeug.urls import url_parse from werkzeug.security import generate_password_hash, check_password_hash @@ -27,47 +27,47 @@ login_manager.login_view = 'login' #### #### ####### User Routes/Queries ####### #### #### -@app.route('/user/signup', methods=['GET']) -def signup(): - return User().signup() +#@app.route('/user/signup', methods=['GET']) +#def signup(): +# return User().signup() -@app.route('/user/loginModel', methods=['GET']) -def loginModel(): - return User().loginModel() +#@app.route('/user/loginModel', methods=['GET']) +#def loginModel(): +# return User().loginModel() -@app.route('/user/signout') -def signout(): - return User().signout() +#@app.route('/user/signout') +#def signout(): +# return User().signout() #### #### ####### Time Routes/Queries ####### #### #### -@app.route('/time/clockin', methods=['GET', 'POST']) -def clockin(): - return Time().clockin() +#@app.route('/time/clockin', methods=['GET', 'POST']) +#def clockin(): +# return Time().clockin() -@app.route('/time/clockout', methods=['GET', 'POST']) -def clockout(): - return Time().clockout() +#@app.route('/time/clockout', methods=['GET', 'POST']) +#def clockout(): +# return Time().clockout() #### #### ####### Vehicle Routes/Queries ####### #### #### -@app.route('/fleet/vehicle_repair', methods=['GET', 'POST']) -def vehicle_repair(): - return Fleet().vehicle_repair() +#@app.route('/fleet/vehicle_repair', methods=['GET', 'POST']) +#def vehicle_repair(): +# return Fleet().vehicle_repair() #### #### ####### Agreement Routes/Queries ####### #### #### -@app.route('/agreement/document', methods=['GET', 'POST']) -def document(): - return Agreement().document() +#@app.route('/agreement/document', methods=['GET', 'POST']) +#def document(): +# return Agreement().document() #### #### ####### Project Routes/Queries ####### #### #### -@app.route('/projects/project', methods=['GET', 'POST', 'PUT']) +#@app.route('/projects/project', methods=['GET', 'POST', 'PUT']) ##{{{{{{{{{{{{{{{{{{{{{ Decorator Functions }}}}}}}}}}}}}}}}}}}}}## #@login_required @@ -140,6 +140,17 @@ def load_user(username): user_obj.password_hash = u['password_hash'] return user_obj +@app.route('/newpass',methods=['GET','POST']) +@login_required +def chgpass(): + form = ChangePasswordForm() + if form.validate_on_submit(): + mongo.db.users_collection.update_one({'username':current_user.username},{'$set':{'password_hash':generate_password_hash(form.confpass)}}) + flash("Changed password for {}".format(current_user.username)) #Will need to sendmail password to form.email.data later + + return redirect(url_for('dashboard')) + + return render_template('admin/users/newpass.html',form=form,ORGNAME=OrganizationName) #### #### ####### Dashboard Route ####### #### #### @@ -287,6 +298,7 @@ def dashboard(): return render_template('dashboard/layout.html',permissions=dashperms,clocked_out=clocked_out,clockoutform=clockoutform,clockinform=clockinform,fleetCheckedOut=fleetCheckedOut,crewform=crewform,vehicle_name=vehicle_name,fleetinform=fleetinform,fleetoutform=fleetoutform,clocked_in_users=clocked_in_users,ORGNAME=OrganizationName) @app.route("/toggle-lunch/<timeid>",methods=['GET','POST']) +@login_required def toggle_lunch(timeid): timeid = ObjectId(timeid) @@ -300,6 +312,7 @@ def toggle_lunch(timeid): return redirect(url_for('dashboard')) @app.route("/toggle-per-diem/<timeid>",methods=['GET','POST']) +@login_required def toggle_per_diem(timeid): timeid = ObjectId(timeid) @@ -313,6 +326,7 @@ def toggle_per_diem(timeid): return redirect(url_for('dashboard')) @app.route("/clockinuser/<modusernm>/<usertoinid>/<project>/<intime>", methods=['GET','POST']) +@login_required def clockin_by_id(modusernm,usertoinid,project,intime): timeid = ObjectId() user2 = eval(usertoinid) @@ -326,6 +340,7 @@ def clockin_by_id(modusernm,usertoinid,project,intime): return redirect(url_for('dashboard')) @app.route("/clockoutuser/<modusernm>/<timeid>", methods=['GET','POST']) +@login_required def clockout_by_id(modusernm,timeid): # if modified_by.last != modusernm: modified_by.append(modusernm) @@ -347,6 +362,7 @@ def clockout_by_id(modusernm,timeid): ####### Admin Route ####### #### #### @app.route("/admin") +@login_required #@admin_required def admin(): adminperms=mongo.db.permissions_collection.find_one({'label': current_user.role},{'admin':1,'_id':0}) @@ -441,7 +457,7 @@ def hours(username):#userid goes into call to db to get user[] -> then returns f statement_hours = "{} Hours, {} Minutes".format(total_hours.seconds//3600,(total_hours.seconds//60)%60) #hours = mongo.db.time_collection.find({'modified_by.0':user.username}) - return render_template ('dashboard/punchclock/index.html',form=form,hours=hours,total_hours=total_hours,statement_hours=statement_hours,user=user,choices=projectChoices,ORGNAME=OrganizationName) + return render_template ('dashboard/punchclock/index.html',form=form,hours=hours,total_hours=total_hours,statement_hours=statement_hours,user=user,ORGNAME=OrganizationName) # Don't really need this until additional functionality is added, not in current project scope #@app.route("/fleet") diff --git a/app/static/imgs/logo.svg b/app/static/imgs/logo.svg @@ -28,8 +28,8 @@ <g id="g1601"> <image - width="1159.6801" - height="1132.8" + width="100%" + height="100%" preserveAspectRatio="none" style="image-rendering:optimizeQuality" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS4AAAEnCAYAAAAXT66LAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAg diff --git a/app/templates/admin/agreements/widget.html b/app/templates/admin/agreements/widget.html @@ -8,7 +8,7 @@ {% endfor %} </div></a> {% endfor %} - {% for agreement in agreements %} + {#{% for agreement in agreements %} {{ agreement.agreement_name }}<br> {{ agreement['budget'] }}<br> {% for project in agreement['projects'] %} @@ -19,7 +19,7 @@ {% endfor %} {{ agreement['costs'] }} <br><br> - {% endfor %} + {% endfor %}#} <a href="{{ url_for('newagreement') }}"><input type="submit" value="Add New Agreement"></a> <a href="{{ url_for('newproject') }}"><input type="submit" value="Add New Project"></a> </section> diff --git a/app/templates/dashboard/punchclock/index.html b/app/templates/dashboard/punchclock/index.html @@ -8,12 +8,8 @@ <h1 id="clock"></h1> <div><!-- abstract to payPeriod() --> <h6>$payperiod range</h6> - <h5>Total: {{ total_hours }}</h5> <h5>Total: {{ statement_hours }}</h5> </div> - {% for choice in choices %} - {%- print(choice) %} - {% endfor %} <form action="" method="POST" novalidate> <table><tr> {% for field in form %}{% if field.widget.input_type != 'hidden' %} @@ -21,14 +17,14 @@ {% endif %}{% endfor %}</tr> {% for entry in hours %} - <tr> + <tr><!-- remove the forms and create each tr as a link to a modify entry['_id'] route(redirects back to hours) --> <td>{{ entry.project }}{{ form.projectChg(default=entry.project) }}</td> - <td>{{ entry.clock_in.0 }}{{ form.startTiChg() }}</td> - <td>{{ entry.clock_out.0 }}{{ form.endTimeChg() }}</td> + <td>{{ entry.clock_in.0.time().isoformat(timespec='minutes') }}{{ form.startTiChg() }}</td> + <td>{{ entry.clock_out.0.time().isoformat(timespec='minutes') }}{{ form.endTimeChg() }}</td> <td>{{ entry.lunch }}{% if entry.lunch %}{{ form.lunchBxChg(default="checked")}}{%else%}{{ form.lunchBxChg() }}{% endif %} </td> <td>{{ entry.per_diem }}{{ form.perDiemChg(default='checked') }}</td> - <td>{{ form.updateEntr() }}</td> - <td>{{ form.removeEntr() }}</td> + <td>{{ form.updateEntr() }}</td><!-- remove? --> + <td>{{ form.removeEntr() }}</td><!-- change to input type=submit like activecrewlist index pg --> {{ form.hidden_tag() }} </tr> {% endfor %}