Skip to content

Commit

Permalink
working 3rd commit, clean spinner code
Browse files Browse the repository at this point in the history
  • Loading branch information
horeaporutiu committed Sep 20, 2023
1 parent 8840abd commit f837253
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 181 deletions.
4 changes: 0 additions & 4 deletions examples/ai-image-generator/components/PromptInput.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// components/TextInput.js

import React, { useState } from "react";

const TextInput = ({ label, placeholder, value, onChange }) => {

Check warning on line 1 in examples/ai-image-generator/components/PromptInput.jsx

View workflow job for this annotation

GitHub Actions / Run linters

'label' is defined but never used
return (
<div className="form-group">
Expand Down
3 changes: 2 additions & 1 deletion examples/ai-image-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "ai-image-generator",
"version": "0.1.0",
"license": "MIT",
"author": "[email protected]",
"scripts": {
"build": "next build",
"start": "next dev",
Expand All @@ -13,7 +14,7 @@
"dotenv": "^16.0.3",
"mirotone": "5",
"next": "^13.0.0",
"openai": "^4.7.1",
"openai": "^4.8.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
Expand Down
4 changes: 0 additions & 4 deletions examples/ai-image-generator/pages/api/openai.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ const openai = new OpenAI({
export default async (req, res) => {
// grab prompt from the front end
let prompt = await req.body.prompt;
console.log("hello");
console.log(prompt);

try {
const response = await openai.images.generate({
prompt: prompt,
});
console.log("response after open.img.generate");
console.log(response);
let image_url = response.data[0].url;
// send url to front end to display the image
res.status(200).json({
Expand Down
89 changes: 45 additions & 44 deletions examples/ai-image-generator/pages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Button from "../components/Button";

export const getServerSideProps = async function getServerSideProps({ req }) {
const { miro } = initMiro(req);

// redirect to auth url if user has not authorized the app
if (!(await miro.isAuthorized(""))) {
return {
Expand All @@ -15,26 +14,15 @@ export const getServerSideProps = async function getServerSideProps({ req }) {
},
};
}

const api = miro.as("");

const boards = [];

for await (const board of api.getAllBoards()) {
boards.push(board.name || "");
}

return {
props: {
boards,
},
props: {},
};
};

export default function Main({ boards, authUrl }) {

Check warning on line 22 in examples/ai-image-generator/pages/index.jsx

View workflow job for this annotation

GitHub Actions / Run linters

'boards' is defined but never used
useEffect(() => {
removeSpinner();
if (new URLSearchParams(window.location.search).has("panel")) return;

window.miro.board.ui.on("icon:click", async () => {
window.miro.board.ui.openPanel({
url: `/?panel=1`,
Expand All @@ -45,69 +33,78 @@ export default function Main({ boards, authUrl }) {
// Register the drop event handler once.
useEffect(() => {
window.miro.board.ui.on("drop", drop);
console.log("drop event is running");
}, []);

//drag and drop logic
const drop = async (e) => {
const { x, y, target } = e;
showSpinner();
const { initialX, initialY, target } = e;

Check warning on line 41 in examples/ai-image-generator/pages/index.jsx

View workflow job for this annotation

GitHub Actions / Run linters

'initialX' is assigned a value but never used

Check warning on line 41 in examples/ai-image-generator/pages/index.jsx

View workflow job for this annotation

GitHub Actions / Run linters

'initialY' is assigned a value but never used

if (target instanceof HTMLImageElement) {
console.log("about to create image");
let position = await window.miro.board.experimental.findEmptySpace({
x: 0,
y: 0,
width: 200,
height: 200,
});
console.log(position);
let x = position.x;
let y = position.y;

const image = await window.miro.board.createImage({
x,
y,
url: target.src,
});
await window.miro.board.viewport.zoomTo(image);
}
removeSpinner();
};

const [inputValue, setInputValue] = useState("");

//handles the response being returned from backend (URL of image)
const [response, setResponse] = useState("");

//handles the prompt input being typed in
const handleInputChange = (newValue) => {
setInputValue(newValue);
};

// Shows spinner while API calls are in progress
function showSpinner() {
document.querySelector(".spinner").classList.add("show");
async function showSpinner() {
let spinner = await document.getElementById("spinner");
spinner.style.visibility = "visible";
}

// Removes spinner when API calls are finished and data is returned
function removeSpinner() {
document.querySelector(".spinner").classList.remove("show");
async function removeSpinner() {
let spinner = await document.getElementById("spinner");
spinner.style.visibility = "hidden";
}

const handleButtonClick = async () => {
//spinner should start once the API call is made
//setting the image source to be a transparent color, otherwise we have a border which looks bad
document.querySelector("#image").src =
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA";
showSpinner();
setResponse("");

// post our prompt to our backend
try {
const response = await fetch("/api/openai", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt: inputValue }),
});
try {
const response = await fetch("/api/openai", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt: inputValue }),
});

const data = await response.json();
let imageUrl = data.data;
//get the response back from backend, which has the URL which we are looking for
const data = await response.json();
let imageUrl = data.data;

console.log(imageUrl);
setResponse(imageUrl);
document.querySelector("#image").src = imageUrl;
} finally {
removeSpinner();
}
removeSpinner();
document.querySelector("#image").src = imageUrl;
removeSpinner();
} catch (err) {
console.log(err);
}
};

if (authUrl) {
Expand All @@ -124,6 +121,7 @@ try {

return (
<div className="grid wrapper">
{/* Text input which defines the prompt to the API call to OpenAI */}
<div id="promptInput">
<PromptInput
placeholder={"Van Gogh inspired portrait of a dog"}
Expand All @@ -132,14 +130,17 @@ try {
/>
</div>

{/* Button which starts the API call to OpenAI */}
<Button
label="Generate Image"
onClick={handleButtonClick}
id="generateImgBtn"
/>

<div className="spinner"></div>
<div className="spinner" id="spinner"></div>
<div className="image-container">
{/* This image must be draggable. Draggable={false} is syntax needed for Miro image to be
draggble. Src is being set to a gif with transparent background to eliminate ugly border */}
<img
className="miro-draggable"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA"
Expand Down
Binary file not shown.
145 changes: 17 additions & 128 deletions examples/ai-image-generator/src/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ body {
background: url(https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRvF4WdZJSA4MkWJXClae4eCvSdk87c5Ok63fgxBxVyR6aHB2Ju_A)
no-repeat center;
}

/* Spinner From: https://codepen.io/tbrownvisuals/pen/edGYvx */
.spinner {
position: fixed;
Expand All @@ -51,7 +52,7 @@ body {
width: 2em;
overflow: show;
margin: auto;
top: 0;
top: 250px;
left: 0;
bottom: 0;
right: 0;
Expand All @@ -62,136 +63,24 @@ body {
display: block;
}

/* Transparent Overlay */
.spinner:before {
content: "";
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(rgba(20, 20, 20, 0.8), rgba(0, 0, 0, 0.8));

background: -webkit-radial-gradient(
rgba(20, 20, 20, 0.8),
rgba(0, 0, 0, 0.8)
);
}

/* :not(:required) hides these rules from IE9 and below */
.spinner:not(:required) {
/* hide "loading..." text */
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}

.spinner:not(:required):after {
content: "";
display: block;
font-size: 10px;
width: 1em;
height: 1em;
margin-top: -0.5em;
-webkit-animation: spinner 150ms infinite linear;
-moz-animation: spinner 150ms infinite linear;
-ms-animation: spinner 150ms infinite linear;
-o-animation: spinner 150ms infinite linear;
animation: spinner 150ms infinite linear;
border-radius: 0.5em;
-webkit-box-shadow:
rgba(255, 255, 255, 0.75) 1.5em 0 0 0,
rgba(255, 255, 255, 0.75) 1.1em 1.1em 0 0,
rgba(255, 255, 255, 0.75) 0 1.5em 0 0,
rgba(255, 255, 255, 0.75) -1.1em 1.1em 0 0,
rgba(255, 255, 255, 0.75) -1.5em 0 0 0,
rgba(255, 255, 255, 0.75) -1.1em -1.1em 0 0,
rgba(255, 255, 255, 0.75) 0 -1.5em 0 0,
rgba(255, 255, 255, 0.75) 1.1em -1.1em 0 0;
box-shadow:
rgba(255, 255, 255, 0.75) 1.5em 0 0 0,
rgba(255, 255, 255, 0.75) 1.1em 1.1em 0 0,
rgba(255, 255, 255, 0.75) 0 1.5em 0 0,
rgba(255, 255, 255, 0.75) -1.1em 1.1em 0 0,
rgba(255, 255, 255, 0.75) -1.5em 0 0 0,
rgba(255, 255, 255, 0.75) -1.1em -1.1em 0 0,
rgba(255, 255, 255, 0.75) 0 -1.5em 0 0,
rgba(255, 255, 255, 0.75) 1.1em -1.1em 0 0;
}

/* Animation */

@-webkit-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}

100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@-moz-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}

100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@-o-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}

100% {
.spinner {
display: inline-block;
width: 50px;
height: 50px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #121111;
animation: spin 1s ease-in-out infinite;
-webkit-animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
to {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}

100% {
@-webkit-keyframes spin {
to {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
Binary file removed examples/ai-image-generator/src/assets/welcome.png
Binary file not shown.

0 comments on commit f837253

Please sign in to comment.