From 01ac6b61cafac34b600418f384506c9d6da0851f Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Thu, 2 Jan 2025 21:55:56 +0000 Subject: [PATCH 01/17] wip: added magic icon with modal --- django/chat/static/chat/js/chatInput.js | 10 ++++- .../templates/chat/components/chat_input.html | 45 ++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index c2a79f999..6e0fff151 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -81,5 +81,11 @@ document.addEventListener('mouseup', function () { document.querySelector('#chat-prompt').focus(); } }); - - +document.getElementById('copy-result').addEventListener('click', function () { + const editableResult = document.getElementById('editable-result'); + navigator.clipboard.writeText(editableResult.value).then(function () { + alert('{% trans "Copied to clipboard!" %}'); + }).catch(function (err) { + console.error('Could not copy text: ', err); + }); +}); diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index 1ef0348c5..57b22723e 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -94,6 +94,14 @@ aria-label='{% trans "Message" %}' placeholder='{% trans "Type your message here..." %}' required> + + + + + + + + {% block page_script %} {% endblock %} From 7f082c3c1a0e375a3909a0f9b35fc1bb25ffb8a3 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Fri, 3 Jan 2025 21:58:04 +0000 Subject: [PATCH 02/17] wip: prompt api --- django/chat/static/chat/js/chatInput.js | 53 +++++++++++++++++++++---- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index 6e0fff151..8e1d1bb62 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -81,11 +81,50 @@ document.addEventListener('mouseup', function () { document.querySelector('#chat-prompt').focus(); } }); -document.getElementById('copy-result').addEventListener('click', function () { - const editableResult = document.getElementById('editable-result'); - navigator.clipboard.writeText(editableResult.value).then(function () { - alert('{% trans "Copied to clipboard!" %}'); - }).catch(function (err) { - console.error('Could not copy text: ', err); +// // Add the "copy code" button to code blocks NOT WORKING +// const copyCodeButtonHTML = ''; + +// for (const block of document.querySelectorAll("pre code")) { +// block.insertAdjacentHTML("beforebegin", copyCodeButtonHTML); +// } + +// // Add event listener for copy buttons in code blocks NOT WORKING +// document.addEventListener('click', function (event) { +// if (event.target.classList.contains('copy-code-button')) { +// const codeBlock = event.target.nextElementSibling; +// if (codeBlock && codeBlock.tagName === 'CODE') { +// navigator.clipboard.writeText(codeBlock.textContent).then(function () { +// alert('Copied to clipboard!'); +// }).catch(function (err) { +// console.error('Could not copy text: ', err); +// }); +// } +// } +// }); + +// Add event listener for the "Generate" button +const generatePromptButton = document.getElementById('generate-prompt'); +if (generatePromptButton) { + generatePromptButton.addEventListener('click', function () { + const userMessage = document.getElementById('chat-prompt').value; + const magicPrompt = document.getElementById('magic-prompt'); + if (userMessage) { + // Send the userMessage to the AI prompt generator endpoint + fetch('/api/generate-prompt', { //use anthropic's API key + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({message: userMessage}), + }) + .then(response => response.json()) + .then(data => { + // Display the generated prompt in the magicPrompt textarea + magicPrompt.value = data.generated_prompt; + }) + .catch(error => { + console.error('Error generating prompt:', error); + }); + } }); -}); +}; From 3eead26b1f44415b9f6b8e8c92ca830009a545b8 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Mon, 6 Jan 2025 21:52:41 +0000 Subject: [PATCH 03/17] wip: generate button --- django/chat/static/chat/js/chatInput.js | 57 +++++-------------- .../templates/chat/components/chat_input.html | 12 +--- 2 files changed, 16 insertions(+), 53 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index 8e1d1bb62..1ccdea3d3 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -81,50 +81,19 @@ document.addEventListener('mouseup', function () { document.querySelector('#chat-prompt').focus(); } }); -// // Add the "copy code" button to code blocks NOT WORKING -// const copyCodeButtonHTML = ''; -// for (const block of document.querySelectorAll("pre code")) { -// block.insertAdjacentHTML("beforebegin", copyCodeButtonHTML); -// } - -// // Add event listener for copy buttons in code blocks NOT WORKING -// document.addEventListener('click', function (event) { -// if (event.target.classList.contains('copy-code-button')) { -// const codeBlock = event.target.nextElementSibling; -// if (codeBlock && codeBlock.tagName === 'CODE') { -// navigator.clipboard.writeText(codeBlock.textContent).then(function () { -// alert('Copied to clipboard!'); -// }).catch(function (err) { -// console.error('Could not copy text: ', err); -// }); -// } -// } -// }); // Add event listener for the "Generate" button -const generatePromptButton = document.getElementById('generate-prompt'); -if (generatePromptButton) { - generatePromptButton.addEventListener('click', function () { - const userMessage = document.getElementById('chat-prompt').value; - const magicPrompt = document.getElementById('magic-prompt'); - if (userMessage) { - // Send the userMessage to the AI prompt generator endpoint - fetch('/api/generate-prompt', { //use anthropic's API key - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({message: userMessage}), - }) - .then(response => response.json()) - .then(data => { - // Display the generated prompt in the magicPrompt textarea - magicPrompt.value = data.generated_prompt; - }) - .catch(error => { - console.error('Error generating prompt:', error); - }); - } - }); -}; +document.addEventListener('DOMContentLoaded', function () { + const generatePromptButton = document.getElementById('generate-prompt'); + if (generatePromptButton) { + generatePromptButton.addEventListener('click', function () { + const magicPromptValue = document.getElementById('magic-prompt').value; + if (magicPromptValue.trim()) { + alert(`Here is your prompt:\n\n${magicPromptValue}`); + } else { + alert('Please type something first.'); + } + }); + } +}); diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index 57b22723e..a2cd1cdb5 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -133,18 +133,12 @@ id="magic-prompt" rows="4" placeholder='{% trans "Type your prompt here..." %}'> - - + + - From 773ae584aa37f6f40a81b6abfa0b9c1e58393e83 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Tue, 7 Jan 2025 22:14:16 +0000 Subject: [PATCH 04/17] wip openai prompt generator --- django/chat/static/chat/js/chatInput.js | 26 ++--- .../templates/chat/components/chat_input.html | 16 ++- django/chat/views.py | 105 ++++++++++++++++++ 3 files changed, 129 insertions(+), 18 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index 1ccdea3d3..07408f41a 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -82,18 +82,18 @@ document.addEventListener('mouseup', function () { } }); - -// Add event listener for the "Generate" button -document.addEventListener('DOMContentLoaded', function () { - const generatePromptButton = document.getElementById('generate-prompt'); - if (generatePromptButton) { - generatePromptButton.addEventListener('click', function () { - const magicPromptValue = document.getElementById('magic-prompt').value; - if (magicPromptValue.trim()) { - alert(`Here is your prompt:\n\n${magicPromptValue}`); - } else { - alert('Please type something first.'); - } +// Add event listener for the modal form +document.getElementById('modal-from').addEventListener('submit', function (event) { + event.preventDefault(); // prevent modal close + const formData = new FormData(this); + fetch("{% url 'user_input_view' %}", { + method: 'POST', + headers: {'X-CSRFToken': '{{ csrf_token }}'}, + body: formData + }) + .then(response => response.text()) + .then(html => { + // Update the input field inside the modal with the response + document.querySelector('.modal-body input[type="text"]').value = formData.get('user_input'); }); - } }); diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index a2cd1cdb5..14c96227a 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -129,12 +129,18 @@ aria-label="Close"> + + - + {% block page_script %} {% endblock %} diff --git a/django/chat/urls.py b/django/chat/urls.py index 77936d6aa..ec2475daa 100644 --- a/django/chat/urls.py +++ b/django/chat/urls.py @@ -110,4 +110,5 @@ views.set_preset_default, name="set_preset_default", ), + path("user-input/", views.user_input_view, name="user_input_view"), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/django/chat/views.py b/django/chat/views.py index 9172f9339..9146d699d 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -910,105 +910,49 @@ def update_qa_options_from_librarian(request, chat_id, library_id): ) -# openai.api_key = settings.OPENAI_API_KEY -# META_PROMPT = """ -# Given a current prompt and a change description, produce a detailed system prompt to guide a language model in completing the task effectively. - -# Your final output will be the full corrected prompt verbatim. However, before that, at the very beginning of your response, use tags to analyze the prompt and determine the following, explicitly: -# -# - Simple Change: (yes/no) Is the change description explicit and simple? (If so, skip the rest of these questions.) -# - Reasoning: (yes/no) Does the current prompt use reasoning, analysis, or chain of thought? -# - Identify: (max 10 words) if so, which section(s) utilize reasoning? -# - Conclusion: (yes/no) is the chain of thought used to determine a conclusion? -# - Ordering: (before/after) is the chain of though located before or after -# - Structure: (yes/no) does the input prompt have a well defined structure -# - Examples: (yes/no) does the input prompt have few-shot examples -# - Representative: (1-5) if present, how representative are the examples? -# - Complexity: (1-5) how complex is the input prompt? -# - Task: (1-5) how complex is the implied task? -# - Necessity: () -# - Specificity: (1-5) how detailed and specific is the prompt? (not to be confused with length) -# - Prioritization: (list) what 1-3 categories are the MOST important to address. -# - Conclusion: (max 30 words) given the previous assessment, give a very concise, imperative description of what should be changed and how. this does not have to adhere strictly to only the categories listed -# - -# # Guidelines - -# - Understand the Task: Grasp the main objective, goals, requirements, constraints, and expected output. -# - Minimal Changes: If an existing prompt is provided, improve it only if it's simple. For complex prompts, enhance clarity and add missing elements without altering the original structure. -# - Reasoning Before Conclusions**: Encourage reasoning steps before any conclusions are reached. ATTENTION! If the user provides examples where the reasoning happens afterward, REVERSE the order! NEVER START EXAMPLES WITH CONCLUSIONS! -# - Reasoning Order: Call out reasoning portions of the prompt and conclusion parts (specific fields by name). For each, determine the ORDER in which this is done, and whether it needs to be reversed. -# - Conclusion, classifications, or results should ALWAYS appear last. -# - Examples: Include high-quality examples if helpful, using placeholders [in brackets] for complex elements. -# - What kinds of examples may need to be included, how many, and whether they are complex enough to benefit from placeholders. -# - Clarity and Conciseness: Use clear, specific language. Avoid unnecessary instructions or bland statements. -# - Formatting: Use markdown features for readability. DO NOT USE ``` CODE BLOCKS UNLESS SPECIFICALLY REQUESTED. -# - Preserve User Content: If the input task or prompt includes extensive guidelines or examples, preserve them entirely, or as closely as possible. If they are vague, consider breaking down into sub-steps. Keep any details, guidelines, examples, variables, or placeholders provided by the user. -# - Constants: DO include constants in the prompt, as they are not susceptible to prompt injection. Such as guides, rubrics, and examples. -# - Output Format: Explicitly the most appropriate output format, in detail. This should include length and syntax (e.g. short sentence, paragraph, JSON, etc.) -# - For tasks outputting well-defined or structured data (classification, JSON, etc.) bias toward outputting a JSON. -# - JSON should never be wrapped in code blocks (```) unless explicitly requested. - -# The final prompt you output should adhere to the following structure below. Do not include any additional commentary, only output the completed system prompt. SPECIFICALLY, do not include any additional messages at the start or end of the prompt. (e.g. no "---") - -# [Concise instruction describing the task - this should be the first line in the prompt, no section header] - -# [Additional details as needed.] - -# [Optional sections with headings or bullet points for detailed steps.] - -# # Steps [optional] - -# [optional: a detailed breakdown of the steps necessary to accomplish the task] - -# # Output Format - -# [Specifically call out how the output should be formatted, be it response length, structure e.g. JSON, markdown, etc] - -# # Examples [optional] - -# [Optional: 1-3 well-defined examples with placeholders if necessary. Clearly mark where examples start and end, and what the input and output are. User placeholders as necessary.] -# [If the examples are shorter than what a realistic example is expected to be, make a reference with () explaining how real examples should be longer / shorter / different. AND USE PLACEHOLDERS! ] - -# # Notes [optional] - -# [optional: edge cases, details, and an area to call or repeat out specific important considerations] -# [NOTE: you must start with a section. the immediate next token you produce should be ] -# """.strip() - - -# def generate_prompt(task_or_prompt: str): -# completion = client.chat.completions.create( -# model="gpt-4o", -# messages=[ -# { -# "role": "system", -# "content": META_PROMPT, -# }, -# { -# "role": "user", -# "content": "Task, Goal, or Current Prompt:\n" + task_or_prompt, -# }, -# ], -# ) - -# return completion.choices[0].message.content - - -def user_input_view(request): - output_text = "" - if request.method == "POST": - user_input = request.POST.get("user_input", "") - # output_text = generate_prompt(user_input) - return render( - request, "chat/components/chat_input.html", {"output_text": output_text} - ) - +def generate_prompt(task_or_prompt: str): + # completion = client.chat.completions.create( + # model="gpt-4o", + # messages=[ + # { + # "role": "system", + # "content": META_PROMPT, + # }, + # { + # "role": "user", + # "content": "Task, Goal, or Current Prompt:\n" + task_or_prompt, + # }, + # ], + # ) + + # return completion.choices[0].message.content + return "This is a placeholder for the output prompt." -from openai import AsyncAzureOpenAI -client = AsyncAzureOpenAI( - azure_endpoint=settings.AZURE_ENDPOINT, - api_key=settings.AZURE_API_KEY, - api_version="2024-02-15-preview", -) +@require_POST +@permission_required("chat.access_chat", objectgetter(Chat, "chat_id")) +def user_input_view(request, chat_id, current_chat=None): + import logging + + # output_text = "" + # if request.method == "POST": + # user_input = request.POST.get("user_input", "") + # output_text = generate_prompt(user_input) + # return render( + # request, "chat/components/chat_input.html", {"output_text": output_text} + # ) + try: + if request.method == "POST": + user_input = request.POST.get("user_input", "") + logging.info(f"Received user input: {user_input}") + output_text = generate_prompt(user_input) + logging.info(f"Generated prompt: {output_text}") + return render( + request, + "chat/components/generated_prompt.html", + {"output_text": output_text}, + ) + except Exception as e: + logging.error(f"Error in user_input_view: {e}") + return HttpResponse("An error occurred", status=500) + return HttpResponse("") From f1a927b47c8fe755bcb8024468b884844e8ac336 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Wed, 8 Jan 2025 19:35:55 +0000 Subject: [PATCH 06/17] front-end complete with complete with js --- .../chat/components/generated_prompt.html | 35 +++++++++++++++++++ django/chat/urls.py | 2 +- django/chat/views.py | 11 ++---- 3 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 django/chat/templates/chat/components/generated_prompt.html diff --git a/django/chat/templates/chat/components/generated_prompt.html b/django/chat/templates/chat/components/generated_prompt.html new file mode 100644 index 000000000..efe3da2eb --- /dev/null +++ b/django/chat/templates/chat/components/generated_prompt.html @@ -0,0 +1,35 @@ +{% load i18n %} +{% load static %} +{# #} + diff --git a/django/chat/urls.py b/django/chat/urls.py index ec2475daa..1cca17121 100644 --- a/django/chat/urls.py +++ b/django/chat/urls.py @@ -110,5 +110,5 @@ views.set_preset_default, name="set_preset_default", ), - path("user-input/", views.user_input_view, name="user_input_view"), + # path("user-input/", views.user_input_view, name="user_input_view"), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/django/chat/views.py b/django/chat/views.py index 9146d699d..2eed6f646 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -1,4 +1,5 @@ import json +import logging from django.conf import settings from django.contrib.auth import get_user_model @@ -932,15 +933,7 @@ def generate_prompt(task_or_prompt: str): @require_POST @permission_required("chat.access_chat", objectgetter(Chat, "chat_id")) def user_input_view(request, chat_id, current_chat=None): - import logging - - # output_text = "" - # if request.method == "POST": - # user_input = request.POST.get("user_input", "") - # output_text = generate_prompt(user_input) - # return render( - # request, "chat/components/chat_input.html", {"output_text": output_text} - # ) + try: if request.method == "POST": user_input = request.POST.get("user_input", "") From 85e279a618bbe02b54b9e21bc36f7b9440e26f7b Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Wed, 8 Jan 2025 20:47:13 +0000 Subject: [PATCH 07/17] wip ai generator --- django/chat/static/chat/js/chatInput.js | 24 ++++++ django/chat/urls.py | 3 +- django/chat/views.py | 105 ++++++++++++++++++++---- 3 files changed, 113 insertions(+), 19 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index 8a99e7824..222e69450 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -120,3 +120,27 @@ function generatePrompt(input) { // Replace this with your actual prompt generation logic return `Generated prompt for: ${input}`; } + +// document.getElementById('magic-form').addEventListener('submit', function (event) { +// event.preventDefault(); // prevent default form submission +// const userInput = document.getElementById('magic-prompt').value; + +// // Send a POST request to the Django backend +// fetch('/user-input/', { +// method: 'POST', +// headers: { +// 'Content-Type': 'application/json', +// 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, +// }, +// body: JSON.stringify({input: userInput}) +// }) +// .then(response => response.json()) +// .then(data => { +// if (data.prompt) { +// document.getElementById('generated-prompt').value = data.prompt; +// } else { +// console.error('Error:', data.error); +// } +// }) +// .catch(error => console.error('Error:', error)); +// }); diff --git a/django/chat/urls.py b/django/chat/urls.py index 1cca17121..e4f2026db 100644 --- a/django/chat/urls.py +++ b/django/chat/urls.py @@ -110,5 +110,6 @@ views.set_preset_default, name="set_preset_default", ), - # path("user-input/", views.user_input_view, name="user_input_view"), + path("user-input/", views.user_input_view, name="user_input_view"), + path("generate-prompt/", views.generate_prompt, name="generate_prompt"), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/django/chat/views.py b/django/chat/views.py index 2eed6f646..143b56c96 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -912,27 +912,96 @@ def update_qa_options_from_librarian(request, chat_id, library_id): def generate_prompt(task_or_prompt: str): - # completion = client.chat.completions.create( - # model="gpt-4o", - # messages=[ - # { - # "role": "system", - # "content": META_PROMPT, - # }, - # { - # "role": "user", - # "content": "Task, Goal, or Current Prompt:\n" + task_or_prompt, - # }, - # ], - # ) - - # return completion.choices[0].message.content - return "This is a placeholder for the output prompt." + from django.conf import settings + + from openai import OpenAI + + api_key = settings.OPENAI_API_KEY + META_PROMPT = """ + Given a current prompt and a change description, produce a detailed system prompt to guide a language model in completing the task effectively. + + Your final output will be the full corrected prompt verbatim. However, before that, at the very beginning of your response, use tags to analyze the prompt and determine the following, explicitly: + + - Simple Change: (yes/no) Is the change description explicit and simple? (If so, skip the rest of these questions.) + - Reasoning: (yes/no) Does the current prompt use reasoning, analysis, or chain of thought? + - Identify: (max 10 words) if so, which section(s) utilize reasoning? + - Conclusion: (yes/no) is the chain of thought used to determine a conclusion? + - Ordering: (before/after) is the chain of though located before or after + - Structure: (yes/no) does the input prompt have a well defined structure + - Examples: (yes/no) does the input prompt have few-shot examples + - Representative: (1-5) if present, how representative are the examples? + - Complexity: (1-5) how complex is the input prompt? + - Task: (1-5) how complex is the implied task? + - Necessity: () + - Specificity: (1-5) how detailed and specific is the prompt? (not to be confused with length) + - Prioritization: (list) what 1-3 categories are the MOST important to address. + - Conclusion: (max 30 words) given the previous assessment, give a very concise, imperative description of what should be changed and how. this does not have to adhere strictly to only the categories listed + + + # Guidelines + + - Understand the Task: Grasp the main objective, goals, requirements, constraints, and expected output. + - Minimal Changes: If an existing prompt is provided, improve it only if it's simple. For complex prompts, enhance clarity and add missing elements without altering the original structure. + - Reasoning Before Conclusions**: Encourage reasoning steps before any conclusions are reached. ATTENTION! If the user provides examples where the reasoning happens afterward, REVERSE the order! NEVER START EXAMPLES WITH CONCLUSIONS! + - Reasoning Order: Call out reasoning portions of the prompt and conclusion parts (specific fields by name). For each, determine the ORDER in which this is done, and whether it needs to be reversed. + - Conclusion, classifications, or results should ALWAYS appear last. + - Examples: Include high-quality examples if helpful, using placeholders [in brackets] for complex elements. + - What kinds of examples may need to be included, how many, and whether they are complex enough to benefit from placeholders. + - Clarity and Conciseness: Use clear, specific language. Avoid unnecessary instructions or bland statements. + - Formatting: Use markdown features for readability. DO NOT USE ``` CODE BLOCKS UNLESS SPECIFICALLY REQUESTED. + - Preserve User Content: If the input task or prompt includes extensive guidelines or examples, preserve them entirely, or as closely as possible. If they are vague, consider breaking down into sub-steps. Keep any details, guidelines, examples, variables, or placeholders provided by the user. + - Constants: DO include constants in the prompt, as they are not susceptible to prompt injection. Such as guides, rubrics, and examples. + - Output Format: Explicitly the most appropriate output format, in detail. This should include length and syntax (e.g. short sentence, paragraph, JSON, etc.) + - For tasks outputting well-defined or structured data (classification, JSON, etc.) bias toward outputting a JSON. + - JSON should never be wrapped in code blocks (```) unless explicitly requested. + + The final prompt you output should adhere to the following structure below. Do not include any additional commentary, only output the completed system prompt. SPECIFICALLY, do not include any additional messages at the start or end of the prompt. (e.g. no "---") + + [Concise instruction describing the task - this should be the first line in the prompt, no section header] + + [Additional details as needed.] + + [Optional sections with headings or bullet points for detailed steps.] + + # Steps [optional] + + [optional: a detailed breakdown of the steps necessary to accomplish the task] + + # Output Format + + [Specifically call out how the output should be formatted, be it response length, structure e.g. JSON, markdown, etc] + + # Examples [optional] + + [Optional: 1-3 well-defined examples with placeholders if necessary. Clearly mark where examples start and end, and what the input and output are. User placeholders as necessary.] + [If the examples are shorter than what a realistic example is expected to be, make a reference with () explaining how real examples should be longer / shorter / different. AND USE PLACEHOLDERS! ] + + # Notes [optional] + + [optional: edge cases, details, and an area to call or repeat out specific important considerations] + [NOTE: you must start with a section. the immediate next token you produce should be ] + """.strip() + client = OpenAI() + completion = client.chat.completions.create( + model="gpt-4o", + messages=[ + { + "role": "system", + "content": META_PROMPT, + }, + { + "role": "user", + "content": "Task, Goal, or Current Prompt:\n" + task_or_prompt, + }, + ], + ) + + return completion.choices[0].message.content + # return "This is a placeholder for the output prompt." @require_POST -@permission_required("chat.access_chat", objectgetter(Chat, "chat_id")) -def user_input_view(request, chat_id, current_chat=None): +def user_input_view(request): try: if request.method == "POST": From 06729b0616687ad252006213b5a3ea1d199ebf53 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Thu, 9 Jan 2025 19:37:02 +0000 Subject: [PATCH 08/17] wip --- django/chat/static/chat/js/chatInput.js | 41 ++++++----- .../templates/chat/components/chat_input.html | 41 +++++++---- django/chat/urls.py | 5 +- django/chat/views.py | 73 ++++++++++++++----- 4 files changed, 105 insertions(+), 55 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index 222e69450..ed86f795d 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -104,43 +104,44 @@ document.addEventListener('mouseup', function () { // }); // }); +//-------------js only document.getElementById('magic-button').addEventListener('click', function () { const userInput = document.getElementById('chat-prompt').value; document.getElementById('magic-prompt').value = userInput; }); -document.getElementById('magic-form').addEventListener('submit', function (event) { - event.preventDefault(); // prevent default form submission - const userInput = document.getElementById('magic-prompt').value; - const outputText = generatePrompt(userInput); - document.getElementById('generated-prompt').value = outputText; -}); +// document.getElementById('magic-form').addEventListener('submit', function (event) { +// event.preventDefault(); // prevent default form submission +// const userInput = document.getElementById('magic-prompt').value; +// const outputText = generatePrompt(userInput); +// document.getElementById('generated-prompt').value = outputText; +// }); -function generatePrompt(input) { - // Replace this with your actual prompt generation logic - return `Generated prompt for: ${input}`; -} +// function generatePrompt(input) { +// // Replace this with your actual prompt generation logic +// return `Generated prompt for: ${input}`; +// } +//-------------------- +//--------------js with python // document.getElementById('magic-form').addEventListener('submit', function (event) { // event.preventDefault(); // prevent default form submission // const userInput = document.getElementById('magic-prompt').value; +// const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; -// // Send a POST request to the Django backend -// fetch('/user-input/', { +// fetch('/chat/generate-prompt/', { // method: 'POST', // headers: { // 'Content-Type': 'application/json', -// 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, +// 'X-CSRFToken': csrfToken // }, -// body: JSON.stringify({input: userInput}) +// body: JSON.stringify({user_input: userInput}) // }) // .then(response => response.json()) // .then(data => { -// if (data.prompt) { -// document.getElementById('generated-prompt').value = data.prompt; -// } else { -// console.error('Error:', data.error); -// } +// document.getElementById('generated-prompt').value = data.output_text; // }) -// .catch(error => console.error('Error:', error)); +// .catch(error => { +// console.error('Error:', error); +// }); // }); diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index 7afecd893..43565b792 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -130,29 +130,40 @@ aria-label="Close"> - + {% block page_script %} diff --git a/django/chat/urls.py b/django/chat/urls.py index e4f2026db..f87c4e7fa 100644 --- a/django/chat/urls.py +++ b/django/chat/urls.py @@ -110,6 +110,7 @@ views.set_preset_default, name="set_preset_default", ), - path("user-input/", views.user_input_view, name="user_input_view"), - path("generate-prompt/", views.generate_prompt, name="generate_prompt"), + # path("user-input/", views.user_input_view, name="user_input_view"), + # path("generate-prompt/", views.generate_prompt, name="generate_prompt"), + path("generate-prompt/", views.generate_prompt_view, name="generate_prompt_view"), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/django/chat/views.py b/django/chat/views.py index 143b56c96..b366ac7aa 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -996,25 +996,62 @@ def generate_prompt(task_or_prompt: str): ], ) - return completion.choices[0].message.content - # return "This is a placeholder for the output prompt." - - -@require_POST -def user_input_view(request): - - try: - if request.method == "POST": + # return completion.choices[0].message.content + return "This is a placeholder for the output prompt." + + +from django.views.decorators.csrf import csrf_exempt + +# js with python------------------ +# @csrf_exempt +# def generate_prompt_view(request): +# if request.method == "POST": +# try: +# data = json.loads(request.body) +# user_input = data.get("user_input", "") +# logging.info(f"Received user input: {user_input}") +# output_text = ( +# "AI generate prompt will be here" # generate_prompt(user_input) +# ) +# logging.info(f"Generated prompt: {output_text}") +# return JsonResponse({"output_text": output_text}) +# except Exception as e: +# logging.error(f"Error in generate_prompt_view: {e}") +# return JsonResponse({"error": "An error occurred"}, status=500) +# return JsonResponse({"error": "Invalid request method"}, status=400) +# ------------------------------------- + +# @require_POST +# def user_input_view(request): + +# try: +# if request.method == "POST": +# user_input = request.POST.get("user_input", "") +# logging.info(f"Received user input: {user_input}") +# output_text = generate_prompt(user_input) +# logging.info(f"Generated prompt: {output_text}") +# return render( +# request, +# "chat/components/generated_prompt.html", +# {"output_text": output_text}, +# ) +# except Exception as e: +# logging.error(f"Error in user_input_view: {e}") +# return HttpResponse("An error occurred", status=500) +# return HttpResponse("") + + +# htmx------------------ +@csrf_exempt +def generate_prompt_view(request): + if request.method == "POST": + try: user_input = request.POST.get("user_input", "") logging.info(f"Received user input: {user_input}") output_text = generate_prompt(user_input) logging.info(f"Generated prompt: {output_text}") - return render( - request, - "chat/components/generated_prompt.html", - {"output_text": output_text}, - ) - except Exception as e: - logging.error(f"Error in user_input_view: {e}") - return HttpResponse("An error occurred", status=500) - return HttpResponse("") + return JsonResponse({"output_text": output_text}) + except Exception as e: + logging.error(f"Error in generate_prompt_view: {e}") + return JsonResponse({"error": "An error occurred"}, status=500) + return JsonResponse({"error": "Invalid request method"}, status=400) From 700ace3ec31c73726ed899cc993316024732d2e8 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Fri, 10 Jan 2025 22:04:51 +0000 Subject: [PATCH 09/17] generating prompt successful with azure_openai_key, output layout needs more work --- django/chat/views.py | 61 +++++++++++--------------------------------- 1 file changed, 15 insertions(+), 46 deletions(-) diff --git a/django/chat/views.py b/django/chat/views.py index b366ac7aa..69ec4b2fd 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -912,11 +912,18 @@ def update_qa_options_from_librarian(request, chat_id, library_id): def generate_prompt(task_or_prompt: str): + import os + from django.conf import settings - from openai import OpenAI + import openai + from dotenv import load_dotenv + + load_dotenv() + openai.api_key = os.getenv("AZURE_OPENAI_KEY") + # openai.= os.getenv('AZURE_OPENAI_ENDPOINT') + openai.api_version = os.getenv("AZURE_OPENAI_VERSION") - api_key = settings.OPENAI_API_KEY META_PROMPT = """ Given a current prompt and a change description, produce a detailed system prompt to guide a language model in completing the task effectively. @@ -981,8 +988,8 @@ def generate_prompt(task_or_prompt: str): [optional: edge cases, details, and an area to call or repeat out specific important considerations] [NOTE: you must start with a section. the immediate next token you produce should be ] """.strip() - client = OpenAI() - completion = client.chat.completions.create( + + completion = openai.chat.completions.create( model="gpt-4o", messages=[ { @@ -996,52 +1003,14 @@ def generate_prompt(task_or_prompt: str): ], ) - # return completion.choices[0].message.content - return "This is a placeholder for the output prompt." + return completion.choices[0].message.content + # return "This is a placeholder for the output prompt." from django.views.decorators.csrf import csrf_exempt -# js with python------------------ -# @csrf_exempt -# def generate_prompt_view(request): -# if request.method == "POST": -# try: -# data = json.loads(request.body) -# user_input = data.get("user_input", "") -# logging.info(f"Received user input: {user_input}") -# output_text = ( -# "AI generate prompt will be here" # generate_prompt(user_input) -# ) -# logging.info(f"Generated prompt: {output_text}") -# return JsonResponse({"output_text": output_text}) -# except Exception as e: -# logging.error(f"Error in generate_prompt_view: {e}") -# return JsonResponse({"error": "An error occurred"}, status=500) -# return JsonResponse({"error": "Invalid request method"}, status=400) -# ------------------------------------- - -# @require_POST -# def user_input_view(request): - -# try: -# if request.method == "POST": -# user_input = request.POST.get("user_input", "") -# logging.info(f"Received user input: {user_input}") -# output_text = generate_prompt(user_input) -# logging.info(f"Generated prompt: {output_text}") -# return render( -# request, -# "chat/components/generated_prompt.html", -# {"output_text": output_text}, -# ) -# except Exception as e: -# logging.error(f"Error in user_input_view: {e}") -# return HttpResponse("An error occurred", status=500) -# return HttpResponse("") - - -# htmx------------------ + +# with htmx------------------ @csrf_exempt def generate_prompt_view(request): if request.method == "POST": From c37b6ad4fd76577b499b60f753da986edfe10fa0 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Fri, 10 Jan 2025 22:30:15 +0000 Subject: [PATCH 10/17] output format improved --- django/chat/static/chat/js/chatInput.js | 83 +++++++------------ .../templates/chat/components/chat_input.html | 15 ++-- django/chat/views.py | 6 +- 3 files changed, 42 insertions(+), 62 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index ed86f795d..f6ba10bda 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -82,66 +82,39 @@ document.addEventListener('mouseup', function () { } }); -// + +//-------------js only // document.getElementById('magic-button').addEventListener('click', function () { // const userInput = document.getElementById('chat-prompt').value; // document.getElementById('magic-prompt').value = userInput; // }); -// document.getElementById('magic-form').addEventListener('submit', function (event) { -// event.preventDefault(); // prevent default form submission -// const formData = new FormData(this); -// fetch(this.action, { -// method: 'POST', -// headers: { -// 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, -// }, -// body: formData -// }) -// .then(response => response.text()) -// .then(html => { -// document.querySelector('#magicModal .modal-body').innerHTML = html; -// }); -// }); - -//-------------js only -document.getElementById('magic-button').addEventListener('click', function () { - const userInput = document.getElementById('chat-prompt').value; - document.getElementById('magic-prompt').value = userInput; -}); - -// document.getElementById('magic-form').addEventListener('submit', function (event) { -// event.preventDefault(); // prevent default form submission -// const userInput = document.getElementById('magic-prompt').value; -// const outputText = generatePrompt(userInput); -// document.getElementById('generated-prompt').value = outputText; -// }); -// function generatePrompt(input) { -// // Replace this with your actual prompt generation logic -// return `Generated prompt for: ${input}`; -// } -//-------------------- +document.getElementById('magic-form').addEventListener('submit', function (event) { + event.preventDefault(); // Prevent the default form submission -//--------------js with python -// document.getElementById('magic-form').addEventListener('submit', function (event) { -// event.preventDefault(); // prevent default form submission -// const userInput = document.getElementById('magic-prompt').value; -// const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; + const userInput = document.getElementById('magic-prompt').value; + const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; -// fetch('/chat/generate-prompt/', { -// method: 'POST', -// headers: { -// 'Content-Type': 'application/json', -// 'X-CSRFToken': csrfToken -// }, -// body: JSON.stringify({user_input: userInput}) -// }) -// .then(response => response.json()) -// .then(data => { -// document.getElementById('generated-prompt').value = data.output_text; -// }) -// .catch(error => { -// console.error('Error:', error); -// }); -// }); + fetch('/chat/generate-prompt/', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'X-CSRFToken': csrfToken + }, + body: new URLSearchParams({ + 'user_input': userInput + }) + }) + .then(response => response.json()) + .then(data => { + if (data.output_text) { + document.getElementById('generated-prompt').value = data.output_text; + } else { + console.error('Error:', data.error); + } + }) + .catch(error => { + console.error('Error:', error); + }); +}); diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index 43565b792..6180f382d 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -137,8 +137,8 @@ - - --> + + --> diff --git a/django/chat/views.py b/django/chat/views.py index 69ec4b2fd..cd9c74f1e 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -1019,7 +1019,11 @@ def generate_prompt_view(request): logging.info(f"Received user input: {user_input}") output_text = generate_prompt(user_input) logging.info(f"Generated prompt: {output_text}") - return JsonResponse({"output_text": output_text}) + # return JsonResponse({"output_text": output_text}) + # Return an HTML snippet to update the textarea + return HttpResponse( + f'' + ) except Exception as e: logging.error(f"Error in generate_prompt_view: {e}") return JsonResponse({"error": "An error occurred"}, status=500) From e90d81874799f46a01143cb0fca6c8297a9ac74c Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Mon, 13 Jan 2025 19:48:05 +0000 Subject: [PATCH 11/17] buttons restructured --- django/chat/static/chat/js/chatInput.js | 8 ++++ .../templates/chat/components/chat_input.html | 37 ++++++++++++------- .../chat/components/generated_prompt.html | 35 ------------------ django/chat/urls.py | 1 + django/chat/views.py | 4 ++ 5 files changed, 37 insertions(+), 48 deletions(-) delete mode 100644 django/chat/templates/chat/components/generated_prompt.html diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index f6ba10bda..a5eff3005 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -118,3 +118,11 @@ document.getElementById('magic-form').addEventListener('submit', function (event console.error('Error:', error); }); }); +function copyTextareaContent() { + const textarea = document.getElementById('generated-prompt'); + navigator.clipboard.writeText(textarea.value).then(() => { + alert('Copied the text: ' + textarea.value); + }).catch(err => { + console.error('Failed to copy text: ', err); + }); +} diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index 6180f382d..c59a1bbf5 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -99,7 +99,10 @@ type="button" aria-label='{% trans "Generate Prompt" %}' data-bs-toggle="modal" - data-bs-target="#magicModal"> + data-bs-target="#magicModal" + hx-get="/reset-form/" + hx-target="#magicModal .modal-content" + hx-swap="outerHTML"> + aria-label="Close" + onclick="location.reload();"> + + --> @@ -170,4 +180,5 @@ {% block page_script %} + {% endblock %} diff --git a/django/chat/templates/chat/components/generated_prompt.html b/django/chat/templates/chat/components/generated_prompt.html deleted file mode 100644 index efe3da2eb..000000000 --- a/django/chat/templates/chat/components/generated_prompt.html +++ /dev/null @@ -1,35 +0,0 @@ -{% load i18n %} -{% load static %} -{# #} - diff --git a/django/chat/urls.py b/django/chat/urls.py index f87c4e7fa..7ac6cdfba 100644 --- a/django/chat/urls.py +++ b/django/chat/urls.py @@ -110,6 +110,7 @@ views.set_preset_default, name="set_preset_default", ), + path("reset-form/", views.reset_form_view, name="reset_form_view"), # path("user-input/", views.user_input_view, name="user_input_view"), # path("generate-prompt/", views.generate_prompt, name="generate_prompt"), path("generate-prompt/", views.generate_prompt_view, name="generate_prompt_view"), diff --git a/django/chat/views.py b/django/chat/views.py index cd9c74f1e..fd53447cb 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -1010,6 +1010,10 @@ def generate_prompt(task_or_prompt: str): from django.views.decorators.csrf import csrf_exempt +def reset_form_view(request): + return render(request, "chat/components/chat_input.html") + + # with htmx------------------ @csrf_exempt def generate_prompt_view(request): From 7d34695429a9fe6e514cab58737edba4ae9e3564 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Mon, 13 Jan 2025 21:39:56 +0000 Subject: [PATCH 12/17] in-block prompt generated with ai, prompt truncated to after the reasoning tag --- django/chat/static/chat/js/chatInput.js | 42 ---------- .../templates/chat/components/chat_input.html | 77 +++++-------------- django/chat/views.py | 23 +++--- 3 files changed, 34 insertions(+), 108 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index a5eff3005..93d984f5e 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -83,46 +83,4 @@ document.addEventListener('mouseup', function () { }); -//-------------js only -// document.getElementById('magic-button').addEventListener('click', function () { -// const userInput = document.getElementById('chat-prompt').value; -// document.getElementById('magic-prompt').value = userInput; -// }); - -document.getElementById('magic-form').addEventListener('submit', function (event) { - event.preventDefault(); // Prevent the default form submission - - const userInput = document.getElementById('magic-prompt').value; - const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; - - fetch('/chat/generate-prompt/', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'X-CSRFToken': csrfToken - }, - body: new URLSearchParams({ - 'user_input': userInput - }) - }) - .then(response => response.json()) - .then(data => { - if (data.output_text) { - document.getElementById('generated-prompt').value = data.output_text; - } else { - console.error('Error:', data.error); - } - }) - .catch(error => { - console.error('Error:', error); - }); -}); -function copyTextareaContent() { - const textarea = document.getElementById('generated-prompt'); - navigator.clipboard.writeText(textarea.value).then(() => { - alert('Copied the text: ' + textarea.value); - }).catch(err => { - console.error('Failed to copy text: ', err); - }); -} diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index c59a1bbf5..f310887e5 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -94,15 +94,15 @@ aria-label='{% trans "Message" %}' placeholder='{% trans "Type your message here..." %}' required> - - - - - +--> {% block page_script %} diff --git a/django/chat/views.py b/django/chat/views.py index fd53447cb..94fe76db8 100644 --- a/django/chat/views.py +++ b/django/chat/views.py @@ -1,5 +1,6 @@ import json import logging +import re from django.conf import settings from django.contrib.auth import get_user_model @@ -970,17 +971,17 @@ def generate_prompt(task_or_prompt: str): [Optional sections with headings or bullet points for detailed steps.] - # Steps [optional] + # Steps - [optional: a detailed breakdown of the steps necessary to accomplish the task] + [ a detailed breakdown of the steps necessary to accomplish the task] # Output Format [Specifically call out how the output should be formatted, be it response length, structure e.g. JSON, markdown, etc] - # Examples [optional] + # Examples - [Optional: 1-3 well-defined examples with placeholders if necessary. Clearly mark where examples start and end, and what the input and output are. User placeholders as necessary.] + [ 1-3 well-defined examples with placeholders if necessary. Clearly mark where examples start and end, and what the input and output are. User placeholders as necessary.] [If the examples are shorter than what a realistic example is expected to be, make a reference with () explaining how real examples should be longer / shorter / different. AND USE PLACEHOLDERS! ] # Notes [optional] @@ -1019,16 +1020,18 @@ def reset_form_view(request): def generate_prompt_view(request): if request.method == "POST": try: - user_input = request.POST.get("user_input", "") + # user_input = request.POST.get("user_input", "") + user_input = request.POST.get("user-message", "") logging.info(f"Received user input: {user_input}") output_text = generate_prompt(user_input) logging.info(f"Generated prompt: {output_text}") - # return JsonResponse({"output_text": output_text}) - # Return an HTML snippet to update the textarea + output_text = re.sub( + r".*?", "", output_text, flags=re.DOTALL + ) return HttpResponse( - f'' + f'' ) except Exception as e: logging.error(f"Error in generate_prompt_view: {e}") - return JsonResponse({"error": "An error occurred"}, status=500) - return JsonResponse({"error": "Invalid request method"}, status=400) + return HttpResponse("An error occurred", status=500) + return HttpResponse("Invalid request method", status=400) From de56c0795a6322b7cb679e172c3102ed27722ee1 Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Mon, 13 Jan 2025 22:27:01 +0000 Subject: [PATCH 13/17] flaoating button icon --- .../templates/chat/components/chat_input.html | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index f310887e5..95aed2f26 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -96,13 +96,17 @@ required> + @@ -145,5 +150,27 @@ {% block page_script %} - + {% endblock %} From 5abb33100497b58204f8bfc1a402b683c76d08bd Mon Sep 17 00:00:00 2001 From: Rifahaziz Date: Tue, 14 Jan 2025 21:55:58 +0000 Subject: [PATCH 14/17] added a requirement to input text; costs and spinner wip --- django/chat/static/chat/js/chatInput.js | 1 + django/chat/static/chat/style.css | 10 ++- .../templates/chat/components/chat_input.html | 68 +++++-------------- django/chat/views.py | 5 +- 4 files changed, 29 insertions(+), 55 deletions(-) diff --git a/django/chat/static/chat/js/chatInput.js b/django/chat/static/chat/js/chatInput.js index 93d984f5e..09d55c8bf 100644 --- a/django/chat/static/chat/js/chatInput.js +++ b/django/chat/static/chat/js/chatInput.js @@ -84,3 +84,4 @@ document.addEventListener('mouseup', function () { + diff --git a/django/chat/static/chat/style.css b/django/chat/static/chat/style.css index c5969f68e..433e999ef 100644 --- a/django/chat/static/chat/style.css +++ b/django/chat/static/chat/style.css @@ -828,7 +828,7 @@ div#chat-toolbar { color: initial !important; } - &:focus>i { + &:focus > i { display: block !important; } } @@ -860,7 +860,7 @@ div#chat-toolbar { background-color: var(--bs-light); } - &:focus>i { + &:focus > i { display: block !important; } } @@ -1061,7 +1061,7 @@ ul.errorlist { word-break: break-word; } -#editLibrariesInner .modal-body>.row>div { +#editLibrariesInner .modal-body > .row > div { max-height: calc(100vh - 10rem); overflow-y: auto; } @@ -1272,3 +1272,7 @@ math[display="block"] { margin-top: 1rem; padding-bottom: 1rem; } + +.floating-icon i { + font-size: 24px; +} diff --git a/django/chat/templates/chat/components/chat_input.html b/django/chat/templates/chat/components/chat_input.html index 95aed2f26..ae5de8635 100644 --- a/django/chat/templates/chat/components/chat_input.html +++ b/django/chat/templates/chat/components/chat_input.html @@ -96,19 +96,20 @@ required> +