Milestone Report 3 - bounswe/bounswe2024group6 GitHub Wiki
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:
- Authentication System: Robust authentication hooks for secure user login and registration.
- Dynamic Search Capabilities: A fully functional search bar that supports querying architectural data, including buildings, architects, and styles.
- Interactive User Profiles: Enhanced user profiles that allow for posting, commenting, and social interactions.
- Content Management: Users can create and manage architectural blog posts, further fostering community engagement.
-
Backend and Infrastructure:
- Dockerization: Both the backend and frontend applications are containerized using Docker, ensuring consistent environments across development and deployment stages.
- Database Integration: Configured MySQL database for reliable data management and storage.
-
Deployment: The application is deployed on DigitalOcean (accessible at http://165.232.66.11:5173 for the frontend and port 8000 for the Django backend). Deployment is streamlined through Docker Compose, allowing for easy setup with
docker-compose up
.
- API Integration: Efficient integration with the WikiData API, providing users with reliable and extensive architectural information.
- Responsive Design: Implementation of a responsive design that adapts to various devices, enhancing user experience.
- Security Measures: Advanced security protocols to protect user data and interactions across the platform.
- We plan to expand the platform's features, including enhanced analytics for user interactions and broader API integrations to enrich the content.
- Continuous improvements in UI/UX to ensure the platform remains intuitive and user-friendly.
- Further enhancements in our DevOps pipeline to support scaling and maintenance as the user base grows.
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.
1.1.1 Sign-up Requirements
- Users shall provide their unique username. -> DONE
- Users shall provide their secure password. -> DONE
- Users shall provide their e-mail adresses. -> DONE
- Users shall provide another e-mail adress for recovery.
- Users shall verify their e-mail adress.
1.1.2 Sign-in / Sign-out Requirements
- Users should be able to recover their password given their e-mail.
- Users shall be able to log in to their profile given credentials. -> DONE
- Users should be able to change their passwords.
- Users shall be able to log out from their profiles and continue with guest user account. -> DONE
1.1.3 Guest requirements
- Guests represents people using system without log-in. -> DONE
- Guests should be able to see users posts. -> DONE
- Guests shall not be able to post. -> DONE
- Guests shall not be able to bookmark. -> DONE
- Guests shall not be able to comment. -> DONE
- Guests shall not be able to like. -> DONE
- Guests shall not be able to send personal message. -> DONE
- Guests should have an empty avatar in the profile section. -> DONE
1.1.4 Profile Requirements
- Only Registered Users should have a profile -> DONE
- A profile shall have an initial avatar. -> DONE
- A profile shall have biography section. -> DONE
- A profile should let the user to update its avatar. -> DONE
- A profile should let the user to update the biography. -> DONE
- A profile shall keep track of bookmarks. -> DONE
- A profile should keep track of likes. -> DONE
- A profile shall keep track of previous posts. -> DONE
- A profile should include a message box.
- A profile should store previous messages.
1.1.5 User Interaction Requirements
- Users shall be able to view other users profiles. -> DONE
- Registered users shall be able to post a new post. -> DONE
- Registered users shall be able to bookmark a post. -> DONE
- Users shall be able to view posts. -> DONE
- Users shall be able to query a search giving an architect name. -> DONE
- Users shall be able to query a search giving an building name. -> DONE
- Users shall be able to query a search giving an architectural-style name. -> DONE
- Registered users shall be able to comment to the posts. -> DONE
- Registered users should be able to delete the comment to the posts. -> DONE
- Registered users shall be able to like posts. -> DONE
- Registered users shall be able to undo like posts. -> DONE
- Registered users shall be able to bookmark posts. -> DONE
- Registered users shall be able to undo bookmark posts. -> DONE
- Users shall be able to see the locations on the posts via google maps. -> DONE
- Users shall be able to navigate to the related pages from a single page. -> DONE
- Registered users shall be able to follow other users. -> DONE
- Registered users shall be able to undo follow other users. -> DONE
1.2.1 Searching and Sorting Requirements
- Architectural trends should be able to be searched using keywords or specific queries. -> DONE
- Results should be allowed to be sorted based on relevance, date, popularity, or other relevant factors. -> DONE
- Results should be allowed to be filtered based on criteria such as time period, geographical location, architectural style, etc.
- Functionality should be implemented to save search history for users and provide an option to revisit previous searches. -> DONE
- Users should be able to do semantic search. Providing a keyword they should get the result for closest query. -> DONE
1.2.2 Integration Requirements
- Integration with the Wikidata API should be implemented to fetch relevant data about architectural trends, ensuring proper handling of API requests and responses. -> DONE
- Caching mechanisms should be implemented to optimize performance and reduce the load on the Wikidata API by storing frequently accessed data locally. -> DONE
1.2.3 Post Requirements
- A post should contain 3 sections: Style, Architect, Building. -> DONE
- Under the Style section, relevant information about the stylistic part of the building should be included. -> DONE
- Under the Architect section, general information about the architect, the trends they are associated with, and an image of the architect should be provided. -> DONE
- Under the Building section, information about the building and a picture should be included. -> DONE
- At the bottom of the page, a map should be displayed showing the location of the building. -> DONE
- Posts should have the functionality to be liked and disliked. -> DONE
2.1 Availability and Reliability Requirements
- The project should be available in English. -> DONE
- The system should be designed to restore functionality within one or two hours following any unexpected system disruptions -> DONE
- Should set up backups to protect against data loss and quickly fix any problems if data gets corrupted or lost. -> DONE
- The platform must be capable of accommodating a minimum of 100 simultaneous user actions. -> DONE
2.2 Compatibility
- Compatibility with popular web browsers like Google Chrome, Safari is ensured for the project. -> DONE
- The users shall be able to enter the system from a smartphone, tablet. -> DONE
- It should be compatible with different popular Operating Systems. -> DONE
- Testing must be regularly conducted to ensure that updates to browsers or operating systems do not affect the system's usability or accessibility -> DONE
2.3 Performance
- The system shall respond to requests within 3 seconds. -> DONE
- The system is capable of handling up to 5000 requests per second -> DONE
- The platform must maintain a minimum uptime of 99%. -> DONE
2.4 Security
- Passwords maintained in the system's database will be secured through encryption. -> DONE
- Personal information of users must be concealed from other members -> DONE
- Should be used strong passwords for user accounts, combining letters, numbers, and symbols -> DONE
- The system will utilize the HTTPS protocol. -> DONE
- Unique and valid emails should be used. -> DONE
2.5 Database
- The system will store user information, user histories, and user preferences in the database. -> DONE
- The information within the database should support updates. -> DONE
- The database structure will prioritize efficiency -> DONE
- The database should be designed to support scalability, allowing for easy expansion as the number of users and the volume of data grows -> DONE
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 |
- Project Plan : link
- Adaptive Meeting Strategies: Recognizing the challenge of synchronizing schedules across diverse team, we adopted a more flexible approach to meetings. Instead of attempting to coordinate the perfect meeting time for everyone, we shifted to smaller, focused meetings based on responsibilities and deadlines. This change significantly improved our efficiency.
-
Refining Git Practices: Continuous development of our application required a robust and clear version control strategy. We convened a dedicated session to refine our Git workflow, which proved essential for managing our multi-faceted development process. Key outcomes included:
- Branch Strategy: We established guidelines for when and how to branch and merge, ensuring that branches are purpose-driven and manageable in size.
- Pull Request (PR) Management: We defined the characteristics of a strong PR, including clarity in communication and changes, and thoroughness in testing. This includes ensuring that PRs are linked to specific issues or features for better traceability.
- Conflict Resolution: Introduced standardized procedures for resolving merge conflicts, which often occur due to the concurrent development efforts on our backend, frontend, and mobile applications. This involved regular code reviews and adopting rebase strategies to maintain a clean commit history.
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.
- Authentication System: We've implemented a dual authentication system that supports both session-based and token-based mechanisms to cater to different client needs.
- API Endpoints: Developed RESTful APIs that interface with the WikiData API to fetch detailed information about architects, buildings, and architectural styles.
- User Profile Management: Functionality for users to manage their profiles, enhancing personalization within the app.
- Social Features: Users can engage through social features such as following other users, posting comments, liking, and bookmarking posts.
- Learning Curve: To ramp up on Django, team members new to the framework participated in weekly educational sessions, which were supplemented with online resources.
- Database Optimization: Faced with performance bottlenecks as user interactions increased, we optimized our database queries and restructured models for better performance.
- Security Enhancements: Initially confronted with security gaps, we tightened our application's security by improving input validation and configuring CORS settings appropriately.
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:
- React Router: Manages routing and navigation within the application, ensuring smooth transitions and maintaining browser history.
- Material-UI: Provides a rich set of UI components that are both functional and aesthetically pleasing, enhancing the overall user interface.
- Axios: Handles API requests, simplifying the process of communicating with our backend services.
- React Map GL: Integrates interactive maps into our application, allowing users to visually explore architectural sites.
- ClipLoader: Enhances the user experience during data fetching operations by displaying elegant loading spinners.
- Dynamic Pages: We've implemented several key pages including Home, Feed, Profile, Architect, Building, and Style pages, each tailored to deliver specific content relevant to architecture enthusiasts.
-
Interactive Search: Users can search for architects, buildings, or styles, and results are dynamically rendered using the
SearchItem
component. - User Authentication: The application supports user authentication processes, allowing users to login, register, and manage their profiles.
- Social Interaction: Features such as following/unfollowing users, liking posts, and commenting are integrated to foster community interactions within the app.
- Rich Media Content: Implements image galleries and map views to provide rich media content, enhancing user engagement.
- State Management: Managing state across multiple components was challenging. We adopted React's Context API to share state efficiently between components without prop-drilling.
- Responsive Design: Ensuring the application is responsive across various devices required meticulous CSS and Material-UI customization.
- API Integration: Initially, handling asynchronous API calls was problematic due to state updates on unmounted components. We refined our useEffect hooks and implemented cleanup functions to prevent memory leaks.
-
React Hooks: Gained a deeper understanding of React hooks, particularly
useState
,useEffect
, anduseContext
, which helped in managing local and global states effectively. - Advanced Routing: Learned to handle complex routing scenarios using React Router, which was pivotal in managing the navigational flows of our application.
- Optimization Techniques: Adopted various optimization techniques such as code splitting and lazy loading to improve the performance and loading times of our application.
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
):-
Image: We use the
mysql:8.0
image for our relational database needs. - Ports: The container's 3306 port is mapped to the host's 3306 port to allow local access.
- Environment Variables: These are used to configure the MySQL root password and database name, utilizing environment variables to keep sensitive information out of the version control.
- Healthcheck: Ensures the database service is healthy before other services start.
-
Image: We use the
-
Backend Service (
backend
):-
Build Context: Built from a Dockerfile located in
./new_backend/project
. - Ports: Exposes port 8000 on the container to port 8000 on the host, allowing access to the Django development server.
-
Volumes: Maps the project directory to the
/app
directory inside the container, facilitating live updates by linking the local development environment to the container environment. -
Dependencies: Configured to wait for the
db
service to be healthy before starting.
-
Build Context: Built from a Dockerfile located in
-
Frontend Service (
frontend
):-
Build Context: Built from a Dockerfile in the
./frontend
directory. - Ports: Maps port 5173 on the container to port 5173 on the host, used for accessing the frontend.
-
Volumes: Binds the local frontend directory to
/app
in the container and uses an anonymous volume fornode_modules
to avoid overwriting the installed node modules with local ones.
-
Build Context: Built from a Dockerfile in the
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.
- Monitoring: We plan to implement Prometheus and Grafana for monitoring our applications.
- Security: Uses environment variables to manage sensitive configurations securely. Future enhancements will include integrating SSL/TLS for encrypted communication.
-
Database Connectivity: Initially faced challenges in service communication within Docker. Resolved by using Docker Compose’s
depends_on
and health checks to ensure services start in the correct order. -
Environment Configuration: Managing sensitive data securely through environment variables and
.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
- ![image](https://hackmd.io/_uploads/BkJAT4PQA.png =250x)
- ![image](https://hackmd.io/_uploads/HyxfANvQ0.png =250x)
- ![image](https://hackmd.io/_uploads/Hy5d6EDQC.png =250x)
- ![image](https://hackmd.io/_uploads/HywsaED7C.png =250x)
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.
- User Authentication: Includes screens for user registration and login, ensuring secure access to the application.
- Feed Screen: Displays dynamic content to users, pulling data from the backend and updating in real-time.
- Landing Page: Acts as the initial point of contact for users, offering options to navigate to other parts of the application or proceed as a guest.
- Search Functionality: Allows users to search for architectural information, integrating with backend services to fetch and display results.
- Navigation and State Management: Initially, managing state transitions and navigation was complex due to the asynchronous nature of network requests. We optimized this by using the React Context API for state management and carefully managing side effects in React components.
-
API Integration: Ensuring that the mobile app consistently received and correctly handled data from our backend was challenging, particularly in handling errors and loading states. We implemented robust error handling and loading indicators (like
ClipLoader
) to enhance user experience. - Cross-Platform Compatibility: We faced issues with layout and performance across different devices and screen sizes. These were addressed by using responsive design principles and testing extensively on multiple devices.
- Expo Development: Gained significant insights into Expo's capabilities, especially its ease of use for developing and testing on multiple platforms.
- Advanced React Patterns: Improved our use of React hooks for better state and effect management, which was crucial for maintaining performance and reliability.
- User Interface Design: Learned to implement and customize mobile UI components that are both attractive and functional, enhancing overall user engagement.
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%E2%80%903
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%E2%80%903
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-%E2%80%90-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%E2%80%903 https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-%26-Effort%3A-An%C4%B1l-K%C3%B6se
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.
- I was all alone in the mobile application development.
- I had to figure out solutions for all sort of mobile-related issues.
- I had to make critical decisions for Searchitect's mobile application.
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-%C3%96zel https://github.com/bounswe/bounswe2024group6/wiki/Work-Done-By-Each-Member-Milestone%E2%80%903
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%E2%80%903 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%E2%80%903 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%E2%80%903 https://github.com/bounswe/bounswe2024group6/wiki/Personal-Wiki-&-Effort:-Yunus-Emre-%C3%96zdemir
https://github.com/bounswe/bounswe2024group6/wiki/Meeting-%E2%80%90-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.