Compare commits

..

No commits in common. "master" and "testbranch" have entirely different histories.

51 changed files with 59 additions and 948 deletions

1
.gitignore vendored
View file

@ -1,5 +1,4 @@
/__pycache__ /__pycache__
**/__pycache__
/errorlog.txt /errorlog.txt
/instance /instance
/logs.log /logs.log

View file

@ -32,15 +32,10 @@ def create_app():
app.wsgi_app, x_for=1, x_proto=1 app.wsgi_app, x_for=1, x_proto=1
) )
import app.users.models as user_models from app.users.models import User
import app.campaigns.models as campaign_models
import app.main.models as main_models
@login_manager.user_loader @login_manager.user_loader
def load_user(user_id): def load_user(user_id):
user = user_models.User.query.get(user_id) user = User.query.get(user_id)
if user: if user:
return user return user
else: else:
@ -48,22 +43,17 @@ def create_app():
login_manager.login_view = 'users.login' login_manager.login_view = 'users.login'
from app.users import users from app.users import users
from app.users.users_api import users_api
from app.main import main from app.main import main
from app.campaigns import campaigns from app.campaigns import campaigns
from app.campaigns.campaign_api import campaign_api
from app.admin import admin from app.admin import admin
from app.arba_yesodot import arba_yesodot # from app.agent_reports import agent_reports
# from app.status_reports import status_reports
campaigns.register_blueprint(campaign_api)
users.register_blueprint(users_api)
app.register_blueprint(users) app.register_blueprint(users)
app.register_blueprint(main) app.register_blueprint(main)
app.register_blueprint(campaigns) app.register_blueprint(campaigns)
app.register_blueprint(admin) app.register_blueprint(admin)
app.register_blueprint(arba_yesodot) # app.register_blueprint(agent_reports)
# app.register_blueprint(status_reports)
@app.route('/') @app.route('/')
def reroute_base_url(): def reroute_base_url():

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,8 +1,6 @@
from app import db from app import db
from app.admin import admin from app.admin import admin
from app.users.models import User from app.users.models import User
from app.campaigns.models import Campaign
from app.main.models import Donation
from app.users.forms import LoginForm, RegisterUserForm#, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm from app.users.forms import LoginForm, RegisterUserForm#, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm
from flask import render_template, redirect, url_for, flash, request from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required, login_user, current_user, logout_user from flask_login import login_required, login_user, current_user, logout_user
@ -12,14 +10,4 @@ import os
@admin.route('administration') @admin.route('administration')
def administration(): def administration():
users = User.query.all() return render_template('administration.html')
campaigns = Campaign.query.filter_by(archived=False).all()
return render_template('administration.html',
users=users,
campaigns=campaigns)
@admin.route('archive')
def archive():
archived_campaigns = Campaign.query.filter_by(archived=True).all()
return render_template('archive.html',
archived_campaigns=archived_campaigns)

View file

@ -1,98 +0,0 @@
const archiveButtons = document.getElementsByClassName('archive-button');
const activityButtons = document.getElementsByClassName('change-activity-btn');
const adminButtons = document.getElementsByClassName('change-admin-btn');
function deactivateAdminButtons(){
for (let i = 0; i < adminButtons.length; i++){
adminButtons[i].disabled=true;
}
}
function activateAdminButtons(){
for (let i = 0; i < adminButtons.length; i++){
adminButtons[i].disabled=false;
}
}
function deactivateArchiveButtons(){
for (let i = 0; i < archiveButtons.length; i++){
archiveButtons[i].disabled=true;
}
}
function activateArchiveButtons(){
for (let i = 0; i < archiveButtons.length; i++){
archiveButtons[i].disabled=false;
}
}
function deactivateActiveStatusCheckboxes(){
for (let i = 0; i < activityButtons.length; i++){
activityButtons[i].disabled=true;
}
}
function activateActiveStatusCheckboxes(){
for (let i = 0; i < activityButtons.length; i++){
activityButtons[i].disabled=false;
}
}
function activateAllButtons(){
activateAdminButtons()
activateArchiveButtons()
activateActiveStatusCheckboxes()
}
function deactivateAllButtons(){
deactivateAdminButtons()
deactivateArchiveButtons()
deactivateActiveStatusCheckboxes()
}
async function updateActiveStatus(id, status) {
deactivateAllButtons()
var result = await fetch(`/campaigns/campaign_api/update_active_status/${id}/${status}`, {method:'PUT'});
var data = await result.json();
if (status === true){
status = 'True'
} else {
status = 'False'
}
document.getElementById(`${id}-active-status`).innerText = status;
activateAllButtons()
}
async function archiveCampaign(id){
deactivateAllButtons()
var result = await fetch(`/campaigns/campaign_api/archive_campaign/${id}`, {method:'PUT'});
var data = await result.json();
document.getElementById(`${id}-row`).remove();
activateAllButtons()
}
async function updateAdminStatus(id, status) {
deactivateAllButtons()
var result = await fetch(`/users/users_api/update_admin_status/${id}/${status}`, {method:'PUT'});
var data = await result.json();
if (status === true){
status = 'True'
} else {
status = 'False'
}
document.getElementById(`${id}-admin-status`).innerText = status;
activateAllButtons()
}
document.addEventListener("DOMContentLoaded", (event) => {
for(let i = 0; i < activityButtons.length; i++){
activityButtons[i].addEventListener('change', e => {
updateActiveStatus(parseInt(e.target.value), e.target.checked)
})
}
for(let i = 0; i < archiveButtons.length; i++){
archiveButtons[i].addEventListener('click', e => {
archiveCampaign(parseInt(e.target.value))
})
}
for(let i = 0; i < adminButtons.length; i++){
adminButtons[i].addEventListener('change', e => {
updateAdminStatus(parseInt(e.target.value), e.target.checked)
})
}
});

View file

@ -1,56 +0,0 @@
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}

View file

@ -1,31 +0,0 @@
const unArchiveButtons = document.getElementsByClassName('unarchive-button');
function deactivateUnArchiveButtons(){
for (let i = 0; i < unArchiveButtons.length; i++){
unArchiveButtons[i].disabled=true;
}
}
function activateUnArchiveButtons(){
for (let i = 0; i < unArchiveButtons.length; i++){
unArchiveButtons[i].disabled=false;
}
}
async function unArchiveCampaign(id){
deactivateUnArchiveButtons()
var result = await fetch(`/campaigns/campaign_api/un_archive_campaign/${id}`, {method:'PUT'});
var data = await result.json();
document.getElementById(`${id}-row`).remove();
activateUnArchiveButtons()
}
document.addEventListener("DOMContentLoaded", (event) => {
for(let i = 0; i < unArchiveButtons.length; i++){
unArchiveButtons[i].addEventListener('click', e => {
unArchiveCampaign(parseInt(e.target.value))
})
}
});

View file

@ -1,90 +1,2 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Administration{% endblock title %} {% block title %}Administration{% endblock title %}
{% block stylesheet %}
<link rel="stylesheet" href="{{ url_for('admin.static', filename='administration.css') }}">
{% endblock stylesheet %}
{% block content %}
<main>
<div class="container my-4 px-5">
<h2 class="text-center">Users</h2>
<table class="table table-bordered table-striped">
<thead class="table-dark">
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Is Admin?</th>
<th>Change Admin Status</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{user.id}}</td>
<td>{{user.first_name}}</td>
<td>{{user.last_name}}</td>
<td>{{user.email}}</td>
<td id="{{user.id}}-admin-status">{% if user.user_type == 'Admin' %}True{%else%}False{%endif%}</td>
<td>
<label class="switch">
<input
type="checkbox"
value="{{user.id}}"
id="admin-checkbox-{{user.id}}"
class="change-admin-btn"
{%if user.user_type == 'Admin'%}checked{%endif%}>
<span class="slider round"></span>
</label>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="container my-4 px-5">
<div class="d-flex justify-content-center align-items-center">
<h2 class="me-3">Campaigns</h2>
<a href="{{url_for('campaigns.add_campaign')}}" class="btn btn-primary">New Campaign</a>
</div>
<table class="table table-bordered table-striped">
<thead class="table-dark">
<tr>
<th>#</th>
<th>Title</th>
<th>Active</th>
<th>Change Active Status</th>
<th>Archive?</th>
</tr>
</thead>
<tbody>
{% for campaign in campaigns %}
<tr id="{{campaign.id}}-row" >
<td>{{campaign.id}}</td>
<td>{{campaign.title}}</td>
<td id="{{campaign.id}}-active-status">{{campaign.active}}</td>
<td>
<label class="switch">
<input
type="checkbox"
value="{{campaign.id}}"
id="active-checkbox-{{campaign.id}}"
class="change-activity-btn"
{%if campaign.active%}checked{%endif%}>
<span class="slider round"></span>
</label>
</td>
<td><button
id="archive-button-{{campaign.id}}"
value="{{campaign.id}}"
class="archive-button btn btn-primary">Click to archive</button></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</main>
<script src="{{url_for('.static', filename='admin.js')}}"></script>
{% endblock content %}

View file

@ -1,38 +0,0 @@
{% extends 'base.html' %}
{% block title %}Archive{% endblock title %}
{% block stylesheet %}{% endblock stylesheet %}
{% block content %}
<main>
<div class="container my-4 px-5">
<h2 class="text-center">Archived Campaigns</h2>
<table class="table table-bordered table-striped custom-table">
<thead class="table-dark">
<tr>
<th>Title</th>
<th>Goal</th>
<th>Raised</th>
<th>Campaign Link</th>
<th>Unarchive?</th>
</tr>
</thead>
<tbody>
{% for campaign in archived_campaigns %}
<tr id="{{campaign.id}}-row">
<td>{{campaign.title}}</td>
<td>{{campaign.goal}}</td>
<td>{{campaign.get_amount_raised()}}</td>
<td><a href="{{url_for('campaigns.campaign_page', campaign_id=campaign.id)}}">See campaign details</a></td>
<td><button
id="unarchive-button-{{campaign.id}}"
value="{{campaign.id}}"
class="unarchive-button btn btn-primary">Click to un-archive</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</main>
<script src="{{url_for('.static', filename='archive.js')}}"></script>
{% endblock content %}

View file

@ -1,9 +0,0 @@
from flask import Blueprint
arba_yesodot = Blueprint('arba_yesodot',
__name__,
template_folder='templates',
static_folder='static',
url_prefix='/arba_yesodot')
from app.arba_yesodot import routes

View file

@ -1,15 +0,0 @@
from app import db
from app.arba_yesodot import arba_yesodot
from app.users.models import User
from app.campaigns.models import Campaign
from app.campaigns.forms import CreateCampaignForm
from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required, login_user, current_user, logout_user
from werkzeug.security import check_password_hash, generate_password_hash
from datetime import datetime
import os
from time import sleep
@arba_yesodot.route('arba_yesodot_homepage')
def arba_yesodot_homepage():
return render_template('arba_yesodot_homepage.html')

View file

@ -1,6 +0,0 @@
{% extends 'base.html' %}
{% block title %}Arba Yesodot{% endblock title %}
{% block stylesheet %}{% endblock stylesheet %}
{% block content %}
{% endblock content %}

Binary file not shown.

Binary file not shown.

View file

@ -1,9 +0,0 @@
from flask import Blueprint
campaign_api = Blueprint('campaign_api',
__name__,
template_folder='templates',
static_folder='static',
url_prefix='/campaign_api')
from app.campaigns.campaign_api import routes

View file

@ -1,30 +0,0 @@
from app import db
from flask import render_template
from app.campaigns.campaign_api import campaign_api
from app.campaigns.models import Campaign
from time import sleep
@campaign_api.route('update_active_status/<id>/<status>', methods=['PUT'])
def update_active_status(id, status):
if status == 'true':
status = True
else:
status = False
Campaign.query.filter_by(id=id).update({'active':status})
db.session.commit()
sleep(1)
return {'status':'success'}
@campaign_api.route('archive_campaign/<id>', methods=['PUT'])
def archive_campaign(id):
Campaign.query.filter_by(id=id).update({'archived': True, 'active':False})
db.session.commit()
return {'status':'success'}
@campaign_api.route('un_archive_campaign/<id>', methods=['PUT'])
def un_archive_campaign(id):
Campaign.query.filter_by(id=id).update({'archived': False, 'active':False})
db.session.commit()
return {'status':'success'}

View file

@ -1,20 +0,0 @@
from flask_wtf import FlaskForm
from wtforms import StringField, \
EmailField, \
PasswordField, \
SubmitField, \
SelectField, \
BooleanField,\
DateField, IntegerField
from flask_wtf.file import FileField, FileRequired, FileAllowed
from wtforms.validators import DataRequired, ValidationError, NumberRange, EqualTo, Email
from app.campaigns.models import Campaign
from flask_login import current_user
# import logging
# logging.basicConfig(filename='logs.log', encoding='utf-8', level=logging.DEBUG)
class CreateCampaignForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
active = BooleanField('Initialize as active?')
goal = IntegerField('Goal')
submit = SubmitField('Add Campaign')

View file

@ -6,37 +6,9 @@ import jwt
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
class AmbassadorMap(db.Model):
__tablename__ = 'ambassador_map'
id = Column('id', INTEGER(), primary_key=True)
campaign_id = Column('campaign_id', INTEGER(), nullable=False)
user_id = Column('user_id', INTEGER(), nullable=False)
goal = Column('ambassador_goal', INTEGER())
class Campaign(db.Model): class Campaign(db.Model):
__tablename__ = 'campaign' __tablename__ = 'campaign'
id = Column('id', INTEGER(), primary_key=True) id = Column('id', INTEGER(), primary_key=True)
title = Column('title', TEXT(), nullable=False) title = Column('title', TEXT(), nullable=False)
active = Column('active', Boolean(), nullable=False, default=True) #ambassadors
goal = Column('goal', INTEGER(), default=0)
archived = Column('archived', Boolean(), default=False)
def get_donations(self):
from app.main.models import Donation
return Donation.query.filter_by(campaign_id=self.id).all()
def get_amount_raised(self):
donations = self.get_donations()
total = 0
for donation in donations:
total += donation.amount
return total
def get_ambassadors(self):
return AmbassadorMap.query.filter_by(campaign_id=self.id).all()
def __repr__(self) -> str:
return f"{self.id} - {self.title}"

View file

@ -1,36 +1,13 @@
from app import db from app import db
from app.campaigns import campaigns from app.campaigns import campaigns
from app.users.models import User from app.users.models import User
from app.campaigns.models import Campaign # from forms import LoginForm, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm
from app.campaigns.forms import CreateCampaignForm
from flask import render_template, redirect, url_for, flash, request from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required, login_user, current_user, logout_user from flask_login import login_required, login_user, current_user, logout_user
from werkzeug.security import check_password_hash, generate_password_hash from werkzeug.security import check_password_hash, generate_password_hash
from datetime import datetime from datetime import datetime
import os import os
from time import sleep
@campaigns.route('add_campaign', methods=['GET', 'POST']) @campaigns.route('add_campaign')
def add_campaign(): def add_campaign():
form = CreateCampaignForm() return render_template('add_campaign.html')
if form.validate_on_submit():
campaign = Campaign(
title=form.title.data,
active=form.active.data,
goal=form.goal.data
)
db.session.add(campaign)
db.session.commit()
return redirect(url_for('admin.administration'))
return render_template('add_campaign.html',
form=form)
@campaigns.route('campaign_page/<campaign_id>')
def campaign_page(campaign_id):
campaign = Campaign.query.filter_by(id=campaign_id).first()
return render_template('campaign_page.html',
campaign=campaign)
@campaigns.route('add_ambassador')
def add_ambassador():
return render_template('add_ambassador.html')

View file

@ -1,56 +1,2 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Add campaign{% endblock title %} {% block title %}Add campaign{% endblock title %}
{% block content %}
<main class="container-lg mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h3 class="card-title">Register</h3>
<form method="post" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.title.label(class="form-label") }}
{{ form.title(class="form-control") }}
{% if form.title.errors %}
<ul class="errors">
{% for error in form.title.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<div class="mb-3">
{{ form.active.label(class="form-label") }}
{{ form.active() }}
{% if form.active.errors %}
<ul class="errors">
{% for error in form.active.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<div class="mb-3">
{{ form.goal.label(class="form-label") }}
{{ form.goal(class="form-control") }}
{% if form.goal.errors %}
<ul class="errors">
{% for error in form.goal.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{{ form.submit(class='btn btn-primary') }}
</form>
</div>
</div>
</div>
</div>
</main>
{% endblock content %}

View file

@ -1,62 +0,0 @@
{% extends 'base.html' %}
{% block title %}{{campaign.title}}{% endblock title %}
{% block content %}
<main class="container-lg mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mb-5">
<div class="card-body">
<div class="d-flex justify-content-center align-items-center">
<h2 class="text-center">{{campaign.title}} Ambassadors</h2>
<a href="{{url_for('campaigns.add_ambassador')}}" class="btn btn-primary">Become an ambassador!</a>
</div>
<table class="table table-bordered table-striped">
<thead class="table-dark">
<tr>
<th>Name</th>
<th>Goal</th>
<th>Ambassador Page Link</th>
</tr>
</thead>
<tbody>
{% for campaign_ambassador in campaign.get_ambassadors() %}
<tr>
<td>{{campaign_ambassador.user_id}}</td>
<td>{{campaign_ambassador.goal}}</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-body">
<h2 class="text-center">{{campaign.title}}</h2>
<table class="table table-bordered table-striped">
<thead class="table-dark">
<tr>
<th>#</th>
<th>Amount</th>
<th>User</th>
</tr>
</thead>
<tbody>
{% for campaign_donation in campaign.get_donations() %}
<tr>
<td>{{campaign_donation.id}}</td>
<td>{{campaign_donation.amount}}</td>
<td>{{campaign_donation.get_user()}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
{% endblock content %}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,23 +0,0 @@
from app import db
from flask import current_app
from flask_login import UserMixin, current_user
from sqlalchemy import TEXT, Column, Boolean, ForeignKey, TEXT, INTEGER, VARCHAR
import jwt
from datetime import datetime, timezone, timedelta
class Donation(db.Model):
__tablename__ = 'donation'
id = Column('id', INTEGER(), primary_key=True, autoincrement=True)
currency_type = Column('currency_type', TEXT(), nullable=False)
amount = Column('amount', INTEGER(), nullable=False)
user_id = Column('user_id', INTEGER(), nullable=False)
campaign_id = Column('campaign_id', INTEGER(), nullable=False)
anonymous = Column('anonymous', Boolean(), default=False)
def get_user(self):
from app.users.models import User
return User.query.filter_by(id=self.user_id).first()
def __repr__(self) -> str:
return f"{self.id} - {self.currency_type} - {self.amount}"

View file

@ -1,7 +1,6 @@
from app import db from app import db
from app.main import main from app.main import main
from app.users.models import User from app.users.models import User
from app.campaigns.models import Campaign
# from forms import LoginForm, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm # from forms import LoginForm, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm
from flask import render_template, redirect, url_for, flash, request from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required, login_user, current_user, logout_user from flask_login import login_required, login_user, current_user, logout_user
@ -13,7 +12,6 @@ import os
@main.route('/homepage') @main.route('/homepage')
def homepage(): def homepage():
active_campaigns = Campaign.query.filter_by(active=True).all()
return render_template('homepage.html', return render_template('homepage.html')
active_campaigns=active_campaigns)

View file

@ -14,19 +14,18 @@
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<a href="{{url_for('main.homepage')}}" style="text-decoration: none; margin-right: 10px;"><p>Pilzno</p></a> <a href="{{url_for('main.homepage')}}" style="text-decoration: none; margin-right: 10px;"><p>Pilzno</p></a>
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<a href="{{url_for('users.user_page', user_id=current_user.id)}}" style="text-decoration: none;"><span class="navbar-brand">User Page</span></a> <a href="{{url_for('users.user_page', user_id=current_user.id)}}" style="text-decoration: none;"><span class="navbar-brand">User Page</span></a>
{% if current_user.user_type == 'Admin' %} {% if current_user.user_type == 'Admin' %}
<a href="{{url_for('admin.administration')}}" style="text-decoration: none;"><span class="navbar-brand">Admin Management</span></a> <a href="{{url_for('admin.administration')}}" style="text-decoration: none;"><span class="navbar-brand">Admin Management</span></a>
<a href="{{url_for('admin.archive')}}" style="text-decoration: none;"><span class="navbar-brand">Archive</span></a> {% endif %}
{% endif %} <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="collapse navbar-collapse" id="navbarNavAltMarkup"> <div class="navbar-nav">
<div class="navbar-nav"> <a class="nav-item nav-link active" href="{{url_for('users.logout')}}">Logout</a>
<a class="nav-item nav-link active" href="{{url_for('users.logout')}}">Logout</a> </div>
</div> </div>
</div>
{% else %} {% else %}
<a href="{{url_for('users.login')}}" style="text-decoration: none;"><span class="navbar-brand">Login</span></a> <a href="{{url_for('users.login')}}" style="text-decoration: none;"><span class="navbar-brand">Login</span></a>
<a href="{{url_for('users.register_user')}}" style="text-decoration: none;"><span class="navbar-brand">Register</span></a> <a href="{{url_for('users.register_user')}}" style="text-decoration: none;"><span class="navbar-brand">Register</span></a>
{% endif %} {% endif %}
</nav> </nav>
{% with messages = get_flashed_messages(with_categories=true) %} {% with messages = get_flashed_messages(with_categories=true) %}

View file

@ -1,44 +1,2 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Homepage{% endblock title %} {% block title %}Customer Search{% endblock title %}
{% block stylesheet %}
<style>
.custom-table {
border-radius: 15px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
overflow: hidden; /* Ensures rounded corners apply to the entire table */
}
</style>
{% endblock stylesheet %}
{% block content %}
<main>
<div class="container my-4 px-5">
<div class="text-center mb-4">
<a href="{{ url_for('arba_yesodot.arba_yesodot_homepage') }}" class="btn btn-primary">Check out the arba yesodot program!</a>
</div>
<h2 class="text-center">Visit Campaigns</h2>
<table class="table table-bordered table-striped custom-table">
<thead class="table-dark">
<tr>
<th>Title</th>
<th>Goal</th>
<th>Raised</th>
<th>Campaign Link</th>
</tr>
</thead>
<tbody>
{% for campaign in active_campaigns %}
<tr>
<td>{{campaign.title}}</td>
<td>{{campaign.goal}}</td>
<td>{{campaign.get_amount_raised()}}</td>
<td><a href="{{url_for('campaigns.campaign_page', campaign_id=campaign.id)}}">See campaign details</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</main>
{% endblock content %}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,7 +1,7 @@
from app import db from app import db
from flask import current_app from flask import current_app
from flask_login import UserMixin, current_user from flask_login import UserMixin, current_user
from sqlalchemy import TEXT, Column, Boolean, ForeignKey, TEXT, INTEGER, VARCHAR, select from sqlalchemy import TEXT, Column, Boolean, ForeignKey, TEXT, INTEGER, VARCHAR
import jwt import jwt
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
@ -14,14 +14,6 @@ class User(db.Model, UserMixin):
email = Column('email', TEXT(), nullable=False, unique=True) email = Column('email', TEXT(), nullable=False, unique=True)
password = Column('password', TEXT(), nullable=False) password = Column('password', TEXT(), nullable=False)
user_type = Column('user_type', TEXT(), nullable=False) user_type = Column('user_type', TEXT(), nullable=False)
def get_donations(self):
from app.main.models import Donation
return db.session.execute(select(Donation.currency_type,Donation.amount).where(Donation.user_id == self.id)).all()
def __repr__(self) -> str:
return f"{self.first_name} {self.last_name}"
# donation_id = Column(INTEGER, ForeignKey('donation.id'))
def get_reset_token(self, expiration=600): def get_reset_token(self, expiration=600):
reset_token = jwt.encode( reset_token = jwt.encode(

View file

@ -1,8 +1,6 @@
from app import db from app import db
from app.users import users from app.users import users
from app.users.models import User from app.users.models import User
from app.campaigns.models import Campaign
from app.main.models import Donation
from app.users.forms import LoginForm, RegisterUserForm#, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm from app.users.forms import LoginForm, RegisterUserForm#, RequestResetForm, ResetPasswordForm, EditUserForm, AddUserForm
from flask import render_template, redirect, url_for, flash, request from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required, login_user, current_user, logout_user from flask_login import login_required, login_user, current_user, logout_user
@ -17,19 +15,17 @@ import os
@login_required @login_required
def user_page(user_id): def user_page(user_id):
if not int(current_user.id) == int(user_id): if not int(current_user.id) == int(user_id):
return redirect(url_for('main.homepage')) return redirect(url_for('main.dashboard'))
user = User.query.filter_by(id=user_id).first() user = User.query.filter_by(id=user_id).first()
donations = user.get_donations()
return render_template('user_page.html', return render_template('user_page.html',
user=user, user=user)
donations=donations)
@users.route('/') @users.route('/')
@users.route('/login', methods=('GET', 'POST')) @users.route('/login', methods=('GET', 'POST'))
def login(): def login():
if current_user.is_authenticated: if current_user.is_authenticated:
return redirect(url_for('main.homepage')) return redirect(url_for('main.dashboard'))
form = LoginForm() form = LoginForm()
if form.validate_on_submit(): if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first() user = User.query.filter_by(email=form.email.data).first()
@ -70,4 +66,4 @@ def register_user():
login_user(user) login_user(user)
flash('Succesfully Registered!') flash('Succesfully Registered!')
return redirect(url_for('main.homepage')) return redirect(url_for('main.homepage'))
return render_template('register_user.html', form=form) return render_template('register_user.html', form=form)

View file

@ -1,40 +1,38 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}User Page{% endblock title %} {% block title %}User Page{% endblock title %}
{% block content %} {% block content %}
<main class="container-lg mt-5"> <main class="container">
<div class="row mt-4"> <div class="row mt-4">
<div class="col-md-6 offset-md-3"> <div class="col-md-6 offset-md-3">
<h1>Welcome, {{ user.first_name }} {{ user.last_name }}</h1> <h1>Welcome, {{ user.first_name }} {{ user.last_name }}</h1>
<hr> <hr>
</div> </div>
</div> </div>
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mb-5">
<div class="card-body">
<div class="d-flex justify-content-center align-items-center">
<h2 class="text-center">Donations</h2>
</div>
<table class="table table-bordered table-striped">
<thead class="table-dark">
<tr>
<th>Currency</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for donation in donations %}
<tr>
<td>{{donation[0]}}</td>
<td>{{donation[1]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> <div class="row">
</div> <div class="col-md-10 offset-md-1">
{% if user_reports %}
<h2>Downloadable Files:</h2>
<table class="table mt-3">
<thead>
<tr>
<th>Report Type</th>
<th>Number of Rows</th>
<th>Time Created</th>
<th>Range Start</th>
<th>Range End</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% else %}
<p>No reports available.</p>
{% endif %}
</div> </div>
</div> </div>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -1,9 +0,0 @@
from flask import Blueprint
users_api = Blueprint('users_api',
__name__,
template_folder='templates',
static_folder='static',
url_prefix='/users_api')
from app.users.users_api import routes

View file

@ -1,18 +0,0 @@
from app import db
from flask import render_template
from app.users.users_api import users_api
from app.users.models import User
from time import sleep
@users_api.route('update_admin_status/<id>/<status>', methods=['PUT'])
def update_admin_status(id, status):
if status == 'true':
status = 'Admin'
else:
status = 'User'
User.query.filter_by(id=id).update({'user_type':status})
db.session.commit()
sleep(1)
return {'status':'success'}

View file

@ -1,151 +0,0 @@
from sqlalchemy import create_engine, MetaData, Table, select, insert, func, update, bindparam, delete
import os
import csv
from datetime import datetime, timedelta
from dateutil.parser import parse
import time
import json
from werkzeug.security import generate_password_hash
import random
def engineer():
path1 = 'C:/Users/Lenovo/Desktop/Pilzno/instance/site.db'
path2 = '/home/yisroel2/Desktop/Pilzno/instance/site.db'
path3 = '/home/ubuntu/PilznoProject/PilznoProduction/instance/site.db'
for p in [path1, path2, path3]:
if os.path.exists(p):
path = p
break
engine = create_engine(f'sqlite:///{path}')
metadata_obj = MetaData()
metadata_obj.reflect(bind=engine)
return engine, metadata_obj
def check_db():
engine, metadata_obj = engineer()
user_table = Table("user", metadata_obj, autoload_with=engine)
donation_table = Table("donation", metadata_obj, autoload_with=engine)
campaign_table = Table("campaign", metadata_obj, autoload_with=engine)
with engine.connect() as conn:
print('USERS')
users = conn.execute(select(user_table)).all()
if users:
for user in users:
print(user.first_name)
else:
print('no users')
print("DONATIONS")
donations = conn.execute(select(donation_table)).all()
if donations:
for donation in donations:
print(donation.id)
else:
print('no donations')
campaigns = conn.execute(select(campaign_table)).all()
print('CAMPAIGNS')
if campaigns:
for campaign in campaigns:
print(campaign.title)
else:
print('no campaigns')
def insert_users():
users = [
['Yisroel', 'Baum', 'yisroel.d.baum@gmail.com', generate_password_hash('12'), 'Admin'],
['Yoni', 'Gerzi', 'yoni@gerzi.com', generate_password_hash('12'), 'User'],
['Shmuli', 'Modes', 'shmuli@modes.com', generate_password_hash('12'), 'User'],
['Emma', 'Baum', 'emma@baum.com', generate_password_hash('12'), 'User'],
['Yisroel', 'Factor', 'yisroel@factor.com', generate_password_hash('12'), 'User'],
['Yaakov', 'Frager', 'yaakov@frager.com', generate_password_hash('12'), 'User'],
['Michael', 'Oshman', 'michael@oshman.com', generate_password_hash('12'), 'User'],
['Shalom', 'Goldberg', 'shalom@goldberg.com', generate_password_hash('12'), 'User'],
['Daniel', 'Caller', 'daniel@caller.com', generate_password_hash('12'), 'User'],
]
engine, metadata_obj = engineer()
user_table = Table("user", metadata_obj, autoload_with=engine)
with engine.connect() as conn:
for user in users:
conn.execute(user_table.insert().values(
first_name = user[0],
last_name = user[1],
email = user[2],
password = user[3],
user_type = user[4]
))
conn.commit()
def insert_donations():
engine, metadata_obj = engineer()
donation_table = Table("donation", metadata_obj, autoload_with=engine)
currency_types = ['shekel', 'dollar']
boolean_choice = [True, False]
with engine.connect() as conn:
for _ in range(100):
conn.execute(donation_table.insert().values(
currency_type = currency_types[random.randint(0,1)],
amount = random.randint(1,200),
anonymous = boolean_choice[random.randint(0,1)],
campaign_id=random.randint(1,4),
user_id=random.randint(1,9)
))
conn.commit()
def insert_campaigns():
engine, metadata_obj = engineer()
campaign_table = Table("campaign", metadata_obj, autoload_with=engine)
campaign_titles = ['general campaign', 'yomim noraim 2024', 'pesach kibbudim 2024', 'RH kibbudim 2024']
is_active = [True, False]
with engine.connect() as conn:
for title in campaign_titles:
conn.execute(campaign_table.insert().values(
title=title,
active=is_active[random.randint(0,1)],
goal=5000,
archived=False
))
conn.commit()
def insert_ambassador_relationships():
engine, metadata_obj = engineer()
user_table = Table("user", metadata_obj, autoload_with=engine)
donation_table = Table("donation", metadata_obj, autoload_with=engine)
campaign_table = Table("campaign", metadata_obj, autoload_with=engine)
with engine.connect() as conn:
campaign_ids = conn.execute(select(campaign_table.c.id)).all()
user_ids = conn.execute(select(user_table.c.id)).all()
def test_selections():
engine, metadata_obj = engineer()
user_table = Table("user", metadata_obj, autoload_with=engine)
donation_table = Table("donation", metadata_obj, autoload_with=engine)
campaign_table = Table("campaign", metadata_obj, autoload_with=engine)
def delete_all():
engine, metadata_obj = engineer()
user_table = Table("user", metadata_obj, autoload_with=engine)
donation_table = Table("donation", metadata_obj, autoload_with=engine)
campaign_table = Table("campaign", metadata_obj, autoload_with=engine)
with engine.connect() as conn:
conn.execute(delete(user_table))
conn.execute(delete(campaign_table))
conn.execute(delete(donation_table))
conn.commit()
def insert_all():
insert_users()
insert_campaigns()
insert_donations()
if __name__ == '__main__':
delete_all()
insert_all()

View file

@ -1,39 +0,0 @@
alembic==1.13.2
amqp==5.2.0
billiard==4.2.0
blinker==1.8.2
celery==5.4.0
cffi==1.17.0
click==8.1.7
click-didyoumean==0.3.1
click-plugins==1.1.1
click-repl==0.3.0
colorama==0.4.6
cryptography==43.0.1
dnspython==2.6.1
email_validator==2.2.0
Flask==3.0.3
Flask-Login==0.6.3
Flask-Mail==0.10.0
Flask-Migrate==4.0.7
Flask-SQLAlchemy==3.1.1
Flask-WTF==1.2.1
greenlet==3.0.3
idna==3.8
itsdangerous==2.2.0
Jinja2==3.1.4
jwt==1.3.1
kombu==5.4.0
Mako==1.3.5
MarkupSafe==2.1.5
prompt_toolkit==3.0.47
pycparser==2.22
python-dateutil==2.9.0.post0
six==1.16.0
SQLAlchemy==2.0.33
typing_extensions==4.12.2
tzdata==2024.1
vine==5.1.0
wcwidth==0.2.13
Werkzeug==3.0.4
WTForms==3.1.2