diff --git a/backend/app/migrations/0009_word_sentence.py b/backend/app/migrations/0009_word_sentence.py new file mode 100644 index 00000000..5c96b264 --- /dev/null +++ b/backend/app/migrations/0009_word_sentence.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.16 on 2024-11-05 12:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0008_translation_remove_word_categories_delete_category_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='word', + name='sentence', + field=models.CharField(default='Sentence not available', max_length=1000), + ), + ] diff --git a/backend/app/views_directory/create_post-activity-streams.py b/backend/app/views_directory/create_post-activity-streams.py new file mode 100644 index 00000000..b74a8466 --- /dev/null +++ b/backend/app/views_directory/create_post-activity-streams.py @@ -0,0 +1,38 @@ +from rest_framework import status +from rest_framework.decorators import api_view +from rest_framework.response import Response +from ..models import Post, Tags +from ..serializers import PostSerializer + +@api_view(['POST']) +def create_post(request): + post_data = request.data + + serializer = PostSerializer(data=post_data) + if serializer.is_valid(): + post = serializer.save() + + if 'tags' in post_data: + tags = post_data['tags'] + post.tags.add(*[Tags.objects.get_or_create(name=tag)[0] for tag in tags]) + + activity_stream = { + "@context": "https://www.w3.org/ns/activitystreams", + "type": "Create", + "actor": { + "type": "Person", + "name": post.author.username, + }, + "object": { + "type": "Note", + "id": post.id, + "name": post.title, + "content": post.description, + "tags": [{"type": "Hashtag", "name": tag} for tag in post.tags.values_list('name', flat=True)] + }, + "published": post.created_at.isoformat() + } + + return Response({'activity_stream': activity_stream}, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) diff --git a/backend/app/views_directory/like-unlike-views-with-activity-streams.py b/backend/app/views_directory/like-unlike-views-with-activity-streams.py new file mode 100644 index 00000000..252ec62d --- /dev/null +++ b/backend/app/views_directory/like-unlike-views-with-activity-streams.py @@ -0,0 +1,78 @@ +from django.shortcuts import get_object_or_404 +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework import status +from app.models import Post +import json +from datetime import datetime + +def log_activity(actor, verb, obj_type, obj_id, obj_content): + activity = { + "@context": "localhost", + "type": "Post Like/Unlike", + "actor": { + "type": "Person", + "id": actor.id, + "name": actor.username + }, + "verb": verb, + "object": { + "type": obj_type, + "id": obj_id, + "content": obj_content + }, + "published": datetime.utcnow().isoformat() + 'Z' + } + print(json.dumps(activity)) + +@api_view(['POST']) +@permission_classes([IsAuthenticated]) +def like_post(request): + post_id = request.data.get("post_id") + if not post_id: + return Response({"detail": "Post ID is required."}, status=status.HTTP_400_BAD_REQUEST) + + post = get_object_or_404(Post, id=post_id) + if request.user in post.liked_by.all(): + return Response({"detail": "You have already liked this post."}, status=status.HTTP_400_BAD_REQUEST) + + post.liked_by.add(request.user) + post.like_count = post.liked_by.count() + post.save() + + log_activity( + actor=request.user, + verb="like", + obj_type="Post", + obj_id=post.id, + obj_content=post.content + ) + + return Response({"detail": "Post liked successfully.", "like_count": post.like_count}, status=status.HTTP_200_OK) + +@api_view(['POST']) +@permission_classes([IsAuthenticated]) +def unlike_post(request): + post_id = request.data.get("post_id") + if not post_id: + return Response({"detail": "Post ID is required."}, status=status.HTTP_400_BAD_REQUEST) + + post = get_object_or_404(Post, id=post_id) + if request.user not in post.liked_by.all(): + return Response({"detail": "You have not liked this post yet."}, status=status.HTTP_400_BAD_REQUEST) + + post.liked_by.remove(request.user) + post.like_count = post.liked_by.count() + post.save() + + # Log the "unlike" activity + log_activity( + actor=request.user, + verb="unlike", + obj_type="Post", + obj_id=post.id, + obj_content=post.content + ) + + return Response({"detail": "Post unliked successfully.", "like_count": post.like_count}, status=status.HTTP_200_OK) diff --git a/backend/app/views_directory/profileviews.py b/backend/app/views_directory/profileviews.py index fb5c433c..b5b30c2a 100644 --- a/backend/app/views_directory/profileviews.py +++ b/backend/app/views_directory/profileviews.py @@ -26,4 +26,125 @@ def update_profile(request): if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +@api_view(['GET']) +def view_profile_mock(request): + mock_profile = { + "@context": "https://www.w3.org/ns/activitystreams", + "type": "Person", + "id": "https://example.com/profiles/oktay_ozel", + "name": "oktay_ozel", + "image": { + "type": "Image", + "url": "https://private-user-images.githubusercontent.com/24993956/309188090-69afd5bb-8258-4995-939c-4600b6ecce12.jpg" + }, + "followers": { + "type": "Collection", + "totalItems": 100 + }, + "following": { + "type": "Collection", + "totalItems": 50 + }, + "level": "B2", + "activity": [ + { + "type": "Create", + "id": "https://example.com/posts/2", + "actor": { + "type": "Person", + "name": "oktay_ozel", + "image": { + "type": "Image", + "url": "https://private-user-images.githubusercontent.com/57640531/310137517-cbe7aa9f-3457-4f64-b37b-c3e46d4e448b.png" + } + }, + "object": { + "type": "Note", + "name": "Petrichor: The Smell of Rain", + "content": "Petrichor is the pleasant, earthy smell that comes after rain. Example: 'She loved the petrichor that filled the air after the storm.'", + "tag": [ + { + "type": "Hashtag", + "name": "Vocabulary" + } + ], + "published": "2024-11-05T17:00:00Z", + "replies": { + "type": "Collection", + "totalItems": 3 + }, + "likes": { + "type": "Collection", + "totalItems": 90 + } + } + }, + { + "type": "Create", + "id": "https://example.com/posts/3", + "actor": { + "type": "Person", + "name": "oktay_ozel", + "image": { + "type": "Image", + "url": "https://private-user-images.githubusercontent.com/57640531/310137517-cbe7aa9f-3457-4f64-b37b-c3e46d4e448b.png" + } + }, + "object": { + "type": "Note", + "name": "Serendipity: A Fortunate Discovery", + "content": "Serendipity is the occurrence of events by chance in a happy or beneficial way. Example: 'They met by serendipity and became lifelong friends.'", + "tag": [ + { + "type": "Hashtag", + "name": "Vocabulary" + } + ], + "published": "2024-11-05T20:00:00Z", + "replies": { + "type": "Collection", + "totalItems": 5 + }, + "likes": { + "type": "Collection", + "totalItems": 75 + } + } + } + ], + "quizzes": [ + { + "type": "Quiz", + "id": "https://example.com/quizzes/1", + "name": "Basic Vocabulary Quiz", + "summary": "Test your knowledge on basic vocabulary words!", + "attributedTo": { + "type": "Person", + "name": "oktay_ozel" + }, + "audienceLevel": "Beginner", + "likes": { + "type": "Collection", + "totalItems": 5 + } + }, + { + "type": "Quiz", + "id": "https://example.com/quizzes/2", + "name": "Advanced Vocabulary Quiz", + "summary": "Challenge yourself with advanced vocabulary words.", + "attributedTo": { + "type": "Person", + "name": "oktay_ozel" + }, + "audienceLevel": "Advanced", + "likes": { + "type": "Collection", + "totalItems": 9 + } + } + ] +} + return Response(mock_profile, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/backend/data/db_files/relationships.csv b/backend/data/db_files/relationships.csv new file mode 100644 index 00000000..5bc5e1c9 --- /dev/null +++ b/backend/data/db_files/relationships.csv @@ -0,0 +1,105 @@ +word,related_word,relation_type +a,synset-A-noun-6,synonym +a,letter,broader +abandon,synset-abandon-verb-1,synonym +abandon,discard,broader +abandon,chuck,narrower +abandon,forfeit,narrower +abandon,dispense,narrower +abandon,consign,narrower +abandon,synset-wildness-noun-1,synonym +abandon,passion,broader +abandon,synset-abandon-verb-2,synonym +abandon,foreswear,narrower +abandon,synset-abandon-noun-1,synonym +abandon,unrestraint,broader +abandon,synset-abandon-verb-10,synonym +abandon,synset-abandon-verb-1,synonym +abandon,leave,broader +abandon,maroon,narrower +abandon,expose,narrower +abandon,ditch,narrower +abandon,walk,narrower +abandon,synset-vacate-verb-2,synonym +abandon,leave,broader +abandoned,synset-abandoned-adjectivesatellite-2,synonym +abandoned,synset-abandoned-adjectivesatellite-1,synonym +ability,c,broader +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,c,narrower +ability,sh85082114,narrower +ability,sh2005004875,narrower +ability,sh85142795,narrower +ability,sh85041103,narrower +ability,sh2008004738,narrower +ability,sh97008210,narrower +ability,sh85082750,narrower +ability,sh85075527,narrower +ability,sh85076844,narrower +ability,sh85075480,narrower +ability,sh85009146,narrower +ability,sh2008008130,narrower +ability,sh89002679,narrower +ability,sh2010000098,narrower +ability,sh85126514,narrower +ability,sh85046278,narrower +ability,sh85033833,narrower +ability,sh85088948,narrower +ability,sh85087575,narrower +ability,sh00002431,narrower +ability,sh85067157,narrower +ability,synset-ability-noun-3,synonym +ability,cognition,broader +ability,know-how,narrower +ability,hand,narrower +ability,skill,narrower +ability,intelligence,narrower +ability,creativity,narrower +ability,aptitude,narrower +ability,bilingualism,narrower +ability,leadership,narrower +ability,faculty,narrower +ability,superior,narrower +ability,capacity,narrower +ability,skill,narrower +ability,originality,narrower +ability,synset-ability-noun-1,synonym +ability,quality,broader +ability,totipotency,narrower +ability,Midas,narrower +ability,immunocompetence,narrower +ability,physical,narrower +ability,penetration,narrower +ability,magical,narrower +ability,interoperability,narrower +ability,form,narrower +ability,adaptability,narrower +ability,competence,narrower +ability,sensitivity,narrower +ability,capability,narrower +ability,contractility,narrower +able,synset-able-adjectivesatellite-5,synonym +able,synset-able-adjectivesatellite-1,synonym +able,synset-able-adjectivesatellite-3,synonym +able,synset-able-adjective-1,synonym +abnormal,synset-abnormal-adjective-2,synonym +abnormal,synset-abnormal-adjectivesatellite-3,synonym +abnormal,synset-abnormal-adjective-2,synonym +abnormally,synset-abnormally-adverb-1,synonym +aboard,synset-aboard-adverb-1,synonym +aboard,synset-aboard-adverb-4,synonym +aboard,synset-aboard-adverb-1,synonym +aboard,synset-aboard-adverb-1,synonym +abolish,synset-abolish-verb-3,synonym +abolish,cashier,narrower +abolish,abrogate,narrower diff --git a/backend/data/db_files/translations.csv b/backend/data/db_files/translations.csv new file mode 100644 index 00000000..5ea0ada5 --- /dev/null +++ b/backend/data/db_files/translations.csv @@ -0,0 +1,8 @@ +word,turkish_translation +a,a +a,bir +abandon,terk etmek +abandon,bırakmak +abandon,kovmak +abandoned,terk edilmiş +abnormal,anormal diff --git a/backend/data/db_files/words.csv b/backend/data/db_files/words.csv new file mode 100644 index 00000000..4418534e --- /dev/null +++ b/backend/data/db_files/words.csv @@ -0,0 +1,26 @@ +word,explanation,sentence,level,part_of_speech +a,the 1st letter of the Roman alphabet,,A1,determiner +abandon,"forsake, leave behind;",We abandoned the old car in the empty parking lot,B1,verb +abandon,a feeling of extreme emotional intensity;,the wildness of his anger,B1,verb +abandon,give up with the intent of never claiming again;,"Abandon your life to God""; ""She gave up her children to her ex-husband when she moved to Tahiti""; ""We gave the drowning victim up for dead",B1,verb +abandon,the trait of lacking restraint or control; reckless freedom from inhibition or worry;,she danced with abandon,B1,verb +abandon,stop maintaining or insisting on; of ideas or claims;,"He abandoned the thought of asking for her hand in marriage""; ""Both sides have to give up some claims in these negotiations",B1,verb +abandon,leave someone who needs or counts on you; leave in the lurch;,The mother deserted her children,B1,verb +abandon,leave behind empty; move out of;,You must vacate your office by tonight,B1,verb +abandoned,free from constraint;,"an abandoned sadness born of grief""- Liam O'Flaherty",B2,adjective +abandoned,forsaken by owner or inhabitants ;,weed-grown yard of an abandoned farmhouse,B2,adjective +ability,possession of the qualities (especially mental qualities) required to do something or get something done;,danger heightened his powers of discrimination,A2,noun +ability,the quality of being able to perform; a quality that permits or facilitates achievement or accomplishment,,A2,noun +able,have the skills and qualifications to do things well;,"able teachers""; ""a capable administrator""; ""children as young as 14 can be extremely capable and dependable",B1,adjective +able,having a strong healthy body;,"an able seaman""; ""every able-bodied young man served in the army",B1,adjective +able,having inherent physical or mental ability or capacity;,"able to learn""; ""human beings are able to walk on two feet""; ""Superman is able to leap tall buildings",B1,adjective +able,(usually followed by `to') having the necessary means or skill or know-how or authority to do something;,"able to swim""; ""she was able to program her computer""; ""we were at last able to buy a car""; ""able to get a grant for the project",B1,adjective +abnormal,not normal; not typical or usual or regular or conforming to a norm;,"abnormal powers of concentration""; ""abnormal amounts of rain""; ""abnormal circumstances""; ""an abnormal interest in food",B1,adjective +abnormal,much greater than the normal;,"abnormal profits""; ""abnormal ambition",B1,adjective +abnormal,departing from the normal in e.g. intelligence and development;,"they were heartbroken when they learned their child was abnormal""; ""an abnormal personality",B1,adjective +abnormally,in an abnormal manner;,"they were behaving abnormally""; ""his blood pressure was abnormally low",B2,adverb +aboard,side by side;,anchored close aboard another ship,B1,adverb +aboard,part of a group;,Bill's been aboard for three years now,B1,adverb +aboard,on first or second or third base;,Their second homer with Bob Allison aboard,B1,adverb +aboard,"on a ship, train, plane or other vehicle",,B1,adverb +abolish,do away with;,Slavery was abolished in the mid-19th century in America and in Russia,B2,verb diff --git a/docker-compose.yml b/docker-compose.yml index 5b02a63f..8f769b52 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,9 @@ services: container_name: postgres_db restart: always environment: - POSTGRES_DB: ${DB_NAME} - POSTGRES_USER: ${DB_USER} - POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: db + POSTGRES_USER: halil + POSTGRES_PASSWORD: 123 volumes: - ./dbdata:/var/lib/postgresql/data ports: diff --git a/frontend/src/components/common/navbar.tsx b/frontend/src/components/common/navbar.tsx index 2bd696cc..d3ced483 100644 --- a/frontend/src/components/common/navbar.tsx +++ b/frontend/src/components/common/navbar.tsx @@ -1,5 +1,16 @@ -import { Popover, PopoverTrigger, PopoverContent, Avatar, Card, Input, Button, Divider } from "@nextui-org/react"; +import { + Popover, + PopoverTrigger, + PopoverContent, + Avatar, + Card, + Input, + Button, + Divider, + Badge, +} from "@nextui-org/react"; import { useNavigate, useLocation } from "react-router-dom"; +import { IconBell } from "@tabler/icons-react"; export default function Navbar() { const navigate = useNavigate(); @@ -60,7 +71,18 @@ export default function Navbar() { -
{content}
+{timePassed}
+