Structure synchronised with Apache server on Zume. Styles improved. Store removed from app2.py

This commit is contained in:
2024-04-30 14:49:05 +01:00
parent 6f6fbbcca9
commit 7b4d1ae1b0
43 changed files with 5682 additions and 30 deletions

7
.htaccess Normal file
View File

@@ -0,0 +1,7 @@
PassengerEnabled On
PassengerAppRoot parts_website
PassengerAppType wsgi
PassengerStartupFile passenger_wsgi.py
# Optional: Set the Python interpreter if required
PassengerPython /home/partsltd/virtualenv/public_html/parts_website/3.11/bin/python

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

6
app.py
View File

@@ -713,6 +713,6 @@ def error_403():
# Onload
if __name__ == '__main__':
# app.run()
app.run(debug=True, host="0.0.0.0", port=5000)
if True or __name__ == '__main__':
app.run()
# app.run(debug=True, host="0.0.0.0", port=5000)

204
app2.py Normal file
View File

@@ -0,0 +1,204 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App General
Feature: App
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# VARIABLE INSTANTIATION
# METHODS
# IMPORTS
# internal
from config import app_config, Config
# from routes import bp_home
from forms import Form_Contact
from models.model_view_base import Model_View_Base
from models.model_view_home import Model_View_Home
from models.model_view_contact import Model_View_Contact
from business_objects.product import Product # , Product_Image_Filters, Resolution_Level_Enum
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_mail import Mail, Message
from flask_wtf.csrf import CSRFProtect
import stripe
import json
from dotenv import load_dotenv, find_dotenv
import os
import sys
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
import jwt
# VARIABLE INSTANTIATION
app = Flask(__name__)
csrf = CSRFProtect(app)
CORS(app)
# app.register_blueprint(bp_home, url_prefix='')
email_recipient = 'edward.middletonsmith@gmail.com' # 'noreply'
# app.config.from_object(app_config)
# app.app_config = app_config
app.DEBUG = Config.DEBUG
app.TESTING = Config.TESTING
app.SECRET_KEY = "007cfbdaaf6d1eb27209720e8a5fc8ba0a334ae0be6fcac132b0a471549cde7c" # Config.SECRET_KEY
app.config['SECRET_KEY'] = app.SECRET_KEY
app.SQLALCHEMY_DATABASE_URI = Config.SQLALCHEMY_DATABASE_URI
app.SQLALCHEMY_TRACK_MODIFICATIONS = Config.SQLALCHEMY_TRACK_MODIFICATIONS
app.ID_AUTH0_CLIENT = Config.ID_AUTH0_CLIENT
app.ID_AUTH0_CLIENT_SECRET = Config.ID_AUTH0_CLIENT_SECRET
app.DOMAIN_AUTH0 = Config.DOMAIN_AUTH0
app.ID_TOKEN_USER = Config.ID_TOKEN_USER
app.config.SQLALCHEMY_DATABASE_URI = Config.SQLALCHEMY_DATABASE_URI
app.config.SQLALCHEMY_TRACK_MODIFICATIONS = Config.SQLALCHEMY_TRACK_MODIFICATIONS
app.config.ID_AUTH0_CLIENT = Config.ID_AUTH0_CLIENT
app.config.ID_AUTH0_CLIENT_SECRET = Config.ID_AUTH0_CLIENT_SECRET
app.config.DOMAIN_AUTH0 = Config.DOMAIN_AUTH0
app.config.ID_TOKEN_USER = Config.ID_TOKEN_USER
app.MAIL_SERVER = Config.MAIL_SERVER
app.MAIL_PORT = Config.MAIL_PORT
app.MAIL_USE_TLS = Config.MAIL_USE_TLS
app.MAIL_USERNAME = Config.MAIL_USERNAME
app.MAIL_PASSWORD = Config.MAIL_PASSWORD
app.MAIL_DEFAULT_SENDER = Config.MAIL_DEFAULT_SENDER
app.config['MAIL_SERVER'] = Config.MAIL_SERVER
app.config['MAIL_PORT'] = Config.MAIL_PORT
app.config['MAIL_USE_TLS'] = Config.MAIL_USE_TLS
app.config['MAIL_USERNAME'] = Config.MAIL_USERNAME
app.config['MAIL_PASSWORD'] = Config.MAIL_PASSWORD
app.config['MAIL_DEFAULT_SENDER'] = Config.MAIL_DEFAULT_SENDER
app.RECAPTCHA_PUBLIC_KEY = Config.RECAPTCHA_PUBLIC_KEY
app.config['RECAPTCHA_PUBLIC_KEY'] = Config.RECAPTCHA_PUBLIC_KEY
app.RECAPTCHA_PRIVATE_KEY = Config.RECAPTCHA_PRIVATE_KEY
app.config['RECAPTCHA_PRIVATE_KEY'] = Config.RECAPTCHA_PRIVATE_KEY
# db = SQLAlchemy(app)
app.config['SQLALCHEMY_DATABASE_URI'] = app.SQLALCHEMY_DATABASE_URI
db = SQLAlchemy()
db.init_app(app)
with app.app_context():
db.create_all()
db.engine.url = app.config.SQLALCHEMY_DATABASE_URI
"""
oauth = OAuth(app)
oauth.register(
"auth0",
client_id = app.ID_AUTH0_CLIENT,
client_secret = app.ID_AUTH0_CLIENT_SECRET, # =env.get("AUTH0_CLIENT_SECRET"),
client_kwargs={
"scope": "openid profile email",
},
server_metadata_url=f'https://{app.DOMAIN_AUTH0}/.well-known/openid-configuration'
)
# session[app.ID_TOKEN_USER] = {'userinfo': {'sub': ''}}
"""
mail = Mail(app)
# METHODS
sys.path.insert(0, os.path.dirname(__file__))
@app.route('/hello')
def hello():
return "Hello, World!" + f"{app.errors}\n{app.config.SQLALCHEMY_DATABASE_URI == app.SQLALCHEMY_DATABASE_URI}"
@app.route('/goodbye')
def goodbye():
return "Goodbye, cruel World!"
@app.route('/public_html/403.shtml', methods=['GET'])
def forbidden():
return send_from_directory('/home/partsltd/public_html', '403.shtml')
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
message = 'It works!\n'
version = 'Python %s\n' % sys.version.split()[0]
response = '\n'.join([message, version])
return [response.encode()]
# ROUTING
@app.route('/', methods=['GET'])
def home():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_home.html', model = model)
except Exception as e:
return str(e)
return html_body
@app.route('/contact', methods=['GET'])
def contact():
try:
form = Form_Contact()
model = Model_View_Contact(db, get_info_user(), app, form)
html_body = render_template('_page_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@app.route('/contact', methods=['POST'])
def contact_post():
try:
form = Form_Contact()
if form.validate_on_submit():
# Handle form submission
email = form.email.data
CC = form.CC.data # not in use
name = form.name.data
msg = form.msg.data
# send email
mailItem = Message("PARTS Website Contact Us Message", recipients=[app.config['MAIL_DEFAULT_SENDER']])
mailItem.body = f"Dear Lord Edward Middleton-Smith,\n\n{msg}\n\nKind regards,\n{name}\n{email}"
mail.send(mailItem)
return "Submitted."
return "Invalid. Failed to submit."
# html_body = render_template('_page_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
@app.route('/services', methods=['GET', 'POST'])
# @app.route('/public_html/services', methods=['GET', 'POST'])
def services():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_services.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@app.route('/license', methods=['GET'])
def license():
try:
model = Model_View_Home(db, get_info_user(), app)
html_body = render_template('_page_license.html', model = model)
except Exception as e:
return str(e)
return html_body
def get_info_user():
try:
return session[app.ID_TOKEN_USER].get('userinfo') # .get('sub')
except:
return {'sub': ''}
# Onload
if __name__ == '__main__':
app.run()
# app.run(debug=True, host="0.0.0.0", port=5000)

View File

@@ -60,6 +60,7 @@ class Model_View_Base(ABC):
HASH_PAGE_CONTACT = '/contact'
HASH_PAGE_ERROR_NO_PERMISSION = '/error'
HASH_PAGE_HOME = '/'
HASH_PAGE_LICENSE = '/license'
HASH_PAGE_SERVICES = '/services'
HASH_PAGE_STORE_HOME = '/store'
HASH_PAGE_STORE_PRODUCT = '/store/product'
@@ -77,7 +78,7 @@ class Model_View_Base(ABC):
ID_NAV_STORE_PRODUCT = 'navStoreProduct'
ID_OVERLAY_HAMBURGER = 'overlayHamburger'
ID_PAGE_BODY = 'pageBody'
URL_HOST = 'http://127.0.0.1:5000'
URL_HOST = 'https://www.partsltd.co.uk' # 'http://127.0.0.1:5000'
URL_GITHUB = 'https://github.com/Teddy-1024'
URL_LINKEDIN = 'https://uk.linkedin.com/in/lordteddyms'

15
passenger_wsgi.py Normal file
View File

@@ -0,0 +1,15 @@
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
message = 'It works!\n'
version = 'Python %s\n' % sys.version.split()[0]
response = '\n'.join([message, version])
return [response.encode()]
from app2 import app as application # Import the Flask application from app.py

View File

@@ -6,6 +6,9 @@ flask_cors
authlib
jwt
mysqlclient
stripe
python_dotenv
authlib
# environment variables

7
static/css/license.css Normal file
View File

@@ -0,0 +1,7 @@
.page-body > * {
}
#pageBody > * :first-child{
}
#pageBody > * :last-child {
}

View File

@@ -57,6 +57,9 @@ h3 {
h4 {
font-size: 13px;
margin: 1vh;
text-align: center;
margin-left: auto;
margin-right: auto;
}
h5 {
@@ -135,12 +138,15 @@ h5 {
.company-name {
font-size: 2.5vh;
font-size: min(28px, calc(1vh * 7));
color: white;
margin: 0;
padding: 0;
}
@media screen and (max-width: 450px) {
.company-name {
font-size: min(24px, calc(1vh * 7));
}
}
.page-body {
height: 75vh !important;
@@ -167,7 +173,7 @@ h5 {
text-align: center;
width: 100%;
align-self: center;
font-size: 20px;
font-size: min(20px, calc(1vh * 6));
}
#pageBody > * > * {
width: 100%;
@@ -272,6 +278,9 @@ img.header-logo {
/* min-width: fit-content; */
position: relative;
height: fit-content;
max-width: 80vw;
padding-left: 2.5vw;
padding-right: 2.5vw;
}
.card.subcard {
@@ -290,7 +299,7 @@ img.header-logo {
align-items: flex-start;
justify-content: flex-start;
text-align: flex-start;
max-width: 100%;
/* max-width: 100%; */
/* min-width: fit-content; */
}

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -2,5 +2,14 @@ var _loading = true;
function hookupPageHome() {
hookupVideos();
let btnContact = $($("button.button-contact")[0]);
initialiseEventHandler(btnContact, flagInitialised, function() {
btnContact.on("click", function(event) {
event.stopPropagation();
goToPage(hashPageContact);
});
});
_loading = false;
}

5
static/js/license.js Normal file
View File

@@ -0,0 +1,5 @@
var _loading = true;
function hookupPageHome() {
_loading = false;
}

View File

@@ -10,6 +10,14 @@ function hookupShared() {
$(idOverlayHamburger).removeClass(flagCollapsed);
$(idOverlayHamburger).addClass(flagExpanded);
*/
let imgLogo = $($("img.header-logo")[0]);
initialiseEventHandler(imgLogo, flagInitialised, function() {
imgLogo.on("click", function(event) {
event.stopPropagation();
goToPage(hashPageHome);
});
});
}
function hookupVideos() {

5352
stderr.log

File diff suppressed because it is too large Load Diff

View File

@@ -70,17 +70,16 @@
</form>
</div>
<div class="card">
<h3 class="label-title" style="padding-bottom: 0;">Contact Details</h3>
<div class="container" style="padding-top: 0;">
<h4>edward.middletonsmith@gmail.com</h4>
<a href="{{ model.url_LinkedIn }}" class="container-icon-label"><img class="img-icon" src="{{ url_for('static', filename='images/Logo_LinkedIn.png') }}"/><h4>LinkedIn</h4></a>
<a href="{{ model.url_GitHub }}" class="container-icon-label"><img class="img-icon" src="{{ url_for('static', filename='images/Logo_GitHub.png') }}"/><h4>GitHub</h4></a>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}">
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<h3 class="label-title" style="padding-bottom: 0;">Where to find us</h3>
</div>
<div class="container" style="padding-top: 0;">
<h4>53 Alfred Green Close</h4>
<h4>Rugby, Warwickshire</h4>
<h4>CV22 6DN</h4>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<h4>edward.middletonsmith@gmail.com</h4>
</div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}" style="padding-top: 0; width: fit-content;">
<a href="{{ model.url_LinkedIn }}" class="container-icon-label"><img class="img-icon" src="{{ url_for('static', filename='images/Logo_LinkedIn.png') }}" alt="LinkedIn"></img><!--<h4>LinkedIn</h4>--></a>
<a href="{{ model.url_GitHub }}" class="container-icon-label"><img class="img-icon" src="{{ url_for('static', filename='images/Logo_GitHub.png') }}" alt="GitHub"></img><!--<h4>GitHub</h4>--></a>
</div>
</div>

View File

@@ -10,7 +10,7 @@
<!-- HTML content -->
<div>
<p>Your software engineering solution</p>
<p style="font-size: 24px; color: white;">Your software engineering solution</p>
<button class="button-contact">Get in touch</button>
</div>

View File

@@ -0,0 +1,33 @@
{% extends 'layout.html' %}
{% block title %}{{ model.title }}{% endblock %}
{% block page_body %}
<!-- Include Stylesheet -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/contact.css') }}">
<!-- HTML content -->
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_COLUMN }}">
<p>Copyright &copy; 2024 Precision And Research Technology Systems Limited
</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
</p>
<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
</p>
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</p>
</div>
<!-- Include JavaScript -->
<script src="{{ url_for('static', filename='js/contact.js') }}"></script>
<script>
var hashPageCurrent = "{{ model.HASH_PAGE_LICENSE }}";
$(document).ready(function() {
hookupPageLicense();
});
</script>
{% endblock %}

View File

@@ -21,7 +21,7 @@
<ul>
<li>Expertise to guide your cloud journey and optimize your architecture</li>
<li>Ensure scalability, security and cost-efficiency in the cloud</li>
<li>Unlock the power of cloud-native services to accelerate innovation</li>
<li>Unlock the power of cloud-native services, like AI, to accelerate innovation</li>
</ul>
</div>
</div>
@@ -93,12 +93,12 @@
<td><a href="https://www.python.org/" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/python.png')}}" alt="python"></img></a></td>
</tr>
<tr>
<td><a href="https://www.microsoft.com/en-us/sql-server/sql-server-2019" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/MS_SQL_Server.svg')}}" alt="MS SQL Server"></img></a></td>
<td><a href="https://dotnet.microsoft.com/en-us/languages/csharp" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/C#_NET.png')}}" alt="C# .NET"></img></a></td>
<td><a href="https://www.microsoft.com/en-us/sql-server/sql-server-2019" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/MS_SQL_Server.svg')}}" alt="Microsoft SQL Server"></img></a></td>
<td><a href="https://dotnet.microsoft.com/en-us/languages/csharp" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/Csharp_NET.png')}}" alt="C sharp dot NET"></img></a></td>
</tr>
<tr>
<td><a href="https://firebase.google.com/" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/Firebase.png')}}" alt="Firebase"></img></a></td>
<td><a href="https://nodejs.org/en" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/Node_js.png')}}" alt="Node.js"></img></a></td>
<td><a href="https://nodejs.org/en" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/Node_js.png')}}" alt="Node dot js"></img></a></td>
</tr>
<tr>
<td></td>
@@ -124,7 +124,7 @@
</tr>
<tr>
<td><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/JavaScript.png')}}" alt="JavaScript"></img></a></td>
<td><a href="https://dotnet.microsoft.com/en-us/apps/aspnet/mvc" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/MVC.png')}}" alt="MVC"></img></a></td>
<td><a href="https://dotnet.microsoft.com/en-us/apps/aspnet/mvc" target="_blank"><img class="img-icon" src="{{ url_for('static', filename='images/MVC.png')}}" alt="Model View Controller"></img></a></td>
</tr>
<tr>
<td></td>

View File

@@ -61,13 +61,13 @@
<div class="topnav">
<div class="{{ model.FLAG_CONTAINER }}" style="width: 18vw; min-width: 18vw; max-width: 20vw;">
<img class="header-logo" src="{{ url_for('static', filename='images/Logo.png') }}" alt="PARTS logo">
<img class="header-logo" src="{{ url_for('static', filename='images/Logo.png') }}" alt="PARTS logo" tabindex="0">
</div>
<div class="{{ model.FLAG_CONTAINER }}" style="width: 75vw; min-width: 65vw; max-width: 80vw;">
<p class="company-name">Precision And Research Technology Systems</p>
<h4 class="company-name">Precision And Research Technology Systems</h4>
</div>
<div class="{{ model.FLAG_CONTAINER }}" style="width: 7vw; min-width: 7vw; max-width: 15vw; justify-content: flex-end; "> <!-- padding-left: 25%; -->
<button id="{{ model.ID_BUTTON_HAMBURGER }}">=</button>
<button id="{{ model.ID_BUTTON_HAMBURGER }}" tabindex="1">=</button>
</div>
</div>
@@ -140,7 +140,7 @@
<div class="footer">
<h4 style="padding-top: 1vh;">Copyright (C) Precision And Research Technology Systems Limited. All rights reserved.</h4>
<h4 style="padding-top: 1vh;">Copyright &copy; Precision And Research Technology Systems Limited. All rights reserved.</h4>
<h5>Company number 13587499</h5>
</div>