diff --git a/__pycache__/app.cpython-311.pyc b/__pycache__/app.cpython-311.pyc index 5d9b7c48..e781b418 100644 Binary files a/__pycache__/app.cpython-311.pyc and b/__pycache__/app.cpython-311.pyc differ diff --git a/__pycache__/config.cpython-311.pyc b/__pycache__/config.cpython-311.pyc index 7adbb684..4eec61aa 100644 Binary files a/__pycache__/config.cpython-311.pyc and b/__pycache__/config.cpython-311.pyc differ diff --git a/__pycache__/forms.cpython-311.pyc b/__pycache__/forms.cpython-311.pyc index dc8338bb..d1012abf 100644 Binary files a/__pycache__/forms.cpython-311.pyc and b/__pycache__/forms.cpython-311.pyc differ diff --git a/app.py b/app.py index 67edba02..ca5f0a72 100644 --- a/app.py +++ b/app.py @@ -100,7 +100,7 @@ def home(): return render_template('_page_home.html', model=Model_View_Home(db, get_info_user(), app)) -@app.route('/contact', methods=['GET', 'POST']) +@app.route('/contact', methods=['GET']) def contact(): form = Form_Contact() if form.validate_on_submit(): @@ -115,6 +115,10 @@ def contact(): mail.send(mailItem) return render_template('_page_contact.html', model=Model_View_Contact(db, get_info_user(), app, form)) +@app.route('/services', methods=['GET', 'POST']) +def services(): + return render_template('_page_services.html', model=Model_View_Home(db, get_info_user(), app)) + # Store @app.route('/store', methods=['GET', 'POST']) diff --git a/config.py b/config.py index 25d29489..d37c8b3e 100644 --- a/config.py +++ b/config.py @@ -44,6 +44,9 @@ class Config: MAIL_PASSWORD = os.getenv('MAIL_PASSWORD') MAIL_DEFAULT_SENDER = 'edward.middletonsmith@gmail.com' + RECAPTCHA_PUBLIC_KEY = os.getenv('RECAPTCHA_PUBLIC_KEY') + RECAPTCHA_PRIVATE_KEY = os.getenv('RECAPTCHA_PRIVATE_KEY') + class DevelopmentConfig(Config): DEBUG = True # Add development-specific configuration variables diff --git a/forms.py b/forms.py index 6e3b5ebd..3efee6bb 100644 --- a/forms.py +++ b/forms.py @@ -17,7 +17,7 @@ Defines Flask-WTF forms for handling user input. from flask_wtf import FlaskForm from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired - +from flask_wtf.recaptcha import RecaptchaField class Form_Contact(FlaskForm): @@ -25,6 +25,7 @@ class Form_Contact(FlaskForm): CC = BooleanField('Would you like to receive a copy of this email request?') # not in use name = StringField('Name') msg = TextAreaField('Message') + recaptcha = RecaptchaField() submit = SubmitField('Submit') class Form_Register(FlaskForm): diff --git a/requirements.txt b/requirements.txt index 968a69d8..6b443f41 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,9 +17,13 @@ mysqlclient # SQLALCHEMY_DATABASE_URI = 'mysql://username:password@localhost/dbname' # Replace 'username', 'password', 'localhost', and 'dbname' with your actual database credentials # MAIL_PASSWORD=uifv utsy yzxy hpnm +# RECAPTCHA_PUBLIC_KEY = '' +# RECAPTCHA_PRIVATE_KEY = '' # run with: # python -m flask run +# host network-wide with: +# python -m flask run --host=0.0.0.0 # not env var: # auth0 recovery key: S92HY59VU5J9YDVYWCRHSKJ8 \ No newline at end of file diff --git a/static/css/contact.css b/static/css/contact.css index 93fd8108..89205d10 100644 --- a/static/css/contact.css +++ b/static/css/contact.css @@ -8,6 +8,7 @@ #pageBody > .card:not(:first-of-type) { } + /* .content > a { display: flex; diff --git a/static/css/services.css b/static/css/services.css new file mode 100644 index 00000000..1ef83971 --- /dev/null +++ b/static/css/services.css @@ -0,0 +1,37 @@ +#pageBody > .card { + padding-left: 5vw; + padding-right: 5vw; + max-width: 80vw; +} +#pageBody > .card:first-of-type{ +} +#pageBody > .card:last-of-type { + padding-left: 5vw; + padding-right: 5vw; +} +#pageBody > .card:not(:first-of-type) { +} + +table { + left: 5vw; + max-width: 70vw; + width: fit-content !important; +} + +/* +tr th::after { + content: ""; + position: absolute; + top: 65px; + left: 4%; + width: 92%; + border-bottom: 2px solid var(--c_purple_dark); +} +*/ + +/* +img { + max-height: 5vh; + max-width: 10vw; +} +*/ \ No newline at end of file diff --git a/static/css/shared.css b/static/css/shared.css index bcf5f251..c253cf64 100644 --- a/static/css/shared.css +++ b/static/css/shared.css @@ -51,7 +51,7 @@ h2 { h3 { font-size: 18px; - margin: 1vh; + margin-top: 1vh; } h4 { @@ -92,7 +92,7 @@ h5 { width: 100%; max-height: 15vh; font-weight: normal; - font-size: 25px; + font-size: 20px; } /* .topnav a { @@ -224,13 +224,14 @@ img, video { /* header image */ img.header-logo { max-height: 15vh; + max-width: 20vw; } /* icon images */ .img-icon { - max-width: 5vh; - max-height: 5vh; - border-radius: 1vh; + max-width: 16vh; + max-height: 8vh; + border-radius: 0; } .container-icon-label { @@ -270,6 +271,7 @@ img.header-logo { border-radius: 4vh; /* min-width: fit-content; */ position: relative; + height: fit-content; } .card.subcard { @@ -464,3 +466,8 @@ button, .btn-submit, input[type="submit"] { margin-top: 4.5px; margin-bottom: 4.5px; } + +li { + text-align: left; + font-size: 18px; +} \ No newline at end of file diff --git a/static/images/C#_NET.png b/static/images/C#_NET.png new file mode 100644 index 00000000..98c81744 Binary files /dev/null and b/static/images/C#_NET.png differ diff --git a/static/images/CSS3.jpg b/static/images/CSS3.jpg new file mode 100644 index 00000000..62b709e7 Binary files /dev/null and b/static/images/CSS3.jpg differ diff --git a/static/images/Firebase.png b/static/images/Firebase.png new file mode 100644 index 00000000..082d4a25 Binary files /dev/null and b/static/images/Firebase.png differ diff --git a/static/images/Flask.png b/static/images/Flask.png new file mode 100644 index 00000000..090f6410 Binary files /dev/null and b/static/images/Flask.png differ diff --git a/static/images/HTML5.png b/static/images/HTML5.png new file mode 100644 index 00000000..c6dd2454 Binary files /dev/null and b/static/images/HTML5.png differ diff --git a/static/images/Java.png b/static/images/Java.png new file mode 100644 index 00000000..aa24d48f Binary files /dev/null and b/static/images/Java.png differ diff --git a/static/images/JavaScript.png b/static/images/JavaScript.png new file mode 100644 index 00000000..f96024fc Binary files /dev/null and b/static/images/JavaScript.png differ diff --git a/static/images/MS_SQL_Server.svg b/static/images/MS_SQL_Server.svg new file mode 100644 index 00000000..ea088947 --- /dev/null +++ b/static/images/MS_SQL_Server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/MVC.png b/static/images/MVC.png new file mode 100644 index 00000000..9b12dd2a Binary files /dev/null and b/static/images/MVC.png differ diff --git a/static/images/MySQL.png b/static/images/MySQL.png new file mode 100644 index 00000000..b3e9cebb Binary files /dev/null and b/static/images/MySQL.png differ diff --git a/static/images/Node_js.png b/static/images/Node_js.png new file mode 100644 index 00000000..999c4ea9 Binary files /dev/null and b/static/images/Node_js.png differ diff --git a/static/images/REST.png b/static/images/REST.png new file mode 100644 index 00000000..a3500061 Binary files /dev/null and b/static/images/REST.png differ diff --git a/static/images/React.png b/static/images/React.png new file mode 100644 index 00000000..614f78bf Binary files /dev/null and b/static/images/React.png differ diff --git a/static/images/python.png b/static/images/python.png new file mode 100644 index 00000000..db846141 Binary files /dev/null and b/static/images/python.png differ diff --git a/static/js/services.js b/static/js/services.js new file mode 100644 index 00000000..1b14f553 --- /dev/null +++ b/static/js/services.js @@ -0,0 +1,5 @@ +var _loading = true; + +function hookupPageServices() { + _loading = false; +} diff --git a/static/js/shared.js b/static/js/shared.js index 56c54f32..6e831204 100644 --- a/static/js/shared.js +++ b/static/js/shared.js @@ -59,6 +59,14 @@ function hookupNavigation() { }); }); + let btnNavServices = $(idNavServices); + initialiseEventHandler(btnNavServices, flagInitialised, function() { + btnNavServices.on("click", function(event) { + event.stopPropagation(); + goToPage(hashPageServices); + }); + }); + let btnNavContact = $(idNavContact); initialiseEventHandler(btnNavContact, flagInitialised, function() { btnNavContact.on("click", function(event) { diff --git a/templates/_page_contact.html b/templates/_page_contact.html index c67db85c..36fb1c6e 100644 --- a/templates/_page_contact.html +++ b/templates/_page_contact.html @@ -61,6 +61,9 @@
{{ error }}
{% endfor %} +Your software engineering solution
- +| Database | +Server / Application | +
|---|---|
![]() |
+ ![]() |
+
![]() |
+ |
![]() |
+ ![]() |
+
| + | ![]() |
+
| Web | +Frameworks | +
|---|---|
![]() |
+ ![]() |
+
![]() |
+ ![]() |
+
![]() |
+ ![]() |
+
| + | ![]() |
+
Crafting seamless digital experiences with expertly designed web applications and robust database solutions.
-Empowering businesses with efficient automation, web manipulation, and cutting-edge AI/ML solutions for complex tasks.
-Unleashing the power of MS Office for streamlined data analysis, automation, and enhanced productivity across Excel, PowerPoint, and Outlook.
-Integrating mechanical and electronic components seamlessly for innovative mechatronic solutions, elevating your product design.
-
- Transforming concepts into reality with precision CAD designs, Design for Manufacturing (DFM), and Design for Additive Manufacturing (DFAM) expertise.
-
- Navigating the forefront of materials science and additive manufacturing, providing expert advice on photopolymerisation and innovative AM solutions.
-