diff --git a/README.md b/README.md index 63d9237..4cf66c0 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,12 @@ cd bounswe2024group9 AWS_HOST=XXX JUDGE0_API_KEY=XXX DJANGO_SECRET_KEY=XXX -ALTERNATIVE_JUDGE0_API_KEY=XXX -REACT_APP_API_URL=XXX +JUDGE0_API_KEY_POOL=XXX +REACT_APP_API_URL=XXX +REACT_APP_FRONTEND_URL=XXX +EMAIL_HOST_USER=XXX +GEMINI_AI_KEY_POOL=XXX +
  • Run the following command to run Docker image
    docker compose up
  • diff --git a/django_project_491/django_app/migrations/0006_topic.py b/django_project_491/django_app/migrations/0006_topic.py deleted file mode 100644 index d012fb3..0000000 --- a/django_project_491/django_app/migrations/0006_topic.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 5.1.2 on 2024-11-23 20:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('django_app', '0005_comment_language'), - ] - - operations = [ - migrations.CreateModel( - name='Topic', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True)), - ('related_url', models.URLField()), - ], - ), - ] diff --git a/django_project_491/django_app/models.py b/django_project_491/django_app/models.py index ce89056..4895f67 100644 --- a/django_project_491/django_app/models.py +++ b/django_project_491/django_app/models.py @@ -276,25 +276,6 @@ def check_and_promote(self): return self.userType -class Topic(models.Model): - name = models.CharField(max_length=100, unique=True) - related_url = models.URLField() - - def __str__(self): - return self.name - - @staticmethod - def get_all_topics(): - return Topic.objects.all() - - @staticmethod - def get_url_for_topic(topic_name): - try: - topic = Topic.objects.get(name__iexact=topic_name) - return topic.related_url - except Topic.DoesNotExist: - return None - class Annotation(models.Model): _id = models.AutoField(primary_key=True) @@ -320,3 +301,23 @@ def __repr__(self): def __unicode__(self): return self.text + + +class Topic(models.Model): + name = models.CharField(max_length=100, unique=True) + related_url = models.URLField() + + def __str__(self): + return self.name + + @staticmethod + def get_all_topics(): + return Topic.objects.all() + + @staticmethod + def get_url_for_topic(topic_name): + try: + topic = Topic.objects.get(name__iexact=topic_name) + return topic.related_url + except Topic.DoesNotExist: + return None diff --git a/django_project_491/django_app/urls.py b/django_project_491/django_app/urls.py index 0358446..76749e8 100644 --- a/django_project_491/django_app/urls.py +++ b/django_project_491/django_app/urls.py @@ -81,4 +81,9 @@ path('questions//topic/', question_views.get_topic_url, name='get_topic_url'), path('topics/', question_views.list_all_topics, name='list_all_topics'), + path('create_annotation/', annotation_views.create_annotation, name='create_annotation'), + path('delete_annotation//', annotation_views.delete_annotation, name='delete_annotation'), + path('edit_annotation//', annotation_views.edit_annotation, name='edit_annotation'), + path('get_annotations_by_language_id//', annotation_views.get_annotations_by_language, name='get_annotations_by_language_id'), + path('annotations/all/', annotation_views.get_all_annotations, name='get_all_annotations'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/koduyorum-web/src/Annotation.css b/koduyorum-web/src/Annotation.css index 5ca821d..87d797b 100644 --- a/koduyorum-web/src/Annotation.css +++ b/koduyorum-web/src/Annotation.css @@ -1,9 +1,14 @@ .annotation { position: relative; cursor: pointer; - font-style: italic; - color: darkcyan; /* Example: Tomato color */ - } + font-style: italic; /* Italicize the text to differentiate it from the rest */ + background-color: cyan; /* Light yellow background for highlight effect */ + padding: 2px; /* Add padding for better appearance */ + border-radius: 2px; /* Slightly round the edges to mimic a marker stroke */ + display: inline-block; /* Keep it inline while allowing styling */ + color: black; /* Ensure the text is readable */ +} + .annotation-tooltip { position: absolute; @@ -11,10 +16,10 @@ left: 20%; background-color: rgba(0, 0, 0, 0.7); color: white; - padding: 5px; + padding: 10px; /* Comfortable padding */ border-radius: 3px; font-size: 12px; - max-width: 200px; + max-width: 300px; /* Limit width to prevent overflowing */ white-space: nowrap; z-index: 10; opacity: 0; diff --git a/koduyorum-web/src/CreateAnnotation.js b/koduyorum-web/src/CreateAnnotation.js index bbaaafd..c64b5b2 100644 --- a/koduyorum-web/src/CreateAnnotation.js +++ b/koduyorum-web/src/CreateAnnotation.js @@ -67,8 +67,15 @@ const CreateAnnotation = ({ visible, selectedText, startIndex, endIndex, languag placeholder="Enter your annotation..." />
    - - + +
    @@ -109,14 +116,28 @@ const CreateAnnotation = ({ visible, selectedText, startIndex, endIndex, languag justify-content: space-between; gap: 10px; } - .submit-button { - background: #4CAF50; + .save-button { + background: #007bff; /* Blue color for Save Changes */ color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; } + .save-button:hover { + background: #0056b3; /* Darker blue on hover */ + } + .create-button { + background: #28a745; /* Green color for Create */ + color: white; + padding: 10px 20px; + border: none; + border-radius: 4px; + cursor: pointer; + } + .create-button:hover { + background: #218838; /* Darker green on hover */ + } .cancel-button { background: #f44336; color: white; diff --git a/koduyorum-web/src/SearchResults.js b/koduyorum-web/src/SearchResults.js index dd5c58c..2d45774 100644 --- a/koduyorum-web/src/SearchResults.js +++ b/koduyorum-web/src/SearchResults.js @@ -181,16 +181,26 @@ const fetchSearchResults = async (query) => { }; const addAnnotations = (text, annotations) => { + console.log("Adding annotations to text:", text); + console.log("Annotations list:", annotations); + let annotatedText = []; let lastIndex = 0; + + // Sort annotations by starting point to avoid misplacement + const sortedAnnotations = annotations.sort( + (a, b) => a.annotation_starting_point - b.annotation_starting_point + ); - annotations.forEach((annotation) => { + sortedAnnotations.forEach((annotation) => { const { annotation_starting_point, annotation_ending_point, text: annotationText , annotation_id: annotationId} = annotation; - // Add text before the annotation + + console.log("Processing annotation:", annotation); + if (lastIndex < annotation_starting_point) { annotatedText.push(text.slice(lastIndex, annotation_starting_point)); } - + // Add annotated text with tooltip annotatedText.push( @@ -221,18 +231,26 @@ const fetchSearchResults = async (query) => { if (lastIndex < text.length) { annotatedText.push(text.slice(lastIndex)); } - + console.log("Final annotated text:", annotatedText); return annotatedText; }; const handleEditAnnotation = async (annotationId, startOffset, endOffset) => { - // Fetch annotation data by ID - setStartIndex(startOffset); - setEndIndex(endOffset); - setModalVisible(true); - setAnnotationId(annotationId); + // Fetch the annotation to get its text + const annotationToEdit = annotationData.find((annotation) => annotation.annotation_id === annotationId); + if (annotationToEdit) { + console.log("Editing annotation:", annotationToEdit); + setSelectedText(annotationToEdit.text); // Set selected text from the annotation + setStartIndex(startOffset); + setEndIndex(endOffset); + setModalVisible(true); + setAnnotationId(annotationId); + } else { + console.error("Annotation not found for editing."); + } }; + const handleDeleteAnnotation = async (annotationId) => { try { const userId = localStorage.getItem('user_id'); @@ -245,6 +263,10 @@ const fetchSearchResults = async (query) => { }); if (response.ok) { + // Update the state to remove the deleted annotation + setAnnotationData((prevAnnotations) => + prevAnnotations.filter((annotation) => annotation.annotation_id !== annotationId) + ); alert('Annotation deleted successfully.'); // Optional: Trigger a re-fetch of annotations or update state to reflect the deletion } else { @@ -270,6 +292,9 @@ const fetchSearchResults = async (query) => { const mouseX = e.clientX; const mouseY = e.clientY; + console.log("Text selected:", selection.toString()); + console.log("Selection start index:", startOffset, "end index:", endOffset); + setSelectedText(selection.toString()); setStartIndex(startOffset); setEndIndex(endOffset); @@ -279,7 +304,10 @@ const fetchSearchResults = async (query) => { console.log('No text selected.'); } }; + + + const renderAnnotatedText = (textData) => { const { text, annotation, start, end } = textData; @@ -318,11 +346,12 @@ const fetchSearchResults = async (query) => { searched={searched} handleSearchResultClick={handleSearchResultClick} /> - +
    - -
    + +
    +
    - {activeTab === 'info' ? (
    { onClose={() => setModalVisible(false)} />
    handleTextSelection(e)}> -

    {wiki_name}

    -

    {wiki_name}

    @@ -418,7 +444,6 @@ const fetchSearchResults = async (query) => { )}
    -
    ) : (