Our project, a domain-specific semantic information browser for "Architecture," serves as both an educational resource and a social media platform specifically tailored for enthusiasts of notable architectural works, renowned architects, and architectural styles. Utilizing the WikiData API, the platform ensures access to high-quality and extensive information on all aspects of architecture. Additionally, users can engage with each other through social media functionalities such as posting blogs, commenting, liking, and bookmarking content, enriching the community experience.
Frontend Development: We have successfully bootstrapped our frontend using Vite, integrating react-router for efficient routing and shadcn/ui for responsive UI components. Key features implemented include:
Backend and Infrastructure:
docker-compose up
.This comprehensive update highlights our commitment to developing a robust platform that not only provides valuable architectural information but also supports a vibrant community of architecture enthusiasts. The next steps involve refining these features and expanding our service offerings to include more interactive and user-driven functionalities.
https://github.com/bounswe/bounswe2024group6/wiki/Documented-API
Prerequisites: Docker
Clone the repository to your local environment:
git clone https://github.com/bounswe/bounswe2024group6.git
cd bounswe2024group6
Set the env variables as shown in ./.env.example in ./.env.
Sign up to Mapbox and create a Mapbox Access Token, create a .env file under frontend folder and set VITE_MAPBOX_ACCESS_TOKEN.
Update allowed hosts in ./backend\django-rest-auth\server\settings.py. Add the IPs that can send request to your API. For your local environment, add local host.
Set the base url in frontend\src\lib\baseUrl.ts (ie. local host).
After that, run the docker commands below at bounswe2024group6 folder to start the application:
docker compose build
docker compose up
The front-end server will be avaliable at port 5173 and the back-end server will be avaliable at port 8000.
NOTE: Local permissions may interfere with the installation of node packages, current frontend Dockerfile works well on our computers, but we used this version in digitalocean:
FROM node:20-alpine
WORKDIR /app
CMD npm install && npm run dev -- --host
Diagram | Link |
---|---|
Class Diagrams | link |
Sequential Diagrams | link |
Use Case Diagrams | link |
These initiatives have not only streamlined our development process but also minimized errors and improved our team’s ability to collaborate effectively under varying conditions. The iterative discussions and continual feedback within the team have been vital in refining these practices, significantly boosting our project’s productivity and morale.
The backend of our project leverages Django due to its comprehensive feature set that supports rapid development and clean, pragmatic design. We've containerized our application with Docker to ensure consistent environments across development and deployment stages, facilitating smoother operations and scalability on platforms like DigitalOcean.
Here is how we handle user login, showcasing the use of Django Rest Framework for building secure, scalable API endpoints:
@api_view(['POST'])
def login(request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(request, username=username, password=password)
if user:
token, _ = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_id': user.pk,
'username': user.username,
'profile_image': user.profile_image.url if user.profile_image else None
}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Invalid Credentials'}, status=status.HTTP_401_UNAUTHORIZED)
Our frontend is developed using React, showcasing a modern single-page application approach. We leverage several libraries to enhance the functionality and user experience:
SearchItem
component.useState
, useEffect
, and useContext
, which helped in managing local and global states effectively.Here is a snippet from our Architect
component, showcasing the use of hooks and API integration to fetch and display data:
import { useEffect, useState } from 'react';
import axios from 'axios';
import { useParams } from 'react-router-dom';
import BASE_URL from '../lib/baseUrl';
function Architect() {
let { qid } = useParams();
const [architectData, setArchitectData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
axios.post(`${BASE_URL}:8000/architect/`, { entity_id: qid })
.then(response => {
setArchitectData(response.data);
setIsLoading(false);
})
.catch(error => {
console.log(error);
setIsLoading(false);
});
}, [qid]);
return isLoading ? <ClipLoader /> : <DisplayArchitect data={architectData} />;
}
Our project leverages Docker to ensure consistent environments across development, testing, and production. Docker containers wrap our application and its dependencies into a complete filesystem, guaranteeing that the application will work seamlessly in any environment.
We utilize Docker Compose to define and run multi-container Docker applications. Here’s a breakdown of our configuration:
Database Service (db
):
mysql:8.0
image for our relational database needs.Backend Service (backend
):
./new_backend/project
./app
directory inside the container, facilitating live updates by linking the local development environment to the container environment.db
service to be healthy before starting.Frontend Service (frontend
):
./frontend
directory./app
in the container and uses an anonymous volume for node_modules
to avoid overwriting the installed node modules with local ones.Our CI/CD pipeline (not detailed here) could be set up using GitHub Actions or Jenkins to automate testing and deployment, ensuring that every commit is tested, and the main branch is always deployable.
depends_on
and health checks to ensure services start in the correct order..env
files to prevent hard-coding credentials in the source code.Here's a snippet from our Dockerfile for the backend service, showcasing the setup steps:
FROM python:3.12.3
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
CMD python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000
Our mobile application is developed using React Native, providing a seamless and unified user experience across both iOS and Android platforms. The project leverages expo-router
for navigation, ensuring smooth transitions and consistent behavior across different screens.
ClipLoader
) to enhance user experience.Here's a snippet from our Landing
component, illustrating how we handle navigation and user interaction:
import { SafeAreaView, TextInput, TouchableOpacity, Text } from 'react-native';
import { useNavigation } from 'expo-router';
const Landing = () => {
const navigation = useNavigation();
const [searchText, setSearchText] = useState('');
const search = (text) => {
navigation.replace("/landingImage", { params: { query: text } });
};
return (
<SafeAreaView>
<TextInput
value={searchText}
onChangeText={setSearchText}
placeholder="Search..."
/>
<TouchableOpacity onPress={() => search(searchText)}>
<Text>Search</Text>
</TouchableOpacity>
</SafeAreaView>
);
};
In this scenario, we demonstrate the flexibility of our system that allows both guests and logged-in users to search for architects, buildings, or styles.
Users can perform searches without needing to sign up or log in, ensuring accessibility and ease of use.
After initiating a search, for example for the architect "Gaudi", the system displays relevant information. Below are the search results showing Gaudi's profile, his notable works, and the architectural styles he influenced:
Selecting an architect takes users to a detailed profile page where they can explore the architect’s major works, the styles followed, and view the locations of these buildings on a map.
In our second scenario, a logged-in user starts on the feed page, which showcases the latest posts in the system.
From here, the user can use the search bar to look up an architect, building, or style. Here, we search for "hagia", revealing three buildings with "hagia" in their names.
Upon selecting "Hagia Sophia", the system presents detailed information about the building just as in the first scenario. However, since the user is logged in, additional functionalities become available.
The user can create a post about Hagia Sophia, contributing to the community-driven content on the platform.
Once the post is published, it appears on the feed page, making it visible to other users.
This scenario illustrates the interactive and social aspects of our platform, highlighting how users can actively participate and share insights about their architectural interests.
There are multiple images from db that have same ID
Uniquenes
There are missing tests and need to rearrange already written tests
Link
Got the review some PR's that have conflicts
Link
Building, architect and style wiki endpoints
Link
Sync API calls and items with no image and uniqueness
Link
Tests for user profile
Link
Link
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Efforts:-Eymen-Çeliktürk
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-13
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-14
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-15
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-16
Links to my Unit test issues can be found here:
https://github.com/bounswe/bounswe2024group6/issues/234
https://github.com/bounswe/bounswe2024group6/issues/229
One of my test example:
class BuildingViewTest(APITestCase):
def setUp(self):
self.client = APIClient()
self.url = reverse('building_view') # Adjust according to your URL pattern name
self.entity_id = "building_123"
self.mock_response = {"name": "Test Building", "description": "A test building."}
self.search_result = SearchResult.objects.create(
entity_id=self.entity_id,
name="Test Building",
image="http://example.com/building.jpg",
type="building"
)
@patch('your_app.views.get_building_info', return_value={"name": "Test Building", "description": "A test building."})
def test_building_view_get(self, mock_get_building_info):
response = self.client.get(self.url, {'entity_id': self.entity_id}, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), self.mock_response)
mock_get_building_info.assert_called_once_with(self.entity_id)
@patch('app.views.get_building_info', return_value={"name": "Test Building"})
def test_building_view_no_entity_id(self, mock_get_building_info):
response = self.client.get(self.url, {}, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
mock_get_building_info.assert_not_called()
class ArchitectViewTest(APITestCase):
def setUp(self):
self.client = APIClient()
self.url = reverse('architect_view') # Adjust according to your URL pattern name
self.entity_id = "architect_123"
self.mock_response = {"name": "Test Architect", "description": "A test architect."}
self.search_result = SearchResult.objects.create(
entity_id=self.entity_id,
name="Test Architect",
image="http://example.com/architect.jpg",
type="architect"
)
@patch('your_app.views.get_architect_info', return_value={"name": "Test Architect", "description": "A test architect."})
def test_architect_view_get(self, mock_get_architect_info):
response = self.client.get(self.url, {'entity_id': self.entity_id}, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), self.mock_response)
mock_get_architect_info.assert_called_once_with(self.entity_id)
@patch('app.views.get_architect_info', return_value={"name": "Test Architect", "description": "A test architect."})
def test_architect_view_no_entity_id(self, mock_get_architect_info):
response = self.client.get(self.url, {}, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
mock_get_architect_info.assert_not_called()
We have reorganized the application's structure from Milestone 2 to adhere more closely to Django app development conventions. This restructuring aims to improve the development process by making it more organized and easier to manage. By following these best practices, we ensure that our project is not only more maintainable but also aligns with the standard Django framework, which facilitates better collaboration and scalability in the long run.
One of the challenging aspects for me was the short time between milestones, which made it difficult to keep up with the pace of development. Additionally, the lack of clear division of tasks within the group further complicated the situation. This ambiguity in task allocation often led to confusion and inefficiencies, making it harder to stay on track and meet our project goals in a timely manner.
I tested the website for many different search and increased its reliability. I added so many if checks to code to handle null returns.
link
I designed the wiki pages completely with real data. Spent some time on the ui for a better experience.
link
I created the post ui too according to the mock ups.
link
Somehow there was a confusion and we couldn't merge this one with main branch. But I added some important functionalities and fixed some errors in this branch. I fixed the post image_url not found error, I added post creation features to missing pages and I created error-success messages for post creation.
https://github.com/bounswe/bounswe2024group6/compare/post-responses
I created the wiki result pages (Building, Architect, Style) and formed mock data for backend.
https://github.com/bounswe/bounswe2024group6/pull/160/
I finished wiki result pages' designs in here with real data. I put many if statements to handle null data returns so that it would have a nicer UI.
https://github.com/bounswe/bounswe2024group6/pull/191
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Effort:-Elif-Nur-Deniz
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-‐-Frontend-%234
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-13
I was in the frontend team…
I was very knowledgeable about the requirements from the start of the project and answered team's questions, made design decisions when necessary. I created mock Jsons and created the basis of the wiki results pages by investigating wikidata. I used the application a lot to test the features. When I encountered them, I reported to backend team and updated my designs based on the new code. I first debugged the error myself, then reported them with the details of the error. I once reported a missing endpoint. I was always active in deployment periods. I was always active in meetings and planning.
I didn't know much about frontend development at the beginning. So, I had learn it while developing the project. Luckily, my frontend teammate was experienced about it and helped me when I needed. It was harder for me to get my tasks done in the 1st milestone. But since then, I improved myself a lot and I overcame some hard tasks. I made the same mistake at least 3 times when working with real data. Since data call take time, sometimes when page is loaded data was not present. I put an if else statements to overcome that. So that the application would not try to access the data which is unpresent and would cause errors.
Implemented the endpoints of style, building and architect pages #154
Sped up the building wiki endpoint response time #174
Sped up the searching functionality by migrating search results into our database #247
Implemented the endpoints of style building and architect pages merged to main #167
Sped up and broadened the building query #175
Migrated the search results into database for permanent storage #181
Personel Efforts and Wiki
Meeting 12
Here's a pull request that contains a bulked amount of API functions for building, style and architect pages: #175
Another PR that I made that made search functionalities a lot faster by storing them in our database and making search queries directly in the server: #181
I have written extensive SPARQL queries for WikiData and abided by a huge amount of complex mock data given by the frontend team, you can take a look at utils.py on the backend for examples.
Here's an examplary view I've written:
@api_view(['POST'])
def search(request):
if request.method == "POST" and "query" in request.data:
keyword = request.data['query']
results = SearchResult.objects.filter(
Q(name__icontains=keyword)
)
architect_response = []
style_response = []
building_response = []
for result in results:
if result.type == 'architect':
architect_response.append({"name": result.name, "image": result.image, "entity_id": result.entity_id})
elif result.type == 'style':
style_response.append({"name": result.name, "image": result.image, "entity_id": result.entity_id})
elif result.type == 'building':
building_response.append({"name": result.name, "image": result.image, "entity_id": result.entity_id})
response = {"style": style_response, "architect":architect_response, "building":building_response}
return JsonResponse(response)
return Response("there was an error with the query.",status=status.HTTP_204_NO_CONTENT)
I also tried to improve the search functionality response time by other means: speeding up the search query. Instead of making three separate queries for each type of entity in our domain, it made sense to make just one query and get their type. I managed to improve the response time from around 1 minute to 20-30 seconds, but this just was not enough for a user-friendly experience - so we scrapped it and went for directly storing search results in our database.
As someone who hasn't done backend development before, considering all the edge cases that should be handled was difficult. You can find many PRs opened by me that fixes such unhandled edge cases, because the frontend team found them on-the-go. This was also a bit nerve-wracking as the responsibilities of the search functionality and retrieving information about building/style/architect pages were entirely on me and it felt as if people counted on me on these major features and I was letting them down. But in the end, I believe I have learnt a lot about both technical details of backend development and managing the social balance of a team that stares at a very near deadline.
Implemented Search Logic with the help of Aras
Search Logic
Implemented Parameter Passing across different pages.
In-App Navigation
Since I am the only mobile application developer of the project, I have a single branch called mobile, and therefore I have a single PR.
Link
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-%26-Effort%3A-Anıl-Köse
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-13
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-14
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-15
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-16
The component below is a list item for the list of style objects.
const renderStyleItem = ({ item }) => {
const itemLink = item['image'];
console.log(' STYLE itemLink ');
console.log(itemLink);
return (
<TouchableOpacity onPress={() => router.push(`wikiPages/styleWiki?viewData=${item.entity_id}`)}>
<View style={styles.item}>
<Text style={styles.itemText}>{item['name']}</Text>
<Image
source={{ uri: itemLink }}
style={styles.image}
/>
</View>
</TouchableOpacity>
);
};
General Overview of a Page/ Screen in the app.
<View style={styles.container}>
{!response && <Text style={{ color: 'white' }}>Loading...</Text>}
{response &&
response.architect &&
response.architect.length > 0 && (
<>
<Text style={styles.header}>Architect</Text>
<FlatList
data={response.architect}
renderItem={renderArchitectItem}
keyExtractor={(item) => item['entity_id']}
/>
</>
)}
{response && response.style && response.style.length > 0 && (
<>
<Text style={styles.header}>Style</Text>
<FlatList
data={response.style}
renderItem={renderStyleItem}
keyExtractor={(item) => item['entity_id']}
/>
</>
)}
{response && response.building && response.building.length > 0 && (
<>
<Text style={styles.header}>Building</Text>
<FlatList
data={response.building}
renderItem={renderBuildingItem}
keyExtractor={(item) => item['entity_id']}
/>
</>
)}
</View>
To add some styling to the components, we use StyleSheet.
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: 'black',
},
header: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
marginBottom: 10,
},
item: {
marginBottom: 10,
borderBottomWidth: 1,
borderBottomColor: 'white',
paddingBottom: 10,
},
itemText: {
fontSize: 18,
color: 'white',
},
image: {
width: 300,
height: 200,
marginTop: 10,
},
errorText: {
fontSize: 18,
color: 'red',
textAlign: 'center',
marginTop: 50,
},
});
An example function to interact with the backend server.
export const searchQuery = (query: string): Promise<any> => {
return new Promise((resolve, reject) => {
axios.post(`${BASE_URL}search/`, { query: query })
.then(response => {
resolve(response.data);
})
.catch(error => {
console.error(error);
reject(error);
});
});
};
In addition to the tasks mentioned above, I took on the responsibility of reorganizing the project file structure during Milestone 2 to better adhere to app development conventions.
Furthermore, I conducted extensive research on generating APK outputs for our React Native application. This involved understanding the various steps and tools required to build and package our mobile application for Android devices. I ensured that our team can reliably produce APKs for different stages of development and release.
Implemented Database Models with Kaan
Database Models
New Backend creation and migration from old one
Link
Like, Comment, Bookmark Functionalities Issues(209, 210, 211,212)
Link
Sync API calls and items with no image
Link
Created tests for several backend functionalities and refactor all
Link
Fetching results faster
Link
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Effort-:-Oktay-Özel
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-13
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-14
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-15
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-16
I did a crosscheck on the works of Aras with WikiData API's.
Links to my Unit test issues can be found here:
https://github.com/bounswe/bounswe2024group6/issues/217
https://github.com/bounswe/bounswe2024group6/issues/218
https://github.com/bounswe/bounswe2024group6/issues/219Here I am adding one of my unit tests as a sample.
class UserTestCase(TestCase):
def setUp(self):
self.client = Client()
self.user_data = {
'username': 'test_user',
'password': 'test_password'
}
self.user = CustomUser.objects.create_user(**self.user_data)
def test_login(self):
url = reverse('user_login')
response = self.client.post(url, self.user_data)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'token')
def test_invalid_login(self):
url = reverse('user_login')
invalid_data = {
'username': 'invalid_user',
'password': 'invalid_password'
}
response = self.client.post(url, invalid_data)
self.assertEqual(response.status_code, 401)
Reorganizing the erroneous structure that we have contemplated for the 2nd milestone. That way wasn't providing us a space to add our further developments than the login and signup functionalities. Taking an active role during the whole implementation time with frontend and mobile team to answer their questions and implement their requests during their implementation. Spent last 3 days before deadline totally being active.
Also I have done the initial configuration of backend and pushed the first running version of the project this includes all framework adjustments, database connections and requirements files etc. I have been active in deployment and presentation.
I had to learn the backend development properly from scratch also without guidance and someone knowing the proper usage of backend features it was like searching something in a dark room. However, thanks to Yunus Emre, Elif, Kaan and Aras we overcame challenges at the end. Also time constraint was a bit harsh from our side since we had to realize the project under 3 days almost. I can definitely say working in a group was also very challenging. Up until this project I have neverworked with more than 3 people in a project however this time I have seen how hard it is to come to a decision and apply it to project in a crowded group.
Implemented user profile endpoint
Issue
Implementing like test with kaan yolcu
Issue
Implementing feed endpoints
Issue
Adding user profile
PR Link
Adding like test with kaan yolcu
PR Link
Adding feed view
PR Link
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Effort:-Halil-Özkan
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-14
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-15
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-16
This test checks whether we can like a post properly or not.
def test_like_post(self):
url = reverse('like_post')
data = {'post_id': self.post.id}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertTrue(Like.objects.filter(user=self.user, post=self.post).exists())
self.post.refresh_from_db()
self.assertEqual(self.post.likes_count, 1)
This test checks whether we can like a post without post id or not .
def test_like_post_without_post_id(self):
url = reverse('like_post')
response = self.client.post(url, {}, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
I helped some on the dockerization part to Yunus Emre Özdemir, we were taking some errors at working on local and we solved it. I get involved the decision of what framework we should use.
Generally, I had challenges to get involved at first because I haven't made a software internship, I generally took place on research and development parts of companies. So, lack of experience in software development was hard for me. Working with lots of people and opening new branches and pulling the main code was the biggest challange to me.
Implemented Database Models with Oktay
Database Models
Implementing All Following Functionality related endpoints and tests
Follow Endpoints
Implementing All Commenting Functionality related endpoints and tests
Comment Endpoints]
Reorganizing all backend Structure
Link
Resolving Tag SearchResult in models.py combining the models and made neccessary changes in the whole project.
Link
Creating neccessary endpoints and serializers for following functionality.
Link
Creating neccessary endpoints and serializers for commenting functionality.
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Effort:-Kaan-Yolcu
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-14
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-15
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-16
This endpoint gets a username in body from authorized user and saves the following information in the database.
@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def follow_user(request):
username = request.data.get('username')
if not username:
return Response({'error': 'Username is missing in the request body.'}, status=status.HTTP_400_BAD_REQUEST)
try:
user_to_follow = CustomUser.objects.get(username=username)
user = request.user
if user == user_to_follow:
return Response({'error': 'You cannot follow yourself.'}, status=status.HTTP_400_BAD_REQUEST)
follow, created = Follow.objects.get_or_create(follower=user, followed=user_to_follow)
if created:
return Response({'message': f'You are now following {username}.'}, status=status.HTTP_201_CREATED)
else:
return Response({'message': f'You are already following {username}.'}, status=status.HTTP_200_OK)
except CustomUser.DoesNotExist:
return Response({'error': 'User does not exist.'}, status=status.HTTP_404_NOT_FOUND)
This endpoint below gets title text image_url and entity_id of wiki object and creates a post entity in database it returns response code 200 if sucessfull 500 if not.
@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_post(request):
user = request.user
title = request.data.get('title')
text = request.data.get('text')
image_url = request.data.get('image_url')
entity_id = request.data.get('entity_id')
if not title or not text:
return Response({'error': 'Title and text are required fields.'}, status=status.HTTP_400_BAD_REQUEST)
try:
image = None
if image_url:
image, created = Image.objects.get_or_create(image_url=image_url)
searchresult, created = SearchResult.objects.get_or_create(entity_id=entity_id)
post = Post.objects.create(
title=title,
text=text,
author=user,
image=image,
searchresult=searchresult
)
return Response({'message': 'Post created successfully'}, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
This endpoint is for commenting in the header we must provide a token , and in the body post_id abd comment_text that saves the post into database
@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def comment_post(request):
user = request.user
post_id = request.data.get('post_id')
comment_text = request.data.get('comment_text')
if not post_id or not comment_text:
return Response({'error': 'Post ID and comment text are required.'}, status=status.HTTP_400_BAD_REQUEST)
try:
post = Post.objects.get(pk=post_id)
except Post.DoesNotExist:
return Response({'error': 'Post does not exist.'}, status=status.HTTP_404_NOT_FOUND)
# Create a new comment
PostComments.objects.create(user=user, post=post, comment_text=comment_text)
return Response({'message': 'Comment added successfully.'}, status=status.HTTP_201_CREATED)
Here this test checks the functionality of whether two user can follow each other properly and the changes can be seen in the database
def test_follow_user(self):
url = reverse('follow_user')
data = {'username': 'user2'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertTrue(Follow.objects.filter(follower=self.user1, followed=self.user2).exists())
This test checks whether we can delete a comment properly or not.
def test_delete_comment(self):
comment = PostComments.objects.create(user=self.user, post=self.post, comment_text='This is a test comment.')
url = reverse('delete_comment')
data = {'comment_id': comment.id}
response = self.client.delete(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(PostComments.objects.filter(id=comment.id).exists())
We reorganized the app project file structure in the Project from Milestone 2 in order to obey the conventions for django app development and make the development more easily.
I had to change some models and unify them just in the middle on the work there were two models like Tag and SearchResults unifying them modifying the endpoints according to it and informing web and mobile teams was little bit challenning. Other than that communication the with the web and mobile team
guiding them the usage of the endpoints was the other challenge.
Dear friends, we want you to add honor code statements to your milestone reports. You can add them at the end of the report.
Please use the template below. Each member should add it to the report themselves, so the same text with the names changed will be reoccurring at the end.
Implement Dynamic Routing for Wiki Pages and Connection with Browser
Link
Implement Profile Page: UI, Dynamic Routing, Display/Edit Profile, Follow/Unfollow
Link
Implement Post Creation
Link
This PR adds dynamic routing for profile page, profile and logout navigation, basic profile ui and two new actions to useAuth hook, getToken to send tokens to authenticated routes and getUsername.
Link
This PR adds post creation, feed display functionalities and fixes entity id uniqueness problem at frontend.
Link
This PR adds edit profile and follow/unfollow user functionalities.
Link
https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone‐3
https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Effort:-Yunus-Emre-Özdemir
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-‐-Frontend-%234
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-14
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-15
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-16
I have implemented three APIs: basic_user_info, entity_from_searchresult and auth_user_profile.
PR including basic_user_info and entity_from_searchresult:
Link
PR including auth_user_profile:
Link
Example code snippet:
@api_view(['POST'])
def entity_from_searchresult(request):
id = request.data.get('id')
search_result = get_object_or_404(SearchResult, id=id)
entity_id = search_result.entity_id
name = search_result.name
category = search_result.type
return Response({'entity_id': entity_id, 'name': name, 'category': category}, status=200)
I have written unit tests for the APIs I implemented, unfortunately these couldn't make it to the release.
Example code snippet:
class EntityFromSearchResultTest(APITestCase):
def setUp(self):
self.url = reverse('entity_from_searchresult')
self.search_result = SearchResult.objects.create(
id=1, entity_id=101, name='Test Entity', type='ExampleType'
)
def test_entity_from_searchresult_success(self):
response = self.client.post(self.url, {'id': self.search_result.id})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {
'entity_id': self.search_result.entity_id,
'name': self.search_result.name,
'category': self.search_result.type
})
def test_entity_from_searchresult_nonexistent_id(self):
response = self.client.post(self.url, {'id': 9999})
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_entity_from_searchresult_no_id_provided(self):
response = self.client.post(self.url, {})
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
I did research, decided on and set up react-mapbox-gl and implemented the initial map component. After the migration to the new backend, I resolved CORS errors, set up MySQL connection and rewritten backend Dockerfiles and requirements. I also created a post page with dynamic routing for users to be able to share posts. I was in charge of devops, that is Docker files, requirements and digitalocean deployment. I was in close communication with every team member throughout the process and helped refactor and fix backend routes according to the application requirements.
I needed to fix some errors that came up after we migrate to the new backend, we also encountered and fixed many issues on the Docker front. Other than these, the main challenge was to connect the frontend with the backend. Although the UI and the routes were ready and tested in principle, we encountered many issues while connecting them. A major one was uniqueness problem, which were related to duplicate results from SPARQL browsing, which crashed many routes. Fortunately we were able to fix it with close coordination with the backend team.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Elif Nur Deniz, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Eymen Esad Çeliktürk, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Anıl Köse, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Yunus Emre Özdemir, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Oktay Özel, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Halil Özkan, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Aras Taşçı, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.
Related to the submission of all the project deliverables for the project of the CMPE 352 course, during the 2024 Spring semester, reported in this report, I, Kaan Yolcu, declare that:
I am a student in the Computer Engineering program at Boğaziçi University and am registered for the CMPE 352 course during the 2024 Spring semester.
All the material that I am submitting related to my project (including but not limited to the project repository, the final project report, and supplementary documents) have been exclusively prepared by myself.
I have prepared this material individually without the assistance of anyone else with the exception of permitted peer assistance which I have explicitly disclosed in this report.