Compare commits
No commits in common. "master" and "testbranch" have entirely different histories.
master
...
testbranch
51 changed files with 59 additions and 948 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,4 @@
|
||||||
/__pycache__
|
/__pycache__
|
||||||
**/__pycache__
|
|
||||||
/errorlog.txt
|
/errorlog.txt
|
||||||
/instance
|
/instance
|
||||||
/logs.log
|
/logs.log
|
||||||
|
|
|
||||||
|
|
@ -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():
|
||||||
|
|
|
||||||
BIN
app/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
app/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
app/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/config.cpython-310.pyc
Normal file
BIN
app/__pycache__/config.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/config.cpython-311.pyc
Normal file
BIN
app/__pycache__/config.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/models.cpython-311.pyc
Normal file
BIN
app/__pycache__/models.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/admin/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
app/admin/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/admin/__pycache__/routes.cpython-310.pyc
Normal file
BIN
app/admin/__pycache__/routes.cpython-310.pyc
Normal file
Binary file not shown.
|
|
@ -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)
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -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%;
|
|
||||||
}
|
|
||||||
|
|
@ -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))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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')
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% block title %}Arba Yesodot{% endblock title %}
|
|
||||||
{% block stylesheet %}{% endblock stylesheet %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
||||||
BIN
app/campaigns/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
app/campaigns/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/campaigns/__pycache__/routes.cpython-310.pyc
Normal file
BIN
app/campaigns/__pycache__/routes.cpython-310.pyc
Normal file
Binary file not shown.
|
|
@ -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
|
|
||||||
|
|
@ -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'}
|
|
||||||
|
|
@ -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')
|
|
||||||
|
|
@ -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}"
|
|
||||||
|
|
@ -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')
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
@ -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 %}
|
|
||||||
BIN
app/main/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
app/main/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/main/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
app/main/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/main/__pycache__/routes.cpython-310.pyc
Normal file
BIN
app/main/__pycache__/routes.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/main/__pycache__/routes.cpython-311.pyc
Normal file
BIN
app/main/__pycache__/routes.cpython-311.pyc
Normal file
Binary file not shown.
|
|
@ -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}"
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -14,6 +13,5 @@ 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)
|
|
||||||
|
|
@ -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) %}
|
||||||
|
|
|
||||||
|
|
@ -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 %}
|
|
||||||
BIN
app/users/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
app/users/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/users/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
app/users/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/users/__pycache__/forms.cpython-310.pyc
Normal file
BIN
app/users/__pycache__/forms.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/users/__pycache__/models.cpython-310.pyc
Normal file
BIN
app/users/__pycache__/models.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/users/__pycache__/models.cpython-311.pyc
Normal file
BIN
app/users/__pycache__/models.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/users/__pycache__/routes.cpython-310.pyc
Normal file
BIN
app/users/__pycache__/routes.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/users/__pycache__/routes.cpython-311.pyc
Normal file
BIN
app/users/__pycache__/routes.cpython-311.pyc
Normal file
Binary file not shown.
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -15,14 +15,6 @@ class User(db.Model, UserMixin):
|
||||||
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(
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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 %}
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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'}
|
|
||||||
|
|
@ -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()
|
|
||||||
|
|
@ -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
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue