diff --git a/.gitignore b/.gitignore
index 3b925b8..3e834f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,6 @@ Model_training/AnswerAwareQG/fine_tuned_t5_tokenizer_aaqg_2
backend/models
backend/tokenizers
backend/sample_input.py
-extension/pdfjs-3.9.179-dist
\ No newline at end of file
+extension/pdfjs-3.9.179-dist
+backend/credentials.json
+backend/token.json
\ No newline at end of file
diff --git a/backend/__pycache__/extract_keywords.cpython-310.pyc b/backend/__pycache__/extract_keywords.cpython-310.pyc
new file mode 100644
index 0000000..1bfa4b3
Binary files /dev/null and b/backend/__pycache__/extract_keywords.cpython-310.pyc differ
diff --git a/backend/__pycache__/find_sentances.cpython-310.pyc b/backend/__pycache__/find_sentances.cpython-310.pyc
new file mode 100644
index 0000000..f317f52
Binary files /dev/null and b/backend/__pycache__/find_sentances.cpython-310.pyc differ
diff --git a/backend/server.py b/backend/server.py
index 0d4abe0..3ac70ff 100644
--- a/backend/server.py
+++ b/backend/server.py
@@ -1,114 +1,192 @@
import http.server
+import json
import socketserver
-import urllib.parse
import torch
+from models.modelC.distractor_generator import DistractorGenerator
from transformers import T5ForConditionalGeneration, T5Tokenizer, pipeline
-from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
-import json
-IP='127.0.0.1'
-PORT=8000
+import webbrowser
-def summarize(text):
- summarizer=pipeline('summarization')
- return summarizer(text,max_length=110)[0]['summary_text']
+from apiclient import discovery
+from httplib2 import Http
+from oauth2client import client, file, tools
+
+IP = "127.0.0.1"
+PORT = 8000
-def generate_question(context,answer,model_path, tokenizer_path):
+def summarize(text):
+ summarizer = pipeline("summarization")
+ return summarizer(text, max_length=110)[0]["summary_text"]
+
+def generate_question(context, answer, model_path, tokenizer_path):
model = T5ForConditionalGeneration.from_pretrained(model_path)
tokenizer = T5Tokenizer.from_pretrained(tokenizer_path)
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
- input_text=f'answer: {answer} context: {context}'
+ input_text = f"answer: {answer} context: {context}"
- inputs=tokenizer.encode_plus(
+ inputs = tokenizer.encode_plus(
input_text,
- padding='max_length',
+ padding="max_length",
truncation=True,
max_length=512,
- return_tensors='pt'
+ return_tensors="pt",
)
- input_ids=inputs['input_ids'].to(device)
- attention_mask=inputs['attention_mask'].to(device)
+ input_ids = inputs["input_ids"].to(device)
+ attention_mask = inputs["attention_mask"].to(device)
with torch.no_grad():
- output=model.generate(
- input_ids=input_ids,
- attention_mask=attention_mask,
- max_length=32
+ output = model.generate(
+ input_ids=input_ids, attention_mask=attention_mask, max_length=32
)
generated_question = tokenizer.decode(output[0], skip_special_tokens=True)
return generated_question
-def generate_keyphrases(abstract, model_path,tokenizer_path):
- device= torch.device('cuda' if torch.cuda.is_available() else 'cpu')
+
+def generate_keyphrases(abstract, model_path, tokenizer_path):
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = T5ForConditionalGeneration.from_pretrained(model_path)
tokenizer = T5Tokenizer.from_pretrained(tokenizer_path)
model.to(device)
# tokenizer.to(device)
- input_text=f'detect keyword: abstract: {abstract}'
- input_ids=tokenizer.encode(input_text, truncation=True,padding='max_length',max_length=512,return_tensors='pt').to(device)
- output=model.generate(input_ids)
- keyphrases= tokenizer.decode(output[0],skip_special_tokens=True).split(',')
- return [x.strip() for x in keyphrases if x != '']
-
-def generate_qa(text):
-
- # text_summary=summarize(text)
- text_summary=text
-
-
- modelA, modelB='./models/modelA','./models/modelB'
- # tokenizerA, tokenizerB= './tokenizers/tokenizerA', './tokenizers/tokenizerB'
- tokenizerA, tokenizerB= 't5-base', 't5-base'
-
- answers=generate_keyphrases(text_summary, modelA, tokenizerA)
-
- qa={}
- for answer in answers:
- question= generate_question(text_summary, answer, modelB, tokenizerB)
- qa[question]=answer
-
- return qa
-
-
-
+ input_text = f"detect keyword: abstract: {abstract}"
+ input_ids = tokenizer.encode(
+ input_text,
+ truncation=True,
+ padding="max_length",
+ max_length=512,
+ return_tensors="pt",
+ ).to(device)
+ output = model.generate(input_ids)
+ keyphrases = tokenizer.decode(output[0], skip_special_tokens=True).split(",")
+ return [x.strip() for x in keyphrases if x != ""]
+
+
+def generate_qa(self, text, question_type):
+ modelA, modelB = "./models/modelA", "./models/modelB"
+ tokenizerA, tokenizerB = "t5-base", "t5-base"
+ if question_type == "text":
+ text_summary = text
+ answers = generate_keyphrases(text_summary, modelA, tokenizerA)
+ qa = {}
+ for answer in answers:
+ question = generate_question(text_summary, answer, modelB, tokenizerB)
+ qa[question] = answer
+
+ return qa
+ if question_type == "form":
+ text_summary = text
+ answers = generate_keyphrases(text_summary, modelA, tokenizerA)
+ qa = {}
+ for answer in answers:
+ question = generate_question(text_summary, answer, modelB, tokenizerB)
+ qa[question] = answer
+ SCOPES = "https://www.googleapis.com/auth/forms.body"
+ DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"
+
+ store = file.Storage("token.json")
+ creds = None
+ if not creds or creds.invalid:
+ flow = client.flow_from_clientsecrets("credentials.json", SCOPES)
+ creds = tools.run_flow(flow, store)
+
+ form_service = discovery.build(
+ "forms",
+ "v1",
+ http=creds.authorize(Http()),
+ discoveryServiceUrl=DISCOVERY_DOC,
+ static_discovery=False,
+ )
+ NEW_FORM = {
+ "info": {
+ "title": "EduAid form",
+ }
+ }
+ requests_list = []
+
+ for index, (question, answer) in enumerate(qa.items()):
+ request = {
+ "createItem": {
+ "item": {
+ "title": question,
+ "questionItem": {
+ "question": {
+ "required": True,
+ "textQuestion": {},
+ }
+ },
+ },
+ "location": {"index": index},
+ }
+ }
+ requests_list.append(request)
+
+ NEW_QUESTION = {"requests": requests_list}
+
+ result = form_service.forms().create(body=NEW_FORM).execute()
+ question_setting = (
+ form_service.forms()
+ .batchUpdate(formId=result["formId"], body=NEW_QUESTION)
+ .execute()
+ )
+ edit_url = result["responderUri"]
+ qa["edit_url"] = edit_url
+ webbrowser.open_new_tab(
+ "https://docs.google.com/forms/d/" + result["formId"] + "/edit"
+ )
+ return qa
class QARequestHandler(http.server.BaseHTTPRequestHandler):
- def do_POST(self):
+ def do_OPTIONS(self):
+ self.send_response(200)
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.send_header("Access-Control-Allow-Methods", "POST, OPTIONS")
+ self.send_header("Access-Control-Allow-Headers", "Content-Type")
+ self.send_header("Content-Length", "0")
+ self.end_headers()
+ def do_POST(self):
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
- content_length=int(self.headers["Content-Length"])
- post_data=self.rfile.read(content_length).decode('utf-8')
-
- # parsed_data=urllib.parse.parse_qs(post_data)
+ content_length = int(self.headers["Content-Length"])
+ post_data = self.rfile.read(content_length).decode("utf-8")
parsed_data = json.loads(post_data)
+ if self.path == "/":
+ input_text = parsed_data.get("input_text")
+ question_type = self.headers.get("Question-Type", "text")
+ qa = generate_qa(self, input_text, question_type)
- input_text=parsed_data.get('input_text')
+ self.wfile.write(json.dumps(qa).encode("utf-8"))
+ self.wfile.flush()
- qa=generate_qa(input_text)
+class CustomRequestHandler(QARequestHandler):
+ def __init__(self, *args, **kwargs):
+ self.distractor_generator = kwargs.pop("distractor_generator")
+ super().__init__(*args, **kwargs)
- self.wfile.write(json.dumps(qa).encode("utf-8"))
- self.wfile.flush()
-
def main():
- with socketserver.TCPServer((IP, PORT), QARequestHandler) as server:
- print(f'Server started at http://{IP}:{PORT}')
+ distractor_generator = DistractorGenerator()
+ with socketserver.TCPServer(
+ (IP, PORT),
+ lambda x, y, z: CustomRequestHandler(
+ x, y, z, distractor_generator=distractor_generator
+ ),
+ ) as server:
+ print(f"Server started at http://{IP}:{PORT}")
server.serve_forever()
-if __name__=="__main__":
- main()
-
\ No newline at end of file
+if __name__ == "__main__":
+ main()
diff --git a/extension/html/text_input.html b/extension/html/text_input.html
index f62c2da..56a1a8b 100644
--- a/extension/html/text_input.html
+++ b/extension/html/text_input.html
@@ -2,8 +2,6 @@
EduAid: Text Input
-
@@ -24,11 +22,10 @@ Generate QnA
-
+
-
diff --git a/extension/js/question_generation.js b/extension/js/question_generation.js
index 58bdd94..4f80563 100644
--- a/extension/js/question_generation.js
+++ b/extension/js/question_generation.js
@@ -1,56 +1,61 @@
-document.addEventListener("DOMContentLoaded", function(){
- const saveButton= document.getElementById("save-button");
- const backButton= document.getElementById("back-button");
- const viewQuestionsButton = document.getElementById("view-questions-button");
- const qaPairs=JSON.parse(localStorage.getItem("qaPairs"));
- const modalClose= document.querySelector("[data-close-modal]");
- const modal=document.querySelector("[data-modal]");
-
-
- viewQuestionsButton.addEventListener("click", function(){
- const modalQuestionList = document.getElementById("modal-question-list");
- modalQuestionList.innerHTML = ""; // Clear previous content
-
- for (const [question, answer] of Object.entries(qaPairs)) {
- const questionElement = document.createElement("li");
- questionElement.textContent = `Question: ${question}, Answer: ${answer}`;
- modalQuestionList.appendChild(questionElement)
+document.addEventListener("DOMContentLoaded", function () {
+ const saveButton = document.getElementById("save-button");
+ const backButton = document.getElementById("back-button");
+ const viewQuestionsButton = document.getElementById("view-questions-button");
+ const qaPairs = JSON.parse(localStorage.getItem("qaPairs"));
+ const modalClose = document.querySelector("[data-close-modal]");
+ const modal = document.querySelector("[data-modal]");
+
+ viewQuestionsButton.addEventListener("click", function () {
+ const modalQuestionList = document.getElementById("modal-question-list");
+ modalQuestionList.innerHTML = "";
+
+ for (const [question, answer] of Object.entries(qaPairs)) {
+ const questionElement = document.createElement("li");
+ if (question.includes("Options:")) {
+ const options = question.split("Options: ")[1].split(", ");
+ const formattedOptions = options.map(
+ (opt, index) => `${String.fromCharCode(97 + index)}) ${opt}`
+ );
+ questionElement.textContent = `Question: ${
+ question.split(" Options:")[0]
+ }\n${formattedOptions.join("\n")}`;
+ } else {
+ questionElement.textContent = `Question: ${question}\n\nAnswer: ${answer}\n`;
}
- modal.showModal();
- });
- modalClose.addEventListener("click", function(){
- modal.close();
- });
- saveButton.addEventListener("click", async function(){
- let textContent= "EduAid Generated QnA:\n\n";
+ modalQuestionList.appendChild(questionElement);
+ }
+ modal.showModal();
+ });
- for (const [question,answer] of Object.entries(qaPairs)){
- textContent+= `Question: ${question}\nAnswer: ${answer}\n\n`;
- }
- const blob = new Blob([textContent], { type: "text/plain" });
-
- // Create a URL for the Blob
- const blobUrl = URL.createObjectURL(blob);
-
- // Create a temporary element to trigger the download
- const downloadLink = document.createElement("a");
- downloadLink.href = blobUrl;
- downloadLink.download = "questions_and_answers.txt";
- downloadLink.style.display = "none";
-
- // Append the element to the document
- document.body.appendChild(downloadLink);
-
- // Simulate a click on the link to trigger the download
- downloadLink.click();
-
- // Clean up: remove the temporary element and revoke the Blob URL
- document.body.removeChild(downloadLink);
- URL.revokeObjectURL(blobUrl);
- });
-
- backButton.addEventListener("click", function(){
- window.location.href="../html/text_input.html"
- });
-});
\ No newline at end of file
+ modalClose.addEventListener("click", function () {
+ modal.close();
+ });
+ saveButton.addEventListener("click", async function () {
+ let textContent = "EduAid Generated QnA:\n\n";
+
+ for (const [question, answer] of Object.entries(qaPairs)) {
+ textContent += `Question: ${question}\nAnswer: ${answer}\n\n`;
+ }
+ const blob = new Blob([textContent], { type: "text/plain" });
+
+ const blobUrl = URL.createObjectURL(blob);
+
+ const downloadLink = document.createElement("a");
+ downloadLink.href = blobUrl;
+ downloadLink.download = "questions_and_answers.txt";
+ downloadLink.style.display = "none";
+
+ document.body.appendChild(downloadLink);
+
+ downloadLink.click();
+
+ document.body.removeChild(downloadLink);
+ URL.revokeObjectURL(blobUrl);
+ });
+
+ backButton.addEventListener("click", function () {
+ window.location.href = "../html/text_input.html";
+ });
+});
diff --git a/extension/js/text_input.js b/extension/js/text_input.js
index bf65bb9..6489fe6 100644
--- a/extension/js/text_input.js
+++ b/extension/js/text_input.js
@@ -1,79 +1,93 @@
document.addEventListener("DOMContentLoaded", function () {
- const nextButton = document.getElementById("next-button");
- const backButton = document.getElementById("back-button");
- const textInput = document.getElementById("text-input");
- const fileInput = document.getElementById("file-upload");
- const loadingScreen = document.getElementById("loading-screen");
-
-
- fileInput.addEventListener("change", async function () {
- const file = fileInput.files[0];
- if (file) {
- const fileReader = new FileReader();
- fileReader.onload = async function (event) {
- const pdfData = new Uint8Array(event.target.result);
- const pdf = await pdfjsLib.getDocument({ data: pdfData }).promise;
- let pdfText = "";
-
- for (let i = 1; i <= pdf.numPages; i++) {
- const page = await pdf.getPage(i);
- const pageText = await page.getTextContent();
- const pageStrings = pageText.items.map(item => item.str);
- pdfText += pageStrings.join(" ");
- }
-
- textInput.value = pdfText;
- };
- fileReader.readAsArrayBuffer(file);
- }
- });
+ const nextButton = document.getElementById("next-button");
+ const mcqButton = document.getElementById("mcq-button");
+ const backButton = document.getElementById("back-button");
+ const textInput = document.getElementById("text-input");
+ const fileInput = document.getElementById("file-upload");
+ const createForm = document.getElementById("google-form-button");
+ const loadingScreen = document.getElementById("loading-screen");
- nextButton.addEventListener("click", async function () {
- loadingScreen.style.display = "flex"
- const inputText = textInput.value;
-
- if (inputText.trim() === "" && fileInput.files.length > 0) {
- const file = fileInput.files[0];
- const fileReader = new FileReader();
- fileReader.onload = async function (event) {
- const uploadedPdfData = new Uint8Array(event.target.result);
- await sendToBackend(uploadedPdfData,"pdf");
- };
- fileReader.readAsArrayBuffer(file);
- } else if (inputText.trim() !== "") {
- await sendToBackend(inputText,"text");
- } else {
- alert("Please enter text or upload a PDF file.");
- loadingScreen.style.display = "none";
- }
- });
-
- backButton.addEventListener("click", function () {
- window.location.href = "../html/index.html";
+ fileInput.addEventListener("change", async function () {
+ const file = fileInput.files[0];
+ if (file) {
+ const fileReader = new FileReader();
+ fileReader.onload = async function (event) {
+ const pdfData = new Uint8Array(event.target.result);
+ const pdf = await pdfjsLib.getDocument({ data: pdfData }).promise;
+ let pdfText = "";
+
+ for (let i = 1; i <= pdf.numPages; i++) {
+ const page = await pdf.getPage(i);
+ const pageText = await page.getTextContent();
+ const pageStrings = pageText.items.map((item) => item.str);
+ pdfText += pageStrings.join(" ");
+ }
+
+ textInput.value = pdfText;
+ };
+ fileReader.readAsArrayBuffer(file);
+ }
+ });
+
+ nextButton.addEventListener("click", async function () {
+ await generateQuestion("text");
+ });
+
+ createForm.addEventListener("click", async function () {
+ await generateQuestion("form");
+ });
+
+ backButton.addEventListener("click", function () {
+ window.location.href = "../html/index.html";
+ });
+ document
+ .getElementById("generate-quiz-button")
+ .addEventListener("click", function () {
+ window.location.href = "../html/openai.html";
});
-
- async function sendToBackend(data, dataType) {
- let formData;
- let contentType;
- formData = JSON.stringify({ 'input_text': data });
- contentType = "application/json; charset=UTF-8";
-
- const response = await fetch("http://127.0.0.1:8000", {
- method: "POST",
- body: formData,
- headers: {
- "Content-Type": contentType,
- },
- });
-
- if (response.ok) {
- const responseData = await response.json();
- // console.log("Response data:\n"+responseData);
- localStorage.setItem("qaPairs", JSON.stringify(responseData));
- window.location.href = "../html/question_generation.html";
- } else {
- console.error("Backend request failed.");
- }
+
+ async function generateQuestion(questionType) {
+ loadingScreen.style.display = "flex";
+ const inputText = textInput.value;
+
+ if (inputText.trim() === "" && fileInput.files.length > 0) {
+ const file = fileInput.files[0];
+ const fileReader = new FileReader();
+ fileReader.onload = async function (event) {
+ const uploadedPdfData = new Uint8Array(event.target.result);
+ await sendToBackend(uploadedPdfData, "pdf", questionType);
+ };
+ fileReader.readAsArrayBuffer(file);
+ } else if (inputText.trim() !== "") {
+ await sendToBackend(inputText, "text", questionType);
+ } else {
+ alert("Please enter text or upload a PDF file.");
loadingScreen.style.display = "none";
}
- });
\ No newline at end of file
+ }
+
+ async function sendToBackend(data, dataType, questionType) {
+ let formData;
+ let contentType;
+ formData = JSON.stringify({ input_text: data });
+ contentType = "application/json";
+
+ const response = await fetch("http://127.0.0.1:8000/", {
+ method: "POST",
+ body: formData,
+ headers: {
+ "Content-Type": contentType,
+ "Question-Type": questionType,
+ },
+ });
+
+ if (response.ok) {
+ const responseData = await response.json();
+ localStorage.setItem("qaPairs", JSON.stringify(responseData));
+ window.location.href = "../html/question_generation.html";
+ } else {
+ console.error("Backend request failed.");
+ }
+ loadingScreen.style.display = "none";
+ }
+});
diff --git a/extension/manifest.json b/extension/manifest.json
index dabae1a..a8ea075 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -4,7 +4,7 @@
"version": "1.0",
"description": "Generate quizzes with AI-powered questions.",
"permissions": ["activeTab", "storage"],
- "host_permissions":["http://127.0.0.1:8000/*"],
+ "host_permissions":["http://localhost:8000/*","http://127.0.0.1:8000/*","http://localhost:8000/"],
"icons": {
"16": "./assets/aossie_logo.png"
},
@@ -33,4 +33,4 @@
"matches": [""]
}
]
-}
+}
\ No newline at end of file
diff --git a/extension/styles/index.css b/extension/styles/index.css
index 8c0bae4..5eae184 100644
--- a/extension/styles/index.css
+++ b/extension/styles/index.css
@@ -1,8 +1,4 @@
-
-
-
body{
- /* background-color: rgb(18, 89, 231); */
background-color: #FBAB7E;
background-image: linear-gradient(62deg, #FBAB7E 0%, #F7CE68 100%);
font-family: 'Inter';
@@ -29,7 +25,6 @@ h1 {
flex-direction: column;
align-items: center;
justify-content: center;
- /* height: calc(101vh - 102px); Adjust this height value as needed */
}
h2 {
@@ -49,8 +44,6 @@ p{
--black: #000;
}
-
-/* Style the button */
button {
background: linear-gradient(to right, var(--yellow) 0%, var(--green) 50%, var(--yellow) 100%);
background-size: 500%;
@@ -59,9 +52,6 @@ button {
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
color: var(--black);
cursor: pointer;
- /* font: 1.5em Raleway, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale; */
height: 1.5rem;
letter-spacing: 0.05em;
outline: none;
@@ -71,16 +61,14 @@ button {
-ms-user-select: none;
user-select: none;
width: 7rem;
- transition: background-position 0.7s ease; /* Add transition for background position */
+ transition: background-position 0.7s ease;
margin-bottom: 1px;
}
-/* Style the button on hover */
button:hover {
background-position: 100%; /* Move the background gradient on hover */
}
-/* Add animation for button hover effect */
@keyframes gradient {
0% {
background-position: 0% 50%;
diff --git a/extension/styles/question_generation.css b/extension/styles/question_generation.css
index 605639c..d5c8b95 100644
--- a/extension/styles/question_generation.css
+++ b/extension/styles/question_generation.css
@@ -1,5 +1,4 @@
body{
- /* background-color: rgb(18, 89, 231); */
background-color: #FBAB7E;
background-image: linear-gradient(62deg, #FBAB7E 0%, #F7CE68 100%);
font-family: 'Inter';
@@ -26,7 +25,6 @@ h1 {
flex-direction: column;
align-items: center;
justify-content: center;
- /* height: calc(101vh - 102px); Adjust this height value as needed */
}
h2 {
@@ -63,9 +61,6 @@ button {
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
color: var(--black);
cursor: pointer;
- /* font: 1.5em Raleway, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale; */
height: 1.5rem;
letter-spacing: 0.05em;
outline: none;
@@ -75,15 +70,14 @@ button {
-ms-user-select: none;
user-select: none;
width: 3rem;
- transition: background-position 0.7s ease; /* Add transition for background position */
+ transition: background-position 0.7s ease;
margin-bottom: 1px;
}
button:hover {
- background-position: 100%; /* Move the background gradient on hover */
+ background-position: 100%;
}
- /* Add animation for button hover effect */
@keyframes gradient {
0% {
background-position: 0% 50%;
diff --git a/extension/styles/text_input.css b/extension/styles/text_input.css
index 19e1412..ed7934c 100644
--- a/extension/styles/text_input.css
+++ b/extension/styles/text_input.css
@@ -1,49 +1,77 @@
-body{
- /* background-color: rgb(18, 89, 231); */
- background-color: #FBAB7E;
- background-image: linear-gradient(62deg, #FBAB7E 0%, #F7CE68 100%);
- font-family: 'Inter';
- font-weight: 400; /* Regular */
+body {
+ background-color: #fbab7e;
+ background-image: linear-gradient(62deg, #fbab7e 0%, #f7ce68 100%);
+ font-family: "Inter";
+ font-weight: 400; /* Regular */
}
-header{
- display: flex;
- align-items: center;
- padding: 10px 20px;
-
-}
-img{
- width: 32px;
- height: 32px;
- margin-right: 10px;
-
+header {
+ display: flex;
+ align-items: center;
+ padding: 10px 20px;
+}
+img {
+ width: 32px;
+ height: 32px;
+ margin-right: 10px;
}
h1 {
- font-size: 24px;
- }
- main {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- /* height: calc(101vh - 102px); Adjust this height value as needed */
- }
+ font-size: 24px;
+}
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
- h2 {
- font-size: 28px;
- margin-bottom: 10px;
- }
-p{
- margin-left: 2px;
- margin-right: 2px;
- padding-left: 1px;
- padding-right: 1px;
- text-align: left;
-}
-#text-input{
- height: 30px;
+h2 {
+ font-size: 28px;
+ margin-bottom: 10px;
+}
+p {
+ margin-left: 2px;
+ margin-right: 2px;
+ padding-left: 1px;
+ padding-right: 1px;
+ text-align: left;
+}
+#text-input {
+ height: 150px;
width: 150px;
margin-bottom: 10px;
+ resize: vertical;
+ overflow: auto;
+}
+
+#google-form-button {
+ display: inline-block;
+ background: linear-gradient(
+ to right,
+ var(--yellow) 0%,
+ var(--green) 50%,
+ var(--yellow) 100%
+ );
+ background-size: 500%;
+ border: none;
+ border-radius: 2rem;
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
+ color: var(--black);
+ cursor: pointer;
+ font: 1em Inter, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ height: 2rem;
+ letter-spacing: 0.05em;
+ outline: none;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ width: 8rem;
+ transition: background-position 0.7s ease;
+ margin-top: 10px;
}
:root {
--yellow: #e8f222;
@@ -51,21 +79,20 @@ p{
--black: #000;
}
-
-/* Style the button */
-
button {
display: inline-block;
- background: linear-gradient(to right, var(--yellow) 0%, var(--green) 50%, var(--yellow) 100%);
+ background: linear-gradient(
+ to right,
+ var(--yellow) 0%,
+ var(--green) 50%,
+ var(--yellow) 100%
+ );
background-size: 500%;
border: none;
border-radius: 2rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
color: var(--black);
cursor: pointer;
- /* font: 1.5em Raleway, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale; */
height: 1.5rem;
letter-spacing: 0.05em;
outline: none;
@@ -77,20 +104,24 @@ button {
width: 3rem;
transition: background-position 0.7s ease; /* Add transition for background position */
margin-bottom: 1px;
-
}
label {
display: inline-block;
- background: linear-gradient(to right, var(--yellow) 0%, var(--green) 50%, var(--yellow) 100%);
+ background: linear-gradient(
+ to right,
+ var(--yellow) 0%,
+ var(--green) 50%,
+ var(--yellow) 100%
+ );
background-size: 500%;
border: none;
border-radius: 1rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
color: var(--black);
cursor: pointer;
- font: 1em Inter, sans-serif;
+ font: 1em Inter, sans-serif;
-webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ -moz-osx-font-smoothing: grayscale;
height: 1rem;
letter-spacing: 0.05em;
outline: none;
@@ -100,21 +131,20 @@ label {
-ms-user-select: none;
user-select: none;
width: 7rem;
- transition: background-position 0.7s ease;
+ transition: background-position 0.7s ease;
margin-bottom: 10px;
-
}
-#upload-label{
+#upload-label {
text-align: center;
align-items: center;
margin-top: 2px;
}
-/* Style the button on hover */
-label:hover, button:hover {
- background-position: 100%; /* Move the background gradient on hover */
+
+label:hover,
+button:hover {
+ background-position: 100%;
}
-/* Add animation for button hover effect */
@keyframes gradient {
0% {
background-position: 0% 50%;
@@ -134,7 +164,6 @@ label:hover, button:hover {
z-index: 9999;
justify-content: center;
align-items: center;
-
}
.loading-spinner {
@@ -149,6 +178,10 @@ label:hover, button:hover {
}
@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
}