Skip to content
Snippets Groups Projects
Commit 920eb783 authored by Rhiannon Austin's avatar Rhiannon Austin
Browse files

Fixing conflicts

parents ce95164c 5637dcc9
No related branches found
No related tags found
1 merge request!18Login
Showing
with 455 additions and 19 deletions
......@@ -2,5 +2,6 @@
"ExpandedNodes": [
""
],
"SelectedNode": "\\README.md",
"PreviewInSolutionExplorer": false
}
\ No newline at end of file
}
File added
File added
import os
import sqlite3
from typing import List
from typing import List, Tuple
DATABASE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "database.db")
......@@ -50,8 +50,25 @@ with Connection() as conn:
url text NOT NULL,
workspace_id integer NOT NULL,
FOREIGN KEY (workspace_id) REFERENCES Workspaces(id))''')
conn.execute('''CREATE TABLE IF NOT EXISTS AddressToLatLong (
id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
address text NOT NULL,
latlong text NOT NULL)''')
conn.commit()
def lookup_address(address: str):
with Connection() as conn:
conn.execute("SELECT latlong FROM AddressToLatLong WHERE address = ?", (address,))
res = conn.cursor.fetchone()[0]
(lat, long) = res.split(",")
return (float(lat), float(long))
def set_address_latlong(address: str, latlong: Tuple[float, float]):
with Connection() as conn:
latlong_str = f"{ repr(latlong[0]) },{ repr(latlong[1]) }"
conn.execute("INSERT INTO AddressToLatLong (address, latlong) VALUES (?, ?)", (address, latlong_str))
conn.commit()
class Workspace:
def __init__(self, name: str,
address: str, main_photo: str, additional_photos: List[str], description: str,
......@@ -68,10 +85,35 @@ class Workspace:
self.opening_hours = opening_hours
self.checkin_instructions = checkin_instructions
def validate(self):
errors = []
if len(self.name.strip()) <= 0:
errors.append("Name must not be empty")
if len(self.address.strip()) <= 0:
errors.append("Address must not be empty")
if len(self.main_photo.strip()) <= 0:
errors.append("Main photo must not be empty")
if len(self.description.strip()) <= 0:
errors.append("Description must not be empty")
if len(self.website.strip()) <= 0:
errors.append("Website must not be empty")
if len(self.email.strip()) <= 0:
errors.append("Email must not be empty")
if len(self.phone_number.strip()) <= 0:
errors.append("Phone number must not be empty")
if len(self.opening_hours.strip()) <= 0:
errors.append("Opening hours must not be empty")
for x in self.additional_photos:
if len(x.strip()) <= 0:
errors.append("Each edditional photos must not be empty")
return errors
def from_query(conn, tuple):
(id, name, address, main_photo, description, website, email, phone_number, opening_hours, checkin_instructions) = tuple
additional_photos = []
conn.execute("SELECT url FROM AdditionalPhotos WHERE workspace_id = ?", (str(id)))
for x in conn.cursor.fetchall():
additional_photos.append(x[0])
......@@ -96,5 +138,6 @@ def get_workspaces():
with Connection() as conn:
conn.execute("SELECT * FROM Workspaces")
return [Workspace.from_query(conn, x) for x in conn.cursor.fetchall()]
print(get_workspaces())
import database
import os
import json
print(database.add_workspace(database.Workspace(
"CodeBase",
"CodeBase Edinburgh, 37a Castle Terrace, Edinburgh, EH1 2EL",
"https://images.squarespace-cdn.com/content/v1/55439320e4b0f92b5d6c4c8b/1505921023376-PAHUDHVOOKIYF4XQPHOO/5951229048_3e3d50fcb1_o.jpg?format=750w",
["https://images.squarespace-cdn.com/content/v1/55439320e4b0f92b5d6c4c8b/1636387943314-W9JWMS6ZX4DEZSPUV7T0/Copy+of+Unfiltered_square+%281%29.png?format=500w"],
"We've been exploring the world of startups...",
"https://www.thisiscodebase.com",
"hannah@thisiscodebase.com",
"+44 131 560 2003",
"Monday - Friday, 9am - 5pm",
"Tramsched members should contact Hannah using the email address listed."
)))
def import_workspace(data):
workspace = database.Workspace(
data["name"],
data["address"],
data["main_photo"],
data["additional_photos"],
data["description"],
data["website"],
data["email"],
data["phone_number"],
data["opening_hours"],
data["checkin_instructions"]
)
latlong = data["latlong"]
if latlong != None:
database.set_address_latlong(workspace.address, (latlong[0], latlong[1]))
database.add_workspace(workspace)
file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "workspaces.json")
with open(file, "r", encoding="utf8") as stream:
data = json.load(stream)
for workspace in data:
import_workspace(workspace)
print(f"Imported {len(data)} workspace(s)")
from flask import Flask, request, render_template
import database
import json
import re
app = Flask(__name__)
......@@ -9,6 +11,7 @@ def home():
workspaces = database.get_workspaces()
return render_template("home.html", workspaces = workspaces)
@app.route('/login', methods = ["GET"])
def login():
username = request.form.get('username')
......@@ -18,5 +21,67 @@ def login():
message = "Wrong Username"
return redirect("/login.html")
@app.route("/about", methods = ["GET"])
def about():
return render_template("about.html")
@app.route("/Locations", methods = ["GET"])
def Locations():
return render_template("Locations.html")
@app.route("/contact-us", methods = ["GET"])
def contact():
return render_template("contact-us.html")
@app.route("/map", methods = ["GET"])
def map():
if request.method == "GET":
workspaces = database.get_workspaces()
data = [{"id": x.id, "name": x.name, "address": x.address, "phoneNumber": x.phone_number, "email": x.email, "website": x.website, "latlong": database.lookup_address(x.address)} for x in workspaces]
dumped = json.dumps(data)
return render_template("map.html", json = re.sub(r"(?i)\</script\>", "<\/script>", dumped)) # escape </script>
@app.route("/admin/add-workspace", methods = ["GET", "POST"])
def add_workspace():
if request.method == "GET":
return render_template("add-workspace.html")
if request.method == "POST":
additional_photos = request.form["additional_photos"]
additional_photos = [x.strip() for x in additional_photos.split("\n")] if len(additional_photos) > 0 else []
workspace = database.Workspace(
request.form["name"],
request.form["address"],
request.form["main_photo"],
additional_photos,
request.form["description"],
request.form["website"],
request.form["email"],
request.form["phone_number"],
request.form["opening_hours"],
request.form["checkin_instructions"]
)
errors = workspace.validate()
try:
latitude = float(request.form["latitude"])
except ValueError:
errors.append("Latitude must be a number")
try:
longitude = float(request.form["longitude"])
except ValueError:
errors.append("Longitude must be a number")
if len(errors) > 0:
messages = ["Errors were found:"]
messages.extend(errors)
else:
database.set_address_latlong(workspace.address, (latitude, longitude))
database.add_workspace(workspace)
messages = ["Workspace added successfully"]
return render_template("add-workspace-result.html", messages = messages)
if __name__ == "__main__":
app.run(debug = True)
.container {
overflow: hidden;
}
.filterDiv {
float: left;
background-color: #2196F3;
color: #ffffff;
width: 100px;
line-height: 100px;
text-align: center;
margin: 2px;
display: none; /* Hidden by default */
}
.show {
display: block;
}
.btn {
border: none;
outline: none;
padding: 12px 16px;
background-color: #f1f1f1;
cursor: pointer;
}
.btn:hover {
background-color: #ddd;
}
.btn.active {
background-color: #666;
color: white;
}
File added
File added
File added
File added
File added
File added
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
// Add the Show class
for (i = 0; i < x.length; i++) {
RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) AddClass(x[i], "show");
}
}
// Showing filtered elements
function AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
element.className += " " + arr2[i];
}
}
}
// Removing elements that are not selected
function RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to current control button
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
var map = L.map("map").setView([54.004, -2.55], 5);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors"
}).addTo(map);
for (let workspace of mapData) {
L.marker(workspace.latlong).addTo(map)
.bindPopup(`<div class="popup"><div><a href="/workspace/${ encodeURIComponent(workspace.id) }" class="popup-title">${
escapeHTML(workspace.name)
}</a></div><div>Phone: <a href="tel:${ escapeHTML(workspace.phoneNumber) }">${
escapeHTML(workspace.phoneNumber)
}</a></div><div>Email: <a href="mailto:${ escapeHTML(workspace.email) }">${
escapeHTML(workspace.email)
}</a></div><div>Website: <a href="${ escapeHTML(workspace.website) }" target="_blank">${
escapeHTML(workspace.website)
}</a></div><div>${ escapeHTML(workspace.address) }</div></div>`);
}
function escapeHTML(html) {
let lookup = Object.create(null);
lookup["<"] = "&lt;"
lookup[">"] = "&gt;"
lookup["\""] = "&quot;"
lookup["&"] = "&amp";
return html.replace(/[<>"&]/g, v => lookup[v] || "");
}
\ No newline at end of file
h1
{ color: blue;}
/* fonts obtained from and used by https://members.tramshedtech.co.uk/ */
@font-face {
font-family: CircularXX;
src: url(/static/fonts/CircularXX-Book.woff2) format("woff2");
src: url(/static/fonts/CircularXX-Book.woff) format("woff");
font-weight: 400;
font-style: normal
}
@font-face {
font-family: CircularXX;
src: url(/static/fonts/CircularXX-Medium.woff2) format("woff2");
src: url(/static/fonts/CircularXX-Medium.woff) format("woff");
font-weight: 500;
font-style: normal
}
@font-face {
font-family: CircularXX;
src: url(/static/fonts/CircularXX-Bold.woff2) format("woff2");
src: url(/static/fonts/CircularXX-Bold.woff) format("woff");
font-weight: 700;
font-style: normal
}
body {
margin: 0;
font-family: CircularXX,sans-serif;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #111;
text-align: left;
background-color: #f5f5f5
}
header {
background-color: #f5f5f5;
font-size: 30px;
}
nav li {
display: inline;
......@@ -11,7 +54,7 @@ nav li {
nav li:last-child {
color: red;
background-color: red;
background-color:#5F9EA0;
border-right: none;
border-top-left-radius: 1000%;
border-bottom-left-radius: 1000%;
......@@ -21,7 +64,7 @@ nav ul {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
background-color: black;
}
......@@ -50,3 +93,60 @@ nav li a:hover:last-child {
background-color: #111;
}
.workspace-item {
background-color: #fff;
border-radius: 0.5rem;
box-shadow: 0 2px 2px 0 rgb(17 17 17 / 5%);
padding: 1.5rem;
margin: 0.75rem;
display: flex;
}
.workspace-item .image-col {
width: 200px;
}
.workspace-item .image-col .image {
max-width: 100%;
}
.workspace-item .main-col {
flex: 1 0;
margin-left: 1rem;
}
.workspace-item .title {
color: inherit;
display: inline-block;
font-size: 1.25rem;
margin-bottom: 1rem;
font-weight: 600;
line-height: 1.2;
}
.workspace-item .meta {
color: #666;
}
.workspace-item .dot {
color: #666;
font-weight: 700;
}
#map {
height: 600px;
}
#map .popup {
font-family: CircularXX,sans-serif;
font-size: 0.8rem;
font-weight: 400;
line-height: 1.5;
}
#map .popup-title {
color: inherit;
font-size: 1rem;
font-weight: 500;
}
{% extends "main.html" %}
{% block title %}Locations{% endblock %}
{% block mainBlock %}
<div id="myBtnContainer">
<button class="btn active" onclick="filterSelection('all')"> Show all</button>
<button class="btn" onclick="filterSelection('Wales')"> Wales</button>
<button class="btn" onclick="filterSelection('North-England')"> North England</button>
<button class="btn" onclick="filterSelection('South-West-England')"> South West England</button>
<button class="btn" onclick="filterSelection('Midlands')"> Midlands</button>
<<<<<<< HEAD
<button class="btn" onclick="filterSelection('Scotland')"> Scotland</button>
=======
<button class="btn" onclick="filterSelection('Scotland')"> Scotland<button>
>>>>>>> eee8f2dbda7bb480a8543f73de8f7278a1aed2e0
</div>
<div class="container">
<div class="filterDiv Wales">Location 1</div>
<div class="filterDiv Wales">Location 2</div>
<div class="filterDiv North-England">Location 3</div>
<div class="filterDiv North-England">Location 4</div>
<div class="filterDiv South-West-England">Location 5</div>
<div class="filterDiv South-West-England">Location 6</div>
<div class="filterDiv South-West-England">Location 7</div>
<div class="filterDiv Midlands">Location 8</div>
<div class="filterDiv Midlands">Location 9</div>
<div class="filterDiv Scotland">Location 10</div>
<div class="filterDiv Scotland">Location 11</div>
<div class="filterDiv Scotland">Location 12</div>
</div>
{% extends "main.html" %}
{% block title %}About{% endblock %}
{% block mainBlock %}
<header> About 1</header>
<p>text about us.</p>
{% endblock %}
{% extends "main.html" %}
{% block title %}Add Workspace{% endblock %}
{% block mainBlock %}
{% for message in messages %}
<div>{{ message }}</div>
{% endfor %}
{% endblock %}
\ No newline at end of file
{% extends "main.html" %}
{% block title %}Add Workspace{% endblock %}
{% block mainBlock %}
<form action="/admin/add-workspace" method="POST">
<table>
<tr>
<td><label for="name">Name:</label></td>
<td><input id="name" type="text" name="name"></td>
</tr>
<tr>
<td><label for="address">Address:</label></td>
<td><input id="address" type="text" name="address"></td>
</tr>
<tr>
<td><label for="main-photo">Main Photo:</label></td>
<td><input id="main-photo" type="text" name="main_photo"></td>
</tr>
<tr>
<td><label for="additional-photos">Additional Photos:</label></td>
<td><div><textarea id="additional-photos" name="additional_photos"></textarea></div></td>
</tr>
<tr>
<td><label for="description">Description:</label></td>
<td><div><textarea id="description" name="description"></textarea></div></td>
</tr>
<tr>
<td><label for="website">Website:</label></td>
<td><input id="website" type="text" name="website"></td>
</tr>
<tr>
<td><label for="email">Email:</label></td>
<td><input id="email" type="text" name="email"></td>
</tr>
<tr>
<td><label for="phone-number">Phone Number:</label></td>
<td><input id="phone-number" type="text" name="phone_number"></td>
</tr>
<tr>
<td><label for="opening-hours">Opening Hours:</label></td>
<td><input id="opening-hours" type="text" name="opening_hours"></td>
</tr>
<tr>
<td><label for="checkin-instructions">Check-in Instructions:</label></td>
<td><div><textarea id="checkin-instructions" name="checkin_instructions"></textarea></div></td>
</tr>
<tr>
<td><label for="latitude">Latitude:</label></td>
<td><input id="latitude" type="text" name="latitude"></td>
</tr>
<tr>
<td><label for="longitude">Longitude:</label></td>
<td><input id="longitude" type="text" name="longitude"></td>
</tr>
</table>
<input type="submit">
</form>
{% endblock %}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment