Skip to content

Commit

Permalink
Merge pull request #62 from grant-baer/image-saving
Browse files Browse the repository at this point in the history
Image saving
  • Loading branch information
caseyavila authored Dec 6, 2023
2 parents d6d81fd + cbb0f4b commit a95d0b9
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 73 deletions.
27 changes: 13 additions & 14 deletions Backend/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import requests
from flask_cors import CORS, cross_origin

from mongoengine import connect, Document, StringField, DoesNotExist
from mongoengine import connect, Document, StringField, BinaryField, DoesNotExist
from werkzeug.security import generate_password_hash, check_password_hash
import secrets # For generating a session key

Expand All @@ -20,6 +20,8 @@
from db_access import Image
from db_access import check_user, create_user, db_connect, get_image, create_image

import base64


app = Flask(__name__)
cors = CORS(app)
Expand All @@ -34,10 +36,7 @@


@app.route("/generate_image", methods=["POST"])
@jwt_required()
def generate_image():
current_user = get_jwt_identity()

data = request.get_json()
url = "https://imagegolf.io/api/generate"
url_data = {"inputValue": data["prompt"]}
Expand Down Expand Up @@ -85,6 +84,7 @@ def update_image_elo():
@jwt_required()
def store_image():
current_user = get_jwt_identity() # Gets the identity of the current user
print(current_user)

data = request.get_json()
# Validate required fields
Expand All @@ -93,11 +93,13 @@ def store_image():
if field not in data:
return jsonify({"error": f"Missing field: {field}"}), 400

image_res = requests.get(data["url"])

# Prepare the data for creating an image
image_data = {
"creator": current_user, # Assuming the creator is the logged-in user
"prompt": data["prompt"],
"url": data["url"]
"data": image_res.content
}

# Call the create_image function from db_access
Expand All @@ -115,22 +117,20 @@ def store_image():
@app.route("/fetch_portfolio", methods=["GET"])
@jwt_required()
def fetch_portfolio():
current_user_username = get_jwt_identity() # Get the username from the JWT token

try:
# Retrieve the user by username
user = User.objects.get(username=current_user_username)
user = get_jwt_identity()

# Fetch all images created by this user
user_images = Image.objects(creator=user)
portfolio_images = User.objects.get(pk=user).portfolio

# Format the response with the list of images
portfolio = [{
"image_id": str(image.id),
"prompt": image.prompt,
"url": image.url,
"creator": user
} for image in user_images]
"creator": user,
"data": base64.b64encode(image.data).decode("ascii")
} for image in portfolio_images]

return jsonify(portfolio), 200

Expand All @@ -154,7 +154,7 @@ def login():
# Generate session key/token
# This is just a placeholder for an actual session key/token
# session_key = secrets.token_hex(16)
access_token = create_access_token(identity=str(user.username))
access_token = create_access_token(identity=str(user.pk))
# You would store this session key in a session store or database
# with a reference to the user and a valid time period

Expand All @@ -177,7 +177,6 @@ def login():
)
except DoesNotExist:
# Username does not exist
print("bad user")
return (
jsonify({"message": "Login failed, invalid username"}),
401,
Expand Down
15 changes: 7 additions & 8 deletions Backend/db_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
connect,
Document,
StringField,
BinaryField,
IntField,
ListField,
ReferenceField,
Expand Down Expand Up @@ -47,8 +48,8 @@ class User(Document):

class Image(Document):
creator = ReferenceField(User, required=True)
url = StringField(required=True)
prompt = StringField(required=True)
data = BinaryField(required=True)

meta = {"collection": "images"}

Expand All @@ -60,7 +61,6 @@ def create_user(data):
encrypted_password=data["password"],
email=data["email"],
portfolio=[] # Initialize an empty portfolio

)
try:
user.save()
Expand Down Expand Up @@ -91,16 +91,15 @@ def check_user(data):

def create_image(data):
try:
# Retrieve the user by username
creator = User.objects.get(username=data["creator"])

# Create and save the image
image = Image(
creator=creator,
creator=data["creator"],
prompt=data["prompt"],
url=data["url"]
data=data["data"]
)
image.save()

creator = User.objects.get(pk=data["creator"])

# Optionally, you can also append this image to the user's portfolio here
creator.update(push__portfolio=image)
Expand All @@ -109,7 +108,7 @@ def create_image(data):
except DoesNotExist:
return Response("Creator user does not exist.", 404)
except Exception as e:
return Response(f"Internal server error {e}", 500)
return Response(f"Internal server error: {e}", 500)


def get_image(image_id):
Expand Down
49 changes: 35 additions & 14 deletions Frontend/src/pages/create.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,53 @@
import React, { useState } from "react";
import axios from "axios";
import Image from "next/image";
import Cookie from "js-cookie";

export default function Home() {
export default function Create() {
const [text, setText] = useState("");
const [url, setUrl] = useState("");
const [isImageAccepted, setImageAccepted] = useState(null); // null = not decided, true = accepted, false = rejected
const [generating, setGenerating] = useState(false);
const [failed, setFailed] = useState(false);

const handleSubmit = async (e) => {
e.preventDefault();

try {
const response = await axios.post(
setGenerating(true);
setFailed(false);
await axios.post(
"http://localhost:5000/generate_image",
{ prompt: text },
);
).then(response => {
if (response.data.output) {
setUrl(response.data.output);
setImageAccepted(null); // Reset the decision state when a new image is fetched
} else if (response.data.error) {
setFailed(true);
console.error(response.data.error);
}
}).then(() => setGenerating(false));

if (response.data.output) {
setUrl(response.data.output);
setImageAccepted(null); // Reset the decision state when a new image is fetched
} else if (response.data.error) {
console.error(response.data.error);
}
} catch (error) {
console.error("Error:", error);
}
};

const handleAccept = () => {
const handleAccept = async (e) => {
e.preventDefault();

setImageAccepted(true);
// You can add any additional logic here for when the image is accepted
};
await axios.post("http://localhost:5000/store_image",
{
"prompt": text,
"url": url
},
{
headers: {
"Authorization": `Bearer ${Cookie.get("token")}`
}
}).catch((error) => console.error("Error: ", error))};

const handleReject = () => {
setImageAccepted(false);
Expand All @@ -52,9 +69,10 @@ export default function Home() {
/>
<button
type="submit"
className="bg-blue-500 text-white p-2 rounded w-full hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
className="bg-blue-500 text-white p-2 rounded w-full hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:bg-blue-300"
disabled={generating}
>
Submit
{generating ? "Generating..." : "Submit"}
</button>
</form>

Expand Down Expand Up @@ -90,6 +108,9 @@ export default function Home() {
{isImageAccepted === false && (
<p className="mt-8 text-red-500">Image rejected.</p>
)}
{failed === true && (
<p className="mt-8 text-red-500">Image generation failed.</p>
)}
</div>
);
}
32 changes: 16 additions & 16 deletions Frontend/src/pages/nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ const NavBar = () => {
</div>
{/* Primary Navbar items */}
<div className="hidden md:flex items-center space-x-1">
<Link
href="/"
className="py-4 px-2 text-gray-300 font-semibold hover:text-blue-400 transition duration-300"
>
Home
</Link>
<Link
href="/vote"
className="py-4 px-2 text-gray-300 font-semibold hover:text-blue-400 transition duration-300"
Expand All @@ -41,7 +35,13 @@ const NavBar = () => {
href="/leaderboard"
className="py-4 px-2 text-gray-300 font-semibold hover:text-blue-400 transition duration-300"
>
leaderboard
Leaderboard
</Link>
<Link
href="/create"
className="py-4 px-2 text-gray-300 font-semibold hover:text-blue-400 transition duration-300"
>
Create
</Link>
</div>
</div>
Expand All @@ -68,24 +68,18 @@ const NavBar = () => {
<div className="hidden mobile-menu">
<ul className="">
<li>
<Link
href="/"
className="block text-sm px-2 py-4 text-white bg-blue-500 font-semibold"
>
Home
</Link>
</li>
<li>
<Link
href="/Vote"
href="/vote"
className="block text-sm px-2 py-4 hover:bg-blue-500 transition duration-300"
>
Vote
</Link>
</li>
<li>
<Link
href="/Portfolio"
href="/portfolio"
className="block text-sm px-2 py-4 hover:bg-blue-500 transition duration-300"
>
Portfolio
Expand All @@ -96,7 +90,13 @@ const NavBar = () => {
href="/leaderboard"
className="block text-sm px-2 py-4 hover:bg-blue-500 transition duration-300"
>
leaderboard
Leaderboard
</Link>
<Link
href="/create"
className="block text-sm px-2 py-4 hover:bg-blue-500 transition duration-300"
>
Create
</Link>
</li>
</ul>
Expand Down
47 changes: 26 additions & 21 deletions Frontend/src/pages/portfolio.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import Link from "next/link";
import { isAuthenticated } from "./auth"; // Make sure to use the correct path
import Cookie from "js-cookie";
import React, { useEffect, useState } from "react";
import Image from "next/image";
import axios from "axios";

export default function Portfolio() {
const [portfolio, setPortfolio] = useState(null);

useEffect(() => {
async function fetch_portfolio() {
await axios.get("http://localhost:5000/fetch_portfolio",
{
headers: {
"Authorization": `Bearer ${Cookie.get("token")}`
}
}).then(response => {
setPortfolio(response.data);
}).catch((error) => console.error("Error: ", error));
}
fetch_portfolio();
}, []);

return (
<div className="p-6">
<h1 className="text-2xl mb-4">Portfolio</h1>
<div className="grid grid-cols-3 gap-4">
{/* You can map through your portfolio images/items here */}
{portfolio && portfolio.map((image) =>
<Image src={"data:image/png;base64, " + image.data}
loader={() => image.url}
height={500}
width={500}
/>)}
</div>
</div>
);
}

export async function getServerSideProps(context) {
const { req } = context;
const token = req.cookies["token"]; // Replace "your_cookie_name" with your actual cookie name

if (!isAuthenticated(token)) {
// If the user is not authenticated, redirect them to the login page
return {
redirect: {
destination: "/login",
permanent: false,
},
};
}

// If the user is authenticated, render the Portfolio page
return {
props: {}, // Will be passed to the page component as props
};
}

0 comments on commit a95d0b9

Please sign in to comment.